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., 51 Franklin Street, Fifth Floor, Boston MA 02110-1301 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
;
60 #if !defined(CONFIG_USER_ONLY)
65 #if defined(CONFIG_USER_ONLY)
68 #define IS_USER(s) (s->user)
71 /* These instructions trap after executing, so defer them until after the
72 conditional executions state has been updated. */
76 static TCGv_ptr cpu_env
;
77 /* We reuse the same 64-bit temporaries for efficiency. */
78 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
80 /* FIXME: These should be removed. */
82 static TCGv cpu_F0s
, cpu_F1s
;
83 static TCGv_i64 cpu_F0d
, cpu_F1d
;
85 #define ICOUNT_TEMP cpu_T[0]
86 #include "gen-icount.h"
88 /* initialize TCG globals. */
89 void arm_translate_init(void)
91 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
93 cpu_T
[0] = tcg_global_reg_new_i32(TCG_AREG1
, "T0");
94 cpu_T
[1] = tcg_global_reg_new_i32(TCG_AREG2
, "T1");
100 /* The code generator doesn't like lots of temporaries, so maintain our own
101 cache for reuse within a function. */
103 static int num_temps
;
104 static TCGv temps
[MAX_TEMPS
];
106 /* Allocate a temporary variable. */
107 static TCGv_i32
new_tmp(void)
110 if (num_temps
== MAX_TEMPS
)
113 if (GET_TCGV_I32(temps
[num_temps
]))
114 return temps
[num_temps
++];
116 tmp
= tcg_temp_new_i32();
117 temps
[num_temps
++] = tmp
;
121 /* Release a temporary variable. */
122 static void dead_tmp(TCGv tmp
)
127 if (TCGV_EQUAL(temps
[i
], tmp
))
130 /* Shuffle this temp to the last slot. */
131 while (!TCGV_EQUAL(temps
[i
], tmp
))
133 while (i
< num_temps
) {
134 temps
[i
] = temps
[i
+ 1];
140 static inline TCGv
load_cpu_offset(int offset
)
142 TCGv tmp
= new_tmp();
143 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
147 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUState, name))
149 static inline void store_cpu_offset(TCGv var
, int offset
)
151 tcg_gen_st_i32(var
, cpu_env
, offset
);
155 #define store_cpu_field(var, name) \
156 store_cpu_offset(var, offsetof(CPUState, name))
158 /* Set a variable to the value of a CPU register. */
159 static void load_reg_var(DisasContext
*s
, TCGv var
, int reg
)
163 /* normaly, since we updated PC, we need only to add one insn */
165 addr
= (long)s
->pc
+ 2;
167 addr
= (long)s
->pc
+ 4;
168 tcg_gen_movi_i32(var
, addr
);
170 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
174 /* Create a new temporary and set it to the value of a CPU register. */
175 static inline TCGv
load_reg(DisasContext
*s
, int reg
)
177 TCGv tmp
= new_tmp();
178 load_reg_var(s
, tmp
, reg
);
182 /* Set a CPU register. The source must be a temporary and will be
184 static void store_reg(DisasContext
*s
, int reg
, TCGv var
)
187 tcg_gen_andi_i32(var
, var
, ~1);
188 s
->is_jmp
= DISAS_JUMP
;
190 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
195 /* Basic operations. */
196 #define gen_op_movl_T0_T1() tcg_gen_mov_i32(cpu_T[0], cpu_T[1])
197 #define gen_op_movl_T0_im(im) tcg_gen_movi_i32(cpu_T[0], im)
198 #define gen_op_movl_T1_im(im) tcg_gen_movi_i32(cpu_T[1], im)
200 #define gen_op_addl_T1_im(im) tcg_gen_addi_i32(cpu_T[1], cpu_T[1], im)
201 #define gen_op_addl_T0_T1() tcg_gen_add_i32(cpu_T[0], cpu_T[0], cpu_T[1])
202 #define gen_op_subl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[0], cpu_T[1])
203 #define gen_op_rsbl_T0_T1() tcg_gen_sub_i32(cpu_T[0], cpu_T[1], cpu_T[0])
205 #define gen_op_addl_T0_T1_cc() gen_helper_add_cc(cpu_T[0], cpu_T[0], cpu_T[1])
206 #define gen_op_adcl_T0_T1_cc() gen_helper_adc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
207 #define gen_op_subl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[0], cpu_T[1])
208 #define gen_op_sbcl_T0_T1_cc() gen_helper_sbc_cc(cpu_T[0], cpu_T[0], cpu_T[1])
209 #define gen_op_rsbl_T0_T1_cc() gen_helper_sub_cc(cpu_T[0], cpu_T[1], cpu_T[0])
211 #define gen_op_andl_T0_T1() tcg_gen_and_i32(cpu_T[0], cpu_T[0], cpu_T[1])
212 #define gen_op_xorl_T0_T1() tcg_gen_xor_i32(cpu_T[0], cpu_T[0], cpu_T[1])
213 #define gen_op_orl_T0_T1() tcg_gen_or_i32(cpu_T[0], cpu_T[0], cpu_T[1])
214 #define gen_op_notl_T0() tcg_gen_not_i32(cpu_T[0], cpu_T[0])
215 #define gen_op_notl_T1() tcg_gen_not_i32(cpu_T[1], cpu_T[1])
216 #define gen_op_logic_T0_cc() gen_logic_CC(cpu_T[0]);
217 #define gen_op_logic_T1_cc() gen_logic_CC(cpu_T[1]);
219 #define gen_op_shll_T1_im(im) tcg_gen_shli_i32(cpu_T[1], cpu_T[1], im)
220 #define gen_op_shrl_T1_im(im) tcg_gen_shri_i32(cpu_T[1], cpu_T[1], im)
222 /* Value extensions. */
223 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
224 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
225 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
226 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
228 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
229 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
231 #define gen_op_mul_T0_T1() tcg_gen_mul_i32(cpu_T[0], cpu_T[0], cpu_T[1])
233 #define gen_set_cpsr(var, mask) gen_helper_cpsr_write(var, tcg_const_i32(mask))
234 /* Set NZCV flags from the high 4 bits of var. */
235 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
237 static void gen_exception(int excp
)
239 TCGv tmp
= new_tmp();
240 tcg_gen_movi_i32(tmp
, excp
);
241 gen_helper_exception(tmp
);
245 static void gen_smul_dual(TCGv a
, TCGv b
)
247 TCGv tmp1
= new_tmp();
248 TCGv tmp2
= new_tmp();
249 tcg_gen_ext16s_i32(tmp1
, a
);
250 tcg_gen_ext16s_i32(tmp2
, b
);
251 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
253 tcg_gen_sari_i32(a
, a
, 16);
254 tcg_gen_sari_i32(b
, b
, 16);
255 tcg_gen_mul_i32(b
, b
, a
);
256 tcg_gen_mov_i32(a
, tmp1
);
260 /* Byteswap each halfword. */
261 static void gen_rev16(TCGv var
)
263 TCGv tmp
= new_tmp();
264 tcg_gen_shri_i32(tmp
, var
, 8);
265 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
266 tcg_gen_shli_i32(var
, var
, 8);
267 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
268 tcg_gen_or_i32(var
, var
, tmp
);
272 /* Byteswap low halfword and sign extend. */
273 static void gen_revsh(TCGv var
)
275 TCGv tmp
= new_tmp();
276 tcg_gen_shri_i32(tmp
, var
, 8);
277 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff);
278 tcg_gen_shli_i32(var
, var
, 8);
279 tcg_gen_ext8s_i32(var
, var
);
280 tcg_gen_or_i32(var
, var
, tmp
);
284 /* Unsigned bitfield extract. */
285 static void gen_ubfx(TCGv var
, int shift
, uint32_t mask
)
288 tcg_gen_shri_i32(var
, var
, shift
);
289 tcg_gen_andi_i32(var
, var
, mask
);
292 /* Signed bitfield extract. */
293 static void gen_sbfx(TCGv var
, int shift
, int width
)
298 tcg_gen_sari_i32(var
, var
, shift
);
299 if (shift
+ width
< 32) {
300 signbit
= 1u << (width
- 1);
301 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
302 tcg_gen_xori_i32(var
, var
, signbit
);
303 tcg_gen_subi_i32(var
, var
, signbit
);
307 /* Bitfield insertion. Insert val into base. Clobbers base and val. */
308 static void gen_bfi(TCGv dest
, TCGv base
, TCGv val
, int shift
, uint32_t mask
)
310 tcg_gen_andi_i32(val
, val
, mask
);
311 tcg_gen_shli_i32(val
, val
, shift
);
312 tcg_gen_andi_i32(base
, base
, ~(mask
<< shift
));
313 tcg_gen_or_i32(dest
, base
, val
);
316 /* Round the top 32 bits of a 64-bit value. */
317 static void gen_roundqd(TCGv a
, TCGv b
)
319 tcg_gen_shri_i32(a
, a
, 31);
320 tcg_gen_add_i32(a
, a
, b
);
323 /* FIXME: Most targets have native widening multiplication.
324 It would be good to use that instead of a full wide multiply. */
325 /* 32x32->64 multiply. Marks inputs as dead. */
326 static TCGv_i64
gen_mulu_i64_i32(TCGv a
, TCGv b
)
328 TCGv_i64 tmp1
= tcg_temp_new_i64();
329 TCGv_i64 tmp2
= tcg_temp_new_i64();
331 tcg_gen_extu_i32_i64(tmp1
, a
);
333 tcg_gen_extu_i32_i64(tmp2
, b
);
335 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
339 static TCGv_i64
gen_muls_i64_i32(TCGv a
, TCGv b
)
341 TCGv_i64 tmp1
= tcg_temp_new_i64();
342 TCGv_i64 tmp2
= tcg_temp_new_i64();
344 tcg_gen_ext_i32_i64(tmp1
, a
);
346 tcg_gen_ext_i32_i64(tmp2
, b
);
348 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
352 /* Unsigned 32x32->64 multiply. */
353 static void gen_op_mull_T0_T1(void)
355 TCGv_i64 tmp1
= tcg_temp_new_i64();
356 TCGv_i64 tmp2
= tcg_temp_new_i64();
358 tcg_gen_extu_i32_i64(tmp1
, cpu_T
[0]);
359 tcg_gen_extu_i32_i64(tmp2
, cpu_T
[1]);
360 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
361 tcg_gen_trunc_i64_i32(cpu_T
[0], tmp1
);
362 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
363 tcg_gen_trunc_i64_i32(cpu_T
[1], tmp1
);
366 /* Signed 32x32->64 multiply. */
367 static void gen_imull(TCGv a
, TCGv b
)
369 TCGv_i64 tmp1
= tcg_temp_new_i64();
370 TCGv_i64 tmp2
= tcg_temp_new_i64();
372 tcg_gen_ext_i32_i64(tmp1
, a
);
373 tcg_gen_ext_i32_i64(tmp2
, b
);
374 tcg_gen_mul_i64(tmp1
, tmp1
, tmp2
);
375 tcg_gen_trunc_i64_i32(a
, tmp1
);
376 tcg_gen_shri_i64(tmp1
, tmp1
, 32);
377 tcg_gen_trunc_i64_i32(b
, tmp1
);
380 /* Swap low and high halfwords. */
381 static void gen_swap_half(TCGv var
)
383 TCGv tmp
= new_tmp();
384 tcg_gen_shri_i32(tmp
, var
, 16);
385 tcg_gen_shli_i32(var
, var
, 16);
386 tcg_gen_or_i32(var
, var
, tmp
);
390 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
391 tmp = (t0 ^ t1) & 0x8000;
394 t0 = (t0 + t1) ^ tmp;
397 static void gen_add16(TCGv t0
, TCGv t1
)
399 TCGv tmp
= new_tmp();
400 tcg_gen_xor_i32(tmp
, t0
, t1
);
401 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
402 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
403 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
404 tcg_gen_add_i32(t0
, t0
, t1
);
405 tcg_gen_xor_i32(t0
, t0
, tmp
);
410 #define gen_set_CF(var) tcg_gen_st_i32(var, cpu_env, offsetof(CPUState, CF))
412 /* Set CF to the top bit of var. */
413 static void gen_set_CF_bit31(TCGv var
)
415 TCGv tmp
= new_tmp();
416 tcg_gen_shri_i32(tmp
, var
, 31);
421 /* Set N and Z flags from var. */
422 static inline void gen_logic_CC(TCGv var
)
424 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, NF
));
425 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUState
, ZF
));
429 static void gen_adc_T0_T1(void)
433 tmp
= load_cpu_field(CF
);
434 tcg_gen_add_i32(cpu_T
[0], cpu_T
[0], tmp
);
438 /* dest = T0 + T1 + CF. */
439 static void gen_add_carry(TCGv dest
, TCGv t0
, TCGv t1
)
442 tcg_gen_add_i32(dest
, t0
, t1
);
443 tmp
= load_cpu_field(CF
);
444 tcg_gen_add_i32(dest
, dest
, tmp
);
448 /* dest = T0 - T1 + CF - 1. */
449 static void gen_sub_carry(TCGv dest
, TCGv t0
, TCGv t1
)
452 tcg_gen_sub_i32(dest
, t0
, t1
);
453 tmp
= load_cpu_field(CF
);
454 tcg_gen_add_i32(dest
, dest
, tmp
);
455 tcg_gen_subi_i32(dest
, dest
, 1);
459 #define gen_sbc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[0], cpu_T[1])
460 #define gen_rsc_T0_T1() gen_sub_carry(cpu_T[0], cpu_T[1], cpu_T[0])
462 /* T0 &= ~T1. Clobbers T1. */
463 /* FIXME: Implement bic natively. */
464 static inline void tcg_gen_bic_i32(TCGv dest
, TCGv t0
, TCGv t1
)
466 TCGv tmp
= new_tmp();
467 tcg_gen_not_i32(tmp
, t1
);
468 tcg_gen_and_i32(dest
, t0
, tmp
);
471 static inline void gen_op_bicl_T0_T1(void)
477 /* FIXME: Implement this natively. */
478 #define tcg_gen_abs_i32(t0, t1) gen_helper_abs(t0, t1)
480 /* FIXME: Implement this natively. */
481 static void tcg_gen_rori_i32(TCGv t0
, TCGv t1
, int i
)
489 tcg_gen_shri_i32(tmp
, t1
, i
);
490 tcg_gen_shli_i32(t1
, t1
, 32 - i
);
491 tcg_gen_or_i32(t0
, t1
, tmp
);
495 static void shifter_out_im(TCGv var
, int shift
)
497 TCGv tmp
= new_tmp();
499 tcg_gen_andi_i32(tmp
, var
, 1);
501 tcg_gen_shri_i32(tmp
, var
, shift
);
503 tcg_gen_andi_i32(tmp
, tmp
, 1);
509 /* Shift by immediate. Includes special handling for shift == 0. */
510 static inline void gen_arm_shift_im(TCGv var
, int shiftop
, int shift
, int flags
)
516 shifter_out_im(var
, 32 - shift
);
517 tcg_gen_shli_i32(var
, var
, shift
);
523 tcg_gen_shri_i32(var
, var
, 31);
526 tcg_gen_movi_i32(var
, 0);
529 shifter_out_im(var
, shift
- 1);
530 tcg_gen_shri_i32(var
, var
, shift
);
537 shifter_out_im(var
, shift
- 1);
540 tcg_gen_sari_i32(var
, var
, shift
);
542 case 3: /* ROR/RRX */
545 shifter_out_im(var
, shift
- 1);
546 tcg_gen_rori_i32(var
, var
, shift
); break;
548 TCGv tmp
= load_cpu_field(CF
);
550 shifter_out_im(var
, 0);
551 tcg_gen_shri_i32(var
, var
, 1);
552 tcg_gen_shli_i32(tmp
, tmp
, 31);
553 tcg_gen_or_i32(var
, var
, tmp
);
559 static inline void gen_arm_shift_reg(TCGv var
, int shiftop
,
560 TCGv shift
, int flags
)
564 case 0: gen_helper_shl_cc(var
, var
, shift
); break;
565 case 1: gen_helper_shr_cc(var
, var
, shift
); break;
566 case 2: gen_helper_sar_cc(var
, var
, shift
); break;
567 case 3: gen_helper_ror_cc(var
, var
, shift
); break;
571 case 0: gen_helper_shl(var
, var
, shift
); break;
572 case 1: gen_helper_shr(var
, var
, shift
); break;
573 case 2: gen_helper_sar(var
, var
, shift
); break;
574 case 3: gen_helper_ror(var
, var
, shift
); break;
580 #define PAS_OP(pfx) \
582 case 0: gen_pas_helper(glue(pfx,add16)); break; \
583 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
584 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
585 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
586 case 4: gen_pas_helper(glue(pfx,add8)); break; \
587 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
589 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
594 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
596 tmp
= tcg_temp_new_ptr();
597 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
601 tmp
= tcg_temp_new_ptr();
602 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
605 #undef gen_pas_helper
606 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
619 #undef gen_pas_helper
624 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
625 #define PAS_OP(pfx) \
627 case 0: gen_pas_helper(glue(pfx,add8)); break; \
628 case 1: gen_pas_helper(glue(pfx,add16)); break; \
629 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
630 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
631 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
632 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
634 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv a
, TCGv b
)
639 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
641 tmp
= tcg_temp_new_ptr();
642 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
646 tmp
= tcg_temp_new_ptr();
647 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUState
, GE
));
650 #undef gen_pas_helper
651 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
664 #undef gen_pas_helper
669 static void gen_test_cc(int cc
, int label
)
677 tmp
= load_cpu_field(ZF
);
678 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
681 tmp
= load_cpu_field(ZF
);
682 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
685 tmp
= load_cpu_field(CF
);
686 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
689 tmp
= load_cpu_field(CF
);
690 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
693 tmp
= load_cpu_field(NF
);
694 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
697 tmp
= load_cpu_field(NF
);
698 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
701 tmp
= load_cpu_field(VF
);
702 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
705 tmp
= load_cpu_field(VF
);
706 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
708 case 8: /* hi: C && !Z */
709 inv
= gen_new_label();
710 tmp
= load_cpu_field(CF
);
711 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
713 tmp
= load_cpu_field(ZF
);
714 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, label
);
717 case 9: /* ls: !C || Z */
718 tmp
= load_cpu_field(CF
);
719 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
721 tmp
= load_cpu_field(ZF
);
722 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
724 case 10: /* ge: N == V -> N ^ V == 0 */
725 tmp
= load_cpu_field(VF
);
726 tmp2
= load_cpu_field(NF
);
727 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
729 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
731 case 11: /* lt: N != V -> N ^ V != 0 */
732 tmp
= load_cpu_field(VF
);
733 tmp2
= load_cpu_field(NF
);
734 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
736 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
738 case 12: /* gt: !Z && N == V */
739 inv
= gen_new_label();
740 tmp
= load_cpu_field(ZF
);
741 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, inv
);
743 tmp
= load_cpu_field(VF
);
744 tmp2
= load_cpu_field(NF
);
745 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
747 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
750 case 13: /* le: Z || N != V */
751 tmp
= load_cpu_field(ZF
);
752 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, label
);
754 tmp
= load_cpu_field(VF
);
755 tmp2
= load_cpu_field(NF
);
756 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
758 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
761 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
767 static const uint8_t table_logic_cc
[16] = {
786 /* Set PC and Thumb state from an immediate address. */
787 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
791 s
->is_jmp
= DISAS_UPDATE
;
793 if (s
->thumb
!= (addr
& 1)) {
794 tcg_gen_movi_i32(tmp
, addr
& 1);
795 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, thumb
));
797 tcg_gen_movi_i32(tmp
, addr
& ~1);
798 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[15]));
802 /* Set PC and Thumb state from var. var is marked as dead. */
803 static inline void gen_bx(DisasContext
*s
, TCGv var
)
807 s
->is_jmp
= DISAS_UPDATE
;
809 tcg_gen_andi_i32(tmp
, var
, 1);
810 store_cpu_field(tmp
, thumb
);
811 tcg_gen_andi_i32(var
, var
, ~1);
812 store_cpu_field(var
, regs
[15]);
815 /* TODO: This should be removed. Use gen_bx instead. */
816 static inline void gen_bx_T0(DisasContext
*s
)
818 TCGv tmp
= new_tmp();
819 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
823 /* Variant of store_reg which uses branch&exchange logic when storing
824 to r15 in ARM architecture v7 and above. The source must be a temporary
825 and will be marked as dead. */
826 static inline void store_reg_bx(CPUState
*env
, DisasContext
*s
,
829 if (reg
== 15 && ENABLE_ARCH_7
) {
832 store_reg(s
, reg
, var
);
836 static inline TCGv
gen_ld8s(TCGv addr
, int index
)
838 TCGv tmp
= new_tmp();
839 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
842 static inline TCGv
gen_ld8u(TCGv addr
, int index
)
844 TCGv tmp
= new_tmp();
845 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
848 static inline TCGv
gen_ld16s(TCGv addr
, int index
)
850 TCGv tmp
= new_tmp();
851 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
854 static inline TCGv
gen_ld16u(TCGv addr
, int index
)
856 TCGv tmp
= new_tmp();
857 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
860 static inline TCGv
gen_ld32(TCGv addr
, int index
)
862 TCGv tmp
= new_tmp();
863 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
866 static inline void gen_st8(TCGv val
, TCGv addr
, int index
)
868 tcg_gen_qemu_st8(val
, addr
, index
);
871 static inline void gen_st16(TCGv val
, TCGv addr
, int index
)
873 tcg_gen_qemu_st16(val
, addr
, index
);
876 static inline void gen_st32(TCGv val
, TCGv addr
, int index
)
878 tcg_gen_qemu_st32(val
, addr
, index
);
882 static inline void gen_movl_T0_reg(DisasContext
*s
, int reg
)
884 load_reg_var(s
, cpu_T
[0], reg
);
887 static inline void gen_movl_T1_reg(DisasContext
*s
, int reg
)
889 load_reg_var(s
, cpu_T
[1], reg
);
892 static inline void gen_movl_T2_reg(DisasContext
*s
, int reg
)
894 load_reg_var(s
, cpu_T
[2], reg
);
897 static inline void gen_set_pc_im(uint32_t val
)
899 TCGv tmp
= new_tmp();
900 tcg_gen_movi_i32(tmp
, val
);
901 store_cpu_field(tmp
, regs
[15]);
904 static inline void gen_movl_reg_TN(DisasContext
*s
, int reg
, int t
)
909 tcg_gen_andi_i32(tmp
, cpu_T
[t
], ~1);
913 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUState
, regs
[reg
]));
916 s
->is_jmp
= DISAS_JUMP
;
920 static inline void gen_movl_reg_T0(DisasContext
*s
, int reg
)
922 gen_movl_reg_TN(s
, reg
, 0);
925 static inline void gen_movl_reg_T1(DisasContext
*s
, int reg
)
927 gen_movl_reg_TN(s
, reg
, 1);
930 /* Force a TB lookup after an instruction that changes the CPU state. */
931 static inline void gen_lookup_tb(DisasContext
*s
)
933 gen_op_movl_T0_im(s
->pc
);
934 gen_movl_reg_T0(s
, 15);
935 s
->is_jmp
= DISAS_UPDATE
;
938 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
941 int val
, rm
, shift
, shiftop
;
944 if (!(insn
& (1 << 25))) {
947 if (!(insn
& (1 << 23)))
950 tcg_gen_addi_i32(var
, var
, val
);
954 shift
= (insn
>> 7) & 0x1f;
955 shiftop
= (insn
>> 5) & 3;
956 offset
= load_reg(s
, rm
);
957 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
958 if (!(insn
& (1 << 23)))
959 tcg_gen_sub_i32(var
, var
, offset
);
961 tcg_gen_add_i32(var
, var
, offset
);
966 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
972 if (insn
& (1 << 22)) {
974 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
975 if (!(insn
& (1 << 23)))
979 tcg_gen_addi_i32(var
, var
, val
);
983 tcg_gen_addi_i32(var
, var
, extra
);
985 offset
= load_reg(s
, rm
);
986 if (!(insn
& (1 << 23)))
987 tcg_gen_sub_i32(var
, var
, offset
);
989 tcg_gen_add_i32(var
, var
, offset
);
994 #define VFP_OP2(name) \
995 static inline void gen_vfp_##name(int dp) \
998 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, cpu_env); \
1000 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, cpu_env); \
1010 static inline void gen_vfp_abs(int dp
)
1013 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
1015 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
1018 static inline void gen_vfp_neg(int dp
)
1021 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
1023 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
1026 static inline void gen_vfp_sqrt(int dp
)
1029 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
1031 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
1034 static inline void gen_vfp_cmp(int dp
)
1037 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
1039 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
1042 static inline void gen_vfp_cmpe(int dp
)
1045 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1047 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1050 static inline void gen_vfp_F1_ld0(int dp
)
1053 tcg_gen_movi_i64(cpu_F1d
, 0);
1055 tcg_gen_movi_i32(cpu_F1s
, 0);
1058 static inline void gen_vfp_uito(int dp
)
1061 gen_helper_vfp_uitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1063 gen_helper_vfp_uitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1066 static inline void gen_vfp_sito(int dp
)
1069 gen_helper_vfp_sitod(cpu_F0d
, cpu_F0s
, cpu_env
);
1071 gen_helper_vfp_sitos(cpu_F0s
, cpu_F0s
, cpu_env
);
1074 static inline void gen_vfp_toui(int dp
)
1077 gen_helper_vfp_touid(cpu_F0s
, cpu_F0d
, cpu_env
);
1079 gen_helper_vfp_touis(cpu_F0s
, cpu_F0s
, cpu_env
);
1082 static inline void gen_vfp_touiz(int dp
)
1085 gen_helper_vfp_touizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1087 gen_helper_vfp_touizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1090 static inline void gen_vfp_tosi(int dp
)
1093 gen_helper_vfp_tosid(cpu_F0s
, cpu_F0d
, cpu_env
);
1095 gen_helper_vfp_tosis(cpu_F0s
, cpu_F0s
, cpu_env
);
1098 static inline void gen_vfp_tosiz(int dp
)
1101 gen_helper_vfp_tosizd(cpu_F0s
, cpu_F0d
, cpu_env
);
1103 gen_helper_vfp_tosizs(cpu_F0s
, cpu_F0s
, cpu_env
);
1106 #define VFP_GEN_FIX(name) \
1107 static inline void gen_vfp_##name(int dp, int shift) \
1110 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tcg_const_i32(shift), cpu_env);\
1112 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tcg_const_i32(shift), cpu_env);\
1124 static inline void gen_vfp_ld(DisasContext
*s
, int dp
)
1127 tcg_gen_qemu_ld64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1129 tcg_gen_qemu_ld32u(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1132 static inline void gen_vfp_st(DisasContext
*s
, int dp
)
1135 tcg_gen_qemu_st64(cpu_F0d
, cpu_T
[1], IS_USER(s
));
1137 tcg_gen_qemu_st32(cpu_F0s
, cpu_T
[1], IS_USER(s
));
1141 vfp_reg_offset (int dp
, int reg
)
1144 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1146 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1147 + offsetof(CPU_DoubleU
, l
.upper
);
1149 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1150 + offsetof(CPU_DoubleU
, l
.lower
);
1154 /* Return the offset of a 32-bit piece of a NEON register.
1155 zero is the least significant end of the register. */
1157 neon_reg_offset (int reg
, int n
)
1161 return vfp_reg_offset(0, sreg
);
1164 /* FIXME: Remove these. */
1165 #define neon_T0 cpu_T[0]
1166 #define neon_T1 cpu_T[1]
1167 #define NEON_GET_REG(T, reg, n) \
1168 tcg_gen_ld_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1169 #define NEON_SET_REG(T, reg, n) \
1170 tcg_gen_st_i32(neon_##T, cpu_env, neon_reg_offset(reg, n))
1172 static TCGv
neon_load_reg(int reg
, int pass
)
1174 TCGv tmp
= new_tmp();
1175 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1179 static void neon_store_reg(int reg
, int pass
, TCGv var
)
1181 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1185 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1187 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1190 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1192 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1195 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1196 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1197 #define tcg_gen_st_f32 tcg_gen_st_i32
1198 #define tcg_gen_st_f64 tcg_gen_st_i64
1200 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1203 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1205 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1208 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1211 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1213 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1216 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1219 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1221 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1224 #define ARM_CP_RW_BIT (1 << 20)
1226 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1228 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1231 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1233 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUState
, iwmmxt
.regs
[reg
]));
1236 static inline void gen_op_iwmmxt_movl_wCx_T0(int reg
)
1238 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1241 static inline void gen_op_iwmmxt_movl_T0_wCx(int reg
)
1243 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1246 static inline void gen_op_iwmmxt_movl_T1_wCx(int reg
)
1248 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offsetof(CPUState
, iwmmxt
.cregs
[reg
]));
1251 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1253 iwmmxt_store_reg(cpu_M0
, rn
);
1256 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1258 iwmmxt_load_reg(cpu_M0
, rn
);
1261 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1263 iwmmxt_load_reg(cpu_V1
, rn
);
1264 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1267 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1269 iwmmxt_load_reg(cpu_V1
, rn
);
1270 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1273 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1275 iwmmxt_load_reg(cpu_V1
, rn
);
1276 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1279 #define IWMMXT_OP(name) \
1280 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1282 iwmmxt_load_reg(cpu_V1, rn); \
1283 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1286 #define IWMMXT_OP_ENV(name) \
1287 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1289 iwmmxt_load_reg(cpu_V1, rn); \
1290 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1293 #define IWMMXT_OP_ENV_SIZE(name) \
1294 IWMMXT_OP_ENV(name##b) \
1295 IWMMXT_OP_ENV(name##w) \
1296 IWMMXT_OP_ENV(name##l)
1298 #define IWMMXT_OP_ENV1(name) \
1299 static inline void gen_op_iwmmxt_##name##_M0(void) \
1301 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1315 IWMMXT_OP_ENV_SIZE(unpackl
)
1316 IWMMXT_OP_ENV_SIZE(unpackh
)
1318 IWMMXT_OP_ENV1(unpacklub
)
1319 IWMMXT_OP_ENV1(unpackluw
)
1320 IWMMXT_OP_ENV1(unpacklul
)
1321 IWMMXT_OP_ENV1(unpackhub
)
1322 IWMMXT_OP_ENV1(unpackhuw
)
1323 IWMMXT_OP_ENV1(unpackhul
)
1324 IWMMXT_OP_ENV1(unpacklsb
)
1325 IWMMXT_OP_ENV1(unpacklsw
)
1326 IWMMXT_OP_ENV1(unpacklsl
)
1327 IWMMXT_OP_ENV1(unpackhsb
)
1328 IWMMXT_OP_ENV1(unpackhsw
)
1329 IWMMXT_OP_ENV1(unpackhsl
)
1331 IWMMXT_OP_ENV_SIZE(cmpeq
)
1332 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1333 IWMMXT_OP_ENV_SIZE(cmpgts
)
1335 IWMMXT_OP_ENV_SIZE(mins
)
1336 IWMMXT_OP_ENV_SIZE(minu
)
1337 IWMMXT_OP_ENV_SIZE(maxs
)
1338 IWMMXT_OP_ENV_SIZE(maxu
)
1340 IWMMXT_OP_ENV_SIZE(subn
)
1341 IWMMXT_OP_ENV_SIZE(addn
)
1342 IWMMXT_OP_ENV_SIZE(subu
)
1343 IWMMXT_OP_ENV_SIZE(addu
)
1344 IWMMXT_OP_ENV_SIZE(subs
)
1345 IWMMXT_OP_ENV_SIZE(adds
)
1347 IWMMXT_OP_ENV(avgb0
)
1348 IWMMXT_OP_ENV(avgb1
)
1349 IWMMXT_OP_ENV(avgw0
)
1350 IWMMXT_OP_ENV(avgw1
)
1354 IWMMXT_OP_ENV(packuw
)
1355 IWMMXT_OP_ENV(packul
)
1356 IWMMXT_OP_ENV(packuq
)
1357 IWMMXT_OP_ENV(packsw
)
1358 IWMMXT_OP_ENV(packsl
)
1359 IWMMXT_OP_ENV(packsq
)
1361 static inline void gen_op_iwmmxt_muladdsl_M0_T0_T1(void)
1363 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1366 static inline void gen_op_iwmmxt_muladdsw_M0_T0_T1(void)
1368 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1371 static inline void gen_op_iwmmxt_muladdswl_M0_T0_T1(void)
1373 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1]);
1376 static inline void gen_op_iwmmxt_align_M0_T0_wRn(int rn
)
1378 iwmmxt_load_reg(cpu_V1
, rn
);
1379 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, cpu_T
[0]);
1382 static inline void gen_op_iwmmxt_insr_M0_T0_T1(int shift
)
1384 TCGv tmp
= tcg_const_i32(shift
);
1385 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, cpu_T
[0], cpu_T
[1], tmp
);
1388 static inline void gen_op_iwmmxt_extrsb_T0_M0(int shift
)
1390 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1391 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1392 tcg_gen_ext8s_i32(cpu_T
[0], cpu_T
[0]);
1395 static inline void gen_op_iwmmxt_extrsw_T0_M0(int shift
)
1397 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1398 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1399 tcg_gen_ext16s_i32(cpu_T
[0], cpu_T
[0]);
1402 static inline void gen_op_iwmmxt_extru_T0_M0(int shift
, uint32_t mask
)
1404 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, shift
);
1405 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_M0
);
1407 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
1410 static void gen_op_iwmmxt_set_mup(void)
1413 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1414 tcg_gen_ori_i32(tmp
, tmp
, 2);
1415 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1418 static void gen_op_iwmmxt_set_cup(void)
1421 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1422 tcg_gen_ori_i32(tmp
, tmp
, 1);
1423 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1426 static void gen_op_iwmmxt_setpsr_nz(void)
1428 TCGv tmp
= new_tmp();
1429 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1430 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1433 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1435 iwmmxt_load_reg(cpu_V1
, rn
);
1436 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1437 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1441 static void gen_iwmmxt_movl_T0_T1_wRn(int rn
)
1443 iwmmxt_load_reg(cpu_V0
, rn
);
1444 tcg_gen_trunc_i64_i32(cpu_T
[0], cpu_V0
);
1445 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1446 tcg_gen_trunc_i64_i32(cpu_T
[1], cpu_V0
);
1449 static void gen_iwmmxt_movl_wRn_T0_T1(int rn
)
1451 tcg_gen_concat_i32_i64(cpu_V0
, cpu_T
[0], cpu_T
[1]);
1452 iwmmxt_store_reg(cpu_V0
, rn
);
1455 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
)
1460 rd
= (insn
>> 16) & 0xf;
1461 gen_movl_T1_reg(s
, rd
);
1463 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1464 if (insn
& (1 << 24)) {
1466 if (insn
& (1 << 23))
1467 gen_op_addl_T1_im(offset
);
1469 gen_op_addl_T1_im(-offset
);
1471 if (insn
& (1 << 21))
1472 gen_movl_reg_T1(s
, rd
);
1473 } else if (insn
& (1 << 21)) {
1475 if (insn
& (1 << 23))
1476 gen_op_movl_T0_im(offset
);
1478 gen_op_movl_T0_im(- offset
);
1479 gen_op_addl_T0_T1();
1480 gen_movl_reg_T0(s
, rd
);
1481 } else if (!(insn
& (1 << 23)))
1486 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
)
1488 int rd
= (insn
>> 0) & 0xf;
1490 if (insn
& (1 << 8))
1491 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
)
1494 gen_op_iwmmxt_movl_T0_wCx(rd
);
1496 gen_iwmmxt_movl_T0_T1_wRn(rd
);
1498 gen_op_movl_T1_im(mask
);
1499 gen_op_andl_T0_T1();
1503 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occured
1504 (ie. an undefined instruction). */
1505 static int disas_iwmmxt_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
1508 int rdhi
, rdlo
, rd0
, rd1
, i
;
1511 if ((insn
& 0x0e000e00) == 0x0c000000) {
1512 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1514 rdlo
= (insn
>> 12) & 0xf;
1515 rdhi
= (insn
>> 16) & 0xf;
1516 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1517 gen_iwmmxt_movl_T0_T1_wRn(wrd
);
1518 gen_movl_reg_T0(s
, rdlo
);
1519 gen_movl_reg_T1(s
, rdhi
);
1520 } else { /* TMCRR */
1521 gen_movl_T0_reg(s
, rdlo
);
1522 gen_movl_T1_reg(s
, rdhi
);
1523 gen_iwmmxt_movl_wRn_T0_T1(wrd
);
1524 gen_op_iwmmxt_set_mup();
1529 wrd
= (insn
>> 12) & 0xf;
1530 if (gen_iwmmxt_address(s
, insn
))
1532 if (insn
& ARM_CP_RW_BIT
) {
1533 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1534 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1535 tcg_gen_mov_i32(cpu_T
[0], tmp
);
1537 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1540 if (insn
& (1 << 8)) {
1541 if (insn
& (1 << 22)) { /* WLDRD */
1542 tcg_gen_qemu_ld64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1544 } else { /* WLDRW wRd */
1545 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
1548 if (insn
& (1 << 22)) { /* WLDRH */
1549 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
1550 } else { /* WLDRB */
1551 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
1555 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1558 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1561 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1562 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1564 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
1565 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1567 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1569 if (insn
& (1 << 8)) {
1570 if (insn
& (1 << 22)) { /* WSTRD */
1572 tcg_gen_qemu_st64(cpu_M0
, cpu_T
[1], IS_USER(s
));
1573 } else { /* WSTRW wRd */
1574 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1575 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
1578 if (insn
& (1 << 22)) { /* WSTRH */
1579 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1580 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
1581 } else { /* WSTRB */
1582 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1583 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
1591 if ((insn
& 0x0f000000) != 0x0e000000)
1594 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1595 case 0x000: /* WOR */
1596 wrd
= (insn
>> 12) & 0xf;
1597 rd0
= (insn
>> 0) & 0xf;
1598 rd1
= (insn
>> 16) & 0xf;
1599 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1600 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1601 gen_op_iwmmxt_setpsr_nz();
1602 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1603 gen_op_iwmmxt_set_mup();
1604 gen_op_iwmmxt_set_cup();
1606 case 0x011: /* TMCR */
1609 rd
= (insn
>> 12) & 0xf;
1610 wrd
= (insn
>> 16) & 0xf;
1612 case ARM_IWMMXT_wCID
:
1613 case ARM_IWMMXT_wCASF
:
1615 case ARM_IWMMXT_wCon
:
1616 gen_op_iwmmxt_set_cup();
1618 case ARM_IWMMXT_wCSSF
:
1619 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1620 gen_movl_T1_reg(s
, rd
);
1621 gen_op_bicl_T0_T1();
1622 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1624 case ARM_IWMMXT_wCGR0
:
1625 case ARM_IWMMXT_wCGR1
:
1626 case ARM_IWMMXT_wCGR2
:
1627 case ARM_IWMMXT_wCGR3
:
1628 gen_op_iwmmxt_set_cup();
1629 gen_movl_reg_T0(s
, rd
);
1630 gen_op_iwmmxt_movl_wCx_T0(wrd
);
1636 case 0x100: /* WXOR */
1637 wrd
= (insn
>> 12) & 0xf;
1638 rd0
= (insn
>> 0) & 0xf;
1639 rd1
= (insn
>> 16) & 0xf;
1640 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1641 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1642 gen_op_iwmmxt_setpsr_nz();
1643 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1644 gen_op_iwmmxt_set_mup();
1645 gen_op_iwmmxt_set_cup();
1647 case 0x111: /* TMRC */
1650 rd
= (insn
>> 12) & 0xf;
1651 wrd
= (insn
>> 16) & 0xf;
1652 gen_op_iwmmxt_movl_T0_wCx(wrd
);
1653 gen_movl_reg_T0(s
, rd
);
1655 case 0x300: /* WANDN */
1656 wrd
= (insn
>> 12) & 0xf;
1657 rd0
= (insn
>> 0) & 0xf;
1658 rd1
= (insn
>> 16) & 0xf;
1659 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1660 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1661 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1662 gen_op_iwmmxt_setpsr_nz();
1663 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1664 gen_op_iwmmxt_set_mup();
1665 gen_op_iwmmxt_set_cup();
1667 case 0x200: /* WAND */
1668 wrd
= (insn
>> 12) & 0xf;
1669 rd0
= (insn
>> 0) & 0xf;
1670 rd1
= (insn
>> 16) & 0xf;
1671 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1672 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1673 gen_op_iwmmxt_setpsr_nz();
1674 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1675 gen_op_iwmmxt_set_mup();
1676 gen_op_iwmmxt_set_cup();
1678 case 0x810: case 0xa10: /* WMADD */
1679 wrd
= (insn
>> 12) & 0xf;
1680 rd0
= (insn
>> 0) & 0xf;
1681 rd1
= (insn
>> 16) & 0xf;
1682 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1683 if (insn
& (1 << 21))
1684 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1686 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1687 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1688 gen_op_iwmmxt_set_mup();
1690 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1691 wrd
= (insn
>> 12) & 0xf;
1692 rd0
= (insn
>> 16) & 0xf;
1693 rd1
= (insn
>> 0) & 0xf;
1694 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1695 switch ((insn
>> 22) & 3) {
1697 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1700 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1703 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1708 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1709 gen_op_iwmmxt_set_mup();
1710 gen_op_iwmmxt_set_cup();
1712 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1713 wrd
= (insn
>> 12) & 0xf;
1714 rd0
= (insn
>> 16) & 0xf;
1715 rd1
= (insn
>> 0) & 0xf;
1716 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1717 switch ((insn
>> 22) & 3) {
1719 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1722 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1725 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1730 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1731 gen_op_iwmmxt_set_mup();
1732 gen_op_iwmmxt_set_cup();
1734 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1735 wrd
= (insn
>> 12) & 0xf;
1736 rd0
= (insn
>> 16) & 0xf;
1737 rd1
= (insn
>> 0) & 0xf;
1738 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1739 if (insn
& (1 << 22))
1740 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1742 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1743 if (!(insn
& (1 << 20)))
1744 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1745 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1746 gen_op_iwmmxt_set_mup();
1748 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1749 wrd
= (insn
>> 12) & 0xf;
1750 rd0
= (insn
>> 16) & 0xf;
1751 rd1
= (insn
>> 0) & 0xf;
1752 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1753 if (insn
& (1 << 21)) {
1754 if (insn
& (1 << 20))
1755 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1757 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1759 if (insn
& (1 << 20))
1760 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1762 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1764 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1765 gen_op_iwmmxt_set_mup();
1767 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1768 wrd
= (insn
>> 12) & 0xf;
1769 rd0
= (insn
>> 16) & 0xf;
1770 rd1
= (insn
>> 0) & 0xf;
1771 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1772 if (insn
& (1 << 21))
1773 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1775 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1776 if (!(insn
& (1 << 20))) {
1777 iwmmxt_load_reg(cpu_V1
, wrd
);
1778 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1780 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1781 gen_op_iwmmxt_set_mup();
1783 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1784 wrd
= (insn
>> 12) & 0xf;
1785 rd0
= (insn
>> 16) & 0xf;
1786 rd1
= (insn
>> 0) & 0xf;
1787 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1788 switch ((insn
>> 22) & 3) {
1790 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1793 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1796 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1801 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1802 gen_op_iwmmxt_set_mup();
1803 gen_op_iwmmxt_set_cup();
1805 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1806 wrd
= (insn
>> 12) & 0xf;
1807 rd0
= (insn
>> 16) & 0xf;
1808 rd1
= (insn
>> 0) & 0xf;
1809 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1810 if (insn
& (1 << 22)) {
1811 if (insn
& (1 << 20))
1812 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1814 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1816 if (insn
& (1 << 20))
1817 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1819 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1821 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1822 gen_op_iwmmxt_set_mup();
1823 gen_op_iwmmxt_set_cup();
1825 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1826 wrd
= (insn
>> 12) & 0xf;
1827 rd0
= (insn
>> 16) & 0xf;
1828 rd1
= (insn
>> 0) & 0xf;
1829 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1830 gen_op_iwmmxt_movl_T0_wCx(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1831 gen_op_movl_T1_im(7);
1832 gen_op_andl_T0_T1();
1833 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
1834 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1835 gen_op_iwmmxt_set_mup();
1837 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1838 rd
= (insn
>> 12) & 0xf;
1839 wrd
= (insn
>> 16) & 0xf;
1840 gen_movl_T0_reg(s
, rd
);
1841 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1842 switch ((insn
>> 6) & 3) {
1844 gen_op_movl_T1_im(0xff);
1845 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 7) << 3);
1848 gen_op_movl_T1_im(0xffff);
1849 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 3) << 4);
1852 gen_op_movl_T1_im(0xffffffff);
1853 gen_op_iwmmxt_insr_M0_T0_T1((insn
& 1) << 5);
1858 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1859 gen_op_iwmmxt_set_mup();
1861 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1862 rd
= (insn
>> 12) & 0xf;
1863 wrd
= (insn
>> 16) & 0xf;
1866 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1867 switch ((insn
>> 22) & 3) {
1870 gen_op_iwmmxt_extrsb_T0_M0((insn
& 7) << 3);
1872 gen_op_iwmmxt_extru_T0_M0((insn
& 7) << 3, 0xff);
1877 gen_op_iwmmxt_extrsw_T0_M0((insn
& 3) << 4);
1879 gen_op_iwmmxt_extru_T0_M0((insn
& 3) << 4, 0xffff);
1883 gen_op_iwmmxt_extru_T0_M0((insn
& 1) << 5, ~0u);
1888 gen_movl_reg_T0(s
, rd
);
1890 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1891 if ((insn
& 0x000ff008) != 0x0003f000)
1893 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1894 switch ((insn
>> 22) & 3) {
1896 gen_op_shrl_T1_im(((insn
& 7) << 2) + 0);
1899 gen_op_shrl_T1_im(((insn
& 3) << 3) + 4);
1902 gen_op_shrl_T1_im(((insn
& 1) << 4) + 12);
1907 gen_op_shll_T1_im(28);
1908 gen_set_nzcv(cpu_T
[1]);
1910 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1911 rd
= (insn
>> 12) & 0xf;
1912 wrd
= (insn
>> 16) & 0xf;
1913 gen_movl_T0_reg(s
, rd
);
1914 switch ((insn
>> 6) & 3) {
1916 gen_helper_iwmmxt_bcstb(cpu_M0
, cpu_T
[0]);
1919 gen_helper_iwmmxt_bcstw(cpu_M0
, cpu_T
[0]);
1922 gen_helper_iwmmxt_bcstl(cpu_M0
, cpu_T
[0]);
1927 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1928 gen_op_iwmmxt_set_mup();
1930 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1931 if ((insn
& 0x000ff00f) != 0x0003f000)
1933 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1934 switch ((insn
>> 22) & 3) {
1936 for (i
= 0; i
< 7; i
++) {
1937 gen_op_shll_T1_im(4);
1938 gen_op_andl_T0_T1();
1942 for (i
= 0; i
< 3; i
++) {
1943 gen_op_shll_T1_im(8);
1944 gen_op_andl_T0_T1();
1948 gen_op_shll_T1_im(16);
1949 gen_op_andl_T0_T1();
1954 gen_set_nzcv(cpu_T
[0]);
1956 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1957 wrd
= (insn
>> 12) & 0xf;
1958 rd0
= (insn
>> 16) & 0xf;
1959 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1960 switch ((insn
>> 22) & 3) {
1962 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1965 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1968 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1973 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1974 gen_op_iwmmxt_set_mup();
1976 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1977 if ((insn
& 0x000ff00f) != 0x0003f000)
1979 gen_op_iwmmxt_movl_T1_wCx(ARM_IWMMXT_wCASF
);
1980 switch ((insn
>> 22) & 3) {
1982 for (i
= 0; i
< 7; i
++) {
1983 gen_op_shll_T1_im(4);
1988 for (i
= 0; i
< 3; i
++) {
1989 gen_op_shll_T1_im(8);
1994 gen_op_shll_T1_im(16);
2000 gen_set_nzcv(cpu_T
[0]);
2002 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2003 rd
= (insn
>> 12) & 0xf;
2004 rd0
= (insn
>> 16) & 0xf;
2005 if ((insn
& 0xf) != 0)
2007 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2008 switch ((insn
>> 22) & 3) {
2010 gen_helper_iwmmxt_msbb(cpu_T
[0], cpu_M0
);
2013 gen_helper_iwmmxt_msbw(cpu_T
[0], cpu_M0
);
2016 gen_helper_iwmmxt_msbl(cpu_T
[0], cpu_M0
);
2021 gen_movl_reg_T0(s
, rd
);
2023 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2024 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2025 wrd
= (insn
>> 12) & 0xf;
2026 rd0
= (insn
>> 16) & 0xf;
2027 rd1
= (insn
>> 0) & 0xf;
2028 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2029 switch ((insn
>> 22) & 3) {
2031 if (insn
& (1 << 21))
2032 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
2034 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
2037 if (insn
& (1 << 21))
2038 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
2040 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
2043 if (insn
& (1 << 21))
2044 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
2046 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
2051 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2052 gen_op_iwmmxt_set_mup();
2053 gen_op_iwmmxt_set_cup();
2055 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2056 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2057 wrd
= (insn
>> 12) & 0xf;
2058 rd0
= (insn
>> 16) & 0xf;
2059 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2060 switch ((insn
>> 22) & 3) {
2062 if (insn
& (1 << 21))
2063 gen_op_iwmmxt_unpacklsb_M0();
2065 gen_op_iwmmxt_unpacklub_M0();
2068 if (insn
& (1 << 21))
2069 gen_op_iwmmxt_unpacklsw_M0();
2071 gen_op_iwmmxt_unpackluw_M0();
2074 if (insn
& (1 << 21))
2075 gen_op_iwmmxt_unpacklsl_M0();
2077 gen_op_iwmmxt_unpacklul_M0();
2082 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2083 gen_op_iwmmxt_set_mup();
2084 gen_op_iwmmxt_set_cup();
2086 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2087 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2088 wrd
= (insn
>> 12) & 0xf;
2089 rd0
= (insn
>> 16) & 0xf;
2090 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2091 switch ((insn
>> 22) & 3) {
2093 if (insn
& (1 << 21))
2094 gen_op_iwmmxt_unpackhsb_M0();
2096 gen_op_iwmmxt_unpackhub_M0();
2099 if (insn
& (1 << 21))
2100 gen_op_iwmmxt_unpackhsw_M0();
2102 gen_op_iwmmxt_unpackhuw_M0();
2105 if (insn
& (1 << 21))
2106 gen_op_iwmmxt_unpackhsl_M0();
2108 gen_op_iwmmxt_unpackhul_M0();
2113 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2114 gen_op_iwmmxt_set_mup();
2115 gen_op_iwmmxt_set_cup();
2117 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2118 case 0x214: case 0x614: case 0xa14: case 0xe14:
2119 wrd
= (insn
>> 12) & 0xf;
2120 rd0
= (insn
>> 16) & 0xf;
2121 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2122 if (gen_iwmmxt_shift(insn
, 0xff))
2124 switch ((insn
>> 22) & 3) {
2128 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2131 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2134 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2137 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2138 gen_op_iwmmxt_set_mup();
2139 gen_op_iwmmxt_set_cup();
2141 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2142 case 0x014: case 0x414: case 0x814: case 0xc14:
2143 wrd
= (insn
>> 12) & 0xf;
2144 rd0
= (insn
>> 16) & 0xf;
2145 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2146 if (gen_iwmmxt_shift(insn
, 0xff))
2148 switch ((insn
>> 22) & 3) {
2152 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2155 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2158 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2161 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2162 gen_op_iwmmxt_set_mup();
2163 gen_op_iwmmxt_set_cup();
2165 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2166 case 0x114: case 0x514: case 0x914: case 0xd14:
2167 wrd
= (insn
>> 12) & 0xf;
2168 rd0
= (insn
>> 16) & 0xf;
2169 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2170 if (gen_iwmmxt_shift(insn
, 0xff))
2172 switch ((insn
>> 22) & 3) {
2176 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2179 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2182 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2185 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2186 gen_op_iwmmxt_set_mup();
2187 gen_op_iwmmxt_set_cup();
2189 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2190 case 0x314: case 0x714: case 0xb14: case 0xf14:
2191 wrd
= (insn
>> 12) & 0xf;
2192 rd0
= (insn
>> 16) & 0xf;
2193 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2194 switch ((insn
>> 22) & 3) {
2198 if (gen_iwmmxt_shift(insn
, 0xf))
2200 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2203 if (gen_iwmmxt_shift(insn
, 0x1f))
2205 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2208 if (gen_iwmmxt_shift(insn
, 0x3f))
2210 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2213 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2214 gen_op_iwmmxt_set_mup();
2215 gen_op_iwmmxt_set_cup();
2217 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2218 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2219 wrd
= (insn
>> 12) & 0xf;
2220 rd0
= (insn
>> 16) & 0xf;
2221 rd1
= (insn
>> 0) & 0xf;
2222 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2223 switch ((insn
>> 22) & 3) {
2225 if (insn
& (1 << 21))
2226 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2228 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2231 if (insn
& (1 << 21))
2232 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2234 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2237 if (insn
& (1 << 21))
2238 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2240 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2245 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2246 gen_op_iwmmxt_set_mup();
2248 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2249 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2250 wrd
= (insn
>> 12) & 0xf;
2251 rd0
= (insn
>> 16) & 0xf;
2252 rd1
= (insn
>> 0) & 0xf;
2253 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2254 switch ((insn
>> 22) & 3) {
2256 if (insn
& (1 << 21))
2257 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2259 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2262 if (insn
& (1 << 21))
2263 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2265 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2268 if (insn
& (1 << 21))
2269 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2271 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2276 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2277 gen_op_iwmmxt_set_mup();
2279 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2280 case 0x402: case 0x502: case 0x602: case 0x702:
2281 wrd
= (insn
>> 12) & 0xf;
2282 rd0
= (insn
>> 16) & 0xf;
2283 rd1
= (insn
>> 0) & 0xf;
2284 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2285 gen_op_movl_T0_im((insn
>> 20) & 3);
2286 gen_op_iwmmxt_align_M0_T0_wRn(rd1
);
2287 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2288 gen_op_iwmmxt_set_mup();
2290 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2291 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2292 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2293 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2294 wrd
= (insn
>> 12) & 0xf;
2295 rd0
= (insn
>> 16) & 0xf;
2296 rd1
= (insn
>> 0) & 0xf;
2297 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2298 switch ((insn
>> 20) & 0xf) {
2300 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2303 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2306 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2309 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2312 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2315 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2318 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2321 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2324 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2329 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2330 gen_op_iwmmxt_set_mup();
2331 gen_op_iwmmxt_set_cup();
2333 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2334 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2335 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2336 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2337 wrd
= (insn
>> 12) & 0xf;
2338 rd0
= (insn
>> 16) & 0xf;
2339 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2340 gen_op_movl_T0_im(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2341 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, cpu_T
[0]);
2342 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2343 gen_op_iwmmxt_set_mup();
2344 gen_op_iwmmxt_set_cup();
2346 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2347 case 0x418: case 0x518: case 0x618: case 0x718:
2348 case 0x818: case 0x918: case 0xa18: case 0xb18:
2349 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2350 wrd
= (insn
>> 12) & 0xf;
2351 rd0
= (insn
>> 16) & 0xf;
2352 rd1
= (insn
>> 0) & 0xf;
2353 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2354 switch ((insn
>> 20) & 0xf) {
2356 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2359 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2362 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2365 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2368 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2371 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2374 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2377 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2380 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2385 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2386 gen_op_iwmmxt_set_mup();
2387 gen_op_iwmmxt_set_cup();
2389 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2390 case 0x408: case 0x508: case 0x608: case 0x708:
2391 case 0x808: case 0x908: case 0xa08: case 0xb08:
2392 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2393 wrd
= (insn
>> 12) & 0xf;
2394 rd0
= (insn
>> 16) & 0xf;
2395 rd1
= (insn
>> 0) & 0xf;
2396 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2397 if (!(insn
& (1 << 20)))
2399 switch ((insn
>> 22) & 3) {
2403 if (insn
& (1 << 21))
2404 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2406 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2409 if (insn
& (1 << 21))
2410 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2412 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2415 if (insn
& (1 << 21))
2416 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2418 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2421 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2422 gen_op_iwmmxt_set_mup();
2423 gen_op_iwmmxt_set_cup();
2425 case 0x201: case 0x203: case 0x205: case 0x207:
2426 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2427 case 0x211: case 0x213: case 0x215: case 0x217:
2428 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2429 wrd
= (insn
>> 5) & 0xf;
2430 rd0
= (insn
>> 12) & 0xf;
2431 rd1
= (insn
>> 0) & 0xf;
2432 if (rd0
== 0xf || rd1
== 0xf)
2434 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2435 switch ((insn
>> 16) & 0xf) {
2436 case 0x0: /* TMIA */
2437 gen_movl_T0_reg(s
, rd0
);
2438 gen_movl_T1_reg(s
, rd1
);
2439 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2441 case 0x8: /* TMIAPH */
2442 gen_movl_T0_reg(s
, rd0
);
2443 gen_movl_T1_reg(s
, rd1
);
2444 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2446 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2447 gen_movl_T1_reg(s
, rd0
);
2448 if (insn
& (1 << 16))
2449 gen_op_shrl_T1_im(16);
2450 gen_op_movl_T0_T1();
2451 gen_movl_T1_reg(s
, rd1
);
2452 if (insn
& (1 << 17))
2453 gen_op_shrl_T1_im(16);
2454 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2459 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2460 gen_op_iwmmxt_set_mup();
2469 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occured
2470 (ie. an undefined instruction). */
2471 static int disas_dsp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2473 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2475 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2476 /* Multiply with Internal Accumulate Format */
2477 rd0
= (insn
>> 12) & 0xf;
2479 acc
= (insn
>> 5) & 7;
2484 switch ((insn
>> 16) & 0xf) {
2486 gen_movl_T0_reg(s
, rd0
);
2487 gen_movl_T1_reg(s
, rd1
);
2488 gen_op_iwmmxt_muladdsl_M0_T0_T1();
2490 case 0x8: /* MIAPH */
2491 gen_movl_T0_reg(s
, rd0
);
2492 gen_movl_T1_reg(s
, rd1
);
2493 gen_op_iwmmxt_muladdsw_M0_T0_T1();
2495 case 0xc: /* MIABB */
2496 case 0xd: /* MIABT */
2497 case 0xe: /* MIATB */
2498 case 0xf: /* MIATT */
2499 gen_movl_T1_reg(s
, rd0
);
2500 if (insn
& (1 << 16))
2501 gen_op_shrl_T1_im(16);
2502 gen_op_movl_T0_T1();
2503 gen_movl_T1_reg(s
, rd1
);
2504 if (insn
& (1 << 17))
2505 gen_op_shrl_T1_im(16);
2506 gen_op_iwmmxt_muladdswl_M0_T0_T1();
2512 gen_op_iwmmxt_movq_wRn_M0(acc
);
2516 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2517 /* Internal Accumulator Access Format */
2518 rdhi
= (insn
>> 16) & 0xf;
2519 rdlo
= (insn
>> 12) & 0xf;
2525 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2526 gen_iwmmxt_movl_T0_T1_wRn(acc
);
2527 gen_movl_reg_T0(s
, rdlo
);
2528 gen_op_movl_T0_im((1 << (40 - 32)) - 1);
2529 gen_op_andl_T0_T1();
2530 gen_movl_reg_T0(s
, rdhi
);
2532 gen_movl_T0_reg(s
, rdlo
);
2533 gen_movl_T1_reg(s
, rdhi
);
2534 gen_iwmmxt_movl_wRn_T0_T1(acc
);
2542 /* Disassemble system coprocessor instruction. Return nonzero if
2543 instruction is not defined. */
2544 static int disas_cp_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2547 uint32_t rd
= (insn
>> 12) & 0xf;
2548 uint32_t cp
= (insn
>> 8) & 0xf;
2553 if (insn
& ARM_CP_RW_BIT
) {
2554 if (!env
->cp
[cp
].cp_read
)
2556 gen_set_pc_im(s
->pc
);
2558 gen_helper_get_cp(tmp
, cpu_env
, tcg_const_i32(insn
));
2559 store_reg(s
, rd
, tmp
);
2561 if (!env
->cp
[cp
].cp_write
)
2563 gen_set_pc_im(s
->pc
);
2564 tmp
= load_reg(s
, rd
);
2565 gen_helper_set_cp(cpu_env
, tcg_const_i32(insn
), tmp
);
2571 static int cp15_user_ok(uint32_t insn
)
2573 int cpn
= (insn
>> 16) & 0xf;
2574 int cpm
= insn
& 0xf;
2575 int op
= ((insn
>> 5) & 7) | ((insn
>> 18) & 0x38);
2577 if (cpn
== 13 && cpm
== 0) {
2579 if (op
== 2 || (op
== 3 && (insn
& ARM_CP_RW_BIT
)))
2583 /* ISB, DSB, DMB. */
2584 if ((cpm
== 5 && op
== 4)
2585 || (cpm
== 10 && (op
== 4 || op
== 5)))
2591 /* Disassemble system coprocessor (cp15) instruction. Return nonzero if
2592 instruction is not defined. */
2593 static int disas_cp15_insn(CPUState
*env
, DisasContext
*s
, uint32_t insn
)
2598 /* M profile cores use memory mapped registers instead of cp15. */
2599 if (arm_feature(env
, ARM_FEATURE_M
))
2602 if ((insn
& (1 << 25)) == 0) {
2603 if (insn
& (1 << 20)) {
2607 /* mcrr. Used for block cache operations, so implement as no-op. */
2610 if ((insn
& (1 << 4)) == 0) {
2614 if (IS_USER(s
) && !cp15_user_ok(insn
)) {
2617 if ((insn
& 0x0fff0fff) == 0x0e070f90
2618 || (insn
& 0x0fff0fff) == 0x0e070f58) {
2619 /* Wait for interrupt. */
2620 gen_set_pc_im(s
->pc
);
2621 s
->is_jmp
= DISAS_WFI
;
2624 rd
= (insn
>> 12) & 0xf;
2625 if (insn
& ARM_CP_RW_BIT
) {
2627 gen_helper_get_cp15(tmp
, cpu_env
, tcg_const_i32(insn
));
2628 /* If the destination register is r15 then sets condition codes. */
2630 store_reg(s
, rd
, tmp
);
2634 tmp
= load_reg(s
, rd
);
2635 gen_helper_set_cp15(cpu_env
, tcg_const_i32(insn
), tmp
);
2637 /* Normally we would always end the TB here, but Linux
2638 * arch/arm/mach-pxa/sleep.S expects two instructions following
2639 * an MMU enable to execute from cache. Imitate this behaviour. */
2640 if (!arm_feature(env
, ARM_FEATURE_XSCALE
) ||
2641 (insn
& 0x0fff0fff) != 0x0e010f10)
2647 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2648 #define VFP_SREG(insn, bigbit, smallbit) \
2649 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2650 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2651 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2652 reg = (((insn) >> (bigbit)) & 0x0f) \
2653 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2655 if (insn & (1 << (smallbit))) \
2657 reg = ((insn) >> (bigbit)) & 0x0f; \
2660 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2661 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2662 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2663 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2664 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2665 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2667 /* Move between integer and VFP cores. */
2668 static TCGv
gen_vfp_mrs(void)
2670 TCGv tmp
= new_tmp();
2671 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2675 static void gen_vfp_msr(TCGv tmp
)
2677 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2682 vfp_enabled(CPUState
* env
)
2684 return ((env
->vfp
.xregs
[ARM_VFP_FPEXC
] & (1 << 30)) != 0);
2687 static void gen_neon_dup_u8(TCGv var
, int shift
)
2689 TCGv tmp
= new_tmp();
2691 tcg_gen_shri_i32(var
, var
, shift
);
2692 tcg_gen_ext8u_i32(var
, var
);
2693 tcg_gen_shli_i32(tmp
, var
, 8);
2694 tcg_gen_or_i32(var
, var
, tmp
);
2695 tcg_gen_shli_i32(tmp
, var
, 16);
2696 tcg_gen_or_i32(var
, var
, tmp
);
2700 static void gen_neon_dup_low16(TCGv var
)
2702 TCGv tmp
= new_tmp();
2703 tcg_gen_ext16u_i32(var
, var
);
2704 tcg_gen_shli_i32(tmp
, var
, 16);
2705 tcg_gen_or_i32(var
, var
, tmp
);
2709 static void gen_neon_dup_high16(TCGv var
)
2711 TCGv tmp
= new_tmp();
2712 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2713 tcg_gen_shri_i32(tmp
, var
, 16);
2714 tcg_gen_or_i32(var
, var
, tmp
);
2718 /* Disassemble a VFP instruction. Returns nonzero if an error occured
2719 (ie. an undefined instruction). */
2720 static int disas_vfp_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
2722 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2727 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2730 if (!vfp_enabled(env
)) {
2731 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2732 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2734 rn
= (insn
>> 16) & 0xf;
2735 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2736 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2739 dp
= ((insn
& 0xf00) == 0xb00);
2740 switch ((insn
>> 24) & 0xf) {
2742 if (insn
& (1 << 4)) {
2743 /* single register transfer */
2744 rd
= (insn
>> 12) & 0xf;
2749 VFP_DREG_N(rn
, insn
);
2752 if (insn
& 0x00c00060
2753 && !arm_feature(env
, ARM_FEATURE_NEON
))
2756 pass
= (insn
>> 21) & 1;
2757 if (insn
& (1 << 22)) {
2759 offset
= ((insn
>> 5) & 3) * 8;
2760 } else if (insn
& (1 << 5)) {
2762 offset
= (insn
& (1 << 6)) ? 16 : 0;
2767 if (insn
& ARM_CP_RW_BIT
) {
2769 tmp
= neon_load_reg(rn
, pass
);
2773 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2774 if (insn
& (1 << 23))
2780 if (insn
& (1 << 23)) {
2782 tcg_gen_shri_i32(tmp
, tmp
, 16);
2788 tcg_gen_sari_i32(tmp
, tmp
, 16);
2797 store_reg(s
, rd
, tmp
);
2800 tmp
= load_reg(s
, rd
);
2801 if (insn
& (1 << 23)) {
2804 gen_neon_dup_u8(tmp
, 0);
2805 } else if (size
== 1) {
2806 gen_neon_dup_low16(tmp
);
2808 for (n
= 0; n
<= pass
* 2; n
++) {
2810 tcg_gen_mov_i32(tmp2
, tmp
);
2811 neon_store_reg(rn
, n
, tmp2
);
2813 neon_store_reg(rn
, n
, tmp
);
2818 tmp2
= neon_load_reg(rn
, pass
);
2819 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xff);
2823 tmp2
= neon_load_reg(rn
, pass
);
2824 gen_bfi(tmp
, tmp2
, tmp
, offset
, 0xffff);
2830 neon_store_reg(rn
, pass
, tmp
);
2834 if ((insn
& 0x6f) != 0x00)
2836 rn
= VFP_SREG_N(insn
);
2837 if (insn
& ARM_CP_RW_BIT
) {
2839 if (insn
& (1 << 21)) {
2840 /* system register */
2845 /* VFP2 allows access to FSID from userspace.
2846 VFP3 restricts all id registers to privileged
2849 && arm_feature(env
, ARM_FEATURE_VFP3
))
2851 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2856 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2858 case ARM_VFP_FPINST
:
2859 case ARM_VFP_FPINST2
:
2860 /* Not present in VFP3. */
2862 || arm_feature(env
, ARM_FEATURE_VFP3
))
2864 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2868 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2869 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2872 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2878 || !arm_feature(env
, ARM_FEATURE_VFP3
))
2880 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2886 gen_mov_F0_vreg(0, rn
);
2887 tmp
= gen_vfp_mrs();
2890 /* Set the 4 flag bits in the CPSR. */
2894 store_reg(s
, rd
, tmp
);
2898 tmp
= load_reg(s
, rd
);
2899 if (insn
& (1 << 21)) {
2901 /* system register */
2906 /* Writes are ignored. */
2909 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2916 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2919 case ARM_VFP_FPINST
:
2920 case ARM_VFP_FPINST2
:
2921 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2928 gen_mov_vreg_F0(0, rn
);
2933 /* data processing */
2934 /* The opcode is in bits 23, 21, 20 and 6. */
2935 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2939 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2941 /* rn is register number */
2942 VFP_DREG_N(rn
, insn
);
2945 if (op
== 15 && (rn
== 15 || rn
> 17)) {
2946 /* Integer or single precision destination. */
2947 rd
= VFP_SREG_D(insn
);
2949 VFP_DREG_D(rd
, insn
);
2952 if (op
== 15 && (rn
== 16 || rn
== 17)) {
2953 /* Integer source. */
2954 rm
= ((insn
<< 1) & 0x1e) | ((insn
>> 5) & 1);
2956 VFP_DREG_M(rm
, insn
);
2959 rn
= VFP_SREG_N(insn
);
2960 if (op
== 15 && rn
== 15) {
2961 /* Double precision destination. */
2962 VFP_DREG_D(rd
, insn
);
2964 rd
= VFP_SREG_D(insn
);
2966 rm
= VFP_SREG_M(insn
);
2969 veclen
= env
->vfp
.vec_len
;
2970 if (op
== 15 && rn
> 3)
2973 /* Shut up compiler warnings. */
2984 /* Figure out what type of vector operation this is. */
2985 if ((rd
& bank_mask
) == 0) {
2990 delta_d
= (env
->vfp
.vec_stride
>> 1) + 1;
2992 delta_d
= env
->vfp
.vec_stride
+ 1;
2994 if ((rm
& bank_mask
) == 0) {
2995 /* mixed scalar/vector */
3004 /* Load the initial operands. */
3009 /* Integer source */
3010 gen_mov_F0_vreg(0, rm
);
3015 gen_mov_F0_vreg(dp
, rd
);
3016 gen_mov_F1_vreg(dp
, rm
);
3020 /* Compare with zero */
3021 gen_mov_F0_vreg(dp
, rd
);
3032 /* Source and destination the same. */
3033 gen_mov_F0_vreg(dp
, rd
);
3036 /* One source operand. */
3037 gen_mov_F0_vreg(dp
, rm
);
3041 /* Two source operands. */
3042 gen_mov_F0_vreg(dp
, rn
);
3043 gen_mov_F1_vreg(dp
, rm
);
3047 /* Perform the calculation. */
3049 case 0: /* mac: fd + (fn * fm) */
3051 gen_mov_F1_vreg(dp
, rd
);
3054 case 1: /* nmac: fd - (fn * fm) */
3057 gen_mov_F1_vreg(dp
, rd
);
3060 case 2: /* msc: -fd + (fn * fm) */
3062 gen_mov_F1_vreg(dp
, rd
);
3065 case 3: /* nmsc: -fd - (fn * fm) */
3068 gen_mov_F1_vreg(dp
, rd
);
3071 case 4: /* mul: fn * fm */
3074 case 5: /* nmul: -(fn * fm) */
3078 case 6: /* add: fn + fm */
3081 case 7: /* sub: fn - fm */
3084 case 8: /* div: fn / fm */
3087 case 14: /* fconst */
3088 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3091 n
= (insn
<< 12) & 0x80000000;
3092 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3099 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3106 tcg_gen_movi_i32(cpu_F0s
, n
);
3109 case 15: /* extension space */
3132 case 11: /* cmpez */
3136 case 15: /* single<->double conversion */
3138 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3140 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3142 case 16: /* fuito */
3145 case 17: /* fsito */
3148 case 20: /* fshto */
3149 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3151 gen_vfp_shto(dp
, 16 - rm
);
3153 case 21: /* fslto */
3154 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3156 gen_vfp_slto(dp
, 32 - rm
);
3158 case 22: /* fuhto */
3159 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3161 gen_vfp_uhto(dp
, 16 - rm
);
3163 case 23: /* fulto */
3164 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3166 gen_vfp_ulto(dp
, 32 - rm
);
3168 case 24: /* ftoui */
3171 case 25: /* ftouiz */
3174 case 26: /* ftosi */
3177 case 27: /* ftosiz */
3180 case 28: /* ftosh */
3181 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3183 gen_vfp_tosh(dp
, 16 - rm
);
3185 case 29: /* ftosl */
3186 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3188 gen_vfp_tosl(dp
, 32 - rm
);
3190 case 30: /* ftouh */
3191 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3193 gen_vfp_touh(dp
, 16 - rm
);
3195 case 31: /* ftoul */
3196 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3198 gen_vfp_toul(dp
, 32 - rm
);
3200 default: /* undefined */
3201 printf ("rn:%d\n", rn
);
3205 default: /* undefined */
3206 printf ("op:%d\n", op
);
3210 /* Write back the result. */
3211 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3212 ; /* Comparison, do nothing. */
3213 else if (op
== 15 && rn
> 17)
3214 /* Integer result. */
3215 gen_mov_vreg_F0(0, rd
);
3216 else if (op
== 15 && rn
== 15)
3218 gen_mov_vreg_F0(!dp
, rd
);
3220 gen_mov_vreg_F0(dp
, rd
);
3222 /* break out of the loop if we have finished */
3226 if (op
== 15 && delta_m
== 0) {
3227 /* single source one-many */
3229 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3231 gen_mov_vreg_F0(dp
, rd
);
3235 /* Setup the next operands. */
3237 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3241 /* One source operand. */
3242 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3244 gen_mov_F0_vreg(dp
, rm
);
3246 /* Two source operands. */
3247 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3249 gen_mov_F0_vreg(dp
, rn
);
3251 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3253 gen_mov_F1_vreg(dp
, rm
);
3261 if (dp
&& (insn
& 0x03e00000) == 0x00400000) {
3262 /* two-register transfer */
3263 rn
= (insn
>> 16) & 0xf;
3264 rd
= (insn
>> 12) & 0xf;
3266 VFP_DREG_M(rm
, insn
);
3268 rm
= VFP_SREG_M(insn
);
3271 if (insn
& ARM_CP_RW_BIT
) {
3274 gen_mov_F0_vreg(0, rm
* 2);
3275 tmp
= gen_vfp_mrs();
3276 store_reg(s
, rd
, tmp
);
3277 gen_mov_F0_vreg(0, rm
* 2 + 1);
3278 tmp
= gen_vfp_mrs();
3279 store_reg(s
, rn
, tmp
);
3281 gen_mov_F0_vreg(0, rm
);
3282 tmp
= gen_vfp_mrs();
3283 store_reg(s
, rn
, tmp
);
3284 gen_mov_F0_vreg(0, rm
+ 1);
3285 tmp
= gen_vfp_mrs();
3286 store_reg(s
, rd
, tmp
);
3291 tmp
= load_reg(s
, rd
);
3293 gen_mov_vreg_F0(0, rm
* 2);
3294 tmp
= load_reg(s
, rn
);
3296 gen_mov_vreg_F0(0, rm
* 2 + 1);
3298 tmp
= load_reg(s
, rn
);
3300 gen_mov_vreg_F0(0, rm
);
3301 tmp
= load_reg(s
, rd
);
3303 gen_mov_vreg_F0(0, rm
+ 1);
3308 rn
= (insn
>> 16) & 0xf;
3310 VFP_DREG_D(rd
, insn
);
3312 rd
= VFP_SREG_D(insn
);
3313 if (s
->thumb
&& rn
== 15) {
3314 gen_op_movl_T1_im(s
->pc
& ~2);
3316 gen_movl_T1_reg(s
, rn
);
3318 if ((insn
& 0x01200000) == 0x01000000) {
3319 /* Single load/store */
3320 offset
= (insn
& 0xff) << 2;
3321 if ((insn
& (1 << 23)) == 0)
3323 gen_op_addl_T1_im(offset
);
3324 if (insn
& (1 << 20)) {
3326 gen_mov_vreg_F0(dp
, rd
);
3328 gen_mov_F0_vreg(dp
, rd
);
3332 /* load/store multiple */
3334 n
= (insn
>> 1) & 0x7f;
3338 if (insn
& (1 << 24)) /* pre-decrement */
3339 gen_op_addl_T1_im(-((insn
& 0xff) << 2));
3345 for (i
= 0; i
< n
; i
++) {
3346 if (insn
& ARM_CP_RW_BIT
) {
3349 gen_mov_vreg_F0(dp
, rd
+ i
);
3352 gen_mov_F0_vreg(dp
, rd
+ i
);
3355 gen_op_addl_T1_im(offset
);
3357 if (insn
& (1 << 21)) {
3359 if (insn
& (1 << 24))
3360 offset
= -offset
* n
;
3361 else if (dp
&& (insn
& 1))
3367 gen_op_addl_T1_im(offset
);
3368 gen_movl_reg_T1(s
, rn
);
3374 /* Should never happen. */
3380 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3382 TranslationBlock
*tb
;
3385 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3387 gen_set_pc_im(dest
);
3388 tcg_gen_exit_tb((long)tb
+ n
);
3390 gen_set_pc_im(dest
);
3395 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3397 if (unlikely(s
->singlestep_enabled
)) {
3398 /* An indirect jump so that we still trigger the debug exception. */
3403 gen_goto_tb(s
, 0, dest
);
3404 s
->is_jmp
= DISAS_TB_JUMP
;
3408 static inline void gen_mulxy(TCGv t0
, TCGv t1
, int x
, int y
)
3411 tcg_gen_sari_i32(t0
, t0
, 16);
3415 tcg_gen_sari_i32(t1
, t1
, 16);
3418 tcg_gen_mul_i32(t0
, t0
, t1
);
3421 /* Return the mask of PSR bits set by a MSR instruction. */
3422 static uint32_t msr_mask(CPUState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3426 if (flags
& (1 << 0))
3428 if (flags
& (1 << 1))
3430 if (flags
& (1 << 2))
3432 if (flags
& (1 << 3))
3435 /* Mask out undefined bits. */
3436 mask
&= ~CPSR_RESERVED
;
3437 if (!arm_feature(env
, ARM_FEATURE_V6
))
3438 mask
&= ~(CPSR_E
| CPSR_GE
);
3439 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3441 /* Mask out execution state bits. */
3444 /* Mask out privileged bits. */
3450 /* Returns nonzero if access to the PSR is not permitted. */
3451 static int gen_set_psr_T0(DisasContext
*s
, uint32_t mask
, int spsr
)
3455 /* ??? This is also undefined in system mode. */
3459 tmp
= load_cpu_field(spsr
);
3460 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3461 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], mask
);
3462 tcg_gen_or_i32(tmp
, tmp
, cpu_T
[0]);
3463 store_cpu_field(tmp
, spsr
);
3465 gen_set_cpsr(cpu_T
[0], mask
);
3471 /* Generate an old-style exception return. Marks pc as dead. */
3472 static void gen_exception_return(DisasContext
*s
, TCGv pc
)
3475 store_reg(s
, 15, pc
);
3476 tmp
= load_cpu_field(spsr
);
3477 gen_set_cpsr(tmp
, 0xffffffff);
3479 s
->is_jmp
= DISAS_UPDATE
;
3482 /* Generate a v6 exception return. Marks both values as dead. */
3483 static void gen_rfe(DisasContext
*s
, TCGv pc
, TCGv cpsr
)
3485 gen_set_cpsr(cpsr
, 0xffffffff);
3487 store_reg(s
, 15, pc
);
3488 s
->is_jmp
= DISAS_UPDATE
;
3492 gen_set_condexec (DisasContext
*s
)
3494 if (s
->condexec_mask
) {
3495 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3496 TCGv tmp
= new_tmp();
3497 tcg_gen_movi_i32(tmp
, val
);
3498 store_cpu_field(tmp
, condexec_bits
);
3502 static void gen_nop_hint(DisasContext
*s
, int val
)
3506 gen_set_pc_im(s
->pc
);
3507 s
->is_jmp
= DISAS_WFI
;
3511 /* TODO: Implement SEV and WFE. May help SMP performance. */
3517 /* These macros help make the code more readable when migrating from the
3518 old dyngen helpers. They should probably be removed when
3519 T0/T1 are removed. */
3520 #define CPU_T001 cpu_T[0], cpu_T[0], cpu_T[1]
3521 #define CPU_T0E01 cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]
3523 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3525 static inline int gen_neon_add(int size
)
3528 case 0: gen_helper_neon_add_u8(CPU_T001
); break;
3529 case 1: gen_helper_neon_add_u16(CPU_T001
); break;
3530 case 2: gen_op_addl_T0_T1(); break;
3536 static inline void gen_neon_rsb(int size
)
3539 case 0: gen_helper_neon_sub_u8(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3540 case 1: gen_helper_neon_sub_u16(cpu_T
[0], cpu_T
[1], cpu_T
[0]); break;
3541 case 2: gen_op_rsbl_T0_T1(); break;
3546 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3547 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3548 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3549 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3550 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3552 /* FIXME: This is wrong. They set the wrong overflow bit. */
3553 #define gen_helper_neon_qadd_s32(a, e, b, c) gen_helper_add_saturate(a, b, c)
3554 #define gen_helper_neon_qadd_u32(a, e, b, c) gen_helper_add_usaturate(a, b, c)
3555 #define gen_helper_neon_qsub_s32(a, e, b, c) gen_helper_sub_saturate(a, b, c)
3556 #define gen_helper_neon_qsub_u32(a, e, b, c) gen_helper_sub_usaturate(a, b, c)
3558 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3559 switch ((size << 1) | u) { \
3561 gen_helper_neon_##name##_s8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3564 gen_helper_neon_##name##_u8(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3567 gen_helper_neon_##name##_s16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3570 gen_helper_neon_##name##_u16(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3573 gen_helper_neon_##name##_s32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3576 gen_helper_neon_##name##_u32(cpu_T[0], cpu_env, cpu_T[0], cpu_T[1]); \
3578 default: return 1; \
3581 #define GEN_NEON_INTEGER_OP(name) do { \
3582 switch ((size << 1) | u) { \
3584 gen_helper_neon_##name##_s8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3587 gen_helper_neon_##name##_u8(cpu_T[0], cpu_T[0], cpu_T[1]); \
3590 gen_helper_neon_##name##_s16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3593 gen_helper_neon_##name##_u16(cpu_T[0], cpu_T[0], cpu_T[1]); \
3596 gen_helper_neon_##name##_s32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3599 gen_helper_neon_##name##_u32(cpu_T[0], cpu_T[0], cpu_T[1]); \
3601 default: return 1; \
3605 gen_neon_movl_scratch_T0(int scratch
)
3609 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3610 tcg_gen_st_i32(cpu_T
[0], cpu_env
, offset
);
3614 gen_neon_movl_scratch_T1(int scratch
)
3618 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3619 tcg_gen_st_i32(cpu_T
[1], cpu_env
, offset
);
3623 gen_neon_movl_T0_scratch(int scratch
)
3627 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3628 tcg_gen_ld_i32(cpu_T
[0], cpu_env
, offset
);
3632 gen_neon_movl_T1_scratch(int scratch
)
3636 offset
= offsetof(CPUARMState
, vfp
.scratch
[scratch
]);
3637 tcg_gen_ld_i32(cpu_T
[1], cpu_env
, offset
);
3640 static inline void gen_neon_get_scalar(int size
, int reg
)
3643 NEON_GET_REG(T0
, reg
>> 1, reg
& 1);
3645 NEON_GET_REG(T0
, reg
>> 2, (reg
>> 1) & 1);
3647 gen_neon_dup_low16(cpu_T
[0]);
3649 gen_neon_dup_high16(cpu_T
[0]);
3653 static void gen_neon_unzip(int reg
, int q
, int tmp
, int size
)
3657 for (n
= 0; n
< q
+ 1; n
+= 2) {
3658 NEON_GET_REG(T0
, reg
, n
);
3659 NEON_GET_REG(T0
, reg
, n
+ n
);
3661 case 0: gen_helper_neon_unzip_u8(); break;
3662 case 1: gen_helper_neon_zip_u16(); break; /* zip and unzip are the same. */
3663 case 2: /* no-op */; break;
3666 gen_neon_movl_scratch_T0(tmp
+ n
);
3667 gen_neon_movl_scratch_T1(tmp
+ n
+ 1);
3675 } neon_ls_element_type
[11] = {
3689 /* Translate a NEON load/store element instruction. Return nonzero if the
3690 instruction is invalid. */
3691 static int disas_neon_ls_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
3707 if (!vfp_enabled(env
))
3709 VFP_DREG_D(rd
, insn
);
3710 rn
= (insn
>> 16) & 0xf;
3712 load
= (insn
& (1 << 21)) != 0;
3713 if ((insn
& (1 << 23)) == 0) {
3714 /* Load store all elements. */
3715 op
= (insn
>> 8) & 0xf;
3716 size
= (insn
>> 6) & 3;
3717 if (op
> 10 || size
== 3)
3719 nregs
= neon_ls_element_type
[op
].nregs
;
3720 interleave
= neon_ls_element_type
[op
].interleave
;
3721 gen_movl_T1_reg(s
, rn
);
3722 stride
= (1 << size
) * interleave
;
3723 for (reg
= 0; reg
< nregs
; reg
++) {
3724 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3725 gen_movl_T1_reg(s
, rn
);
3726 gen_op_addl_T1_im((1 << size
) * reg
);
3727 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3728 gen_movl_T1_reg(s
, rn
);
3729 gen_op_addl_T1_im(1 << size
);
3731 for (pass
= 0; pass
< 2; pass
++) {
3734 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3735 neon_store_reg(rd
, pass
, tmp
);
3737 tmp
= neon_load_reg(rd
, pass
);
3738 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3740 gen_op_addl_T1_im(stride
);
3741 } else if (size
== 1) {
3743 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3744 gen_op_addl_T1_im(stride
);
3745 tmp2
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3746 gen_op_addl_T1_im(stride
);
3747 gen_bfi(tmp
, tmp
, tmp2
, 16, 0xffff);
3749 neon_store_reg(rd
, pass
, tmp
);
3751 tmp
= neon_load_reg(rd
, pass
);
3753 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3754 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3755 gen_op_addl_T1_im(stride
);
3756 gen_st16(tmp2
, cpu_T
[1], IS_USER(s
));
3757 gen_op_addl_T1_im(stride
);
3759 } else /* size == 0 */ {
3762 for (n
= 0; n
< 4; n
++) {
3763 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3764 gen_op_addl_T1_im(stride
);
3768 gen_bfi(tmp2
, tmp2
, tmp
, n
* 8, 0xff);
3772 neon_store_reg(rd
, pass
, tmp2
);
3774 tmp2
= neon_load_reg(rd
, pass
);
3775 for (n
= 0; n
< 4; n
++) {
3778 tcg_gen_mov_i32(tmp
, tmp2
);
3780 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3782 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3783 gen_op_addl_T1_im(stride
);
3789 rd
+= neon_ls_element_type
[op
].spacing
;
3793 size
= (insn
>> 10) & 3;
3795 /* Load single element to all lanes. */
3798 size
= (insn
>> 6) & 3;
3799 nregs
= ((insn
>> 8) & 3) + 1;
3800 stride
= (insn
& (1 << 5)) ? 2 : 1;
3801 gen_movl_T1_reg(s
, rn
);
3802 for (reg
= 0; reg
< nregs
; reg
++) {
3805 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3806 gen_neon_dup_u8(tmp
, 0);
3809 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3810 gen_neon_dup_low16(tmp
);
3813 tmp
= gen_ld32(cpu_T
[0], IS_USER(s
));
3817 default: /* Avoid compiler warnings. */
3820 gen_op_addl_T1_im(1 << size
);
3822 tcg_gen_mov_i32(tmp2
, tmp
);
3823 neon_store_reg(rd
, 0, tmp2
);
3824 neon_store_reg(rd
, 1, tmp
);
3827 stride
= (1 << size
) * nregs
;
3829 /* Single element. */
3830 pass
= (insn
>> 7) & 1;
3833 shift
= ((insn
>> 5) & 3) * 8;
3837 shift
= ((insn
>> 6) & 1) * 16;
3838 stride
= (insn
& (1 << 5)) ? 2 : 1;
3842 stride
= (insn
& (1 << 6)) ? 2 : 1;
3847 nregs
= ((insn
>> 8) & 3) + 1;
3848 gen_movl_T1_reg(s
, rn
);
3849 for (reg
= 0; reg
< nregs
; reg
++) {
3853 tmp
= gen_ld8u(cpu_T
[1], IS_USER(s
));
3856 tmp
= gen_ld16u(cpu_T
[1], IS_USER(s
));
3859 tmp
= gen_ld32(cpu_T
[1], IS_USER(s
));
3861 default: /* Avoid compiler warnings. */
3865 tmp2
= neon_load_reg(rd
, pass
);
3866 gen_bfi(tmp
, tmp2
, tmp
, shift
, size
? 0xffff : 0xff);
3869 neon_store_reg(rd
, pass
, tmp
);
3870 } else { /* Store */
3871 tmp
= neon_load_reg(rd
, pass
);
3873 tcg_gen_shri_i32(tmp
, tmp
, shift
);
3876 gen_st8(tmp
, cpu_T
[1], IS_USER(s
));
3879 gen_st16(tmp
, cpu_T
[1], IS_USER(s
));
3882 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
3887 gen_op_addl_T1_im(1 << size
);
3889 stride
= nregs
* (1 << size
);
3895 base
= load_reg(s
, rn
);
3897 tcg_gen_addi_i32(base
, base
, stride
);
3900 index
= load_reg(s
, rm
);
3901 tcg_gen_add_i32(base
, base
, index
);
3904 store_reg(s
, rn
, base
);
3909 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
3910 static void gen_neon_bsl(TCGv dest
, TCGv t
, TCGv f
, TCGv c
)
3912 tcg_gen_and_i32(t
, t
, c
);
3913 tcg_gen_bic_i32(f
, f
, c
);
3914 tcg_gen_or_i32(dest
, t
, f
);
3917 static inline void gen_neon_narrow(int size
, TCGv dest
, TCGv_i64 src
)
3920 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
3921 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
3922 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
3927 static inline void gen_neon_narrow_sats(int size
, TCGv dest
, TCGv_i64 src
)
3930 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
3931 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
3932 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
3937 static inline void gen_neon_narrow_satu(int size
, TCGv dest
, TCGv_i64 src
)
3940 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
3941 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
3942 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
3947 static inline void gen_neon_shift_narrow(int size
, TCGv var
, TCGv shift
,
3953 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3954 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3959 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
3960 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
3967 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
3968 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
3973 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
3974 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
3981 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv src
, int size
, int u
)
3985 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
3986 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
3987 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
3992 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
3993 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
3994 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4001 static inline void gen_neon_addl(int size
)
4004 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4005 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4006 case 2: tcg_gen_add_i64(CPU_V001
); break;
4011 static inline void gen_neon_subl(int size
)
4014 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4015 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4016 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4021 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4024 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4025 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4026 case 2: gen_helper_neon_negl_u64(var
, var
); break;
4031 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4034 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4035 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4040 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv a
, TCGv b
, int size
, int u
)
4044 switch ((size
<< 1) | u
) {
4045 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4046 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4047 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4048 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4050 tmp
= gen_muls_i64_i32(a
, b
);
4051 tcg_gen_mov_i64(dest
, tmp
);
4054 tmp
= gen_mulu_i64_i32(a
, b
);
4055 tcg_gen_mov_i64(dest
, tmp
);
4065 /* Translate a NEON data processing instruction. Return nonzero if the
4066 instruction is invalid.
4067 We process data in a mixture of 32-bit and 64-bit chunks.
4068 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4070 static int disas_neon_data_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
4088 if (!vfp_enabled(env
))
4090 q
= (insn
& (1 << 6)) != 0;
4091 u
= (insn
>> 24) & 1;
4092 VFP_DREG_D(rd
, insn
);
4093 VFP_DREG_N(rn
, insn
);
4094 VFP_DREG_M(rm
, insn
);
4095 size
= (insn
>> 20) & 3;
4096 if ((insn
& (1 << 23)) == 0) {
4097 /* Three register same length. */
4098 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4099 if (size
== 3 && (op
== 1 || op
== 5 || op
== 8 || op
== 9
4100 || op
== 10 || op
== 11 || op
== 16)) {
4101 /* 64-bit element instructions. */
4102 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4103 neon_load_reg64(cpu_V0
, rn
+ pass
);
4104 neon_load_reg64(cpu_V1
, rm
+ pass
);
4108 gen_helper_neon_add_saturate_u64(CPU_V001
);
4110 gen_helper_neon_add_saturate_s64(CPU_V001
);
4115 gen_helper_neon_sub_saturate_u64(CPU_V001
);
4117 gen_helper_neon_sub_saturate_s64(CPU_V001
);
4122 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4124 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4129 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4132 gen_helper_neon_qshl_s64(cpu_V1
, cpu_env
,
4136 case 10: /* VRSHL */
4138 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4140 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4143 case 11: /* VQRSHL */
4145 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4148 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4154 tcg_gen_sub_i64(CPU_V001
);
4156 tcg_gen_add_i64(CPU_V001
);
4162 neon_store_reg64(cpu_V0
, rd
+ pass
);
4169 case 10: /* VRSHL */
4170 case 11: /* VQRSHL */
4173 /* Shift instruction operands are reversed. */
4180 case 20: /* VPMAX */
4181 case 21: /* VPMIN */
4182 case 23: /* VPADD */
4185 case 26: /* VPADD (float) */
4186 pairwise
= (u
&& size
< 2);
4188 case 30: /* VPMIN/VPMAX (float) */
4195 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4204 NEON_GET_REG(T0
, rn
, n
);
4205 NEON_GET_REG(T1
, rn
, n
+ 1);
4207 NEON_GET_REG(T0
, rm
, n
);
4208 NEON_GET_REG(T1
, rm
, n
+ 1);
4212 NEON_GET_REG(T0
, rn
, pass
);
4213 NEON_GET_REG(T1
, rm
, pass
);
4217 GEN_NEON_INTEGER_OP(hadd
);
4220 GEN_NEON_INTEGER_OP_ENV(qadd
);
4222 case 2: /* VRHADD */
4223 GEN_NEON_INTEGER_OP(rhadd
);
4225 case 3: /* Logic ops. */
4226 switch ((u
<< 2) | size
) {
4228 gen_op_andl_T0_T1();
4231 gen_op_bicl_T0_T1();
4241 gen_op_xorl_T0_T1();
4244 tmp
= neon_load_reg(rd
, pass
);
4245 gen_neon_bsl(cpu_T
[0], cpu_T
[0], cpu_T
[1], tmp
);
4249 tmp
= neon_load_reg(rd
, pass
);
4250 gen_neon_bsl(cpu_T
[0], cpu_T
[0], tmp
, cpu_T
[1]);
4254 tmp
= neon_load_reg(rd
, pass
);
4255 gen_neon_bsl(cpu_T
[0], tmp
, cpu_T
[0], cpu_T
[1]);
4261 GEN_NEON_INTEGER_OP(hsub
);
4264 GEN_NEON_INTEGER_OP_ENV(qsub
);
4267 GEN_NEON_INTEGER_OP(cgt
);
4270 GEN_NEON_INTEGER_OP(cge
);
4273 GEN_NEON_INTEGER_OP(shl
);
4276 GEN_NEON_INTEGER_OP_ENV(qshl
);
4278 case 10: /* VRSHL */
4279 GEN_NEON_INTEGER_OP(rshl
);
4281 case 11: /* VQRSHL */
4282 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4285 GEN_NEON_INTEGER_OP(max
);
4288 GEN_NEON_INTEGER_OP(min
);
4291 GEN_NEON_INTEGER_OP(abd
);
4294 GEN_NEON_INTEGER_OP(abd
);
4295 NEON_GET_REG(T1
, rd
, pass
);
4299 if (!u
) { /* VADD */
4300 if (gen_neon_add(size
))
4304 case 0: gen_helper_neon_sub_u8(CPU_T001
); break;
4305 case 1: gen_helper_neon_sub_u16(CPU_T001
); break;
4306 case 2: gen_op_subl_T0_T1(); break;
4312 if (!u
) { /* VTST */
4314 case 0: gen_helper_neon_tst_u8(CPU_T001
); break;
4315 case 1: gen_helper_neon_tst_u16(CPU_T001
); break;
4316 case 2: gen_helper_neon_tst_u32(CPU_T001
); break;
4321 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
4322 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
4323 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
4328 case 18: /* Multiply. */
4330 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4331 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4332 case 2: gen_op_mul_T0_T1(); break;
4335 NEON_GET_REG(T1
, rd
, pass
);
4343 if (u
) { /* polynomial */
4344 gen_helper_neon_mul_p8(CPU_T001
);
4345 } else { /* Integer */
4347 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
4348 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
4349 case 2: gen_op_mul_T0_T1(); break;
4354 case 20: /* VPMAX */
4355 GEN_NEON_INTEGER_OP(pmax
);
4357 case 21: /* VPMIN */
4358 GEN_NEON_INTEGER_OP(pmin
);
4360 case 22: /* Hultiply high. */
4361 if (!u
) { /* VQDMULH */
4363 case 1: gen_helper_neon_qdmulh_s16(CPU_T0E01
); break;
4364 case 2: gen_helper_neon_qdmulh_s32(CPU_T0E01
); break;
4367 } else { /* VQRDHMUL */
4369 case 1: gen_helper_neon_qrdmulh_s16(CPU_T0E01
); break;
4370 case 2: gen_helper_neon_qrdmulh_s32(CPU_T0E01
); break;
4375 case 23: /* VPADD */
4379 case 0: gen_helper_neon_padd_u8(CPU_T001
); break;
4380 case 1: gen_helper_neon_padd_u16(CPU_T001
); break;
4381 case 2: gen_op_addl_T0_T1(); break;
4385 case 26: /* Floating point arithnetic. */
4386 switch ((u
<< 2) | size
) {
4388 gen_helper_neon_add_f32(CPU_T001
);
4391 gen_helper_neon_sub_f32(CPU_T001
);
4394 gen_helper_neon_add_f32(CPU_T001
);
4397 gen_helper_neon_abd_f32(CPU_T001
);
4403 case 27: /* Float multiply. */
4404 gen_helper_neon_mul_f32(CPU_T001
);
4406 NEON_GET_REG(T1
, rd
, pass
);
4408 gen_helper_neon_add_f32(CPU_T001
);
4410 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
4414 case 28: /* Float compare. */
4416 gen_helper_neon_ceq_f32(CPU_T001
);
4419 gen_helper_neon_cge_f32(CPU_T001
);
4421 gen_helper_neon_cgt_f32(CPU_T001
);
4424 case 29: /* Float compare absolute. */
4428 gen_helper_neon_acge_f32(CPU_T001
);
4430 gen_helper_neon_acgt_f32(CPU_T001
);
4432 case 30: /* Float min/max. */
4434 gen_helper_neon_max_f32(CPU_T001
);
4436 gen_helper_neon_min_f32(CPU_T001
);
4440 gen_helper_recps_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4442 gen_helper_rsqrts_f32(cpu_T
[0], cpu_T
[0], cpu_T
[1], cpu_env
);
4447 /* Save the result. For elementwise operations we can put it
4448 straight into the destination register. For pairwise operations
4449 we have to be careful to avoid clobbering the source operands. */
4450 if (pairwise
&& rd
== rm
) {
4451 gen_neon_movl_scratch_T0(pass
);
4453 NEON_SET_REG(T0
, rd
, pass
);
4457 if (pairwise
&& rd
== rm
) {
4458 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4459 gen_neon_movl_T0_scratch(pass
);
4460 NEON_SET_REG(T0
, rd
, pass
);
4463 /* End of 3 register same size operations. */
4464 } else if (insn
& (1 << 4)) {
4465 if ((insn
& 0x00380080) != 0) {
4466 /* Two registers and shift. */
4467 op
= (insn
>> 8) & 0xf;
4468 if (insn
& (1 << 7)) {
4473 while ((insn
& (1 << (size
+ 19))) == 0)
4476 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4477 /* To avoid excessive dumplication of ops we implement shift
4478 by immediate using the variable shift operations. */
4480 /* Shift by immediate:
4481 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4482 /* Right shifts are encoded as N - shift, where N is the
4483 element size in bits. */
4485 shift
= shift
- (1 << (size
+ 3));
4493 imm
= (uint8_t) shift
;
4498 imm
= (uint16_t) shift
;
4509 for (pass
= 0; pass
< count
; pass
++) {
4511 neon_load_reg64(cpu_V0
, rm
+ pass
);
4512 tcg_gen_movi_i64(cpu_V1
, imm
);
4517 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4519 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4524 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4526 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4531 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4533 case 5: /* VSHL, VSLI */
4534 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4538 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4540 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4542 case 7: /* VQSHLU */
4543 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
, cpu_V0
, cpu_V1
);
4546 if (op
== 1 || op
== 3) {
4548 neon_load_reg64(cpu_V0
, rd
+ pass
);
4549 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
4550 } else if (op
== 4 || (op
== 5 && u
)) {
4552 cpu_abort(env
, "VS[LR]I.64 not implemented");
4554 neon_store_reg64(cpu_V0
, rd
+ pass
);
4555 } else { /* size < 3 */
4556 /* Operands in T0 and T1. */
4557 gen_op_movl_T1_im(imm
);
4558 NEON_GET_REG(T0
, rm
, pass
);
4562 GEN_NEON_INTEGER_OP(shl
);
4566 GEN_NEON_INTEGER_OP(rshl
);
4571 GEN_NEON_INTEGER_OP(shl
);
4573 case 5: /* VSHL, VSLI */
4575 case 0: gen_helper_neon_shl_u8(CPU_T001
); break;
4576 case 1: gen_helper_neon_shl_u16(CPU_T001
); break;
4577 case 2: gen_helper_neon_shl_u32(CPU_T001
); break;
4582 GEN_NEON_INTEGER_OP_ENV(qshl
);
4584 case 7: /* VQSHLU */
4586 case 0: gen_helper_neon_qshl_u8(CPU_T0E01
); break;
4587 case 1: gen_helper_neon_qshl_u16(CPU_T0E01
); break;
4588 case 2: gen_helper_neon_qshl_u32(CPU_T0E01
); break;
4594 if (op
== 1 || op
== 3) {
4596 NEON_GET_REG(T1
, rd
, pass
);
4598 } else if (op
== 4 || (op
== 5 && u
)) {
4603 imm
= 0xff >> -shift
;
4605 imm
= (uint8_t)(0xff << shift
);
4611 imm
= 0xffff >> -shift
;
4613 imm
= (uint16_t)(0xffff << shift
);
4618 imm
= 0xffffffffu
>> -shift
;
4620 imm
= 0xffffffffu
<< shift
;
4625 tmp
= neon_load_reg(rd
, pass
);
4626 tcg_gen_andi_i32(cpu_T
[0], cpu_T
[0], imm
);
4627 tcg_gen_andi_i32(tmp
, tmp
, ~imm
);
4628 tcg_gen_or_i32(cpu_T
[0], cpu_T
[0], tmp
);
4630 NEON_SET_REG(T0
, rd
, pass
);
4633 } else if (op
< 10) {
4634 /* Shift by immediate and narrow:
4635 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
4636 shift
= shift
- (1 << (size
+ 3));
4640 imm
= (uint16_t)shift
;
4642 tmp2
= tcg_const_i32(imm
);
4643 TCGV_UNUSED_I64(tmp64
);
4646 imm
= (uint32_t)shift
;
4647 tmp2
= tcg_const_i32(imm
);
4648 TCGV_UNUSED_I64(tmp64
);
4651 tmp64
= tcg_const_i64(shift
);
4658 for (pass
= 0; pass
< 2; pass
++) {
4660 neon_load_reg64(cpu_V0
, rm
+ pass
);
4663 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, tmp64
);
4665 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, tmp64
);
4668 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, tmp64
);
4670 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, tmp64
);
4673 tmp
= neon_load_reg(rm
+ pass
, 0);
4674 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
, u
);
4675 tmp3
= neon_load_reg(rm
+ pass
, 1);
4676 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
, u
);
4677 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
4682 if (op
== 8 && !u
) {
4683 gen_neon_narrow(size
- 1, tmp
, cpu_V0
);
4686 gen_neon_narrow_sats(size
- 1, tmp
, cpu_V0
);
4688 gen_neon_narrow_satu(size
- 1, tmp
, cpu_V0
);
4693 neon_store_reg(rd
, 0, tmp2
);
4694 neon_store_reg(rd
, 1, tmp
);
4697 } else if (op
== 10) {
4701 tmp
= neon_load_reg(rm
, 0);
4702 tmp2
= neon_load_reg(rm
, 1);
4703 for (pass
= 0; pass
< 2; pass
++) {
4707 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4710 /* The shift is less than the width of the source
4711 type, so we can just shift the whole register. */
4712 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
4713 if (size
< 2 || !u
) {
4716 imm
= (0xffu
>> (8 - shift
));
4719 imm
= 0xffff >> (16 - shift
);
4721 imm64
= imm
| (((uint64_t)imm
) << 32);
4722 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, imm64
);
4725 neon_store_reg64(cpu_V0
, rd
+ pass
);
4727 } else if (op
== 15 || op
== 16) {
4728 /* VCVT fixed-point. */
4729 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4730 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
4733 gen_vfp_ulto(0, shift
);
4735 gen_vfp_slto(0, shift
);
4738 gen_vfp_toul(0, shift
);
4740 gen_vfp_tosl(0, shift
);
4742 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
4747 } else { /* (insn & 0x00380080) == 0 */
4750 op
= (insn
>> 8) & 0xf;
4751 /* One register and immediate. */
4752 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
4753 invert
= (insn
& (1 << 5)) != 0;
4771 imm
= (imm
<< 8) | (imm
<< 24);
4774 imm
= (imm
< 8) | 0xff;
4777 imm
= (imm
<< 16) | 0xffff;
4780 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
4785 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
4786 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
4792 if (op
!= 14 || !invert
)
4793 gen_op_movl_T1_im(imm
);
4795 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4796 if (op
& 1 && op
< 12) {
4797 tmp
= neon_load_reg(rd
, pass
);
4799 /* The immediate value has already been inverted, so
4801 tcg_gen_andi_i32(tmp
, tmp
, imm
);
4803 tcg_gen_ori_i32(tmp
, tmp
, imm
);
4808 if (op
== 14 && invert
) {
4811 for (n
= 0; n
< 4; n
++) {
4812 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
4813 val
|= 0xff << (n
* 8);
4815 tcg_gen_movi_i32(tmp
, val
);
4817 tcg_gen_movi_i32(tmp
, imm
);
4820 neon_store_reg(rd
, pass
, tmp
);
4823 } else { /* (insn & 0x00800010 == 0x00800000) */
4825 op
= (insn
>> 8) & 0xf;
4826 if ((insn
& (1 << 6)) == 0) {
4827 /* Three registers of different lengths. */
4831 /* prewiden, src1_wide, src2_wide */
4832 static const int neon_3reg_wide
[16][3] = {
4833 {1, 0, 0}, /* VADDL */
4834 {1, 1, 0}, /* VADDW */
4835 {1, 0, 0}, /* VSUBL */
4836 {1, 1, 0}, /* VSUBW */
4837 {0, 1, 1}, /* VADDHN */
4838 {0, 0, 0}, /* VABAL */
4839 {0, 1, 1}, /* VSUBHN */
4840 {0, 0, 0}, /* VABDL */
4841 {0, 0, 0}, /* VMLAL */
4842 {0, 0, 0}, /* VQDMLAL */
4843 {0, 0, 0}, /* VMLSL */
4844 {0, 0, 0}, /* VQDMLSL */
4845 {0, 0, 0}, /* Integer VMULL */
4846 {0, 0, 0}, /* VQDMULL */
4847 {0, 0, 0} /* Polynomial VMULL */
4850 prewiden
= neon_3reg_wide
[op
][0];
4851 src1_wide
= neon_3reg_wide
[op
][1];
4852 src2_wide
= neon_3reg_wide
[op
][2];
4854 if (size
== 0 && (op
== 9 || op
== 11 || op
== 13))
4857 /* Avoid overlapping operands. Wide source operands are
4858 always aligned so will never overlap with wide
4859 destinations in problematic ways. */
4860 if (rd
== rm
&& !src2_wide
) {
4861 NEON_GET_REG(T0
, rm
, 1);
4862 gen_neon_movl_scratch_T0(2);
4863 } else if (rd
== rn
&& !src1_wide
) {
4864 NEON_GET_REG(T0
, rn
, 1);
4865 gen_neon_movl_scratch_T0(2);
4868 for (pass
= 0; pass
< 2; pass
++) {
4870 neon_load_reg64(cpu_V0
, rn
+ pass
);
4873 if (pass
== 1 && rd
== rn
) {
4874 gen_neon_movl_T0_scratch(2);
4876 tcg_gen_mov_i32(tmp
, cpu_T
[0]);
4878 tmp
= neon_load_reg(rn
, pass
);
4881 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
4885 neon_load_reg64(cpu_V1
, rm
+ pass
);
4888 if (pass
== 1 && rd
== rm
) {
4889 gen_neon_movl_T0_scratch(2);
4891 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
4893 tmp2
= neon_load_reg(rm
, pass
);
4896 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
4900 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
4901 gen_neon_addl(size
);
4903 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHL, VRSUBHL */
4904 gen_neon_subl(size
);
4906 case 5: case 7: /* VABAL, VABDL */
4907 switch ((size
<< 1) | u
) {
4909 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
4912 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
4915 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
4918 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
4921 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
4924 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
4931 case 8: case 9: case 10: case 11: case 12: case 13:
4932 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
4933 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
4935 case 14: /* Polynomial VMULL */
4936 cpu_abort(env
, "Polynomial VMULL not implemented");
4938 default: /* 15 is RESERVED. */
4941 if (op
== 5 || op
== 13 || (op
>= 8 && op
<= 11)) {
4943 if (op
== 10 || op
== 11) {
4944 gen_neon_negl(cpu_V0
, size
);
4948 neon_load_reg64(cpu_V1
, rd
+ pass
);
4952 case 5: case 8: case 10: /* VABAL, VMLAL, VMLSL */
4953 gen_neon_addl(size
);
4955 case 9: case 11: /* VQDMLAL, VQDMLSL */
4956 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4957 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
4960 case 13: /* VQDMULL */
4961 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
4966 neon_store_reg64(cpu_V0
, rd
+ pass
);
4967 } else if (op
== 4 || op
== 6) {
4968 /* Narrowing operation. */
4973 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
4976 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
4979 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4980 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
4987 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
4990 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
4993 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
4994 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
4995 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5003 neon_store_reg(rd
, 0, tmp3
);
5004 neon_store_reg(rd
, 1, tmp
);
5007 /* Write back the result. */
5008 neon_store_reg64(cpu_V0
, rd
+ pass
);
5012 /* Two registers and a scalar. */
5014 case 0: /* Integer VMLA scalar */
5015 case 1: /* Float VMLA scalar */
5016 case 4: /* Integer VMLS scalar */
5017 case 5: /* Floating point VMLS scalar */
5018 case 8: /* Integer VMUL scalar */
5019 case 9: /* Floating point VMUL scalar */
5020 case 12: /* VQDMULH scalar */
5021 case 13: /* VQRDMULH scalar */
5022 gen_neon_get_scalar(size
, rm
);
5023 gen_neon_movl_scratch_T0(0);
5024 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5026 gen_neon_movl_T0_scratch(0);
5027 NEON_GET_REG(T1
, rn
, pass
);
5030 gen_helper_neon_qdmulh_s16(CPU_T0E01
);
5032 gen_helper_neon_qdmulh_s32(CPU_T0E01
);
5034 } else if (op
== 13) {
5036 gen_helper_neon_qrdmulh_s16(CPU_T0E01
);
5038 gen_helper_neon_qrdmulh_s32(CPU_T0E01
);
5040 } else if (op
& 1) {
5041 gen_helper_neon_mul_f32(CPU_T001
);
5044 case 0: gen_helper_neon_mul_u8(CPU_T001
); break;
5045 case 1: gen_helper_neon_mul_u16(CPU_T001
); break;
5046 case 2: gen_op_mul_T0_T1(); break;
5052 NEON_GET_REG(T1
, rd
, pass
);
5058 gen_helper_neon_add_f32(CPU_T001
);
5064 gen_helper_neon_sub_f32(cpu_T
[0], cpu_T
[1], cpu_T
[0]);
5070 NEON_SET_REG(T0
, rd
, pass
);
5073 case 2: /* VMLAL sclar */
5074 case 3: /* VQDMLAL scalar */
5075 case 6: /* VMLSL scalar */
5076 case 7: /* VQDMLSL scalar */
5077 case 10: /* VMULL scalar */
5078 case 11: /* VQDMULL scalar */
5079 if (size
== 0 && (op
== 3 || op
== 7 || op
== 11))
5082 gen_neon_get_scalar(size
, rm
);
5083 NEON_GET_REG(T1
, rn
, 1);
5085 for (pass
= 0; pass
< 2; pass
++) {
5087 tmp
= neon_load_reg(rn
, 0);
5090 tcg_gen_mov_i32(tmp
, cpu_T
[1]);
5093 tcg_gen_mov_i32(tmp2
, cpu_T
[0]);
5094 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5095 if (op
== 6 || op
== 7) {
5096 gen_neon_negl(cpu_V0
, size
);
5099 neon_load_reg64(cpu_V1
, rd
+ pass
);
5103 gen_neon_addl(size
);
5106 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5107 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5113 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5118 neon_store_reg64(cpu_V0
, rd
+ pass
);
5121 default: /* 14 and 15 are RESERVED */
5125 } else { /* size == 3 */
5128 imm
= (insn
>> 8) & 0xf;
5135 neon_load_reg64(cpu_V0
, rn
);
5137 neon_load_reg64(cpu_V1
, rn
+ 1);
5139 } else if (imm
== 8) {
5140 neon_load_reg64(cpu_V0
, rn
+ 1);
5142 neon_load_reg64(cpu_V1
, rm
);
5145 tmp64
= tcg_temp_new_i64();
5147 neon_load_reg64(cpu_V0
, rn
);
5148 neon_load_reg64(tmp64
, rn
+ 1);
5150 neon_load_reg64(cpu_V0
, rn
+ 1);
5151 neon_load_reg64(tmp64
, rm
);
5153 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5154 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5155 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5157 neon_load_reg64(cpu_V1
, rm
);
5159 neon_load_reg64(cpu_V1
, rm
+ 1);
5162 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5163 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5164 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5167 neon_load_reg64(cpu_V0
, rn
);
5168 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5169 neon_load_reg64(cpu_V1
, rm
);
5170 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5171 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5173 neon_store_reg64(cpu_V0
, rd
);
5175 neon_store_reg64(cpu_V1
, rd
+ 1);
5177 } else if ((insn
& (1 << 11)) == 0) {
5178 /* Two register misc. */
5179 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5180 size
= (insn
>> 18) & 3;
5182 case 0: /* VREV64 */
5185 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5186 NEON_GET_REG(T0
, rm
, pass
* 2);
5187 NEON_GET_REG(T1
, rm
, pass
* 2 + 1);
5189 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5190 case 1: gen_swap_half(cpu_T
[0]); break;
5191 case 2: /* no-op */ break;
5194 NEON_SET_REG(T0
, rd
, pass
* 2 + 1);
5196 NEON_SET_REG(T1
, rd
, pass
* 2);
5198 gen_op_movl_T0_T1();
5200 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5201 case 1: gen_swap_half(cpu_T
[0]); break;
5204 NEON_SET_REG(T0
, rd
, pass
* 2);
5208 case 4: case 5: /* VPADDL */
5209 case 12: case 13: /* VPADAL */
5212 for (pass
= 0; pass
< q
+ 1; pass
++) {
5213 tmp
= neon_load_reg(rm
, pass
* 2);
5214 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5215 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5216 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5218 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5219 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5220 case 2: tcg_gen_add_i64(CPU_V001
); break;
5225 neon_load_reg64(cpu_V1
, rd
+ pass
);
5226 gen_neon_addl(size
);
5228 neon_store_reg64(cpu_V0
, rd
+ pass
);
5233 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5234 NEON_GET_REG(T0
, rm
, n
);
5235 NEON_GET_REG(T1
, rd
, n
+ 1);
5236 NEON_SET_REG(T1
, rm
, n
);
5237 NEON_SET_REG(T0
, rd
, n
+ 1);
5245 Rd A3 A2 A1 A0 B2 B0 A2 A0
5246 Rm B3 B2 B1 B0 B3 B1 A3 A1
5250 gen_neon_unzip(rd
, q
, 0, size
);
5251 gen_neon_unzip(rm
, q
, 4, size
);
5253 static int unzip_order_q
[8] =
5254 {0, 2, 4, 6, 1, 3, 5, 7};
5255 for (n
= 0; n
< 8; n
++) {
5256 int reg
= (n
< 4) ? rd
: rm
;
5257 gen_neon_movl_T0_scratch(unzip_order_q
[n
]);
5258 NEON_SET_REG(T0
, reg
, n
% 4);
5261 static int unzip_order
[4] =
5263 for (n
= 0; n
< 4; n
++) {
5264 int reg
= (n
< 2) ? rd
: rm
;
5265 gen_neon_movl_T0_scratch(unzip_order
[n
]);
5266 NEON_SET_REG(T0
, reg
, n
% 2);
5272 Rd A3 A2 A1 A0 B1 A1 B0 A0
5273 Rm B3 B2 B1 B0 B3 A3 B2 A2
5277 count
= (q
? 4 : 2);
5278 for (n
= 0; n
< count
; n
++) {
5279 NEON_GET_REG(T0
, rd
, n
);
5280 NEON_GET_REG(T1
, rd
, n
);
5282 case 0: gen_helper_neon_zip_u8(); break;
5283 case 1: gen_helper_neon_zip_u16(); break;
5284 case 2: /* no-op */; break;
5287 gen_neon_movl_scratch_T0(n
* 2);
5288 gen_neon_movl_scratch_T1(n
* 2 + 1);
5290 for (n
= 0; n
< count
* 2; n
++) {
5291 int reg
= (n
< count
) ? rd
: rm
;
5292 gen_neon_movl_T0_scratch(n
);
5293 NEON_SET_REG(T0
, reg
, n
% count
);
5296 case 36: case 37: /* VMOVN, VQMOVUN, VQMOVN */
5300 for (pass
= 0; pass
< 2; pass
++) {
5301 neon_load_reg64(cpu_V0
, rm
+ pass
);
5303 if (op
== 36 && q
== 0) {
5304 gen_neon_narrow(size
, tmp
, cpu_V0
);
5306 gen_neon_narrow_satu(size
, tmp
, cpu_V0
);
5308 gen_neon_narrow_sats(size
, tmp
, cpu_V0
);
5313 neon_store_reg(rd
, 0, tmp2
);
5314 neon_store_reg(rd
, 1, tmp
);
5318 case 38: /* VSHLL */
5321 tmp
= neon_load_reg(rm
, 0);
5322 tmp2
= neon_load_reg(rm
, 1);
5323 for (pass
= 0; pass
< 2; pass
++) {
5326 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5327 neon_store_reg64(cpu_V0
, rd
+ pass
);
5332 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5333 if (op
== 30 || op
== 31 || op
>= 58) {
5334 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5335 neon_reg_offset(rm
, pass
));
5337 NEON_GET_REG(T0
, rm
, pass
);
5340 case 1: /* VREV32 */
5342 case 0: tcg_gen_bswap32_i32(cpu_T
[0], cpu_T
[0]); break;
5343 case 1: gen_swap_half(cpu_T
[0]); break;
5347 case 2: /* VREV16 */
5350 gen_rev16(cpu_T
[0]);
5354 case 0: gen_helper_neon_cls_s8(cpu_T
[0], cpu_T
[0]); break;
5355 case 1: gen_helper_neon_cls_s16(cpu_T
[0], cpu_T
[0]); break;
5356 case 2: gen_helper_neon_cls_s32(cpu_T
[0], cpu_T
[0]); break;
5362 case 0: gen_helper_neon_clz_u8(cpu_T
[0], cpu_T
[0]); break;
5363 case 1: gen_helper_neon_clz_u16(cpu_T
[0], cpu_T
[0]); break;
5364 case 2: gen_helper_clz(cpu_T
[0], cpu_T
[0]); break;
5371 gen_helper_neon_cnt_u8(cpu_T
[0], cpu_T
[0]);
5378 case 14: /* VQABS */
5380 case 0: gen_helper_neon_qabs_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5381 case 1: gen_helper_neon_qabs_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5382 case 2: gen_helper_neon_qabs_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5386 case 15: /* VQNEG */
5388 case 0: gen_helper_neon_qneg_s8(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5389 case 1: gen_helper_neon_qneg_s16(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5390 case 2: gen_helper_neon_qneg_s32(cpu_T
[0], cpu_env
, cpu_T
[0]); break;
5394 case 16: case 19: /* VCGT #0, VCLE #0 */
5395 gen_op_movl_T1_im(0);
5397 case 0: gen_helper_neon_cgt_s8(CPU_T001
); break;
5398 case 1: gen_helper_neon_cgt_s16(CPU_T001
); break;
5399 case 2: gen_helper_neon_cgt_s32(CPU_T001
); break;
5405 case 17: case 20: /* VCGE #0, VCLT #0 */
5406 gen_op_movl_T1_im(0);
5408 case 0: gen_helper_neon_cge_s8(CPU_T001
); break;
5409 case 1: gen_helper_neon_cge_s16(CPU_T001
); break;
5410 case 2: gen_helper_neon_cge_s32(CPU_T001
); break;
5416 case 18: /* VCEQ #0 */
5417 gen_op_movl_T1_im(0);
5419 case 0: gen_helper_neon_ceq_u8(CPU_T001
); break;
5420 case 1: gen_helper_neon_ceq_u16(CPU_T001
); break;
5421 case 2: gen_helper_neon_ceq_u32(CPU_T001
); break;
5427 case 0: gen_helper_neon_abs_s8(cpu_T
[0], cpu_T
[0]); break;
5428 case 1: gen_helper_neon_abs_s16(cpu_T
[0], cpu_T
[0]); break;
5429 case 2: tcg_gen_abs_i32(cpu_T
[0], cpu_T
[0]); break;
5434 gen_op_movl_T1_im(0);
5439 case 24: case 27: /* Float VCGT #0, Float VCLE #0 */
5440 gen_op_movl_T1_im(0);
5441 gen_helper_neon_cgt_f32(CPU_T001
);
5445 case 25: case 28: /* Float VCGE #0, Float VCLT #0 */
5446 gen_op_movl_T1_im(0);
5447 gen_helper_neon_cge_f32(CPU_T001
);
5451 case 26: /* Float VCEQ #0 */
5452 gen_op_movl_T1_im(0);
5453 gen_helper_neon_ceq_f32(CPU_T001
);
5455 case 30: /* Float VABS */
5458 case 31: /* Float VNEG */
5462 NEON_GET_REG(T1
, rd
, pass
);
5463 NEON_SET_REG(T1
, rm
, pass
);
5466 NEON_GET_REG(T1
, rd
, pass
);
5468 case 0: gen_helper_neon_trn_u8(); break;
5469 case 1: gen_helper_neon_trn_u16(); break;
5473 NEON_SET_REG(T1
, rm
, pass
);
5475 case 56: /* Integer VRECPE */
5476 gen_helper_recpe_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5478 case 57: /* Integer VRSQRTE */
5479 gen_helper_rsqrte_u32(cpu_T
[0], cpu_T
[0], cpu_env
);
5481 case 58: /* Float VRECPE */
5482 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5484 case 59: /* Float VRSQRTE */
5485 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
5487 case 60: /* VCVT.F32.S32 */
5490 case 61: /* VCVT.F32.U32 */
5493 case 62: /* VCVT.S32.F32 */
5496 case 63: /* VCVT.U32.F32 */
5500 /* Reserved: 21, 29, 39-56 */
5503 if (op
== 30 || op
== 31 || op
>= 58) {
5504 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
5505 neon_reg_offset(rd
, pass
));
5507 NEON_SET_REG(T0
, rd
, pass
);
5512 } else if ((insn
& (1 << 10)) == 0) {
5514 n
= ((insn
>> 5) & 0x18) + 8;
5515 if (insn
& (1 << 6)) {
5516 tmp
= neon_load_reg(rd
, 0);
5519 tcg_gen_movi_i32(tmp
, 0);
5521 tmp2
= neon_load_reg(rm
, 0);
5522 gen_helper_neon_tbl(tmp2
, tmp2
, tmp
, tcg_const_i32(rn
),
5525 if (insn
& (1 << 6)) {
5526 tmp
= neon_load_reg(rd
, 1);
5529 tcg_gen_movi_i32(tmp
, 0);
5531 tmp3
= neon_load_reg(rm
, 1);
5532 gen_helper_neon_tbl(tmp3
, tmp3
, tmp
, tcg_const_i32(rn
),
5534 neon_store_reg(rd
, 0, tmp2
);
5535 neon_store_reg(rd
, 1, tmp3
);
5537 } else if ((insn
& 0x380) == 0) {
5539 if (insn
& (1 << 19)) {
5540 NEON_SET_REG(T0
, rm
, 1);
5542 NEON_SET_REG(T0
, rm
, 0);
5544 if (insn
& (1 << 16)) {
5545 gen_neon_dup_u8(cpu_T
[0], ((insn
>> 17) & 3) * 8);
5546 } else if (insn
& (1 << 17)) {
5547 if ((insn
>> 18) & 1)
5548 gen_neon_dup_high16(cpu_T
[0]);
5550 gen_neon_dup_low16(cpu_T
[0]);
5552 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5553 NEON_SET_REG(T0
, rd
, pass
);
5563 static int disas_cp14_read(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5565 int crn
= (insn
>> 16) & 0xf;
5566 int crm
= insn
& 0xf;
5567 int op1
= (insn
>> 21) & 7;
5568 int op2
= (insn
>> 5) & 7;
5569 int rt
= (insn
>> 12) & 0xf;
5572 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5573 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5577 tmp
= load_cpu_field(teecr
);
5578 store_reg(s
, rt
, tmp
);
5581 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5583 if (IS_USER(s
) && (env
->teecr
& 1))
5585 tmp
= load_cpu_field(teehbr
);
5586 store_reg(s
, rt
, tmp
);
5590 fprintf(stderr
, "Unknown cp14 read op1:%d crn:%d crm:%d op2:%d\n",
5591 op1
, crn
, crm
, op2
);
5595 static int disas_cp14_write(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5597 int crn
= (insn
>> 16) & 0xf;
5598 int crm
= insn
& 0xf;
5599 int op1
= (insn
>> 21) & 7;
5600 int op2
= (insn
>> 5) & 7;
5601 int rt
= (insn
>> 12) & 0xf;
5604 if (arm_feature(env
, ARM_FEATURE_THUMB2EE
)) {
5605 if (op1
== 6 && crn
== 0 && crm
== 0 && op2
== 0) {
5609 tmp
= load_reg(s
, rt
);
5610 gen_helper_set_teecr(cpu_env
, tmp
);
5614 if (op1
== 6 && crn
== 1 && crm
== 0 && op2
== 0) {
5616 if (IS_USER(s
) && (env
->teecr
& 1))
5618 tmp
= load_reg(s
, rt
);
5619 store_cpu_field(tmp
, teehbr
);
5623 fprintf(stderr
, "Unknown cp14 write op1:%d crn:%d crm:%d op2:%d\n",
5624 op1
, crn
, crm
, op2
);
5628 static int disas_coproc_insn(CPUState
* env
, DisasContext
*s
, uint32_t insn
)
5632 cpnum
= (insn
>> 8) & 0xf;
5633 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
5634 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
5640 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5641 return disas_iwmmxt_insn(env
, s
, insn
);
5642 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
5643 return disas_dsp_insn(env
, s
, insn
);
5648 return disas_vfp_insn (env
, s
, insn
);
5650 /* Coprocessors 7-15 are architecturally reserved by ARM.
5651 Unfortunately Intel decided to ignore this. */
5652 if (arm_feature(env
, ARM_FEATURE_XSCALE
))
5654 if (insn
& (1 << 20))
5655 return disas_cp14_read(env
, s
, insn
);
5657 return disas_cp14_write(env
, s
, insn
);
5659 return disas_cp15_insn (env
, s
, insn
);
5662 /* Unknown coprocessor. See if the board has hooked it. */
5663 return disas_cp_insn (env
, s
, insn
);
5668 /* Store a 64-bit value to a register pair. Clobbers val. */
5669 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
5673 tcg_gen_trunc_i64_i32(tmp
, val
);
5674 store_reg(s
, rlow
, tmp
);
5676 tcg_gen_shri_i64(val
, val
, 32);
5677 tcg_gen_trunc_i64_i32(tmp
, val
);
5678 store_reg(s
, rhigh
, tmp
);
5681 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
5682 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
5687 /* Load value and extend to 64 bits. */
5688 tmp
= tcg_temp_new_i64();
5689 tmp2
= load_reg(s
, rlow
);
5690 tcg_gen_extu_i32_i64(tmp
, tmp2
);
5692 tcg_gen_add_i64(val
, val
, tmp
);
5695 /* load and add a 64-bit value from a register pair. */
5696 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
5702 /* Load 64-bit value rd:rn. */
5703 tmpl
= load_reg(s
, rlow
);
5704 tmph
= load_reg(s
, rhigh
);
5705 tmp
= tcg_temp_new_i64();
5706 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
5709 tcg_gen_add_i64(val
, val
, tmp
);
5712 /* Set N and Z flags from a 64-bit value. */
5713 static void gen_logicq_cc(TCGv_i64 val
)
5715 TCGv tmp
= new_tmp();
5716 gen_helper_logicq_cc(tmp
, val
);
5721 static void disas_arm_insn(CPUState
* env
, DisasContext
*s
)
5723 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
5730 insn
= ldl_code(s
->pc
);
5733 /* M variants do not implement ARM mode. */
5738 /* Unconditional instructions. */
5739 if (((insn
>> 25) & 7) == 1) {
5740 /* NEON Data processing. */
5741 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5744 if (disas_neon_data_insn(env
, s
, insn
))
5748 if ((insn
& 0x0f100000) == 0x04000000) {
5749 /* NEON load/store. */
5750 if (!arm_feature(env
, ARM_FEATURE_NEON
))
5753 if (disas_neon_ls_insn(env
, s
, insn
))
5757 if ((insn
& 0x0d70f000) == 0x0550f000)
5759 else if ((insn
& 0x0ffffdff) == 0x01010000) {
5762 if (insn
& (1 << 9)) {
5763 /* BE8 mode not implemented. */
5767 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
5768 switch ((insn
>> 4) & 0xf) {
5771 gen_helper_clrex(cpu_env
);
5777 /* We don't emulate caches so these are a no-op. */
5782 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
5788 op1
= (insn
& 0x1f);
5789 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5790 addr
= load_reg(s
, 13);
5793 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op1
));
5795 i
= (insn
>> 23) & 3;
5797 case 0: offset
= -4; break; /* DA */
5798 case 1: offset
= -8; break; /* DB */
5799 case 2: offset
= 0; break; /* IA */
5800 case 3: offset
= 4; break; /* IB */
5804 tcg_gen_addi_i32(addr
, addr
, offset
);
5805 tmp
= load_reg(s
, 14);
5806 gen_st32(tmp
, addr
, 0);
5808 gen_helper_cpsr_read(tmp
);
5809 tcg_gen_addi_i32(addr
, addr
, 4);
5810 gen_st32(tmp
, addr
, 0);
5811 if (insn
& (1 << 21)) {
5812 /* Base writeback. */
5814 case 0: offset
= -8; break;
5815 case 1: offset
= -4; break;
5816 case 2: offset
= 4; break;
5817 case 3: offset
= 0; break;
5821 tcg_gen_addi_i32(addr
, tmp
, offset
);
5822 if (op1
== (env
->uncached_cpsr
& CPSR_M
)) {
5823 gen_movl_reg_T1(s
, 13);
5825 gen_helper_set_r13_banked(cpu_env
, tcg_const_i32(op1
), cpu_T
[1]);
5830 } else if ((insn
& 0x0e5fffe0) == 0x081d0a00) {
5836 rn
= (insn
>> 16) & 0xf;
5837 addr
= load_reg(s
, rn
);
5838 i
= (insn
>> 23) & 3;
5840 case 0: offset
= -4; break; /* DA */
5841 case 1: offset
= -8; break; /* DB */
5842 case 2: offset
= 0; break; /* IA */
5843 case 3: offset
= 4; break; /* IB */
5847 tcg_gen_addi_i32(addr
, addr
, offset
);
5848 /* Load PC into tmp and CPSR into tmp2. */
5849 tmp
= gen_ld32(addr
, 0);
5850 tcg_gen_addi_i32(addr
, addr
, 4);
5851 tmp2
= gen_ld32(addr
, 0);
5852 if (insn
& (1 << 21)) {
5853 /* Base writeback. */
5855 case 0: offset
= -8; break;
5856 case 1: offset
= -4; break;
5857 case 2: offset
= 4; break;
5858 case 3: offset
= 0; break;
5862 tcg_gen_addi_i32(addr
, addr
, offset
);
5863 store_reg(s
, rn
, addr
);
5867 gen_rfe(s
, tmp
, tmp2
);
5868 } else if ((insn
& 0x0e000000) == 0x0a000000) {
5869 /* branch link and change to thumb (blx <offset>) */
5872 val
= (uint32_t)s
->pc
;
5874 tcg_gen_movi_i32(tmp
, val
);
5875 store_reg(s
, 14, tmp
);
5876 /* Sign-extend the 24-bit offset */
5877 offset
= (((int32_t)insn
) << 8) >> 8;
5878 /* offset * 4 + bit24 * 2 + (thumb bit) */
5879 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
5880 /* pipeline offset */
5884 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
5885 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
5886 /* iWMMXt register transfer. */
5887 if (env
->cp15
.c15_cpar
& (1 << 1))
5888 if (!disas_iwmmxt_insn(env
, s
, insn
))
5891 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
5892 /* Coprocessor double register transfer. */
5893 } else if ((insn
& 0x0f000010) == 0x0e000010) {
5894 /* Additional coprocessor register transfer. */
5895 } else if ((insn
& 0x0ff10020) == 0x01000000) {
5898 /* cps (privileged) */
5902 if (insn
& (1 << 19)) {
5903 if (insn
& (1 << 8))
5905 if (insn
& (1 << 7))
5907 if (insn
& (1 << 6))
5909 if (insn
& (1 << 18))
5912 if (insn
& (1 << 17)) {
5914 val
|= (insn
& 0x1f);
5917 gen_op_movl_T0_im(val
);
5918 gen_set_psr_T0(s
, mask
, 0);
5925 /* if not always execute, we generate a conditional jump to
5927 s
->condlabel
= gen_new_label();
5928 gen_test_cc(cond
^ 1, s
->condlabel
);
5931 if ((insn
& 0x0f900000) == 0x03000000) {
5932 if ((insn
& (1 << 21)) == 0) {
5934 rd
= (insn
>> 12) & 0xf;
5935 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
5936 if ((insn
& (1 << 22)) == 0) {
5939 tcg_gen_movi_i32(tmp
, val
);
5942 tmp
= load_reg(s
, rd
);
5943 tcg_gen_ext16u_i32(tmp
, tmp
);
5944 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
5946 store_reg(s
, rd
, tmp
);
5948 if (((insn
>> 12) & 0xf) != 0xf)
5950 if (((insn
>> 16) & 0xf) == 0) {
5951 gen_nop_hint(s
, insn
& 0xff);
5953 /* CPSR = immediate */
5955 shift
= ((insn
>> 8) & 0xf) * 2;
5957 val
= (val
>> shift
) | (val
<< (32 - shift
));
5958 gen_op_movl_T0_im(val
);
5959 i
= ((insn
& (1 << 22)) != 0);
5960 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5964 } else if ((insn
& 0x0f900000) == 0x01000000
5965 && (insn
& 0x00000090) != 0x00000090) {
5966 /* miscellaneous instructions */
5967 op1
= (insn
>> 21) & 3;
5968 sh
= (insn
>> 4) & 0xf;
5971 case 0x0: /* move program status register */
5974 gen_movl_T0_reg(s
, rm
);
5975 i
= ((op1
& 2) != 0);
5976 if (gen_set_psr_T0(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
))
5980 rd
= (insn
>> 12) & 0xf;
5984 tmp
= load_cpu_field(spsr
);
5987 gen_helper_cpsr_read(tmp
);
5989 store_reg(s
, rd
, tmp
);
5994 /* branch/exchange thumb (bx). */
5995 tmp
= load_reg(s
, rm
);
5997 } else if (op1
== 3) {
5999 rd
= (insn
>> 12) & 0xf;
6000 tmp
= load_reg(s
, rm
);
6001 gen_helper_clz(tmp
, tmp
);
6002 store_reg(s
, rd
, tmp
);
6010 /* Trivial implementation equivalent to bx. */
6011 tmp
= load_reg(s
, rm
);
6021 /* branch link/exchange thumb (blx) */
6022 tmp
= load_reg(s
, rm
);
6024 tcg_gen_movi_i32(tmp2
, s
->pc
);
6025 store_reg(s
, 14, tmp2
);
6028 case 0x5: /* saturating add/subtract */
6029 rd
= (insn
>> 12) & 0xf;
6030 rn
= (insn
>> 16) & 0xf;
6031 tmp
= load_reg(s
, rm
);
6032 tmp2
= load_reg(s
, rn
);
6034 gen_helper_double_saturate(tmp2
, tmp2
);
6036 gen_helper_sub_saturate(tmp
, tmp
, tmp2
);
6038 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
6040 store_reg(s
, rd
, tmp
);
6043 gen_set_condexec(s
);
6044 gen_set_pc_im(s
->pc
- 4);
6045 gen_exception(EXCP_BKPT
);
6046 s
->is_jmp
= DISAS_JUMP
;
6048 case 0x8: /* signed multiply */
6052 rs
= (insn
>> 8) & 0xf;
6053 rn
= (insn
>> 12) & 0xf;
6054 rd
= (insn
>> 16) & 0xf;
6056 /* (32 * 16) >> 16 */
6057 tmp
= load_reg(s
, rm
);
6058 tmp2
= load_reg(s
, rs
);
6060 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6063 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6064 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6066 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6067 if ((sh
& 2) == 0) {
6068 tmp2
= load_reg(s
, rn
);
6069 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6072 store_reg(s
, rd
, tmp
);
6075 tmp
= load_reg(s
, rm
);
6076 tmp2
= load_reg(s
, rs
);
6077 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6080 tmp64
= tcg_temp_new_i64();
6081 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6083 gen_addq(s
, tmp64
, rn
, rd
);
6084 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6087 tmp2
= load_reg(s
, rn
);
6088 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6091 store_reg(s
, rd
, tmp
);
6098 } else if (((insn
& 0x0e000000) == 0 &&
6099 (insn
& 0x00000090) != 0x90) ||
6100 ((insn
& 0x0e000000) == (1 << 25))) {
6101 int set_cc
, logic_cc
, shiftop
;
6103 op1
= (insn
>> 21) & 0xf;
6104 set_cc
= (insn
>> 20) & 1;
6105 logic_cc
= table_logic_cc
[op1
] & set_cc
;
6107 /* data processing instruction */
6108 if (insn
& (1 << 25)) {
6109 /* immediate operand */
6111 shift
= ((insn
>> 8) & 0xf) * 2;
6113 val
= (val
>> shift
) | (val
<< (32 - shift
));
6116 tcg_gen_movi_i32(tmp2
, val
);
6117 if (logic_cc
&& shift
) {
6118 gen_set_CF_bit31(tmp2
);
6123 tmp2
= load_reg(s
, rm
);
6124 shiftop
= (insn
>> 5) & 3;
6125 if (!(insn
& (1 << 4))) {
6126 shift
= (insn
>> 7) & 0x1f;
6127 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
6129 rs
= (insn
>> 8) & 0xf;
6130 tmp
= load_reg(s
, rs
);
6131 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
6134 if (op1
!= 0x0f && op1
!= 0x0d) {
6135 rn
= (insn
>> 16) & 0xf;
6136 tmp
= load_reg(s
, rn
);
6140 rd
= (insn
>> 12) & 0xf;
6143 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6147 store_reg_bx(env
, s
, rd
, tmp
);
6150 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6154 store_reg_bx(env
, s
, rd
, tmp
);
6157 if (set_cc
&& rd
== 15) {
6158 /* SUBS r15, ... is used for exception return. */
6162 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6163 gen_exception_return(s
, tmp
);
6166 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6168 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6170 store_reg_bx(env
, s
, rd
, tmp
);
6175 gen_helper_sub_cc(tmp
, tmp2
, tmp
);
6177 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6179 store_reg_bx(env
, s
, rd
, tmp
);
6183 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6185 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6187 store_reg_bx(env
, s
, rd
, tmp
);
6191 gen_helper_adc_cc(tmp
, tmp
, tmp2
);
6193 gen_add_carry(tmp
, tmp
, tmp2
);
6195 store_reg_bx(env
, s
, rd
, tmp
);
6199 gen_helper_sbc_cc(tmp
, tmp
, tmp2
);
6201 gen_sub_carry(tmp
, tmp
, tmp2
);
6203 store_reg_bx(env
, s
, rd
, tmp
);
6207 gen_helper_sbc_cc(tmp
, tmp2
, tmp
);
6209 gen_sub_carry(tmp
, tmp2
, tmp
);
6211 store_reg_bx(env
, s
, rd
, tmp
);
6215 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
6222 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
6229 gen_helper_sub_cc(tmp
, tmp
, tmp2
);
6235 gen_helper_add_cc(tmp
, tmp
, tmp2
);
6240 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6244 store_reg_bx(env
, s
, rd
, tmp
);
6247 if (logic_cc
&& rd
== 15) {
6248 /* MOVS r15, ... is used for exception return. */
6252 gen_exception_return(s
, tmp2
);
6257 store_reg_bx(env
, s
, rd
, tmp2
);
6261 tcg_gen_bic_i32(tmp
, tmp
, tmp2
);
6265 store_reg_bx(env
, s
, rd
, tmp
);
6269 tcg_gen_not_i32(tmp2
, tmp2
);
6273 store_reg_bx(env
, s
, rd
, tmp2
);
6276 if (op1
!= 0x0f && op1
!= 0x0d) {
6280 /* other instructions */
6281 op1
= (insn
>> 24) & 0xf;
6285 /* multiplies, extra load/stores */
6286 sh
= (insn
>> 5) & 3;
6289 rd
= (insn
>> 16) & 0xf;
6290 rn
= (insn
>> 12) & 0xf;
6291 rs
= (insn
>> 8) & 0xf;
6293 op1
= (insn
>> 20) & 0xf;
6295 case 0: case 1: case 2: case 3: case 6:
6297 tmp
= load_reg(s
, rs
);
6298 tmp2
= load_reg(s
, rm
);
6299 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
6301 if (insn
& (1 << 22)) {
6302 /* Subtract (mls) */
6304 tmp2
= load_reg(s
, rn
);
6305 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
6307 } else if (insn
& (1 << 21)) {
6309 tmp2
= load_reg(s
, rn
);
6310 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6313 if (insn
& (1 << 20))
6315 store_reg(s
, rd
, tmp
);
6319 tmp
= load_reg(s
, rs
);
6320 tmp2
= load_reg(s
, rm
);
6321 if (insn
& (1 << 22))
6322 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6324 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
6325 if (insn
& (1 << 21)) /* mult accumulate */
6326 gen_addq(s
, tmp64
, rn
, rd
);
6327 if (!(insn
& (1 << 23))) { /* double accumulate */
6329 gen_addq_lo(s
, tmp64
, rn
);
6330 gen_addq_lo(s
, tmp64
, rd
);
6332 if (insn
& (1 << 20))
6333 gen_logicq_cc(tmp64
);
6334 gen_storeq_reg(s
, rn
, rd
, tmp64
);
6338 rn
= (insn
>> 16) & 0xf;
6339 rd
= (insn
>> 12) & 0xf;
6340 if (insn
& (1 << 23)) {
6341 /* load/store exclusive */
6342 op1
= (insn
>> 21) & 0x3;
6347 gen_movl_T1_reg(s
, rn
);
6349 if (insn
& (1 << 20)) {
6350 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
6353 tmp
= gen_ld32(addr
, IS_USER(s
));
6355 case 1: /* ldrexd */
6356 tmp
= gen_ld32(addr
, IS_USER(s
));
6357 store_reg(s
, rd
, tmp
);
6358 tcg_gen_addi_i32(addr
, addr
, 4);
6359 tmp
= gen_ld32(addr
, IS_USER(s
));
6362 case 2: /* ldrexb */
6363 tmp
= gen_ld8u(addr
, IS_USER(s
));
6365 case 3: /* ldrexh */
6366 tmp
= gen_ld16u(addr
, IS_USER(s
));
6371 store_reg(s
, rd
, tmp
);
6373 int label
= gen_new_label();
6375 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
6376 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
6378 tmp
= load_reg(s
,rm
);
6381 gen_st32(tmp
, addr
, IS_USER(s
));
6383 case 1: /* strexd */
6384 gen_st32(tmp
, addr
, IS_USER(s
));
6385 tcg_gen_addi_i32(addr
, addr
, 4);
6386 tmp
= load_reg(s
, rm
+ 1);
6387 gen_st32(tmp
, addr
, IS_USER(s
));
6389 case 2: /* strexb */
6390 gen_st8(tmp
, addr
, IS_USER(s
));
6392 case 3: /* strexh */
6393 gen_st16(tmp
, addr
, IS_USER(s
));
6398 gen_set_label(label
);
6399 gen_movl_reg_T0(s
, rd
);
6402 /* SWP instruction */
6405 /* ??? This is not really atomic. However we know
6406 we never have multiple CPUs running in parallel,
6407 so it is good enough. */
6408 addr
= load_reg(s
, rn
);
6409 tmp
= load_reg(s
, rm
);
6410 if (insn
& (1 << 22)) {
6411 tmp2
= gen_ld8u(addr
, IS_USER(s
));
6412 gen_st8(tmp
, addr
, IS_USER(s
));
6414 tmp2
= gen_ld32(addr
, IS_USER(s
));
6415 gen_st32(tmp
, addr
, IS_USER(s
));
6418 store_reg(s
, rd
, tmp2
);
6424 /* Misc load/store */
6425 rn
= (insn
>> 16) & 0xf;
6426 rd
= (insn
>> 12) & 0xf;
6427 addr
= load_reg(s
, rn
);
6428 if (insn
& (1 << 24))
6429 gen_add_datah_offset(s
, insn
, 0, addr
);
6431 if (insn
& (1 << 20)) {
6435 tmp
= gen_ld16u(addr
, IS_USER(s
));
6438 tmp
= gen_ld8s(addr
, IS_USER(s
));
6442 tmp
= gen_ld16s(addr
, IS_USER(s
));
6446 } else if (sh
& 2) {
6450 tmp
= load_reg(s
, rd
);
6451 gen_st32(tmp
, addr
, IS_USER(s
));
6452 tcg_gen_addi_i32(addr
, addr
, 4);
6453 tmp
= load_reg(s
, rd
+ 1);
6454 gen_st32(tmp
, addr
, IS_USER(s
));
6458 tmp
= gen_ld32(addr
, IS_USER(s
));
6459 store_reg(s
, rd
, tmp
);
6460 tcg_gen_addi_i32(addr
, addr
, 4);
6461 tmp
= gen_ld32(addr
, IS_USER(s
));
6465 address_offset
= -4;
6468 tmp
= load_reg(s
, rd
);
6469 gen_st16(tmp
, addr
, IS_USER(s
));
6472 /* Perform base writeback before the loaded value to
6473 ensure correct behavior with overlapping index registers.
6474 ldrd with base writeback is is undefined if the
6475 destination and index registers overlap. */
6476 if (!(insn
& (1 << 24))) {
6477 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
6478 store_reg(s
, rn
, addr
);
6479 } else if (insn
& (1 << 21)) {
6481 tcg_gen_addi_i32(addr
, addr
, address_offset
);
6482 store_reg(s
, rn
, addr
);
6487 /* Complete the load. */
6488 store_reg(s
, rd
, tmp
);
6497 if (insn
& (1 << 4)) {
6499 /* Armv6 Media instructions. */
6501 rn
= (insn
>> 16) & 0xf;
6502 rd
= (insn
>> 12) & 0xf;
6503 rs
= (insn
>> 8) & 0xf;
6504 switch ((insn
>> 23) & 3) {
6505 case 0: /* Parallel add/subtract. */
6506 op1
= (insn
>> 20) & 7;
6507 tmp
= load_reg(s
, rn
);
6508 tmp2
= load_reg(s
, rm
);
6509 sh
= (insn
>> 5) & 7;
6510 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
6512 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
6514 store_reg(s
, rd
, tmp
);
6517 if ((insn
& 0x00700020) == 0) {
6518 /* Halfword pack. */
6519 tmp
= load_reg(s
, rn
);
6520 tmp2
= load_reg(s
, rm
);
6521 shift
= (insn
>> 7) & 0x1f;
6522 if (insn
& (1 << 6)) {
6526 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
6527 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
6528 tcg_gen_ext16u_i32(tmp2
, tmp2
);
6532 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
6533 tcg_gen_ext16u_i32(tmp
, tmp
);
6534 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
6536 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
6538 store_reg(s
, rd
, tmp
);
6539 } else if ((insn
& 0x00200020) == 0x00200000) {
6541 tmp
= load_reg(s
, rm
);
6542 shift
= (insn
>> 7) & 0x1f;
6543 if (insn
& (1 << 6)) {
6546 tcg_gen_sari_i32(tmp
, tmp
, shift
);
6548 tcg_gen_shli_i32(tmp
, tmp
, shift
);
6550 sh
= (insn
>> 16) & 0x1f;
6552 if (insn
& (1 << 22))
6553 gen_helper_usat(tmp
, tmp
, tcg_const_i32(sh
));
6555 gen_helper_ssat(tmp
, tmp
, tcg_const_i32(sh
));
6557 store_reg(s
, rd
, tmp
);
6558 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
6560 tmp
= load_reg(s
, rm
);
6561 sh
= (insn
>> 16) & 0x1f;
6563 if (insn
& (1 << 22))
6564 gen_helper_usat16(tmp
, tmp
, tcg_const_i32(sh
));
6566 gen_helper_ssat16(tmp
, tmp
, tcg_const_i32(sh
));
6568 store_reg(s
, rd
, tmp
);
6569 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
6571 tmp
= load_reg(s
, rn
);
6572 tmp2
= load_reg(s
, rm
);
6574 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
6575 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
6578 store_reg(s
, rd
, tmp
);
6579 } else if ((insn
& 0x000003e0) == 0x00000060) {
6580 tmp
= load_reg(s
, rm
);
6581 shift
= (insn
>> 10) & 3;
6582 /* ??? In many cases it's not neccessary to do a
6583 rotate, a shift is sufficient. */
6585 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
6586 op1
= (insn
>> 20) & 7;
6588 case 0: gen_sxtb16(tmp
); break;
6589 case 2: gen_sxtb(tmp
); break;
6590 case 3: gen_sxth(tmp
); break;
6591 case 4: gen_uxtb16(tmp
); break;
6592 case 6: gen_uxtb(tmp
); break;
6593 case 7: gen_uxth(tmp
); break;
6594 default: goto illegal_op
;
6597 tmp2
= load_reg(s
, rn
);
6598 if ((op1
& 3) == 0) {
6599 gen_add16(tmp
, tmp2
);
6601 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6605 store_reg(s
, rd
, tmp
);
6606 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
6608 tmp
= load_reg(s
, rm
);
6609 if (insn
& (1 << 22)) {
6610 if (insn
& (1 << 7)) {
6614 gen_helper_rbit(tmp
, tmp
);
6617 if (insn
& (1 << 7))
6620 tcg_gen_bswap32_i32(tmp
, tmp
);
6622 store_reg(s
, rd
, tmp
);
6627 case 2: /* Multiplies (Type 3). */
6628 tmp
= load_reg(s
, rm
);
6629 tmp2
= load_reg(s
, rs
);
6630 if (insn
& (1 << 20)) {
6631 /* Signed multiply most significant [accumulate]. */
6632 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6633 if (insn
& (1 << 5))
6634 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
6635 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6637 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6639 tmp2
= load_reg(s
, rd
);
6640 if (insn
& (1 << 6)) {
6641 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6643 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6647 store_reg(s
, rn
, tmp
);
6649 if (insn
& (1 << 5))
6650 gen_swap_half(tmp2
);
6651 gen_smul_dual(tmp
, tmp2
);
6652 /* This addition cannot overflow. */
6653 if (insn
& (1 << 6)) {
6654 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
6656 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6659 if (insn
& (1 << 22)) {
6660 /* smlald, smlsld */
6661 tmp64
= tcg_temp_new_i64();
6662 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6664 gen_addq(s
, tmp64
, rd
, rn
);
6665 gen_storeq_reg(s
, rd
, rn
, tmp64
);
6667 /* smuad, smusd, smlad, smlsd */
6670 tmp2
= load_reg(s
, rd
);
6671 gen_helper_add_setq(tmp
, tmp
, tmp2
);
6674 store_reg(s
, rn
, tmp
);
6679 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
6681 case 0: /* Unsigned sum of absolute differences. */
6683 tmp
= load_reg(s
, rm
);
6684 tmp2
= load_reg(s
, rs
);
6685 gen_helper_usad8(tmp
, tmp
, tmp2
);
6688 tmp2
= load_reg(s
, rd
);
6689 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
6692 store_reg(s
, rn
, tmp
);
6694 case 0x20: case 0x24: case 0x28: case 0x2c:
6695 /* Bitfield insert/clear. */
6697 shift
= (insn
>> 7) & 0x1f;
6698 i
= (insn
>> 16) & 0x1f;
6702 tcg_gen_movi_i32(tmp
, 0);
6704 tmp
= load_reg(s
, rm
);
6707 tmp2
= load_reg(s
, rd
);
6708 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << i
) - 1);
6711 store_reg(s
, rd
, tmp
);
6713 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
6714 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
6716 tmp
= load_reg(s
, rm
);
6717 shift
= (insn
>> 7) & 0x1f;
6718 i
= ((insn
>> 16) & 0x1f) + 1;
6723 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
6725 gen_sbfx(tmp
, shift
, i
);
6728 store_reg(s
, rd
, tmp
);
6738 /* Check for undefined extension instructions
6739 * per the ARM Bible IE:
6740 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
6742 sh
= (0xf << 20) | (0xf << 4);
6743 if (op1
== 0x7 && ((insn
& sh
) == sh
))
6747 /* load/store byte/word */
6748 rn
= (insn
>> 16) & 0xf;
6749 rd
= (insn
>> 12) & 0xf;
6750 tmp2
= load_reg(s
, rn
);
6751 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
6752 if (insn
& (1 << 24))
6753 gen_add_data_offset(s
, insn
, tmp2
);
6754 if (insn
& (1 << 20)) {
6756 if (insn
& (1 << 22)) {
6757 tmp
= gen_ld8u(tmp2
, i
);
6759 tmp
= gen_ld32(tmp2
, i
);
6763 tmp
= load_reg(s
, rd
);
6764 if (insn
& (1 << 22))
6765 gen_st8(tmp
, tmp2
, i
);
6767 gen_st32(tmp
, tmp2
, i
);
6769 if (!(insn
& (1 << 24))) {
6770 gen_add_data_offset(s
, insn
, tmp2
);
6771 store_reg(s
, rn
, tmp2
);
6772 } else if (insn
& (1 << 21)) {
6773 store_reg(s
, rn
, tmp2
);
6777 if (insn
& (1 << 20)) {
6778 /* Complete the load. */
6782 store_reg(s
, rd
, tmp
);
6788 int j
, n
, user
, loaded_base
;
6790 /* load/store multiple words */
6791 /* XXX: store correct base if write back */
6793 if (insn
& (1 << 22)) {
6795 goto illegal_op
; /* only usable in supervisor mode */
6797 if ((insn
& (1 << 15)) == 0)
6800 rn
= (insn
>> 16) & 0xf;
6801 addr
= load_reg(s
, rn
);
6803 /* compute total size */
6805 TCGV_UNUSED(loaded_var
);
6808 if (insn
& (1 << i
))
6811 /* XXX: test invalid n == 0 case ? */
6812 if (insn
& (1 << 23)) {
6813 if (insn
& (1 << 24)) {
6815 tcg_gen_addi_i32(addr
, addr
, 4);
6817 /* post increment */
6820 if (insn
& (1 << 24)) {
6822 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6824 /* post decrement */
6826 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6831 if (insn
& (1 << i
)) {
6832 if (insn
& (1 << 20)) {
6834 tmp
= gen_ld32(addr
, IS_USER(s
));
6838 gen_helper_set_user_reg(tcg_const_i32(i
), tmp
);
6840 } else if (i
== rn
) {
6844 store_reg(s
, i
, tmp
);
6849 /* special case: r15 = PC + 8 */
6850 val
= (long)s
->pc
+ 4;
6852 tcg_gen_movi_i32(tmp
, val
);
6855 gen_helper_get_user_reg(tmp
, tcg_const_i32(i
));
6857 tmp
= load_reg(s
, i
);
6859 gen_st32(tmp
, addr
, IS_USER(s
));
6862 /* no need to add after the last transfer */
6864 tcg_gen_addi_i32(addr
, addr
, 4);
6867 if (insn
& (1 << 21)) {
6869 if (insn
& (1 << 23)) {
6870 if (insn
& (1 << 24)) {
6873 /* post increment */
6874 tcg_gen_addi_i32(addr
, addr
, 4);
6877 if (insn
& (1 << 24)) {
6880 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
6882 /* post decrement */
6883 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
6886 store_reg(s
, rn
, addr
);
6891 store_reg(s
, rn
, loaded_var
);
6893 if ((insn
& (1 << 22)) && !user
) {
6894 /* Restore CPSR from SPSR. */
6895 tmp
= load_cpu_field(spsr
);
6896 gen_set_cpsr(tmp
, 0xffffffff);
6898 s
->is_jmp
= DISAS_UPDATE
;
6907 /* branch (and link) */
6908 val
= (int32_t)s
->pc
;
6909 if (insn
& (1 << 24)) {
6911 tcg_gen_movi_i32(tmp
, val
);
6912 store_reg(s
, 14, tmp
);
6914 offset
= (((int32_t)insn
<< 8) >> 8);
6915 val
+= (offset
<< 2) + 4;
6923 if (disas_coproc_insn(env
, s
, insn
))
6928 gen_set_pc_im(s
->pc
);
6929 s
->is_jmp
= DISAS_SWI
;
6933 gen_set_condexec(s
);
6934 gen_set_pc_im(s
->pc
- 4);
6935 gen_exception(EXCP_UDEF
);
6936 s
->is_jmp
= DISAS_JUMP
;
6942 /* Return true if this is a Thumb-2 logical op. */
6944 thumb2_logic_op(int op
)
6949 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
6950 then set condition code flags based on the result of the operation.
6951 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
6952 to the high bit of T1.
6953 Returns zero if the opcode is valid. */
6956 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
)
6963 gen_op_andl_T0_T1();
6967 gen_op_bicl_T0_T1();
6980 gen_op_xorl_T0_T1();
6985 gen_op_addl_T0_T1_cc();
6987 gen_op_addl_T0_T1();
6991 gen_op_adcl_T0_T1_cc();
6997 gen_op_sbcl_T0_T1_cc();
7003 gen_op_subl_T0_T1_cc();
7005 gen_op_subl_T0_T1();
7009 gen_op_rsbl_T0_T1_cc();
7011 gen_op_rsbl_T0_T1();
7013 default: /* 5, 6, 7, 9, 12, 15. */
7017 gen_op_logic_T0_cc();
7019 gen_set_CF_bit31(cpu_T
[1]);
7024 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7026 static int disas_thumb2_insn(CPUState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
7028 uint32_t insn
, imm
, shift
, offset
;
7029 uint32_t rd
, rn
, rm
, rs
;
7040 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
7041 || arm_feature (env
, ARM_FEATURE_M
))) {
7042 /* Thumb-1 cores may need to treat bl and blx as a pair of
7043 16-bit instructions to get correct prefetch abort behavior. */
7045 if ((insn
& (1 << 12)) == 0) {
7046 /* Second half of blx. */
7047 offset
= ((insn
& 0x7ff) << 1);
7048 tmp
= load_reg(s
, 14);
7049 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7050 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
7053 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7054 store_reg(s
, 14, tmp2
);
7058 if (insn
& (1 << 11)) {
7059 /* Second half of bl. */
7060 offset
= ((insn
& 0x7ff) << 1) | 1;
7061 tmp
= load_reg(s
, 14);
7062 tcg_gen_addi_i32(tmp
, tmp
, offset
);
7065 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
7066 store_reg(s
, 14, tmp2
);
7070 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
7071 /* Instruction spans a page boundary. Implement it as two
7072 16-bit instructions in case the second half causes an
7074 offset
= ((int32_t)insn
<< 21) >> 9;
7075 gen_op_movl_T0_im(s
->pc
+ 2 + offset
);
7076 gen_movl_reg_T0(s
, 14);
7079 /* Fall through to 32-bit decode. */
7082 insn
= lduw_code(s
->pc
);
7084 insn
|= (uint32_t)insn_hw1
<< 16;
7086 if ((insn
& 0xf800e800) != 0xf000e800) {
7090 rn
= (insn
>> 16) & 0xf;
7091 rs
= (insn
>> 12) & 0xf;
7092 rd
= (insn
>> 8) & 0xf;
7094 switch ((insn
>> 25) & 0xf) {
7095 case 0: case 1: case 2: case 3:
7096 /* 16-bit instructions. Should never happen. */
7099 if (insn
& (1 << 22)) {
7100 /* Other load/store, table branch. */
7101 if (insn
& 0x01200000) {
7102 /* Load/store doubleword. */
7105 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
7107 addr
= load_reg(s
, rn
);
7109 offset
= (insn
& 0xff) * 4;
7110 if ((insn
& (1 << 23)) == 0)
7112 if (insn
& (1 << 24)) {
7113 tcg_gen_addi_i32(addr
, addr
, offset
);
7116 if (insn
& (1 << 20)) {
7118 tmp
= gen_ld32(addr
, IS_USER(s
));
7119 store_reg(s
, rs
, tmp
);
7120 tcg_gen_addi_i32(addr
, addr
, 4);
7121 tmp
= gen_ld32(addr
, IS_USER(s
));
7122 store_reg(s
, rd
, tmp
);
7125 tmp
= load_reg(s
, rs
);
7126 gen_st32(tmp
, addr
, IS_USER(s
));
7127 tcg_gen_addi_i32(addr
, addr
, 4);
7128 tmp
= load_reg(s
, rd
);
7129 gen_st32(tmp
, addr
, IS_USER(s
));
7131 if (insn
& (1 << 21)) {
7132 /* Base writeback. */
7135 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
7136 store_reg(s
, rn
, addr
);
7140 } else if ((insn
& (1 << 23)) == 0) {
7141 /* Load/store exclusive word. */
7142 gen_movl_T1_reg(s
, rn
);
7144 if (insn
& (1 << 20)) {
7145 gen_helper_mark_exclusive(cpu_env
, cpu_T
[1]);
7146 tmp
= gen_ld32(addr
, IS_USER(s
));
7147 store_reg(s
, rd
, tmp
);
7149 int label
= gen_new_label();
7150 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7151 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0],
7153 tmp
= load_reg(s
, rs
);
7154 gen_st32(tmp
, cpu_T
[1], IS_USER(s
));
7155 gen_set_label(label
);
7156 gen_movl_reg_T0(s
, rd
);
7158 } else if ((insn
& (1 << 6)) == 0) {
7162 tcg_gen_movi_i32(addr
, s
->pc
);
7164 addr
= load_reg(s
, rn
);
7166 tmp
= load_reg(s
, rm
);
7167 tcg_gen_add_i32(addr
, addr
, tmp
);
7168 if (insn
& (1 << 4)) {
7170 tcg_gen_add_i32(addr
, addr
, tmp
);
7172 tmp
= gen_ld16u(addr
, IS_USER(s
));
7175 tmp
= gen_ld8u(addr
, IS_USER(s
));
7178 tcg_gen_shli_i32(tmp
, tmp
, 1);
7179 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
7180 store_reg(s
, 15, tmp
);
7182 /* Load/store exclusive byte/halfword/doubleword. */
7183 /* ??? These are not really atomic. However we know
7184 we never have multiple CPUs running in parallel,
7185 so it is good enough. */
7186 op
= (insn
>> 4) & 0x3;
7187 /* Must use a global reg for the address because we have
7188 a conditional branch in the store instruction. */
7189 gen_movl_T1_reg(s
, rn
);
7191 if (insn
& (1 << 20)) {
7192 gen_helper_mark_exclusive(cpu_env
, addr
);
7195 tmp
= gen_ld8u(addr
, IS_USER(s
));
7198 tmp
= gen_ld16u(addr
, IS_USER(s
));
7201 tmp
= gen_ld32(addr
, IS_USER(s
));
7202 tcg_gen_addi_i32(addr
, addr
, 4);
7203 tmp2
= gen_ld32(addr
, IS_USER(s
));
7204 store_reg(s
, rd
, tmp2
);
7209 store_reg(s
, rs
, tmp
);
7211 int label
= gen_new_label();
7212 /* Must use a global that is not killed by the branch. */
7213 gen_helper_test_exclusive(cpu_T
[0], cpu_env
, addr
);
7214 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_T
[0], 0, label
);
7215 tmp
= load_reg(s
, rs
);
7218 gen_st8(tmp
, addr
, IS_USER(s
));
7221 gen_st16(tmp
, addr
, IS_USER(s
));
7224 gen_st32(tmp
, addr
, IS_USER(s
));
7225 tcg_gen_addi_i32(addr
, addr
, 4);
7226 tmp
= load_reg(s
, rd
);
7227 gen_st32(tmp
, addr
, IS_USER(s
));
7232 gen_set_label(label
);
7233 gen_movl_reg_T0(s
, rm
);
7237 /* Load/store multiple, RFE, SRS. */
7238 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
7239 /* Not available in user mode. */
7242 if (insn
& (1 << 20)) {
7244 addr
= load_reg(s
, rn
);
7245 if ((insn
& (1 << 24)) == 0)
7246 tcg_gen_addi_i32(addr
, addr
, -8);
7247 /* Load PC into tmp and CPSR into tmp2. */
7248 tmp
= gen_ld32(addr
, 0);
7249 tcg_gen_addi_i32(addr
, addr
, 4);
7250 tmp2
= gen_ld32(addr
, 0);
7251 if (insn
& (1 << 21)) {
7252 /* Base writeback. */
7253 if (insn
& (1 << 24)) {
7254 tcg_gen_addi_i32(addr
, addr
, 4);
7256 tcg_gen_addi_i32(addr
, addr
, -4);
7258 store_reg(s
, rn
, addr
);
7262 gen_rfe(s
, tmp
, tmp2
);
7266 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7267 addr
= load_reg(s
, 13);
7270 gen_helper_get_r13_banked(addr
, cpu_env
, tcg_const_i32(op
));
7272 if ((insn
& (1 << 24)) == 0) {
7273 tcg_gen_addi_i32(addr
, addr
, -8);
7275 tmp
= load_reg(s
, 14);
7276 gen_st32(tmp
, addr
, 0);
7277 tcg_gen_addi_i32(addr
, addr
, 4);
7279 gen_helper_cpsr_read(tmp
);
7280 gen_st32(tmp
, addr
, 0);
7281 if (insn
& (1 << 21)) {
7282 if ((insn
& (1 << 24)) == 0) {
7283 tcg_gen_addi_i32(addr
, addr
, -4);
7285 tcg_gen_addi_i32(addr
, addr
, 4);
7287 if (op
== (env
->uncached_cpsr
& CPSR_M
)) {
7288 store_reg(s
, 13, addr
);
7290 gen_helper_set_r13_banked(cpu_env
,
7291 tcg_const_i32(op
), addr
);
7299 /* Load/store multiple. */
7300 addr
= load_reg(s
, rn
);
7302 for (i
= 0; i
< 16; i
++) {
7303 if (insn
& (1 << i
))
7306 if (insn
& (1 << 24)) {
7307 tcg_gen_addi_i32(addr
, addr
, -offset
);
7310 for (i
= 0; i
< 16; i
++) {
7311 if ((insn
& (1 << i
)) == 0)
7313 if (insn
& (1 << 20)) {
7315 tmp
= gen_ld32(addr
, IS_USER(s
));
7319 store_reg(s
, i
, tmp
);
7323 tmp
= load_reg(s
, i
);
7324 gen_st32(tmp
, addr
, IS_USER(s
));
7326 tcg_gen_addi_i32(addr
, addr
, 4);
7328 if (insn
& (1 << 21)) {
7329 /* Base register writeback. */
7330 if (insn
& (1 << 24)) {
7331 tcg_gen_addi_i32(addr
, addr
, -offset
);
7333 /* Fault if writeback register is in register list. */
7334 if (insn
& (1 << rn
))
7336 store_reg(s
, rn
, addr
);
7343 case 5: /* Data processing register constant shift. */
7345 gen_op_movl_T0_im(0);
7347 gen_movl_T0_reg(s
, rn
);
7348 gen_movl_T1_reg(s
, rm
);
7349 op
= (insn
>> 21) & 0xf;
7350 shiftop
= (insn
>> 4) & 3;
7351 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7352 conds
= (insn
& (1 << 20)) != 0;
7353 logic_cc
= (conds
&& thumb2_logic_op(op
));
7354 gen_arm_shift_im(cpu_T
[1], shiftop
, shift
, logic_cc
);
7355 if (gen_thumb2_data_op(s
, op
, conds
, 0))
7358 gen_movl_reg_T0(s
, rd
);
7360 case 13: /* Misc data processing. */
7361 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
7362 if (op
< 4 && (insn
& 0xf000) != 0xf000)
7365 case 0: /* Register controlled shift. */
7366 tmp
= load_reg(s
, rn
);
7367 tmp2
= load_reg(s
, rm
);
7368 if ((insn
& 0x70) != 0)
7370 op
= (insn
>> 21) & 3;
7371 logic_cc
= (insn
& (1 << 20)) != 0;
7372 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
7375 store_reg_bx(env
, s
, rd
, tmp
);
7377 case 1: /* Sign/zero extend. */
7378 tmp
= load_reg(s
, rm
);
7379 shift
= (insn
>> 4) & 3;
7380 /* ??? In many cases it's not neccessary to do a
7381 rotate, a shift is sufficient. */
7383 tcg_gen_rori_i32(tmp
, tmp
, shift
* 8);
7384 op
= (insn
>> 20) & 7;
7386 case 0: gen_sxth(tmp
); break;
7387 case 1: gen_uxth(tmp
); break;
7388 case 2: gen_sxtb16(tmp
); break;
7389 case 3: gen_uxtb16(tmp
); break;
7390 case 4: gen_sxtb(tmp
); break;
7391 case 5: gen_uxtb(tmp
); break;
7392 default: goto illegal_op
;
7395 tmp2
= load_reg(s
, rn
);
7396 if ((op
>> 1) == 1) {
7397 gen_add16(tmp
, tmp2
);
7399 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7403 store_reg(s
, rd
, tmp
);
7405 case 2: /* SIMD add/subtract. */
7406 op
= (insn
>> 20) & 7;
7407 shift
= (insn
>> 4) & 7;
7408 if ((op
& 3) == 3 || (shift
& 3) == 3)
7410 tmp
= load_reg(s
, rn
);
7411 tmp2
= load_reg(s
, rm
);
7412 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
7414 store_reg(s
, rd
, tmp
);
7416 case 3: /* Other data processing. */
7417 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
7419 /* Saturating add/subtract. */
7420 tmp
= load_reg(s
, rn
);
7421 tmp2
= load_reg(s
, rm
);
7423 gen_helper_double_saturate(tmp
, tmp
);
7425 gen_helper_sub_saturate(tmp
, tmp2
, tmp
);
7427 gen_helper_add_saturate(tmp
, tmp
, tmp2
);
7430 tmp
= load_reg(s
, rn
);
7432 case 0x0a: /* rbit */
7433 gen_helper_rbit(tmp
, tmp
);
7435 case 0x08: /* rev */
7436 tcg_gen_bswap32_i32(tmp
, tmp
);
7438 case 0x09: /* rev16 */
7441 case 0x0b: /* revsh */
7444 case 0x10: /* sel */
7445 tmp2
= load_reg(s
, rm
);
7447 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUState
, GE
));
7448 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7452 case 0x18: /* clz */
7453 gen_helper_clz(tmp
, tmp
);
7459 store_reg(s
, rd
, tmp
);
7461 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
7462 op
= (insn
>> 4) & 0xf;
7463 tmp
= load_reg(s
, rn
);
7464 tmp2
= load_reg(s
, rm
);
7465 switch ((insn
>> 20) & 7) {
7466 case 0: /* 32 x 32 -> 32 */
7467 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7470 tmp2
= load_reg(s
, rs
);
7472 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7474 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7478 case 1: /* 16 x 16 -> 32 */
7479 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7482 tmp2
= load_reg(s
, rs
);
7483 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7487 case 2: /* Dual multiply add. */
7488 case 4: /* Dual multiply subtract. */
7490 gen_swap_half(tmp2
);
7491 gen_smul_dual(tmp
, tmp2
);
7492 /* This addition cannot overflow. */
7493 if (insn
& (1 << 22)) {
7494 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7496 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7501 tmp2
= load_reg(s
, rs
);
7502 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7506 case 3: /* 32 * 16 -> 32msb */
7508 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7511 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7512 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7514 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7517 tmp2
= load_reg(s
, rs
);
7518 gen_helper_add_setq(tmp
, tmp
, tmp2
);
7522 case 5: case 6: /* 32 * 32 -> 32msb */
7523 gen_imull(tmp
, tmp2
);
7524 if (insn
& (1 << 5)) {
7525 gen_roundqd(tmp
, tmp2
);
7532 tmp2
= load_reg(s
, rs
);
7533 if (insn
& (1 << 21)) {
7534 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7536 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7541 case 7: /* Unsigned sum of absolute differences. */
7542 gen_helper_usad8(tmp
, tmp
, tmp2
);
7545 tmp2
= load_reg(s
, rs
);
7546 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7551 store_reg(s
, rd
, tmp
);
7553 case 6: case 7: /* 64-bit multiply, Divide. */
7554 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
7555 tmp
= load_reg(s
, rn
);
7556 tmp2
= load_reg(s
, rm
);
7557 if ((op
& 0x50) == 0x10) {
7559 if (!arm_feature(env
, ARM_FEATURE_DIV
))
7562 gen_helper_udiv(tmp
, tmp
, tmp2
);
7564 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7566 store_reg(s
, rd
, tmp
);
7567 } else if ((op
& 0xe) == 0xc) {
7568 /* Dual multiply accumulate long. */
7570 gen_swap_half(tmp2
);
7571 gen_smul_dual(tmp
, tmp2
);
7573 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7575 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7579 tmp64
= tcg_temp_new_i64();
7580 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7582 gen_addq(s
, tmp64
, rs
, rd
);
7583 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7586 /* Unsigned 64-bit multiply */
7587 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7591 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
7593 tmp64
= tcg_temp_new_i64();
7594 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7597 /* Signed 64-bit multiply */
7598 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7603 gen_addq_lo(s
, tmp64
, rs
);
7604 gen_addq_lo(s
, tmp64
, rd
);
7605 } else if (op
& 0x40) {
7606 /* 64-bit accumulate. */
7607 gen_addq(s
, tmp64
, rs
, rd
);
7609 gen_storeq_reg(s
, rs
, rd
, tmp64
);
7614 case 6: case 7: case 14: case 15:
7616 if (((insn
>> 24) & 3) == 3) {
7617 /* Translate into the equivalent ARM encoding. */
7618 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4);
7619 if (disas_neon_data_insn(env
, s
, insn
))
7622 if (insn
& (1 << 28))
7624 if (disas_coproc_insn (env
, s
, insn
))
7628 case 8: case 9: case 10: case 11:
7629 if (insn
& (1 << 15)) {
7630 /* Branches, misc control. */
7631 if (insn
& 0x5000) {
7632 /* Unconditional branch. */
7633 /* signextend(hw1[10:0]) -> offset[:12]. */
7634 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
7635 /* hw1[10:0] -> offset[11:1]. */
7636 offset
|= (insn
& 0x7ff) << 1;
7637 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
7638 offset[24:22] already have the same value because of the
7639 sign extension above. */
7640 offset
^= ((~insn
) & (1 << 13)) << 10;
7641 offset
^= ((~insn
) & (1 << 11)) << 11;
7643 if (insn
& (1 << 14)) {
7644 /* Branch and link. */
7645 gen_op_movl_T1_im(s
->pc
| 1);
7646 gen_movl_reg_T1(s
, 14);
7650 if (insn
& (1 << 12)) {
7655 offset
&= ~(uint32_t)2;
7656 gen_bx_im(s
, offset
);
7658 } else if (((insn
>> 23) & 7) == 7) {
7660 if (insn
& (1 << 13))
7663 if (insn
& (1 << 26)) {
7664 /* Secure monitor call (v6Z) */
7665 goto illegal_op
; /* not implemented. */
7667 op
= (insn
>> 20) & 7;
7669 case 0: /* msr cpsr. */
7671 tmp
= load_reg(s
, rn
);
7672 addr
= tcg_const_i32(insn
& 0xff);
7673 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
7678 case 1: /* msr spsr. */
7681 gen_movl_T0_reg(s
, rn
);
7682 if (gen_set_psr_T0(s
,
7683 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
7687 case 2: /* cps, nop-hint. */
7688 if (((insn
>> 8) & 7) == 0) {
7689 gen_nop_hint(s
, insn
& 0xff);
7691 /* Implemented as NOP in user mode. */
7696 if (insn
& (1 << 10)) {
7697 if (insn
& (1 << 7))
7699 if (insn
& (1 << 6))
7701 if (insn
& (1 << 5))
7703 if (insn
& (1 << 9))
7704 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
7706 if (insn
& (1 << 8)) {
7708 imm
|= (insn
& 0x1f);
7711 gen_op_movl_T0_im(imm
);
7712 gen_set_psr_T0(s
, offset
, 0);
7715 case 3: /* Special control operations. */
7716 op
= (insn
>> 4) & 0xf;
7719 gen_helper_clrex(cpu_env
);
7724 /* These execute as NOPs. */
7732 /* Trivial implementation equivalent to bx. */
7733 tmp
= load_reg(s
, rn
);
7736 case 5: /* Exception return. */
7737 /* Unpredictable in user mode. */
7739 case 6: /* mrs cpsr. */
7742 addr
= tcg_const_i32(insn
& 0xff);
7743 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
7745 gen_helper_cpsr_read(tmp
);
7747 store_reg(s
, rd
, tmp
);
7749 case 7: /* mrs spsr. */
7750 /* Not accessible in user mode. */
7751 if (IS_USER(s
) || IS_M(env
))
7753 tmp
= load_cpu_field(spsr
);
7754 store_reg(s
, rd
, tmp
);
7759 /* Conditional branch. */
7760 op
= (insn
>> 22) & 0xf;
7761 /* Generate a conditional jump to next instruction. */
7762 s
->condlabel
= gen_new_label();
7763 gen_test_cc(op
^ 1, s
->condlabel
);
7766 /* offset[11:1] = insn[10:0] */
7767 offset
= (insn
& 0x7ff) << 1;
7768 /* offset[17:12] = insn[21:16]. */
7769 offset
|= (insn
& 0x003f0000) >> 4;
7770 /* offset[31:20] = insn[26]. */
7771 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
7772 /* offset[18] = insn[13]. */
7773 offset
|= (insn
& (1 << 13)) << 5;
7774 /* offset[19] = insn[11]. */
7775 offset
|= (insn
& (1 << 11)) << 8;
7777 /* jump to the offset */
7778 gen_jmp(s
, s
->pc
+ offset
);
7781 /* Data processing immediate. */
7782 if (insn
& (1 << 25)) {
7783 if (insn
& (1 << 24)) {
7784 if (insn
& (1 << 20))
7786 /* Bitfield/Saturate. */
7787 op
= (insn
>> 21) & 7;
7789 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
7792 tcg_gen_movi_i32(tmp
, 0);
7794 tmp
= load_reg(s
, rn
);
7797 case 2: /* Signed bitfield extract. */
7799 if (shift
+ imm
> 32)
7802 gen_sbfx(tmp
, shift
, imm
);
7804 case 6: /* Unsigned bitfield extract. */
7806 if (shift
+ imm
> 32)
7809 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
7811 case 3: /* Bitfield insert/clear. */
7814 imm
= imm
+ 1 - shift
;
7816 tmp2
= load_reg(s
, rd
);
7817 gen_bfi(tmp
, tmp2
, tmp
, shift
, (1u << imm
) - 1);
7823 default: /* Saturate. */
7826 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7828 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7830 tmp2
= tcg_const_i32(imm
);
7833 if ((op
& 1) && shift
== 0)
7834 gen_helper_usat16(tmp
, tmp
, tmp2
);
7836 gen_helper_usat(tmp
, tmp
, tmp2
);
7839 if ((op
& 1) && shift
== 0)
7840 gen_helper_ssat16(tmp
, tmp
, tmp2
);
7842 gen_helper_ssat(tmp
, tmp
, tmp2
);
7846 store_reg(s
, rd
, tmp
);
7848 imm
= ((insn
& 0x04000000) >> 15)
7849 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
7850 if (insn
& (1 << 22)) {
7851 /* 16-bit immediate. */
7852 imm
|= (insn
>> 4) & 0xf000;
7853 if (insn
& (1 << 23)) {
7855 tmp
= load_reg(s
, rd
);
7856 tcg_gen_ext16u_i32(tmp
, tmp
);
7857 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
7861 tcg_gen_movi_i32(tmp
, imm
);
7864 /* Add/sub 12-bit immediate. */
7866 offset
= s
->pc
& ~(uint32_t)3;
7867 if (insn
& (1 << 23))
7872 tcg_gen_movi_i32(tmp
, offset
);
7874 tmp
= load_reg(s
, rn
);
7875 if (insn
& (1 << 23))
7876 tcg_gen_subi_i32(tmp
, tmp
, imm
);
7878 tcg_gen_addi_i32(tmp
, tmp
, imm
);
7881 store_reg(s
, rd
, tmp
);
7884 int shifter_out
= 0;
7885 /* modified 12-bit immediate. */
7886 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
7887 imm
= (insn
& 0xff);
7890 /* Nothing to do. */
7892 case 1: /* 00XY00XY */
7895 case 2: /* XY00XY00 */
7899 case 3: /* XYXYXYXY */
7903 default: /* Rotated constant. */
7904 shift
= (shift
<< 1) | (imm
>> 7);
7906 imm
= imm
<< (32 - shift
);
7910 gen_op_movl_T1_im(imm
);
7911 rn
= (insn
>> 16) & 0xf;
7913 gen_op_movl_T0_im(0);
7915 gen_movl_T0_reg(s
, rn
);
7916 op
= (insn
>> 21) & 0xf;
7917 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
7920 rd
= (insn
>> 8) & 0xf;
7922 gen_movl_reg_T0(s
, rd
);
7927 case 12: /* Load/store single data item. */
7932 if ((insn
& 0x01100000) == 0x01000000) {
7933 if (disas_neon_ls_insn(env
, s
, insn
))
7941 /* s->pc has already been incremented by 4. */
7942 imm
= s
->pc
& 0xfffffffc;
7943 if (insn
& (1 << 23))
7944 imm
+= insn
& 0xfff;
7946 imm
-= insn
& 0xfff;
7947 tcg_gen_movi_i32(addr
, imm
);
7949 addr
= load_reg(s
, rn
);
7950 if (insn
& (1 << 23)) {
7951 /* Positive offset. */
7953 tcg_gen_addi_i32(addr
, addr
, imm
);
7955 op
= (insn
>> 8) & 7;
7958 case 0: case 8: /* Shifted Register. */
7959 shift
= (insn
>> 4) & 0xf;
7962 tmp
= load_reg(s
, rm
);
7964 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7965 tcg_gen_add_i32(addr
, addr
, tmp
);
7968 case 4: /* Negative offset. */
7969 tcg_gen_addi_i32(addr
, addr
, -imm
);
7971 case 6: /* User privilege. */
7972 tcg_gen_addi_i32(addr
, addr
, imm
);
7975 case 1: /* Post-decrement. */
7978 case 3: /* Post-increment. */
7982 case 5: /* Pre-decrement. */
7985 case 7: /* Pre-increment. */
7986 tcg_gen_addi_i32(addr
, addr
, imm
);
7994 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
7995 if (insn
& (1 << 20)) {
7997 if (rs
== 15 && op
!= 2) {
8000 /* Memory hint. Implemented as NOP. */
8003 case 0: tmp
= gen_ld8u(addr
, user
); break;
8004 case 4: tmp
= gen_ld8s(addr
, user
); break;
8005 case 1: tmp
= gen_ld16u(addr
, user
); break;
8006 case 5: tmp
= gen_ld16s(addr
, user
); break;
8007 case 2: tmp
= gen_ld32(addr
, user
); break;
8008 default: goto illegal_op
;
8013 store_reg(s
, rs
, tmp
);
8020 tmp
= load_reg(s
, rs
);
8022 case 0: gen_st8(tmp
, addr
, user
); break;
8023 case 1: gen_st16(tmp
, addr
, user
); break;
8024 case 2: gen_st32(tmp
, addr
, user
); break;
8025 default: goto illegal_op
;
8029 tcg_gen_addi_i32(addr
, addr
, imm
);
8031 store_reg(s
, rn
, addr
);
8045 static void disas_thumb_insn(CPUState
*env
, DisasContext
*s
)
8047 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
8054 if (s
->condexec_mask
) {
8055 cond
= s
->condexec_cond
;
8056 s
->condlabel
= gen_new_label();
8057 gen_test_cc(cond
^ 1, s
->condlabel
);
8061 insn
= lduw_code(s
->pc
);
8064 switch (insn
>> 12) {
8067 op
= (insn
>> 11) & 3;
8070 rn
= (insn
>> 3) & 7;
8071 gen_movl_T0_reg(s
, rn
);
8072 if (insn
& (1 << 10)) {
8074 gen_op_movl_T1_im((insn
>> 6) & 7);
8077 rm
= (insn
>> 6) & 7;
8078 gen_movl_T1_reg(s
, rm
);
8080 if (insn
& (1 << 9)) {
8081 if (s
->condexec_mask
)
8082 gen_op_subl_T0_T1();
8084 gen_op_subl_T0_T1_cc();
8086 if (s
->condexec_mask
)
8087 gen_op_addl_T0_T1();
8089 gen_op_addl_T0_T1_cc();
8091 gen_movl_reg_T0(s
, rd
);
8093 /* shift immediate */
8094 rm
= (insn
>> 3) & 7;
8095 shift
= (insn
>> 6) & 0x1f;
8096 tmp
= load_reg(s
, rm
);
8097 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
8098 if (!s
->condexec_mask
)
8100 store_reg(s
, rd
, tmp
);
8104 /* arithmetic large immediate */
8105 op
= (insn
>> 11) & 3;
8106 rd
= (insn
>> 8) & 0x7;
8108 gen_op_movl_T0_im(insn
& 0xff);
8110 gen_movl_T0_reg(s
, rd
);
8111 gen_op_movl_T1_im(insn
& 0xff);
8115 if (!s
->condexec_mask
)
8116 gen_op_logic_T0_cc();
8119 gen_op_subl_T0_T1_cc();
8122 if (s
->condexec_mask
)
8123 gen_op_addl_T0_T1();
8125 gen_op_addl_T0_T1_cc();
8128 if (s
->condexec_mask
)
8129 gen_op_subl_T0_T1();
8131 gen_op_subl_T0_T1_cc();
8135 gen_movl_reg_T0(s
, rd
);
8138 if (insn
& (1 << 11)) {
8139 rd
= (insn
>> 8) & 7;
8140 /* load pc-relative. Bit 1 of PC is ignored. */
8141 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
8142 val
&= ~(uint32_t)2;
8144 tcg_gen_movi_i32(addr
, val
);
8145 tmp
= gen_ld32(addr
, IS_USER(s
));
8147 store_reg(s
, rd
, tmp
);
8150 if (insn
& (1 << 10)) {
8151 /* data processing extended or blx */
8152 rd
= (insn
& 7) | ((insn
>> 4) & 8);
8153 rm
= (insn
>> 3) & 0xf;
8154 op
= (insn
>> 8) & 3;
8157 gen_movl_T0_reg(s
, rd
);
8158 gen_movl_T1_reg(s
, rm
);
8159 gen_op_addl_T0_T1();
8160 gen_movl_reg_T0(s
, rd
);
8163 gen_movl_T0_reg(s
, rd
);
8164 gen_movl_T1_reg(s
, rm
);
8165 gen_op_subl_T0_T1_cc();
8167 case 2: /* mov/cpy */
8168 gen_movl_T0_reg(s
, rm
);
8169 gen_movl_reg_T0(s
, rd
);
8171 case 3:/* branch [and link] exchange thumb register */
8172 tmp
= load_reg(s
, rm
);
8173 if (insn
& (1 << 7)) {
8174 val
= (uint32_t)s
->pc
| 1;
8176 tcg_gen_movi_i32(tmp2
, val
);
8177 store_reg(s
, 14, tmp2
);
8185 /* data processing register */
8187 rm
= (insn
>> 3) & 7;
8188 op
= (insn
>> 6) & 0xf;
8189 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
8190 /* the shift/rotate ops want the operands backwards */
8199 if (op
== 9) /* neg */
8200 gen_op_movl_T0_im(0);
8201 else if (op
!= 0xf) /* mvn doesn't read its first operand */
8202 gen_movl_T0_reg(s
, rd
);
8204 gen_movl_T1_reg(s
, rm
);
8207 gen_op_andl_T0_T1();
8208 if (!s
->condexec_mask
)
8209 gen_op_logic_T0_cc();
8212 gen_op_xorl_T0_T1();
8213 if (!s
->condexec_mask
)
8214 gen_op_logic_T0_cc();
8217 if (s
->condexec_mask
) {
8218 gen_helper_shl(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8220 gen_helper_shl_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8221 gen_op_logic_T1_cc();
8225 if (s
->condexec_mask
) {
8226 gen_helper_shr(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8228 gen_helper_shr_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8229 gen_op_logic_T1_cc();
8233 if (s
->condexec_mask
) {
8234 gen_helper_sar(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8236 gen_helper_sar_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8237 gen_op_logic_T1_cc();
8241 if (s
->condexec_mask
)
8244 gen_op_adcl_T0_T1_cc();
8247 if (s
->condexec_mask
)
8250 gen_op_sbcl_T0_T1_cc();
8253 if (s
->condexec_mask
) {
8254 gen_helper_ror(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8256 gen_helper_ror_cc(cpu_T
[1], cpu_T
[1], cpu_T
[0]);
8257 gen_op_logic_T1_cc();
8261 gen_op_andl_T0_T1();
8262 gen_op_logic_T0_cc();
8266 if (s
->condexec_mask
)
8267 tcg_gen_neg_i32(cpu_T
[0], cpu_T
[1]);
8269 gen_op_subl_T0_T1_cc();
8272 gen_op_subl_T0_T1_cc();
8276 gen_op_addl_T0_T1_cc();
8281 if (!s
->condexec_mask
)
8282 gen_op_logic_T0_cc();
8285 gen_op_mull_T0_T1();
8286 if (!s
->condexec_mask
)
8287 gen_op_logic_T0_cc();
8290 gen_op_bicl_T0_T1();
8291 if (!s
->condexec_mask
)
8292 gen_op_logic_T0_cc();
8296 if (!s
->condexec_mask
)
8297 gen_op_logic_T1_cc();
8304 gen_movl_reg_T1(s
, rm
);
8306 gen_movl_reg_T0(s
, rd
);
8311 /* load/store register offset. */
8313 rn
= (insn
>> 3) & 7;
8314 rm
= (insn
>> 6) & 7;
8315 op
= (insn
>> 9) & 7;
8316 addr
= load_reg(s
, rn
);
8317 tmp
= load_reg(s
, rm
);
8318 tcg_gen_add_i32(addr
, addr
, tmp
);
8321 if (op
< 3) /* store */
8322 tmp
= load_reg(s
, rd
);
8326 gen_st32(tmp
, addr
, IS_USER(s
));
8329 gen_st16(tmp
, addr
, IS_USER(s
));
8332 gen_st8(tmp
, addr
, IS_USER(s
));
8335 tmp
= gen_ld8s(addr
, IS_USER(s
));
8338 tmp
= gen_ld32(addr
, IS_USER(s
));
8341 tmp
= gen_ld16u(addr
, IS_USER(s
));
8344 tmp
= gen_ld8u(addr
, IS_USER(s
));
8347 tmp
= gen_ld16s(addr
, IS_USER(s
));
8350 if (op
>= 3) /* load */
8351 store_reg(s
, rd
, tmp
);
8356 /* load/store word immediate offset */
8358 rn
= (insn
>> 3) & 7;
8359 addr
= load_reg(s
, rn
);
8360 val
= (insn
>> 4) & 0x7c;
8361 tcg_gen_addi_i32(addr
, addr
, val
);
8363 if (insn
& (1 << 11)) {
8365 tmp
= gen_ld32(addr
, IS_USER(s
));
8366 store_reg(s
, rd
, tmp
);
8369 tmp
= load_reg(s
, rd
);
8370 gen_st32(tmp
, addr
, IS_USER(s
));
8376 /* load/store byte immediate offset */
8378 rn
= (insn
>> 3) & 7;
8379 addr
= load_reg(s
, rn
);
8380 val
= (insn
>> 6) & 0x1f;
8381 tcg_gen_addi_i32(addr
, addr
, val
);
8383 if (insn
& (1 << 11)) {
8385 tmp
= gen_ld8u(addr
, IS_USER(s
));
8386 store_reg(s
, rd
, tmp
);
8389 tmp
= load_reg(s
, rd
);
8390 gen_st8(tmp
, addr
, IS_USER(s
));
8396 /* load/store halfword immediate offset */
8398 rn
= (insn
>> 3) & 7;
8399 addr
= load_reg(s
, rn
);
8400 val
= (insn
>> 5) & 0x3e;
8401 tcg_gen_addi_i32(addr
, addr
, val
);
8403 if (insn
& (1 << 11)) {
8405 tmp
= gen_ld16u(addr
, IS_USER(s
));
8406 store_reg(s
, rd
, tmp
);
8409 tmp
= load_reg(s
, rd
);
8410 gen_st16(tmp
, addr
, IS_USER(s
));
8416 /* load/store from stack */
8417 rd
= (insn
>> 8) & 7;
8418 addr
= load_reg(s
, 13);
8419 val
= (insn
& 0xff) * 4;
8420 tcg_gen_addi_i32(addr
, addr
, val
);
8422 if (insn
& (1 << 11)) {
8424 tmp
= gen_ld32(addr
, IS_USER(s
));
8425 store_reg(s
, rd
, tmp
);
8428 tmp
= load_reg(s
, rd
);
8429 gen_st32(tmp
, addr
, IS_USER(s
));
8435 /* add to high reg */
8436 rd
= (insn
>> 8) & 7;
8437 if (insn
& (1 << 11)) {
8439 tmp
= load_reg(s
, 13);
8441 /* PC. bit 1 is ignored. */
8443 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
8445 val
= (insn
& 0xff) * 4;
8446 tcg_gen_addi_i32(tmp
, tmp
, val
);
8447 store_reg(s
, rd
, tmp
);
8452 op
= (insn
>> 8) & 0xf;
8455 /* adjust stack pointer */
8456 tmp
= load_reg(s
, 13);
8457 val
= (insn
& 0x7f) * 4;
8458 if (insn
& (1 << 7))
8459 val
= -(int32_t)val
;
8460 tcg_gen_addi_i32(tmp
, tmp
, val
);
8461 store_reg(s
, 13, tmp
);
8464 case 2: /* sign/zero extend. */
8467 rm
= (insn
>> 3) & 7;
8468 tmp
= load_reg(s
, rm
);
8469 switch ((insn
>> 6) & 3) {
8470 case 0: gen_sxth(tmp
); break;
8471 case 1: gen_sxtb(tmp
); break;
8472 case 2: gen_uxth(tmp
); break;
8473 case 3: gen_uxtb(tmp
); break;
8475 store_reg(s
, rd
, tmp
);
8477 case 4: case 5: case 0xc: case 0xd:
8479 addr
= load_reg(s
, 13);
8480 if (insn
& (1 << 8))
8484 for (i
= 0; i
< 8; i
++) {
8485 if (insn
& (1 << i
))
8488 if ((insn
& (1 << 11)) == 0) {
8489 tcg_gen_addi_i32(addr
, addr
, -offset
);
8491 for (i
= 0; i
< 8; i
++) {
8492 if (insn
& (1 << i
)) {
8493 if (insn
& (1 << 11)) {
8495 tmp
= gen_ld32(addr
, IS_USER(s
));
8496 store_reg(s
, i
, tmp
);
8499 tmp
= load_reg(s
, i
);
8500 gen_st32(tmp
, addr
, IS_USER(s
));
8502 /* advance to the next address. */
8503 tcg_gen_addi_i32(addr
, addr
, 4);
8507 if (insn
& (1 << 8)) {
8508 if (insn
& (1 << 11)) {
8510 tmp
= gen_ld32(addr
, IS_USER(s
));
8511 /* don't set the pc until the rest of the instruction
8515 tmp
= load_reg(s
, 14);
8516 gen_st32(tmp
, addr
, IS_USER(s
));
8518 tcg_gen_addi_i32(addr
, addr
, 4);
8520 if ((insn
& (1 << 11)) == 0) {
8521 tcg_gen_addi_i32(addr
, addr
, -offset
);
8523 /* write back the new stack pointer */
8524 store_reg(s
, 13, addr
);
8525 /* set the new PC value */
8526 if ((insn
& 0x0900) == 0x0900)
8530 case 1: case 3: case 9: case 11: /* czb */
8532 tmp
= load_reg(s
, rm
);
8533 s
->condlabel
= gen_new_label();
8535 if (insn
& (1 << 11))
8536 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
8538 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
8540 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
8541 val
= (uint32_t)s
->pc
+ 2;
8546 case 15: /* IT, nop-hint. */
8547 if ((insn
& 0xf) == 0) {
8548 gen_nop_hint(s
, (insn
>> 4) & 0xf);
8552 s
->condexec_cond
= (insn
>> 4) & 0xe;
8553 s
->condexec_mask
= insn
& 0x1f;
8554 /* No actual code generated for this insn, just setup state. */
8557 case 0xe: /* bkpt */
8558 gen_set_condexec(s
);
8559 gen_set_pc_im(s
->pc
- 2);
8560 gen_exception(EXCP_BKPT
);
8561 s
->is_jmp
= DISAS_JUMP
;
8566 rn
= (insn
>> 3) & 0x7;
8568 tmp
= load_reg(s
, rn
);
8569 switch ((insn
>> 6) & 3) {
8570 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
8571 case 1: gen_rev16(tmp
); break;
8572 case 3: gen_revsh(tmp
); break;
8573 default: goto illegal_op
;
8575 store_reg(s
, rd
, tmp
);
8583 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
8586 addr
= tcg_const_i32(16);
8587 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8591 addr
= tcg_const_i32(17);
8592 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8596 if (insn
& (1 << 4))
8597 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
8601 val
= ((insn
& 7) << 6) & shift
;
8602 gen_op_movl_T0_im(val
);
8603 gen_set_psr_T0(s
, shift
, 0);
8613 /* load/store multiple */
8614 rn
= (insn
>> 8) & 0x7;
8615 addr
= load_reg(s
, rn
);
8616 for (i
= 0; i
< 8; i
++) {
8617 if (insn
& (1 << i
)) {
8618 if (insn
& (1 << 11)) {
8620 tmp
= gen_ld32(addr
, IS_USER(s
));
8621 store_reg(s
, i
, tmp
);
8624 tmp
= load_reg(s
, i
);
8625 gen_st32(tmp
, addr
, IS_USER(s
));
8627 /* advance to the next address */
8628 tcg_gen_addi_i32(addr
, addr
, 4);
8631 /* Base register writeback. */
8632 if ((insn
& (1 << rn
)) == 0) {
8633 store_reg(s
, rn
, addr
);
8640 /* conditional branch or swi */
8641 cond
= (insn
>> 8) & 0xf;
8647 gen_set_condexec(s
);
8648 gen_set_pc_im(s
->pc
);
8649 s
->is_jmp
= DISAS_SWI
;
8652 /* generate a conditional jump to next instruction */
8653 s
->condlabel
= gen_new_label();
8654 gen_test_cc(cond
^ 1, s
->condlabel
);
8656 gen_movl_T1_reg(s
, 15);
8658 /* jump to the offset */
8659 val
= (uint32_t)s
->pc
+ 2;
8660 offset
= ((int32_t)insn
<< 24) >> 24;
8666 if (insn
& (1 << 11)) {
8667 if (disas_thumb2_insn(env
, s
, insn
))
8671 /* unconditional branch */
8672 val
= (uint32_t)s
->pc
;
8673 offset
= ((int32_t)insn
<< 21) >> 21;
8674 val
+= (offset
<< 1) + 2;
8679 if (disas_thumb2_insn(env
, s
, insn
))
8685 gen_set_condexec(s
);
8686 gen_set_pc_im(s
->pc
- 4);
8687 gen_exception(EXCP_UDEF
);
8688 s
->is_jmp
= DISAS_JUMP
;
8692 gen_set_condexec(s
);
8693 gen_set_pc_im(s
->pc
- 2);
8694 gen_exception(EXCP_UDEF
);
8695 s
->is_jmp
= DISAS_JUMP
;
8698 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
8699 basic block 'tb'. If search_pc is TRUE, also generate PC
8700 information for each intermediate instruction. */
8701 static inline void gen_intermediate_code_internal(CPUState
*env
,
8702 TranslationBlock
*tb
,
8705 DisasContext dc1
, *dc
= &dc1
;
8707 uint16_t *gen_opc_end
;
8709 target_ulong pc_start
;
8710 uint32_t next_page_start
;
8714 /* generate intermediate code */
8716 memset(temps
, 0, sizeof(temps
));
8722 gen_opc_end
= gen_opc_buf
+ OPC_MAX_SIZE
;
8724 dc
->is_jmp
= DISAS_NEXT
;
8726 dc
->singlestep_enabled
= env
->singlestep_enabled
;
8728 dc
->thumb
= env
->thumb
;
8729 dc
->condexec_mask
= (env
->condexec_bits
& 0xf) << 1;
8730 dc
->condexec_cond
= env
->condexec_bits
>> 4;
8731 #if !defined(CONFIG_USER_ONLY)
8733 dc
->user
= ((env
->v7m
.exception
== 0) && (env
->v7m
.control
& 1));
8735 dc
->user
= (env
->uncached_cpsr
& 0x1f) == ARM_CPU_MODE_USR
;
8738 cpu_F0s
= tcg_temp_new_i32();
8739 cpu_F1s
= tcg_temp_new_i32();
8740 cpu_F0d
= tcg_temp_new_i64();
8741 cpu_F1d
= tcg_temp_new_i64();
8744 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
8745 cpu_M0
= tcg_temp_new_i64();
8746 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
8749 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
8751 max_insns
= CF_COUNT_MASK
;
8754 /* Reset the conditional execution bits immediately. This avoids
8755 complications trying to do it at the end of the block. */
8756 if (env
->condexec_bits
)
8758 TCGv tmp
= new_tmp();
8759 tcg_gen_movi_i32(tmp
, 0);
8760 store_cpu_field(tmp
, condexec_bits
);
8763 #ifdef CONFIG_USER_ONLY
8764 /* Intercept jump to the magic kernel page. */
8765 if (dc
->pc
>= 0xffff0000) {
8766 /* We always get here via a jump, so know we are not in a
8767 conditional execution block. */
8768 gen_exception(EXCP_KERNEL_TRAP
);
8769 dc
->is_jmp
= DISAS_UPDATE
;
8773 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
8774 /* We always get here via a jump, so know we are not in a
8775 conditional execution block. */
8776 gen_exception(EXCP_EXCEPTION_EXIT
);
8777 dc
->is_jmp
= DISAS_UPDATE
;
8782 if (unlikely(!TAILQ_EMPTY(&env
->breakpoints
))) {
8783 TAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
8784 if (bp
->pc
== dc
->pc
) {
8785 gen_set_condexec(dc
);
8786 gen_set_pc_im(dc
->pc
);
8787 gen_exception(EXCP_DEBUG
);
8788 dc
->is_jmp
= DISAS_JUMP
;
8789 /* Advance PC so that clearing the breakpoint will
8790 invalidate this TB. */
8792 goto done_generating
;
8798 j
= gen_opc_ptr
- gen_opc_buf
;
8802 gen_opc_instr_start
[lj
++] = 0;
8804 gen_opc_pc
[lj
] = dc
->pc
;
8805 gen_opc_instr_start
[lj
] = 1;
8806 gen_opc_icount
[lj
] = num_insns
;
8809 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
8813 disas_thumb_insn(env
, dc
);
8814 if (dc
->condexec_mask
) {
8815 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
8816 | ((dc
->condexec_mask
>> 4) & 1);
8817 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
8818 if (dc
->condexec_mask
== 0) {
8819 dc
->condexec_cond
= 0;
8823 disas_arm_insn(env
, dc
);
8826 fprintf(stderr
, "Internal resource leak before %08x\n", dc
->pc
);
8830 if (dc
->condjmp
&& !dc
->is_jmp
) {
8831 gen_set_label(dc
->condlabel
);
8834 /* Translation stops when a conditional branch is encountered.
8835 * Otherwise the subsequent code could get translated several times.
8836 * Also stop translation when a page boundary is reached. This
8837 * ensures prefetch aborts occur at the right place. */
8839 } while (!dc
->is_jmp
&& gen_opc_ptr
< gen_opc_end
&&
8840 !env
->singlestep_enabled
&&
8842 dc
->pc
< next_page_start
&&
8843 num_insns
< max_insns
);
8845 if (tb
->cflags
& CF_LAST_IO
) {
8847 /* FIXME: This can theoretically happen with self-modifying
8849 cpu_abort(env
, "IO on conditional branch instruction");
8854 /* At this stage dc->condjmp will only be set when the skipped
8855 instruction was a conditional branch or trap, and the PC has
8856 already been written. */
8857 if (unlikely(env
->singlestep_enabled
)) {
8858 /* Make sure the pc is updated, and raise a debug exception. */
8860 gen_set_condexec(dc
);
8861 if (dc
->is_jmp
== DISAS_SWI
) {
8862 gen_exception(EXCP_SWI
);
8864 gen_exception(EXCP_DEBUG
);
8866 gen_set_label(dc
->condlabel
);
8868 if (dc
->condjmp
|| !dc
->is_jmp
) {
8869 gen_set_pc_im(dc
->pc
);
8872 gen_set_condexec(dc
);
8873 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
8874 gen_exception(EXCP_SWI
);
8876 /* FIXME: Single stepping a WFI insn will not halt
8878 gen_exception(EXCP_DEBUG
);
8881 /* While branches must always occur at the end of an IT block,
8882 there are a few other things that can cause us to terminate
8883 the TB in the middel of an IT block:
8884 - Exception generating instructions (bkpt, swi, undefined).
8886 - Hardware watchpoints.
8887 Hardware breakpoints have already been handled and skip this code.
8889 gen_set_condexec(dc
);
8890 switch(dc
->is_jmp
) {
8892 gen_goto_tb(dc
, 1, dc
->pc
);
8897 /* indicate that the hash table must be used to find the next TB */
8901 /* nothing more to generate */
8907 gen_exception(EXCP_SWI
);
8911 gen_set_label(dc
->condlabel
);
8912 gen_set_condexec(dc
);
8913 gen_goto_tb(dc
, 1, dc
->pc
);
8919 gen_icount_end(tb
, num_insns
);
8920 *gen_opc_ptr
= INDEX_op_end
;
8923 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
8924 qemu_log("----------------\n");
8925 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
8926 log_target_disas(pc_start
, dc
->pc
- pc_start
, env
->thumb
);
8931 j
= gen_opc_ptr
- gen_opc_buf
;
8934 gen_opc_instr_start
[lj
++] = 0;
8936 tb
->size
= dc
->pc
- pc_start
;
8937 tb
->icount
= num_insns
;
8941 void gen_intermediate_code(CPUState
*env
, TranslationBlock
*tb
)
8943 gen_intermediate_code_internal(env
, tb
, 0);
8946 void gen_intermediate_code_pc(CPUState
*env
, TranslationBlock
*tb
)
8948 gen_intermediate_code_internal(env
, tb
, 1);
8951 static const char *cpu_mode_names
[16] = {
8952 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
8953 "???", "???", "???", "und", "???", "???", "???", "sys"
8956 void cpu_dump_state(CPUState
*env
, FILE *f
,
8957 int (*cpu_fprintf
)(FILE *f
, const char *fmt
, ...),
8967 /* ??? This assumes float64 and double have the same layout.
8968 Oh well, it's only debug dumps. */
8977 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
8979 cpu_fprintf(f
, "\n");
8981 cpu_fprintf(f
, " ");
8983 psr
= cpsr_read(env
);
8984 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
8986 psr
& (1 << 31) ? 'N' : '-',
8987 psr
& (1 << 30) ? 'Z' : '-',
8988 psr
& (1 << 29) ? 'C' : '-',
8989 psr
& (1 << 28) ? 'V' : '-',
8990 psr
& CPSR_T
? 'T' : 'A',
8991 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
8994 for (i
= 0; i
< 16; i
++) {
8995 d
.d
= env
->vfp
.regs
[i
];
8999 cpu_fprintf(f
, "s%02d=%08x(%8g) s%02d=%08x(%8g) d%02d=%08x%08x(%8g)\n",
9000 i
* 2, (int)s0
.i
, s0
.s
,
9001 i
* 2 + 1, (int)s1
.i
, s1
.s
,
9002 i
, (int)(uint32_t)d
.l
.upper
, (int)(uint32_t)d
.l
.lower
,
9005 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
9009 void gen_pc_load(CPUState
*env
, TranslationBlock
*tb
,
9010 unsigned long searched_pc
, int pc_pos
, void *puc
)
9012 env
->regs
[15] = gen_opc_pc
[pc_pos
];