4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
28 #include "disas/disas.h"
36 #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
37 #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
38 /* currently all emulated v5 cores are also v5TE, so don't bother */
39 #define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5)
40 #define ENABLE_ARCH_5J 0
41 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
42 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
43 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
44 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
46 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
48 /* internal defines */
49 typedef struct DisasContext
{
52 /* Nonzero if this instruction has been conditionally skipped. */
54 /* The label that will be jumped to when the instruction is skipped. */
56 /* Thumb-2 conditional execution bits. */
59 struct TranslationBlock
*tb
;
60 int singlestep_enabled
;
63 #if !defined(CONFIG_USER_ONLY)
71 static uint32_t gen_opc_condexec_bits
[OPC_BUF_SIZE
];
73 #if defined(CONFIG_USER_ONLY)
76 #define IS_USER(s) (s->user)
79 /* These instructions trap after executing, so defer them until after the
80 conditional execution state has been updated. */
84 static TCGv_ptr cpu_env
;
85 /* We reuse the same 64-bit temporaries for efficiency. */
86 static TCGv_i64 cpu_V0
, cpu_V1
, cpu_M0
;
87 static TCGv_i32 cpu_R
[16];
88 static TCGv_i32 cpu_CF
, cpu_NF
, cpu_VF
, cpu_ZF
;
89 static TCGv_i32 cpu_exclusive_addr
;
90 static TCGv_i32 cpu_exclusive_val
;
91 static TCGv_i32 cpu_exclusive_high
;
92 #ifdef CONFIG_USER_ONLY
93 static TCGv_i32 cpu_exclusive_test
;
94 static TCGv_i32 cpu_exclusive_info
;
97 /* FIXME: These should be removed. */
98 static TCGv_i32 cpu_F0s
, cpu_F1s
;
99 static TCGv_i64 cpu_F0d
, cpu_F1d
;
101 #include "exec/gen-icount.h"
103 static const char *regnames
[] =
104 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
105 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
107 /* initialize TCG globals. */
108 void arm_translate_init(void)
112 cpu_env
= tcg_global_reg_new_ptr(TCG_AREG0
, "env");
114 for (i
= 0; i
< 16; i
++) {
115 cpu_R
[i
] = tcg_global_mem_new_i32(TCG_AREG0
,
116 offsetof(CPUARMState
, regs
[i
]),
119 cpu_CF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUARMState
, CF
), "CF");
120 cpu_NF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUARMState
, NF
), "NF");
121 cpu_VF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUARMState
, VF
), "VF");
122 cpu_ZF
= tcg_global_mem_new_i32(TCG_AREG0
, offsetof(CPUARMState
, ZF
), "ZF");
124 cpu_exclusive_addr
= tcg_global_mem_new_i32(TCG_AREG0
,
125 offsetof(CPUARMState
, exclusive_addr
), "exclusive_addr");
126 cpu_exclusive_val
= tcg_global_mem_new_i32(TCG_AREG0
,
127 offsetof(CPUARMState
, exclusive_val
), "exclusive_val");
128 cpu_exclusive_high
= tcg_global_mem_new_i32(TCG_AREG0
,
129 offsetof(CPUARMState
, exclusive_high
), "exclusive_high");
130 #ifdef CONFIG_USER_ONLY
131 cpu_exclusive_test
= tcg_global_mem_new_i32(TCG_AREG0
,
132 offsetof(CPUARMState
, exclusive_test
), "exclusive_test");
133 cpu_exclusive_info
= tcg_global_mem_new_i32(TCG_AREG0
,
134 offsetof(CPUARMState
, exclusive_info
), "exclusive_info");
141 static inline TCGv_i32
load_cpu_offset(int offset
)
143 TCGv_i32 tmp
= tcg_temp_new_i32();
144 tcg_gen_ld_i32(tmp
, cpu_env
, offset
);
148 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
150 static inline void store_cpu_offset(TCGv_i32 var
, int offset
)
152 tcg_gen_st_i32(var
, cpu_env
, offset
);
153 tcg_temp_free_i32(var
);
156 #define store_cpu_field(var, name) \
157 store_cpu_offset(var, offsetof(CPUARMState, name))
159 /* Set a variable to the value of a CPU register. */
160 static void load_reg_var(DisasContext
*s
, TCGv_i32 var
, int reg
)
164 /* normally, since we updated PC, we need only to add one insn */
166 addr
= (long)s
->pc
+ 2;
168 addr
= (long)s
->pc
+ 4;
169 tcg_gen_movi_i32(var
, addr
);
171 tcg_gen_mov_i32(var
, cpu_R
[reg
]);
175 /* Create a new temporary and set it to the value of a CPU register. */
176 static inline TCGv_i32
load_reg(DisasContext
*s
, int reg
)
178 TCGv_i32 tmp
= tcg_temp_new_i32();
179 load_reg_var(s
, tmp
, reg
);
183 /* Set a CPU register. The source must be a temporary and will be
185 static void store_reg(DisasContext
*s
, int reg
, TCGv_i32 var
)
188 tcg_gen_andi_i32(var
, var
, ~1);
189 s
->is_jmp
= DISAS_JUMP
;
191 tcg_gen_mov_i32(cpu_R
[reg
], var
);
192 tcg_temp_free_i32(var
);
195 /* Value extensions. */
196 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
197 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
198 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
199 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
201 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
202 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
205 static inline void gen_set_cpsr(TCGv_i32 var
, uint32_t mask
)
207 TCGv_i32 tmp_mask
= tcg_const_i32(mask
);
208 gen_helper_cpsr_write(cpu_env
, var
, tmp_mask
);
209 tcg_temp_free_i32(tmp_mask
);
211 /* Set NZCV flags from the high 4 bits of var. */
212 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
214 static void gen_exception(int excp
)
216 TCGv_i32 tmp
= tcg_temp_new_i32();
217 tcg_gen_movi_i32(tmp
, excp
);
218 gen_helper_exception(cpu_env
, tmp
);
219 tcg_temp_free_i32(tmp
);
222 static void gen_smul_dual(TCGv_i32 a
, TCGv_i32 b
)
224 TCGv_i32 tmp1
= tcg_temp_new_i32();
225 TCGv_i32 tmp2
= tcg_temp_new_i32();
226 tcg_gen_ext16s_i32(tmp1
, a
);
227 tcg_gen_ext16s_i32(tmp2
, b
);
228 tcg_gen_mul_i32(tmp1
, tmp1
, tmp2
);
229 tcg_temp_free_i32(tmp2
);
230 tcg_gen_sari_i32(a
, a
, 16);
231 tcg_gen_sari_i32(b
, b
, 16);
232 tcg_gen_mul_i32(b
, b
, a
);
233 tcg_gen_mov_i32(a
, tmp1
);
234 tcg_temp_free_i32(tmp1
);
237 /* Byteswap each halfword. */
238 static void gen_rev16(TCGv_i32 var
)
240 TCGv_i32 tmp
= tcg_temp_new_i32();
241 tcg_gen_shri_i32(tmp
, var
, 8);
242 tcg_gen_andi_i32(tmp
, tmp
, 0x00ff00ff);
243 tcg_gen_shli_i32(var
, var
, 8);
244 tcg_gen_andi_i32(var
, var
, 0xff00ff00);
245 tcg_gen_or_i32(var
, var
, tmp
);
246 tcg_temp_free_i32(tmp
);
249 /* Byteswap low halfword and sign extend. */
250 static void gen_revsh(TCGv_i32 var
)
252 tcg_gen_ext16u_i32(var
, var
);
253 tcg_gen_bswap16_i32(var
, var
);
254 tcg_gen_ext16s_i32(var
, var
);
257 /* Unsigned bitfield extract. */
258 static void gen_ubfx(TCGv_i32 var
, int shift
, uint32_t mask
)
261 tcg_gen_shri_i32(var
, var
, shift
);
262 tcg_gen_andi_i32(var
, var
, mask
);
265 /* Signed bitfield extract. */
266 static void gen_sbfx(TCGv_i32 var
, int shift
, int width
)
271 tcg_gen_sari_i32(var
, var
, shift
);
272 if (shift
+ width
< 32) {
273 signbit
= 1u << (width
- 1);
274 tcg_gen_andi_i32(var
, var
, (1u << width
) - 1);
275 tcg_gen_xori_i32(var
, var
, signbit
);
276 tcg_gen_subi_i32(var
, var
, signbit
);
280 /* Return (b << 32) + a. Mark inputs as dead */
281 static TCGv_i64
gen_addq_msw(TCGv_i64 a
, TCGv_i32 b
)
283 TCGv_i64 tmp64
= tcg_temp_new_i64();
285 tcg_gen_extu_i32_i64(tmp64
, b
);
286 tcg_temp_free_i32(b
);
287 tcg_gen_shli_i64(tmp64
, tmp64
, 32);
288 tcg_gen_add_i64(a
, tmp64
, a
);
290 tcg_temp_free_i64(tmp64
);
294 /* Return (b << 32) - a. Mark inputs as dead. */
295 static TCGv_i64
gen_subq_msw(TCGv_i64 a
, TCGv_i32 b
)
297 TCGv_i64 tmp64
= tcg_temp_new_i64();
299 tcg_gen_extu_i32_i64(tmp64
, b
);
300 tcg_temp_free_i32(b
);
301 tcg_gen_shli_i64(tmp64
, tmp64
, 32);
302 tcg_gen_sub_i64(a
, tmp64
, a
);
304 tcg_temp_free_i64(tmp64
);
308 /* 32x32->64 multiply. Marks inputs as dead. */
309 static TCGv_i64
gen_mulu_i64_i32(TCGv_i32 a
, TCGv_i32 b
)
311 TCGv_i32 lo
= tcg_temp_new_i32();
312 TCGv_i32 hi
= tcg_temp_new_i32();
315 tcg_gen_mulu2_i32(lo
, hi
, a
, b
);
316 tcg_temp_free_i32(a
);
317 tcg_temp_free_i32(b
);
319 ret
= tcg_temp_new_i64();
320 tcg_gen_concat_i32_i64(ret
, lo
, hi
);
321 tcg_temp_free_i32(lo
);
322 tcg_temp_free_i32(hi
);
327 static TCGv_i64
gen_muls_i64_i32(TCGv_i32 a
, TCGv_i32 b
)
329 TCGv_i32 lo
= tcg_temp_new_i32();
330 TCGv_i32 hi
= tcg_temp_new_i32();
333 tcg_gen_muls2_i32(lo
, hi
, a
, b
);
334 tcg_temp_free_i32(a
);
335 tcg_temp_free_i32(b
);
337 ret
= tcg_temp_new_i64();
338 tcg_gen_concat_i32_i64(ret
, lo
, hi
);
339 tcg_temp_free_i32(lo
);
340 tcg_temp_free_i32(hi
);
345 /* Swap low and high halfwords. */
346 static void gen_swap_half(TCGv_i32 var
)
348 TCGv_i32 tmp
= tcg_temp_new_i32();
349 tcg_gen_shri_i32(tmp
, var
, 16);
350 tcg_gen_shli_i32(var
, var
, 16);
351 tcg_gen_or_i32(var
, var
, tmp
);
352 tcg_temp_free_i32(tmp
);
355 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
356 tmp = (t0 ^ t1) & 0x8000;
359 t0 = (t0 + t1) ^ tmp;
362 static void gen_add16(TCGv_i32 t0
, TCGv_i32 t1
)
364 TCGv_i32 tmp
= tcg_temp_new_i32();
365 tcg_gen_xor_i32(tmp
, t0
, t1
);
366 tcg_gen_andi_i32(tmp
, tmp
, 0x8000);
367 tcg_gen_andi_i32(t0
, t0
, ~0x8000);
368 tcg_gen_andi_i32(t1
, t1
, ~0x8000);
369 tcg_gen_add_i32(t0
, t0
, t1
);
370 tcg_gen_xor_i32(t0
, t0
, tmp
);
371 tcg_temp_free_i32(tmp
);
372 tcg_temp_free_i32(t1
);
375 /* Set CF to the top bit of var. */
376 static void gen_set_CF_bit31(TCGv_i32 var
)
378 tcg_gen_shri_i32(cpu_CF
, var
, 31);
381 /* Set N and Z flags from var. */
382 static inline void gen_logic_CC(TCGv_i32 var
)
384 tcg_gen_mov_i32(cpu_NF
, var
);
385 tcg_gen_mov_i32(cpu_ZF
, var
);
389 static void gen_adc(TCGv_i32 t0
, TCGv_i32 t1
)
391 tcg_gen_add_i32(t0
, t0
, t1
);
392 tcg_gen_add_i32(t0
, t0
, cpu_CF
);
395 /* dest = T0 + T1 + CF. */
396 static void gen_add_carry(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
398 tcg_gen_add_i32(dest
, t0
, t1
);
399 tcg_gen_add_i32(dest
, dest
, cpu_CF
);
402 /* dest = T0 - T1 + CF - 1. */
403 static void gen_sub_carry(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
405 tcg_gen_sub_i32(dest
, t0
, t1
);
406 tcg_gen_add_i32(dest
, dest
, cpu_CF
);
407 tcg_gen_subi_i32(dest
, dest
, 1);
410 /* dest = T0 + T1. Compute C, N, V and Z flags */
411 static void gen_add_CC(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
413 TCGv_i32 tmp
= tcg_temp_new_i32();
414 tcg_gen_movi_i32(tmp
, 0);
415 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, t0
, tmp
, t1
, tmp
);
416 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
417 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0
);
418 tcg_gen_xor_i32(tmp
, t0
, t1
);
419 tcg_gen_andc_i32(cpu_VF
, cpu_VF
, tmp
);
420 tcg_temp_free_i32(tmp
);
421 tcg_gen_mov_i32(dest
, cpu_NF
);
424 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
425 static void gen_adc_CC(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
427 TCGv_i32 tmp
= tcg_temp_new_i32();
428 if (TCG_TARGET_HAS_add2_i32
) {
429 tcg_gen_movi_i32(tmp
, 0);
430 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, t0
, tmp
, cpu_CF
, tmp
);
431 tcg_gen_add2_i32(cpu_NF
, cpu_CF
, cpu_NF
, cpu_CF
, t1
, tmp
);
433 TCGv_i64 q0
= tcg_temp_new_i64();
434 TCGv_i64 q1
= tcg_temp_new_i64();
435 tcg_gen_extu_i32_i64(q0
, t0
);
436 tcg_gen_extu_i32_i64(q1
, t1
);
437 tcg_gen_add_i64(q0
, q0
, q1
);
438 tcg_gen_extu_i32_i64(q1
, cpu_CF
);
439 tcg_gen_add_i64(q0
, q0
, q1
);
440 tcg_gen_extr_i64_i32(cpu_NF
, cpu_CF
, q0
);
441 tcg_temp_free_i64(q0
);
442 tcg_temp_free_i64(q1
);
444 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
445 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0
);
446 tcg_gen_xor_i32(tmp
, t0
, t1
);
447 tcg_gen_andc_i32(cpu_VF
, cpu_VF
, tmp
);
448 tcg_temp_free_i32(tmp
);
449 tcg_gen_mov_i32(dest
, cpu_NF
);
452 /* dest = T0 - T1. Compute C, N, V and Z flags */
453 static void gen_sub_CC(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
456 tcg_gen_sub_i32(cpu_NF
, t0
, t1
);
457 tcg_gen_mov_i32(cpu_ZF
, cpu_NF
);
458 tcg_gen_setcond_i32(TCG_COND_GEU
, cpu_CF
, t0
, t1
);
459 tcg_gen_xor_i32(cpu_VF
, cpu_NF
, t0
);
460 tmp
= tcg_temp_new_i32();
461 tcg_gen_xor_i32(tmp
, t0
, t1
);
462 tcg_gen_and_i32(cpu_VF
, cpu_VF
, tmp
);
463 tcg_temp_free_i32(tmp
);
464 tcg_gen_mov_i32(dest
, cpu_NF
);
467 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
468 static void gen_sbc_CC(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
470 TCGv_i32 tmp
= tcg_temp_new_i32();
471 tcg_gen_not_i32(tmp
, t1
);
472 gen_adc_CC(dest
, t0
, tmp
);
473 tcg_temp_free_i32(tmp
);
476 #define GEN_SHIFT(name) \
477 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
479 TCGv_i32 tmp1, tmp2, tmp3; \
480 tmp1 = tcg_temp_new_i32(); \
481 tcg_gen_andi_i32(tmp1, t1, 0xff); \
482 tmp2 = tcg_const_i32(0); \
483 tmp3 = tcg_const_i32(0x1f); \
484 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
485 tcg_temp_free_i32(tmp3); \
486 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
487 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
488 tcg_temp_free_i32(tmp2); \
489 tcg_temp_free_i32(tmp1); \
495 static void gen_sar(TCGv_i32 dest
, TCGv_i32 t0
, TCGv_i32 t1
)
498 tmp1
= tcg_temp_new_i32();
499 tcg_gen_andi_i32(tmp1
, t1
, 0xff);
500 tmp2
= tcg_const_i32(0x1f);
501 tcg_gen_movcond_i32(TCG_COND_GTU
, tmp1
, tmp1
, tmp2
, tmp2
, tmp1
);
502 tcg_temp_free_i32(tmp2
);
503 tcg_gen_sar_i32(dest
, t0
, tmp1
);
504 tcg_temp_free_i32(tmp1
);
507 static void tcg_gen_abs_i32(TCGv_i32 dest
, TCGv_i32 src
)
509 TCGv_i32 c0
= tcg_const_i32(0);
510 TCGv_i32 tmp
= tcg_temp_new_i32();
511 tcg_gen_neg_i32(tmp
, src
);
512 tcg_gen_movcond_i32(TCG_COND_GT
, dest
, src
, c0
, src
, tmp
);
513 tcg_temp_free_i32(c0
);
514 tcg_temp_free_i32(tmp
);
517 static void shifter_out_im(TCGv_i32 var
, int shift
)
520 tcg_gen_andi_i32(cpu_CF
, var
, 1);
522 tcg_gen_shri_i32(cpu_CF
, var
, shift
);
524 tcg_gen_andi_i32(cpu_CF
, cpu_CF
, 1);
529 /* Shift by immediate. Includes special handling for shift == 0. */
530 static inline void gen_arm_shift_im(TCGv_i32 var
, int shiftop
,
531 int shift
, int flags
)
537 shifter_out_im(var
, 32 - shift
);
538 tcg_gen_shli_i32(var
, var
, shift
);
544 tcg_gen_shri_i32(cpu_CF
, var
, 31);
546 tcg_gen_movi_i32(var
, 0);
549 shifter_out_im(var
, shift
- 1);
550 tcg_gen_shri_i32(var
, var
, shift
);
557 shifter_out_im(var
, shift
- 1);
560 tcg_gen_sari_i32(var
, var
, shift
);
562 case 3: /* ROR/RRX */
565 shifter_out_im(var
, shift
- 1);
566 tcg_gen_rotri_i32(var
, var
, shift
); break;
568 TCGv_i32 tmp
= tcg_temp_new_i32();
569 tcg_gen_shli_i32(tmp
, cpu_CF
, 31);
571 shifter_out_im(var
, 0);
572 tcg_gen_shri_i32(var
, var
, 1);
573 tcg_gen_or_i32(var
, var
, tmp
);
574 tcg_temp_free_i32(tmp
);
579 static inline void gen_arm_shift_reg(TCGv_i32 var
, int shiftop
,
580 TCGv_i32 shift
, int flags
)
584 case 0: gen_helper_shl_cc(var
, cpu_env
, var
, shift
); break;
585 case 1: gen_helper_shr_cc(var
, cpu_env
, var
, shift
); break;
586 case 2: gen_helper_sar_cc(var
, cpu_env
, var
, shift
); break;
587 case 3: gen_helper_ror_cc(var
, cpu_env
, var
, shift
); break;
592 gen_shl(var
, var
, shift
);
595 gen_shr(var
, var
, shift
);
598 gen_sar(var
, var
, shift
);
600 case 3: tcg_gen_andi_i32(shift
, shift
, 0x1f);
601 tcg_gen_rotr_i32(var
, var
, shift
); break;
604 tcg_temp_free_i32(shift
);
607 #define PAS_OP(pfx) \
609 case 0: gen_pas_helper(glue(pfx,add16)); break; \
610 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
611 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
612 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
613 case 4: gen_pas_helper(glue(pfx,add8)); break; \
614 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
616 static void gen_arm_parallel_addsub(int op1
, int op2
, TCGv_i32 a
, TCGv_i32 b
)
621 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
623 tmp
= tcg_temp_new_ptr();
624 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUARMState
, GE
));
626 tcg_temp_free_ptr(tmp
);
629 tmp
= tcg_temp_new_ptr();
630 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUARMState
, GE
));
632 tcg_temp_free_ptr(tmp
);
634 #undef gen_pas_helper
635 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
648 #undef gen_pas_helper
653 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
654 #define PAS_OP(pfx) \
656 case 0: gen_pas_helper(glue(pfx,add8)); break; \
657 case 1: gen_pas_helper(glue(pfx,add16)); break; \
658 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
659 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
660 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
661 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
663 static void gen_thumb2_parallel_addsub(int op1
, int op2
, TCGv_i32 a
, TCGv_i32 b
)
668 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
670 tmp
= tcg_temp_new_ptr();
671 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUARMState
, GE
));
673 tcg_temp_free_ptr(tmp
);
676 tmp
= tcg_temp_new_ptr();
677 tcg_gen_addi_ptr(tmp
, cpu_env
, offsetof(CPUARMState
, GE
));
679 tcg_temp_free_ptr(tmp
);
681 #undef gen_pas_helper
682 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
695 #undef gen_pas_helper
700 static void gen_test_cc(int cc
, int label
)
707 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_ZF
, 0, label
);
710 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_ZF
, 0, label
);
713 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_CF
, 0, label
);
716 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_CF
, 0, label
);
719 tcg_gen_brcondi_i32(TCG_COND_LT
, cpu_NF
, 0, label
);
722 tcg_gen_brcondi_i32(TCG_COND_GE
, cpu_NF
, 0, label
);
725 tcg_gen_brcondi_i32(TCG_COND_LT
, cpu_VF
, 0, label
);
728 tcg_gen_brcondi_i32(TCG_COND_GE
, cpu_VF
, 0, label
);
730 case 8: /* hi: C && !Z */
731 inv
= gen_new_label();
732 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_CF
, 0, inv
);
733 tcg_gen_brcondi_i32(TCG_COND_NE
, cpu_ZF
, 0, label
);
736 case 9: /* ls: !C || Z */
737 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_CF
, 0, label
);
738 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_ZF
, 0, label
);
740 case 10: /* ge: N == V -> N ^ V == 0 */
741 tmp
= tcg_temp_new_i32();
742 tcg_gen_xor_i32(tmp
, cpu_VF
, cpu_NF
);
743 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
744 tcg_temp_free_i32(tmp
);
746 case 11: /* lt: N != V -> N ^ V != 0 */
747 tmp
= tcg_temp_new_i32();
748 tcg_gen_xor_i32(tmp
, cpu_VF
, cpu_NF
);
749 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
750 tcg_temp_free_i32(tmp
);
752 case 12: /* gt: !Z && N == V */
753 inv
= gen_new_label();
754 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_ZF
, 0, inv
);
755 tmp
= tcg_temp_new_i32();
756 tcg_gen_xor_i32(tmp
, cpu_VF
, cpu_NF
);
757 tcg_gen_brcondi_i32(TCG_COND_GE
, tmp
, 0, label
);
758 tcg_temp_free_i32(tmp
);
761 case 13: /* le: Z || N != V */
762 tcg_gen_brcondi_i32(TCG_COND_EQ
, cpu_ZF
, 0, label
);
763 tmp
= tcg_temp_new_i32();
764 tcg_gen_xor_i32(tmp
, cpu_VF
, cpu_NF
);
765 tcg_gen_brcondi_i32(TCG_COND_LT
, tmp
, 0, label
);
766 tcg_temp_free_i32(tmp
);
769 fprintf(stderr
, "Bad condition code 0x%x\n", cc
);
774 static const uint8_t table_logic_cc
[16] = {
793 /* Set PC and Thumb state from an immediate address. */
794 static inline void gen_bx_im(DisasContext
*s
, uint32_t addr
)
798 s
->is_jmp
= DISAS_UPDATE
;
799 if (s
->thumb
!= (addr
& 1)) {
800 tmp
= tcg_temp_new_i32();
801 tcg_gen_movi_i32(tmp
, addr
& 1);
802 tcg_gen_st_i32(tmp
, cpu_env
, offsetof(CPUARMState
, thumb
));
803 tcg_temp_free_i32(tmp
);
805 tcg_gen_movi_i32(cpu_R
[15], addr
& ~1);
808 /* Set PC and Thumb state from var. var is marked as dead. */
809 static inline void gen_bx(DisasContext
*s
, TCGv_i32 var
)
811 s
->is_jmp
= DISAS_UPDATE
;
812 tcg_gen_andi_i32(cpu_R
[15], var
, ~1);
813 tcg_gen_andi_i32(var
, var
, 1);
814 store_cpu_field(var
, thumb
);
817 /* Variant of store_reg which uses branch&exchange logic when storing
818 to r15 in ARM architecture v7 and above. The source must be a temporary
819 and will be marked as dead. */
820 static inline void store_reg_bx(CPUARMState
*env
, DisasContext
*s
,
821 int reg
, TCGv_i32 var
)
823 if (reg
== 15 && ENABLE_ARCH_7
) {
826 store_reg(s
, reg
, var
);
830 /* Variant of store_reg which uses branch&exchange logic when storing
831 * to r15 in ARM architecture v5T and above. This is used for storing
832 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
833 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
834 static inline void store_reg_from_load(CPUARMState
*env
, DisasContext
*s
,
835 int reg
, TCGv_i32 var
)
837 if (reg
== 15 && ENABLE_ARCH_5
) {
840 store_reg(s
, reg
, var
);
844 static inline TCGv_i32
gen_ld8s(TCGv_i32 addr
, int index
)
846 TCGv_i32 tmp
= tcg_temp_new_i32();
847 tcg_gen_qemu_ld8s(tmp
, addr
, index
);
850 static inline TCGv_i32
gen_ld8u(TCGv_i32 addr
, int index
)
852 TCGv_i32 tmp
= tcg_temp_new_i32();
853 tcg_gen_qemu_ld8u(tmp
, addr
, index
);
856 static inline TCGv_i32
gen_ld16s(TCGv_i32 addr
, int index
)
858 TCGv_i32 tmp
= tcg_temp_new_i32();
859 tcg_gen_qemu_ld16s(tmp
, addr
, index
);
862 static inline TCGv_i32
gen_ld16u(TCGv_i32 addr
, int index
)
864 TCGv_i32 tmp
= tcg_temp_new_i32();
865 tcg_gen_qemu_ld16u(tmp
, addr
, index
);
868 static inline TCGv_i32
gen_ld32(TCGv_i32 addr
, int index
)
870 TCGv_i32 tmp
= tcg_temp_new_i32();
871 tcg_gen_qemu_ld32u(tmp
, addr
, index
);
874 static inline void gen_st8(TCGv_i32 val
, TCGv_i32 addr
, int index
)
876 tcg_gen_qemu_st8(val
, addr
, index
);
877 tcg_temp_free_i32(val
);
879 static inline void gen_st16(TCGv_i32 val
, TCGv_i32 addr
, int index
)
881 tcg_gen_qemu_st16(val
, addr
, index
);
882 tcg_temp_free_i32(val
);
884 static inline void gen_st32(TCGv_i32 val
, TCGv_i32 addr
, int index
)
886 tcg_gen_qemu_st32(val
, addr
, index
);
887 tcg_temp_free_i32(val
);
890 static inline void gen_set_pc_im(uint32_t val
)
892 tcg_gen_movi_i32(cpu_R
[15], val
);
895 /* Force a TB lookup after an instruction that changes the CPU state. */
896 static inline void gen_lookup_tb(DisasContext
*s
)
898 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
899 s
->is_jmp
= DISAS_UPDATE
;
902 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
905 int val
, rm
, shift
, shiftop
;
908 if (!(insn
& (1 << 25))) {
911 if (!(insn
& (1 << 23)))
914 tcg_gen_addi_i32(var
, var
, val
);
918 shift
= (insn
>> 7) & 0x1f;
919 shiftop
= (insn
>> 5) & 3;
920 offset
= load_reg(s
, rm
);
921 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
922 if (!(insn
& (1 << 23)))
923 tcg_gen_sub_i32(var
, var
, offset
);
925 tcg_gen_add_i32(var
, var
, offset
);
926 tcg_temp_free_i32(offset
);
930 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
931 int extra
, TCGv_i32 var
)
936 if (insn
& (1 << 22)) {
938 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
939 if (!(insn
& (1 << 23)))
943 tcg_gen_addi_i32(var
, var
, val
);
947 tcg_gen_addi_i32(var
, var
, extra
);
949 offset
= load_reg(s
, rm
);
950 if (!(insn
& (1 << 23)))
951 tcg_gen_sub_i32(var
, var
, offset
);
953 tcg_gen_add_i32(var
, var
, offset
);
954 tcg_temp_free_i32(offset
);
958 static TCGv_ptr
get_fpstatus_ptr(int neon
)
960 TCGv_ptr statusptr
= tcg_temp_new_ptr();
963 offset
= offsetof(CPUARMState
, vfp
.standard_fp_status
);
965 offset
= offsetof(CPUARMState
, vfp
.fp_status
);
967 tcg_gen_addi_ptr(statusptr
, cpu_env
, offset
);
971 #define VFP_OP2(name) \
972 static inline void gen_vfp_##name(int dp) \
974 TCGv_ptr fpst = get_fpstatus_ptr(0); \
976 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
978 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
980 tcg_temp_free_ptr(fpst); \
990 static inline void gen_vfp_F1_mul(int dp
)
992 /* Like gen_vfp_mul() but put result in F1 */
993 TCGv_ptr fpst
= get_fpstatus_ptr(0);
995 gen_helper_vfp_muld(cpu_F1d
, cpu_F0d
, cpu_F1d
, fpst
);
997 gen_helper_vfp_muls(cpu_F1s
, cpu_F0s
, cpu_F1s
, fpst
);
999 tcg_temp_free_ptr(fpst
);
1002 static inline void gen_vfp_F1_neg(int dp
)
1004 /* Like gen_vfp_neg() but put result in F1 */
1006 gen_helper_vfp_negd(cpu_F1d
, cpu_F0d
);
1008 gen_helper_vfp_negs(cpu_F1s
, cpu_F0s
);
1012 static inline void gen_vfp_abs(int dp
)
1015 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
1017 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
1020 static inline void gen_vfp_neg(int dp
)
1023 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
1025 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
1028 static inline void gen_vfp_sqrt(int dp
)
1031 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
1033 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
1036 static inline void gen_vfp_cmp(int dp
)
1039 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
1041 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
1044 static inline void gen_vfp_cmpe(int dp
)
1047 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1049 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1052 static inline void gen_vfp_F1_ld0(int dp
)
1055 tcg_gen_movi_i64(cpu_F1d
, 0);
1057 tcg_gen_movi_i32(cpu_F1s
, 0);
1060 #define VFP_GEN_ITOF(name) \
1061 static inline void gen_vfp_##name(int dp, int neon) \
1063 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1065 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1067 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1069 tcg_temp_free_ptr(statusptr); \
1076 #define VFP_GEN_FTOI(name) \
1077 static inline void gen_vfp_##name(int dp, int neon) \
1079 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1081 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1083 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1085 tcg_temp_free_ptr(statusptr); \
1094 #define VFP_GEN_FIX(name) \
1095 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1097 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1098 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1100 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
1102 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
1104 tcg_temp_free_i32(tmp_shift); \
1105 tcg_temp_free_ptr(statusptr); \
1117 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv_i32 addr
)
1120 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1122 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1125 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv_i32 addr
)
1128 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1130 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1134 vfp_reg_offset (int dp
, int reg
)
1137 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1139 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1140 + offsetof(CPU_DoubleU
, l
.upper
);
1142 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1143 + offsetof(CPU_DoubleU
, l
.lower
);
1147 /* Return the offset of a 32-bit piece of a NEON register.
1148 zero is the least significant end of the register. */
1150 neon_reg_offset (int reg
, int n
)
1154 return vfp_reg_offset(0, sreg
);
1157 static TCGv_i32
neon_load_reg(int reg
, int pass
)
1159 TCGv_i32 tmp
= tcg_temp_new_i32();
1160 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1164 static void neon_store_reg(int reg
, int pass
, TCGv_i32 var
)
1166 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1167 tcg_temp_free_i32(var
);
1170 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1172 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1175 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1177 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1180 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1181 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1182 #define tcg_gen_st_f32 tcg_gen_st_i32
1183 #define tcg_gen_st_f64 tcg_gen_st_i64
1185 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1188 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1190 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1193 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1196 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1198 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1201 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1204 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1206 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1209 #define ARM_CP_RW_BIT (1 << 20)
1211 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1213 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.regs
[reg
]));
1216 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1218 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.regs
[reg
]));
1221 static inline TCGv_i32
iwmmxt_load_creg(int reg
)
1223 TCGv_i32 var
= tcg_temp_new_i32();
1224 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.cregs
[reg
]));
1228 static inline void iwmmxt_store_creg(int reg
, TCGv_i32 var
)
1230 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.cregs
[reg
]));
1231 tcg_temp_free_i32(var
);
1234 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1236 iwmmxt_store_reg(cpu_M0
, rn
);
1239 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1241 iwmmxt_load_reg(cpu_M0
, rn
);
1244 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1246 iwmmxt_load_reg(cpu_V1
, rn
);
1247 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1250 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1252 iwmmxt_load_reg(cpu_V1
, rn
);
1253 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1256 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1258 iwmmxt_load_reg(cpu_V1
, rn
);
1259 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1262 #define IWMMXT_OP(name) \
1263 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1265 iwmmxt_load_reg(cpu_V1, rn); \
1266 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1269 #define IWMMXT_OP_ENV(name) \
1270 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1272 iwmmxt_load_reg(cpu_V1, rn); \
1273 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1276 #define IWMMXT_OP_ENV_SIZE(name) \
1277 IWMMXT_OP_ENV(name##b) \
1278 IWMMXT_OP_ENV(name##w) \
1279 IWMMXT_OP_ENV(name##l)
1281 #define IWMMXT_OP_ENV1(name) \
1282 static inline void gen_op_iwmmxt_##name##_M0(void) \
1284 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1298 IWMMXT_OP_ENV_SIZE(unpackl
)
1299 IWMMXT_OP_ENV_SIZE(unpackh
)
1301 IWMMXT_OP_ENV1(unpacklub
)
1302 IWMMXT_OP_ENV1(unpackluw
)
1303 IWMMXT_OP_ENV1(unpacklul
)
1304 IWMMXT_OP_ENV1(unpackhub
)
1305 IWMMXT_OP_ENV1(unpackhuw
)
1306 IWMMXT_OP_ENV1(unpackhul
)
1307 IWMMXT_OP_ENV1(unpacklsb
)
1308 IWMMXT_OP_ENV1(unpacklsw
)
1309 IWMMXT_OP_ENV1(unpacklsl
)
1310 IWMMXT_OP_ENV1(unpackhsb
)
1311 IWMMXT_OP_ENV1(unpackhsw
)
1312 IWMMXT_OP_ENV1(unpackhsl
)
1314 IWMMXT_OP_ENV_SIZE(cmpeq
)
1315 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1316 IWMMXT_OP_ENV_SIZE(cmpgts
)
1318 IWMMXT_OP_ENV_SIZE(mins
)
1319 IWMMXT_OP_ENV_SIZE(minu
)
1320 IWMMXT_OP_ENV_SIZE(maxs
)
1321 IWMMXT_OP_ENV_SIZE(maxu
)
1323 IWMMXT_OP_ENV_SIZE(subn
)
1324 IWMMXT_OP_ENV_SIZE(addn
)
1325 IWMMXT_OP_ENV_SIZE(subu
)
1326 IWMMXT_OP_ENV_SIZE(addu
)
1327 IWMMXT_OP_ENV_SIZE(subs
)
1328 IWMMXT_OP_ENV_SIZE(adds
)
1330 IWMMXT_OP_ENV(avgb0
)
1331 IWMMXT_OP_ENV(avgb1
)
1332 IWMMXT_OP_ENV(avgw0
)
1333 IWMMXT_OP_ENV(avgw1
)
1337 IWMMXT_OP_ENV(packuw
)
1338 IWMMXT_OP_ENV(packul
)
1339 IWMMXT_OP_ENV(packuq
)
1340 IWMMXT_OP_ENV(packsw
)
1341 IWMMXT_OP_ENV(packsl
)
1342 IWMMXT_OP_ENV(packsq
)
1344 static void gen_op_iwmmxt_set_mup(void)
1347 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1348 tcg_gen_ori_i32(tmp
, tmp
, 2);
1349 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1352 static void gen_op_iwmmxt_set_cup(void)
1355 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1356 tcg_gen_ori_i32(tmp
, tmp
, 1);
1357 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1360 static void gen_op_iwmmxt_setpsr_nz(void)
1362 TCGv_i32 tmp
= tcg_temp_new_i32();
1363 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1364 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1367 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1369 iwmmxt_load_reg(cpu_V1
, rn
);
1370 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1371 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1374 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
,
1381 rd
= (insn
>> 16) & 0xf;
1382 tmp
= load_reg(s
, rd
);
1384 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1385 if (insn
& (1 << 24)) {
1387 if (insn
& (1 << 23))
1388 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1390 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1391 tcg_gen_mov_i32(dest
, tmp
);
1392 if (insn
& (1 << 21))
1393 store_reg(s
, rd
, tmp
);
1395 tcg_temp_free_i32(tmp
);
1396 } else if (insn
& (1 << 21)) {
1398 tcg_gen_mov_i32(dest
, tmp
);
1399 if (insn
& (1 << 23))
1400 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1402 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1403 store_reg(s
, rd
, tmp
);
1404 } else if (!(insn
& (1 << 23)))
1409 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv_i32 dest
)
1411 int rd
= (insn
>> 0) & 0xf;
1414 if (insn
& (1 << 8)) {
1415 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1418 tmp
= iwmmxt_load_creg(rd
);
1421 tmp
= tcg_temp_new_i32();
1422 iwmmxt_load_reg(cpu_V0
, rd
);
1423 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1425 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1426 tcg_gen_mov_i32(dest
, tmp
);
1427 tcg_temp_free_i32(tmp
);
1431 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1432 (ie. an undefined instruction). */
1433 static int disas_iwmmxt_insn(CPUARMState
*env
, DisasContext
*s
, uint32_t insn
)
1436 int rdhi
, rdlo
, rd0
, rd1
, i
;
1438 TCGv_i32 tmp
, tmp2
, tmp3
;
1440 if ((insn
& 0x0e000e00) == 0x0c000000) {
1441 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1443 rdlo
= (insn
>> 12) & 0xf;
1444 rdhi
= (insn
>> 16) & 0xf;
1445 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1446 iwmmxt_load_reg(cpu_V0
, wrd
);
1447 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1448 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1449 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1450 } else { /* TMCRR */
1451 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1452 iwmmxt_store_reg(cpu_V0
, wrd
);
1453 gen_op_iwmmxt_set_mup();
1458 wrd
= (insn
>> 12) & 0xf;
1459 addr
= tcg_temp_new_i32();
1460 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1461 tcg_temp_free_i32(addr
);
1464 if (insn
& ARM_CP_RW_BIT
) {
1465 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1466 tmp
= tcg_temp_new_i32();
1467 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1468 iwmmxt_store_creg(wrd
, tmp
);
1471 if (insn
& (1 << 8)) {
1472 if (insn
& (1 << 22)) { /* WLDRD */
1473 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1475 } else { /* WLDRW wRd */
1476 tmp
= tcg_temp_new_i32();
1477 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1480 tmp
= tcg_temp_new_i32();
1481 if (insn
& (1 << 22)) { /* WLDRH */
1482 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
1483 } else { /* WLDRB */
1484 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
1488 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1489 tcg_temp_free_i32(tmp
);
1491 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1494 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1495 tmp
= iwmmxt_load_creg(wrd
);
1496 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
1498 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1499 tmp
= tcg_temp_new_i32();
1500 if (insn
& (1 << 8)) {
1501 if (insn
& (1 << 22)) { /* WSTRD */
1502 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1503 } else { /* WSTRW wRd */
1504 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1505 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
1508 if (insn
& (1 << 22)) { /* WSTRH */
1509 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1510 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
1511 } else { /* WSTRB */
1512 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1513 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
1517 tcg_temp_free_i32(tmp
);
1519 tcg_temp_free_i32(addr
);
1523 if ((insn
& 0x0f000000) != 0x0e000000)
1526 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1527 case 0x000: /* WOR */
1528 wrd
= (insn
>> 12) & 0xf;
1529 rd0
= (insn
>> 0) & 0xf;
1530 rd1
= (insn
>> 16) & 0xf;
1531 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1532 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1533 gen_op_iwmmxt_setpsr_nz();
1534 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1535 gen_op_iwmmxt_set_mup();
1536 gen_op_iwmmxt_set_cup();
1538 case 0x011: /* TMCR */
1541 rd
= (insn
>> 12) & 0xf;
1542 wrd
= (insn
>> 16) & 0xf;
1544 case ARM_IWMMXT_wCID
:
1545 case ARM_IWMMXT_wCASF
:
1547 case ARM_IWMMXT_wCon
:
1548 gen_op_iwmmxt_set_cup();
1550 case ARM_IWMMXT_wCSSF
:
1551 tmp
= iwmmxt_load_creg(wrd
);
1552 tmp2
= load_reg(s
, rd
);
1553 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
1554 tcg_temp_free_i32(tmp2
);
1555 iwmmxt_store_creg(wrd
, tmp
);
1557 case ARM_IWMMXT_wCGR0
:
1558 case ARM_IWMMXT_wCGR1
:
1559 case ARM_IWMMXT_wCGR2
:
1560 case ARM_IWMMXT_wCGR3
:
1561 gen_op_iwmmxt_set_cup();
1562 tmp
= load_reg(s
, rd
);
1563 iwmmxt_store_creg(wrd
, tmp
);
1569 case 0x100: /* WXOR */
1570 wrd
= (insn
>> 12) & 0xf;
1571 rd0
= (insn
>> 0) & 0xf;
1572 rd1
= (insn
>> 16) & 0xf;
1573 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1574 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1575 gen_op_iwmmxt_setpsr_nz();
1576 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1577 gen_op_iwmmxt_set_mup();
1578 gen_op_iwmmxt_set_cup();
1580 case 0x111: /* TMRC */
1583 rd
= (insn
>> 12) & 0xf;
1584 wrd
= (insn
>> 16) & 0xf;
1585 tmp
= iwmmxt_load_creg(wrd
);
1586 store_reg(s
, rd
, tmp
);
1588 case 0x300: /* WANDN */
1589 wrd
= (insn
>> 12) & 0xf;
1590 rd0
= (insn
>> 0) & 0xf;
1591 rd1
= (insn
>> 16) & 0xf;
1592 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1593 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1594 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1595 gen_op_iwmmxt_setpsr_nz();
1596 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1597 gen_op_iwmmxt_set_mup();
1598 gen_op_iwmmxt_set_cup();
1600 case 0x200: /* WAND */
1601 wrd
= (insn
>> 12) & 0xf;
1602 rd0
= (insn
>> 0) & 0xf;
1603 rd1
= (insn
>> 16) & 0xf;
1604 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1605 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1606 gen_op_iwmmxt_setpsr_nz();
1607 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1608 gen_op_iwmmxt_set_mup();
1609 gen_op_iwmmxt_set_cup();
1611 case 0x810: case 0xa10: /* WMADD */
1612 wrd
= (insn
>> 12) & 0xf;
1613 rd0
= (insn
>> 0) & 0xf;
1614 rd1
= (insn
>> 16) & 0xf;
1615 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1616 if (insn
& (1 << 21))
1617 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1619 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1620 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1621 gen_op_iwmmxt_set_mup();
1623 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1624 wrd
= (insn
>> 12) & 0xf;
1625 rd0
= (insn
>> 16) & 0xf;
1626 rd1
= (insn
>> 0) & 0xf;
1627 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1628 switch ((insn
>> 22) & 3) {
1630 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1633 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1636 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1641 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1642 gen_op_iwmmxt_set_mup();
1643 gen_op_iwmmxt_set_cup();
1645 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1646 wrd
= (insn
>> 12) & 0xf;
1647 rd0
= (insn
>> 16) & 0xf;
1648 rd1
= (insn
>> 0) & 0xf;
1649 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1650 switch ((insn
>> 22) & 3) {
1652 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1655 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1658 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1663 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1664 gen_op_iwmmxt_set_mup();
1665 gen_op_iwmmxt_set_cup();
1667 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1668 wrd
= (insn
>> 12) & 0xf;
1669 rd0
= (insn
>> 16) & 0xf;
1670 rd1
= (insn
>> 0) & 0xf;
1671 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1672 if (insn
& (1 << 22))
1673 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1675 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1676 if (!(insn
& (1 << 20)))
1677 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1678 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1679 gen_op_iwmmxt_set_mup();
1681 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1682 wrd
= (insn
>> 12) & 0xf;
1683 rd0
= (insn
>> 16) & 0xf;
1684 rd1
= (insn
>> 0) & 0xf;
1685 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1686 if (insn
& (1 << 21)) {
1687 if (insn
& (1 << 20))
1688 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1690 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1692 if (insn
& (1 << 20))
1693 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1695 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1697 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1698 gen_op_iwmmxt_set_mup();
1700 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1701 wrd
= (insn
>> 12) & 0xf;
1702 rd0
= (insn
>> 16) & 0xf;
1703 rd1
= (insn
>> 0) & 0xf;
1704 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1705 if (insn
& (1 << 21))
1706 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1708 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1709 if (!(insn
& (1 << 20))) {
1710 iwmmxt_load_reg(cpu_V1
, wrd
);
1711 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1713 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1714 gen_op_iwmmxt_set_mup();
1716 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1717 wrd
= (insn
>> 12) & 0xf;
1718 rd0
= (insn
>> 16) & 0xf;
1719 rd1
= (insn
>> 0) & 0xf;
1720 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1721 switch ((insn
>> 22) & 3) {
1723 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1726 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1729 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1734 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1735 gen_op_iwmmxt_set_mup();
1736 gen_op_iwmmxt_set_cup();
1738 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1739 wrd
= (insn
>> 12) & 0xf;
1740 rd0
= (insn
>> 16) & 0xf;
1741 rd1
= (insn
>> 0) & 0xf;
1742 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1743 if (insn
& (1 << 22)) {
1744 if (insn
& (1 << 20))
1745 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1747 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1749 if (insn
& (1 << 20))
1750 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1752 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1754 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1755 gen_op_iwmmxt_set_mup();
1756 gen_op_iwmmxt_set_cup();
1758 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1759 wrd
= (insn
>> 12) & 0xf;
1760 rd0
= (insn
>> 16) & 0xf;
1761 rd1
= (insn
>> 0) & 0xf;
1762 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1763 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1764 tcg_gen_andi_i32(tmp
, tmp
, 7);
1765 iwmmxt_load_reg(cpu_V1
, rd1
);
1766 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1767 tcg_temp_free_i32(tmp
);
1768 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1769 gen_op_iwmmxt_set_mup();
1771 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1772 if (((insn
>> 6) & 3) == 3)
1774 rd
= (insn
>> 12) & 0xf;
1775 wrd
= (insn
>> 16) & 0xf;
1776 tmp
= load_reg(s
, rd
);
1777 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1778 switch ((insn
>> 6) & 3) {
1780 tmp2
= tcg_const_i32(0xff);
1781 tmp3
= tcg_const_i32((insn
& 7) << 3);
1784 tmp2
= tcg_const_i32(0xffff);
1785 tmp3
= tcg_const_i32((insn
& 3) << 4);
1788 tmp2
= tcg_const_i32(0xffffffff);
1789 tmp3
= tcg_const_i32((insn
& 1) << 5);
1792 TCGV_UNUSED_I32(tmp2
);
1793 TCGV_UNUSED_I32(tmp3
);
1795 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1796 tcg_temp_free_i32(tmp3
);
1797 tcg_temp_free_i32(tmp2
);
1798 tcg_temp_free_i32(tmp
);
1799 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1800 gen_op_iwmmxt_set_mup();
1802 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1803 rd
= (insn
>> 12) & 0xf;
1804 wrd
= (insn
>> 16) & 0xf;
1805 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1807 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1808 tmp
= tcg_temp_new_i32();
1809 switch ((insn
>> 22) & 3) {
1811 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1812 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1814 tcg_gen_ext8s_i32(tmp
, tmp
);
1816 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1820 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1821 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1823 tcg_gen_ext16s_i32(tmp
, tmp
);
1825 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1829 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1830 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1833 store_reg(s
, rd
, tmp
);
1835 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1836 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1838 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1839 switch ((insn
>> 22) & 3) {
1841 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1844 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1847 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1850 tcg_gen_shli_i32(tmp
, tmp
, 28);
1852 tcg_temp_free_i32(tmp
);
1854 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1855 if (((insn
>> 6) & 3) == 3)
1857 rd
= (insn
>> 12) & 0xf;
1858 wrd
= (insn
>> 16) & 0xf;
1859 tmp
= load_reg(s
, rd
);
1860 switch ((insn
>> 6) & 3) {
1862 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1865 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1868 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1871 tcg_temp_free_i32(tmp
);
1872 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1873 gen_op_iwmmxt_set_mup();
1875 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1876 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1878 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1879 tmp2
= tcg_temp_new_i32();
1880 tcg_gen_mov_i32(tmp2
, tmp
);
1881 switch ((insn
>> 22) & 3) {
1883 for (i
= 0; i
< 7; i
++) {
1884 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1885 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1889 for (i
= 0; i
< 3; i
++) {
1890 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1891 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1895 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1896 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1900 tcg_temp_free_i32(tmp2
);
1901 tcg_temp_free_i32(tmp
);
1903 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1904 wrd
= (insn
>> 12) & 0xf;
1905 rd0
= (insn
>> 16) & 0xf;
1906 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1907 switch ((insn
>> 22) & 3) {
1909 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1912 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1915 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1920 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1921 gen_op_iwmmxt_set_mup();
1923 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1924 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1926 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1927 tmp2
= tcg_temp_new_i32();
1928 tcg_gen_mov_i32(tmp2
, tmp
);
1929 switch ((insn
>> 22) & 3) {
1931 for (i
= 0; i
< 7; i
++) {
1932 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1933 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1937 for (i
= 0; i
< 3; i
++) {
1938 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1939 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1943 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1944 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1948 tcg_temp_free_i32(tmp2
);
1949 tcg_temp_free_i32(tmp
);
1951 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1952 rd
= (insn
>> 12) & 0xf;
1953 rd0
= (insn
>> 16) & 0xf;
1954 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1956 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1957 tmp
= tcg_temp_new_i32();
1958 switch ((insn
>> 22) & 3) {
1960 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1963 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1966 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1969 store_reg(s
, rd
, tmp
);
1971 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1972 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1973 wrd
= (insn
>> 12) & 0xf;
1974 rd0
= (insn
>> 16) & 0xf;
1975 rd1
= (insn
>> 0) & 0xf;
1976 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1977 switch ((insn
>> 22) & 3) {
1979 if (insn
& (1 << 21))
1980 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1982 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1985 if (insn
& (1 << 21))
1986 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1988 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1991 if (insn
& (1 << 21))
1992 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1994 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1999 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2000 gen_op_iwmmxt_set_mup();
2001 gen_op_iwmmxt_set_cup();
2003 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2004 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2005 wrd
= (insn
>> 12) & 0xf;
2006 rd0
= (insn
>> 16) & 0xf;
2007 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2008 switch ((insn
>> 22) & 3) {
2010 if (insn
& (1 << 21))
2011 gen_op_iwmmxt_unpacklsb_M0();
2013 gen_op_iwmmxt_unpacklub_M0();
2016 if (insn
& (1 << 21))
2017 gen_op_iwmmxt_unpacklsw_M0();
2019 gen_op_iwmmxt_unpackluw_M0();
2022 if (insn
& (1 << 21))
2023 gen_op_iwmmxt_unpacklsl_M0();
2025 gen_op_iwmmxt_unpacklul_M0();
2030 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2031 gen_op_iwmmxt_set_mup();
2032 gen_op_iwmmxt_set_cup();
2034 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2035 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2036 wrd
= (insn
>> 12) & 0xf;
2037 rd0
= (insn
>> 16) & 0xf;
2038 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2039 switch ((insn
>> 22) & 3) {
2041 if (insn
& (1 << 21))
2042 gen_op_iwmmxt_unpackhsb_M0();
2044 gen_op_iwmmxt_unpackhub_M0();
2047 if (insn
& (1 << 21))
2048 gen_op_iwmmxt_unpackhsw_M0();
2050 gen_op_iwmmxt_unpackhuw_M0();
2053 if (insn
& (1 << 21))
2054 gen_op_iwmmxt_unpackhsl_M0();
2056 gen_op_iwmmxt_unpackhul_M0();
2061 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2062 gen_op_iwmmxt_set_mup();
2063 gen_op_iwmmxt_set_cup();
2065 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2066 case 0x214: case 0x614: case 0xa14: case 0xe14:
2067 if (((insn
>> 22) & 3) == 0)
2069 wrd
= (insn
>> 12) & 0xf;
2070 rd0
= (insn
>> 16) & 0xf;
2071 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2072 tmp
= tcg_temp_new_i32();
2073 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2074 tcg_temp_free_i32(tmp
);
2077 switch ((insn
>> 22) & 3) {
2079 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2082 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2085 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2088 tcg_temp_free_i32(tmp
);
2089 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2090 gen_op_iwmmxt_set_mup();
2091 gen_op_iwmmxt_set_cup();
2093 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2094 case 0x014: case 0x414: case 0x814: case 0xc14:
2095 if (((insn
>> 22) & 3) == 0)
2097 wrd
= (insn
>> 12) & 0xf;
2098 rd0
= (insn
>> 16) & 0xf;
2099 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2100 tmp
= tcg_temp_new_i32();
2101 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2102 tcg_temp_free_i32(tmp
);
2105 switch ((insn
>> 22) & 3) {
2107 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2110 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2113 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2116 tcg_temp_free_i32(tmp
);
2117 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2118 gen_op_iwmmxt_set_mup();
2119 gen_op_iwmmxt_set_cup();
2121 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2122 case 0x114: case 0x514: case 0x914: case 0xd14:
2123 if (((insn
>> 22) & 3) == 0)
2125 wrd
= (insn
>> 12) & 0xf;
2126 rd0
= (insn
>> 16) & 0xf;
2127 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2128 tmp
= tcg_temp_new_i32();
2129 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2130 tcg_temp_free_i32(tmp
);
2133 switch ((insn
>> 22) & 3) {
2135 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2138 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2141 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2144 tcg_temp_free_i32(tmp
);
2145 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2146 gen_op_iwmmxt_set_mup();
2147 gen_op_iwmmxt_set_cup();
2149 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2150 case 0x314: case 0x714: case 0xb14: case 0xf14:
2151 if (((insn
>> 22) & 3) == 0)
2153 wrd
= (insn
>> 12) & 0xf;
2154 rd0
= (insn
>> 16) & 0xf;
2155 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2156 tmp
= tcg_temp_new_i32();
2157 switch ((insn
>> 22) & 3) {
2159 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2160 tcg_temp_free_i32(tmp
);
2163 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2166 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2167 tcg_temp_free_i32(tmp
);
2170 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2173 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2174 tcg_temp_free_i32(tmp
);
2177 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2180 tcg_temp_free_i32(tmp
);
2181 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2182 gen_op_iwmmxt_set_mup();
2183 gen_op_iwmmxt_set_cup();
2185 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2186 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2187 wrd
= (insn
>> 12) & 0xf;
2188 rd0
= (insn
>> 16) & 0xf;
2189 rd1
= (insn
>> 0) & 0xf;
2190 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2191 switch ((insn
>> 22) & 3) {
2193 if (insn
& (1 << 21))
2194 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2196 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2199 if (insn
& (1 << 21))
2200 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2202 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2205 if (insn
& (1 << 21))
2206 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2208 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2213 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2214 gen_op_iwmmxt_set_mup();
2216 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2217 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2218 wrd
= (insn
>> 12) & 0xf;
2219 rd0
= (insn
>> 16) & 0xf;
2220 rd1
= (insn
>> 0) & 0xf;
2221 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2222 switch ((insn
>> 22) & 3) {
2224 if (insn
& (1 << 21))
2225 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2227 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2230 if (insn
& (1 << 21))
2231 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2233 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2236 if (insn
& (1 << 21))
2237 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2239 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2244 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2245 gen_op_iwmmxt_set_mup();
2247 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2248 case 0x402: case 0x502: case 0x602: case 0x702:
2249 wrd
= (insn
>> 12) & 0xf;
2250 rd0
= (insn
>> 16) & 0xf;
2251 rd1
= (insn
>> 0) & 0xf;
2252 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2253 tmp
= tcg_const_i32((insn
>> 20) & 3);
2254 iwmmxt_load_reg(cpu_V1
, rd1
);
2255 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2256 tcg_temp_free_i32(tmp
);
2257 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2258 gen_op_iwmmxt_set_mup();
2260 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2261 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2262 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2263 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2264 wrd
= (insn
>> 12) & 0xf;
2265 rd0
= (insn
>> 16) & 0xf;
2266 rd1
= (insn
>> 0) & 0xf;
2267 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2268 switch ((insn
>> 20) & 0xf) {
2270 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2273 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2276 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2279 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2282 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2285 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2288 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2291 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2294 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2299 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2300 gen_op_iwmmxt_set_mup();
2301 gen_op_iwmmxt_set_cup();
2303 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2304 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2305 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2306 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2307 wrd
= (insn
>> 12) & 0xf;
2308 rd0
= (insn
>> 16) & 0xf;
2309 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2310 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2311 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2312 tcg_temp_free_i32(tmp
);
2313 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2314 gen_op_iwmmxt_set_mup();
2315 gen_op_iwmmxt_set_cup();
2317 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2318 case 0x418: case 0x518: case 0x618: case 0x718:
2319 case 0x818: case 0x918: case 0xa18: case 0xb18:
2320 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2321 wrd
= (insn
>> 12) & 0xf;
2322 rd0
= (insn
>> 16) & 0xf;
2323 rd1
= (insn
>> 0) & 0xf;
2324 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2325 switch ((insn
>> 20) & 0xf) {
2327 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2330 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2333 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2336 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2339 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2342 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2345 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2348 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2351 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2356 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2357 gen_op_iwmmxt_set_mup();
2358 gen_op_iwmmxt_set_cup();
2360 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2361 case 0x408: case 0x508: case 0x608: case 0x708:
2362 case 0x808: case 0x908: case 0xa08: case 0xb08:
2363 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2364 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2366 wrd
= (insn
>> 12) & 0xf;
2367 rd0
= (insn
>> 16) & 0xf;
2368 rd1
= (insn
>> 0) & 0xf;
2369 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2370 switch ((insn
>> 22) & 3) {
2372 if (insn
& (1 << 21))
2373 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2375 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2378 if (insn
& (1 << 21))
2379 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2381 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2384 if (insn
& (1 << 21))
2385 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2387 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2390 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2391 gen_op_iwmmxt_set_mup();
2392 gen_op_iwmmxt_set_cup();
2394 case 0x201: case 0x203: case 0x205: case 0x207:
2395 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2396 case 0x211: case 0x213: case 0x215: case 0x217:
2397 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2398 wrd
= (insn
>> 5) & 0xf;
2399 rd0
= (insn
>> 12) & 0xf;
2400 rd1
= (insn
>> 0) & 0xf;
2401 if (rd0
== 0xf || rd1
== 0xf)
2403 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2404 tmp
= load_reg(s
, rd0
);
2405 tmp2
= load_reg(s
, rd1
);
2406 switch ((insn
>> 16) & 0xf) {
2407 case 0x0: /* TMIA */
2408 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2410 case 0x8: /* TMIAPH */
2411 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2413 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2414 if (insn
& (1 << 16))
2415 tcg_gen_shri_i32(tmp
, tmp
, 16);
2416 if (insn
& (1 << 17))
2417 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2418 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2421 tcg_temp_free_i32(tmp2
);
2422 tcg_temp_free_i32(tmp
);
2425 tcg_temp_free_i32(tmp2
);
2426 tcg_temp_free_i32(tmp
);
2427 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2428 gen_op_iwmmxt_set_mup();
2437 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2438 (ie. an undefined instruction). */
2439 static int disas_dsp_insn(CPUARMState
*env
, DisasContext
*s
, uint32_t insn
)
2441 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2444 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2445 /* Multiply with Internal Accumulate Format */
2446 rd0
= (insn
>> 12) & 0xf;
2448 acc
= (insn
>> 5) & 7;
2453 tmp
= load_reg(s
, rd0
);
2454 tmp2
= load_reg(s
, rd1
);
2455 switch ((insn
>> 16) & 0xf) {
2457 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2459 case 0x8: /* MIAPH */
2460 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2462 case 0xc: /* MIABB */
2463 case 0xd: /* MIABT */
2464 case 0xe: /* MIATB */
2465 case 0xf: /* MIATT */
2466 if (insn
& (1 << 16))
2467 tcg_gen_shri_i32(tmp
, tmp
, 16);
2468 if (insn
& (1 << 17))
2469 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2470 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2475 tcg_temp_free_i32(tmp2
);
2476 tcg_temp_free_i32(tmp
);
2478 gen_op_iwmmxt_movq_wRn_M0(acc
);
2482 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2483 /* Internal Accumulator Access Format */
2484 rdhi
= (insn
>> 16) & 0xf;
2485 rdlo
= (insn
>> 12) & 0xf;
2491 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2492 iwmmxt_load_reg(cpu_V0
, acc
);
2493 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2494 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2495 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2496 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2498 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2499 iwmmxt_store_reg(cpu_V0
, acc
);
2507 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2508 #define VFP_SREG(insn, bigbit, smallbit) \
2509 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2510 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2511 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2512 reg = (((insn) >> (bigbit)) & 0x0f) \
2513 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2515 if (insn & (1 << (smallbit))) \
2517 reg = ((insn) >> (bigbit)) & 0x0f; \
2520 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2521 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2522 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2523 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2524 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2525 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2527 /* Move between integer and VFP cores. */
2528 static TCGv_i32
gen_vfp_mrs(void)
2530 TCGv_i32 tmp
= tcg_temp_new_i32();
2531 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2535 static void gen_vfp_msr(TCGv_i32 tmp
)
2537 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2538 tcg_temp_free_i32(tmp
);
2541 static void gen_neon_dup_u8(TCGv_i32 var
, int shift
)
2543 TCGv_i32 tmp
= tcg_temp_new_i32();
2545 tcg_gen_shri_i32(var
, var
, shift
);
2546 tcg_gen_ext8u_i32(var
, var
);
2547 tcg_gen_shli_i32(tmp
, var
, 8);
2548 tcg_gen_or_i32(var
, var
, tmp
);
2549 tcg_gen_shli_i32(tmp
, var
, 16);
2550 tcg_gen_or_i32(var
, var
, tmp
);
2551 tcg_temp_free_i32(tmp
);
2554 static void gen_neon_dup_low16(TCGv_i32 var
)
2556 TCGv_i32 tmp
= tcg_temp_new_i32();
2557 tcg_gen_ext16u_i32(var
, var
);
2558 tcg_gen_shli_i32(tmp
, var
, 16);
2559 tcg_gen_or_i32(var
, var
, tmp
);
2560 tcg_temp_free_i32(tmp
);
2563 static void gen_neon_dup_high16(TCGv_i32 var
)
2565 TCGv_i32 tmp
= tcg_temp_new_i32();
2566 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2567 tcg_gen_shri_i32(tmp
, var
, 16);
2568 tcg_gen_or_i32(var
, var
, tmp
);
2569 tcg_temp_free_i32(tmp
);
2572 static TCGv_i32
gen_load_and_replicate(DisasContext
*s
, TCGv_i32 addr
, int size
)
2574 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2575 TCGv_i32 tmp
= tcg_temp_new_i32();
2578 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
2579 gen_neon_dup_u8(tmp
, 0);
2582 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
2583 gen_neon_dup_low16(tmp
);
2586 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
2588 default: /* Avoid compiler warnings. */
2594 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2595 (ie. an undefined instruction). */
2596 static int disas_vfp_insn(CPUARMState
* env
, DisasContext
*s
, uint32_t insn
)
2598 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2604 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2607 if (!s
->vfp_enabled
) {
2608 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2609 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2611 rn
= (insn
>> 16) & 0xf;
2612 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2613 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2616 dp
= ((insn
& 0xf00) == 0xb00);
2617 switch ((insn
>> 24) & 0xf) {
2619 if (insn
& (1 << 4)) {
2620 /* single register transfer */
2621 rd
= (insn
>> 12) & 0xf;
2626 VFP_DREG_N(rn
, insn
);
2629 if (insn
& 0x00c00060
2630 && !arm_feature(env
, ARM_FEATURE_NEON
))
2633 pass
= (insn
>> 21) & 1;
2634 if (insn
& (1 << 22)) {
2636 offset
= ((insn
>> 5) & 3) * 8;
2637 } else if (insn
& (1 << 5)) {
2639 offset
= (insn
& (1 << 6)) ? 16 : 0;
2644 if (insn
& ARM_CP_RW_BIT
) {
2646 tmp
= neon_load_reg(rn
, pass
);
2650 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2651 if (insn
& (1 << 23))
2657 if (insn
& (1 << 23)) {
2659 tcg_gen_shri_i32(tmp
, tmp
, 16);
2665 tcg_gen_sari_i32(tmp
, tmp
, 16);
2674 store_reg(s
, rd
, tmp
);
2677 tmp
= load_reg(s
, rd
);
2678 if (insn
& (1 << 23)) {
2681 gen_neon_dup_u8(tmp
, 0);
2682 } else if (size
== 1) {
2683 gen_neon_dup_low16(tmp
);
2685 for (n
= 0; n
<= pass
* 2; n
++) {
2686 tmp2
= tcg_temp_new_i32();
2687 tcg_gen_mov_i32(tmp2
, tmp
);
2688 neon_store_reg(rn
, n
, tmp2
);
2690 neon_store_reg(rn
, n
, tmp
);
2695 tmp2
= neon_load_reg(rn
, pass
);
2696 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
, offset
, 8);
2697 tcg_temp_free_i32(tmp2
);
2700 tmp2
= neon_load_reg(rn
, pass
);
2701 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
, offset
, 16);
2702 tcg_temp_free_i32(tmp2
);
2707 neon_store_reg(rn
, pass
, tmp
);
2711 if ((insn
& 0x6f) != 0x00)
2713 rn
= VFP_SREG_N(insn
);
2714 if (insn
& ARM_CP_RW_BIT
) {
2716 if (insn
& (1 << 21)) {
2717 /* system register */
2722 /* VFP2 allows access to FSID from userspace.
2723 VFP3 restricts all id registers to privileged
2726 && arm_feature(env
, ARM_FEATURE_VFP3
))
2728 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2733 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2735 case ARM_VFP_FPINST
:
2736 case ARM_VFP_FPINST2
:
2737 /* Not present in VFP3. */
2739 || arm_feature(env
, ARM_FEATURE_VFP3
))
2741 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2745 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2746 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2748 tmp
= tcg_temp_new_i32();
2749 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2755 || !arm_feature(env
, ARM_FEATURE_MVFR
))
2757 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2763 gen_mov_F0_vreg(0, rn
);
2764 tmp
= gen_vfp_mrs();
2767 /* Set the 4 flag bits in the CPSR. */
2769 tcg_temp_free_i32(tmp
);
2771 store_reg(s
, rd
, tmp
);
2775 if (insn
& (1 << 21)) {
2777 /* system register */
2782 /* Writes are ignored. */
2785 tmp
= load_reg(s
, rd
);
2786 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2787 tcg_temp_free_i32(tmp
);
2793 /* TODO: VFP subarchitecture support.
2794 * For now, keep the EN bit only */
2795 tmp
= load_reg(s
, rd
);
2796 tcg_gen_andi_i32(tmp
, tmp
, 1 << 30);
2797 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2800 case ARM_VFP_FPINST
:
2801 case ARM_VFP_FPINST2
:
2802 tmp
= load_reg(s
, rd
);
2803 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2809 tmp
= load_reg(s
, rd
);
2811 gen_mov_vreg_F0(0, rn
);
2816 /* data processing */
2817 /* The opcode is in bits 23, 21, 20 and 6. */
2818 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2822 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2824 /* rn is register number */
2825 VFP_DREG_N(rn
, insn
);
2828 if (op
== 15 && (rn
== 15 || ((rn
& 0x1c) == 0x18))) {
2829 /* Integer or single precision destination. */
2830 rd
= VFP_SREG_D(insn
);
2832 VFP_DREG_D(rd
, insn
);
2835 (((rn
& 0x1c) == 0x10) || ((rn
& 0x14) == 0x14))) {
2836 /* VCVT from int is always from S reg regardless of dp bit.
2837 * VCVT with immediate frac_bits has same format as SREG_M
2839 rm
= VFP_SREG_M(insn
);
2841 VFP_DREG_M(rm
, insn
);
2844 rn
= VFP_SREG_N(insn
);
2845 if (op
== 15 && rn
== 15) {
2846 /* Double precision destination. */
2847 VFP_DREG_D(rd
, insn
);
2849 rd
= VFP_SREG_D(insn
);
2851 /* NB that we implicitly rely on the encoding for the frac_bits
2852 * in VCVT of fixed to float being the same as that of an SREG_M
2854 rm
= VFP_SREG_M(insn
);
2857 veclen
= s
->vec_len
;
2858 if (op
== 15 && rn
> 3)
2861 /* Shut up compiler warnings. */
2872 /* Figure out what type of vector operation this is. */
2873 if ((rd
& bank_mask
) == 0) {
2878 delta_d
= (s
->vec_stride
>> 1) + 1;
2880 delta_d
= s
->vec_stride
+ 1;
2882 if ((rm
& bank_mask
) == 0) {
2883 /* mixed scalar/vector */
2892 /* Load the initial operands. */
2897 /* Integer source */
2898 gen_mov_F0_vreg(0, rm
);
2903 gen_mov_F0_vreg(dp
, rd
);
2904 gen_mov_F1_vreg(dp
, rm
);
2908 /* Compare with zero */
2909 gen_mov_F0_vreg(dp
, rd
);
2920 /* Source and destination the same. */
2921 gen_mov_F0_vreg(dp
, rd
);
2927 /* VCVTB, VCVTT: only present with the halfprec extension,
2928 * UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
2930 if (dp
|| !arm_feature(env
, ARM_FEATURE_VFP_FP16
)) {
2933 /* Otherwise fall through */
2935 /* One source operand. */
2936 gen_mov_F0_vreg(dp
, rm
);
2940 /* Two source operands. */
2941 gen_mov_F0_vreg(dp
, rn
);
2942 gen_mov_F1_vreg(dp
, rm
);
2946 /* Perform the calculation. */
2948 case 0: /* VMLA: fd + (fn * fm) */
2949 /* Note that order of inputs to the add matters for NaNs */
2951 gen_mov_F0_vreg(dp
, rd
);
2954 case 1: /* VMLS: fd + -(fn * fm) */
2957 gen_mov_F0_vreg(dp
, rd
);
2960 case 2: /* VNMLS: -fd + (fn * fm) */
2961 /* Note that it isn't valid to replace (-A + B) with (B - A)
2962 * or similar plausible looking simplifications
2963 * because this will give wrong results for NaNs.
2966 gen_mov_F0_vreg(dp
, rd
);
2970 case 3: /* VNMLA: -fd + -(fn * fm) */
2973 gen_mov_F0_vreg(dp
, rd
);
2977 case 4: /* mul: fn * fm */
2980 case 5: /* nmul: -(fn * fm) */
2984 case 6: /* add: fn + fm */
2987 case 7: /* sub: fn - fm */
2990 case 8: /* div: fn / fm */
2993 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
2994 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
2995 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
2996 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
2997 /* These are fused multiply-add, and must be done as one
2998 * floating point operation with no rounding between the
2999 * multiplication and addition steps.
3000 * NB that doing the negations here as separate steps is
3001 * correct : an input NaN should come out with its sign bit
3002 * flipped if it is a negated-input.
3004 if (!arm_feature(env
, ARM_FEATURE_VFP4
)) {
3012 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
3014 frd
= tcg_temp_new_i64();
3015 tcg_gen_ld_f64(frd
, cpu_env
, vfp_reg_offset(dp
, rd
));
3018 gen_helper_vfp_negd(frd
, frd
);
3020 fpst
= get_fpstatus_ptr(0);
3021 gen_helper_vfp_muladdd(cpu_F0d
, cpu_F0d
,
3022 cpu_F1d
, frd
, fpst
);
3023 tcg_temp_free_ptr(fpst
);
3024 tcg_temp_free_i64(frd
);
3030 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
3032 frd
= tcg_temp_new_i32();
3033 tcg_gen_ld_f32(frd
, cpu_env
, vfp_reg_offset(dp
, rd
));
3035 gen_helper_vfp_negs(frd
, frd
);
3037 fpst
= get_fpstatus_ptr(0);
3038 gen_helper_vfp_muladds(cpu_F0s
, cpu_F0s
,
3039 cpu_F1s
, frd
, fpst
);
3040 tcg_temp_free_ptr(fpst
);
3041 tcg_temp_free_i32(frd
);
3044 case 14: /* fconst */
3045 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3048 n
= (insn
<< 12) & 0x80000000;
3049 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3056 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3063 tcg_gen_movi_i32(cpu_F0s
, n
);
3066 case 15: /* extension space */
3080 case 4: /* vcvtb.f32.f16 */
3081 tmp
= gen_vfp_mrs();
3082 tcg_gen_ext16u_i32(tmp
, tmp
);
3083 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3084 tcg_temp_free_i32(tmp
);
3086 case 5: /* vcvtt.f32.f16 */
3087 tmp
= gen_vfp_mrs();
3088 tcg_gen_shri_i32(tmp
, tmp
, 16);
3089 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3090 tcg_temp_free_i32(tmp
);
3092 case 6: /* vcvtb.f16.f32 */
3093 tmp
= tcg_temp_new_i32();
3094 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3095 gen_mov_F0_vreg(0, rd
);
3096 tmp2
= gen_vfp_mrs();
3097 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
3098 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3099 tcg_temp_free_i32(tmp2
);
3102 case 7: /* vcvtt.f16.f32 */
3103 tmp
= tcg_temp_new_i32();
3104 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3105 tcg_gen_shli_i32(tmp
, tmp
, 16);
3106 gen_mov_F0_vreg(0, rd
);
3107 tmp2
= gen_vfp_mrs();
3108 tcg_gen_ext16u_i32(tmp2
, tmp2
);
3109 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3110 tcg_temp_free_i32(tmp2
);
3122 case 11: /* cmpez */
3126 case 15: /* single<->double conversion */
3128 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3130 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3132 case 16: /* fuito */
3133 gen_vfp_uito(dp
, 0);
3135 case 17: /* fsito */
3136 gen_vfp_sito(dp
, 0);
3138 case 20: /* fshto */
3139 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3141 gen_vfp_shto(dp
, 16 - rm
, 0);
3143 case 21: /* fslto */
3144 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3146 gen_vfp_slto(dp
, 32 - rm
, 0);
3148 case 22: /* fuhto */
3149 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3151 gen_vfp_uhto(dp
, 16 - rm
, 0);
3153 case 23: /* fulto */
3154 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3156 gen_vfp_ulto(dp
, 32 - rm
, 0);
3158 case 24: /* ftoui */
3159 gen_vfp_toui(dp
, 0);
3161 case 25: /* ftouiz */
3162 gen_vfp_touiz(dp
, 0);
3164 case 26: /* ftosi */
3165 gen_vfp_tosi(dp
, 0);
3167 case 27: /* ftosiz */
3168 gen_vfp_tosiz(dp
, 0);
3170 case 28: /* ftosh */
3171 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3173 gen_vfp_tosh(dp
, 16 - rm
, 0);
3175 case 29: /* ftosl */
3176 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3178 gen_vfp_tosl(dp
, 32 - rm
, 0);
3180 case 30: /* ftouh */
3181 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3183 gen_vfp_touh(dp
, 16 - rm
, 0);
3185 case 31: /* ftoul */
3186 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3188 gen_vfp_toul(dp
, 32 - rm
, 0);
3190 default: /* undefined */
3194 default: /* undefined */
3198 /* Write back the result. */
3199 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3200 ; /* Comparison, do nothing. */
3201 else if (op
== 15 && dp
&& ((rn
& 0x1c) == 0x18))
3202 /* VCVT double to int: always integer result. */
3203 gen_mov_vreg_F0(0, rd
);
3204 else if (op
== 15 && rn
== 15)
3206 gen_mov_vreg_F0(!dp
, rd
);
3208 gen_mov_vreg_F0(dp
, rd
);
3210 /* break out of the loop if we have finished */
3214 if (op
== 15 && delta_m
== 0) {
3215 /* single source one-many */
3217 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3219 gen_mov_vreg_F0(dp
, rd
);
3223 /* Setup the next operands. */
3225 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3229 /* One source operand. */
3230 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3232 gen_mov_F0_vreg(dp
, rm
);
3234 /* Two source operands. */
3235 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3237 gen_mov_F0_vreg(dp
, rn
);
3239 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3241 gen_mov_F1_vreg(dp
, rm
);
3249 if ((insn
& 0x03e00000) == 0x00400000) {
3250 /* two-register transfer */
3251 rn
= (insn
>> 16) & 0xf;
3252 rd
= (insn
>> 12) & 0xf;
3254 VFP_DREG_M(rm
, insn
);
3256 rm
= VFP_SREG_M(insn
);
3259 if (insn
& ARM_CP_RW_BIT
) {
3262 gen_mov_F0_vreg(0, rm
* 2);
3263 tmp
= gen_vfp_mrs();
3264 store_reg(s
, rd
, tmp
);
3265 gen_mov_F0_vreg(0, rm
* 2 + 1);
3266 tmp
= gen_vfp_mrs();
3267 store_reg(s
, rn
, tmp
);
3269 gen_mov_F0_vreg(0, rm
);
3270 tmp
= gen_vfp_mrs();
3271 store_reg(s
, rd
, tmp
);
3272 gen_mov_F0_vreg(0, rm
+ 1);
3273 tmp
= gen_vfp_mrs();
3274 store_reg(s
, rn
, tmp
);
3279 tmp
= load_reg(s
, rd
);
3281 gen_mov_vreg_F0(0, rm
* 2);
3282 tmp
= load_reg(s
, rn
);
3284 gen_mov_vreg_F0(0, rm
* 2 + 1);
3286 tmp
= load_reg(s
, rd
);
3288 gen_mov_vreg_F0(0, rm
);
3289 tmp
= load_reg(s
, rn
);
3291 gen_mov_vreg_F0(0, rm
+ 1);
3296 rn
= (insn
>> 16) & 0xf;
3298 VFP_DREG_D(rd
, insn
);
3300 rd
= VFP_SREG_D(insn
);
3301 if ((insn
& 0x01200000) == 0x01000000) {
3302 /* Single load/store */
3303 offset
= (insn
& 0xff) << 2;
3304 if ((insn
& (1 << 23)) == 0)
3306 if (s
->thumb
&& rn
== 15) {
3307 /* This is actually UNPREDICTABLE */
3308 addr
= tcg_temp_new_i32();
3309 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3311 addr
= load_reg(s
, rn
);
3313 tcg_gen_addi_i32(addr
, addr
, offset
);
3314 if (insn
& (1 << 20)) {
3315 gen_vfp_ld(s
, dp
, addr
);
3316 gen_mov_vreg_F0(dp
, rd
);
3318 gen_mov_F0_vreg(dp
, rd
);
3319 gen_vfp_st(s
, dp
, addr
);
3321 tcg_temp_free_i32(addr
);
3323 /* load/store multiple */
3324 int w
= insn
& (1 << 21);
3326 n
= (insn
>> 1) & 0x7f;
3330 if (w
&& !(((insn
>> 23) ^ (insn
>> 24)) & 1)) {
3331 /* P == U , W == 1 => UNDEF */
3334 if (n
== 0 || (rd
+ n
) > 32 || (dp
&& n
> 16)) {
3335 /* UNPREDICTABLE cases for bad immediates: we choose to
3336 * UNDEF to avoid generating huge numbers of TCG ops
3340 if (rn
== 15 && w
) {
3341 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3345 if (s
->thumb
&& rn
== 15) {
3346 /* This is actually UNPREDICTABLE */
3347 addr
= tcg_temp_new_i32();
3348 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3350 addr
= load_reg(s
, rn
);
3352 if (insn
& (1 << 24)) /* pre-decrement */
3353 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3359 for (i
= 0; i
< n
; i
++) {
3360 if (insn
& ARM_CP_RW_BIT
) {
3362 gen_vfp_ld(s
, dp
, addr
);
3363 gen_mov_vreg_F0(dp
, rd
+ i
);
3366 gen_mov_F0_vreg(dp
, rd
+ i
);
3367 gen_vfp_st(s
, dp
, addr
);
3369 tcg_gen_addi_i32(addr
, addr
, offset
);
3373 if (insn
& (1 << 24))
3374 offset
= -offset
* n
;
3375 else if (dp
&& (insn
& 1))
3381 tcg_gen_addi_i32(addr
, addr
, offset
);
3382 store_reg(s
, rn
, addr
);
3384 tcg_temp_free_i32(addr
);
3390 /* Should never happen. */
3396 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3398 TranslationBlock
*tb
;
3401 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3403 gen_set_pc_im(dest
);
3404 tcg_gen_exit_tb((tcg_target_long
)tb
+ n
);
3406 gen_set_pc_im(dest
);
3411 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3413 if (unlikely(s
->singlestep_enabled
)) {
3414 /* An indirect jump so that we still trigger the debug exception. */
3419 gen_goto_tb(s
, 0, dest
);
3420 s
->is_jmp
= DISAS_TB_JUMP
;
3424 static inline void gen_mulxy(TCGv_i32 t0
, TCGv_i32 t1
, int x
, int y
)
3427 tcg_gen_sari_i32(t0
, t0
, 16);
3431 tcg_gen_sari_i32(t1
, t1
, 16);
3434 tcg_gen_mul_i32(t0
, t0
, t1
);
3437 /* Return the mask of PSR bits set by a MSR instruction. */
3438 static uint32_t msr_mask(CPUARMState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3442 if (flags
& (1 << 0))
3444 if (flags
& (1 << 1))
3446 if (flags
& (1 << 2))
3448 if (flags
& (1 << 3))
3451 /* Mask out undefined bits. */
3452 mask
&= ~CPSR_RESERVED
;
3453 if (!arm_feature(env
, ARM_FEATURE_V4T
))
3455 if (!arm_feature(env
, ARM_FEATURE_V5
))
3456 mask
&= ~CPSR_Q
; /* V5TE in reality*/
3457 if (!arm_feature(env
, ARM_FEATURE_V6
))
3458 mask
&= ~(CPSR_E
| CPSR_GE
);
3459 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3461 /* Mask out execution state bits. */
3464 /* Mask out privileged bits. */
3470 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3471 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv_i32 t0
)
3475 /* ??? This is also undefined in system mode. */
3479 tmp
= load_cpu_field(spsr
);
3480 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3481 tcg_gen_andi_i32(t0
, t0
, mask
);
3482 tcg_gen_or_i32(tmp
, tmp
, t0
);
3483 store_cpu_field(tmp
, spsr
);
3485 gen_set_cpsr(t0
, mask
);
3487 tcg_temp_free_i32(t0
);
3492 /* Returns nonzero if access to the PSR is not permitted. */
3493 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3496 tmp
= tcg_temp_new_i32();
3497 tcg_gen_movi_i32(tmp
, val
);
3498 return gen_set_psr(s
, mask
, spsr
, tmp
);
3501 /* Generate an old-style exception return. Marks pc as dead. */
3502 static void gen_exception_return(DisasContext
*s
, TCGv_i32 pc
)
3505 store_reg(s
, 15, pc
);
3506 tmp
= load_cpu_field(spsr
);
3507 gen_set_cpsr(tmp
, 0xffffffff);
3508 tcg_temp_free_i32(tmp
);
3509 s
->is_jmp
= DISAS_UPDATE
;
3512 /* Generate a v6 exception return. Marks both values as dead. */
3513 static void gen_rfe(DisasContext
*s
, TCGv_i32 pc
, TCGv_i32 cpsr
)
3515 gen_set_cpsr(cpsr
, 0xffffffff);
3516 tcg_temp_free_i32(cpsr
);
3517 store_reg(s
, 15, pc
);
3518 s
->is_jmp
= DISAS_UPDATE
;
3522 gen_set_condexec (DisasContext
*s
)
3524 if (s
->condexec_mask
) {
3525 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3526 TCGv_i32 tmp
= tcg_temp_new_i32();
3527 tcg_gen_movi_i32(tmp
, val
);
3528 store_cpu_field(tmp
, condexec_bits
);
3532 static void gen_exception_insn(DisasContext
*s
, int offset
, int excp
)
3534 gen_set_condexec(s
);
3535 gen_set_pc_im(s
->pc
- offset
);
3536 gen_exception(excp
);
3537 s
->is_jmp
= DISAS_JUMP
;
3540 static void gen_nop_hint(DisasContext
*s
, int val
)
3544 gen_set_pc_im(s
->pc
);
3545 s
->is_jmp
= DISAS_WFI
;
3549 /* TODO: Implement SEV and WFE. May help SMP performance. */
3555 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3557 static inline void gen_neon_add(int size
, TCGv_i32 t0
, TCGv_i32 t1
)
3560 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3561 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3562 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3567 static inline void gen_neon_rsb(int size
, TCGv_i32 t0
, TCGv_i32 t1
)
3570 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3571 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3572 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3577 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3578 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3579 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3580 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3581 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3583 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3584 switch ((size << 1) | u) { \
3586 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3589 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3592 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3595 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3598 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3601 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3603 default: return 1; \
3606 #define GEN_NEON_INTEGER_OP(name) do { \
3607 switch ((size << 1) | u) { \
3609 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3612 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3615 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3618 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3621 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3624 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3626 default: return 1; \
3629 static TCGv_i32
neon_load_scratch(int scratch
)
3631 TCGv_i32 tmp
= tcg_temp_new_i32();
3632 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3636 static void neon_store_scratch(int scratch
, TCGv_i32 var
)
3638 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3639 tcg_temp_free_i32(var
);
3642 static inline TCGv_i32
neon_get_scalar(int size
, int reg
)
3646 tmp
= neon_load_reg(reg
& 7, reg
>> 4);
3648 gen_neon_dup_high16(tmp
);
3650 gen_neon_dup_low16(tmp
);
3653 tmp
= neon_load_reg(reg
& 15, reg
>> 4);
3658 static int gen_neon_unzip(int rd
, int rm
, int size
, int q
)
3661 if (!q
&& size
== 2) {
3664 tmp
= tcg_const_i32(rd
);
3665 tmp2
= tcg_const_i32(rm
);
3669 gen_helper_neon_qunzip8(cpu_env
, tmp
, tmp2
);
3672 gen_helper_neon_qunzip16(cpu_env
, tmp
, tmp2
);
3675 gen_helper_neon_qunzip32(cpu_env
, tmp
, tmp2
);
3683 gen_helper_neon_unzip8(cpu_env
, tmp
, tmp2
);
3686 gen_helper_neon_unzip16(cpu_env
, tmp
, tmp2
);
3692 tcg_temp_free_i32(tmp
);
3693 tcg_temp_free_i32(tmp2
);
3697 static int gen_neon_zip(int rd
, int rm
, int size
, int q
)
3700 if (!q
&& size
== 2) {
3703 tmp
= tcg_const_i32(rd
);
3704 tmp2
= tcg_const_i32(rm
);
3708 gen_helper_neon_qzip8(cpu_env
, tmp
, tmp2
);
3711 gen_helper_neon_qzip16(cpu_env
, tmp
, tmp2
);
3714 gen_helper_neon_qzip32(cpu_env
, tmp
, tmp2
);
3722 gen_helper_neon_zip8(cpu_env
, tmp
, tmp2
);
3725 gen_helper_neon_zip16(cpu_env
, tmp
, tmp2
);
3731 tcg_temp_free_i32(tmp
);
3732 tcg_temp_free_i32(tmp2
);
3736 static void gen_neon_trn_u8(TCGv_i32 t0
, TCGv_i32 t1
)
3740 rd
= tcg_temp_new_i32();
3741 tmp
= tcg_temp_new_i32();
3743 tcg_gen_shli_i32(rd
, t0
, 8);
3744 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3745 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3746 tcg_gen_or_i32(rd
, rd
, tmp
);
3748 tcg_gen_shri_i32(t1
, t1
, 8);
3749 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3750 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3751 tcg_gen_or_i32(t1
, t1
, tmp
);
3752 tcg_gen_mov_i32(t0
, rd
);
3754 tcg_temp_free_i32(tmp
);
3755 tcg_temp_free_i32(rd
);
3758 static void gen_neon_trn_u16(TCGv_i32 t0
, TCGv_i32 t1
)
3762 rd
= tcg_temp_new_i32();
3763 tmp
= tcg_temp_new_i32();
3765 tcg_gen_shli_i32(rd
, t0
, 16);
3766 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3767 tcg_gen_or_i32(rd
, rd
, tmp
);
3768 tcg_gen_shri_i32(t1
, t1
, 16);
3769 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3770 tcg_gen_or_i32(t1
, t1
, tmp
);
3771 tcg_gen_mov_i32(t0
, rd
);
3773 tcg_temp_free_i32(tmp
);
3774 tcg_temp_free_i32(rd
);
3782 } neon_ls_element_type
[11] = {
3796 /* Translate a NEON load/store element instruction. Return nonzero if the
3797 instruction is invalid. */
3798 static int disas_neon_ls_insn(CPUARMState
* env
, DisasContext
*s
, uint32_t insn
)
3817 if (!s
->vfp_enabled
)
3819 VFP_DREG_D(rd
, insn
);
3820 rn
= (insn
>> 16) & 0xf;
3822 load
= (insn
& (1 << 21)) != 0;
3823 if ((insn
& (1 << 23)) == 0) {
3824 /* Load store all elements. */
3825 op
= (insn
>> 8) & 0xf;
3826 size
= (insn
>> 6) & 3;
3829 /* Catch UNDEF cases for bad values of align field */
3832 if (((insn
>> 5) & 1) == 1) {
3837 if (((insn
>> 4) & 3) == 3) {
3844 nregs
= neon_ls_element_type
[op
].nregs
;
3845 interleave
= neon_ls_element_type
[op
].interleave
;
3846 spacing
= neon_ls_element_type
[op
].spacing
;
3847 if (size
== 3 && (interleave
| spacing
) != 1)
3849 addr
= tcg_temp_new_i32();
3850 load_reg_var(s
, addr
, rn
);
3851 stride
= (1 << size
) * interleave
;
3852 for (reg
= 0; reg
< nregs
; reg
++) {
3853 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3854 load_reg_var(s
, addr
, rn
);
3855 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3856 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3857 load_reg_var(s
, addr
, rn
);
3858 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3861 tmp64
= tcg_temp_new_i64();
3863 tcg_gen_qemu_ld64(tmp64
, addr
, IS_USER(s
));
3864 neon_store_reg64(tmp64
, rd
);
3866 neon_load_reg64(tmp64
, rd
);
3867 tcg_gen_qemu_st64(tmp64
, addr
, IS_USER(s
));
3869 tcg_temp_free_i64(tmp64
);
3870 tcg_gen_addi_i32(addr
, addr
, stride
);
3872 for (pass
= 0; pass
< 2; pass
++) {
3875 tmp
= tcg_temp_new_i32();
3876 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
3877 neon_store_reg(rd
, pass
, tmp
);
3879 tmp
= neon_load_reg(rd
, pass
);
3880 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
3881 tcg_temp_free_i32(tmp
);
3883 tcg_gen_addi_i32(addr
, addr
, stride
);
3884 } else if (size
== 1) {
3886 tmp
= tcg_temp_new_i32();
3887 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
3888 tcg_gen_addi_i32(addr
, addr
, stride
);
3889 tmp2
= tcg_temp_new_i32();
3890 tcg_gen_qemu_ld16u(tmp2
, addr
, IS_USER(s
));
3891 tcg_gen_addi_i32(addr
, addr
, stride
);
3892 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
3893 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3894 tcg_temp_free_i32(tmp2
);
3895 neon_store_reg(rd
, pass
, tmp
);
3897 tmp
= neon_load_reg(rd
, pass
);
3898 tmp2
= tcg_temp_new_i32();
3899 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3900 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
3901 tcg_temp_free_i32(tmp
);
3902 tcg_gen_addi_i32(addr
, addr
, stride
);
3903 tcg_gen_qemu_st16(tmp2
, addr
, IS_USER(s
));
3904 tcg_temp_free_i32(tmp2
);
3905 tcg_gen_addi_i32(addr
, addr
, stride
);
3907 } else /* size == 0 */ {
3909 TCGV_UNUSED_I32(tmp2
);
3910 for (n
= 0; n
< 4; n
++) {
3911 tmp
= tcg_temp_new_i32();
3912 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
3913 tcg_gen_addi_i32(addr
, addr
, stride
);
3917 tcg_gen_shli_i32(tmp
, tmp
, n
* 8);
3918 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
3919 tcg_temp_free_i32(tmp
);
3922 neon_store_reg(rd
, pass
, tmp2
);
3924 tmp2
= neon_load_reg(rd
, pass
);
3925 for (n
= 0; n
< 4; n
++) {
3926 tmp
= tcg_temp_new_i32();
3928 tcg_gen_mov_i32(tmp
, tmp2
);
3930 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3932 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
3933 tcg_temp_free_i32(tmp
);
3934 tcg_gen_addi_i32(addr
, addr
, stride
);
3936 tcg_temp_free_i32(tmp2
);
3943 tcg_temp_free_i32(addr
);
3946 size
= (insn
>> 10) & 3;
3948 /* Load single element to all lanes. */
3949 int a
= (insn
>> 4) & 1;
3953 size
= (insn
>> 6) & 3;
3954 nregs
= ((insn
>> 8) & 3) + 1;
3957 if (nregs
!= 4 || a
== 0) {
3960 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3963 if (nregs
== 1 && a
== 1 && size
== 0) {
3966 if (nregs
== 3 && a
== 1) {
3969 addr
= tcg_temp_new_i32();
3970 load_reg_var(s
, addr
, rn
);
3972 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
3973 tmp
= gen_load_and_replicate(s
, addr
, size
);
3974 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
, 0));
3975 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
, 1));
3976 if (insn
& (1 << 5)) {
3977 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
+ 1, 0));
3978 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
+ 1, 1));
3980 tcg_temp_free_i32(tmp
);
3982 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
3983 stride
= (insn
& (1 << 5)) ? 2 : 1;
3984 for (reg
= 0; reg
< nregs
; reg
++) {
3985 tmp
= gen_load_and_replicate(s
, addr
, size
);
3986 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
, 0));
3987 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
, 1));
3988 tcg_temp_free_i32(tmp
);
3989 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3993 tcg_temp_free_i32(addr
);
3994 stride
= (1 << size
) * nregs
;
3996 /* Single element. */
3997 int idx
= (insn
>> 4) & 0xf;
3998 pass
= (insn
>> 7) & 1;
4001 shift
= ((insn
>> 5) & 3) * 8;
4005 shift
= ((insn
>> 6) & 1) * 16;
4006 stride
= (insn
& (1 << 5)) ? 2 : 1;
4010 stride
= (insn
& (1 << 6)) ? 2 : 1;
4015 nregs
= ((insn
>> 8) & 3) + 1;
4016 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4019 if (((idx
& (1 << size
)) != 0) ||
4020 (size
== 2 && ((idx
& 3) == 1 || (idx
& 3) == 2))) {
4025 if ((idx
& 1) != 0) {
4030 if (size
== 2 && (idx
& 2) != 0) {
4035 if ((size
== 2) && ((idx
& 3) == 3)) {
4042 if ((rd
+ stride
* (nregs
- 1)) > 31) {
4043 /* Attempts to write off the end of the register file
4044 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4045 * the neon_load_reg() would write off the end of the array.
4049 addr
= tcg_temp_new_i32();
4050 load_reg_var(s
, addr
, rn
);
4051 for (reg
= 0; reg
< nregs
; reg
++) {
4053 tmp
= tcg_temp_new_i32();
4056 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
4059 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
4062 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
4064 default: /* Avoid compiler warnings. */
4068 tmp2
= neon_load_reg(rd
, pass
);
4069 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
,
4070 shift
, size
? 16 : 8);
4071 tcg_temp_free_i32(tmp2
);
4073 neon_store_reg(rd
, pass
, tmp
);
4074 } else { /* Store */
4075 tmp
= neon_load_reg(rd
, pass
);
4077 tcg_gen_shri_i32(tmp
, tmp
, shift
);
4080 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
4083 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
4086 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
4089 tcg_temp_free_i32(tmp
);
4092 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
4094 tcg_temp_free_i32(addr
);
4095 stride
= nregs
* (1 << size
);
4101 base
= load_reg(s
, rn
);
4103 tcg_gen_addi_i32(base
, base
, stride
);
4106 index
= load_reg(s
, rm
);
4107 tcg_gen_add_i32(base
, base
, index
);
4108 tcg_temp_free_i32(index
);
4110 store_reg(s
, rn
, base
);
4115 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4116 static void gen_neon_bsl(TCGv_i32 dest
, TCGv_i32 t
, TCGv_i32 f
, TCGv_i32 c
)
4118 tcg_gen_and_i32(t
, t
, c
);
4119 tcg_gen_andc_i32(f
, f
, c
);
4120 tcg_gen_or_i32(dest
, t
, f
);
4123 static inline void gen_neon_narrow(int size
, TCGv_i32 dest
, TCGv_i64 src
)
4126 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
4127 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
4128 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
4133 static inline void gen_neon_narrow_sats(int size
, TCGv_i32 dest
, TCGv_i64 src
)
4136 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
4137 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
4138 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4143 static inline void gen_neon_narrow_satu(int size
, TCGv_i32 dest
, TCGv_i64 src
)
4146 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4147 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4148 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4153 static inline void gen_neon_unarrow_sats(int size
, TCGv_i32 dest
, TCGv_i64 src
)
4156 case 0: gen_helper_neon_unarrow_sat8(dest
, cpu_env
, src
); break;
4157 case 1: gen_helper_neon_unarrow_sat16(dest
, cpu_env
, src
); break;
4158 case 2: gen_helper_neon_unarrow_sat32(dest
, cpu_env
, src
); break;
4163 static inline void gen_neon_shift_narrow(int size
, TCGv_i32 var
, TCGv_i32 shift
,
4169 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4170 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4175 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4176 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4183 case 1: gen_helper_neon_shl_u16(var
, var
, shift
); break;
4184 case 2: gen_helper_neon_shl_u32(var
, var
, shift
); break;
4189 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4190 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4197 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv_i32 src
, int size
, int u
)
4201 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4202 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4203 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4208 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4209 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4210 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4214 tcg_temp_free_i32(src
);
4217 static inline void gen_neon_addl(int size
)
4220 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4221 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4222 case 2: tcg_gen_add_i64(CPU_V001
); break;
4227 static inline void gen_neon_subl(int size
)
4230 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4231 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4232 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4237 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4240 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4241 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4243 tcg_gen_neg_i64(var
, var
);
4249 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4252 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4253 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4258 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv_i32 a
, TCGv_i32 b
,
4263 switch ((size
<< 1) | u
) {
4264 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4265 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4266 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4267 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4269 tmp
= gen_muls_i64_i32(a
, b
);
4270 tcg_gen_mov_i64(dest
, tmp
);
4271 tcg_temp_free_i64(tmp
);
4274 tmp
= gen_mulu_i64_i32(a
, b
);
4275 tcg_gen_mov_i64(dest
, tmp
);
4276 tcg_temp_free_i64(tmp
);
4281 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4282 Don't forget to clean them now. */
4284 tcg_temp_free_i32(a
);
4285 tcg_temp_free_i32(b
);
4289 static void gen_neon_narrow_op(int op
, int u
, int size
,
4290 TCGv_i32 dest
, TCGv_i64 src
)
4294 gen_neon_unarrow_sats(size
, dest
, src
);
4296 gen_neon_narrow(size
, dest
, src
);
4300 gen_neon_narrow_satu(size
, dest
, src
);
4302 gen_neon_narrow_sats(size
, dest
, src
);
4307 /* Symbolic constants for op fields for Neon 3-register same-length.
4308 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4311 #define NEON_3R_VHADD 0
4312 #define NEON_3R_VQADD 1
4313 #define NEON_3R_VRHADD 2
4314 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4315 #define NEON_3R_VHSUB 4
4316 #define NEON_3R_VQSUB 5
4317 #define NEON_3R_VCGT 6
4318 #define NEON_3R_VCGE 7
4319 #define NEON_3R_VSHL 8
4320 #define NEON_3R_VQSHL 9
4321 #define NEON_3R_VRSHL 10
4322 #define NEON_3R_VQRSHL 11
4323 #define NEON_3R_VMAX 12
4324 #define NEON_3R_VMIN 13
4325 #define NEON_3R_VABD 14
4326 #define NEON_3R_VABA 15
4327 #define NEON_3R_VADD_VSUB 16
4328 #define NEON_3R_VTST_VCEQ 17
4329 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4330 #define NEON_3R_VMUL 19
4331 #define NEON_3R_VPMAX 20
4332 #define NEON_3R_VPMIN 21
4333 #define NEON_3R_VQDMULH_VQRDMULH 22
4334 #define NEON_3R_VPADD 23
4335 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4336 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4337 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4338 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4339 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4340 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4341 #define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
4343 static const uint8_t neon_3r_sizes
[] = {
4344 [NEON_3R_VHADD
] = 0x7,
4345 [NEON_3R_VQADD
] = 0xf,
4346 [NEON_3R_VRHADD
] = 0x7,
4347 [NEON_3R_LOGIC
] = 0xf, /* size field encodes op type */
4348 [NEON_3R_VHSUB
] = 0x7,
4349 [NEON_3R_VQSUB
] = 0xf,
4350 [NEON_3R_VCGT
] = 0x7,
4351 [NEON_3R_VCGE
] = 0x7,
4352 [NEON_3R_VSHL
] = 0xf,
4353 [NEON_3R_VQSHL
] = 0xf,
4354 [NEON_3R_VRSHL
] = 0xf,
4355 [NEON_3R_VQRSHL
] = 0xf,
4356 [NEON_3R_VMAX
] = 0x7,
4357 [NEON_3R_VMIN
] = 0x7,
4358 [NEON_3R_VABD
] = 0x7,
4359 [NEON_3R_VABA
] = 0x7,
4360 [NEON_3R_VADD_VSUB
] = 0xf,
4361 [NEON_3R_VTST_VCEQ
] = 0x7,
4362 [NEON_3R_VML
] = 0x7,
4363 [NEON_3R_VMUL
] = 0x7,
4364 [NEON_3R_VPMAX
] = 0x7,
4365 [NEON_3R_VPMIN
] = 0x7,
4366 [NEON_3R_VQDMULH_VQRDMULH
] = 0x6,
4367 [NEON_3R_VPADD
] = 0x7,
4368 [NEON_3R_VFM
] = 0x5, /* size bit 1 encodes op */
4369 [NEON_3R_FLOAT_ARITH
] = 0x5, /* size bit 1 encodes op */
4370 [NEON_3R_FLOAT_MULTIPLY
] = 0x5, /* size bit 1 encodes op */
4371 [NEON_3R_FLOAT_CMP
] = 0x5, /* size bit 1 encodes op */
4372 [NEON_3R_FLOAT_ACMP
] = 0x5, /* size bit 1 encodes op */
4373 [NEON_3R_FLOAT_MINMAX
] = 0x5, /* size bit 1 encodes op */
4374 [NEON_3R_VRECPS_VRSQRTS
] = 0x5, /* size bit 1 encodes op */
4377 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4378 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4381 #define NEON_2RM_VREV64 0
4382 #define NEON_2RM_VREV32 1
4383 #define NEON_2RM_VREV16 2
4384 #define NEON_2RM_VPADDL 4
4385 #define NEON_2RM_VPADDL_U 5
4386 #define NEON_2RM_VCLS 8
4387 #define NEON_2RM_VCLZ 9
4388 #define NEON_2RM_VCNT 10
4389 #define NEON_2RM_VMVN 11
4390 #define NEON_2RM_VPADAL 12
4391 #define NEON_2RM_VPADAL_U 13
4392 #define NEON_2RM_VQABS 14
4393 #define NEON_2RM_VQNEG 15
4394 #define NEON_2RM_VCGT0 16
4395 #define NEON_2RM_VCGE0 17
4396 #define NEON_2RM_VCEQ0 18
4397 #define NEON_2RM_VCLE0 19
4398 #define NEON_2RM_VCLT0 20
4399 #define NEON_2RM_VABS 22
4400 #define NEON_2RM_VNEG 23
4401 #define NEON_2RM_VCGT0_F 24
4402 #define NEON_2RM_VCGE0_F 25
4403 #define NEON_2RM_VCEQ0_F 26
4404 #define NEON_2RM_VCLE0_F 27
4405 #define NEON_2RM_VCLT0_F 28
4406 #define NEON_2RM_VABS_F 30
4407 #define NEON_2RM_VNEG_F 31
4408 #define NEON_2RM_VSWP 32
4409 #define NEON_2RM_VTRN 33
4410 #define NEON_2RM_VUZP 34
4411 #define NEON_2RM_VZIP 35
4412 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4413 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4414 #define NEON_2RM_VSHLL 38
4415 #define NEON_2RM_VCVT_F16_F32 44
4416 #define NEON_2RM_VCVT_F32_F16 46
4417 #define NEON_2RM_VRECPE 56
4418 #define NEON_2RM_VRSQRTE 57
4419 #define NEON_2RM_VRECPE_F 58
4420 #define NEON_2RM_VRSQRTE_F 59
4421 #define NEON_2RM_VCVT_FS 60
4422 #define NEON_2RM_VCVT_FU 61
4423 #define NEON_2RM_VCVT_SF 62
4424 #define NEON_2RM_VCVT_UF 63
4426 static int neon_2rm_is_float_op(int op
)
4428 /* Return true if this neon 2reg-misc op is float-to-float */
4429 return (op
== NEON_2RM_VABS_F
|| op
== NEON_2RM_VNEG_F
||
4430 op
>= NEON_2RM_VRECPE_F
);
4433 /* Each entry in this array has bit n set if the insn allows
4434 * size value n (otherwise it will UNDEF). Since unallocated
4435 * op values will have no bits set they always UNDEF.
4437 static const uint8_t neon_2rm_sizes
[] = {
4438 [NEON_2RM_VREV64
] = 0x7,
4439 [NEON_2RM_VREV32
] = 0x3,
4440 [NEON_2RM_VREV16
] = 0x1,
4441 [NEON_2RM_VPADDL
] = 0x7,
4442 [NEON_2RM_VPADDL_U
] = 0x7,
4443 [NEON_2RM_VCLS
] = 0x7,
4444 [NEON_2RM_VCLZ
] = 0x7,
4445 [NEON_2RM_VCNT
] = 0x1,
4446 [NEON_2RM_VMVN
] = 0x1,
4447 [NEON_2RM_VPADAL
] = 0x7,
4448 [NEON_2RM_VPADAL_U
] = 0x7,
4449 [NEON_2RM_VQABS
] = 0x7,
4450 [NEON_2RM_VQNEG
] = 0x7,
4451 [NEON_2RM_VCGT0
] = 0x7,
4452 [NEON_2RM_VCGE0
] = 0x7,
4453 [NEON_2RM_VCEQ0
] = 0x7,
4454 [NEON_2RM_VCLE0
] = 0x7,
4455 [NEON_2RM_VCLT0
] = 0x7,
4456 [NEON_2RM_VABS
] = 0x7,
4457 [NEON_2RM_VNEG
] = 0x7,
4458 [NEON_2RM_VCGT0_F
] = 0x4,
4459 [NEON_2RM_VCGE0_F
] = 0x4,
4460 [NEON_2RM_VCEQ0_F
] = 0x4,
4461 [NEON_2RM_VCLE0_F
] = 0x4,
4462 [NEON_2RM_VCLT0_F
] = 0x4,
4463 [NEON_2RM_VABS_F
] = 0x4,
4464 [NEON_2RM_VNEG_F
] = 0x4,
4465 [NEON_2RM_VSWP
] = 0x1,
4466 [NEON_2RM_VTRN
] = 0x7,
4467 [NEON_2RM_VUZP
] = 0x7,
4468 [NEON_2RM_VZIP
] = 0x7,
4469 [NEON_2RM_VMOVN
] = 0x7,
4470 [NEON_2RM_VQMOVN
] = 0x7,
4471 [NEON_2RM_VSHLL
] = 0x7,
4472 [NEON_2RM_VCVT_F16_F32
] = 0x2,
4473 [NEON_2RM_VCVT_F32_F16
] = 0x2,
4474 [NEON_2RM_VRECPE
] = 0x4,
4475 [NEON_2RM_VRSQRTE
] = 0x4,
4476 [NEON_2RM_VRECPE_F
] = 0x4,
4477 [NEON_2RM_VRSQRTE_F
] = 0x4,
4478 [NEON_2RM_VCVT_FS
] = 0x4,
4479 [NEON_2RM_VCVT_FU
] = 0x4,
4480 [NEON_2RM_VCVT_SF
] = 0x4,
4481 [NEON_2RM_VCVT_UF
] = 0x4,
4484 /* Translate a NEON data processing instruction. Return nonzero if the
4485 instruction is invalid.
4486 We process data in a mixture of 32-bit and 64-bit chunks.
4487 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4489 static int disas_neon_data_insn(CPUARMState
* env
, DisasContext
*s
, uint32_t insn
)
4501 TCGv_i32 tmp
, tmp2
, tmp3
, tmp4
, tmp5
;
4504 if (!s
->vfp_enabled
)
4506 q
= (insn
& (1 << 6)) != 0;
4507 u
= (insn
>> 24) & 1;
4508 VFP_DREG_D(rd
, insn
);
4509 VFP_DREG_N(rn
, insn
);
4510 VFP_DREG_M(rm
, insn
);
4511 size
= (insn
>> 20) & 3;
4512 if ((insn
& (1 << 23)) == 0) {
4513 /* Three register same length. */
4514 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4515 /* Catch invalid op and bad size combinations: UNDEF */
4516 if ((neon_3r_sizes
[op
] & (1 << size
)) == 0) {
4519 /* All insns of this form UNDEF for either this condition or the
4520 * superset of cases "Q==1"; we catch the latter later.
4522 if (q
&& ((rd
| rn
| rm
) & 1)) {
4525 if (size
== 3 && op
!= NEON_3R_LOGIC
) {
4526 /* 64-bit element instructions. */
4527 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4528 neon_load_reg64(cpu_V0
, rn
+ pass
);
4529 neon_load_reg64(cpu_V1
, rm
+ pass
);
4533 gen_helper_neon_qadd_u64(cpu_V0
, cpu_env
,
4536 gen_helper_neon_qadd_s64(cpu_V0
, cpu_env
,
4542 gen_helper_neon_qsub_u64(cpu_V0
, cpu_env
,
4545 gen_helper_neon_qsub_s64(cpu_V0
, cpu_env
,
4551 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4553 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4558 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4561 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
,
4567 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4569 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4572 case NEON_3R_VQRSHL
:
4574 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4577 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4581 case NEON_3R_VADD_VSUB
:
4583 tcg_gen_sub_i64(CPU_V001
);
4585 tcg_gen_add_i64(CPU_V001
);
4591 neon_store_reg64(cpu_V0
, rd
+ pass
);
4600 case NEON_3R_VQRSHL
:
4603 /* Shift instruction operands are reversed. */
4618 case NEON_3R_FLOAT_ARITH
:
4619 pairwise
= (u
&& size
< 2); /* if VPADD (float) */
4621 case NEON_3R_FLOAT_MINMAX
:
4622 pairwise
= u
; /* if VPMIN/VPMAX (float) */
4624 case NEON_3R_FLOAT_CMP
:
4626 /* no encoding for U=0 C=1x */
4630 case NEON_3R_FLOAT_ACMP
:
4635 case NEON_3R_VRECPS_VRSQRTS
:
4641 if (u
&& (size
!= 0)) {
4642 /* UNDEF on invalid size for polynomial subcase */
4647 if (!arm_feature(env
, ARM_FEATURE_VFP4
) || u
) {
4655 if (pairwise
&& q
) {
4656 /* All the pairwise insns UNDEF if Q is set */
4660 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4665 tmp
= neon_load_reg(rn
, 0);
4666 tmp2
= neon_load_reg(rn
, 1);
4668 tmp
= neon_load_reg(rm
, 0);
4669 tmp2
= neon_load_reg(rm
, 1);
4673 tmp
= neon_load_reg(rn
, pass
);
4674 tmp2
= neon_load_reg(rm
, pass
);
4678 GEN_NEON_INTEGER_OP(hadd
);
4681 GEN_NEON_INTEGER_OP_ENV(qadd
);
4683 case NEON_3R_VRHADD
:
4684 GEN_NEON_INTEGER_OP(rhadd
);
4686 case NEON_3R_LOGIC
: /* Logic ops. */
4687 switch ((u
<< 2) | size
) {
4689 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4692 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
4695 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4698 tcg_gen_orc_i32(tmp
, tmp
, tmp2
);
4701 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4704 tmp3
= neon_load_reg(rd
, pass
);
4705 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4706 tcg_temp_free_i32(tmp3
);
4709 tmp3
= neon_load_reg(rd
, pass
);
4710 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4711 tcg_temp_free_i32(tmp3
);
4714 tmp3
= neon_load_reg(rd
, pass
);
4715 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4716 tcg_temp_free_i32(tmp3
);
4721 GEN_NEON_INTEGER_OP(hsub
);
4724 GEN_NEON_INTEGER_OP_ENV(qsub
);
4727 GEN_NEON_INTEGER_OP(cgt
);
4730 GEN_NEON_INTEGER_OP(cge
);
4733 GEN_NEON_INTEGER_OP(shl
);
4736 GEN_NEON_INTEGER_OP_ENV(qshl
);
4739 GEN_NEON_INTEGER_OP(rshl
);
4741 case NEON_3R_VQRSHL
:
4742 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4745 GEN_NEON_INTEGER_OP(max
);
4748 GEN_NEON_INTEGER_OP(min
);
4751 GEN_NEON_INTEGER_OP(abd
);
4754 GEN_NEON_INTEGER_OP(abd
);
4755 tcg_temp_free_i32(tmp2
);
4756 tmp2
= neon_load_reg(rd
, pass
);
4757 gen_neon_add(size
, tmp
, tmp2
);
4759 case NEON_3R_VADD_VSUB
:
4760 if (!u
) { /* VADD */
4761 gen_neon_add(size
, tmp
, tmp2
);
4764 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4765 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4766 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4771 case NEON_3R_VTST_VCEQ
:
4772 if (!u
) { /* VTST */
4774 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4775 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4776 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4781 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4782 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4783 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4788 case NEON_3R_VML
: /* VMLA, VMLAL, VMLS,VMLSL */
4790 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4791 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4792 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4795 tcg_temp_free_i32(tmp2
);
4796 tmp2
= neon_load_reg(rd
, pass
);
4798 gen_neon_rsb(size
, tmp
, tmp2
);
4800 gen_neon_add(size
, tmp
, tmp2
);
4804 if (u
) { /* polynomial */
4805 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4806 } else { /* Integer */
4808 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4809 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4810 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4816 GEN_NEON_INTEGER_OP(pmax
);
4819 GEN_NEON_INTEGER_OP(pmin
);
4821 case NEON_3R_VQDMULH_VQRDMULH
: /* Multiply high. */
4822 if (!u
) { /* VQDMULH */
4825 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
4828 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
4832 } else { /* VQRDMULH */
4835 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
4838 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
4846 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4847 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4848 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4852 case NEON_3R_FLOAT_ARITH
: /* Floating point arithmetic. */
4854 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4855 switch ((u
<< 2) | size
) {
4858 gen_helper_vfp_adds(tmp
, tmp
, tmp2
, fpstatus
);
4861 gen_helper_vfp_subs(tmp
, tmp
, tmp2
, fpstatus
);
4864 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
, fpstatus
);
4869 tcg_temp_free_ptr(fpstatus
);
4872 case NEON_3R_FLOAT_MULTIPLY
:
4874 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4875 gen_helper_vfp_muls(tmp
, tmp
, tmp2
, fpstatus
);
4877 tcg_temp_free_i32(tmp2
);
4878 tmp2
= neon_load_reg(rd
, pass
);
4880 gen_helper_vfp_adds(tmp
, tmp
, tmp2
, fpstatus
);
4882 gen_helper_vfp_subs(tmp
, tmp2
, tmp
, fpstatus
);
4885 tcg_temp_free_ptr(fpstatus
);
4888 case NEON_3R_FLOAT_CMP
:
4890 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4892 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
, fpstatus
);
4895 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
, fpstatus
);
4897 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
, fpstatus
);
4900 tcg_temp_free_ptr(fpstatus
);
4903 case NEON_3R_FLOAT_ACMP
:
4905 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4907 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
, fpstatus
);
4909 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
, fpstatus
);
4911 tcg_temp_free_ptr(fpstatus
);
4914 case NEON_3R_FLOAT_MINMAX
:
4916 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4918 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
, fpstatus
);
4920 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
, fpstatus
);
4922 tcg_temp_free_ptr(fpstatus
);
4925 case NEON_3R_VRECPS_VRSQRTS
:
4927 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4929 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4933 /* VFMA, VFMS: fused multiply-add */
4934 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4935 TCGv_i32 tmp3
= neon_load_reg(rd
, pass
);
4938 gen_helper_vfp_negs(tmp
, tmp
);
4940 gen_helper_vfp_muladds(tmp
, tmp
, tmp2
, tmp3
, fpstatus
);
4941 tcg_temp_free_i32(tmp3
);
4942 tcg_temp_free_ptr(fpstatus
);
4948 tcg_temp_free_i32(tmp2
);
4950 /* Save the result. For elementwise operations we can put it
4951 straight into the destination register. For pairwise operations
4952 we have to be careful to avoid clobbering the source operands. */
4953 if (pairwise
&& rd
== rm
) {
4954 neon_store_scratch(pass
, tmp
);
4956 neon_store_reg(rd
, pass
, tmp
);
4960 if (pairwise
&& rd
== rm
) {
4961 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4962 tmp
= neon_load_scratch(pass
);
4963 neon_store_reg(rd
, pass
, tmp
);
4966 /* End of 3 register same size operations. */
4967 } else if (insn
& (1 << 4)) {
4968 if ((insn
& 0x00380080) != 0) {
4969 /* Two registers and shift. */
4970 op
= (insn
>> 8) & 0xf;
4971 if (insn
& (1 << 7)) {
4979 while ((insn
& (1 << (size
+ 19))) == 0)
4982 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4983 /* To avoid excessive duplication of ops we implement shift
4984 by immediate using the variable shift operations. */
4986 /* Shift by immediate:
4987 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4988 if (q
&& ((rd
| rm
) & 1)) {
4991 if (!u
&& (op
== 4 || op
== 6)) {
4994 /* Right shifts are encoded as N - shift, where N is the
4995 element size in bits. */
4997 shift
= shift
- (1 << (size
+ 3));
5005 imm
= (uint8_t) shift
;
5010 imm
= (uint16_t) shift
;
5021 for (pass
= 0; pass
< count
; pass
++) {
5023 neon_load_reg64(cpu_V0
, rm
+ pass
);
5024 tcg_gen_movi_i64(cpu_V1
, imm
);
5029 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
5031 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
5036 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
5038 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
5041 case 5: /* VSHL, VSLI */
5042 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
5044 case 6: /* VQSHLU */
5045 gen_helper_neon_qshlu_s64(cpu_V0
, cpu_env
,
5050 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
5053 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
,
5058 if (op
== 1 || op
== 3) {
5060 neon_load_reg64(cpu_V1
, rd
+ pass
);
5061 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5062 } else if (op
== 4 || (op
== 5 && u
)) {
5064 neon_load_reg64(cpu_V1
, rd
+ pass
);
5066 if (shift
< -63 || shift
> 63) {
5070 mask
= 0xffffffffffffffffull
>> -shift
;
5072 mask
= 0xffffffffffffffffull
<< shift
;
5075 tcg_gen_andi_i64(cpu_V1
, cpu_V1
, ~mask
);
5076 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5078 neon_store_reg64(cpu_V0
, rd
+ pass
);
5079 } else { /* size < 3 */
5080 /* Operands in T0 and T1. */
5081 tmp
= neon_load_reg(rm
, pass
);
5082 tmp2
= tcg_temp_new_i32();
5083 tcg_gen_movi_i32(tmp2
, imm
);
5087 GEN_NEON_INTEGER_OP(shl
);
5091 GEN_NEON_INTEGER_OP(rshl
);
5094 case 5: /* VSHL, VSLI */
5096 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
5097 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
5098 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
5102 case 6: /* VQSHLU */
5105 gen_helper_neon_qshlu_s8(tmp
, cpu_env
,
5109 gen_helper_neon_qshlu_s16(tmp
, cpu_env
,
5113 gen_helper_neon_qshlu_s32(tmp
, cpu_env
,
5121 GEN_NEON_INTEGER_OP_ENV(qshl
);
5124 tcg_temp_free_i32(tmp2
);
5126 if (op
== 1 || op
== 3) {
5128 tmp2
= neon_load_reg(rd
, pass
);
5129 gen_neon_add(size
, tmp
, tmp2
);
5130 tcg_temp_free_i32(tmp2
);
5131 } else if (op
== 4 || (op
== 5 && u
)) {
5136 mask
= 0xff >> -shift
;
5138 mask
= (uint8_t)(0xff << shift
);
5144 mask
= 0xffff >> -shift
;
5146 mask
= (uint16_t)(0xffff << shift
);
5150 if (shift
< -31 || shift
> 31) {
5154 mask
= 0xffffffffu
>> -shift
;
5156 mask
= 0xffffffffu
<< shift
;
5162 tmp2
= neon_load_reg(rd
, pass
);
5163 tcg_gen_andi_i32(tmp
, tmp
, mask
);
5164 tcg_gen_andi_i32(tmp2
, tmp2
, ~mask
);
5165 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
5166 tcg_temp_free_i32(tmp2
);
5168 neon_store_reg(rd
, pass
, tmp
);
5171 } else if (op
< 10) {
5172 /* Shift by immediate and narrow:
5173 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5174 int input_unsigned
= (op
== 8) ? !u
: u
;
5178 shift
= shift
- (1 << (size
+ 3));
5181 tmp64
= tcg_const_i64(shift
);
5182 neon_load_reg64(cpu_V0
, rm
);
5183 neon_load_reg64(cpu_V1
, rm
+ 1);
5184 for (pass
= 0; pass
< 2; pass
++) {
5192 if (input_unsigned
) {
5193 gen_helper_neon_rshl_u64(cpu_V0
, in
, tmp64
);
5195 gen_helper_neon_rshl_s64(cpu_V0
, in
, tmp64
);
5198 if (input_unsigned
) {
5199 gen_helper_neon_shl_u64(cpu_V0
, in
, tmp64
);
5201 gen_helper_neon_shl_s64(cpu_V0
, in
, tmp64
);
5204 tmp
= tcg_temp_new_i32();
5205 gen_neon_narrow_op(op
== 8, u
, size
- 1, tmp
, cpu_V0
);
5206 neon_store_reg(rd
, pass
, tmp
);
5208 tcg_temp_free_i64(tmp64
);
5211 imm
= (uint16_t)shift
;
5215 imm
= (uint32_t)shift
;
5217 tmp2
= tcg_const_i32(imm
);
5218 tmp4
= neon_load_reg(rm
+ 1, 0);
5219 tmp5
= neon_load_reg(rm
+ 1, 1);
5220 for (pass
= 0; pass
< 2; pass
++) {
5222 tmp
= neon_load_reg(rm
, 0);
5226 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
,
5229 tmp3
= neon_load_reg(rm
, 1);
5233 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
,
5235 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
5236 tcg_temp_free_i32(tmp
);
5237 tcg_temp_free_i32(tmp3
);
5238 tmp
= tcg_temp_new_i32();
5239 gen_neon_narrow_op(op
== 8, u
, size
- 1, tmp
, cpu_V0
);
5240 neon_store_reg(rd
, pass
, tmp
);
5242 tcg_temp_free_i32(tmp2
);
5244 } else if (op
== 10) {
5246 if (q
|| (rd
& 1)) {
5249 tmp
= neon_load_reg(rm
, 0);
5250 tmp2
= neon_load_reg(rm
, 1);
5251 for (pass
= 0; pass
< 2; pass
++) {
5255 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
5258 /* The shift is less than the width of the source
5259 type, so we can just shift the whole register. */
5260 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
5261 /* Widen the result of shift: we need to clear
5262 * the potential overflow bits resulting from
5263 * left bits of the narrow input appearing as
5264 * right bits of left the neighbour narrow
5266 if (size
< 2 || !u
) {
5269 imm
= (0xffu
>> (8 - shift
));
5271 } else if (size
== 1) {
5272 imm
= 0xffff >> (16 - shift
);
5275 imm
= 0xffffffff >> (32 - shift
);
5278 imm64
= imm
| (((uint64_t)imm
) << 32);
5282 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, ~imm64
);
5285 neon_store_reg64(cpu_V0
, rd
+ pass
);
5287 } else if (op
>= 14) {
5288 /* VCVT fixed-point. */
5289 if (!(insn
& (1 << 21)) || (q
&& ((rd
| rm
) & 1))) {
5292 /* We have already masked out the must-be-1 top bit of imm6,
5293 * hence this 32-shift where the ARM ARM has 64-imm6.
5296 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5297 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
5300 gen_vfp_ulto(0, shift
, 1);
5302 gen_vfp_slto(0, shift
, 1);
5305 gen_vfp_toul(0, shift
, 1);
5307 gen_vfp_tosl(0, shift
, 1);
5309 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
5314 } else { /* (insn & 0x00380080) == 0 */
5316 if (q
&& (rd
& 1)) {
5320 op
= (insn
>> 8) & 0xf;
5321 /* One register and immediate. */
5322 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
5323 invert
= (insn
& (1 << 5)) != 0;
5324 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5325 * We choose to not special-case this and will behave as if a
5326 * valid constant encoding of 0 had been given.
5345 imm
= (imm
<< 8) | (imm
<< 24);
5348 imm
= (imm
<< 8) | 0xff;
5351 imm
= (imm
<< 16) | 0xffff;
5354 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
5362 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
5363 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
5369 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5370 if (op
& 1 && op
< 12) {
5371 tmp
= neon_load_reg(rd
, pass
);
5373 /* The immediate value has already been inverted, so
5375 tcg_gen_andi_i32(tmp
, tmp
, imm
);
5377 tcg_gen_ori_i32(tmp
, tmp
, imm
);
5381 tmp
= tcg_temp_new_i32();
5382 if (op
== 14 && invert
) {
5386 for (n
= 0; n
< 4; n
++) {
5387 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
5388 val
|= 0xff << (n
* 8);
5390 tcg_gen_movi_i32(tmp
, val
);
5392 tcg_gen_movi_i32(tmp
, imm
);
5395 neon_store_reg(rd
, pass
, tmp
);
5398 } else { /* (insn & 0x00800010 == 0x00800000) */
5400 op
= (insn
>> 8) & 0xf;
5401 if ((insn
& (1 << 6)) == 0) {
5402 /* Three registers of different lengths. */
5406 /* undefreq: bit 0 : UNDEF if size != 0
5407 * bit 1 : UNDEF if size == 0
5408 * bit 2 : UNDEF if U == 1
5409 * Note that [1:0] set implies 'always UNDEF'
5412 /* prewiden, src1_wide, src2_wide, undefreq */
5413 static const int neon_3reg_wide
[16][4] = {
5414 {1, 0, 0, 0}, /* VADDL */
5415 {1, 1, 0, 0}, /* VADDW */
5416 {1, 0, 0, 0}, /* VSUBL */
5417 {1, 1, 0, 0}, /* VSUBW */
5418 {0, 1, 1, 0}, /* VADDHN */
5419 {0, 0, 0, 0}, /* VABAL */
5420 {0, 1, 1, 0}, /* VSUBHN */
5421 {0, 0, 0, 0}, /* VABDL */
5422 {0, 0, 0, 0}, /* VMLAL */
5423 {0, 0, 0, 6}, /* VQDMLAL */
5424 {0, 0, 0, 0}, /* VMLSL */
5425 {0, 0, 0, 6}, /* VQDMLSL */
5426 {0, 0, 0, 0}, /* Integer VMULL */
5427 {0, 0, 0, 2}, /* VQDMULL */
5428 {0, 0, 0, 5}, /* Polynomial VMULL */
5429 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5432 prewiden
= neon_3reg_wide
[op
][0];
5433 src1_wide
= neon_3reg_wide
[op
][1];
5434 src2_wide
= neon_3reg_wide
[op
][2];
5435 undefreq
= neon_3reg_wide
[op
][3];
5437 if (((undefreq
& 1) && (size
!= 0)) ||
5438 ((undefreq
& 2) && (size
== 0)) ||
5439 ((undefreq
& 4) && u
)) {
5442 if ((src1_wide
&& (rn
& 1)) ||
5443 (src2_wide
&& (rm
& 1)) ||
5444 (!src2_wide
&& (rd
& 1))) {
5448 /* Avoid overlapping operands. Wide source operands are
5449 always aligned so will never overlap with wide
5450 destinations in problematic ways. */
5451 if (rd
== rm
&& !src2_wide
) {
5452 tmp
= neon_load_reg(rm
, 1);
5453 neon_store_scratch(2, tmp
);
5454 } else if (rd
== rn
&& !src1_wide
) {
5455 tmp
= neon_load_reg(rn
, 1);
5456 neon_store_scratch(2, tmp
);
5458 TCGV_UNUSED_I32(tmp3
);
5459 for (pass
= 0; pass
< 2; pass
++) {
5461 neon_load_reg64(cpu_V0
, rn
+ pass
);
5462 TCGV_UNUSED_I32(tmp
);
5464 if (pass
== 1 && rd
== rn
) {
5465 tmp
= neon_load_scratch(2);
5467 tmp
= neon_load_reg(rn
, pass
);
5470 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
5474 neon_load_reg64(cpu_V1
, rm
+ pass
);
5475 TCGV_UNUSED_I32(tmp2
);
5477 if (pass
== 1 && rd
== rm
) {
5478 tmp2
= neon_load_scratch(2);
5480 tmp2
= neon_load_reg(rm
, pass
);
5483 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
5487 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5488 gen_neon_addl(size
);
5490 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5491 gen_neon_subl(size
);
5493 case 5: case 7: /* VABAL, VABDL */
5494 switch ((size
<< 1) | u
) {
5496 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
5499 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
5502 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
5505 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
5508 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
5511 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
5515 tcg_temp_free_i32(tmp2
);
5516 tcg_temp_free_i32(tmp
);
5518 case 8: case 9: case 10: case 11: case 12: case 13:
5519 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5520 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5522 case 14: /* Polynomial VMULL */
5523 gen_helper_neon_mull_p8(cpu_V0
, tmp
, tmp2
);
5524 tcg_temp_free_i32(tmp2
);
5525 tcg_temp_free_i32(tmp
);
5527 default: /* 15 is RESERVED: caught earlier */
5532 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5533 neon_store_reg64(cpu_V0
, rd
+ pass
);
5534 } else if (op
== 5 || (op
>= 8 && op
<= 11)) {
5536 neon_load_reg64(cpu_V1
, rd
+ pass
);
5538 case 10: /* VMLSL */
5539 gen_neon_negl(cpu_V0
, size
);
5541 case 5: case 8: /* VABAL, VMLAL */
5542 gen_neon_addl(size
);
5544 case 9: case 11: /* VQDMLAL, VQDMLSL */
5545 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5547 gen_neon_negl(cpu_V0
, size
);
5549 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5554 neon_store_reg64(cpu_V0
, rd
+ pass
);
5555 } else if (op
== 4 || op
== 6) {
5556 /* Narrowing operation. */
5557 tmp
= tcg_temp_new_i32();
5561 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5564 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5567 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5568 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5575 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5578 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5581 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5582 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5583 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5591 neon_store_reg(rd
, 0, tmp3
);
5592 neon_store_reg(rd
, 1, tmp
);
5595 /* Write back the result. */
5596 neon_store_reg64(cpu_V0
, rd
+ pass
);
5600 /* Two registers and a scalar. NB that for ops of this form
5601 * the ARM ARM labels bit 24 as Q, but it is in our variable
5608 case 1: /* Float VMLA scalar */
5609 case 5: /* Floating point VMLS scalar */
5610 case 9: /* Floating point VMUL scalar */
5615 case 0: /* Integer VMLA scalar */
5616 case 4: /* Integer VMLS scalar */
5617 case 8: /* Integer VMUL scalar */
5618 case 12: /* VQDMULH scalar */
5619 case 13: /* VQRDMULH scalar */
5620 if (u
&& ((rd
| rn
) & 1)) {
5623 tmp
= neon_get_scalar(size
, rm
);
5624 neon_store_scratch(0, tmp
);
5625 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5626 tmp
= neon_load_scratch(0);
5627 tmp2
= neon_load_reg(rn
, pass
);
5630 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5632 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5634 } else if (op
== 13) {
5636 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5638 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5640 } else if (op
& 1) {
5641 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
5642 gen_helper_vfp_muls(tmp
, tmp
, tmp2
, fpstatus
);
5643 tcg_temp_free_ptr(fpstatus
);
5646 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5647 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5648 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5652 tcg_temp_free_i32(tmp2
);
5655 tmp2
= neon_load_reg(rd
, pass
);
5658 gen_neon_add(size
, tmp
, tmp2
);
5662 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
5663 gen_helper_vfp_adds(tmp
, tmp
, tmp2
, fpstatus
);
5664 tcg_temp_free_ptr(fpstatus
);
5668 gen_neon_rsb(size
, tmp
, tmp2
);
5672 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
5673 gen_helper_vfp_subs(tmp
, tmp2
, tmp
, fpstatus
);
5674 tcg_temp_free_ptr(fpstatus
);
5680 tcg_temp_free_i32(tmp2
);
5682 neon_store_reg(rd
, pass
, tmp
);
5685 case 3: /* VQDMLAL scalar */
5686 case 7: /* VQDMLSL scalar */
5687 case 11: /* VQDMULL scalar */
5692 case 2: /* VMLAL sclar */
5693 case 6: /* VMLSL scalar */
5694 case 10: /* VMULL scalar */
5698 tmp2
= neon_get_scalar(size
, rm
);
5699 /* We need a copy of tmp2 because gen_neon_mull
5700 * deletes it during pass 0. */
5701 tmp4
= tcg_temp_new_i32();
5702 tcg_gen_mov_i32(tmp4
, tmp2
);
5703 tmp3
= neon_load_reg(rn
, 1);
5705 for (pass
= 0; pass
< 2; pass
++) {
5707 tmp
= neon_load_reg(rn
, 0);
5712 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5714 neon_load_reg64(cpu_V1
, rd
+ pass
);
5718 gen_neon_negl(cpu_V0
, size
);
5721 gen_neon_addl(size
);
5724 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5726 gen_neon_negl(cpu_V0
, size
);
5728 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5734 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5739 neon_store_reg64(cpu_V0
, rd
+ pass
);
5744 default: /* 14 and 15 are RESERVED */
5748 } else { /* size == 3 */
5751 imm
= (insn
>> 8) & 0xf;
5756 if (q
&& ((rd
| rn
| rm
) & 1)) {
5761 neon_load_reg64(cpu_V0
, rn
);
5763 neon_load_reg64(cpu_V1
, rn
+ 1);
5765 } else if (imm
== 8) {
5766 neon_load_reg64(cpu_V0
, rn
+ 1);
5768 neon_load_reg64(cpu_V1
, rm
);
5771 tmp64
= tcg_temp_new_i64();
5773 neon_load_reg64(cpu_V0
, rn
);
5774 neon_load_reg64(tmp64
, rn
+ 1);
5776 neon_load_reg64(cpu_V0
, rn
+ 1);
5777 neon_load_reg64(tmp64
, rm
);
5779 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5780 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5781 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5783 neon_load_reg64(cpu_V1
, rm
);
5785 neon_load_reg64(cpu_V1
, rm
+ 1);
5788 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5789 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5790 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5791 tcg_temp_free_i64(tmp64
);
5794 neon_load_reg64(cpu_V0
, rn
);
5795 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5796 neon_load_reg64(cpu_V1
, rm
);
5797 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5798 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5800 neon_store_reg64(cpu_V0
, rd
);
5802 neon_store_reg64(cpu_V1
, rd
+ 1);
5804 } else if ((insn
& (1 << 11)) == 0) {
5805 /* Two register misc. */
5806 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5807 size
= (insn
>> 18) & 3;
5808 /* UNDEF for unknown op values and bad op-size combinations */
5809 if ((neon_2rm_sizes
[op
] & (1 << size
)) == 0) {
5812 if ((op
!= NEON_2RM_VMOVN
&& op
!= NEON_2RM_VQMOVN
) &&
5813 q
&& ((rm
| rd
) & 1)) {
5817 case NEON_2RM_VREV64
:
5818 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5819 tmp
= neon_load_reg(rm
, pass
* 2);
5820 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5822 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5823 case 1: gen_swap_half(tmp
); break;
5824 case 2: /* no-op */ break;
5827 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5829 neon_store_reg(rd
, pass
* 2, tmp2
);
5832 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5833 case 1: gen_swap_half(tmp2
); break;
5836 neon_store_reg(rd
, pass
* 2, tmp2
);
5840 case NEON_2RM_VPADDL
: case NEON_2RM_VPADDL_U
:
5841 case NEON_2RM_VPADAL
: case NEON_2RM_VPADAL_U
:
5842 for (pass
= 0; pass
< q
+ 1; pass
++) {
5843 tmp
= neon_load_reg(rm
, pass
* 2);
5844 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5845 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5846 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5848 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5849 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5850 case 2: tcg_gen_add_i64(CPU_V001
); break;
5853 if (op
>= NEON_2RM_VPADAL
) {
5855 neon_load_reg64(cpu_V1
, rd
+ pass
);
5856 gen_neon_addl(size
);
5858 neon_store_reg64(cpu_V0
, rd
+ pass
);
5864 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5865 tmp
= neon_load_reg(rm
, n
);
5866 tmp2
= neon_load_reg(rd
, n
+ 1);
5867 neon_store_reg(rm
, n
, tmp2
);
5868 neon_store_reg(rd
, n
+ 1, tmp
);
5875 if (gen_neon_unzip(rd
, rm
, size
, q
)) {
5880 if (gen_neon_zip(rd
, rm
, size
, q
)) {
5884 case NEON_2RM_VMOVN
: case NEON_2RM_VQMOVN
:
5885 /* also VQMOVUN; op field and mnemonics don't line up */
5889 TCGV_UNUSED_I32(tmp2
);
5890 for (pass
= 0; pass
< 2; pass
++) {
5891 neon_load_reg64(cpu_V0
, rm
+ pass
);
5892 tmp
= tcg_temp_new_i32();
5893 gen_neon_narrow_op(op
== NEON_2RM_VMOVN
, q
, size
,
5898 neon_store_reg(rd
, 0, tmp2
);
5899 neon_store_reg(rd
, 1, tmp
);
5903 case NEON_2RM_VSHLL
:
5904 if (q
|| (rd
& 1)) {
5907 tmp
= neon_load_reg(rm
, 0);
5908 tmp2
= neon_load_reg(rm
, 1);
5909 for (pass
= 0; pass
< 2; pass
++) {
5912 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5913 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, 8 << size
);
5914 neon_store_reg64(cpu_V0
, rd
+ pass
);
5917 case NEON_2RM_VCVT_F16_F32
:
5918 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
) ||
5922 tmp
= tcg_temp_new_i32();
5923 tmp2
= tcg_temp_new_i32();
5924 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 0));
5925 gen_helper_neon_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5926 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 1));
5927 gen_helper_neon_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5928 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5929 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5930 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 2));
5931 gen_helper_neon_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5932 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 3));
5933 neon_store_reg(rd
, 0, tmp2
);
5934 tmp2
= tcg_temp_new_i32();
5935 gen_helper_neon_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5936 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5937 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5938 neon_store_reg(rd
, 1, tmp2
);
5939 tcg_temp_free_i32(tmp
);
5941 case NEON_2RM_VCVT_F32_F16
:
5942 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
) ||
5946 tmp3
= tcg_temp_new_i32();
5947 tmp
= neon_load_reg(rm
, 0);
5948 tmp2
= neon_load_reg(rm
, 1);
5949 tcg_gen_ext16u_i32(tmp3
, tmp
);
5950 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5951 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 0));
5952 tcg_gen_shri_i32(tmp3
, tmp
, 16);
5953 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5954 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 1));
5955 tcg_temp_free_i32(tmp
);
5956 tcg_gen_ext16u_i32(tmp3
, tmp2
);
5957 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5958 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 2));
5959 tcg_gen_shri_i32(tmp3
, tmp2
, 16);
5960 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5961 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 3));
5962 tcg_temp_free_i32(tmp2
);
5963 tcg_temp_free_i32(tmp3
);
5967 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5968 if (neon_2rm_is_float_op(op
)) {
5969 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5970 neon_reg_offset(rm
, pass
));
5971 TCGV_UNUSED_I32(tmp
);
5973 tmp
= neon_load_reg(rm
, pass
);
5976 case NEON_2RM_VREV32
:
5978 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5979 case 1: gen_swap_half(tmp
); break;
5983 case NEON_2RM_VREV16
:
5988 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5989 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5990 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5996 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5997 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5998 case 2: gen_helper_clz(tmp
, tmp
); break;
6003 gen_helper_neon_cnt_u8(tmp
, tmp
);
6006 tcg_gen_not_i32(tmp
, tmp
);
6008 case NEON_2RM_VQABS
:
6011 gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
);
6014 gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
);
6017 gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
);
6022 case NEON_2RM_VQNEG
:
6025 gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
);
6028 gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
);
6031 gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
);
6036 case NEON_2RM_VCGT0
: case NEON_2RM_VCLE0
:
6037 tmp2
= tcg_const_i32(0);
6039 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
6040 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
6041 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
6044 tcg_temp_free_i32(tmp2
);
6045 if (op
== NEON_2RM_VCLE0
) {
6046 tcg_gen_not_i32(tmp
, tmp
);
6049 case NEON_2RM_VCGE0
: case NEON_2RM_VCLT0
:
6050 tmp2
= tcg_const_i32(0);
6052 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
6053 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
6054 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
6057 tcg_temp_free_i32(tmp2
);
6058 if (op
== NEON_2RM_VCLT0
) {
6059 tcg_gen_not_i32(tmp
, tmp
);
6062 case NEON_2RM_VCEQ0
:
6063 tmp2
= tcg_const_i32(0);
6065 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
6066 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
6067 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
6070 tcg_temp_free_i32(tmp2
);
6074 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
6075 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
6076 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
6081 tmp2
= tcg_const_i32(0);
6082 gen_neon_rsb(size
, tmp
, tmp2
);
6083 tcg_temp_free_i32(tmp2
);
6085 case NEON_2RM_VCGT0_F
:
6087 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6088 tmp2
= tcg_const_i32(0);
6089 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
, fpstatus
);
6090 tcg_temp_free_i32(tmp2
);
6091 tcg_temp_free_ptr(fpstatus
);
6094 case NEON_2RM_VCGE0_F
:
6096 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6097 tmp2
= tcg_const_i32(0);
6098 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
, fpstatus
);
6099 tcg_temp_free_i32(tmp2
);
6100 tcg_temp_free_ptr(fpstatus
);
6103 case NEON_2RM_VCEQ0_F
:
6105 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6106 tmp2
= tcg_const_i32(0);
6107 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
, fpstatus
);
6108 tcg_temp_free_i32(tmp2
);
6109 tcg_temp_free_ptr(fpstatus
);
6112 case NEON_2RM_VCLE0_F
:
6114 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6115 tmp2
= tcg_const_i32(0);
6116 gen_helper_neon_cge_f32(tmp
, tmp2
, tmp
, fpstatus
);
6117 tcg_temp_free_i32(tmp2
);
6118 tcg_temp_free_ptr(fpstatus
);
6121 case NEON_2RM_VCLT0_F
:
6123 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6124 tmp2
= tcg_const_i32(0);
6125 gen_helper_neon_cgt_f32(tmp
, tmp2
, tmp
, fpstatus
);
6126 tcg_temp_free_i32(tmp2
);
6127 tcg_temp_free_ptr(fpstatus
);
6130 case NEON_2RM_VABS_F
:
6133 case NEON_2RM_VNEG_F
:
6137 tmp2
= neon_load_reg(rd
, pass
);
6138 neon_store_reg(rm
, pass
, tmp2
);
6141 tmp2
= neon_load_reg(rd
, pass
);
6143 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
6144 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
6147 neon_store_reg(rm
, pass
, tmp2
);
6149 case NEON_2RM_VRECPE
:
6150 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
6152 case NEON_2RM_VRSQRTE
:
6153 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
6155 case NEON_2RM_VRECPE_F
:
6156 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
6158 case NEON_2RM_VRSQRTE_F
:
6159 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
6161 case NEON_2RM_VCVT_FS
: /* VCVT.F32.S32 */
6164 case NEON_2RM_VCVT_FU
: /* VCVT.F32.U32 */
6167 case NEON_2RM_VCVT_SF
: /* VCVT.S32.F32 */
6168 gen_vfp_tosiz(0, 1);
6170 case NEON_2RM_VCVT_UF
: /* VCVT.U32.F32 */
6171 gen_vfp_touiz(0, 1);
6174 /* Reserved op values were caught by the
6175 * neon_2rm_sizes[] check earlier.
6179 if (neon_2rm_is_float_op(op
)) {
6180 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
6181 neon_reg_offset(rd
, pass
));
6183 neon_store_reg(rd
, pass
, tmp
);
6188 } else if ((insn
& (1 << 10)) == 0) {
6190 int n
= ((insn
>> 8) & 3) + 1;
6191 if ((rn
+ n
) > 32) {
6192 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6193 * helper function running off the end of the register file.
6198 if (insn
& (1 << 6)) {
6199 tmp
= neon_load_reg(rd
, 0);
6201 tmp
= tcg_temp_new_i32();
6202 tcg_gen_movi_i32(tmp
, 0);
6204 tmp2
= neon_load_reg(rm
, 0);
6205 tmp4
= tcg_const_i32(rn
);
6206 tmp5
= tcg_const_i32(n
);
6207 gen_helper_neon_tbl(tmp2
, cpu_env
, tmp2
, tmp
, tmp4
, tmp5
);
6208 tcg_temp_free_i32(tmp
);
6209 if (insn
& (1 << 6)) {
6210 tmp
= neon_load_reg(rd
, 1);
6212 tmp
= tcg_temp_new_i32();
6213 tcg_gen_movi_i32(tmp
, 0);
6215 tmp3
= neon_load_reg(rm
, 1);
6216 gen_helper_neon_tbl(tmp3
, cpu_env
, tmp3
, tmp
, tmp4
, tmp5
);
6217 tcg_temp_free_i32(tmp5
);
6218 tcg_temp_free_i32(tmp4
);
6219 neon_store_reg(rd
, 0, tmp2
);
6220 neon_store_reg(rd
, 1, tmp3
);
6221 tcg_temp_free_i32(tmp
);
6222 } else if ((insn
& 0x380) == 0) {
6224 if ((insn
& (7 << 16)) == 0 || (q
&& (rd
& 1))) {
6227 if (insn
& (1 << 19)) {
6228 tmp
= neon_load_reg(rm
, 1);
6230 tmp
= neon_load_reg(rm
, 0);
6232 if (insn
& (1 << 16)) {
6233 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
6234 } else if (insn
& (1 << 17)) {
6235 if ((insn
>> 18) & 1)
6236 gen_neon_dup_high16(tmp
);
6238 gen_neon_dup_low16(tmp
);
6240 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
6241 tmp2
= tcg_temp_new_i32();
6242 tcg_gen_mov_i32(tmp2
, tmp
);
6243 neon_store_reg(rd
, pass
, tmp2
);
6245 tcg_temp_free_i32(tmp
);
6254 static int disas_coproc_insn(CPUARMState
* env
, DisasContext
*s
, uint32_t insn
)
6256 int cpnum
, is64
, crn
, crm
, opc1
, opc2
, isread
, rt
, rt2
;
6257 const ARMCPRegInfo
*ri
;
6258 ARMCPU
*cpu
= arm_env_get_cpu(env
);
6260 cpnum
= (insn
>> 8) & 0xf;
6261 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
6262 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
6265 /* First check for coprocessor space used for actual instructions */
6269 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
6270 return disas_iwmmxt_insn(env
, s
, insn
);
6271 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
6272 return disas_dsp_insn(env
, s
, insn
);
6277 return disas_vfp_insn (env
, s
, insn
);
6282 /* Otherwise treat as a generic register access */
6283 is64
= (insn
& (1 << 25)) == 0;
6284 if (!is64
&& ((insn
& (1 << 4)) == 0)) {
6292 opc1
= (insn
>> 4) & 0xf;
6294 rt2
= (insn
>> 16) & 0xf;
6296 crn
= (insn
>> 16) & 0xf;
6297 opc1
= (insn
>> 21) & 7;
6298 opc2
= (insn
>> 5) & 7;
6301 isread
= (insn
>> 20) & 1;
6302 rt
= (insn
>> 12) & 0xf;
6304 ri
= get_arm_cp_reginfo(cpu
,
6305 ENCODE_CP_REG(cpnum
, is64
, crn
, crm
, opc1
, opc2
));
6307 /* Check access permissions */
6308 if (!cp_access_ok(env
, ri
, isread
)) {
6312 /* Handle special cases first */
6313 switch (ri
->type
& ~(ARM_CP_FLAG_MASK
& ~ARM_CP_SPECIAL
)) {
6320 gen_set_pc_im(s
->pc
);
6321 s
->is_jmp
= DISAS_WFI
;
6332 if (ri
->type
& ARM_CP_CONST
) {
6333 tmp64
= tcg_const_i64(ri
->resetvalue
);
6334 } else if (ri
->readfn
) {
6336 gen_set_pc_im(s
->pc
);
6337 tmp64
= tcg_temp_new_i64();
6338 tmpptr
= tcg_const_ptr(ri
);
6339 gen_helper_get_cp_reg64(tmp64
, cpu_env
, tmpptr
);
6340 tcg_temp_free_ptr(tmpptr
);
6342 tmp64
= tcg_temp_new_i64();
6343 tcg_gen_ld_i64(tmp64
, cpu_env
, ri
->fieldoffset
);
6345 tmp
= tcg_temp_new_i32();
6346 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6347 store_reg(s
, rt
, tmp
);
6348 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6349 tmp
= tcg_temp_new_i32();
6350 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6351 tcg_temp_free_i64(tmp64
);
6352 store_reg(s
, rt2
, tmp
);
6355 if (ri
->type
& ARM_CP_CONST
) {
6356 tmp
= tcg_const_i32(ri
->resetvalue
);
6357 } else if (ri
->readfn
) {
6359 gen_set_pc_im(s
->pc
);
6360 tmp
= tcg_temp_new_i32();
6361 tmpptr
= tcg_const_ptr(ri
);
6362 gen_helper_get_cp_reg(tmp
, cpu_env
, tmpptr
);
6363 tcg_temp_free_ptr(tmpptr
);
6365 tmp
= load_cpu_offset(ri
->fieldoffset
);
6368 /* Destination register of r15 for 32 bit loads sets
6369 * the condition codes from the high 4 bits of the value
6372 tcg_temp_free_i32(tmp
);
6374 store_reg(s
, rt
, tmp
);
6379 if (ri
->type
& ARM_CP_CONST
) {
6380 /* If not forbidden by access permissions, treat as WI */
6385 TCGv_i32 tmplo
, tmphi
;
6386 TCGv_i64 tmp64
= tcg_temp_new_i64();
6387 tmplo
= load_reg(s
, rt
);
6388 tmphi
= load_reg(s
, rt2
);
6389 tcg_gen_concat_i32_i64(tmp64
, tmplo
, tmphi
);
6390 tcg_temp_free_i32(tmplo
);
6391 tcg_temp_free_i32(tmphi
);
6393 TCGv_ptr tmpptr
= tcg_const_ptr(ri
);
6394 gen_set_pc_im(s
->pc
);
6395 gen_helper_set_cp_reg64(cpu_env
, tmpptr
, tmp64
);
6396 tcg_temp_free_ptr(tmpptr
);
6398 tcg_gen_st_i64(tmp64
, cpu_env
, ri
->fieldoffset
);
6400 tcg_temp_free_i64(tmp64
);
6405 gen_set_pc_im(s
->pc
);
6406 tmp
= load_reg(s
, rt
);
6407 tmpptr
= tcg_const_ptr(ri
);
6408 gen_helper_set_cp_reg(cpu_env
, tmpptr
, tmp
);
6409 tcg_temp_free_ptr(tmpptr
);
6410 tcg_temp_free_i32(tmp
);
6412 TCGv_i32 tmp
= load_reg(s
, rt
);
6413 store_cpu_offset(tmp
, ri
->fieldoffset
);
6416 /* We default to ending the TB on a coprocessor register write,
6417 * but allow this to be suppressed by the register definition
6418 * (usually only necessary to work around guest bugs).
6420 if (!(ri
->type
& ARM_CP_SUPPRESS_TB_END
)) {
6431 /* Store a 64-bit value to a register pair. Clobbers val. */
6432 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
6435 tmp
= tcg_temp_new_i32();
6436 tcg_gen_trunc_i64_i32(tmp
, val
);
6437 store_reg(s
, rlow
, tmp
);
6438 tmp
= tcg_temp_new_i32();
6439 tcg_gen_shri_i64(val
, val
, 32);
6440 tcg_gen_trunc_i64_i32(tmp
, val
);
6441 store_reg(s
, rhigh
, tmp
);
6444 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6445 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
6450 /* Load value and extend to 64 bits. */
6451 tmp
= tcg_temp_new_i64();
6452 tmp2
= load_reg(s
, rlow
);
6453 tcg_gen_extu_i32_i64(tmp
, tmp2
);
6454 tcg_temp_free_i32(tmp2
);
6455 tcg_gen_add_i64(val
, val
, tmp
);
6456 tcg_temp_free_i64(tmp
);
6459 /* load and add a 64-bit value from a register pair. */
6460 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
6466 /* Load 64-bit value rd:rn. */
6467 tmpl
= load_reg(s
, rlow
);
6468 tmph
= load_reg(s
, rhigh
);
6469 tmp
= tcg_temp_new_i64();
6470 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
6471 tcg_temp_free_i32(tmpl
);
6472 tcg_temp_free_i32(tmph
);
6473 tcg_gen_add_i64(val
, val
, tmp
);
6474 tcg_temp_free_i64(tmp
);
6477 /* Set N and Z flags from hi|lo. */
6478 static void gen_logicq_cc(TCGv_i32 lo
, TCGv_i32 hi
)
6480 tcg_gen_mov_i32(cpu_NF
, hi
);
6481 tcg_gen_or_i32(cpu_ZF
, lo
, hi
);
6484 /* Load/Store exclusive instructions are implemented by remembering
6485 the value/address loaded, and seeing if these are the same
6486 when the store is performed. This should be sufficient to implement
6487 the architecturally mandated semantics, and avoids having to monitor
6490 In system emulation mode only one CPU will be running at once, so
6491 this sequence is effectively atomic. In user emulation mode we
6492 throw an exception and handle the atomic operation elsewhere. */
6493 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
6494 TCGv_i32 addr
, int size
)
6496 TCGv_i32 tmp
= tcg_temp_new_i32();
6500 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
6503 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
6507 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
6512 tcg_gen_mov_i32(cpu_exclusive_val
, tmp
);
6513 store_reg(s
, rt
, tmp
);
6515 TCGv_i32 tmp2
= tcg_temp_new_i32();
6516 tcg_gen_addi_i32(tmp2
, addr
, 4);
6517 tmp
= tcg_temp_new_i32();
6518 tcg_gen_qemu_ld32u(tmp
, tmp2
, IS_USER(s
));
6519 tcg_temp_free_i32(tmp2
);
6520 tcg_gen_mov_i32(cpu_exclusive_high
, tmp
);
6521 store_reg(s
, rt2
, tmp
);
6523 tcg_gen_mov_i32(cpu_exclusive_addr
, addr
);
6526 static void gen_clrex(DisasContext
*s
)
6528 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
6531 #ifdef CONFIG_USER_ONLY
6532 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
6533 TCGv_i32 addr
, int size
)
6535 tcg_gen_mov_i32(cpu_exclusive_test
, addr
);
6536 tcg_gen_movi_i32(cpu_exclusive_info
,
6537 size
| (rd
<< 4) | (rt
<< 8) | (rt2
<< 12));
6538 gen_exception_insn(s
, 4, EXCP_STREX
);
6541 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
6542 TCGv_i32 addr
, int size
)
6548 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6554 fail_label
= gen_new_label();
6555 done_label
= gen_new_label();
6556 tcg_gen_brcond_i32(TCG_COND_NE
, addr
, cpu_exclusive_addr
, fail_label
);
6557 tmp
= tcg_temp_new_i32();
6560 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
6563 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
6567 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
6572 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_val
, fail_label
);
6573 tcg_temp_free_i32(tmp
);
6575 TCGv_i32 tmp2
= tcg_temp_new_i32();
6576 tcg_gen_addi_i32(tmp2
, addr
, 4);
6577 tmp
= tcg_temp_new_i32();
6578 tcg_gen_qemu_ld32u(tmp
, tmp2
, IS_USER(s
));
6579 tcg_temp_free_i32(tmp2
);
6580 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_high
, fail_label
);
6581 tcg_temp_free_i32(tmp
);
6583 tmp
= load_reg(s
, rt
);
6586 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
6589 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
6593 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
6598 tcg_temp_free_i32(tmp
);
6600 tcg_gen_addi_i32(addr
, addr
, 4);
6601 tmp
= load_reg(s
, rt2
);
6602 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
6603 tcg_temp_free_i32(tmp
);
6605 tcg_gen_movi_i32(cpu_R
[rd
], 0);
6606 tcg_gen_br(done_label
);
6607 gen_set_label(fail_label
);
6608 tcg_gen_movi_i32(cpu_R
[rd
], 1);
6609 gen_set_label(done_label
);
6610 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
6617 * @mode: mode field from insn (which stack to store to)
6618 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
6619 * @writeback: true if writeback bit set
6621 * Generate code for the SRS (Store Return State) insn.
6623 static void gen_srs(DisasContext
*s
,
6624 uint32_t mode
, uint32_t amode
, bool writeback
)
6627 TCGv_i32 addr
= tcg_temp_new_i32();
6628 TCGv_i32 tmp
= tcg_const_i32(mode
);
6629 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
6630 tcg_temp_free_i32(tmp
);
6647 tcg_gen_addi_i32(addr
, addr
, offset
);
6648 tmp
= load_reg(s
, 14);
6649 tcg_gen_qemu_st32(tmp
, addr
, 0);
6650 tcg_temp_free_i32(tmp
);
6651 tmp
= load_cpu_field(spsr
);
6652 tcg_gen_addi_i32(addr
, addr
, 4);
6653 tcg_gen_qemu_st32(tmp
, addr
, 0);
6654 tcg_temp_free_i32(tmp
);
6672 tcg_gen_addi_i32(addr
, addr
, offset
);
6673 tmp
= tcg_const_i32(mode
);
6674 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
6675 tcg_temp_free_i32(tmp
);
6677 tcg_temp_free_i32(addr
);
6680 static void disas_arm_insn(CPUARMState
* env
, DisasContext
*s
)
6682 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
6689 insn
= arm_ldl_code(env
, s
->pc
, s
->bswap_code
);
6692 /* M variants do not implement ARM mode. */
6697 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6698 * choose to UNDEF. In ARMv5 and above the space is used
6699 * for miscellaneous unconditional instructions.
6703 /* Unconditional instructions. */
6704 if (((insn
>> 25) & 7) == 1) {
6705 /* NEON Data processing. */
6706 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6709 if (disas_neon_data_insn(env
, s
, insn
))
6713 if ((insn
& 0x0f100000) == 0x04000000) {
6714 /* NEON load/store. */
6715 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6718 if (disas_neon_ls_insn(env
, s
, insn
))
6722 if (((insn
& 0x0f30f000) == 0x0510f000) ||
6723 ((insn
& 0x0f30f010) == 0x0710f000)) {
6724 if ((insn
& (1 << 22)) == 0) {
6726 if (!arm_feature(env
, ARM_FEATURE_V7MP
)) {
6730 /* Otherwise PLD; v5TE+ */
6734 if (((insn
& 0x0f70f000) == 0x0450f000) ||
6735 ((insn
& 0x0f70f010) == 0x0650f000)) {
6737 return; /* PLI; V7 */
6739 if (((insn
& 0x0f700000) == 0x04100000) ||
6740 ((insn
& 0x0f700010) == 0x06100000)) {
6741 if (!arm_feature(env
, ARM_FEATURE_V7MP
)) {
6744 return; /* v7MP: Unallocated memory hint: must NOP */
6747 if ((insn
& 0x0ffffdff) == 0x01010000) {
6750 if (((insn
>> 9) & 1) != s
->bswap_code
) {
6751 /* Dynamic endianness switching not implemented. */
6755 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
6756 switch ((insn
>> 4) & 0xf) {
6765 /* We don't emulate caches so these are a no-op. */
6770 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
6776 gen_srs(s
, (insn
& 0x1f), (insn
>> 23) & 3, insn
& (1 << 21));
6778 } else if ((insn
& 0x0e50ffe0) == 0x08100a00) {
6784 rn
= (insn
>> 16) & 0xf;
6785 addr
= load_reg(s
, rn
);
6786 i
= (insn
>> 23) & 3;
6788 case 0: offset
= -4; break; /* DA */
6789 case 1: offset
= 0; break; /* IA */
6790 case 2: offset
= -8; break; /* DB */
6791 case 3: offset
= 4; break; /* IB */
6795 tcg_gen_addi_i32(addr
, addr
, offset
);
6796 /* Load PC into tmp and CPSR into tmp2. */
6797 tmp
= tcg_temp_new_i32();
6798 tcg_gen_qemu_ld32u(tmp
, addr
, 0);
6799 tcg_gen_addi_i32(addr
, addr
, 4);
6800 tmp2
= tcg_temp_new_i32();
6801 tcg_gen_qemu_ld32u(tmp
, addr
, 0);
6802 if (insn
& (1 << 21)) {
6803 /* Base writeback. */
6805 case 0: offset
= -8; break;
6806 case 1: offset
= 4; break;
6807 case 2: offset
= -4; break;
6808 case 3: offset
= 0; break;
6812 tcg_gen_addi_i32(addr
, addr
, offset
);
6813 store_reg(s
, rn
, addr
);
6815 tcg_temp_free_i32(addr
);
6817 gen_rfe(s
, tmp
, tmp2
);
6819 } else if ((insn
& 0x0e000000) == 0x0a000000) {
6820 /* branch link and change to thumb (blx <offset>) */
6823 val
= (uint32_t)s
->pc
;
6824 tmp
= tcg_temp_new_i32();
6825 tcg_gen_movi_i32(tmp
, val
);
6826 store_reg(s
, 14, tmp
);
6827 /* Sign-extend the 24-bit offset */
6828 offset
= (((int32_t)insn
) << 8) >> 8;
6829 /* offset * 4 + bit24 * 2 + (thumb bit) */
6830 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
6831 /* pipeline offset */
6833 /* protected by ARCH(5); above, near the start of uncond block */
6836 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
6837 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
6838 /* iWMMXt register transfer. */
6839 if (env
->cp15
.c15_cpar
& (1 << 1))
6840 if (!disas_iwmmxt_insn(env
, s
, insn
))
6843 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
6844 /* Coprocessor double register transfer. */
6846 } else if ((insn
& 0x0f000010) == 0x0e000010) {
6847 /* Additional coprocessor register transfer. */
6848 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6851 /* cps (privileged) */
6855 if (insn
& (1 << 19)) {
6856 if (insn
& (1 << 8))
6858 if (insn
& (1 << 7))
6860 if (insn
& (1 << 6))
6862 if (insn
& (1 << 18))
6865 if (insn
& (1 << 17)) {
6867 val
|= (insn
& 0x1f);
6870 gen_set_psr_im(s
, mask
, 0, val
);
6877 /* if not always execute, we generate a conditional jump to
6879 s
->condlabel
= gen_new_label();
6880 gen_test_cc(cond
^ 1, s
->condlabel
);
6883 if ((insn
& 0x0f900000) == 0x03000000) {
6884 if ((insn
& (1 << 21)) == 0) {
6886 rd
= (insn
>> 12) & 0xf;
6887 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6888 if ((insn
& (1 << 22)) == 0) {
6890 tmp
= tcg_temp_new_i32();
6891 tcg_gen_movi_i32(tmp
, val
);
6894 tmp
= load_reg(s
, rd
);
6895 tcg_gen_ext16u_i32(tmp
, tmp
);
6896 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6898 store_reg(s
, rd
, tmp
);
6900 if (((insn
>> 12) & 0xf) != 0xf)
6902 if (((insn
>> 16) & 0xf) == 0) {
6903 gen_nop_hint(s
, insn
& 0xff);
6905 /* CPSR = immediate */
6907 shift
= ((insn
>> 8) & 0xf) * 2;
6909 val
= (val
>> shift
) | (val
<< (32 - shift
));
6910 i
= ((insn
& (1 << 22)) != 0);
6911 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6915 } else if ((insn
& 0x0f900000) == 0x01000000
6916 && (insn
& 0x00000090) != 0x00000090) {
6917 /* miscellaneous instructions */
6918 op1
= (insn
>> 21) & 3;
6919 sh
= (insn
>> 4) & 0xf;
6922 case 0x0: /* move program status register */
6925 tmp
= load_reg(s
, rm
);
6926 i
= ((op1
& 2) != 0);
6927 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6931 rd
= (insn
>> 12) & 0xf;
6935 tmp
= load_cpu_field(spsr
);
6937 tmp
= tcg_temp_new_i32();
6938 gen_helper_cpsr_read(tmp
, cpu_env
);
6940 store_reg(s
, rd
, tmp
);
6945 /* branch/exchange thumb (bx). */
6947 tmp
= load_reg(s
, rm
);
6949 } else if (op1
== 3) {
6952 rd
= (insn
>> 12) & 0xf;
6953 tmp
= load_reg(s
, rm
);
6954 gen_helper_clz(tmp
, tmp
);
6955 store_reg(s
, rd
, tmp
);
6963 /* Trivial implementation equivalent to bx. */
6964 tmp
= load_reg(s
, rm
);
6975 /* branch link/exchange thumb (blx) */
6976 tmp
= load_reg(s
, rm
);
6977 tmp2
= tcg_temp_new_i32();
6978 tcg_gen_movi_i32(tmp2
, s
->pc
);
6979 store_reg(s
, 14, tmp2
);
6982 case 0x5: /* saturating add/subtract */
6984 rd
= (insn
>> 12) & 0xf;
6985 rn
= (insn
>> 16) & 0xf;
6986 tmp
= load_reg(s
, rm
);
6987 tmp2
= load_reg(s
, rn
);
6989 gen_helper_double_saturate(tmp2
, cpu_env
, tmp2
);
6991 gen_helper_sub_saturate(tmp
, cpu_env
, tmp
, tmp2
);
6993 gen_helper_add_saturate(tmp
, cpu_env
, tmp
, tmp2
);
6994 tcg_temp_free_i32(tmp2
);
6995 store_reg(s
, rd
, tmp
);
6998 /* SMC instruction (op1 == 3)
6999 and undefined instructions (op1 == 0 || op1 == 2)
7006 gen_exception_insn(s
, 4, EXCP_BKPT
);
7008 case 0x8: /* signed multiply */
7013 rs
= (insn
>> 8) & 0xf;
7014 rn
= (insn
>> 12) & 0xf;
7015 rd
= (insn
>> 16) & 0xf;
7017 /* (32 * 16) >> 16 */
7018 tmp
= load_reg(s
, rm
);
7019 tmp2
= load_reg(s
, rs
);
7021 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
7024 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7025 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
7026 tmp
= tcg_temp_new_i32();
7027 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7028 tcg_temp_free_i64(tmp64
);
7029 if ((sh
& 2) == 0) {
7030 tmp2
= load_reg(s
, rn
);
7031 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
7032 tcg_temp_free_i32(tmp2
);
7034 store_reg(s
, rd
, tmp
);
7037 tmp
= load_reg(s
, rm
);
7038 tmp2
= load_reg(s
, rs
);
7039 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
7040 tcg_temp_free_i32(tmp2
);
7042 tmp64
= tcg_temp_new_i64();
7043 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7044 tcg_temp_free_i32(tmp
);
7045 gen_addq(s
, tmp64
, rn
, rd
);
7046 gen_storeq_reg(s
, rn
, rd
, tmp64
);
7047 tcg_temp_free_i64(tmp64
);
7050 tmp2
= load_reg(s
, rn
);
7051 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
7052 tcg_temp_free_i32(tmp2
);
7054 store_reg(s
, rd
, tmp
);
7061 } else if (((insn
& 0x0e000000) == 0 &&
7062 (insn
& 0x00000090) != 0x90) ||
7063 ((insn
& 0x0e000000) == (1 << 25))) {
7064 int set_cc
, logic_cc
, shiftop
;
7066 op1
= (insn
>> 21) & 0xf;
7067 set_cc
= (insn
>> 20) & 1;
7068 logic_cc
= table_logic_cc
[op1
] & set_cc
;
7070 /* data processing instruction */
7071 if (insn
& (1 << 25)) {
7072 /* immediate operand */
7074 shift
= ((insn
>> 8) & 0xf) * 2;
7076 val
= (val
>> shift
) | (val
<< (32 - shift
));
7078 tmp2
= tcg_temp_new_i32();
7079 tcg_gen_movi_i32(tmp2
, val
);
7080 if (logic_cc
&& shift
) {
7081 gen_set_CF_bit31(tmp2
);
7086 tmp2
= load_reg(s
, rm
);
7087 shiftop
= (insn
>> 5) & 3;
7088 if (!(insn
& (1 << 4))) {
7089 shift
= (insn
>> 7) & 0x1f;
7090 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7092 rs
= (insn
>> 8) & 0xf;
7093 tmp
= load_reg(s
, rs
);
7094 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
7097 if (op1
!= 0x0f && op1
!= 0x0d) {
7098 rn
= (insn
>> 16) & 0xf;
7099 tmp
= load_reg(s
, rn
);
7101 TCGV_UNUSED_I32(tmp
);
7103 rd
= (insn
>> 12) & 0xf;
7106 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
7110 store_reg_bx(env
, s
, rd
, tmp
);
7113 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
7117 store_reg_bx(env
, s
, rd
, tmp
);
7120 if (set_cc
&& rd
== 15) {
7121 /* SUBS r15, ... is used for exception return. */
7125 gen_sub_CC(tmp
, tmp
, tmp2
);
7126 gen_exception_return(s
, tmp
);
7129 gen_sub_CC(tmp
, tmp
, tmp2
);
7131 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7133 store_reg_bx(env
, s
, rd
, tmp
);
7138 gen_sub_CC(tmp
, tmp2
, tmp
);
7140 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7142 store_reg_bx(env
, s
, rd
, tmp
);
7146 gen_add_CC(tmp
, tmp
, tmp2
);
7148 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7150 store_reg_bx(env
, s
, rd
, tmp
);
7154 gen_adc_CC(tmp
, tmp
, tmp2
);
7156 gen_add_carry(tmp
, tmp
, tmp2
);
7158 store_reg_bx(env
, s
, rd
, tmp
);
7162 gen_sbc_CC(tmp
, tmp
, tmp2
);
7164 gen_sub_carry(tmp
, tmp
, tmp2
);
7166 store_reg_bx(env
, s
, rd
, tmp
);
7170 gen_sbc_CC(tmp
, tmp2
, tmp
);
7172 gen_sub_carry(tmp
, tmp2
, tmp
);
7174 store_reg_bx(env
, s
, rd
, tmp
);
7178 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
7181 tcg_temp_free_i32(tmp
);
7185 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
7188 tcg_temp_free_i32(tmp
);
7192 gen_sub_CC(tmp
, tmp
, tmp2
);
7194 tcg_temp_free_i32(tmp
);
7198 gen_add_CC(tmp
, tmp
, tmp2
);
7200 tcg_temp_free_i32(tmp
);
7203 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
7207 store_reg_bx(env
, s
, rd
, tmp
);
7210 if (logic_cc
&& rd
== 15) {
7211 /* MOVS r15, ... is used for exception return. */
7215 gen_exception_return(s
, tmp2
);
7220 store_reg_bx(env
, s
, rd
, tmp2
);
7224 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
7228 store_reg_bx(env
, s
, rd
, tmp
);
7232 tcg_gen_not_i32(tmp2
, tmp2
);
7236 store_reg_bx(env
, s
, rd
, tmp2
);
7239 if (op1
!= 0x0f && op1
!= 0x0d) {
7240 tcg_temp_free_i32(tmp2
);
7243 /* other instructions */
7244 op1
= (insn
>> 24) & 0xf;
7248 /* multiplies, extra load/stores */
7249 sh
= (insn
>> 5) & 3;
7252 rd
= (insn
>> 16) & 0xf;
7253 rn
= (insn
>> 12) & 0xf;
7254 rs
= (insn
>> 8) & 0xf;
7256 op1
= (insn
>> 20) & 0xf;
7258 case 0: case 1: case 2: case 3: case 6:
7260 tmp
= load_reg(s
, rs
);
7261 tmp2
= load_reg(s
, rm
);
7262 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7263 tcg_temp_free_i32(tmp2
);
7264 if (insn
& (1 << 22)) {
7265 /* Subtract (mls) */
7267 tmp2
= load_reg(s
, rn
);
7268 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7269 tcg_temp_free_i32(tmp2
);
7270 } else if (insn
& (1 << 21)) {
7272 tmp2
= load_reg(s
, rn
);
7273 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7274 tcg_temp_free_i32(tmp2
);
7276 if (insn
& (1 << 20))
7278 store_reg(s
, rd
, tmp
);
7281 /* 64 bit mul double accumulate (UMAAL) */
7283 tmp
= load_reg(s
, rs
);
7284 tmp2
= load_reg(s
, rm
);
7285 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7286 gen_addq_lo(s
, tmp64
, rn
);
7287 gen_addq_lo(s
, tmp64
, rd
);
7288 gen_storeq_reg(s
, rn
, rd
, tmp64
);
7289 tcg_temp_free_i64(tmp64
);
7291 case 8: case 9: case 10: case 11:
7292 case 12: case 13: case 14: case 15:
7293 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7294 tmp
= load_reg(s
, rs
);
7295 tmp2
= load_reg(s
, rm
);
7296 if (insn
& (1 << 22)) {
7297 tcg_gen_muls2_i32(tmp
, tmp2
, tmp
, tmp2
);
7299 tcg_gen_mulu2_i32(tmp
, tmp2
, tmp
, tmp2
);
7301 if (insn
& (1 << 21)) { /* mult accumulate */
7302 TCGv_i32 al
= load_reg(s
, rn
);
7303 TCGv_i32 ah
= load_reg(s
, rd
);
7304 tcg_gen_add2_i32(tmp
, tmp2
, tmp
, tmp2
, al
, ah
);
7305 tcg_temp_free_i32(al
);
7306 tcg_temp_free_i32(ah
);
7308 if (insn
& (1 << 20)) {
7309 gen_logicq_cc(tmp
, tmp2
);
7311 store_reg(s
, rn
, tmp
);
7312 store_reg(s
, rd
, tmp2
);
7318 rn
= (insn
>> 16) & 0xf;
7319 rd
= (insn
>> 12) & 0xf;
7320 if (insn
& (1 << 23)) {
7321 /* load/store exclusive */
7322 op1
= (insn
>> 21) & 0x3;
7327 addr
= tcg_temp_local_new_i32();
7328 load_reg_var(s
, addr
, rn
);
7329 if (insn
& (1 << 20)) {
7332 gen_load_exclusive(s
, rd
, 15, addr
, 2);
7334 case 1: /* ldrexd */
7335 gen_load_exclusive(s
, rd
, rd
+ 1, addr
, 3);
7337 case 2: /* ldrexb */
7338 gen_load_exclusive(s
, rd
, 15, addr
, 0);
7340 case 3: /* ldrexh */
7341 gen_load_exclusive(s
, rd
, 15, addr
, 1);
7350 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 2);
7352 case 1: /* strexd */
7353 gen_store_exclusive(s
, rd
, rm
, rm
+ 1, addr
, 3);
7355 case 2: /* strexb */
7356 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 0);
7358 case 3: /* strexh */
7359 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 1);
7365 tcg_temp_free_i32(addr
);
7367 /* SWP instruction */
7370 /* ??? This is not really atomic. However we know
7371 we never have multiple CPUs running in parallel,
7372 so it is good enough. */
7373 addr
= load_reg(s
, rn
);
7374 tmp
= load_reg(s
, rm
);
7375 tmp2
= tcg_temp_new_i32();
7376 if (insn
& (1 << 22)) {
7377 tcg_gen_qemu_ld8u(tmp2
, addr
, IS_USER(s
));
7378 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
7380 tcg_gen_qemu_ld32u(tmp2
, addr
, IS_USER(s
));
7381 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
7383 tcg_temp_free_i32(tmp
);
7384 tcg_temp_free_i32(addr
);
7385 store_reg(s
, rd
, tmp2
);
7391 /* Misc load/store */
7392 rn
= (insn
>> 16) & 0xf;
7393 rd
= (insn
>> 12) & 0xf;
7394 addr
= load_reg(s
, rn
);
7395 if (insn
& (1 << 24))
7396 gen_add_datah_offset(s
, insn
, 0, addr
);
7398 if (insn
& (1 << 20)) {
7400 tmp
= tcg_temp_new_i32();
7403 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
7406 tcg_gen_qemu_ld8s(tmp
, addr
, IS_USER(s
));
7410 tcg_gen_qemu_ld16s(tmp
, addr
, IS_USER(s
));
7414 } else if (sh
& 2) {
7419 tmp
= load_reg(s
, rd
);
7420 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
7421 tcg_temp_free_i32(tmp
);
7422 tcg_gen_addi_i32(addr
, addr
, 4);
7423 tmp
= load_reg(s
, rd
+ 1);
7424 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
7425 tcg_temp_free_i32(tmp
);
7429 tmp
= tcg_temp_new_i32();
7430 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
7431 store_reg(s
, rd
, tmp
);
7432 tcg_gen_addi_i32(addr
, addr
, 4);
7433 tmp
= tcg_temp_new_i32();
7434 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
7438 address_offset
= -4;
7441 tmp
= load_reg(s
, rd
);
7442 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
7443 tcg_temp_free_i32(tmp
);
7446 /* Perform base writeback before the loaded value to
7447 ensure correct behavior with overlapping index registers.
7448 ldrd with base writeback is is undefined if the
7449 destination and index registers overlap. */
7450 if (!(insn
& (1 << 24))) {
7451 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
7452 store_reg(s
, rn
, addr
);
7453 } else if (insn
& (1 << 21)) {
7455 tcg_gen_addi_i32(addr
, addr
, address_offset
);
7456 store_reg(s
, rn
, addr
);
7458 tcg_temp_free_i32(addr
);
7461 /* Complete the load. */
7462 store_reg(s
, rd
, tmp
);
7471 if (insn
& (1 << 4)) {
7473 /* Armv6 Media instructions. */
7475 rn
= (insn
>> 16) & 0xf;
7476 rd
= (insn
>> 12) & 0xf;
7477 rs
= (insn
>> 8) & 0xf;
7478 switch ((insn
>> 23) & 3) {
7479 case 0: /* Parallel add/subtract. */
7480 op1
= (insn
>> 20) & 7;
7481 tmp
= load_reg(s
, rn
);
7482 tmp2
= load_reg(s
, rm
);
7483 sh
= (insn
>> 5) & 7;
7484 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
7486 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
7487 tcg_temp_free_i32(tmp2
);
7488 store_reg(s
, rd
, tmp
);
7491 if ((insn
& 0x00700020) == 0) {
7492 /* Halfword pack. */
7493 tmp
= load_reg(s
, rn
);
7494 tmp2
= load_reg(s
, rm
);
7495 shift
= (insn
>> 7) & 0x1f;
7496 if (insn
& (1 << 6)) {
7500 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
7501 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
7502 tcg_gen_ext16u_i32(tmp2
, tmp2
);
7506 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
7507 tcg_gen_ext16u_i32(tmp
, tmp
);
7508 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
7510 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
7511 tcg_temp_free_i32(tmp2
);
7512 store_reg(s
, rd
, tmp
);
7513 } else if ((insn
& 0x00200020) == 0x00200000) {
7515 tmp
= load_reg(s
, rm
);
7516 shift
= (insn
>> 7) & 0x1f;
7517 if (insn
& (1 << 6)) {
7520 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7522 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7524 sh
= (insn
>> 16) & 0x1f;
7525 tmp2
= tcg_const_i32(sh
);
7526 if (insn
& (1 << 22))
7527 gen_helper_usat(tmp
, cpu_env
, tmp
, tmp2
);
7529 gen_helper_ssat(tmp
, cpu_env
, tmp
, tmp2
);
7530 tcg_temp_free_i32(tmp2
);
7531 store_reg(s
, rd
, tmp
);
7532 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
7534 tmp
= load_reg(s
, rm
);
7535 sh
= (insn
>> 16) & 0x1f;
7536 tmp2
= tcg_const_i32(sh
);
7537 if (insn
& (1 << 22))
7538 gen_helper_usat16(tmp
, cpu_env
, tmp
, tmp2
);
7540 gen_helper_ssat16(tmp
, cpu_env
, tmp
, tmp2
);
7541 tcg_temp_free_i32(tmp2
);
7542 store_reg(s
, rd
, tmp
);
7543 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
7545 tmp
= load_reg(s
, rn
);
7546 tmp2
= load_reg(s
, rm
);
7547 tmp3
= tcg_temp_new_i32();
7548 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUARMState
, GE
));
7549 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7550 tcg_temp_free_i32(tmp3
);
7551 tcg_temp_free_i32(tmp2
);
7552 store_reg(s
, rd
, tmp
);
7553 } else if ((insn
& 0x000003e0) == 0x00000060) {
7554 tmp
= load_reg(s
, rm
);
7555 shift
= (insn
>> 10) & 3;
7556 /* ??? In many cases it's not necessary to do a
7557 rotate, a shift is sufficient. */
7559 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7560 op1
= (insn
>> 20) & 7;
7562 case 0: gen_sxtb16(tmp
); break;
7563 case 2: gen_sxtb(tmp
); break;
7564 case 3: gen_sxth(tmp
); break;
7565 case 4: gen_uxtb16(tmp
); break;
7566 case 6: gen_uxtb(tmp
); break;
7567 case 7: gen_uxth(tmp
); break;
7568 default: goto illegal_op
;
7571 tmp2
= load_reg(s
, rn
);
7572 if ((op1
& 3) == 0) {
7573 gen_add16(tmp
, tmp2
);
7575 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7576 tcg_temp_free_i32(tmp2
);
7579 store_reg(s
, rd
, tmp
);
7580 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
7582 tmp
= load_reg(s
, rm
);
7583 if (insn
& (1 << 22)) {
7584 if (insn
& (1 << 7)) {
7588 gen_helper_rbit(tmp
, tmp
);
7591 if (insn
& (1 << 7))
7594 tcg_gen_bswap32_i32(tmp
, tmp
);
7596 store_reg(s
, rd
, tmp
);
7601 case 2: /* Multiplies (Type 3). */
7602 switch ((insn
>> 20) & 0x7) {
7604 if (((insn
>> 6) ^ (insn
>> 7)) & 1) {
7605 /* op2 not 00x or 11x : UNDEF */
7608 /* Signed multiply most significant [accumulate].
7609 (SMMUL, SMMLA, SMMLS) */
7610 tmp
= load_reg(s
, rm
);
7611 tmp2
= load_reg(s
, rs
);
7612 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7615 tmp
= load_reg(s
, rd
);
7616 if (insn
& (1 << 6)) {
7617 tmp64
= gen_subq_msw(tmp64
, tmp
);
7619 tmp64
= gen_addq_msw(tmp64
, tmp
);
7622 if (insn
& (1 << 5)) {
7623 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
7625 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
7626 tmp
= tcg_temp_new_i32();
7627 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7628 tcg_temp_free_i64(tmp64
);
7629 store_reg(s
, rn
, tmp
);
7633 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
7634 if (insn
& (1 << 7)) {
7637 tmp
= load_reg(s
, rm
);
7638 tmp2
= load_reg(s
, rs
);
7639 if (insn
& (1 << 5))
7640 gen_swap_half(tmp2
);
7641 gen_smul_dual(tmp
, tmp2
);
7642 if (insn
& (1 << 6)) {
7643 /* This subtraction cannot overflow. */
7644 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7646 /* This addition cannot overflow 32 bits;
7647 * however it may overflow considered as a signed
7648 * operation, in which case we must set the Q flag.
7650 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
7652 tcg_temp_free_i32(tmp2
);
7653 if (insn
& (1 << 22)) {
7654 /* smlald, smlsld */
7655 tmp64
= tcg_temp_new_i64();
7656 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7657 tcg_temp_free_i32(tmp
);
7658 gen_addq(s
, tmp64
, rd
, rn
);
7659 gen_storeq_reg(s
, rd
, rn
, tmp64
);
7660 tcg_temp_free_i64(tmp64
);
7662 /* smuad, smusd, smlad, smlsd */
7665 tmp2
= load_reg(s
, rd
);
7666 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
7667 tcg_temp_free_i32(tmp2
);
7669 store_reg(s
, rn
, tmp
);
7675 if (!arm_feature(env
, ARM_FEATURE_ARM_DIV
)) {
7678 if (((insn
>> 5) & 7) || (rd
!= 15)) {
7681 tmp
= load_reg(s
, rm
);
7682 tmp2
= load_reg(s
, rs
);
7683 if (insn
& (1 << 21)) {
7684 gen_helper_udiv(tmp
, tmp
, tmp2
);
7686 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7688 tcg_temp_free_i32(tmp2
);
7689 store_reg(s
, rn
, tmp
);
7696 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
7698 case 0: /* Unsigned sum of absolute differences. */
7700 tmp
= load_reg(s
, rm
);
7701 tmp2
= load_reg(s
, rs
);
7702 gen_helper_usad8(tmp
, tmp
, tmp2
);
7703 tcg_temp_free_i32(tmp2
);
7705 tmp2
= load_reg(s
, rd
);
7706 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7707 tcg_temp_free_i32(tmp2
);
7709 store_reg(s
, rn
, tmp
);
7711 case 0x20: case 0x24: case 0x28: case 0x2c:
7712 /* Bitfield insert/clear. */
7714 shift
= (insn
>> 7) & 0x1f;
7715 i
= (insn
>> 16) & 0x1f;
7718 tmp
= tcg_temp_new_i32();
7719 tcg_gen_movi_i32(tmp
, 0);
7721 tmp
= load_reg(s
, rm
);
7724 tmp2
= load_reg(s
, rd
);
7725 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
, shift
, i
);
7726 tcg_temp_free_i32(tmp2
);
7728 store_reg(s
, rd
, tmp
);
7730 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7731 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7733 tmp
= load_reg(s
, rm
);
7734 shift
= (insn
>> 7) & 0x1f;
7735 i
= ((insn
>> 16) & 0x1f) + 1;
7740 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
7742 gen_sbfx(tmp
, shift
, i
);
7745 store_reg(s
, rd
, tmp
);
7755 /* Check for undefined extension instructions
7756 * per the ARM Bible IE:
7757 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7759 sh
= (0xf << 20) | (0xf << 4);
7760 if (op1
== 0x7 && ((insn
& sh
) == sh
))
7764 /* load/store byte/word */
7765 rn
= (insn
>> 16) & 0xf;
7766 rd
= (insn
>> 12) & 0xf;
7767 tmp2
= load_reg(s
, rn
);
7768 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
7769 if (insn
& (1 << 24))
7770 gen_add_data_offset(s
, insn
, tmp2
);
7771 if (insn
& (1 << 20)) {
7773 tmp
= tcg_temp_new_i32();
7774 if (insn
& (1 << 22)) {
7775 tcg_gen_qemu_ld8u(tmp
, tmp2
, i
);
7777 tcg_gen_qemu_ld32u(tmp
, tmp2
, i
);
7781 tmp
= load_reg(s
, rd
);
7782 if (insn
& (1 << 22)) {
7783 tcg_gen_qemu_st8(tmp
, tmp2
, i
);
7785 tcg_gen_qemu_st32(tmp
, tmp2
, i
);
7787 tcg_temp_free_i32(tmp
);
7789 if (!(insn
& (1 << 24))) {
7790 gen_add_data_offset(s
, insn
, tmp2
);
7791 store_reg(s
, rn
, tmp2
);
7792 } else if (insn
& (1 << 21)) {
7793 store_reg(s
, rn
, tmp2
);
7795 tcg_temp_free_i32(tmp2
);
7797 if (insn
& (1 << 20)) {
7798 /* Complete the load. */
7799 store_reg_from_load(env
, s
, rd
, tmp
);
7805 int j
, n
, user
, loaded_base
;
7806 TCGv_i32 loaded_var
;
7807 /* load/store multiple words */
7808 /* XXX: store correct base if write back */
7810 if (insn
& (1 << 22)) {
7812 goto illegal_op
; /* only usable in supervisor mode */
7814 if ((insn
& (1 << 15)) == 0)
7817 rn
= (insn
>> 16) & 0xf;
7818 addr
= load_reg(s
, rn
);
7820 /* compute total size */
7822 TCGV_UNUSED_I32(loaded_var
);
7825 if (insn
& (1 << i
))
7828 /* XXX: test invalid n == 0 case ? */
7829 if (insn
& (1 << 23)) {
7830 if (insn
& (1 << 24)) {
7832 tcg_gen_addi_i32(addr
, addr
, 4);
7834 /* post increment */
7837 if (insn
& (1 << 24)) {
7839 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7841 /* post decrement */
7843 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7848 if (insn
& (1 << i
)) {
7849 if (insn
& (1 << 20)) {
7851 tmp
= tcg_temp_new_i32();
7852 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
7854 tmp2
= tcg_const_i32(i
);
7855 gen_helper_set_user_reg(cpu_env
, tmp2
, tmp
);
7856 tcg_temp_free_i32(tmp2
);
7857 tcg_temp_free_i32(tmp
);
7858 } else if (i
== rn
) {
7862 store_reg_from_load(env
, s
, i
, tmp
);
7867 /* special case: r15 = PC + 8 */
7868 val
= (long)s
->pc
+ 4;
7869 tmp
= tcg_temp_new_i32();
7870 tcg_gen_movi_i32(tmp
, val
);
7872 tmp
= tcg_temp_new_i32();
7873 tmp2
= tcg_const_i32(i
);
7874 gen_helper_get_user_reg(tmp
, cpu_env
, tmp2
);
7875 tcg_temp_free_i32(tmp2
);
7877 tmp
= load_reg(s
, i
);
7879 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
7880 tcg_temp_free_i32(tmp
);
7883 /* no need to add after the last transfer */
7885 tcg_gen_addi_i32(addr
, addr
, 4);
7888 if (insn
& (1 << 21)) {
7890 if (insn
& (1 << 23)) {
7891 if (insn
& (1 << 24)) {
7894 /* post increment */
7895 tcg_gen_addi_i32(addr
, addr
, 4);
7898 if (insn
& (1 << 24)) {
7901 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7903 /* post decrement */
7904 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7907 store_reg(s
, rn
, addr
);
7909 tcg_temp_free_i32(addr
);
7912 store_reg(s
, rn
, loaded_var
);
7914 if ((insn
& (1 << 22)) && !user
) {
7915 /* Restore CPSR from SPSR. */
7916 tmp
= load_cpu_field(spsr
);
7917 gen_set_cpsr(tmp
, 0xffffffff);
7918 tcg_temp_free_i32(tmp
);
7919 s
->is_jmp
= DISAS_UPDATE
;
7928 /* branch (and link) */
7929 val
= (int32_t)s
->pc
;
7930 if (insn
& (1 << 24)) {
7931 tmp
= tcg_temp_new_i32();
7932 tcg_gen_movi_i32(tmp
, val
);
7933 store_reg(s
, 14, tmp
);
7935 offset
= (((int32_t)insn
<< 8) >> 8);
7936 val
+= (offset
<< 2) + 4;
7944 if (disas_coproc_insn(env
, s
, insn
))
7949 gen_set_pc_im(s
->pc
);
7950 s
->is_jmp
= DISAS_SWI
;
7954 gen_exception_insn(s
, 4, EXCP_UDEF
);
7960 /* Return true if this is a Thumb-2 logical op. */
7962 thumb2_logic_op(int op
)
7967 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7968 then set condition code flags based on the result of the operation.
7969 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7970 to the high bit of T1.
7971 Returns zero if the opcode is valid. */
7974 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
,
7975 TCGv_i32 t0
, TCGv_i32 t1
)
7982 tcg_gen_and_i32(t0
, t0
, t1
);
7986 tcg_gen_andc_i32(t0
, t0
, t1
);
7990 tcg_gen_or_i32(t0
, t0
, t1
);
7994 tcg_gen_orc_i32(t0
, t0
, t1
);
7998 tcg_gen_xor_i32(t0
, t0
, t1
);
8003 gen_add_CC(t0
, t0
, t1
);
8005 tcg_gen_add_i32(t0
, t0
, t1
);
8009 gen_adc_CC(t0
, t0
, t1
);
8015 gen_sbc_CC(t0
, t0
, t1
);
8017 gen_sub_carry(t0
, t0
, t1
);
8022 gen_sub_CC(t0
, t0
, t1
);
8024 tcg_gen_sub_i32(t0
, t0
, t1
);
8028 gen_sub_CC(t0
, t1
, t0
);
8030 tcg_gen_sub_i32(t0
, t1
, t0
);
8032 default: /* 5, 6, 7, 9, 12, 15. */
8038 gen_set_CF_bit31(t1
);
8043 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
8045 static int disas_thumb2_insn(CPUARMState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
8047 uint32_t insn
, imm
, shift
, offset
;
8048 uint32_t rd
, rn
, rm
, rs
;
8059 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
8060 || arm_feature (env
, ARM_FEATURE_M
))) {
8061 /* Thumb-1 cores may need to treat bl and blx as a pair of
8062 16-bit instructions to get correct prefetch abort behavior. */
8064 if ((insn
& (1 << 12)) == 0) {
8066 /* Second half of blx. */
8067 offset
= ((insn
& 0x7ff) << 1);
8068 tmp
= load_reg(s
, 14);
8069 tcg_gen_addi_i32(tmp
, tmp
, offset
);
8070 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
8072 tmp2
= tcg_temp_new_i32();
8073 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
8074 store_reg(s
, 14, tmp2
);
8078 if (insn
& (1 << 11)) {
8079 /* Second half of bl. */
8080 offset
= ((insn
& 0x7ff) << 1) | 1;
8081 tmp
= load_reg(s
, 14);
8082 tcg_gen_addi_i32(tmp
, tmp
, offset
);
8084 tmp2
= tcg_temp_new_i32();
8085 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
8086 store_reg(s
, 14, tmp2
);
8090 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
8091 /* Instruction spans a page boundary. Implement it as two
8092 16-bit instructions in case the second half causes an
8094 offset
= ((int32_t)insn
<< 21) >> 9;
8095 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
8098 /* Fall through to 32-bit decode. */
8101 insn
= arm_lduw_code(env
, s
->pc
, s
->bswap_code
);
8103 insn
|= (uint32_t)insn_hw1
<< 16;
8105 if ((insn
& 0xf800e800) != 0xf000e800) {
8109 rn
= (insn
>> 16) & 0xf;
8110 rs
= (insn
>> 12) & 0xf;
8111 rd
= (insn
>> 8) & 0xf;
8113 switch ((insn
>> 25) & 0xf) {
8114 case 0: case 1: case 2: case 3:
8115 /* 16-bit instructions. Should never happen. */
8118 if (insn
& (1 << 22)) {
8119 /* Other load/store, table branch. */
8120 if (insn
& 0x01200000) {
8121 /* Load/store doubleword. */
8123 addr
= tcg_temp_new_i32();
8124 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
8126 addr
= load_reg(s
, rn
);
8128 offset
= (insn
& 0xff) * 4;
8129 if ((insn
& (1 << 23)) == 0)
8131 if (insn
& (1 << 24)) {
8132 tcg_gen_addi_i32(addr
, addr
, offset
);
8135 if (insn
& (1 << 20)) {
8137 tmp
= gen_ld32(addr
, IS_USER(s
));
8138 store_reg(s
, rs
, tmp
);
8139 tcg_gen_addi_i32(addr
, addr
, 4);
8140 tmp
= gen_ld32(addr
, IS_USER(s
));
8141 store_reg(s
, rd
, tmp
);
8144 tmp
= load_reg(s
, rs
);
8145 gen_st32(tmp
, addr
, IS_USER(s
));
8146 tcg_gen_addi_i32(addr
, addr
, 4);
8147 tmp
= load_reg(s
, rd
);
8148 gen_st32(tmp
, addr
, IS_USER(s
));
8150 if (insn
& (1 << 21)) {
8151 /* Base writeback. */
8154 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
8155 store_reg(s
, rn
, addr
);
8157 tcg_temp_free_i32(addr
);
8159 } else if ((insn
& (1 << 23)) == 0) {
8160 /* Load/store exclusive word. */
8161 addr
= tcg_temp_local_new_i32();
8162 load_reg_var(s
, addr
, rn
);
8163 tcg_gen_addi_i32(addr
, addr
, (insn
& 0xff) << 2);
8164 if (insn
& (1 << 20)) {
8165 gen_load_exclusive(s
, rs
, 15, addr
, 2);
8167 gen_store_exclusive(s
, rd
, rs
, 15, addr
, 2);
8169 tcg_temp_free_i32(addr
);
8170 } else if ((insn
& (1 << 6)) == 0) {
8173 addr
= tcg_temp_new_i32();
8174 tcg_gen_movi_i32(addr
, s
->pc
);
8176 addr
= load_reg(s
, rn
);
8178 tmp
= load_reg(s
, rm
);
8179 tcg_gen_add_i32(addr
, addr
, tmp
);
8180 if (insn
& (1 << 4)) {
8182 tcg_gen_add_i32(addr
, addr
, tmp
);
8183 tcg_temp_free_i32(tmp
);
8184 tmp
= gen_ld16u(addr
, IS_USER(s
));
8186 tcg_temp_free_i32(tmp
);
8187 tmp
= gen_ld8u(addr
, IS_USER(s
));
8189 tcg_temp_free_i32(addr
);
8190 tcg_gen_shli_i32(tmp
, tmp
, 1);
8191 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
8192 store_reg(s
, 15, tmp
);
8194 /* Load/store exclusive byte/halfword/doubleword. */
8196 op
= (insn
>> 4) & 0x3;
8200 addr
= tcg_temp_local_new_i32();
8201 load_reg_var(s
, addr
, rn
);
8202 if (insn
& (1 << 20)) {
8203 gen_load_exclusive(s
, rs
, rd
, addr
, op
);
8205 gen_store_exclusive(s
, rm
, rs
, rd
, addr
, op
);
8207 tcg_temp_free_i32(addr
);
8210 /* Load/store multiple, RFE, SRS. */
8211 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
8212 /* RFE, SRS: not available in user mode or on M profile */
8213 if (IS_USER(s
) || IS_M(env
)) {
8216 if (insn
& (1 << 20)) {
8218 addr
= load_reg(s
, rn
);
8219 if ((insn
& (1 << 24)) == 0)
8220 tcg_gen_addi_i32(addr
, addr
, -8);
8221 /* Load PC into tmp and CPSR into tmp2. */
8222 tmp
= gen_ld32(addr
, 0);
8223 tcg_gen_addi_i32(addr
, addr
, 4);
8224 tmp2
= gen_ld32(addr
, 0);
8225 if (insn
& (1 << 21)) {
8226 /* Base writeback. */
8227 if (insn
& (1 << 24)) {
8228 tcg_gen_addi_i32(addr
, addr
, 4);
8230 tcg_gen_addi_i32(addr
, addr
, -4);
8232 store_reg(s
, rn
, addr
);
8234 tcg_temp_free_i32(addr
);
8236 gen_rfe(s
, tmp
, tmp2
);
8239 gen_srs(s
, (insn
& 0x1f), (insn
& (1 << 24)) ? 1 : 2,
8243 int i
, loaded_base
= 0;
8244 TCGv_i32 loaded_var
;
8245 /* Load/store multiple. */
8246 addr
= load_reg(s
, rn
);
8248 for (i
= 0; i
< 16; i
++) {
8249 if (insn
& (1 << i
))
8252 if (insn
& (1 << 24)) {
8253 tcg_gen_addi_i32(addr
, addr
, -offset
);
8256 TCGV_UNUSED_I32(loaded_var
);
8257 for (i
= 0; i
< 16; i
++) {
8258 if ((insn
& (1 << i
)) == 0)
8260 if (insn
& (1 << 20)) {
8262 tmp
= gen_ld32(addr
, IS_USER(s
));
8265 } else if (i
== rn
) {
8269 store_reg(s
, i
, tmp
);
8273 tmp
= load_reg(s
, i
);
8274 gen_st32(tmp
, addr
, IS_USER(s
));
8276 tcg_gen_addi_i32(addr
, addr
, 4);
8279 store_reg(s
, rn
, loaded_var
);
8281 if (insn
& (1 << 21)) {
8282 /* Base register writeback. */
8283 if (insn
& (1 << 24)) {
8284 tcg_gen_addi_i32(addr
, addr
, -offset
);
8286 /* Fault if writeback register is in register list. */
8287 if (insn
& (1 << rn
))
8289 store_reg(s
, rn
, addr
);
8291 tcg_temp_free_i32(addr
);
8298 op
= (insn
>> 21) & 0xf;
8300 /* Halfword pack. */
8301 tmp
= load_reg(s
, rn
);
8302 tmp2
= load_reg(s
, rm
);
8303 shift
= ((insn
>> 10) & 0x1c) | ((insn
>> 6) & 0x3);
8304 if (insn
& (1 << 5)) {
8308 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
8309 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
8310 tcg_gen_ext16u_i32(tmp2
, tmp2
);
8314 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
8315 tcg_gen_ext16u_i32(tmp
, tmp
);
8316 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
8318 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8319 tcg_temp_free_i32(tmp2
);
8320 store_reg(s
, rd
, tmp
);
8322 /* Data processing register constant shift. */
8324 tmp
= tcg_temp_new_i32();
8325 tcg_gen_movi_i32(tmp
, 0);
8327 tmp
= load_reg(s
, rn
);
8329 tmp2
= load_reg(s
, rm
);
8331 shiftop
= (insn
>> 4) & 3;
8332 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
8333 conds
= (insn
& (1 << 20)) != 0;
8334 logic_cc
= (conds
&& thumb2_logic_op(op
));
8335 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
8336 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
8338 tcg_temp_free_i32(tmp2
);
8340 store_reg(s
, rd
, tmp
);
8342 tcg_temp_free_i32(tmp
);
8346 case 13: /* Misc data processing. */
8347 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
8348 if (op
< 4 && (insn
& 0xf000) != 0xf000)
8351 case 0: /* Register controlled shift. */
8352 tmp
= load_reg(s
, rn
);
8353 tmp2
= load_reg(s
, rm
);
8354 if ((insn
& 0x70) != 0)
8356 op
= (insn
>> 21) & 3;
8357 logic_cc
= (insn
& (1 << 20)) != 0;
8358 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
8361 store_reg_bx(env
, s
, rd
, tmp
);
8363 case 1: /* Sign/zero extend. */
8364 tmp
= load_reg(s
, rm
);
8365 shift
= (insn
>> 4) & 3;
8366 /* ??? In many cases it's not necessary to do a
8367 rotate, a shift is sufficient. */
8369 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
8370 op
= (insn
>> 20) & 7;
8372 case 0: gen_sxth(tmp
); break;
8373 case 1: gen_uxth(tmp
); break;
8374 case 2: gen_sxtb16(tmp
); break;
8375 case 3: gen_uxtb16(tmp
); break;
8376 case 4: gen_sxtb(tmp
); break;
8377 case 5: gen_uxtb(tmp
); break;
8378 default: goto illegal_op
;
8381 tmp2
= load_reg(s
, rn
);
8382 if ((op
>> 1) == 1) {
8383 gen_add16(tmp
, tmp2
);
8385 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8386 tcg_temp_free_i32(tmp2
);
8389 store_reg(s
, rd
, tmp
);
8391 case 2: /* SIMD add/subtract. */
8392 op
= (insn
>> 20) & 7;
8393 shift
= (insn
>> 4) & 7;
8394 if ((op
& 3) == 3 || (shift
& 3) == 3)
8396 tmp
= load_reg(s
, rn
);
8397 tmp2
= load_reg(s
, rm
);
8398 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
8399 tcg_temp_free_i32(tmp2
);
8400 store_reg(s
, rd
, tmp
);
8402 case 3: /* Other data processing. */
8403 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
8405 /* Saturating add/subtract. */
8406 tmp
= load_reg(s
, rn
);
8407 tmp2
= load_reg(s
, rm
);
8409 gen_helper_double_saturate(tmp
, cpu_env
, tmp
);
8411 gen_helper_sub_saturate(tmp
, cpu_env
, tmp2
, tmp
);
8413 gen_helper_add_saturate(tmp
, cpu_env
, tmp
, tmp2
);
8414 tcg_temp_free_i32(tmp2
);
8416 tmp
= load_reg(s
, rn
);
8418 case 0x0a: /* rbit */
8419 gen_helper_rbit(tmp
, tmp
);
8421 case 0x08: /* rev */
8422 tcg_gen_bswap32_i32(tmp
, tmp
);
8424 case 0x09: /* rev16 */
8427 case 0x0b: /* revsh */
8430 case 0x10: /* sel */
8431 tmp2
= load_reg(s
, rm
);
8432 tmp3
= tcg_temp_new_i32();
8433 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUARMState
, GE
));
8434 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
8435 tcg_temp_free_i32(tmp3
);
8436 tcg_temp_free_i32(tmp2
);
8438 case 0x18: /* clz */
8439 gen_helper_clz(tmp
, tmp
);
8445 store_reg(s
, rd
, tmp
);
8447 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
8448 op
= (insn
>> 4) & 0xf;
8449 tmp
= load_reg(s
, rn
);
8450 tmp2
= load_reg(s
, rm
);
8451 switch ((insn
>> 20) & 7) {
8452 case 0: /* 32 x 32 -> 32 */
8453 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8454 tcg_temp_free_i32(tmp2
);
8456 tmp2
= load_reg(s
, rs
);
8458 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
8460 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8461 tcg_temp_free_i32(tmp2
);
8464 case 1: /* 16 x 16 -> 32 */
8465 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
8466 tcg_temp_free_i32(tmp2
);
8468 tmp2
= load_reg(s
, rs
);
8469 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
8470 tcg_temp_free_i32(tmp2
);
8473 case 2: /* Dual multiply add. */
8474 case 4: /* Dual multiply subtract. */
8476 gen_swap_half(tmp2
);
8477 gen_smul_dual(tmp
, tmp2
);
8478 if (insn
& (1 << 22)) {
8479 /* This subtraction cannot overflow. */
8480 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8482 /* This addition cannot overflow 32 bits;
8483 * however it may overflow considered as a signed
8484 * operation, in which case we must set the Q flag.
8486 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
8488 tcg_temp_free_i32(tmp2
);
8491 tmp2
= load_reg(s
, rs
);
8492 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
8493 tcg_temp_free_i32(tmp2
);
8496 case 3: /* 32 * 16 -> 32msb */
8498 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
8501 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
8502 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
8503 tmp
= tcg_temp_new_i32();
8504 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
8505 tcg_temp_free_i64(tmp64
);
8508 tmp2
= load_reg(s
, rs
);
8509 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
8510 tcg_temp_free_i32(tmp2
);
8513 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8514 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
8516 tmp
= load_reg(s
, rs
);
8517 if (insn
& (1 << 20)) {
8518 tmp64
= gen_addq_msw(tmp64
, tmp
);
8520 tmp64
= gen_subq_msw(tmp64
, tmp
);
8523 if (insn
& (1 << 4)) {
8524 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
8526 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
8527 tmp
= tcg_temp_new_i32();
8528 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
8529 tcg_temp_free_i64(tmp64
);
8531 case 7: /* Unsigned sum of absolute differences. */
8532 gen_helper_usad8(tmp
, tmp
, tmp2
);
8533 tcg_temp_free_i32(tmp2
);
8535 tmp2
= load_reg(s
, rs
);
8536 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8537 tcg_temp_free_i32(tmp2
);
8541 store_reg(s
, rd
, tmp
);
8543 case 6: case 7: /* 64-bit multiply, Divide. */
8544 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
8545 tmp
= load_reg(s
, rn
);
8546 tmp2
= load_reg(s
, rm
);
8547 if ((op
& 0x50) == 0x10) {
8549 if (!arm_feature(env
, ARM_FEATURE_THUMB_DIV
)) {
8553 gen_helper_udiv(tmp
, tmp
, tmp2
);
8555 gen_helper_sdiv(tmp
, tmp
, tmp2
);
8556 tcg_temp_free_i32(tmp2
);
8557 store_reg(s
, rd
, tmp
);
8558 } else if ((op
& 0xe) == 0xc) {
8559 /* Dual multiply accumulate long. */
8561 gen_swap_half(tmp2
);
8562 gen_smul_dual(tmp
, tmp2
);
8564 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8566 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8568 tcg_temp_free_i32(tmp2
);
8570 tmp64
= tcg_temp_new_i64();
8571 tcg_gen_ext_i32_i64(tmp64
, tmp
);
8572 tcg_temp_free_i32(tmp
);
8573 gen_addq(s
, tmp64
, rs
, rd
);
8574 gen_storeq_reg(s
, rs
, rd
, tmp64
);
8575 tcg_temp_free_i64(tmp64
);
8578 /* Unsigned 64-bit multiply */
8579 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
8583 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
8584 tcg_temp_free_i32(tmp2
);
8585 tmp64
= tcg_temp_new_i64();
8586 tcg_gen_ext_i32_i64(tmp64
, tmp
);
8587 tcg_temp_free_i32(tmp
);
8589 /* Signed 64-bit multiply */
8590 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
8595 gen_addq_lo(s
, tmp64
, rs
);
8596 gen_addq_lo(s
, tmp64
, rd
);
8597 } else if (op
& 0x40) {
8598 /* 64-bit accumulate. */
8599 gen_addq(s
, tmp64
, rs
, rd
);
8601 gen_storeq_reg(s
, rs
, rd
, tmp64
);
8602 tcg_temp_free_i64(tmp64
);
8607 case 6: case 7: case 14: case 15:
8609 if (((insn
>> 24) & 3) == 3) {
8610 /* Translate into the equivalent ARM encoding. */
8611 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4) | (1 << 28);
8612 if (disas_neon_data_insn(env
, s
, insn
))
8615 if (insn
& (1 << 28))
8617 if (disas_coproc_insn (env
, s
, insn
))
8621 case 8: case 9: case 10: case 11:
8622 if (insn
& (1 << 15)) {
8623 /* Branches, misc control. */
8624 if (insn
& 0x5000) {
8625 /* Unconditional branch. */
8626 /* signextend(hw1[10:0]) -> offset[:12]. */
8627 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
8628 /* hw1[10:0] -> offset[11:1]. */
8629 offset
|= (insn
& 0x7ff) << 1;
8630 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8631 offset[24:22] already have the same value because of the
8632 sign extension above. */
8633 offset
^= ((~insn
) & (1 << 13)) << 10;
8634 offset
^= ((~insn
) & (1 << 11)) << 11;
8636 if (insn
& (1 << 14)) {
8637 /* Branch and link. */
8638 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
8642 if (insn
& (1 << 12)) {
8647 offset
&= ~(uint32_t)2;
8648 /* thumb2 bx, no need to check */
8649 gen_bx_im(s
, offset
);
8651 } else if (((insn
>> 23) & 7) == 7) {
8653 if (insn
& (1 << 13))
8656 if (insn
& (1 << 26)) {
8657 /* Secure monitor call (v6Z) */
8658 goto illegal_op
; /* not implemented. */
8660 op
= (insn
>> 20) & 7;
8662 case 0: /* msr cpsr. */
8664 tmp
= load_reg(s
, rn
);
8665 addr
= tcg_const_i32(insn
& 0xff);
8666 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8667 tcg_temp_free_i32(addr
);
8668 tcg_temp_free_i32(tmp
);
8673 case 1: /* msr spsr. */
8676 tmp
= load_reg(s
, rn
);
8678 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
8682 case 2: /* cps, nop-hint. */
8683 if (((insn
>> 8) & 7) == 0) {
8684 gen_nop_hint(s
, insn
& 0xff);
8686 /* Implemented as NOP in user mode. */
8691 if (insn
& (1 << 10)) {
8692 if (insn
& (1 << 7))
8694 if (insn
& (1 << 6))
8696 if (insn
& (1 << 5))
8698 if (insn
& (1 << 9))
8699 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
8701 if (insn
& (1 << 8)) {
8703 imm
|= (insn
& 0x1f);
8706 gen_set_psr_im(s
, offset
, 0, imm
);
8709 case 3: /* Special control operations. */
8711 op
= (insn
>> 4) & 0xf;
8719 /* These execute as NOPs. */
8726 /* Trivial implementation equivalent to bx. */
8727 tmp
= load_reg(s
, rn
);
8730 case 5: /* Exception return. */
8734 if (rn
!= 14 || rd
!= 15) {
8737 tmp
= load_reg(s
, rn
);
8738 tcg_gen_subi_i32(tmp
, tmp
, insn
& 0xff);
8739 gen_exception_return(s
, tmp
);
8741 case 6: /* mrs cpsr. */
8742 tmp
= tcg_temp_new_i32();
8744 addr
= tcg_const_i32(insn
& 0xff);
8745 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
8746 tcg_temp_free_i32(addr
);
8748 gen_helper_cpsr_read(tmp
, cpu_env
);
8750 store_reg(s
, rd
, tmp
);
8752 case 7: /* mrs spsr. */
8753 /* Not accessible in user mode. */
8754 if (IS_USER(s
) || IS_M(env
))
8756 tmp
= load_cpu_field(spsr
);
8757 store_reg(s
, rd
, tmp
);
8762 /* Conditional branch. */
8763 op
= (insn
>> 22) & 0xf;
8764 /* Generate a conditional jump to next instruction. */
8765 s
->condlabel
= gen_new_label();
8766 gen_test_cc(op
^ 1, s
->condlabel
);
8769 /* offset[11:1] = insn[10:0] */
8770 offset
= (insn
& 0x7ff) << 1;
8771 /* offset[17:12] = insn[21:16]. */
8772 offset
|= (insn
& 0x003f0000) >> 4;
8773 /* offset[31:20] = insn[26]. */
8774 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
8775 /* offset[18] = insn[13]. */
8776 offset
|= (insn
& (1 << 13)) << 5;
8777 /* offset[19] = insn[11]. */
8778 offset
|= (insn
& (1 << 11)) << 8;
8780 /* jump to the offset */
8781 gen_jmp(s
, s
->pc
+ offset
);
8784 /* Data processing immediate. */
8785 if (insn
& (1 << 25)) {
8786 if (insn
& (1 << 24)) {
8787 if (insn
& (1 << 20))
8789 /* Bitfield/Saturate. */
8790 op
= (insn
>> 21) & 7;
8792 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
8794 tmp
= tcg_temp_new_i32();
8795 tcg_gen_movi_i32(tmp
, 0);
8797 tmp
= load_reg(s
, rn
);
8800 case 2: /* Signed bitfield extract. */
8802 if (shift
+ imm
> 32)
8805 gen_sbfx(tmp
, shift
, imm
);
8807 case 6: /* Unsigned bitfield extract. */
8809 if (shift
+ imm
> 32)
8812 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
8814 case 3: /* Bitfield insert/clear. */
8817 imm
= imm
+ 1 - shift
;
8819 tmp2
= load_reg(s
, rd
);
8820 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
, shift
, imm
);
8821 tcg_temp_free_i32(tmp2
);
8826 default: /* Saturate. */
8829 tcg_gen_sari_i32(tmp
, tmp
, shift
);
8831 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8833 tmp2
= tcg_const_i32(imm
);
8836 if ((op
& 1) && shift
== 0)
8837 gen_helper_usat16(tmp
, cpu_env
, tmp
, tmp2
);
8839 gen_helper_usat(tmp
, cpu_env
, tmp
, tmp2
);
8842 if ((op
& 1) && shift
== 0)
8843 gen_helper_ssat16(tmp
, cpu_env
, tmp
, tmp2
);
8845 gen_helper_ssat(tmp
, cpu_env
, tmp
, tmp2
);
8847 tcg_temp_free_i32(tmp2
);
8850 store_reg(s
, rd
, tmp
);
8852 imm
= ((insn
& 0x04000000) >> 15)
8853 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
8854 if (insn
& (1 << 22)) {
8855 /* 16-bit immediate. */
8856 imm
|= (insn
>> 4) & 0xf000;
8857 if (insn
& (1 << 23)) {
8859 tmp
= load_reg(s
, rd
);
8860 tcg_gen_ext16u_i32(tmp
, tmp
);
8861 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
8864 tmp
= tcg_temp_new_i32();
8865 tcg_gen_movi_i32(tmp
, imm
);
8868 /* Add/sub 12-bit immediate. */
8870 offset
= s
->pc
& ~(uint32_t)3;
8871 if (insn
& (1 << 23))
8875 tmp
= tcg_temp_new_i32();
8876 tcg_gen_movi_i32(tmp
, offset
);
8878 tmp
= load_reg(s
, rn
);
8879 if (insn
& (1 << 23))
8880 tcg_gen_subi_i32(tmp
, tmp
, imm
);
8882 tcg_gen_addi_i32(tmp
, tmp
, imm
);
8885 store_reg(s
, rd
, tmp
);
8888 int shifter_out
= 0;
8889 /* modified 12-bit immediate. */
8890 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
8891 imm
= (insn
& 0xff);
8894 /* Nothing to do. */
8896 case 1: /* 00XY00XY */
8899 case 2: /* XY00XY00 */
8903 case 3: /* XYXYXYXY */
8907 default: /* Rotated constant. */
8908 shift
= (shift
<< 1) | (imm
>> 7);
8910 imm
= imm
<< (32 - shift
);
8914 tmp2
= tcg_temp_new_i32();
8915 tcg_gen_movi_i32(tmp2
, imm
);
8916 rn
= (insn
>> 16) & 0xf;
8918 tmp
= tcg_temp_new_i32();
8919 tcg_gen_movi_i32(tmp
, 0);
8921 tmp
= load_reg(s
, rn
);
8923 op
= (insn
>> 21) & 0xf;
8924 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8925 shifter_out
, tmp
, tmp2
))
8927 tcg_temp_free_i32(tmp2
);
8928 rd
= (insn
>> 8) & 0xf;
8930 store_reg(s
, rd
, tmp
);
8932 tcg_temp_free_i32(tmp
);
8937 case 12: /* Load/store single data item. */
8942 if ((insn
& 0x01100000) == 0x01000000) {
8943 if (disas_neon_ls_insn(env
, s
, insn
))
8947 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8949 if (!(insn
& (1 << 20))) {
8953 /* Byte or halfword load space with dest == r15 : memory hints.
8954 * Catch them early so we don't emit pointless addressing code.
8955 * This space is a mix of:
8956 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
8957 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8959 * unallocated hints, which must be treated as NOPs
8960 * UNPREDICTABLE space, which we NOP or UNDEF depending on
8961 * which is easiest for the decoding logic
8962 * Some space which must UNDEF
8964 int op1
= (insn
>> 23) & 3;
8965 int op2
= (insn
>> 6) & 0x3f;
8970 /* UNPREDICTABLE, unallocated hint or
8971 * PLD/PLDW/PLI (literal)
8976 return 0; /* PLD/PLDW/PLI or unallocated hint */
8978 if ((op2
== 0) || ((op2
& 0x3c) == 0x30)) {
8979 return 0; /* PLD/PLDW/PLI or unallocated hint */
8981 /* UNDEF space, or an UNPREDICTABLE */
8987 addr
= tcg_temp_new_i32();
8989 /* s->pc has already been incremented by 4. */
8990 imm
= s
->pc
& 0xfffffffc;
8991 if (insn
& (1 << 23))
8992 imm
+= insn
& 0xfff;
8994 imm
-= insn
& 0xfff;
8995 tcg_gen_movi_i32(addr
, imm
);
8997 addr
= load_reg(s
, rn
);
8998 if (insn
& (1 << 23)) {
8999 /* Positive offset. */
9001 tcg_gen_addi_i32(addr
, addr
, imm
);
9004 switch ((insn
>> 8) & 0xf) {
9005 case 0x0: /* Shifted Register. */
9006 shift
= (insn
>> 4) & 0xf;
9008 tcg_temp_free_i32(addr
);
9011 tmp
= load_reg(s
, rm
);
9013 tcg_gen_shli_i32(tmp
, tmp
, shift
);
9014 tcg_gen_add_i32(addr
, addr
, tmp
);
9015 tcg_temp_free_i32(tmp
);
9017 case 0xc: /* Negative offset. */
9018 tcg_gen_addi_i32(addr
, addr
, -imm
);
9020 case 0xe: /* User privilege. */
9021 tcg_gen_addi_i32(addr
, addr
, imm
);
9024 case 0x9: /* Post-decrement. */
9027 case 0xb: /* Post-increment. */
9031 case 0xd: /* Pre-decrement. */
9034 case 0xf: /* Pre-increment. */
9035 tcg_gen_addi_i32(addr
, addr
, imm
);
9039 tcg_temp_free_i32(addr
);
9044 if (insn
& (1 << 20)) {
9046 tmp
= tcg_temp_new_i32();
9049 tcg_gen_qemu_ld8u(tmp
, addr
, user
);
9052 tcg_gen_qemu_ld8s(tmp
, addr
, user
);
9055 tcg_gen_qemu_ld16u(tmp
, addr
, user
);
9058 tcg_gen_qemu_ld16s(tmp
, addr
, user
);
9061 tcg_gen_qemu_ld32u(tmp
, addr
, user
);
9064 tcg_temp_free_i32(tmp
);
9065 tcg_temp_free_i32(addr
);
9071 store_reg(s
, rs
, tmp
);
9075 tmp
= load_reg(s
, rs
);
9078 tcg_gen_qemu_st8(tmp
, addr
, user
);
9081 tcg_gen_qemu_st16(tmp
, addr
, user
);
9084 tcg_gen_qemu_st32(tmp
, addr
, user
);
9087 tcg_temp_free_i32(tmp
);
9088 tcg_temp_free_i32(addr
);
9091 tcg_temp_free_i32(tmp
);
9094 tcg_gen_addi_i32(addr
, addr
, imm
);
9096 store_reg(s
, rn
, addr
);
9098 tcg_temp_free_i32(addr
);
9110 static void disas_thumb_insn(CPUARMState
*env
, DisasContext
*s
)
9112 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
9119 if (s
->condexec_mask
) {
9120 cond
= s
->condexec_cond
;
9121 if (cond
!= 0x0e) { /* Skip conditional when condition is AL. */
9122 s
->condlabel
= gen_new_label();
9123 gen_test_cc(cond
^ 1, s
->condlabel
);
9128 insn
= arm_lduw_code(env
, s
->pc
, s
->bswap_code
);
9131 switch (insn
>> 12) {
9135 op
= (insn
>> 11) & 3;
9138 rn
= (insn
>> 3) & 7;
9139 tmp
= load_reg(s
, rn
);
9140 if (insn
& (1 << 10)) {
9142 tmp2
= tcg_temp_new_i32();
9143 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
9146 rm
= (insn
>> 6) & 7;
9147 tmp2
= load_reg(s
, rm
);
9149 if (insn
& (1 << 9)) {
9150 if (s
->condexec_mask
)
9151 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
9153 gen_sub_CC(tmp
, tmp
, tmp2
);
9155 if (s
->condexec_mask
)
9156 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
9158 gen_add_CC(tmp
, tmp
, tmp2
);
9160 tcg_temp_free_i32(tmp2
);
9161 store_reg(s
, rd
, tmp
);
9163 /* shift immediate */
9164 rm
= (insn
>> 3) & 7;
9165 shift
= (insn
>> 6) & 0x1f;
9166 tmp
= load_reg(s
, rm
);
9167 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
9168 if (!s
->condexec_mask
)
9170 store_reg(s
, rd
, tmp
);
9174 /* arithmetic large immediate */
9175 op
= (insn
>> 11) & 3;
9176 rd
= (insn
>> 8) & 0x7;
9177 if (op
== 0) { /* mov */
9178 tmp
= tcg_temp_new_i32();
9179 tcg_gen_movi_i32(tmp
, insn
& 0xff);
9180 if (!s
->condexec_mask
)
9182 store_reg(s
, rd
, tmp
);
9184 tmp
= load_reg(s
, rd
);
9185 tmp2
= tcg_temp_new_i32();
9186 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
9189 gen_sub_CC(tmp
, tmp
, tmp2
);
9190 tcg_temp_free_i32(tmp
);
9191 tcg_temp_free_i32(tmp2
);
9194 if (s
->condexec_mask
)
9195 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
9197 gen_add_CC(tmp
, tmp
, tmp2
);
9198 tcg_temp_free_i32(tmp2
);
9199 store_reg(s
, rd
, tmp
);
9202 if (s
->condexec_mask
)
9203 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
9205 gen_sub_CC(tmp
, tmp
, tmp2
);
9206 tcg_temp_free_i32(tmp2
);
9207 store_reg(s
, rd
, tmp
);
9213 if (insn
& (1 << 11)) {
9214 rd
= (insn
>> 8) & 7;
9215 /* load pc-relative. Bit 1 of PC is ignored. */
9216 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
9217 val
&= ~(uint32_t)2;
9218 addr
= tcg_temp_new_i32();
9219 tcg_gen_movi_i32(addr
, val
);
9220 tmp
= gen_ld32(addr
, IS_USER(s
));
9221 tcg_temp_free_i32(addr
);
9222 store_reg(s
, rd
, tmp
);
9225 if (insn
& (1 << 10)) {
9226 /* data processing extended or blx */
9227 rd
= (insn
& 7) | ((insn
>> 4) & 8);
9228 rm
= (insn
>> 3) & 0xf;
9229 op
= (insn
>> 8) & 3;
9232 tmp
= load_reg(s
, rd
);
9233 tmp2
= load_reg(s
, rm
);
9234 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
9235 tcg_temp_free_i32(tmp2
);
9236 store_reg(s
, rd
, tmp
);
9239 tmp
= load_reg(s
, rd
);
9240 tmp2
= load_reg(s
, rm
);
9241 gen_sub_CC(tmp
, tmp
, tmp2
);
9242 tcg_temp_free_i32(tmp2
);
9243 tcg_temp_free_i32(tmp
);
9245 case 2: /* mov/cpy */
9246 tmp
= load_reg(s
, rm
);
9247 store_reg(s
, rd
, tmp
);
9249 case 3:/* branch [and link] exchange thumb register */
9250 tmp
= load_reg(s
, rm
);
9251 if (insn
& (1 << 7)) {
9253 val
= (uint32_t)s
->pc
| 1;
9254 tmp2
= tcg_temp_new_i32();
9255 tcg_gen_movi_i32(tmp2
, val
);
9256 store_reg(s
, 14, tmp2
);
9258 /* already thumb, no need to check */
9265 /* data processing register */
9267 rm
= (insn
>> 3) & 7;
9268 op
= (insn
>> 6) & 0xf;
9269 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
9270 /* the shift/rotate ops want the operands backwards */
9279 if (op
== 9) { /* neg */
9280 tmp
= tcg_temp_new_i32();
9281 tcg_gen_movi_i32(tmp
, 0);
9282 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
9283 tmp
= load_reg(s
, rd
);
9285 TCGV_UNUSED_I32(tmp
);
9288 tmp2
= load_reg(s
, rm
);
9291 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
9292 if (!s
->condexec_mask
)
9296 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
9297 if (!s
->condexec_mask
)
9301 if (s
->condexec_mask
) {
9302 gen_shl(tmp2
, tmp2
, tmp
);
9304 gen_helper_shl_cc(tmp2
, cpu_env
, tmp2
, tmp
);
9309 if (s
->condexec_mask
) {
9310 gen_shr(tmp2
, tmp2
, tmp
);
9312 gen_helper_shr_cc(tmp2
, cpu_env
, tmp2
, tmp
);
9317 if (s
->condexec_mask
) {
9318 gen_sar(tmp2
, tmp2
, tmp
);
9320 gen_helper_sar_cc(tmp2
, cpu_env
, tmp2
, tmp
);
9325 if (s
->condexec_mask
) {
9328 gen_adc_CC(tmp
, tmp
, tmp2
);
9332 if (s
->condexec_mask
) {
9333 gen_sub_carry(tmp
, tmp
, tmp2
);
9335 gen_sbc_CC(tmp
, tmp
, tmp2
);
9339 if (s
->condexec_mask
) {
9340 tcg_gen_andi_i32(tmp
, tmp
, 0x1f);
9341 tcg_gen_rotr_i32(tmp2
, tmp2
, tmp
);
9343 gen_helper_ror_cc(tmp2
, cpu_env
, tmp2
, tmp
);
9348 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
9353 if (s
->condexec_mask
)
9354 tcg_gen_neg_i32(tmp
, tmp2
);
9356 gen_sub_CC(tmp
, tmp
, tmp2
);
9359 gen_sub_CC(tmp
, tmp
, tmp2
);
9363 gen_add_CC(tmp
, tmp
, tmp2
);
9367 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
9368 if (!s
->condexec_mask
)
9372 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
9373 if (!s
->condexec_mask
)
9377 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
9378 if (!s
->condexec_mask
)
9382 tcg_gen_not_i32(tmp2
, tmp2
);
9383 if (!s
->condexec_mask
)
9391 store_reg(s
, rm
, tmp2
);
9393 tcg_temp_free_i32(tmp
);
9395 store_reg(s
, rd
, tmp
);
9396 tcg_temp_free_i32(tmp2
);
9399 tcg_temp_free_i32(tmp
);
9400 tcg_temp_free_i32(tmp2
);
9405 /* load/store register offset. */
9407 rn
= (insn
>> 3) & 7;
9408 rm
= (insn
>> 6) & 7;
9409 op
= (insn
>> 9) & 7;
9410 addr
= load_reg(s
, rn
);
9411 tmp
= load_reg(s
, rm
);
9412 tcg_gen_add_i32(addr
, addr
, tmp
);
9413 tcg_temp_free_i32(tmp
);
9415 if (op
< 3) /* store */
9416 tmp
= load_reg(s
, rd
);
9420 gen_st32(tmp
, addr
, IS_USER(s
));
9423 gen_st16(tmp
, addr
, IS_USER(s
));
9426 gen_st8(tmp
, addr
, IS_USER(s
));
9429 tmp
= gen_ld8s(addr
, IS_USER(s
));
9432 tmp
= gen_ld32(addr
, IS_USER(s
));
9435 tmp
= gen_ld16u(addr
, IS_USER(s
));
9438 tmp
= gen_ld8u(addr
, IS_USER(s
));
9441 tmp
= gen_ld16s(addr
, IS_USER(s
));
9444 if (op
>= 3) /* load */
9445 store_reg(s
, rd
, tmp
);
9446 tcg_temp_free_i32(addr
);
9450 /* load/store word immediate offset */
9452 rn
= (insn
>> 3) & 7;
9453 addr
= load_reg(s
, rn
);
9454 val
= (insn
>> 4) & 0x7c;
9455 tcg_gen_addi_i32(addr
, addr
, val
);
9457 if (insn
& (1 << 11)) {
9459 tmp
= gen_ld32(addr
, IS_USER(s
));
9460 store_reg(s
, rd
, tmp
);
9463 tmp
= load_reg(s
, rd
);
9464 gen_st32(tmp
, addr
, IS_USER(s
));
9466 tcg_temp_free_i32(addr
);
9470 /* load/store byte immediate offset */
9472 rn
= (insn
>> 3) & 7;
9473 addr
= load_reg(s
, rn
);
9474 val
= (insn
>> 6) & 0x1f;
9475 tcg_gen_addi_i32(addr
, addr
, val
);
9477 if (insn
& (1 << 11)) {
9479 tmp
= gen_ld8u(addr
, IS_USER(s
));
9480 store_reg(s
, rd
, tmp
);
9483 tmp
= load_reg(s
, rd
);
9484 gen_st8(tmp
, addr
, IS_USER(s
));
9486 tcg_temp_free_i32(addr
);
9490 /* load/store halfword immediate offset */
9492 rn
= (insn
>> 3) & 7;
9493 addr
= load_reg(s
, rn
);
9494 val
= (insn
>> 5) & 0x3e;
9495 tcg_gen_addi_i32(addr
, addr
, val
);
9497 if (insn
& (1 << 11)) {
9499 tmp
= gen_ld16u(addr
, IS_USER(s
));
9500 store_reg(s
, rd
, tmp
);
9503 tmp
= load_reg(s
, rd
);
9504 gen_st16(tmp
, addr
, IS_USER(s
));
9506 tcg_temp_free_i32(addr
);
9510 /* load/store from stack */
9511 rd
= (insn
>> 8) & 7;
9512 addr
= load_reg(s
, 13);
9513 val
= (insn
& 0xff) * 4;
9514 tcg_gen_addi_i32(addr
, addr
, val
);
9516 if (insn
& (1 << 11)) {
9518 tmp
= gen_ld32(addr
, IS_USER(s
));
9519 store_reg(s
, rd
, tmp
);
9522 tmp
= load_reg(s
, rd
);
9523 gen_st32(tmp
, addr
, IS_USER(s
));
9525 tcg_temp_free_i32(addr
);
9529 /* add to high reg */
9530 rd
= (insn
>> 8) & 7;
9531 if (insn
& (1 << 11)) {
9533 tmp
= load_reg(s
, 13);
9535 /* PC. bit 1 is ignored. */
9536 tmp
= tcg_temp_new_i32();
9537 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
9539 val
= (insn
& 0xff) * 4;
9540 tcg_gen_addi_i32(tmp
, tmp
, val
);
9541 store_reg(s
, rd
, tmp
);
9546 op
= (insn
>> 8) & 0xf;
9549 /* adjust stack pointer */
9550 tmp
= load_reg(s
, 13);
9551 val
= (insn
& 0x7f) * 4;
9552 if (insn
& (1 << 7))
9553 val
= -(int32_t)val
;
9554 tcg_gen_addi_i32(tmp
, tmp
, val
);
9555 store_reg(s
, 13, tmp
);
9558 case 2: /* sign/zero extend. */
9561 rm
= (insn
>> 3) & 7;
9562 tmp
= load_reg(s
, rm
);
9563 switch ((insn
>> 6) & 3) {
9564 case 0: gen_sxth(tmp
); break;
9565 case 1: gen_sxtb(tmp
); break;
9566 case 2: gen_uxth(tmp
); break;
9567 case 3: gen_uxtb(tmp
); break;
9569 store_reg(s
, rd
, tmp
);
9571 case 4: case 5: case 0xc: case 0xd:
9573 addr
= load_reg(s
, 13);
9574 if (insn
& (1 << 8))
9578 for (i
= 0; i
< 8; i
++) {
9579 if (insn
& (1 << i
))
9582 if ((insn
& (1 << 11)) == 0) {
9583 tcg_gen_addi_i32(addr
, addr
, -offset
);
9585 for (i
= 0; i
< 8; i
++) {
9586 if (insn
& (1 << i
)) {
9587 if (insn
& (1 << 11)) {
9589 tmp
= gen_ld32(addr
, IS_USER(s
));
9590 store_reg(s
, i
, tmp
);
9593 tmp
= load_reg(s
, i
);
9594 gen_st32(tmp
, addr
, IS_USER(s
));
9596 /* advance to the next address. */
9597 tcg_gen_addi_i32(addr
, addr
, 4);
9600 TCGV_UNUSED_I32(tmp
);
9601 if (insn
& (1 << 8)) {
9602 if (insn
& (1 << 11)) {
9604 tmp
= gen_ld32(addr
, IS_USER(s
));
9605 /* don't set the pc until the rest of the instruction
9609 tmp
= load_reg(s
, 14);
9610 gen_st32(tmp
, addr
, IS_USER(s
));
9612 tcg_gen_addi_i32(addr
, addr
, 4);
9614 if ((insn
& (1 << 11)) == 0) {
9615 tcg_gen_addi_i32(addr
, addr
, -offset
);
9617 /* write back the new stack pointer */
9618 store_reg(s
, 13, addr
);
9619 /* set the new PC value */
9620 if ((insn
& 0x0900) == 0x0900) {
9621 store_reg_from_load(env
, s
, 15, tmp
);
9625 case 1: case 3: case 9: case 11: /* czb */
9627 tmp
= load_reg(s
, rm
);
9628 s
->condlabel
= gen_new_label();
9630 if (insn
& (1 << 11))
9631 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
9633 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
9634 tcg_temp_free_i32(tmp
);
9635 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
9636 val
= (uint32_t)s
->pc
+ 2;
9641 case 15: /* IT, nop-hint. */
9642 if ((insn
& 0xf) == 0) {
9643 gen_nop_hint(s
, (insn
>> 4) & 0xf);
9647 s
->condexec_cond
= (insn
>> 4) & 0xe;
9648 s
->condexec_mask
= insn
& 0x1f;
9649 /* No actual code generated for this insn, just setup state. */
9652 case 0xe: /* bkpt */
9654 gen_exception_insn(s
, 2, EXCP_BKPT
);
9659 rn
= (insn
>> 3) & 0x7;
9661 tmp
= load_reg(s
, rn
);
9662 switch ((insn
>> 6) & 3) {
9663 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
9664 case 1: gen_rev16(tmp
); break;
9665 case 3: gen_revsh(tmp
); break;
9666 default: goto illegal_op
;
9668 store_reg(s
, rd
, tmp
);
9672 switch ((insn
>> 5) & 7) {
9676 if (((insn
>> 3) & 1) != s
->bswap_code
) {
9677 /* Dynamic endianness switching not implemented. */
9688 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
9691 addr
= tcg_const_i32(19);
9692 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
9693 tcg_temp_free_i32(addr
);
9697 addr
= tcg_const_i32(16);
9698 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
9699 tcg_temp_free_i32(addr
);
9701 tcg_temp_free_i32(tmp
);
9704 if (insn
& (1 << 4)) {
9705 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
9709 gen_set_psr_im(s
, ((insn
& 7) << 6), 0, shift
);
9724 /* load/store multiple */
9725 TCGv_i32 loaded_var
;
9726 TCGV_UNUSED_I32(loaded_var
);
9727 rn
= (insn
>> 8) & 0x7;
9728 addr
= load_reg(s
, rn
);
9729 for (i
= 0; i
< 8; i
++) {
9730 if (insn
& (1 << i
)) {
9731 if (insn
& (1 << 11)) {
9733 tmp
= gen_ld32(addr
, IS_USER(s
));
9737 store_reg(s
, i
, tmp
);
9741 tmp
= load_reg(s
, i
);
9742 gen_st32(tmp
, addr
, IS_USER(s
));
9744 /* advance to the next address */
9745 tcg_gen_addi_i32(addr
, addr
, 4);
9748 if ((insn
& (1 << rn
)) == 0) {
9749 /* base reg not in list: base register writeback */
9750 store_reg(s
, rn
, addr
);
9752 /* base reg in list: if load, complete it now */
9753 if (insn
& (1 << 11)) {
9754 store_reg(s
, rn
, loaded_var
);
9756 tcg_temp_free_i32(addr
);
9761 /* conditional branch or swi */
9762 cond
= (insn
>> 8) & 0xf;
9768 gen_set_pc_im(s
->pc
);
9769 s
->is_jmp
= DISAS_SWI
;
9772 /* generate a conditional jump to next instruction */
9773 s
->condlabel
= gen_new_label();
9774 gen_test_cc(cond
^ 1, s
->condlabel
);
9777 /* jump to the offset */
9778 val
= (uint32_t)s
->pc
+ 2;
9779 offset
= ((int32_t)insn
<< 24) >> 24;
9785 if (insn
& (1 << 11)) {
9786 if (disas_thumb2_insn(env
, s
, insn
))
9790 /* unconditional branch */
9791 val
= (uint32_t)s
->pc
;
9792 offset
= ((int32_t)insn
<< 21) >> 21;
9793 val
+= (offset
<< 1) + 2;
9798 if (disas_thumb2_insn(env
, s
, insn
))
9804 gen_exception_insn(s
, 4, EXCP_UDEF
);
9808 gen_exception_insn(s
, 2, EXCP_UDEF
);
9811 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9812 basic block 'tb'. If search_pc is TRUE, also generate PC
9813 information for each intermediate instruction. */
9814 static inline void gen_intermediate_code_internal(CPUARMState
*env
,
9815 TranslationBlock
*tb
,
9818 DisasContext dc1
, *dc
= &dc1
;
9820 uint16_t *gen_opc_end
;
9822 target_ulong pc_start
;
9823 uint32_t next_page_start
;
9827 /* generate intermediate code */
9832 gen_opc_end
= tcg_ctx
.gen_opc_buf
+ OPC_MAX_SIZE
;
9834 dc
->is_jmp
= DISAS_NEXT
;
9836 dc
->singlestep_enabled
= env
->singlestep_enabled
;
9838 dc
->thumb
= ARM_TBFLAG_THUMB(tb
->flags
);
9839 dc
->bswap_code
= ARM_TBFLAG_BSWAP_CODE(tb
->flags
);
9840 dc
->condexec_mask
= (ARM_TBFLAG_CONDEXEC(tb
->flags
) & 0xf) << 1;
9841 dc
->condexec_cond
= ARM_TBFLAG_CONDEXEC(tb
->flags
) >> 4;
9842 #if !defined(CONFIG_USER_ONLY)
9843 dc
->user
= (ARM_TBFLAG_PRIV(tb
->flags
) == 0);
9845 dc
->vfp_enabled
= ARM_TBFLAG_VFPEN(tb
->flags
);
9846 dc
->vec_len
= ARM_TBFLAG_VECLEN(tb
->flags
);
9847 dc
->vec_stride
= ARM_TBFLAG_VECSTRIDE(tb
->flags
);
9848 cpu_F0s
= tcg_temp_new_i32();
9849 cpu_F1s
= tcg_temp_new_i32();
9850 cpu_F0d
= tcg_temp_new_i64();
9851 cpu_F1d
= tcg_temp_new_i64();
9854 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9855 cpu_M0
= tcg_temp_new_i64();
9856 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
9859 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
9861 max_insns
= CF_COUNT_MASK
;
9865 tcg_clear_temp_count();
9867 /* A note on handling of the condexec (IT) bits:
9869 * We want to avoid the overhead of having to write the updated condexec
9870 * bits back to the CPUARMState for every instruction in an IT block. So:
9871 * (1) if the condexec bits are not already zero then we write
9872 * zero back into the CPUARMState now. This avoids complications trying
9873 * to do it at the end of the block. (For example if we don't do this
9874 * it's hard to identify whether we can safely skip writing condexec
9875 * at the end of the TB, which we definitely want to do for the case
9876 * where a TB doesn't do anything with the IT state at all.)
9877 * (2) if we are going to leave the TB then we call gen_set_condexec()
9878 * which will write the correct value into CPUARMState if zero is wrong.
9879 * This is done both for leaving the TB at the end, and for leaving
9880 * it because of an exception we know will happen, which is done in
9881 * gen_exception_insn(). The latter is necessary because we need to
9882 * leave the TB with the PC/IT state just prior to execution of the
9883 * instruction which caused the exception.
9884 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9885 * then the CPUARMState will be wrong and we need to reset it.
9886 * This is handled in the same way as restoration of the
9887 * PC in these situations: we will be called again with search_pc=1
9888 * and generate a mapping of the condexec bits for each PC in
9889 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
9890 * this to restore the condexec bits.
9892 * Note that there are no instructions which can read the condexec
9893 * bits, and none which can write non-static values to them, so
9894 * we don't need to care about whether CPUARMState is correct in the
9898 /* Reset the conditional execution bits immediately. This avoids
9899 complications trying to do it at the end of the block. */
9900 if (dc
->condexec_mask
|| dc
->condexec_cond
)
9902 TCGv_i32 tmp
= tcg_temp_new_i32();
9903 tcg_gen_movi_i32(tmp
, 0);
9904 store_cpu_field(tmp
, condexec_bits
);
9907 #ifdef CONFIG_USER_ONLY
9908 /* Intercept jump to the magic kernel page. */
9909 if (dc
->pc
>= 0xffff0000) {
9910 /* We always get here via a jump, so know we are not in a
9911 conditional execution block. */
9912 gen_exception(EXCP_KERNEL_TRAP
);
9913 dc
->is_jmp
= DISAS_UPDATE
;
9917 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
9918 /* We always get here via a jump, so know we are not in a
9919 conditional execution block. */
9920 gen_exception(EXCP_EXCEPTION_EXIT
);
9921 dc
->is_jmp
= DISAS_UPDATE
;
9926 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
9927 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
9928 if (bp
->pc
== dc
->pc
) {
9929 gen_exception_insn(dc
, 0, EXCP_DEBUG
);
9930 /* Advance PC so that clearing the breakpoint will
9931 invalidate this TB. */
9933 goto done_generating
;
9939 j
= tcg_ctx
.gen_opc_ptr
- tcg_ctx
.gen_opc_buf
;
9943 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
9945 tcg_ctx
.gen_opc_pc
[lj
] = dc
->pc
;
9946 gen_opc_condexec_bits
[lj
] = (dc
->condexec_cond
<< 4) | (dc
->condexec_mask
>> 1);
9947 tcg_ctx
.gen_opc_instr_start
[lj
] = 1;
9948 tcg_ctx
.gen_opc_icount
[lj
] = num_insns
;
9951 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
9954 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
| CPU_LOG_TB_OP_OPT
))) {
9955 tcg_gen_debug_insn_start(dc
->pc
);
9959 disas_thumb_insn(env
, dc
);
9960 if (dc
->condexec_mask
) {
9961 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
9962 | ((dc
->condexec_mask
>> 4) & 1);
9963 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
9964 if (dc
->condexec_mask
== 0) {
9965 dc
->condexec_cond
= 0;
9969 disas_arm_insn(env
, dc
);
9972 if (dc
->condjmp
&& !dc
->is_jmp
) {
9973 gen_set_label(dc
->condlabel
);
9977 if (tcg_check_temp_count()) {
9978 fprintf(stderr
, "TCG temporary leak before %08x\n", dc
->pc
);
9981 /* Translation stops when a conditional branch is encountered.
9982 * Otherwise the subsequent code could get translated several times.
9983 * Also stop translation when a page boundary is reached. This
9984 * ensures prefetch aborts occur at the right place. */
9986 } while (!dc
->is_jmp
&& tcg_ctx
.gen_opc_ptr
< gen_opc_end
&&
9987 !env
->singlestep_enabled
&&
9989 dc
->pc
< next_page_start
&&
9990 num_insns
< max_insns
);
9992 if (tb
->cflags
& CF_LAST_IO
) {
9994 /* FIXME: This can theoretically happen with self-modifying
9996 cpu_abort(env
, "IO on conditional branch instruction");
10001 /* At this stage dc->condjmp will only be set when the skipped
10002 instruction was a conditional branch or trap, and the PC has
10003 already been written. */
10004 if (unlikely(env
->singlestep_enabled
)) {
10005 /* Make sure the pc is updated, and raise a debug exception. */
10007 gen_set_condexec(dc
);
10008 if (dc
->is_jmp
== DISAS_SWI
) {
10009 gen_exception(EXCP_SWI
);
10011 gen_exception(EXCP_DEBUG
);
10013 gen_set_label(dc
->condlabel
);
10015 if (dc
->condjmp
|| !dc
->is_jmp
) {
10016 gen_set_pc_im(dc
->pc
);
10019 gen_set_condexec(dc
);
10020 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
10021 gen_exception(EXCP_SWI
);
10023 /* FIXME: Single stepping a WFI insn will not halt
10025 gen_exception(EXCP_DEBUG
);
10028 /* While branches must always occur at the end of an IT block,
10029 there are a few other things that can cause us to terminate
10030 the TB in the middle of an IT block:
10031 - Exception generating instructions (bkpt, swi, undefined).
10033 - Hardware watchpoints.
10034 Hardware breakpoints have already been handled and skip this code.
10036 gen_set_condexec(dc
);
10037 switch(dc
->is_jmp
) {
10039 gen_goto_tb(dc
, 1, dc
->pc
);
10044 /* indicate that the hash table must be used to find the next TB */
10045 tcg_gen_exit_tb(0);
10047 case DISAS_TB_JUMP
:
10048 /* nothing more to generate */
10051 gen_helper_wfi(cpu_env
);
10054 gen_exception(EXCP_SWI
);
10058 gen_set_label(dc
->condlabel
);
10059 gen_set_condexec(dc
);
10060 gen_goto_tb(dc
, 1, dc
->pc
);
10066 gen_tb_end(tb
, num_insns
);
10067 *tcg_ctx
.gen_opc_ptr
= INDEX_op_end
;
10070 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
10071 qemu_log("----------------\n");
10072 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
10073 log_target_disas(env
, pc_start
, dc
->pc
- pc_start
,
10074 dc
->thumb
| (dc
->bswap_code
<< 1));
10079 j
= tcg_ctx
.gen_opc_ptr
- tcg_ctx
.gen_opc_buf
;
10082 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
10084 tb
->size
= dc
->pc
- pc_start
;
10085 tb
->icount
= num_insns
;
10089 void gen_intermediate_code(CPUARMState
*env
, TranslationBlock
*tb
)
10091 gen_intermediate_code_internal(env
, tb
, 0);
10094 void gen_intermediate_code_pc(CPUARMState
*env
, TranslationBlock
*tb
)
10096 gen_intermediate_code_internal(env
, tb
, 1);
10099 static const char *cpu_mode_names
[16] = {
10100 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
10101 "???", "???", "???", "und", "???", "???", "???", "sys"
10104 void cpu_dump_state(CPUARMState
*env
, FILE *f
, fprintf_function cpu_fprintf
,
10110 for(i
=0;i
<16;i
++) {
10111 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
10113 cpu_fprintf(f
, "\n");
10115 cpu_fprintf(f
, " ");
10117 psr
= cpsr_read(env
);
10118 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
10120 psr
& (1 << 31) ? 'N' : '-',
10121 psr
& (1 << 30) ? 'Z' : '-',
10122 psr
& (1 << 29) ? 'C' : '-',
10123 psr
& (1 << 28) ? 'V' : '-',
10124 psr
& CPSR_T
? 'T' : 'A',
10125 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
10127 if (flags
& CPU_DUMP_FPU
) {
10128 int numvfpregs
= 0;
10129 if (arm_feature(env
, ARM_FEATURE_VFP
)) {
10132 if (arm_feature(env
, ARM_FEATURE_VFP3
)) {
10135 for (i
= 0; i
< numvfpregs
; i
++) {
10136 uint64_t v
= float64_val(env
->vfp
.regs
[i
]);
10137 cpu_fprintf(f
, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64
"\n",
10138 i
* 2, (uint32_t)v
,
10139 i
* 2 + 1, (uint32_t)(v
>> 32),
10142 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
10146 void restore_state_to_opc(CPUARMState
*env
, TranslationBlock
*tb
, int pc_pos
)
10148 env
->regs
[15] = tcg_ctx
.gen_opc_pc
[pc_pos
];
10149 env
->condexec_bits
= gen_opc_condexec_bits
[pc_pos
];