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 void gen_set_pc_im(uint32_t val
)
846 tcg_gen_movi_i32(cpu_R
[15], val
);
849 /* Force a TB lookup after an instruction that changes the CPU state. */
850 static inline void gen_lookup_tb(DisasContext
*s
)
852 tcg_gen_movi_i32(cpu_R
[15], s
->pc
& ~1);
853 s
->is_jmp
= DISAS_UPDATE
;
856 static inline void gen_add_data_offset(DisasContext
*s
, unsigned int insn
,
859 int val
, rm
, shift
, shiftop
;
862 if (!(insn
& (1 << 25))) {
865 if (!(insn
& (1 << 23)))
868 tcg_gen_addi_i32(var
, var
, val
);
872 shift
= (insn
>> 7) & 0x1f;
873 shiftop
= (insn
>> 5) & 3;
874 offset
= load_reg(s
, rm
);
875 gen_arm_shift_im(offset
, shiftop
, shift
, 0);
876 if (!(insn
& (1 << 23)))
877 tcg_gen_sub_i32(var
, var
, offset
);
879 tcg_gen_add_i32(var
, var
, offset
);
880 tcg_temp_free_i32(offset
);
884 static inline void gen_add_datah_offset(DisasContext
*s
, unsigned int insn
,
885 int extra
, TCGv_i32 var
)
890 if (insn
& (1 << 22)) {
892 val
= (insn
& 0xf) | ((insn
>> 4) & 0xf0);
893 if (!(insn
& (1 << 23)))
897 tcg_gen_addi_i32(var
, var
, val
);
901 tcg_gen_addi_i32(var
, var
, extra
);
903 offset
= load_reg(s
, rm
);
904 if (!(insn
& (1 << 23)))
905 tcg_gen_sub_i32(var
, var
, offset
);
907 tcg_gen_add_i32(var
, var
, offset
);
908 tcg_temp_free_i32(offset
);
912 static TCGv_ptr
get_fpstatus_ptr(int neon
)
914 TCGv_ptr statusptr
= tcg_temp_new_ptr();
917 offset
= offsetof(CPUARMState
, vfp
.standard_fp_status
);
919 offset
= offsetof(CPUARMState
, vfp
.fp_status
);
921 tcg_gen_addi_ptr(statusptr
, cpu_env
, offset
);
925 #define VFP_OP2(name) \
926 static inline void gen_vfp_##name(int dp) \
928 TCGv_ptr fpst = get_fpstatus_ptr(0); \
930 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
932 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
934 tcg_temp_free_ptr(fpst); \
944 static inline void gen_vfp_F1_mul(int dp
)
946 /* Like gen_vfp_mul() but put result in F1 */
947 TCGv_ptr fpst
= get_fpstatus_ptr(0);
949 gen_helper_vfp_muld(cpu_F1d
, cpu_F0d
, cpu_F1d
, fpst
);
951 gen_helper_vfp_muls(cpu_F1s
, cpu_F0s
, cpu_F1s
, fpst
);
953 tcg_temp_free_ptr(fpst
);
956 static inline void gen_vfp_F1_neg(int dp
)
958 /* Like gen_vfp_neg() but put result in F1 */
960 gen_helper_vfp_negd(cpu_F1d
, cpu_F0d
);
962 gen_helper_vfp_negs(cpu_F1s
, cpu_F0s
);
966 static inline void gen_vfp_abs(int dp
)
969 gen_helper_vfp_absd(cpu_F0d
, cpu_F0d
);
971 gen_helper_vfp_abss(cpu_F0s
, cpu_F0s
);
974 static inline void gen_vfp_neg(int dp
)
977 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
979 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
982 static inline void gen_vfp_sqrt(int dp
)
985 gen_helper_vfp_sqrtd(cpu_F0d
, cpu_F0d
, cpu_env
);
987 gen_helper_vfp_sqrts(cpu_F0s
, cpu_F0s
, cpu_env
);
990 static inline void gen_vfp_cmp(int dp
)
993 gen_helper_vfp_cmpd(cpu_F0d
, cpu_F1d
, cpu_env
);
995 gen_helper_vfp_cmps(cpu_F0s
, cpu_F1s
, cpu_env
);
998 static inline void gen_vfp_cmpe(int dp
)
1001 gen_helper_vfp_cmped(cpu_F0d
, cpu_F1d
, cpu_env
);
1003 gen_helper_vfp_cmpes(cpu_F0s
, cpu_F1s
, cpu_env
);
1006 static inline void gen_vfp_F1_ld0(int dp
)
1009 tcg_gen_movi_i64(cpu_F1d
, 0);
1011 tcg_gen_movi_i32(cpu_F1s
, 0);
1014 #define VFP_GEN_ITOF(name) \
1015 static inline void gen_vfp_##name(int dp, int neon) \
1017 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1019 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1021 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1023 tcg_temp_free_ptr(statusptr); \
1030 #define VFP_GEN_FTOI(name) \
1031 static inline void gen_vfp_##name(int dp, int neon) \
1033 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1035 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1037 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1039 tcg_temp_free_ptr(statusptr); \
1048 #define VFP_GEN_FIX(name) \
1049 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1051 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1052 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1054 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
1056 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
1058 tcg_temp_free_i32(tmp_shift); \
1059 tcg_temp_free_ptr(statusptr); \
1071 static inline void gen_vfp_ld(DisasContext
*s
, int dp
, TCGv_i32 addr
)
1074 tcg_gen_qemu_ld64(cpu_F0d
, addr
, IS_USER(s
));
1076 tcg_gen_qemu_ld32u(cpu_F0s
, addr
, IS_USER(s
));
1079 static inline void gen_vfp_st(DisasContext
*s
, int dp
, TCGv_i32 addr
)
1082 tcg_gen_qemu_st64(cpu_F0d
, addr
, IS_USER(s
));
1084 tcg_gen_qemu_st32(cpu_F0s
, addr
, IS_USER(s
));
1088 vfp_reg_offset (int dp
, int reg
)
1091 return offsetof(CPUARMState
, vfp
.regs
[reg
]);
1093 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1094 + offsetof(CPU_DoubleU
, l
.upper
);
1096 return offsetof(CPUARMState
, vfp
.regs
[reg
>> 1])
1097 + offsetof(CPU_DoubleU
, l
.lower
);
1101 /* Return the offset of a 32-bit piece of a NEON register.
1102 zero is the least significant end of the register. */
1104 neon_reg_offset (int reg
, int n
)
1108 return vfp_reg_offset(0, sreg
);
1111 static TCGv_i32
neon_load_reg(int reg
, int pass
)
1113 TCGv_i32 tmp
= tcg_temp_new_i32();
1114 tcg_gen_ld_i32(tmp
, cpu_env
, neon_reg_offset(reg
, pass
));
1118 static void neon_store_reg(int reg
, int pass
, TCGv_i32 var
)
1120 tcg_gen_st_i32(var
, cpu_env
, neon_reg_offset(reg
, pass
));
1121 tcg_temp_free_i32(var
);
1124 static inline void neon_load_reg64(TCGv_i64 var
, int reg
)
1126 tcg_gen_ld_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1129 static inline void neon_store_reg64(TCGv_i64 var
, int reg
)
1131 tcg_gen_st_i64(var
, cpu_env
, vfp_reg_offset(1, reg
));
1134 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1135 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1136 #define tcg_gen_st_f32 tcg_gen_st_i32
1137 #define tcg_gen_st_f64 tcg_gen_st_i64
1139 static inline void gen_mov_F0_vreg(int dp
, int reg
)
1142 tcg_gen_ld_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1144 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1147 static inline void gen_mov_F1_vreg(int dp
, int reg
)
1150 tcg_gen_ld_f64(cpu_F1d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1152 tcg_gen_ld_f32(cpu_F1s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1155 static inline void gen_mov_vreg_F0(int dp
, int reg
)
1158 tcg_gen_st_f64(cpu_F0d
, cpu_env
, vfp_reg_offset(dp
, reg
));
1160 tcg_gen_st_f32(cpu_F0s
, cpu_env
, vfp_reg_offset(dp
, reg
));
1163 #define ARM_CP_RW_BIT (1 << 20)
1165 static inline void iwmmxt_load_reg(TCGv_i64 var
, int reg
)
1167 tcg_gen_ld_i64(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.regs
[reg
]));
1170 static inline void iwmmxt_store_reg(TCGv_i64 var
, int reg
)
1172 tcg_gen_st_i64(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.regs
[reg
]));
1175 static inline TCGv_i32
iwmmxt_load_creg(int reg
)
1177 TCGv_i32 var
= tcg_temp_new_i32();
1178 tcg_gen_ld_i32(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.cregs
[reg
]));
1182 static inline void iwmmxt_store_creg(int reg
, TCGv_i32 var
)
1184 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, iwmmxt
.cregs
[reg
]));
1185 tcg_temp_free_i32(var
);
1188 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn
)
1190 iwmmxt_store_reg(cpu_M0
, rn
);
1193 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn
)
1195 iwmmxt_load_reg(cpu_M0
, rn
);
1198 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn
)
1200 iwmmxt_load_reg(cpu_V1
, rn
);
1201 tcg_gen_or_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1204 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn
)
1206 iwmmxt_load_reg(cpu_V1
, rn
);
1207 tcg_gen_and_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1210 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn
)
1212 iwmmxt_load_reg(cpu_V1
, rn
);
1213 tcg_gen_xor_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1216 #define IWMMXT_OP(name) \
1217 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1219 iwmmxt_load_reg(cpu_V1, rn); \
1220 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1223 #define IWMMXT_OP_ENV(name) \
1224 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1226 iwmmxt_load_reg(cpu_V1, rn); \
1227 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1230 #define IWMMXT_OP_ENV_SIZE(name) \
1231 IWMMXT_OP_ENV(name##b) \
1232 IWMMXT_OP_ENV(name##w) \
1233 IWMMXT_OP_ENV(name##l)
1235 #define IWMMXT_OP_ENV1(name) \
1236 static inline void gen_op_iwmmxt_##name##_M0(void) \
1238 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1252 IWMMXT_OP_ENV_SIZE(unpackl
)
1253 IWMMXT_OP_ENV_SIZE(unpackh
)
1255 IWMMXT_OP_ENV1(unpacklub
)
1256 IWMMXT_OP_ENV1(unpackluw
)
1257 IWMMXT_OP_ENV1(unpacklul
)
1258 IWMMXT_OP_ENV1(unpackhub
)
1259 IWMMXT_OP_ENV1(unpackhuw
)
1260 IWMMXT_OP_ENV1(unpackhul
)
1261 IWMMXT_OP_ENV1(unpacklsb
)
1262 IWMMXT_OP_ENV1(unpacklsw
)
1263 IWMMXT_OP_ENV1(unpacklsl
)
1264 IWMMXT_OP_ENV1(unpackhsb
)
1265 IWMMXT_OP_ENV1(unpackhsw
)
1266 IWMMXT_OP_ENV1(unpackhsl
)
1268 IWMMXT_OP_ENV_SIZE(cmpeq
)
1269 IWMMXT_OP_ENV_SIZE(cmpgtu
)
1270 IWMMXT_OP_ENV_SIZE(cmpgts
)
1272 IWMMXT_OP_ENV_SIZE(mins
)
1273 IWMMXT_OP_ENV_SIZE(minu
)
1274 IWMMXT_OP_ENV_SIZE(maxs
)
1275 IWMMXT_OP_ENV_SIZE(maxu
)
1277 IWMMXT_OP_ENV_SIZE(subn
)
1278 IWMMXT_OP_ENV_SIZE(addn
)
1279 IWMMXT_OP_ENV_SIZE(subu
)
1280 IWMMXT_OP_ENV_SIZE(addu
)
1281 IWMMXT_OP_ENV_SIZE(subs
)
1282 IWMMXT_OP_ENV_SIZE(adds
)
1284 IWMMXT_OP_ENV(avgb0
)
1285 IWMMXT_OP_ENV(avgb1
)
1286 IWMMXT_OP_ENV(avgw0
)
1287 IWMMXT_OP_ENV(avgw1
)
1291 IWMMXT_OP_ENV(packuw
)
1292 IWMMXT_OP_ENV(packul
)
1293 IWMMXT_OP_ENV(packuq
)
1294 IWMMXT_OP_ENV(packsw
)
1295 IWMMXT_OP_ENV(packsl
)
1296 IWMMXT_OP_ENV(packsq
)
1298 static void gen_op_iwmmxt_set_mup(void)
1301 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1302 tcg_gen_ori_i32(tmp
, tmp
, 2);
1303 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1306 static void gen_op_iwmmxt_set_cup(void)
1309 tmp
= load_cpu_field(iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1310 tcg_gen_ori_i32(tmp
, tmp
, 1);
1311 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCon
]);
1314 static void gen_op_iwmmxt_setpsr_nz(void)
1316 TCGv_i32 tmp
= tcg_temp_new_i32();
1317 gen_helper_iwmmxt_setpsr_nz(tmp
, cpu_M0
);
1318 store_cpu_field(tmp
, iwmmxt
.cregs
[ARM_IWMMXT_wCASF
]);
1321 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn
)
1323 iwmmxt_load_reg(cpu_V1
, rn
);
1324 tcg_gen_ext32u_i64(cpu_V1
, cpu_V1
);
1325 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1328 static inline int gen_iwmmxt_address(DisasContext
*s
, uint32_t insn
,
1335 rd
= (insn
>> 16) & 0xf;
1336 tmp
= load_reg(s
, rd
);
1338 offset
= (insn
& 0xff) << ((insn
>> 7) & 2);
1339 if (insn
& (1 << 24)) {
1341 if (insn
& (1 << 23))
1342 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1344 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1345 tcg_gen_mov_i32(dest
, tmp
);
1346 if (insn
& (1 << 21))
1347 store_reg(s
, rd
, tmp
);
1349 tcg_temp_free_i32(tmp
);
1350 } else if (insn
& (1 << 21)) {
1352 tcg_gen_mov_i32(dest
, tmp
);
1353 if (insn
& (1 << 23))
1354 tcg_gen_addi_i32(tmp
, tmp
, offset
);
1356 tcg_gen_addi_i32(tmp
, tmp
, -offset
);
1357 store_reg(s
, rd
, tmp
);
1358 } else if (!(insn
& (1 << 23)))
1363 static inline int gen_iwmmxt_shift(uint32_t insn
, uint32_t mask
, TCGv_i32 dest
)
1365 int rd
= (insn
>> 0) & 0xf;
1368 if (insn
& (1 << 8)) {
1369 if (rd
< ARM_IWMMXT_wCGR0
|| rd
> ARM_IWMMXT_wCGR3
) {
1372 tmp
= iwmmxt_load_creg(rd
);
1375 tmp
= tcg_temp_new_i32();
1376 iwmmxt_load_reg(cpu_V0
, rd
);
1377 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
1379 tcg_gen_andi_i32(tmp
, tmp
, mask
);
1380 tcg_gen_mov_i32(dest
, tmp
);
1381 tcg_temp_free_i32(tmp
);
1385 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1386 (ie. an undefined instruction). */
1387 static int disas_iwmmxt_insn(CPUARMState
*env
, DisasContext
*s
, uint32_t insn
)
1390 int rdhi
, rdlo
, rd0
, rd1
, i
;
1392 TCGv_i32 tmp
, tmp2
, tmp3
;
1394 if ((insn
& 0x0e000e00) == 0x0c000000) {
1395 if ((insn
& 0x0fe00ff0) == 0x0c400000) {
1397 rdlo
= (insn
>> 12) & 0xf;
1398 rdhi
= (insn
>> 16) & 0xf;
1399 if (insn
& ARM_CP_RW_BIT
) { /* TMRRC */
1400 iwmmxt_load_reg(cpu_V0
, wrd
);
1401 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
1402 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
1403 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
1404 } else { /* TMCRR */
1405 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
1406 iwmmxt_store_reg(cpu_V0
, wrd
);
1407 gen_op_iwmmxt_set_mup();
1412 wrd
= (insn
>> 12) & 0xf;
1413 addr
= tcg_temp_new_i32();
1414 if (gen_iwmmxt_address(s
, insn
, addr
)) {
1415 tcg_temp_free_i32(addr
);
1418 if (insn
& ARM_CP_RW_BIT
) {
1419 if ((insn
>> 28) == 0xf) { /* WLDRW wCx */
1420 tmp
= tcg_temp_new_i32();
1421 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1422 iwmmxt_store_creg(wrd
, tmp
);
1425 if (insn
& (1 << 8)) {
1426 if (insn
& (1 << 22)) { /* WLDRD */
1427 tcg_gen_qemu_ld64(cpu_M0
, addr
, IS_USER(s
));
1429 } else { /* WLDRW wRd */
1430 tmp
= tcg_temp_new_i32();
1431 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
1434 tmp
= tcg_temp_new_i32();
1435 if (insn
& (1 << 22)) { /* WLDRH */
1436 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
1437 } else { /* WLDRB */
1438 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
1442 tcg_gen_extu_i32_i64(cpu_M0
, tmp
);
1443 tcg_temp_free_i32(tmp
);
1445 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1448 if ((insn
>> 28) == 0xf) { /* WSTRW wCx */
1449 tmp
= iwmmxt_load_creg(wrd
);
1450 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
1452 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1453 tmp
= tcg_temp_new_i32();
1454 if (insn
& (1 << 8)) {
1455 if (insn
& (1 << 22)) { /* WSTRD */
1456 tcg_gen_qemu_st64(cpu_M0
, addr
, IS_USER(s
));
1457 } else { /* WSTRW wRd */
1458 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1459 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
1462 if (insn
& (1 << 22)) { /* WSTRH */
1463 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1464 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
1465 } else { /* WSTRB */
1466 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1467 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
1471 tcg_temp_free_i32(tmp
);
1473 tcg_temp_free_i32(addr
);
1477 if ((insn
& 0x0f000000) != 0x0e000000)
1480 switch (((insn
>> 12) & 0xf00) | ((insn
>> 4) & 0xff)) {
1481 case 0x000: /* WOR */
1482 wrd
= (insn
>> 12) & 0xf;
1483 rd0
= (insn
>> 0) & 0xf;
1484 rd1
= (insn
>> 16) & 0xf;
1485 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1486 gen_op_iwmmxt_orq_M0_wRn(rd1
);
1487 gen_op_iwmmxt_setpsr_nz();
1488 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1489 gen_op_iwmmxt_set_mup();
1490 gen_op_iwmmxt_set_cup();
1492 case 0x011: /* TMCR */
1495 rd
= (insn
>> 12) & 0xf;
1496 wrd
= (insn
>> 16) & 0xf;
1498 case ARM_IWMMXT_wCID
:
1499 case ARM_IWMMXT_wCASF
:
1501 case ARM_IWMMXT_wCon
:
1502 gen_op_iwmmxt_set_cup();
1504 case ARM_IWMMXT_wCSSF
:
1505 tmp
= iwmmxt_load_creg(wrd
);
1506 tmp2
= load_reg(s
, rd
);
1507 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
1508 tcg_temp_free_i32(tmp2
);
1509 iwmmxt_store_creg(wrd
, tmp
);
1511 case ARM_IWMMXT_wCGR0
:
1512 case ARM_IWMMXT_wCGR1
:
1513 case ARM_IWMMXT_wCGR2
:
1514 case ARM_IWMMXT_wCGR3
:
1515 gen_op_iwmmxt_set_cup();
1516 tmp
= load_reg(s
, rd
);
1517 iwmmxt_store_creg(wrd
, tmp
);
1523 case 0x100: /* WXOR */
1524 wrd
= (insn
>> 12) & 0xf;
1525 rd0
= (insn
>> 0) & 0xf;
1526 rd1
= (insn
>> 16) & 0xf;
1527 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1528 gen_op_iwmmxt_xorq_M0_wRn(rd1
);
1529 gen_op_iwmmxt_setpsr_nz();
1530 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1531 gen_op_iwmmxt_set_mup();
1532 gen_op_iwmmxt_set_cup();
1534 case 0x111: /* TMRC */
1537 rd
= (insn
>> 12) & 0xf;
1538 wrd
= (insn
>> 16) & 0xf;
1539 tmp
= iwmmxt_load_creg(wrd
);
1540 store_reg(s
, rd
, tmp
);
1542 case 0x300: /* WANDN */
1543 wrd
= (insn
>> 12) & 0xf;
1544 rd0
= (insn
>> 0) & 0xf;
1545 rd1
= (insn
>> 16) & 0xf;
1546 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1547 tcg_gen_neg_i64(cpu_M0
, cpu_M0
);
1548 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1549 gen_op_iwmmxt_setpsr_nz();
1550 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1551 gen_op_iwmmxt_set_mup();
1552 gen_op_iwmmxt_set_cup();
1554 case 0x200: /* WAND */
1555 wrd
= (insn
>> 12) & 0xf;
1556 rd0
= (insn
>> 0) & 0xf;
1557 rd1
= (insn
>> 16) & 0xf;
1558 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1559 gen_op_iwmmxt_andq_M0_wRn(rd1
);
1560 gen_op_iwmmxt_setpsr_nz();
1561 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1562 gen_op_iwmmxt_set_mup();
1563 gen_op_iwmmxt_set_cup();
1565 case 0x810: case 0xa10: /* WMADD */
1566 wrd
= (insn
>> 12) & 0xf;
1567 rd0
= (insn
>> 0) & 0xf;
1568 rd1
= (insn
>> 16) & 0xf;
1569 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1570 if (insn
& (1 << 21))
1571 gen_op_iwmmxt_maddsq_M0_wRn(rd1
);
1573 gen_op_iwmmxt_madduq_M0_wRn(rd1
);
1574 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1575 gen_op_iwmmxt_set_mup();
1577 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1578 wrd
= (insn
>> 12) & 0xf;
1579 rd0
= (insn
>> 16) & 0xf;
1580 rd1
= (insn
>> 0) & 0xf;
1581 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1582 switch ((insn
>> 22) & 3) {
1584 gen_op_iwmmxt_unpacklb_M0_wRn(rd1
);
1587 gen_op_iwmmxt_unpacklw_M0_wRn(rd1
);
1590 gen_op_iwmmxt_unpackll_M0_wRn(rd1
);
1595 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1596 gen_op_iwmmxt_set_mup();
1597 gen_op_iwmmxt_set_cup();
1599 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1600 wrd
= (insn
>> 12) & 0xf;
1601 rd0
= (insn
>> 16) & 0xf;
1602 rd1
= (insn
>> 0) & 0xf;
1603 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1604 switch ((insn
>> 22) & 3) {
1606 gen_op_iwmmxt_unpackhb_M0_wRn(rd1
);
1609 gen_op_iwmmxt_unpackhw_M0_wRn(rd1
);
1612 gen_op_iwmmxt_unpackhl_M0_wRn(rd1
);
1617 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1618 gen_op_iwmmxt_set_mup();
1619 gen_op_iwmmxt_set_cup();
1621 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1622 wrd
= (insn
>> 12) & 0xf;
1623 rd0
= (insn
>> 16) & 0xf;
1624 rd1
= (insn
>> 0) & 0xf;
1625 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1626 if (insn
& (1 << 22))
1627 gen_op_iwmmxt_sadw_M0_wRn(rd1
);
1629 gen_op_iwmmxt_sadb_M0_wRn(rd1
);
1630 if (!(insn
& (1 << 20)))
1631 gen_op_iwmmxt_addl_M0_wRn(wrd
);
1632 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1633 gen_op_iwmmxt_set_mup();
1635 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1636 wrd
= (insn
>> 12) & 0xf;
1637 rd0
= (insn
>> 16) & 0xf;
1638 rd1
= (insn
>> 0) & 0xf;
1639 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1640 if (insn
& (1 << 21)) {
1641 if (insn
& (1 << 20))
1642 gen_op_iwmmxt_mulshw_M0_wRn(rd1
);
1644 gen_op_iwmmxt_mulslw_M0_wRn(rd1
);
1646 if (insn
& (1 << 20))
1647 gen_op_iwmmxt_muluhw_M0_wRn(rd1
);
1649 gen_op_iwmmxt_mululw_M0_wRn(rd1
);
1651 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1652 gen_op_iwmmxt_set_mup();
1654 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1655 wrd
= (insn
>> 12) & 0xf;
1656 rd0
= (insn
>> 16) & 0xf;
1657 rd1
= (insn
>> 0) & 0xf;
1658 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1659 if (insn
& (1 << 21))
1660 gen_op_iwmmxt_macsw_M0_wRn(rd1
);
1662 gen_op_iwmmxt_macuw_M0_wRn(rd1
);
1663 if (!(insn
& (1 << 20))) {
1664 iwmmxt_load_reg(cpu_V1
, wrd
);
1665 tcg_gen_add_i64(cpu_M0
, cpu_M0
, cpu_V1
);
1667 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1668 gen_op_iwmmxt_set_mup();
1670 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1671 wrd
= (insn
>> 12) & 0xf;
1672 rd0
= (insn
>> 16) & 0xf;
1673 rd1
= (insn
>> 0) & 0xf;
1674 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1675 switch ((insn
>> 22) & 3) {
1677 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1
);
1680 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1
);
1683 gen_op_iwmmxt_cmpeql_M0_wRn(rd1
);
1688 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1689 gen_op_iwmmxt_set_mup();
1690 gen_op_iwmmxt_set_cup();
1692 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1693 wrd
= (insn
>> 12) & 0xf;
1694 rd0
= (insn
>> 16) & 0xf;
1695 rd1
= (insn
>> 0) & 0xf;
1696 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1697 if (insn
& (1 << 22)) {
1698 if (insn
& (1 << 20))
1699 gen_op_iwmmxt_avgw1_M0_wRn(rd1
);
1701 gen_op_iwmmxt_avgw0_M0_wRn(rd1
);
1703 if (insn
& (1 << 20))
1704 gen_op_iwmmxt_avgb1_M0_wRn(rd1
);
1706 gen_op_iwmmxt_avgb0_M0_wRn(rd1
);
1708 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1709 gen_op_iwmmxt_set_mup();
1710 gen_op_iwmmxt_set_cup();
1712 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1713 wrd
= (insn
>> 12) & 0xf;
1714 rd0
= (insn
>> 16) & 0xf;
1715 rd1
= (insn
>> 0) & 0xf;
1716 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1717 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCGR0
+ ((insn
>> 20) & 3));
1718 tcg_gen_andi_i32(tmp
, tmp
, 7);
1719 iwmmxt_load_reg(cpu_V1
, rd1
);
1720 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
1721 tcg_temp_free_i32(tmp
);
1722 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1723 gen_op_iwmmxt_set_mup();
1725 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1726 if (((insn
>> 6) & 3) == 3)
1728 rd
= (insn
>> 12) & 0xf;
1729 wrd
= (insn
>> 16) & 0xf;
1730 tmp
= load_reg(s
, rd
);
1731 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1732 switch ((insn
>> 6) & 3) {
1734 tmp2
= tcg_const_i32(0xff);
1735 tmp3
= tcg_const_i32((insn
& 7) << 3);
1738 tmp2
= tcg_const_i32(0xffff);
1739 tmp3
= tcg_const_i32((insn
& 3) << 4);
1742 tmp2
= tcg_const_i32(0xffffffff);
1743 tmp3
= tcg_const_i32((insn
& 1) << 5);
1746 TCGV_UNUSED_I32(tmp2
);
1747 TCGV_UNUSED_I32(tmp3
);
1749 gen_helper_iwmmxt_insr(cpu_M0
, cpu_M0
, tmp
, tmp2
, tmp3
);
1750 tcg_temp_free_i32(tmp3
);
1751 tcg_temp_free_i32(tmp2
);
1752 tcg_temp_free_i32(tmp
);
1753 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1754 gen_op_iwmmxt_set_mup();
1756 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1757 rd
= (insn
>> 12) & 0xf;
1758 wrd
= (insn
>> 16) & 0xf;
1759 if (rd
== 15 || ((insn
>> 22) & 3) == 3)
1761 gen_op_iwmmxt_movq_M0_wRn(wrd
);
1762 tmp
= tcg_temp_new_i32();
1763 switch ((insn
>> 22) & 3) {
1765 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 7) << 3);
1766 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1768 tcg_gen_ext8s_i32(tmp
, tmp
);
1770 tcg_gen_andi_i32(tmp
, tmp
, 0xff);
1774 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 3) << 4);
1775 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1777 tcg_gen_ext16s_i32(tmp
, tmp
);
1779 tcg_gen_andi_i32(tmp
, tmp
, 0xffff);
1783 tcg_gen_shri_i64(cpu_M0
, cpu_M0
, (insn
& 1) << 5);
1784 tcg_gen_trunc_i64_i32(tmp
, cpu_M0
);
1787 store_reg(s
, rd
, tmp
);
1789 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1790 if ((insn
& 0x000ff008) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1792 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1793 switch ((insn
>> 22) & 3) {
1795 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 7) << 2) + 0);
1798 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 3) << 3) + 4);
1801 tcg_gen_shri_i32(tmp
, tmp
, ((insn
& 1) << 4) + 12);
1804 tcg_gen_shli_i32(tmp
, tmp
, 28);
1806 tcg_temp_free_i32(tmp
);
1808 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1809 if (((insn
>> 6) & 3) == 3)
1811 rd
= (insn
>> 12) & 0xf;
1812 wrd
= (insn
>> 16) & 0xf;
1813 tmp
= load_reg(s
, rd
);
1814 switch ((insn
>> 6) & 3) {
1816 gen_helper_iwmmxt_bcstb(cpu_M0
, tmp
);
1819 gen_helper_iwmmxt_bcstw(cpu_M0
, tmp
);
1822 gen_helper_iwmmxt_bcstl(cpu_M0
, tmp
);
1825 tcg_temp_free_i32(tmp
);
1826 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1827 gen_op_iwmmxt_set_mup();
1829 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1830 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1832 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1833 tmp2
= tcg_temp_new_i32();
1834 tcg_gen_mov_i32(tmp2
, tmp
);
1835 switch ((insn
>> 22) & 3) {
1837 for (i
= 0; i
< 7; i
++) {
1838 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1839 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1843 for (i
= 0; i
< 3; i
++) {
1844 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1845 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1849 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1850 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
1854 tcg_temp_free_i32(tmp2
);
1855 tcg_temp_free_i32(tmp
);
1857 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1858 wrd
= (insn
>> 12) & 0xf;
1859 rd0
= (insn
>> 16) & 0xf;
1860 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1861 switch ((insn
>> 22) & 3) {
1863 gen_helper_iwmmxt_addcb(cpu_M0
, cpu_M0
);
1866 gen_helper_iwmmxt_addcw(cpu_M0
, cpu_M0
);
1869 gen_helper_iwmmxt_addcl(cpu_M0
, cpu_M0
);
1874 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1875 gen_op_iwmmxt_set_mup();
1877 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1878 if ((insn
& 0x000ff00f) != 0x0003f000 || ((insn
>> 22) & 3) == 3)
1880 tmp
= iwmmxt_load_creg(ARM_IWMMXT_wCASF
);
1881 tmp2
= tcg_temp_new_i32();
1882 tcg_gen_mov_i32(tmp2
, tmp
);
1883 switch ((insn
>> 22) & 3) {
1885 for (i
= 0; i
< 7; i
++) {
1886 tcg_gen_shli_i32(tmp2
, tmp2
, 4);
1887 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1891 for (i
= 0; i
< 3; i
++) {
1892 tcg_gen_shli_i32(tmp2
, tmp2
, 8);
1893 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1897 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
1898 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
1902 tcg_temp_free_i32(tmp2
);
1903 tcg_temp_free_i32(tmp
);
1905 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1906 rd
= (insn
>> 12) & 0xf;
1907 rd0
= (insn
>> 16) & 0xf;
1908 if ((insn
& 0xf) != 0 || ((insn
>> 22) & 3) == 3)
1910 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1911 tmp
= tcg_temp_new_i32();
1912 switch ((insn
>> 22) & 3) {
1914 gen_helper_iwmmxt_msbb(tmp
, cpu_M0
);
1917 gen_helper_iwmmxt_msbw(tmp
, cpu_M0
);
1920 gen_helper_iwmmxt_msbl(tmp
, cpu_M0
);
1923 store_reg(s
, rd
, tmp
);
1925 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1926 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1927 wrd
= (insn
>> 12) & 0xf;
1928 rd0
= (insn
>> 16) & 0xf;
1929 rd1
= (insn
>> 0) & 0xf;
1930 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1931 switch ((insn
>> 22) & 3) {
1933 if (insn
& (1 << 21))
1934 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1
);
1936 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1
);
1939 if (insn
& (1 << 21))
1940 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1
);
1942 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1
);
1945 if (insn
& (1 << 21))
1946 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1
);
1948 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1
);
1953 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1954 gen_op_iwmmxt_set_mup();
1955 gen_op_iwmmxt_set_cup();
1957 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
1958 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
1959 wrd
= (insn
>> 12) & 0xf;
1960 rd0
= (insn
>> 16) & 0xf;
1961 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1962 switch ((insn
>> 22) & 3) {
1964 if (insn
& (1 << 21))
1965 gen_op_iwmmxt_unpacklsb_M0();
1967 gen_op_iwmmxt_unpacklub_M0();
1970 if (insn
& (1 << 21))
1971 gen_op_iwmmxt_unpacklsw_M0();
1973 gen_op_iwmmxt_unpackluw_M0();
1976 if (insn
& (1 << 21))
1977 gen_op_iwmmxt_unpacklsl_M0();
1979 gen_op_iwmmxt_unpacklul_M0();
1984 gen_op_iwmmxt_movq_wRn_M0(wrd
);
1985 gen_op_iwmmxt_set_mup();
1986 gen_op_iwmmxt_set_cup();
1988 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
1989 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
1990 wrd
= (insn
>> 12) & 0xf;
1991 rd0
= (insn
>> 16) & 0xf;
1992 gen_op_iwmmxt_movq_M0_wRn(rd0
);
1993 switch ((insn
>> 22) & 3) {
1995 if (insn
& (1 << 21))
1996 gen_op_iwmmxt_unpackhsb_M0();
1998 gen_op_iwmmxt_unpackhub_M0();
2001 if (insn
& (1 << 21))
2002 gen_op_iwmmxt_unpackhsw_M0();
2004 gen_op_iwmmxt_unpackhuw_M0();
2007 if (insn
& (1 << 21))
2008 gen_op_iwmmxt_unpackhsl_M0();
2010 gen_op_iwmmxt_unpackhul_M0();
2015 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2016 gen_op_iwmmxt_set_mup();
2017 gen_op_iwmmxt_set_cup();
2019 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2020 case 0x214: case 0x614: case 0xa14: case 0xe14:
2021 if (((insn
>> 22) & 3) == 0)
2023 wrd
= (insn
>> 12) & 0xf;
2024 rd0
= (insn
>> 16) & 0xf;
2025 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2026 tmp
= tcg_temp_new_i32();
2027 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2028 tcg_temp_free_i32(tmp
);
2031 switch ((insn
>> 22) & 3) {
2033 gen_helper_iwmmxt_srlw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2036 gen_helper_iwmmxt_srll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2039 gen_helper_iwmmxt_srlq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2042 tcg_temp_free_i32(tmp
);
2043 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2044 gen_op_iwmmxt_set_mup();
2045 gen_op_iwmmxt_set_cup();
2047 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2048 case 0x014: case 0x414: case 0x814: case 0xc14:
2049 if (((insn
>> 22) & 3) == 0)
2051 wrd
= (insn
>> 12) & 0xf;
2052 rd0
= (insn
>> 16) & 0xf;
2053 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2054 tmp
= tcg_temp_new_i32();
2055 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2056 tcg_temp_free_i32(tmp
);
2059 switch ((insn
>> 22) & 3) {
2061 gen_helper_iwmmxt_sraw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2064 gen_helper_iwmmxt_sral(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2067 gen_helper_iwmmxt_sraq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2070 tcg_temp_free_i32(tmp
);
2071 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2072 gen_op_iwmmxt_set_mup();
2073 gen_op_iwmmxt_set_cup();
2075 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2076 case 0x114: case 0x514: case 0x914: case 0xd14:
2077 if (((insn
>> 22) & 3) == 0)
2079 wrd
= (insn
>> 12) & 0xf;
2080 rd0
= (insn
>> 16) & 0xf;
2081 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2082 tmp
= tcg_temp_new_i32();
2083 if (gen_iwmmxt_shift(insn
, 0xff, tmp
)) {
2084 tcg_temp_free_i32(tmp
);
2087 switch ((insn
>> 22) & 3) {
2089 gen_helper_iwmmxt_sllw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2092 gen_helper_iwmmxt_slll(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2095 gen_helper_iwmmxt_sllq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2098 tcg_temp_free_i32(tmp
);
2099 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2100 gen_op_iwmmxt_set_mup();
2101 gen_op_iwmmxt_set_cup();
2103 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2104 case 0x314: case 0x714: case 0xb14: case 0xf14:
2105 if (((insn
>> 22) & 3) == 0)
2107 wrd
= (insn
>> 12) & 0xf;
2108 rd0
= (insn
>> 16) & 0xf;
2109 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2110 tmp
= tcg_temp_new_i32();
2111 switch ((insn
>> 22) & 3) {
2113 if (gen_iwmmxt_shift(insn
, 0xf, tmp
)) {
2114 tcg_temp_free_i32(tmp
);
2117 gen_helper_iwmmxt_rorw(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2120 if (gen_iwmmxt_shift(insn
, 0x1f, tmp
)) {
2121 tcg_temp_free_i32(tmp
);
2124 gen_helper_iwmmxt_rorl(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2127 if (gen_iwmmxt_shift(insn
, 0x3f, tmp
)) {
2128 tcg_temp_free_i32(tmp
);
2131 gen_helper_iwmmxt_rorq(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2134 tcg_temp_free_i32(tmp
);
2135 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2136 gen_op_iwmmxt_set_mup();
2137 gen_op_iwmmxt_set_cup();
2139 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2140 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2141 wrd
= (insn
>> 12) & 0xf;
2142 rd0
= (insn
>> 16) & 0xf;
2143 rd1
= (insn
>> 0) & 0xf;
2144 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2145 switch ((insn
>> 22) & 3) {
2147 if (insn
& (1 << 21))
2148 gen_op_iwmmxt_minsb_M0_wRn(rd1
);
2150 gen_op_iwmmxt_minub_M0_wRn(rd1
);
2153 if (insn
& (1 << 21))
2154 gen_op_iwmmxt_minsw_M0_wRn(rd1
);
2156 gen_op_iwmmxt_minuw_M0_wRn(rd1
);
2159 if (insn
& (1 << 21))
2160 gen_op_iwmmxt_minsl_M0_wRn(rd1
);
2162 gen_op_iwmmxt_minul_M0_wRn(rd1
);
2167 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2168 gen_op_iwmmxt_set_mup();
2170 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2171 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2172 wrd
= (insn
>> 12) & 0xf;
2173 rd0
= (insn
>> 16) & 0xf;
2174 rd1
= (insn
>> 0) & 0xf;
2175 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2176 switch ((insn
>> 22) & 3) {
2178 if (insn
& (1 << 21))
2179 gen_op_iwmmxt_maxsb_M0_wRn(rd1
);
2181 gen_op_iwmmxt_maxub_M0_wRn(rd1
);
2184 if (insn
& (1 << 21))
2185 gen_op_iwmmxt_maxsw_M0_wRn(rd1
);
2187 gen_op_iwmmxt_maxuw_M0_wRn(rd1
);
2190 if (insn
& (1 << 21))
2191 gen_op_iwmmxt_maxsl_M0_wRn(rd1
);
2193 gen_op_iwmmxt_maxul_M0_wRn(rd1
);
2198 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2199 gen_op_iwmmxt_set_mup();
2201 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2202 case 0x402: case 0x502: case 0x602: case 0x702:
2203 wrd
= (insn
>> 12) & 0xf;
2204 rd0
= (insn
>> 16) & 0xf;
2205 rd1
= (insn
>> 0) & 0xf;
2206 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2207 tmp
= tcg_const_i32((insn
>> 20) & 3);
2208 iwmmxt_load_reg(cpu_V1
, rd1
);
2209 gen_helper_iwmmxt_align(cpu_M0
, cpu_M0
, cpu_V1
, tmp
);
2210 tcg_temp_free_i32(tmp
);
2211 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2212 gen_op_iwmmxt_set_mup();
2214 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2215 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2216 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2217 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
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
>> 20) & 0xf) {
2224 gen_op_iwmmxt_subnb_M0_wRn(rd1
);
2227 gen_op_iwmmxt_subub_M0_wRn(rd1
);
2230 gen_op_iwmmxt_subsb_M0_wRn(rd1
);
2233 gen_op_iwmmxt_subnw_M0_wRn(rd1
);
2236 gen_op_iwmmxt_subuw_M0_wRn(rd1
);
2239 gen_op_iwmmxt_subsw_M0_wRn(rd1
);
2242 gen_op_iwmmxt_subnl_M0_wRn(rd1
);
2245 gen_op_iwmmxt_subul_M0_wRn(rd1
);
2248 gen_op_iwmmxt_subsl_M0_wRn(rd1
);
2253 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2254 gen_op_iwmmxt_set_mup();
2255 gen_op_iwmmxt_set_cup();
2257 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2258 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2259 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2260 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2261 wrd
= (insn
>> 12) & 0xf;
2262 rd0
= (insn
>> 16) & 0xf;
2263 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2264 tmp
= tcg_const_i32(((insn
>> 16) & 0xf0) | (insn
& 0x0f));
2265 gen_helper_iwmmxt_shufh(cpu_M0
, cpu_env
, cpu_M0
, tmp
);
2266 tcg_temp_free_i32(tmp
);
2267 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2268 gen_op_iwmmxt_set_mup();
2269 gen_op_iwmmxt_set_cup();
2271 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2272 case 0x418: case 0x518: case 0x618: case 0x718:
2273 case 0x818: case 0x918: case 0xa18: case 0xb18:
2274 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2275 wrd
= (insn
>> 12) & 0xf;
2276 rd0
= (insn
>> 16) & 0xf;
2277 rd1
= (insn
>> 0) & 0xf;
2278 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2279 switch ((insn
>> 20) & 0xf) {
2281 gen_op_iwmmxt_addnb_M0_wRn(rd1
);
2284 gen_op_iwmmxt_addub_M0_wRn(rd1
);
2287 gen_op_iwmmxt_addsb_M0_wRn(rd1
);
2290 gen_op_iwmmxt_addnw_M0_wRn(rd1
);
2293 gen_op_iwmmxt_adduw_M0_wRn(rd1
);
2296 gen_op_iwmmxt_addsw_M0_wRn(rd1
);
2299 gen_op_iwmmxt_addnl_M0_wRn(rd1
);
2302 gen_op_iwmmxt_addul_M0_wRn(rd1
);
2305 gen_op_iwmmxt_addsl_M0_wRn(rd1
);
2310 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2311 gen_op_iwmmxt_set_mup();
2312 gen_op_iwmmxt_set_cup();
2314 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2315 case 0x408: case 0x508: case 0x608: case 0x708:
2316 case 0x808: case 0x908: case 0xa08: case 0xb08:
2317 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2318 if (!(insn
& (1 << 20)) || ((insn
>> 22) & 3) == 0)
2320 wrd
= (insn
>> 12) & 0xf;
2321 rd0
= (insn
>> 16) & 0xf;
2322 rd1
= (insn
>> 0) & 0xf;
2323 gen_op_iwmmxt_movq_M0_wRn(rd0
);
2324 switch ((insn
>> 22) & 3) {
2326 if (insn
& (1 << 21))
2327 gen_op_iwmmxt_packsw_M0_wRn(rd1
);
2329 gen_op_iwmmxt_packuw_M0_wRn(rd1
);
2332 if (insn
& (1 << 21))
2333 gen_op_iwmmxt_packsl_M0_wRn(rd1
);
2335 gen_op_iwmmxt_packul_M0_wRn(rd1
);
2338 if (insn
& (1 << 21))
2339 gen_op_iwmmxt_packsq_M0_wRn(rd1
);
2341 gen_op_iwmmxt_packuq_M0_wRn(rd1
);
2344 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2345 gen_op_iwmmxt_set_mup();
2346 gen_op_iwmmxt_set_cup();
2348 case 0x201: case 0x203: case 0x205: case 0x207:
2349 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2350 case 0x211: case 0x213: case 0x215: case 0x217:
2351 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2352 wrd
= (insn
>> 5) & 0xf;
2353 rd0
= (insn
>> 12) & 0xf;
2354 rd1
= (insn
>> 0) & 0xf;
2355 if (rd0
== 0xf || rd1
== 0xf)
2357 gen_op_iwmmxt_movq_M0_wRn(wrd
);
2358 tmp
= load_reg(s
, rd0
);
2359 tmp2
= load_reg(s
, rd1
);
2360 switch ((insn
>> 16) & 0xf) {
2361 case 0x0: /* TMIA */
2362 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2364 case 0x8: /* TMIAPH */
2365 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2367 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2368 if (insn
& (1 << 16))
2369 tcg_gen_shri_i32(tmp
, tmp
, 16);
2370 if (insn
& (1 << 17))
2371 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2372 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2375 tcg_temp_free_i32(tmp2
);
2376 tcg_temp_free_i32(tmp
);
2379 tcg_temp_free_i32(tmp2
);
2380 tcg_temp_free_i32(tmp
);
2381 gen_op_iwmmxt_movq_wRn_M0(wrd
);
2382 gen_op_iwmmxt_set_mup();
2391 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2392 (ie. an undefined instruction). */
2393 static int disas_dsp_insn(CPUARMState
*env
, DisasContext
*s
, uint32_t insn
)
2395 int acc
, rd0
, rd1
, rdhi
, rdlo
;
2398 if ((insn
& 0x0ff00f10) == 0x0e200010) {
2399 /* Multiply with Internal Accumulate Format */
2400 rd0
= (insn
>> 12) & 0xf;
2402 acc
= (insn
>> 5) & 7;
2407 tmp
= load_reg(s
, rd0
);
2408 tmp2
= load_reg(s
, rd1
);
2409 switch ((insn
>> 16) & 0xf) {
2411 gen_helper_iwmmxt_muladdsl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2413 case 0x8: /* MIAPH */
2414 gen_helper_iwmmxt_muladdsw(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2416 case 0xc: /* MIABB */
2417 case 0xd: /* MIABT */
2418 case 0xe: /* MIATB */
2419 case 0xf: /* MIATT */
2420 if (insn
& (1 << 16))
2421 tcg_gen_shri_i32(tmp
, tmp
, 16);
2422 if (insn
& (1 << 17))
2423 tcg_gen_shri_i32(tmp2
, tmp2
, 16);
2424 gen_helper_iwmmxt_muladdswl(cpu_M0
, cpu_M0
, tmp
, tmp2
);
2429 tcg_temp_free_i32(tmp2
);
2430 tcg_temp_free_i32(tmp
);
2432 gen_op_iwmmxt_movq_wRn_M0(acc
);
2436 if ((insn
& 0x0fe00ff8) == 0x0c400000) {
2437 /* Internal Accumulator Access Format */
2438 rdhi
= (insn
>> 16) & 0xf;
2439 rdlo
= (insn
>> 12) & 0xf;
2445 if (insn
& ARM_CP_RW_BIT
) { /* MRA */
2446 iwmmxt_load_reg(cpu_V0
, acc
);
2447 tcg_gen_trunc_i64_i32(cpu_R
[rdlo
], cpu_V0
);
2448 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
2449 tcg_gen_trunc_i64_i32(cpu_R
[rdhi
], cpu_V0
);
2450 tcg_gen_andi_i32(cpu_R
[rdhi
], cpu_R
[rdhi
], (1 << (40 - 32)) - 1);
2452 tcg_gen_concat_i32_i64(cpu_V0
, cpu_R
[rdlo
], cpu_R
[rdhi
]);
2453 iwmmxt_store_reg(cpu_V0
, acc
);
2461 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2462 #define VFP_SREG(insn, bigbit, smallbit) \
2463 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2464 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2465 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2466 reg = (((insn) >> (bigbit)) & 0x0f) \
2467 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2469 if (insn & (1 << (smallbit))) \
2471 reg = ((insn) >> (bigbit)) & 0x0f; \
2474 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2475 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2476 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2477 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2478 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2479 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2481 /* Move between integer and VFP cores. */
2482 static TCGv_i32
gen_vfp_mrs(void)
2484 TCGv_i32 tmp
= tcg_temp_new_i32();
2485 tcg_gen_mov_i32(tmp
, cpu_F0s
);
2489 static void gen_vfp_msr(TCGv_i32 tmp
)
2491 tcg_gen_mov_i32(cpu_F0s
, tmp
);
2492 tcg_temp_free_i32(tmp
);
2495 static void gen_neon_dup_u8(TCGv_i32 var
, int shift
)
2497 TCGv_i32 tmp
= tcg_temp_new_i32();
2499 tcg_gen_shri_i32(var
, var
, shift
);
2500 tcg_gen_ext8u_i32(var
, var
);
2501 tcg_gen_shli_i32(tmp
, var
, 8);
2502 tcg_gen_or_i32(var
, var
, tmp
);
2503 tcg_gen_shli_i32(tmp
, var
, 16);
2504 tcg_gen_or_i32(var
, var
, tmp
);
2505 tcg_temp_free_i32(tmp
);
2508 static void gen_neon_dup_low16(TCGv_i32 var
)
2510 TCGv_i32 tmp
= tcg_temp_new_i32();
2511 tcg_gen_ext16u_i32(var
, var
);
2512 tcg_gen_shli_i32(tmp
, var
, 16);
2513 tcg_gen_or_i32(var
, var
, tmp
);
2514 tcg_temp_free_i32(tmp
);
2517 static void gen_neon_dup_high16(TCGv_i32 var
)
2519 TCGv_i32 tmp
= tcg_temp_new_i32();
2520 tcg_gen_andi_i32(var
, var
, 0xffff0000);
2521 tcg_gen_shri_i32(tmp
, var
, 16);
2522 tcg_gen_or_i32(var
, var
, tmp
);
2523 tcg_temp_free_i32(tmp
);
2526 static TCGv_i32
gen_load_and_replicate(DisasContext
*s
, TCGv_i32 addr
, int size
)
2528 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2529 TCGv_i32 tmp
= tcg_temp_new_i32();
2532 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
2533 gen_neon_dup_u8(tmp
, 0);
2536 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
2537 gen_neon_dup_low16(tmp
);
2540 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
2542 default: /* Avoid compiler warnings. */
2548 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2549 (ie. an undefined instruction). */
2550 static int disas_vfp_insn(CPUARMState
* env
, DisasContext
*s
, uint32_t insn
)
2552 uint32_t rd
, rn
, rm
, op
, i
, n
, offset
, delta_d
, delta_m
, bank_mask
;
2558 if (!arm_feature(env
, ARM_FEATURE_VFP
))
2561 if (!s
->vfp_enabled
) {
2562 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2563 if ((insn
& 0x0fe00fff) != 0x0ee00a10)
2565 rn
= (insn
>> 16) & 0xf;
2566 if (rn
!= ARM_VFP_FPSID
&& rn
!= ARM_VFP_FPEXC
2567 && rn
!= ARM_VFP_MVFR1
&& rn
!= ARM_VFP_MVFR0
)
2570 dp
= ((insn
& 0xf00) == 0xb00);
2571 switch ((insn
>> 24) & 0xf) {
2573 if (insn
& (1 << 4)) {
2574 /* single register transfer */
2575 rd
= (insn
>> 12) & 0xf;
2580 VFP_DREG_N(rn
, insn
);
2583 if (insn
& 0x00c00060
2584 && !arm_feature(env
, ARM_FEATURE_NEON
))
2587 pass
= (insn
>> 21) & 1;
2588 if (insn
& (1 << 22)) {
2590 offset
= ((insn
>> 5) & 3) * 8;
2591 } else if (insn
& (1 << 5)) {
2593 offset
= (insn
& (1 << 6)) ? 16 : 0;
2598 if (insn
& ARM_CP_RW_BIT
) {
2600 tmp
= neon_load_reg(rn
, pass
);
2604 tcg_gen_shri_i32(tmp
, tmp
, offset
);
2605 if (insn
& (1 << 23))
2611 if (insn
& (1 << 23)) {
2613 tcg_gen_shri_i32(tmp
, tmp
, 16);
2619 tcg_gen_sari_i32(tmp
, tmp
, 16);
2628 store_reg(s
, rd
, tmp
);
2631 tmp
= load_reg(s
, rd
);
2632 if (insn
& (1 << 23)) {
2635 gen_neon_dup_u8(tmp
, 0);
2636 } else if (size
== 1) {
2637 gen_neon_dup_low16(tmp
);
2639 for (n
= 0; n
<= pass
* 2; n
++) {
2640 tmp2
= tcg_temp_new_i32();
2641 tcg_gen_mov_i32(tmp2
, tmp
);
2642 neon_store_reg(rn
, n
, tmp2
);
2644 neon_store_reg(rn
, n
, tmp
);
2649 tmp2
= neon_load_reg(rn
, pass
);
2650 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
, offset
, 8);
2651 tcg_temp_free_i32(tmp2
);
2654 tmp2
= neon_load_reg(rn
, pass
);
2655 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
, offset
, 16);
2656 tcg_temp_free_i32(tmp2
);
2661 neon_store_reg(rn
, pass
, tmp
);
2665 if ((insn
& 0x6f) != 0x00)
2667 rn
= VFP_SREG_N(insn
);
2668 if (insn
& ARM_CP_RW_BIT
) {
2670 if (insn
& (1 << 21)) {
2671 /* system register */
2676 /* VFP2 allows access to FSID from userspace.
2677 VFP3 restricts all id registers to privileged
2680 && arm_feature(env
, ARM_FEATURE_VFP3
))
2682 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2687 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2689 case ARM_VFP_FPINST
:
2690 case ARM_VFP_FPINST2
:
2691 /* Not present in VFP3. */
2693 || arm_feature(env
, ARM_FEATURE_VFP3
))
2695 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2699 tmp
= load_cpu_field(vfp
.xregs
[ARM_VFP_FPSCR
]);
2700 tcg_gen_andi_i32(tmp
, tmp
, 0xf0000000);
2702 tmp
= tcg_temp_new_i32();
2703 gen_helper_vfp_get_fpscr(tmp
, cpu_env
);
2709 || !arm_feature(env
, ARM_FEATURE_MVFR
))
2711 tmp
= load_cpu_field(vfp
.xregs
[rn
]);
2717 gen_mov_F0_vreg(0, rn
);
2718 tmp
= gen_vfp_mrs();
2721 /* Set the 4 flag bits in the CPSR. */
2723 tcg_temp_free_i32(tmp
);
2725 store_reg(s
, rd
, tmp
);
2729 if (insn
& (1 << 21)) {
2731 /* system register */
2736 /* Writes are ignored. */
2739 tmp
= load_reg(s
, rd
);
2740 gen_helper_vfp_set_fpscr(cpu_env
, tmp
);
2741 tcg_temp_free_i32(tmp
);
2747 /* TODO: VFP subarchitecture support.
2748 * For now, keep the EN bit only */
2749 tmp
= load_reg(s
, rd
);
2750 tcg_gen_andi_i32(tmp
, tmp
, 1 << 30);
2751 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2754 case ARM_VFP_FPINST
:
2755 case ARM_VFP_FPINST2
:
2756 tmp
= load_reg(s
, rd
);
2757 store_cpu_field(tmp
, vfp
.xregs
[rn
]);
2763 tmp
= load_reg(s
, rd
);
2765 gen_mov_vreg_F0(0, rn
);
2770 /* data processing */
2771 /* The opcode is in bits 23, 21, 20 and 6. */
2772 op
= ((insn
>> 20) & 8) | ((insn
>> 19) & 6) | ((insn
>> 6) & 1);
2776 rn
= ((insn
>> 15) & 0x1e) | ((insn
>> 7) & 1);
2778 /* rn is register number */
2779 VFP_DREG_N(rn
, insn
);
2782 if (op
== 15 && (rn
== 15 || ((rn
& 0x1c) == 0x18))) {
2783 /* Integer or single precision destination. */
2784 rd
= VFP_SREG_D(insn
);
2786 VFP_DREG_D(rd
, insn
);
2789 (((rn
& 0x1c) == 0x10) || ((rn
& 0x14) == 0x14))) {
2790 /* VCVT from int is always from S reg regardless of dp bit.
2791 * VCVT with immediate frac_bits has same format as SREG_M
2793 rm
= VFP_SREG_M(insn
);
2795 VFP_DREG_M(rm
, insn
);
2798 rn
= VFP_SREG_N(insn
);
2799 if (op
== 15 && rn
== 15) {
2800 /* Double precision destination. */
2801 VFP_DREG_D(rd
, insn
);
2803 rd
= VFP_SREG_D(insn
);
2805 /* NB that we implicitly rely on the encoding for the frac_bits
2806 * in VCVT of fixed to float being the same as that of an SREG_M
2808 rm
= VFP_SREG_M(insn
);
2811 veclen
= s
->vec_len
;
2812 if (op
== 15 && rn
> 3)
2815 /* Shut up compiler warnings. */
2826 /* Figure out what type of vector operation this is. */
2827 if ((rd
& bank_mask
) == 0) {
2832 delta_d
= (s
->vec_stride
>> 1) + 1;
2834 delta_d
= s
->vec_stride
+ 1;
2836 if ((rm
& bank_mask
) == 0) {
2837 /* mixed scalar/vector */
2846 /* Load the initial operands. */
2851 /* Integer source */
2852 gen_mov_F0_vreg(0, rm
);
2857 gen_mov_F0_vreg(dp
, rd
);
2858 gen_mov_F1_vreg(dp
, rm
);
2862 /* Compare with zero */
2863 gen_mov_F0_vreg(dp
, rd
);
2874 /* Source and destination the same. */
2875 gen_mov_F0_vreg(dp
, rd
);
2881 /* VCVTB, VCVTT: only present with the halfprec extension,
2882 * UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
2884 if (dp
|| !arm_feature(env
, ARM_FEATURE_VFP_FP16
)) {
2887 /* Otherwise fall through */
2889 /* One source operand. */
2890 gen_mov_F0_vreg(dp
, rm
);
2894 /* Two source operands. */
2895 gen_mov_F0_vreg(dp
, rn
);
2896 gen_mov_F1_vreg(dp
, rm
);
2900 /* Perform the calculation. */
2902 case 0: /* VMLA: fd + (fn * fm) */
2903 /* Note that order of inputs to the add matters for NaNs */
2905 gen_mov_F0_vreg(dp
, rd
);
2908 case 1: /* VMLS: fd + -(fn * fm) */
2911 gen_mov_F0_vreg(dp
, rd
);
2914 case 2: /* VNMLS: -fd + (fn * fm) */
2915 /* Note that it isn't valid to replace (-A + B) with (B - A)
2916 * or similar plausible looking simplifications
2917 * because this will give wrong results for NaNs.
2920 gen_mov_F0_vreg(dp
, rd
);
2924 case 3: /* VNMLA: -fd + -(fn * fm) */
2927 gen_mov_F0_vreg(dp
, rd
);
2931 case 4: /* mul: fn * fm */
2934 case 5: /* nmul: -(fn * fm) */
2938 case 6: /* add: fn + fm */
2941 case 7: /* sub: fn - fm */
2944 case 8: /* div: fn / fm */
2947 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
2948 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
2949 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
2950 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
2951 /* These are fused multiply-add, and must be done as one
2952 * floating point operation with no rounding between the
2953 * multiplication and addition steps.
2954 * NB that doing the negations here as separate steps is
2955 * correct : an input NaN should come out with its sign bit
2956 * flipped if it is a negated-input.
2958 if (!arm_feature(env
, ARM_FEATURE_VFP4
)) {
2966 gen_helper_vfp_negd(cpu_F0d
, cpu_F0d
);
2968 frd
= tcg_temp_new_i64();
2969 tcg_gen_ld_f64(frd
, cpu_env
, vfp_reg_offset(dp
, rd
));
2972 gen_helper_vfp_negd(frd
, frd
);
2974 fpst
= get_fpstatus_ptr(0);
2975 gen_helper_vfp_muladdd(cpu_F0d
, cpu_F0d
,
2976 cpu_F1d
, frd
, fpst
);
2977 tcg_temp_free_ptr(fpst
);
2978 tcg_temp_free_i64(frd
);
2984 gen_helper_vfp_negs(cpu_F0s
, cpu_F0s
);
2986 frd
= tcg_temp_new_i32();
2987 tcg_gen_ld_f32(frd
, cpu_env
, vfp_reg_offset(dp
, rd
));
2989 gen_helper_vfp_negs(frd
, frd
);
2991 fpst
= get_fpstatus_ptr(0);
2992 gen_helper_vfp_muladds(cpu_F0s
, cpu_F0s
,
2993 cpu_F1s
, frd
, fpst
);
2994 tcg_temp_free_ptr(fpst
);
2995 tcg_temp_free_i32(frd
);
2998 case 14: /* fconst */
2999 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3002 n
= (insn
<< 12) & 0x80000000;
3003 i
= ((insn
>> 12) & 0x70) | (insn
& 0xf);
3010 tcg_gen_movi_i64(cpu_F0d
, ((uint64_t)n
) << 32);
3017 tcg_gen_movi_i32(cpu_F0s
, n
);
3020 case 15: /* extension space */
3034 case 4: /* vcvtb.f32.f16 */
3035 tmp
= gen_vfp_mrs();
3036 tcg_gen_ext16u_i32(tmp
, tmp
);
3037 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3038 tcg_temp_free_i32(tmp
);
3040 case 5: /* vcvtt.f32.f16 */
3041 tmp
= gen_vfp_mrs();
3042 tcg_gen_shri_i32(tmp
, tmp
, 16);
3043 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s
, tmp
, cpu_env
);
3044 tcg_temp_free_i32(tmp
);
3046 case 6: /* vcvtb.f16.f32 */
3047 tmp
= tcg_temp_new_i32();
3048 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3049 gen_mov_F0_vreg(0, rd
);
3050 tmp2
= gen_vfp_mrs();
3051 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
3052 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3053 tcg_temp_free_i32(tmp2
);
3056 case 7: /* vcvtt.f16.f32 */
3057 tmp
= tcg_temp_new_i32();
3058 gen_helper_vfp_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
3059 tcg_gen_shli_i32(tmp
, tmp
, 16);
3060 gen_mov_F0_vreg(0, rd
);
3061 tmp2
= gen_vfp_mrs();
3062 tcg_gen_ext16u_i32(tmp2
, tmp2
);
3063 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3064 tcg_temp_free_i32(tmp2
);
3076 case 11: /* cmpez */
3080 case 15: /* single<->double conversion */
3082 gen_helper_vfp_fcvtsd(cpu_F0s
, cpu_F0d
, cpu_env
);
3084 gen_helper_vfp_fcvtds(cpu_F0d
, cpu_F0s
, cpu_env
);
3086 case 16: /* fuito */
3087 gen_vfp_uito(dp
, 0);
3089 case 17: /* fsito */
3090 gen_vfp_sito(dp
, 0);
3092 case 20: /* fshto */
3093 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3095 gen_vfp_shto(dp
, 16 - rm
, 0);
3097 case 21: /* fslto */
3098 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3100 gen_vfp_slto(dp
, 32 - rm
, 0);
3102 case 22: /* fuhto */
3103 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3105 gen_vfp_uhto(dp
, 16 - rm
, 0);
3107 case 23: /* fulto */
3108 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3110 gen_vfp_ulto(dp
, 32 - rm
, 0);
3112 case 24: /* ftoui */
3113 gen_vfp_toui(dp
, 0);
3115 case 25: /* ftouiz */
3116 gen_vfp_touiz(dp
, 0);
3118 case 26: /* ftosi */
3119 gen_vfp_tosi(dp
, 0);
3121 case 27: /* ftosiz */
3122 gen_vfp_tosiz(dp
, 0);
3124 case 28: /* ftosh */
3125 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3127 gen_vfp_tosh(dp
, 16 - rm
, 0);
3129 case 29: /* ftosl */
3130 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3132 gen_vfp_tosl(dp
, 32 - rm
, 0);
3134 case 30: /* ftouh */
3135 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3137 gen_vfp_touh(dp
, 16 - rm
, 0);
3139 case 31: /* ftoul */
3140 if (!arm_feature(env
, ARM_FEATURE_VFP3
))
3142 gen_vfp_toul(dp
, 32 - rm
, 0);
3144 default: /* undefined */
3148 default: /* undefined */
3152 /* Write back the result. */
3153 if (op
== 15 && (rn
>= 8 && rn
<= 11))
3154 ; /* Comparison, do nothing. */
3155 else if (op
== 15 && dp
&& ((rn
& 0x1c) == 0x18))
3156 /* VCVT double to int: always integer result. */
3157 gen_mov_vreg_F0(0, rd
);
3158 else if (op
== 15 && rn
== 15)
3160 gen_mov_vreg_F0(!dp
, rd
);
3162 gen_mov_vreg_F0(dp
, rd
);
3164 /* break out of the loop if we have finished */
3168 if (op
== 15 && delta_m
== 0) {
3169 /* single source one-many */
3171 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3173 gen_mov_vreg_F0(dp
, rd
);
3177 /* Setup the next operands. */
3179 rd
= ((rd
+ delta_d
) & (bank_mask
- 1))
3183 /* One source operand. */
3184 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3186 gen_mov_F0_vreg(dp
, rm
);
3188 /* Two source operands. */
3189 rn
= ((rn
+ delta_d
) & (bank_mask
- 1))
3191 gen_mov_F0_vreg(dp
, rn
);
3193 rm
= ((rm
+ delta_m
) & (bank_mask
- 1))
3195 gen_mov_F1_vreg(dp
, rm
);
3203 if ((insn
& 0x03e00000) == 0x00400000) {
3204 /* two-register transfer */
3205 rn
= (insn
>> 16) & 0xf;
3206 rd
= (insn
>> 12) & 0xf;
3208 VFP_DREG_M(rm
, insn
);
3210 rm
= VFP_SREG_M(insn
);
3213 if (insn
& ARM_CP_RW_BIT
) {
3216 gen_mov_F0_vreg(0, rm
* 2);
3217 tmp
= gen_vfp_mrs();
3218 store_reg(s
, rd
, tmp
);
3219 gen_mov_F0_vreg(0, rm
* 2 + 1);
3220 tmp
= gen_vfp_mrs();
3221 store_reg(s
, rn
, tmp
);
3223 gen_mov_F0_vreg(0, rm
);
3224 tmp
= gen_vfp_mrs();
3225 store_reg(s
, rd
, tmp
);
3226 gen_mov_F0_vreg(0, rm
+ 1);
3227 tmp
= gen_vfp_mrs();
3228 store_reg(s
, rn
, tmp
);
3233 tmp
= load_reg(s
, rd
);
3235 gen_mov_vreg_F0(0, rm
* 2);
3236 tmp
= load_reg(s
, rn
);
3238 gen_mov_vreg_F0(0, rm
* 2 + 1);
3240 tmp
= load_reg(s
, rd
);
3242 gen_mov_vreg_F0(0, rm
);
3243 tmp
= load_reg(s
, rn
);
3245 gen_mov_vreg_F0(0, rm
+ 1);
3250 rn
= (insn
>> 16) & 0xf;
3252 VFP_DREG_D(rd
, insn
);
3254 rd
= VFP_SREG_D(insn
);
3255 if ((insn
& 0x01200000) == 0x01000000) {
3256 /* Single load/store */
3257 offset
= (insn
& 0xff) << 2;
3258 if ((insn
& (1 << 23)) == 0)
3260 if (s
->thumb
&& rn
== 15) {
3261 /* This is actually UNPREDICTABLE */
3262 addr
= tcg_temp_new_i32();
3263 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3265 addr
= load_reg(s
, rn
);
3267 tcg_gen_addi_i32(addr
, addr
, offset
);
3268 if (insn
& (1 << 20)) {
3269 gen_vfp_ld(s
, dp
, addr
);
3270 gen_mov_vreg_F0(dp
, rd
);
3272 gen_mov_F0_vreg(dp
, rd
);
3273 gen_vfp_st(s
, dp
, addr
);
3275 tcg_temp_free_i32(addr
);
3277 /* load/store multiple */
3278 int w
= insn
& (1 << 21);
3280 n
= (insn
>> 1) & 0x7f;
3284 if (w
&& !(((insn
>> 23) ^ (insn
>> 24)) & 1)) {
3285 /* P == U , W == 1 => UNDEF */
3288 if (n
== 0 || (rd
+ n
) > 32 || (dp
&& n
> 16)) {
3289 /* UNPREDICTABLE cases for bad immediates: we choose to
3290 * UNDEF to avoid generating huge numbers of TCG ops
3294 if (rn
== 15 && w
) {
3295 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3299 if (s
->thumb
&& rn
== 15) {
3300 /* This is actually UNPREDICTABLE */
3301 addr
= tcg_temp_new_i32();
3302 tcg_gen_movi_i32(addr
, s
->pc
& ~2);
3304 addr
= load_reg(s
, rn
);
3306 if (insn
& (1 << 24)) /* pre-decrement */
3307 tcg_gen_addi_i32(addr
, addr
, -((insn
& 0xff) << 2));
3313 for (i
= 0; i
< n
; i
++) {
3314 if (insn
& ARM_CP_RW_BIT
) {
3316 gen_vfp_ld(s
, dp
, addr
);
3317 gen_mov_vreg_F0(dp
, rd
+ i
);
3320 gen_mov_F0_vreg(dp
, rd
+ i
);
3321 gen_vfp_st(s
, dp
, addr
);
3323 tcg_gen_addi_i32(addr
, addr
, offset
);
3327 if (insn
& (1 << 24))
3328 offset
= -offset
* n
;
3329 else if (dp
&& (insn
& 1))
3335 tcg_gen_addi_i32(addr
, addr
, offset
);
3336 store_reg(s
, rn
, addr
);
3338 tcg_temp_free_i32(addr
);
3344 /* Should never happen. */
3350 static inline void gen_goto_tb(DisasContext
*s
, int n
, uint32_t dest
)
3352 TranslationBlock
*tb
;
3355 if ((tb
->pc
& TARGET_PAGE_MASK
) == (dest
& TARGET_PAGE_MASK
)) {
3357 gen_set_pc_im(dest
);
3358 tcg_gen_exit_tb((tcg_target_long
)tb
+ n
);
3360 gen_set_pc_im(dest
);
3365 static inline void gen_jmp (DisasContext
*s
, uint32_t dest
)
3367 if (unlikely(s
->singlestep_enabled
)) {
3368 /* An indirect jump so that we still trigger the debug exception. */
3373 gen_goto_tb(s
, 0, dest
);
3374 s
->is_jmp
= DISAS_TB_JUMP
;
3378 static inline void gen_mulxy(TCGv_i32 t0
, TCGv_i32 t1
, int x
, int y
)
3381 tcg_gen_sari_i32(t0
, t0
, 16);
3385 tcg_gen_sari_i32(t1
, t1
, 16);
3388 tcg_gen_mul_i32(t0
, t0
, t1
);
3391 /* Return the mask of PSR bits set by a MSR instruction. */
3392 static uint32_t msr_mask(CPUARMState
*env
, DisasContext
*s
, int flags
, int spsr
) {
3396 if (flags
& (1 << 0))
3398 if (flags
& (1 << 1))
3400 if (flags
& (1 << 2))
3402 if (flags
& (1 << 3))
3405 /* Mask out undefined bits. */
3406 mask
&= ~CPSR_RESERVED
;
3407 if (!arm_feature(env
, ARM_FEATURE_V4T
))
3409 if (!arm_feature(env
, ARM_FEATURE_V5
))
3410 mask
&= ~CPSR_Q
; /* V5TE in reality*/
3411 if (!arm_feature(env
, ARM_FEATURE_V6
))
3412 mask
&= ~(CPSR_E
| CPSR_GE
);
3413 if (!arm_feature(env
, ARM_FEATURE_THUMB2
))
3415 /* Mask out execution state bits. */
3418 /* Mask out privileged bits. */
3424 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3425 static int gen_set_psr(DisasContext
*s
, uint32_t mask
, int spsr
, TCGv_i32 t0
)
3429 /* ??? This is also undefined in system mode. */
3433 tmp
= load_cpu_field(spsr
);
3434 tcg_gen_andi_i32(tmp
, tmp
, ~mask
);
3435 tcg_gen_andi_i32(t0
, t0
, mask
);
3436 tcg_gen_or_i32(tmp
, tmp
, t0
);
3437 store_cpu_field(tmp
, spsr
);
3439 gen_set_cpsr(t0
, mask
);
3441 tcg_temp_free_i32(t0
);
3446 /* Returns nonzero if access to the PSR is not permitted. */
3447 static int gen_set_psr_im(DisasContext
*s
, uint32_t mask
, int spsr
, uint32_t val
)
3450 tmp
= tcg_temp_new_i32();
3451 tcg_gen_movi_i32(tmp
, val
);
3452 return gen_set_psr(s
, mask
, spsr
, tmp
);
3455 /* Generate an old-style exception return. Marks pc as dead. */
3456 static void gen_exception_return(DisasContext
*s
, TCGv_i32 pc
)
3459 store_reg(s
, 15, pc
);
3460 tmp
= load_cpu_field(spsr
);
3461 gen_set_cpsr(tmp
, 0xffffffff);
3462 tcg_temp_free_i32(tmp
);
3463 s
->is_jmp
= DISAS_UPDATE
;
3466 /* Generate a v6 exception return. Marks both values as dead. */
3467 static void gen_rfe(DisasContext
*s
, TCGv_i32 pc
, TCGv_i32 cpsr
)
3469 gen_set_cpsr(cpsr
, 0xffffffff);
3470 tcg_temp_free_i32(cpsr
);
3471 store_reg(s
, 15, pc
);
3472 s
->is_jmp
= DISAS_UPDATE
;
3476 gen_set_condexec (DisasContext
*s
)
3478 if (s
->condexec_mask
) {
3479 uint32_t val
= (s
->condexec_cond
<< 4) | (s
->condexec_mask
>> 1);
3480 TCGv_i32 tmp
= tcg_temp_new_i32();
3481 tcg_gen_movi_i32(tmp
, val
);
3482 store_cpu_field(tmp
, condexec_bits
);
3486 static void gen_exception_insn(DisasContext
*s
, int offset
, int excp
)
3488 gen_set_condexec(s
);
3489 gen_set_pc_im(s
->pc
- offset
);
3490 gen_exception(excp
);
3491 s
->is_jmp
= DISAS_JUMP
;
3494 static void gen_nop_hint(DisasContext
*s
, int val
)
3498 gen_set_pc_im(s
->pc
);
3499 s
->is_jmp
= DISAS_WFI
;
3503 /* TODO: Implement SEV and WFE. May help SMP performance. */
3509 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3511 static inline void gen_neon_add(int size
, TCGv_i32 t0
, TCGv_i32 t1
)
3514 case 0: gen_helper_neon_add_u8(t0
, t0
, t1
); break;
3515 case 1: gen_helper_neon_add_u16(t0
, t0
, t1
); break;
3516 case 2: tcg_gen_add_i32(t0
, t0
, t1
); break;
3521 static inline void gen_neon_rsb(int size
, TCGv_i32 t0
, TCGv_i32 t1
)
3524 case 0: gen_helper_neon_sub_u8(t0
, t1
, t0
); break;
3525 case 1: gen_helper_neon_sub_u16(t0
, t1
, t0
); break;
3526 case 2: tcg_gen_sub_i32(t0
, t1
, t0
); break;
3531 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3532 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3533 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3534 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3535 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3537 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3538 switch ((size << 1) | u) { \
3540 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3543 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3546 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3549 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3552 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3555 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3557 default: return 1; \
3560 #define GEN_NEON_INTEGER_OP(name) do { \
3561 switch ((size << 1) | u) { \
3563 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3566 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3569 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3572 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3575 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3578 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3580 default: return 1; \
3583 static TCGv_i32
neon_load_scratch(int scratch
)
3585 TCGv_i32 tmp
= tcg_temp_new_i32();
3586 tcg_gen_ld_i32(tmp
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3590 static void neon_store_scratch(int scratch
, TCGv_i32 var
)
3592 tcg_gen_st_i32(var
, cpu_env
, offsetof(CPUARMState
, vfp
.scratch
[scratch
]));
3593 tcg_temp_free_i32(var
);
3596 static inline TCGv_i32
neon_get_scalar(int size
, int reg
)
3600 tmp
= neon_load_reg(reg
& 7, reg
>> 4);
3602 gen_neon_dup_high16(tmp
);
3604 gen_neon_dup_low16(tmp
);
3607 tmp
= neon_load_reg(reg
& 15, reg
>> 4);
3612 static int gen_neon_unzip(int rd
, int rm
, int size
, int q
)
3615 if (!q
&& size
== 2) {
3618 tmp
= tcg_const_i32(rd
);
3619 tmp2
= tcg_const_i32(rm
);
3623 gen_helper_neon_qunzip8(cpu_env
, tmp
, tmp2
);
3626 gen_helper_neon_qunzip16(cpu_env
, tmp
, tmp2
);
3629 gen_helper_neon_qunzip32(cpu_env
, tmp
, tmp2
);
3637 gen_helper_neon_unzip8(cpu_env
, tmp
, tmp2
);
3640 gen_helper_neon_unzip16(cpu_env
, tmp
, tmp2
);
3646 tcg_temp_free_i32(tmp
);
3647 tcg_temp_free_i32(tmp2
);
3651 static int gen_neon_zip(int rd
, int rm
, int size
, int q
)
3654 if (!q
&& size
== 2) {
3657 tmp
= tcg_const_i32(rd
);
3658 tmp2
= tcg_const_i32(rm
);
3662 gen_helper_neon_qzip8(cpu_env
, tmp
, tmp2
);
3665 gen_helper_neon_qzip16(cpu_env
, tmp
, tmp2
);
3668 gen_helper_neon_qzip32(cpu_env
, tmp
, tmp2
);
3676 gen_helper_neon_zip8(cpu_env
, tmp
, tmp2
);
3679 gen_helper_neon_zip16(cpu_env
, tmp
, tmp2
);
3685 tcg_temp_free_i32(tmp
);
3686 tcg_temp_free_i32(tmp2
);
3690 static void gen_neon_trn_u8(TCGv_i32 t0
, TCGv_i32 t1
)
3694 rd
= tcg_temp_new_i32();
3695 tmp
= tcg_temp_new_i32();
3697 tcg_gen_shli_i32(rd
, t0
, 8);
3698 tcg_gen_andi_i32(rd
, rd
, 0xff00ff00);
3699 tcg_gen_andi_i32(tmp
, t1
, 0x00ff00ff);
3700 tcg_gen_or_i32(rd
, rd
, tmp
);
3702 tcg_gen_shri_i32(t1
, t1
, 8);
3703 tcg_gen_andi_i32(t1
, t1
, 0x00ff00ff);
3704 tcg_gen_andi_i32(tmp
, t0
, 0xff00ff00);
3705 tcg_gen_or_i32(t1
, t1
, tmp
);
3706 tcg_gen_mov_i32(t0
, rd
);
3708 tcg_temp_free_i32(tmp
);
3709 tcg_temp_free_i32(rd
);
3712 static void gen_neon_trn_u16(TCGv_i32 t0
, TCGv_i32 t1
)
3716 rd
= tcg_temp_new_i32();
3717 tmp
= tcg_temp_new_i32();
3719 tcg_gen_shli_i32(rd
, t0
, 16);
3720 tcg_gen_andi_i32(tmp
, t1
, 0xffff);
3721 tcg_gen_or_i32(rd
, rd
, tmp
);
3722 tcg_gen_shri_i32(t1
, t1
, 16);
3723 tcg_gen_andi_i32(tmp
, t0
, 0xffff0000);
3724 tcg_gen_or_i32(t1
, t1
, tmp
);
3725 tcg_gen_mov_i32(t0
, rd
);
3727 tcg_temp_free_i32(tmp
);
3728 tcg_temp_free_i32(rd
);
3736 } neon_ls_element_type
[11] = {
3750 /* Translate a NEON load/store element instruction. Return nonzero if the
3751 instruction is invalid. */
3752 static int disas_neon_ls_insn(CPUARMState
* env
, DisasContext
*s
, uint32_t insn
)
3771 if (!s
->vfp_enabled
)
3773 VFP_DREG_D(rd
, insn
);
3774 rn
= (insn
>> 16) & 0xf;
3776 load
= (insn
& (1 << 21)) != 0;
3777 if ((insn
& (1 << 23)) == 0) {
3778 /* Load store all elements. */
3779 op
= (insn
>> 8) & 0xf;
3780 size
= (insn
>> 6) & 3;
3783 /* Catch UNDEF cases for bad values of align field */
3786 if (((insn
>> 5) & 1) == 1) {
3791 if (((insn
>> 4) & 3) == 3) {
3798 nregs
= neon_ls_element_type
[op
].nregs
;
3799 interleave
= neon_ls_element_type
[op
].interleave
;
3800 spacing
= neon_ls_element_type
[op
].spacing
;
3801 if (size
== 3 && (interleave
| spacing
) != 1)
3803 addr
= tcg_temp_new_i32();
3804 load_reg_var(s
, addr
, rn
);
3805 stride
= (1 << size
) * interleave
;
3806 for (reg
= 0; reg
< nregs
; reg
++) {
3807 if (interleave
> 2 || (interleave
== 2 && nregs
== 2)) {
3808 load_reg_var(s
, addr
, rn
);
3809 tcg_gen_addi_i32(addr
, addr
, (1 << size
) * reg
);
3810 } else if (interleave
== 2 && nregs
== 4 && reg
== 2) {
3811 load_reg_var(s
, addr
, rn
);
3812 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3815 tmp64
= tcg_temp_new_i64();
3817 tcg_gen_qemu_ld64(tmp64
, addr
, IS_USER(s
));
3818 neon_store_reg64(tmp64
, rd
);
3820 neon_load_reg64(tmp64
, rd
);
3821 tcg_gen_qemu_st64(tmp64
, addr
, IS_USER(s
));
3823 tcg_temp_free_i64(tmp64
);
3824 tcg_gen_addi_i32(addr
, addr
, stride
);
3826 for (pass
= 0; pass
< 2; pass
++) {
3829 tmp
= tcg_temp_new_i32();
3830 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
3831 neon_store_reg(rd
, pass
, tmp
);
3833 tmp
= neon_load_reg(rd
, pass
);
3834 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
3835 tcg_temp_free_i32(tmp
);
3837 tcg_gen_addi_i32(addr
, addr
, stride
);
3838 } else if (size
== 1) {
3840 tmp
= tcg_temp_new_i32();
3841 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
3842 tcg_gen_addi_i32(addr
, addr
, stride
);
3843 tmp2
= tcg_temp_new_i32();
3844 tcg_gen_qemu_ld16u(tmp2
, addr
, IS_USER(s
));
3845 tcg_gen_addi_i32(addr
, addr
, stride
);
3846 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
3847 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
3848 tcg_temp_free_i32(tmp2
);
3849 neon_store_reg(rd
, pass
, tmp
);
3851 tmp
= neon_load_reg(rd
, pass
);
3852 tmp2
= tcg_temp_new_i32();
3853 tcg_gen_shri_i32(tmp2
, tmp
, 16);
3854 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
3855 tcg_temp_free_i32(tmp
);
3856 tcg_gen_addi_i32(addr
, addr
, stride
);
3857 tcg_gen_qemu_st16(tmp2
, addr
, IS_USER(s
));
3858 tcg_temp_free_i32(tmp2
);
3859 tcg_gen_addi_i32(addr
, addr
, stride
);
3861 } else /* size == 0 */ {
3863 TCGV_UNUSED_I32(tmp2
);
3864 for (n
= 0; n
< 4; n
++) {
3865 tmp
= tcg_temp_new_i32();
3866 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
3867 tcg_gen_addi_i32(addr
, addr
, stride
);
3871 tcg_gen_shli_i32(tmp
, tmp
, n
* 8);
3872 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
3873 tcg_temp_free_i32(tmp
);
3876 neon_store_reg(rd
, pass
, tmp2
);
3878 tmp2
= neon_load_reg(rd
, pass
);
3879 for (n
= 0; n
< 4; n
++) {
3880 tmp
= tcg_temp_new_i32();
3882 tcg_gen_mov_i32(tmp
, tmp2
);
3884 tcg_gen_shri_i32(tmp
, tmp2
, n
* 8);
3886 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
3887 tcg_temp_free_i32(tmp
);
3888 tcg_gen_addi_i32(addr
, addr
, stride
);
3890 tcg_temp_free_i32(tmp2
);
3897 tcg_temp_free_i32(addr
);
3900 size
= (insn
>> 10) & 3;
3902 /* Load single element to all lanes. */
3903 int a
= (insn
>> 4) & 1;
3907 size
= (insn
>> 6) & 3;
3908 nregs
= ((insn
>> 8) & 3) + 1;
3911 if (nregs
!= 4 || a
== 0) {
3914 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
3917 if (nregs
== 1 && a
== 1 && size
== 0) {
3920 if (nregs
== 3 && a
== 1) {
3923 addr
= tcg_temp_new_i32();
3924 load_reg_var(s
, addr
, rn
);
3926 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
3927 tmp
= gen_load_and_replicate(s
, addr
, size
);
3928 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
, 0));
3929 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
, 1));
3930 if (insn
& (1 << 5)) {
3931 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
+ 1, 0));
3932 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
+ 1, 1));
3934 tcg_temp_free_i32(tmp
);
3936 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
3937 stride
= (insn
& (1 << 5)) ? 2 : 1;
3938 for (reg
= 0; reg
< nregs
; reg
++) {
3939 tmp
= gen_load_and_replicate(s
, addr
, size
);
3940 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
, 0));
3941 tcg_gen_st_i32(tmp
, cpu_env
, neon_reg_offset(rd
, 1));
3942 tcg_temp_free_i32(tmp
);
3943 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
3947 tcg_temp_free_i32(addr
);
3948 stride
= (1 << size
) * nregs
;
3950 /* Single element. */
3951 int idx
= (insn
>> 4) & 0xf;
3952 pass
= (insn
>> 7) & 1;
3955 shift
= ((insn
>> 5) & 3) * 8;
3959 shift
= ((insn
>> 6) & 1) * 16;
3960 stride
= (insn
& (1 << 5)) ? 2 : 1;
3964 stride
= (insn
& (1 << 6)) ? 2 : 1;
3969 nregs
= ((insn
>> 8) & 3) + 1;
3970 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
3973 if (((idx
& (1 << size
)) != 0) ||
3974 (size
== 2 && ((idx
& 3) == 1 || (idx
& 3) == 2))) {
3979 if ((idx
& 1) != 0) {
3984 if (size
== 2 && (idx
& 2) != 0) {
3989 if ((size
== 2) && ((idx
& 3) == 3)) {
3996 if ((rd
+ stride
* (nregs
- 1)) > 31) {
3997 /* Attempts to write off the end of the register file
3998 * are UNPREDICTABLE; we choose to UNDEF because otherwise
3999 * the neon_load_reg() would write off the end of the array.
4003 addr
= tcg_temp_new_i32();
4004 load_reg_var(s
, addr
, rn
);
4005 for (reg
= 0; reg
< nregs
; reg
++) {
4007 tmp
= tcg_temp_new_i32();
4010 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
4013 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
4016 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
4018 default: /* Avoid compiler warnings. */
4022 tmp2
= neon_load_reg(rd
, pass
);
4023 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
,
4024 shift
, size
? 16 : 8);
4025 tcg_temp_free_i32(tmp2
);
4027 neon_store_reg(rd
, pass
, tmp
);
4028 } else { /* Store */
4029 tmp
= neon_load_reg(rd
, pass
);
4031 tcg_gen_shri_i32(tmp
, tmp
, shift
);
4034 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
4037 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
4040 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
4043 tcg_temp_free_i32(tmp
);
4046 tcg_gen_addi_i32(addr
, addr
, 1 << size
);
4048 tcg_temp_free_i32(addr
);
4049 stride
= nregs
* (1 << size
);
4055 base
= load_reg(s
, rn
);
4057 tcg_gen_addi_i32(base
, base
, stride
);
4060 index
= load_reg(s
, rm
);
4061 tcg_gen_add_i32(base
, base
, index
);
4062 tcg_temp_free_i32(index
);
4064 store_reg(s
, rn
, base
);
4069 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4070 static void gen_neon_bsl(TCGv_i32 dest
, TCGv_i32 t
, TCGv_i32 f
, TCGv_i32 c
)
4072 tcg_gen_and_i32(t
, t
, c
);
4073 tcg_gen_andc_i32(f
, f
, c
);
4074 tcg_gen_or_i32(dest
, t
, f
);
4077 static inline void gen_neon_narrow(int size
, TCGv_i32 dest
, TCGv_i64 src
)
4080 case 0: gen_helper_neon_narrow_u8(dest
, src
); break;
4081 case 1: gen_helper_neon_narrow_u16(dest
, src
); break;
4082 case 2: tcg_gen_trunc_i64_i32(dest
, src
); break;
4087 static inline void gen_neon_narrow_sats(int size
, TCGv_i32 dest
, TCGv_i64 src
)
4090 case 0: gen_helper_neon_narrow_sat_s8(dest
, cpu_env
, src
); break;
4091 case 1: gen_helper_neon_narrow_sat_s16(dest
, cpu_env
, src
); break;
4092 case 2: gen_helper_neon_narrow_sat_s32(dest
, cpu_env
, src
); break;
4097 static inline void gen_neon_narrow_satu(int size
, TCGv_i32 dest
, TCGv_i64 src
)
4100 case 0: gen_helper_neon_narrow_sat_u8(dest
, cpu_env
, src
); break;
4101 case 1: gen_helper_neon_narrow_sat_u16(dest
, cpu_env
, src
); break;
4102 case 2: gen_helper_neon_narrow_sat_u32(dest
, cpu_env
, src
); break;
4107 static inline void gen_neon_unarrow_sats(int size
, TCGv_i32 dest
, TCGv_i64 src
)
4110 case 0: gen_helper_neon_unarrow_sat8(dest
, cpu_env
, src
); break;
4111 case 1: gen_helper_neon_unarrow_sat16(dest
, cpu_env
, src
); break;
4112 case 2: gen_helper_neon_unarrow_sat32(dest
, cpu_env
, src
); break;
4117 static inline void gen_neon_shift_narrow(int size
, TCGv_i32 var
, TCGv_i32 shift
,
4123 case 1: gen_helper_neon_rshl_u16(var
, var
, shift
); break;
4124 case 2: gen_helper_neon_rshl_u32(var
, var
, shift
); break;
4129 case 1: gen_helper_neon_rshl_s16(var
, var
, shift
); break;
4130 case 2: gen_helper_neon_rshl_s32(var
, var
, shift
); break;
4137 case 1: gen_helper_neon_shl_u16(var
, var
, shift
); break;
4138 case 2: gen_helper_neon_shl_u32(var
, var
, shift
); break;
4143 case 1: gen_helper_neon_shl_s16(var
, var
, shift
); break;
4144 case 2: gen_helper_neon_shl_s32(var
, var
, shift
); break;
4151 static inline void gen_neon_widen(TCGv_i64 dest
, TCGv_i32 src
, int size
, int u
)
4155 case 0: gen_helper_neon_widen_u8(dest
, src
); break;
4156 case 1: gen_helper_neon_widen_u16(dest
, src
); break;
4157 case 2: tcg_gen_extu_i32_i64(dest
, src
); break;
4162 case 0: gen_helper_neon_widen_s8(dest
, src
); break;
4163 case 1: gen_helper_neon_widen_s16(dest
, src
); break;
4164 case 2: tcg_gen_ext_i32_i64(dest
, src
); break;
4168 tcg_temp_free_i32(src
);
4171 static inline void gen_neon_addl(int size
)
4174 case 0: gen_helper_neon_addl_u16(CPU_V001
); break;
4175 case 1: gen_helper_neon_addl_u32(CPU_V001
); break;
4176 case 2: tcg_gen_add_i64(CPU_V001
); break;
4181 static inline void gen_neon_subl(int size
)
4184 case 0: gen_helper_neon_subl_u16(CPU_V001
); break;
4185 case 1: gen_helper_neon_subl_u32(CPU_V001
); break;
4186 case 2: tcg_gen_sub_i64(CPU_V001
); break;
4191 static inline void gen_neon_negl(TCGv_i64 var
, int size
)
4194 case 0: gen_helper_neon_negl_u16(var
, var
); break;
4195 case 1: gen_helper_neon_negl_u32(var
, var
); break;
4197 tcg_gen_neg_i64(var
, var
);
4203 static inline void gen_neon_addl_saturate(TCGv_i64 op0
, TCGv_i64 op1
, int size
)
4206 case 1: gen_helper_neon_addl_saturate_s32(op0
, cpu_env
, op0
, op1
); break;
4207 case 2: gen_helper_neon_addl_saturate_s64(op0
, cpu_env
, op0
, op1
); break;
4212 static inline void gen_neon_mull(TCGv_i64 dest
, TCGv_i32 a
, TCGv_i32 b
,
4217 switch ((size
<< 1) | u
) {
4218 case 0: gen_helper_neon_mull_s8(dest
, a
, b
); break;
4219 case 1: gen_helper_neon_mull_u8(dest
, a
, b
); break;
4220 case 2: gen_helper_neon_mull_s16(dest
, a
, b
); break;
4221 case 3: gen_helper_neon_mull_u16(dest
, a
, b
); break;
4223 tmp
= gen_muls_i64_i32(a
, b
);
4224 tcg_gen_mov_i64(dest
, tmp
);
4225 tcg_temp_free_i64(tmp
);
4228 tmp
= gen_mulu_i64_i32(a
, b
);
4229 tcg_gen_mov_i64(dest
, tmp
);
4230 tcg_temp_free_i64(tmp
);
4235 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4236 Don't forget to clean them now. */
4238 tcg_temp_free_i32(a
);
4239 tcg_temp_free_i32(b
);
4243 static void gen_neon_narrow_op(int op
, int u
, int size
,
4244 TCGv_i32 dest
, TCGv_i64 src
)
4248 gen_neon_unarrow_sats(size
, dest
, src
);
4250 gen_neon_narrow(size
, dest
, src
);
4254 gen_neon_narrow_satu(size
, dest
, src
);
4256 gen_neon_narrow_sats(size
, dest
, src
);
4261 /* Symbolic constants for op fields for Neon 3-register same-length.
4262 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4265 #define NEON_3R_VHADD 0
4266 #define NEON_3R_VQADD 1
4267 #define NEON_3R_VRHADD 2
4268 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4269 #define NEON_3R_VHSUB 4
4270 #define NEON_3R_VQSUB 5
4271 #define NEON_3R_VCGT 6
4272 #define NEON_3R_VCGE 7
4273 #define NEON_3R_VSHL 8
4274 #define NEON_3R_VQSHL 9
4275 #define NEON_3R_VRSHL 10
4276 #define NEON_3R_VQRSHL 11
4277 #define NEON_3R_VMAX 12
4278 #define NEON_3R_VMIN 13
4279 #define NEON_3R_VABD 14
4280 #define NEON_3R_VABA 15
4281 #define NEON_3R_VADD_VSUB 16
4282 #define NEON_3R_VTST_VCEQ 17
4283 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4284 #define NEON_3R_VMUL 19
4285 #define NEON_3R_VPMAX 20
4286 #define NEON_3R_VPMIN 21
4287 #define NEON_3R_VQDMULH_VQRDMULH 22
4288 #define NEON_3R_VPADD 23
4289 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4290 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4291 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4292 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4293 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4294 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4295 #define NEON_3R_VRECPS_VRSQRTS 31 /* float VRECPS, VRSQRTS */
4297 static const uint8_t neon_3r_sizes
[] = {
4298 [NEON_3R_VHADD
] = 0x7,
4299 [NEON_3R_VQADD
] = 0xf,
4300 [NEON_3R_VRHADD
] = 0x7,
4301 [NEON_3R_LOGIC
] = 0xf, /* size field encodes op type */
4302 [NEON_3R_VHSUB
] = 0x7,
4303 [NEON_3R_VQSUB
] = 0xf,
4304 [NEON_3R_VCGT
] = 0x7,
4305 [NEON_3R_VCGE
] = 0x7,
4306 [NEON_3R_VSHL
] = 0xf,
4307 [NEON_3R_VQSHL
] = 0xf,
4308 [NEON_3R_VRSHL
] = 0xf,
4309 [NEON_3R_VQRSHL
] = 0xf,
4310 [NEON_3R_VMAX
] = 0x7,
4311 [NEON_3R_VMIN
] = 0x7,
4312 [NEON_3R_VABD
] = 0x7,
4313 [NEON_3R_VABA
] = 0x7,
4314 [NEON_3R_VADD_VSUB
] = 0xf,
4315 [NEON_3R_VTST_VCEQ
] = 0x7,
4316 [NEON_3R_VML
] = 0x7,
4317 [NEON_3R_VMUL
] = 0x7,
4318 [NEON_3R_VPMAX
] = 0x7,
4319 [NEON_3R_VPMIN
] = 0x7,
4320 [NEON_3R_VQDMULH_VQRDMULH
] = 0x6,
4321 [NEON_3R_VPADD
] = 0x7,
4322 [NEON_3R_VFM
] = 0x5, /* size bit 1 encodes op */
4323 [NEON_3R_FLOAT_ARITH
] = 0x5, /* size bit 1 encodes op */
4324 [NEON_3R_FLOAT_MULTIPLY
] = 0x5, /* size bit 1 encodes op */
4325 [NEON_3R_FLOAT_CMP
] = 0x5, /* size bit 1 encodes op */
4326 [NEON_3R_FLOAT_ACMP
] = 0x5, /* size bit 1 encodes op */
4327 [NEON_3R_FLOAT_MINMAX
] = 0x5, /* size bit 1 encodes op */
4328 [NEON_3R_VRECPS_VRSQRTS
] = 0x5, /* size bit 1 encodes op */
4331 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4332 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4335 #define NEON_2RM_VREV64 0
4336 #define NEON_2RM_VREV32 1
4337 #define NEON_2RM_VREV16 2
4338 #define NEON_2RM_VPADDL 4
4339 #define NEON_2RM_VPADDL_U 5
4340 #define NEON_2RM_VCLS 8
4341 #define NEON_2RM_VCLZ 9
4342 #define NEON_2RM_VCNT 10
4343 #define NEON_2RM_VMVN 11
4344 #define NEON_2RM_VPADAL 12
4345 #define NEON_2RM_VPADAL_U 13
4346 #define NEON_2RM_VQABS 14
4347 #define NEON_2RM_VQNEG 15
4348 #define NEON_2RM_VCGT0 16
4349 #define NEON_2RM_VCGE0 17
4350 #define NEON_2RM_VCEQ0 18
4351 #define NEON_2RM_VCLE0 19
4352 #define NEON_2RM_VCLT0 20
4353 #define NEON_2RM_VABS 22
4354 #define NEON_2RM_VNEG 23
4355 #define NEON_2RM_VCGT0_F 24
4356 #define NEON_2RM_VCGE0_F 25
4357 #define NEON_2RM_VCEQ0_F 26
4358 #define NEON_2RM_VCLE0_F 27
4359 #define NEON_2RM_VCLT0_F 28
4360 #define NEON_2RM_VABS_F 30
4361 #define NEON_2RM_VNEG_F 31
4362 #define NEON_2RM_VSWP 32
4363 #define NEON_2RM_VTRN 33
4364 #define NEON_2RM_VUZP 34
4365 #define NEON_2RM_VZIP 35
4366 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4367 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4368 #define NEON_2RM_VSHLL 38
4369 #define NEON_2RM_VCVT_F16_F32 44
4370 #define NEON_2RM_VCVT_F32_F16 46
4371 #define NEON_2RM_VRECPE 56
4372 #define NEON_2RM_VRSQRTE 57
4373 #define NEON_2RM_VRECPE_F 58
4374 #define NEON_2RM_VRSQRTE_F 59
4375 #define NEON_2RM_VCVT_FS 60
4376 #define NEON_2RM_VCVT_FU 61
4377 #define NEON_2RM_VCVT_SF 62
4378 #define NEON_2RM_VCVT_UF 63
4380 static int neon_2rm_is_float_op(int op
)
4382 /* Return true if this neon 2reg-misc op is float-to-float */
4383 return (op
== NEON_2RM_VABS_F
|| op
== NEON_2RM_VNEG_F
||
4384 op
>= NEON_2RM_VRECPE_F
);
4387 /* Each entry in this array has bit n set if the insn allows
4388 * size value n (otherwise it will UNDEF). Since unallocated
4389 * op values will have no bits set they always UNDEF.
4391 static const uint8_t neon_2rm_sizes
[] = {
4392 [NEON_2RM_VREV64
] = 0x7,
4393 [NEON_2RM_VREV32
] = 0x3,
4394 [NEON_2RM_VREV16
] = 0x1,
4395 [NEON_2RM_VPADDL
] = 0x7,
4396 [NEON_2RM_VPADDL_U
] = 0x7,
4397 [NEON_2RM_VCLS
] = 0x7,
4398 [NEON_2RM_VCLZ
] = 0x7,
4399 [NEON_2RM_VCNT
] = 0x1,
4400 [NEON_2RM_VMVN
] = 0x1,
4401 [NEON_2RM_VPADAL
] = 0x7,
4402 [NEON_2RM_VPADAL_U
] = 0x7,
4403 [NEON_2RM_VQABS
] = 0x7,
4404 [NEON_2RM_VQNEG
] = 0x7,
4405 [NEON_2RM_VCGT0
] = 0x7,
4406 [NEON_2RM_VCGE0
] = 0x7,
4407 [NEON_2RM_VCEQ0
] = 0x7,
4408 [NEON_2RM_VCLE0
] = 0x7,
4409 [NEON_2RM_VCLT0
] = 0x7,
4410 [NEON_2RM_VABS
] = 0x7,
4411 [NEON_2RM_VNEG
] = 0x7,
4412 [NEON_2RM_VCGT0_F
] = 0x4,
4413 [NEON_2RM_VCGE0_F
] = 0x4,
4414 [NEON_2RM_VCEQ0_F
] = 0x4,
4415 [NEON_2RM_VCLE0_F
] = 0x4,
4416 [NEON_2RM_VCLT0_F
] = 0x4,
4417 [NEON_2RM_VABS_F
] = 0x4,
4418 [NEON_2RM_VNEG_F
] = 0x4,
4419 [NEON_2RM_VSWP
] = 0x1,
4420 [NEON_2RM_VTRN
] = 0x7,
4421 [NEON_2RM_VUZP
] = 0x7,
4422 [NEON_2RM_VZIP
] = 0x7,
4423 [NEON_2RM_VMOVN
] = 0x7,
4424 [NEON_2RM_VQMOVN
] = 0x7,
4425 [NEON_2RM_VSHLL
] = 0x7,
4426 [NEON_2RM_VCVT_F16_F32
] = 0x2,
4427 [NEON_2RM_VCVT_F32_F16
] = 0x2,
4428 [NEON_2RM_VRECPE
] = 0x4,
4429 [NEON_2RM_VRSQRTE
] = 0x4,
4430 [NEON_2RM_VRECPE_F
] = 0x4,
4431 [NEON_2RM_VRSQRTE_F
] = 0x4,
4432 [NEON_2RM_VCVT_FS
] = 0x4,
4433 [NEON_2RM_VCVT_FU
] = 0x4,
4434 [NEON_2RM_VCVT_SF
] = 0x4,
4435 [NEON_2RM_VCVT_UF
] = 0x4,
4438 /* Translate a NEON data processing instruction. Return nonzero if the
4439 instruction is invalid.
4440 We process data in a mixture of 32-bit and 64-bit chunks.
4441 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4443 static int disas_neon_data_insn(CPUARMState
* env
, DisasContext
*s
, uint32_t insn
)
4455 TCGv_i32 tmp
, tmp2
, tmp3
, tmp4
, tmp5
;
4458 if (!s
->vfp_enabled
)
4460 q
= (insn
& (1 << 6)) != 0;
4461 u
= (insn
>> 24) & 1;
4462 VFP_DREG_D(rd
, insn
);
4463 VFP_DREG_N(rn
, insn
);
4464 VFP_DREG_M(rm
, insn
);
4465 size
= (insn
>> 20) & 3;
4466 if ((insn
& (1 << 23)) == 0) {
4467 /* Three register same length. */
4468 op
= ((insn
>> 7) & 0x1e) | ((insn
>> 4) & 1);
4469 /* Catch invalid op and bad size combinations: UNDEF */
4470 if ((neon_3r_sizes
[op
] & (1 << size
)) == 0) {
4473 /* All insns of this form UNDEF for either this condition or the
4474 * superset of cases "Q==1"; we catch the latter later.
4476 if (q
&& ((rd
| rn
| rm
) & 1)) {
4479 if (size
== 3 && op
!= NEON_3R_LOGIC
) {
4480 /* 64-bit element instructions. */
4481 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
4482 neon_load_reg64(cpu_V0
, rn
+ pass
);
4483 neon_load_reg64(cpu_V1
, rm
+ pass
);
4487 gen_helper_neon_qadd_u64(cpu_V0
, cpu_env
,
4490 gen_helper_neon_qadd_s64(cpu_V0
, cpu_env
,
4496 gen_helper_neon_qsub_u64(cpu_V0
, cpu_env
,
4499 gen_helper_neon_qsub_s64(cpu_V0
, cpu_env
,
4505 gen_helper_neon_shl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4507 gen_helper_neon_shl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4512 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
4515 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
,
4521 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V1
, cpu_V0
);
4523 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V1
, cpu_V0
);
4526 case NEON_3R_VQRSHL
:
4528 gen_helper_neon_qrshl_u64(cpu_V0
, cpu_env
,
4531 gen_helper_neon_qrshl_s64(cpu_V0
, cpu_env
,
4535 case NEON_3R_VADD_VSUB
:
4537 tcg_gen_sub_i64(CPU_V001
);
4539 tcg_gen_add_i64(CPU_V001
);
4545 neon_store_reg64(cpu_V0
, rd
+ pass
);
4554 case NEON_3R_VQRSHL
:
4557 /* Shift instruction operands are reversed. */
4572 case NEON_3R_FLOAT_ARITH
:
4573 pairwise
= (u
&& size
< 2); /* if VPADD (float) */
4575 case NEON_3R_FLOAT_MINMAX
:
4576 pairwise
= u
; /* if VPMIN/VPMAX (float) */
4578 case NEON_3R_FLOAT_CMP
:
4580 /* no encoding for U=0 C=1x */
4584 case NEON_3R_FLOAT_ACMP
:
4589 case NEON_3R_VRECPS_VRSQRTS
:
4595 if (u
&& (size
!= 0)) {
4596 /* UNDEF on invalid size for polynomial subcase */
4601 if (!arm_feature(env
, ARM_FEATURE_VFP4
) || u
) {
4609 if (pairwise
&& q
) {
4610 /* All the pairwise insns UNDEF if Q is set */
4614 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4619 tmp
= neon_load_reg(rn
, 0);
4620 tmp2
= neon_load_reg(rn
, 1);
4622 tmp
= neon_load_reg(rm
, 0);
4623 tmp2
= neon_load_reg(rm
, 1);
4627 tmp
= neon_load_reg(rn
, pass
);
4628 tmp2
= neon_load_reg(rm
, pass
);
4632 GEN_NEON_INTEGER_OP(hadd
);
4635 GEN_NEON_INTEGER_OP_ENV(qadd
);
4637 case NEON_3R_VRHADD
:
4638 GEN_NEON_INTEGER_OP(rhadd
);
4640 case NEON_3R_LOGIC
: /* Logic ops. */
4641 switch ((u
<< 2) | size
) {
4643 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
4646 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
4649 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
4652 tcg_gen_orc_i32(tmp
, tmp
, tmp2
);
4655 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
4658 tmp3
= neon_load_reg(rd
, pass
);
4659 gen_neon_bsl(tmp
, tmp
, tmp2
, tmp3
);
4660 tcg_temp_free_i32(tmp3
);
4663 tmp3
= neon_load_reg(rd
, pass
);
4664 gen_neon_bsl(tmp
, tmp
, tmp3
, tmp2
);
4665 tcg_temp_free_i32(tmp3
);
4668 tmp3
= neon_load_reg(rd
, pass
);
4669 gen_neon_bsl(tmp
, tmp3
, tmp
, tmp2
);
4670 tcg_temp_free_i32(tmp3
);
4675 GEN_NEON_INTEGER_OP(hsub
);
4678 GEN_NEON_INTEGER_OP_ENV(qsub
);
4681 GEN_NEON_INTEGER_OP(cgt
);
4684 GEN_NEON_INTEGER_OP(cge
);
4687 GEN_NEON_INTEGER_OP(shl
);
4690 GEN_NEON_INTEGER_OP_ENV(qshl
);
4693 GEN_NEON_INTEGER_OP(rshl
);
4695 case NEON_3R_VQRSHL
:
4696 GEN_NEON_INTEGER_OP_ENV(qrshl
);
4699 GEN_NEON_INTEGER_OP(max
);
4702 GEN_NEON_INTEGER_OP(min
);
4705 GEN_NEON_INTEGER_OP(abd
);
4708 GEN_NEON_INTEGER_OP(abd
);
4709 tcg_temp_free_i32(tmp2
);
4710 tmp2
= neon_load_reg(rd
, pass
);
4711 gen_neon_add(size
, tmp
, tmp2
);
4713 case NEON_3R_VADD_VSUB
:
4714 if (!u
) { /* VADD */
4715 gen_neon_add(size
, tmp
, tmp2
);
4718 case 0: gen_helper_neon_sub_u8(tmp
, tmp
, tmp2
); break;
4719 case 1: gen_helper_neon_sub_u16(tmp
, tmp
, tmp2
); break;
4720 case 2: tcg_gen_sub_i32(tmp
, tmp
, tmp2
); break;
4725 case NEON_3R_VTST_VCEQ
:
4726 if (!u
) { /* VTST */
4728 case 0: gen_helper_neon_tst_u8(tmp
, tmp
, tmp2
); break;
4729 case 1: gen_helper_neon_tst_u16(tmp
, tmp
, tmp2
); break;
4730 case 2: gen_helper_neon_tst_u32(tmp
, tmp
, tmp2
); break;
4735 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
4736 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
4737 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
4742 case NEON_3R_VML
: /* VMLA, VMLAL, VMLS,VMLSL */
4744 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4745 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4746 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4749 tcg_temp_free_i32(tmp2
);
4750 tmp2
= neon_load_reg(rd
, pass
);
4752 gen_neon_rsb(size
, tmp
, tmp2
);
4754 gen_neon_add(size
, tmp
, tmp2
);
4758 if (u
) { /* polynomial */
4759 gen_helper_neon_mul_p8(tmp
, tmp
, tmp2
);
4760 } else { /* Integer */
4762 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
4763 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
4764 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
4770 GEN_NEON_INTEGER_OP(pmax
);
4773 GEN_NEON_INTEGER_OP(pmin
);
4775 case NEON_3R_VQDMULH_VQRDMULH
: /* Multiply high. */
4776 if (!u
) { /* VQDMULH */
4779 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
4782 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
4786 } else { /* VQRDMULH */
4789 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
4792 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
4800 case 0: gen_helper_neon_padd_u8(tmp
, tmp
, tmp2
); break;
4801 case 1: gen_helper_neon_padd_u16(tmp
, tmp
, tmp2
); break;
4802 case 2: tcg_gen_add_i32(tmp
, tmp
, tmp2
); break;
4806 case NEON_3R_FLOAT_ARITH
: /* Floating point arithmetic. */
4808 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4809 switch ((u
<< 2) | size
) {
4812 gen_helper_vfp_adds(tmp
, tmp
, tmp2
, fpstatus
);
4815 gen_helper_vfp_subs(tmp
, tmp
, tmp2
, fpstatus
);
4818 gen_helper_neon_abd_f32(tmp
, tmp
, tmp2
, fpstatus
);
4823 tcg_temp_free_ptr(fpstatus
);
4826 case NEON_3R_FLOAT_MULTIPLY
:
4828 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4829 gen_helper_vfp_muls(tmp
, tmp
, tmp2
, fpstatus
);
4831 tcg_temp_free_i32(tmp2
);
4832 tmp2
= neon_load_reg(rd
, pass
);
4834 gen_helper_vfp_adds(tmp
, tmp
, tmp2
, fpstatus
);
4836 gen_helper_vfp_subs(tmp
, tmp2
, tmp
, fpstatus
);
4839 tcg_temp_free_ptr(fpstatus
);
4842 case NEON_3R_FLOAT_CMP
:
4844 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4846 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
, fpstatus
);
4849 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
, fpstatus
);
4851 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
, fpstatus
);
4854 tcg_temp_free_ptr(fpstatus
);
4857 case NEON_3R_FLOAT_ACMP
:
4859 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4861 gen_helper_neon_acge_f32(tmp
, tmp
, tmp2
, fpstatus
);
4863 gen_helper_neon_acgt_f32(tmp
, tmp
, tmp2
, fpstatus
);
4865 tcg_temp_free_ptr(fpstatus
);
4868 case NEON_3R_FLOAT_MINMAX
:
4870 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4872 gen_helper_neon_max_f32(tmp
, tmp
, tmp2
, fpstatus
);
4874 gen_helper_neon_min_f32(tmp
, tmp
, tmp2
, fpstatus
);
4876 tcg_temp_free_ptr(fpstatus
);
4879 case NEON_3R_VRECPS_VRSQRTS
:
4881 gen_helper_recps_f32(tmp
, tmp
, tmp2
, cpu_env
);
4883 gen_helper_rsqrts_f32(tmp
, tmp
, tmp2
, cpu_env
);
4887 /* VFMA, VFMS: fused multiply-add */
4888 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
4889 TCGv_i32 tmp3
= neon_load_reg(rd
, pass
);
4892 gen_helper_vfp_negs(tmp
, tmp
);
4894 gen_helper_vfp_muladds(tmp
, tmp
, tmp2
, tmp3
, fpstatus
);
4895 tcg_temp_free_i32(tmp3
);
4896 tcg_temp_free_ptr(fpstatus
);
4902 tcg_temp_free_i32(tmp2
);
4904 /* Save the result. For elementwise operations we can put it
4905 straight into the destination register. For pairwise operations
4906 we have to be careful to avoid clobbering the source operands. */
4907 if (pairwise
&& rd
== rm
) {
4908 neon_store_scratch(pass
, tmp
);
4910 neon_store_reg(rd
, pass
, tmp
);
4914 if (pairwise
&& rd
== rm
) {
4915 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
4916 tmp
= neon_load_scratch(pass
);
4917 neon_store_reg(rd
, pass
, tmp
);
4920 /* End of 3 register same size operations. */
4921 } else if (insn
& (1 << 4)) {
4922 if ((insn
& 0x00380080) != 0) {
4923 /* Two registers and shift. */
4924 op
= (insn
>> 8) & 0xf;
4925 if (insn
& (1 << 7)) {
4933 while ((insn
& (1 << (size
+ 19))) == 0)
4936 shift
= (insn
>> 16) & ((1 << (3 + size
)) - 1);
4937 /* To avoid excessive duplication of ops we implement shift
4938 by immediate using the variable shift operations. */
4940 /* Shift by immediate:
4941 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
4942 if (q
&& ((rd
| rm
) & 1)) {
4945 if (!u
&& (op
== 4 || op
== 6)) {
4948 /* Right shifts are encoded as N - shift, where N is the
4949 element size in bits. */
4951 shift
= shift
- (1 << (size
+ 3));
4959 imm
= (uint8_t) shift
;
4964 imm
= (uint16_t) shift
;
4975 for (pass
= 0; pass
< count
; pass
++) {
4977 neon_load_reg64(cpu_V0
, rm
+ pass
);
4978 tcg_gen_movi_i64(cpu_V1
, imm
);
4983 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4985 gen_helper_neon_shl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4990 gen_helper_neon_rshl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4992 gen_helper_neon_rshl_s64(cpu_V0
, cpu_V0
, cpu_V1
);
4995 case 5: /* VSHL, VSLI */
4996 gen_helper_neon_shl_u64(cpu_V0
, cpu_V0
, cpu_V1
);
4998 case 6: /* VQSHLU */
4999 gen_helper_neon_qshlu_s64(cpu_V0
, cpu_env
,
5004 gen_helper_neon_qshl_u64(cpu_V0
, cpu_env
,
5007 gen_helper_neon_qshl_s64(cpu_V0
, cpu_env
,
5012 if (op
== 1 || op
== 3) {
5014 neon_load_reg64(cpu_V1
, rd
+ pass
);
5015 tcg_gen_add_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5016 } else if (op
== 4 || (op
== 5 && u
)) {
5018 neon_load_reg64(cpu_V1
, rd
+ pass
);
5020 if (shift
< -63 || shift
> 63) {
5024 mask
= 0xffffffffffffffffull
>> -shift
;
5026 mask
= 0xffffffffffffffffull
<< shift
;
5029 tcg_gen_andi_i64(cpu_V1
, cpu_V1
, ~mask
);
5030 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5032 neon_store_reg64(cpu_V0
, rd
+ pass
);
5033 } else { /* size < 3 */
5034 /* Operands in T0 and T1. */
5035 tmp
= neon_load_reg(rm
, pass
);
5036 tmp2
= tcg_temp_new_i32();
5037 tcg_gen_movi_i32(tmp2
, imm
);
5041 GEN_NEON_INTEGER_OP(shl
);
5045 GEN_NEON_INTEGER_OP(rshl
);
5048 case 5: /* VSHL, VSLI */
5050 case 0: gen_helper_neon_shl_u8(tmp
, tmp
, tmp2
); break;
5051 case 1: gen_helper_neon_shl_u16(tmp
, tmp
, tmp2
); break;
5052 case 2: gen_helper_neon_shl_u32(tmp
, tmp
, tmp2
); break;
5056 case 6: /* VQSHLU */
5059 gen_helper_neon_qshlu_s8(tmp
, cpu_env
,
5063 gen_helper_neon_qshlu_s16(tmp
, cpu_env
,
5067 gen_helper_neon_qshlu_s32(tmp
, cpu_env
,
5075 GEN_NEON_INTEGER_OP_ENV(qshl
);
5078 tcg_temp_free_i32(tmp2
);
5080 if (op
== 1 || op
== 3) {
5082 tmp2
= neon_load_reg(rd
, pass
);
5083 gen_neon_add(size
, tmp
, tmp2
);
5084 tcg_temp_free_i32(tmp2
);
5085 } else if (op
== 4 || (op
== 5 && u
)) {
5090 mask
= 0xff >> -shift
;
5092 mask
= (uint8_t)(0xff << shift
);
5098 mask
= 0xffff >> -shift
;
5100 mask
= (uint16_t)(0xffff << shift
);
5104 if (shift
< -31 || shift
> 31) {
5108 mask
= 0xffffffffu
>> -shift
;
5110 mask
= 0xffffffffu
<< shift
;
5116 tmp2
= neon_load_reg(rd
, pass
);
5117 tcg_gen_andi_i32(tmp
, tmp
, mask
);
5118 tcg_gen_andi_i32(tmp2
, tmp2
, ~mask
);
5119 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
5120 tcg_temp_free_i32(tmp2
);
5122 neon_store_reg(rd
, pass
, tmp
);
5125 } else if (op
< 10) {
5126 /* Shift by immediate and narrow:
5127 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5128 int input_unsigned
= (op
== 8) ? !u
: u
;
5132 shift
= shift
- (1 << (size
+ 3));
5135 tmp64
= tcg_const_i64(shift
);
5136 neon_load_reg64(cpu_V0
, rm
);
5137 neon_load_reg64(cpu_V1
, rm
+ 1);
5138 for (pass
= 0; pass
< 2; pass
++) {
5146 if (input_unsigned
) {
5147 gen_helper_neon_rshl_u64(cpu_V0
, in
, tmp64
);
5149 gen_helper_neon_rshl_s64(cpu_V0
, in
, tmp64
);
5152 if (input_unsigned
) {
5153 gen_helper_neon_shl_u64(cpu_V0
, in
, tmp64
);
5155 gen_helper_neon_shl_s64(cpu_V0
, in
, tmp64
);
5158 tmp
= tcg_temp_new_i32();
5159 gen_neon_narrow_op(op
== 8, u
, size
- 1, tmp
, cpu_V0
);
5160 neon_store_reg(rd
, pass
, tmp
);
5162 tcg_temp_free_i64(tmp64
);
5165 imm
= (uint16_t)shift
;
5169 imm
= (uint32_t)shift
;
5171 tmp2
= tcg_const_i32(imm
);
5172 tmp4
= neon_load_reg(rm
+ 1, 0);
5173 tmp5
= neon_load_reg(rm
+ 1, 1);
5174 for (pass
= 0; pass
< 2; pass
++) {
5176 tmp
= neon_load_reg(rm
, 0);
5180 gen_neon_shift_narrow(size
, tmp
, tmp2
, q
,
5183 tmp3
= neon_load_reg(rm
, 1);
5187 gen_neon_shift_narrow(size
, tmp3
, tmp2
, q
,
5189 tcg_gen_concat_i32_i64(cpu_V0
, tmp
, tmp3
);
5190 tcg_temp_free_i32(tmp
);
5191 tcg_temp_free_i32(tmp3
);
5192 tmp
= tcg_temp_new_i32();
5193 gen_neon_narrow_op(op
== 8, u
, size
- 1, tmp
, cpu_V0
);
5194 neon_store_reg(rd
, pass
, tmp
);
5196 tcg_temp_free_i32(tmp2
);
5198 } else if (op
== 10) {
5200 if (q
|| (rd
& 1)) {
5203 tmp
= neon_load_reg(rm
, 0);
5204 tmp2
= neon_load_reg(rm
, 1);
5205 for (pass
= 0; pass
< 2; pass
++) {
5209 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
5212 /* The shift is less than the width of the source
5213 type, so we can just shift the whole register. */
5214 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, shift
);
5215 /* Widen the result of shift: we need to clear
5216 * the potential overflow bits resulting from
5217 * left bits of the narrow input appearing as
5218 * right bits of left the neighbour narrow
5220 if (size
< 2 || !u
) {
5223 imm
= (0xffu
>> (8 - shift
));
5225 } else if (size
== 1) {
5226 imm
= 0xffff >> (16 - shift
);
5229 imm
= 0xffffffff >> (32 - shift
);
5232 imm64
= imm
| (((uint64_t)imm
) << 32);
5236 tcg_gen_andi_i64(cpu_V0
, cpu_V0
, ~imm64
);
5239 neon_store_reg64(cpu_V0
, rd
+ pass
);
5241 } else if (op
>= 14) {
5242 /* VCVT fixed-point. */
5243 if (!(insn
& (1 << 21)) || (q
&& ((rd
| rm
) & 1))) {
5246 /* We have already masked out the must-be-1 top bit of imm6,
5247 * hence this 32-shift where the ARM ARM has 64-imm6.
5250 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5251 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, pass
));
5254 gen_vfp_ulto(0, shift
, 1);
5256 gen_vfp_slto(0, shift
, 1);
5259 gen_vfp_toul(0, shift
, 1);
5261 gen_vfp_tosl(0, shift
, 1);
5263 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, pass
));
5268 } else { /* (insn & 0x00380080) == 0 */
5270 if (q
&& (rd
& 1)) {
5274 op
= (insn
>> 8) & 0xf;
5275 /* One register and immediate. */
5276 imm
= (u
<< 7) | ((insn
>> 12) & 0x70) | (insn
& 0xf);
5277 invert
= (insn
& (1 << 5)) != 0;
5278 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5279 * We choose to not special-case this and will behave as if a
5280 * valid constant encoding of 0 had been given.
5299 imm
= (imm
<< 8) | (imm
<< 24);
5302 imm
= (imm
<< 8) | 0xff;
5305 imm
= (imm
<< 16) | 0xffff;
5308 imm
|= (imm
<< 8) | (imm
<< 16) | (imm
<< 24);
5316 imm
= ((imm
& 0x80) << 24) | ((imm
& 0x3f) << 19)
5317 | ((imm
& 0x40) ? (0x1f << 25) : (1 << 30));
5323 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5324 if (op
& 1 && op
< 12) {
5325 tmp
= neon_load_reg(rd
, pass
);
5327 /* The immediate value has already been inverted, so
5329 tcg_gen_andi_i32(tmp
, tmp
, imm
);
5331 tcg_gen_ori_i32(tmp
, tmp
, imm
);
5335 tmp
= tcg_temp_new_i32();
5336 if (op
== 14 && invert
) {
5340 for (n
= 0; n
< 4; n
++) {
5341 if (imm
& (1 << (n
+ (pass
& 1) * 4)))
5342 val
|= 0xff << (n
* 8);
5344 tcg_gen_movi_i32(tmp
, val
);
5346 tcg_gen_movi_i32(tmp
, imm
);
5349 neon_store_reg(rd
, pass
, tmp
);
5352 } else { /* (insn & 0x00800010 == 0x00800000) */
5354 op
= (insn
>> 8) & 0xf;
5355 if ((insn
& (1 << 6)) == 0) {
5356 /* Three registers of different lengths. */
5360 /* undefreq: bit 0 : UNDEF if size != 0
5361 * bit 1 : UNDEF if size == 0
5362 * bit 2 : UNDEF if U == 1
5363 * Note that [1:0] set implies 'always UNDEF'
5366 /* prewiden, src1_wide, src2_wide, undefreq */
5367 static const int neon_3reg_wide
[16][4] = {
5368 {1, 0, 0, 0}, /* VADDL */
5369 {1, 1, 0, 0}, /* VADDW */
5370 {1, 0, 0, 0}, /* VSUBL */
5371 {1, 1, 0, 0}, /* VSUBW */
5372 {0, 1, 1, 0}, /* VADDHN */
5373 {0, 0, 0, 0}, /* VABAL */
5374 {0, 1, 1, 0}, /* VSUBHN */
5375 {0, 0, 0, 0}, /* VABDL */
5376 {0, 0, 0, 0}, /* VMLAL */
5377 {0, 0, 0, 6}, /* VQDMLAL */
5378 {0, 0, 0, 0}, /* VMLSL */
5379 {0, 0, 0, 6}, /* VQDMLSL */
5380 {0, 0, 0, 0}, /* Integer VMULL */
5381 {0, 0, 0, 2}, /* VQDMULL */
5382 {0, 0, 0, 5}, /* Polynomial VMULL */
5383 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5386 prewiden
= neon_3reg_wide
[op
][0];
5387 src1_wide
= neon_3reg_wide
[op
][1];
5388 src2_wide
= neon_3reg_wide
[op
][2];
5389 undefreq
= neon_3reg_wide
[op
][3];
5391 if (((undefreq
& 1) && (size
!= 0)) ||
5392 ((undefreq
& 2) && (size
== 0)) ||
5393 ((undefreq
& 4) && u
)) {
5396 if ((src1_wide
&& (rn
& 1)) ||
5397 (src2_wide
&& (rm
& 1)) ||
5398 (!src2_wide
&& (rd
& 1))) {
5402 /* Avoid overlapping operands. Wide source operands are
5403 always aligned so will never overlap with wide
5404 destinations in problematic ways. */
5405 if (rd
== rm
&& !src2_wide
) {
5406 tmp
= neon_load_reg(rm
, 1);
5407 neon_store_scratch(2, tmp
);
5408 } else if (rd
== rn
&& !src1_wide
) {
5409 tmp
= neon_load_reg(rn
, 1);
5410 neon_store_scratch(2, tmp
);
5412 TCGV_UNUSED_I32(tmp3
);
5413 for (pass
= 0; pass
< 2; pass
++) {
5415 neon_load_reg64(cpu_V0
, rn
+ pass
);
5416 TCGV_UNUSED_I32(tmp
);
5418 if (pass
== 1 && rd
== rn
) {
5419 tmp
= neon_load_scratch(2);
5421 tmp
= neon_load_reg(rn
, pass
);
5424 gen_neon_widen(cpu_V0
, tmp
, size
, u
);
5428 neon_load_reg64(cpu_V1
, rm
+ pass
);
5429 TCGV_UNUSED_I32(tmp2
);
5431 if (pass
== 1 && rd
== rm
) {
5432 tmp2
= neon_load_scratch(2);
5434 tmp2
= neon_load_reg(rm
, pass
);
5437 gen_neon_widen(cpu_V1
, tmp2
, size
, u
);
5441 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5442 gen_neon_addl(size
);
5444 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5445 gen_neon_subl(size
);
5447 case 5: case 7: /* VABAL, VABDL */
5448 switch ((size
<< 1) | u
) {
5450 gen_helper_neon_abdl_s16(cpu_V0
, tmp
, tmp2
);
5453 gen_helper_neon_abdl_u16(cpu_V0
, tmp
, tmp2
);
5456 gen_helper_neon_abdl_s32(cpu_V0
, tmp
, tmp2
);
5459 gen_helper_neon_abdl_u32(cpu_V0
, tmp
, tmp2
);
5462 gen_helper_neon_abdl_s64(cpu_V0
, tmp
, tmp2
);
5465 gen_helper_neon_abdl_u64(cpu_V0
, tmp
, tmp2
);
5469 tcg_temp_free_i32(tmp2
);
5470 tcg_temp_free_i32(tmp
);
5472 case 8: case 9: case 10: case 11: case 12: case 13:
5473 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5474 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5476 case 14: /* Polynomial VMULL */
5477 gen_helper_neon_mull_p8(cpu_V0
, tmp
, tmp2
);
5478 tcg_temp_free_i32(tmp2
);
5479 tcg_temp_free_i32(tmp
);
5481 default: /* 15 is RESERVED: caught earlier */
5486 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5487 neon_store_reg64(cpu_V0
, rd
+ pass
);
5488 } else if (op
== 5 || (op
>= 8 && op
<= 11)) {
5490 neon_load_reg64(cpu_V1
, rd
+ pass
);
5492 case 10: /* VMLSL */
5493 gen_neon_negl(cpu_V0
, size
);
5495 case 5: case 8: /* VABAL, VMLAL */
5496 gen_neon_addl(size
);
5498 case 9: case 11: /* VQDMLAL, VQDMLSL */
5499 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5501 gen_neon_negl(cpu_V0
, size
);
5503 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5508 neon_store_reg64(cpu_V0
, rd
+ pass
);
5509 } else if (op
== 4 || op
== 6) {
5510 /* Narrowing operation. */
5511 tmp
= tcg_temp_new_i32();
5515 gen_helper_neon_narrow_high_u8(tmp
, cpu_V0
);
5518 gen_helper_neon_narrow_high_u16(tmp
, cpu_V0
);
5521 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5522 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5529 gen_helper_neon_narrow_round_high_u8(tmp
, cpu_V0
);
5532 gen_helper_neon_narrow_round_high_u16(tmp
, cpu_V0
);
5535 tcg_gen_addi_i64(cpu_V0
, cpu_V0
, 1u << 31);
5536 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, 32);
5537 tcg_gen_trunc_i64_i32(tmp
, cpu_V0
);
5545 neon_store_reg(rd
, 0, tmp3
);
5546 neon_store_reg(rd
, 1, tmp
);
5549 /* Write back the result. */
5550 neon_store_reg64(cpu_V0
, rd
+ pass
);
5554 /* Two registers and a scalar. NB that for ops of this form
5555 * the ARM ARM labels bit 24 as Q, but it is in our variable
5562 case 1: /* Float VMLA scalar */
5563 case 5: /* Floating point VMLS scalar */
5564 case 9: /* Floating point VMUL scalar */
5569 case 0: /* Integer VMLA scalar */
5570 case 4: /* Integer VMLS scalar */
5571 case 8: /* Integer VMUL scalar */
5572 case 12: /* VQDMULH scalar */
5573 case 13: /* VQRDMULH scalar */
5574 if (u
&& ((rd
| rn
) & 1)) {
5577 tmp
= neon_get_scalar(size
, rm
);
5578 neon_store_scratch(0, tmp
);
5579 for (pass
= 0; pass
< (u
? 4 : 2); pass
++) {
5580 tmp
= neon_load_scratch(0);
5581 tmp2
= neon_load_reg(rn
, pass
);
5584 gen_helper_neon_qdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5586 gen_helper_neon_qdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5588 } else if (op
== 13) {
5590 gen_helper_neon_qrdmulh_s16(tmp
, cpu_env
, tmp
, tmp2
);
5592 gen_helper_neon_qrdmulh_s32(tmp
, cpu_env
, tmp
, tmp2
);
5594 } else if (op
& 1) {
5595 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
5596 gen_helper_vfp_muls(tmp
, tmp
, tmp2
, fpstatus
);
5597 tcg_temp_free_ptr(fpstatus
);
5600 case 0: gen_helper_neon_mul_u8(tmp
, tmp
, tmp2
); break;
5601 case 1: gen_helper_neon_mul_u16(tmp
, tmp
, tmp2
); break;
5602 case 2: tcg_gen_mul_i32(tmp
, tmp
, tmp2
); break;
5606 tcg_temp_free_i32(tmp2
);
5609 tmp2
= neon_load_reg(rd
, pass
);
5612 gen_neon_add(size
, tmp
, tmp2
);
5616 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
5617 gen_helper_vfp_adds(tmp
, tmp
, tmp2
, fpstatus
);
5618 tcg_temp_free_ptr(fpstatus
);
5622 gen_neon_rsb(size
, tmp
, tmp2
);
5626 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
5627 gen_helper_vfp_subs(tmp
, tmp2
, tmp
, fpstatus
);
5628 tcg_temp_free_ptr(fpstatus
);
5634 tcg_temp_free_i32(tmp2
);
5636 neon_store_reg(rd
, pass
, tmp
);
5639 case 3: /* VQDMLAL scalar */
5640 case 7: /* VQDMLSL scalar */
5641 case 11: /* VQDMULL scalar */
5646 case 2: /* VMLAL sclar */
5647 case 6: /* VMLSL scalar */
5648 case 10: /* VMULL scalar */
5652 tmp2
= neon_get_scalar(size
, rm
);
5653 /* We need a copy of tmp2 because gen_neon_mull
5654 * deletes it during pass 0. */
5655 tmp4
= tcg_temp_new_i32();
5656 tcg_gen_mov_i32(tmp4
, tmp2
);
5657 tmp3
= neon_load_reg(rn
, 1);
5659 for (pass
= 0; pass
< 2; pass
++) {
5661 tmp
= neon_load_reg(rn
, 0);
5666 gen_neon_mull(cpu_V0
, tmp
, tmp2
, size
, u
);
5668 neon_load_reg64(cpu_V1
, rd
+ pass
);
5672 gen_neon_negl(cpu_V0
, size
);
5675 gen_neon_addl(size
);
5678 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5680 gen_neon_negl(cpu_V0
, size
);
5682 gen_neon_addl_saturate(cpu_V0
, cpu_V1
, size
);
5688 gen_neon_addl_saturate(cpu_V0
, cpu_V0
, size
);
5693 neon_store_reg64(cpu_V0
, rd
+ pass
);
5698 default: /* 14 and 15 are RESERVED */
5702 } else { /* size == 3 */
5705 imm
= (insn
>> 8) & 0xf;
5710 if (q
&& ((rd
| rn
| rm
) & 1)) {
5715 neon_load_reg64(cpu_V0
, rn
);
5717 neon_load_reg64(cpu_V1
, rn
+ 1);
5719 } else if (imm
== 8) {
5720 neon_load_reg64(cpu_V0
, rn
+ 1);
5722 neon_load_reg64(cpu_V1
, rm
);
5725 tmp64
= tcg_temp_new_i64();
5727 neon_load_reg64(cpu_V0
, rn
);
5728 neon_load_reg64(tmp64
, rn
+ 1);
5730 neon_load_reg64(cpu_V0
, rn
+ 1);
5731 neon_load_reg64(tmp64
, rm
);
5733 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, (imm
& 7) * 8);
5734 tcg_gen_shli_i64(cpu_V1
, tmp64
, 64 - ((imm
& 7) * 8));
5735 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5737 neon_load_reg64(cpu_V1
, rm
);
5739 neon_load_reg64(cpu_V1
, rm
+ 1);
5742 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5743 tcg_gen_shri_i64(tmp64
, tmp64
, imm
* 8);
5744 tcg_gen_or_i64(cpu_V1
, cpu_V1
, tmp64
);
5745 tcg_temp_free_i64(tmp64
);
5748 neon_load_reg64(cpu_V0
, rn
);
5749 tcg_gen_shri_i64(cpu_V0
, cpu_V0
, imm
* 8);
5750 neon_load_reg64(cpu_V1
, rm
);
5751 tcg_gen_shli_i64(cpu_V1
, cpu_V1
, 64 - (imm
* 8));
5752 tcg_gen_or_i64(cpu_V0
, cpu_V0
, cpu_V1
);
5754 neon_store_reg64(cpu_V0
, rd
);
5756 neon_store_reg64(cpu_V1
, rd
+ 1);
5758 } else if ((insn
& (1 << 11)) == 0) {
5759 /* Two register misc. */
5760 op
= ((insn
>> 12) & 0x30) | ((insn
>> 7) & 0xf);
5761 size
= (insn
>> 18) & 3;
5762 /* UNDEF for unknown op values and bad op-size combinations */
5763 if ((neon_2rm_sizes
[op
] & (1 << size
)) == 0) {
5766 if ((op
!= NEON_2RM_VMOVN
&& op
!= NEON_2RM_VQMOVN
) &&
5767 q
&& ((rm
| rd
) & 1)) {
5771 case NEON_2RM_VREV64
:
5772 for (pass
= 0; pass
< (q
? 2 : 1); pass
++) {
5773 tmp
= neon_load_reg(rm
, pass
* 2);
5774 tmp2
= neon_load_reg(rm
, pass
* 2 + 1);
5776 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5777 case 1: gen_swap_half(tmp
); break;
5778 case 2: /* no-op */ break;
5781 neon_store_reg(rd
, pass
* 2 + 1, tmp
);
5783 neon_store_reg(rd
, pass
* 2, tmp2
);
5786 case 0: tcg_gen_bswap32_i32(tmp2
, tmp2
); break;
5787 case 1: gen_swap_half(tmp2
); break;
5790 neon_store_reg(rd
, pass
* 2, tmp2
);
5794 case NEON_2RM_VPADDL
: case NEON_2RM_VPADDL_U
:
5795 case NEON_2RM_VPADAL
: case NEON_2RM_VPADAL_U
:
5796 for (pass
= 0; pass
< q
+ 1; pass
++) {
5797 tmp
= neon_load_reg(rm
, pass
* 2);
5798 gen_neon_widen(cpu_V0
, tmp
, size
, op
& 1);
5799 tmp
= neon_load_reg(rm
, pass
* 2 + 1);
5800 gen_neon_widen(cpu_V1
, tmp
, size
, op
& 1);
5802 case 0: gen_helper_neon_paddl_u16(CPU_V001
); break;
5803 case 1: gen_helper_neon_paddl_u32(CPU_V001
); break;
5804 case 2: tcg_gen_add_i64(CPU_V001
); break;
5807 if (op
>= NEON_2RM_VPADAL
) {
5809 neon_load_reg64(cpu_V1
, rd
+ pass
);
5810 gen_neon_addl(size
);
5812 neon_store_reg64(cpu_V0
, rd
+ pass
);
5818 for (n
= 0; n
< (q
? 4 : 2); n
+= 2) {
5819 tmp
= neon_load_reg(rm
, n
);
5820 tmp2
= neon_load_reg(rd
, n
+ 1);
5821 neon_store_reg(rm
, n
, tmp2
);
5822 neon_store_reg(rd
, n
+ 1, tmp
);
5829 if (gen_neon_unzip(rd
, rm
, size
, q
)) {
5834 if (gen_neon_zip(rd
, rm
, size
, q
)) {
5838 case NEON_2RM_VMOVN
: case NEON_2RM_VQMOVN
:
5839 /* also VQMOVUN; op field and mnemonics don't line up */
5843 TCGV_UNUSED_I32(tmp2
);
5844 for (pass
= 0; pass
< 2; pass
++) {
5845 neon_load_reg64(cpu_V0
, rm
+ pass
);
5846 tmp
= tcg_temp_new_i32();
5847 gen_neon_narrow_op(op
== NEON_2RM_VMOVN
, q
, size
,
5852 neon_store_reg(rd
, 0, tmp2
);
5853 neon_store_reg(rd
, 1, tmp
);
5857 case NEON_2RM_VSHLL
:
5858 if (q
|| (rd
& 1)) {
5861 tmp
= neon_load_reg(rm
, 0);
5862 tmp2
= neon_load_reg(rm
, 1);
5863 for (pass
= 0; pass
< 2; pass
++) {
5866 gen_neon_widen(cpu_V0
, tmp
, size
, 1);
5867 tcg_gen_shli_i64(cpu_V0
, cpu_V0
, 8 << size
);
5868 neon_store_reg64(cpu_V0
, rd
+ pass
);
5871 case NEON_2RM_VCVT_F16_F32
:
5872 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
) ||
5876 tmp
= tcg_temp_new_i32();
5877 tmp2
= tcg_temp_new_i32();
5878 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 0));
5879 gen_helper_neon_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5880 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 1));
5881 gen_helper_neon_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5882 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5883 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5884 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 2));
5885 gen_helper_neon_fcvt_f32_to_f16(tmp
, cpu_F0s
, cpu_env
);
5886 tcg_gen_ld_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rm
, 3));
5887 neon_store_reg(rd
, 0, tmp2
);
5888 tmp2
= tcg_temp_new_i32();
5889 gen_helper_neon_fcvt_f32_to_f16(tmp2
, cpu_F0s
, cpu_env
);
5890 tcg_gen_shli_i32(tmp2
, tmp2
, 16);
5891 tcg_gen_or_i32(tmp2
, tmp2
, tmp
);
5892 neon_store_reg(rd
, 1, tmp2
);
5893 tcg_temp_free_i32(tmp
);
5895 case NEON_2RM_VCVT_F32_F16
:
5896 if (!arm_feature(env
, ARM_FEATURE_VFP_FP16
) ||
5900 tmp3
= tcg_temp_new_i32();
5901 tmp
= neon_load_reg(rm
, 0);
5902 tmp2
= neon_load_reg(rm
, 1);
5903 tcg_gen_ext16u_i32(tmp3
, tmp
);
5904 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5905 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 0));
5906 tcg_gen_shri_i32(tmp3
, tmp
, 16);
5907 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5908 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 1));
5909 tcg_temp_free_i32(tmp
);
5910 tcg_gen_ext16u_i32(tmp3
, tmp2
);
5911 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5912 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 2));
5913 tcg_gen_shri_i32(tmp3
, tmp2
, 16);
5914 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s
, tmp3
, cpu_env
);
5915 tcg_gen_st_f32(cpu_F0s
, cpu_env
, neon_reg_offset(rd
, 3));
5916 tcg_temp_free_i32(tmp2
);
5917 tcg_temp_free_i32(tmp3
);
5921 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
5922 if (neon_2rm_is_float_op(op
)) {
5923 tcg_gen_ld_f32(cpu_F0s
, cpu_env
,
5924 neon_reg_offset(rm
, pass
));
5925 TCGV_UNUSED_I32(tmp
);
5927 tmp
= neon_load_reg(rm
, pass
);
5930 case NEON_2RM_VREV32
:
5932 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
5933 case 1: gen_swap_half(tmp
); break;
5937 case NEON_2RM_VREV16
:
5942 case 0: gen_helper_neon_cls_s8(tmp
, tmp
); break;
5943 case 1: gen_helper_neon_cls_s16(tmp
, tmp
); break;
5944 case 2: gen_helper_neon_cls_s32(tmp
, tmp
); break;
5950 case 0: gen_helper_neon_clz_u8(tmp
, tmp
); break;
5951 case 1: gen_helper_neon_clz_u16(tmp
, tmp
); break;
5952 case 2: gen_helper_clz(tmp
, tmp
); break;
5957 gen_helper_neon_cnt_u8(tmp
, tmp
);
5960 tcg_gen_not_i32(tmp
, tmp
);
5962 case NEON_2RM_VQABS
:
5965 gen_helper_neon_qabs_s8(tmp
, cpu_env
, tmp
);
5968 gen_helper_neon_qabs_s16(tmp
, cpu_env
, tmp
);
5971 gen_helper_neon_qabs_s32(tmp
, cpu_env
, tmp
);
5976 case NEON_2RM_VQNEG
:
5979 gen_helper_neon_qneg_s8(tmp
, cpu_env
, tmp
);
5982 gen_helper_neon_qneg_s16(tmp
, cpu_env
, tmp
);
5985 gen_helper_neon_qneg_s32(tmp
, cpu_env
, tmp
);
5990 case NEON_2RM_VCGT0
: case NEON_2RM_VCLE0
:
5991 tmp2
= tcg_const_i32(0);
5993 case 0: gen_helper_neon_cgt_s8(tmp
, tmp
, tmp2
); break;
5994 case 1: gen_helper_neon_cgt_s16(tmp
, tmp
, tmp2
); break;
5995 case 2: gen_helper_neon_cgt_s32(tmp
, tmp
, tmp2
); break;
5998 tcg_temp_free_i32(tmp2
);
5999 if (op
== NEON_2RM_VCLE0
) {
6000 tcg_gen_not_i32(tmp
, tmp
);
6003 case NEON_2RM_VCGE0
: case NEON_2RM_VCLT0
:
6004 tmp2
= tcg_const_i32(0);
6006 case 0: gen_helper_neon_cge_s8(tmp
, tmp
, tmp2
); break;
6007 case 1: gen_helper_neon_cge_s16(tmp
, tmp
, tmp2
); break;
6008 case 2: gen_helper_neon_cge_s32(tmp
, tmp
, tmp2
); break;
6011 tcg_temp_free_i32(tmp2
);
6012 if (op
== NEON_2RM_VCLT0
) {
6013 tcg_gen_not_i32(tmp
, tmp
);
6016 case NEON_2RM_VCEQ0
:
6017 tmp2
= tcg_const_i32(0);
6019 case 0: gen_helper_neon_ceq_u8(tmp
, tmp
, tmp2
); break;
6020 case 1: gen_helper_neon_ceq_u16(tmp
, tmp
, tmp2
); break;
6021 case 2: gen_helper_neon_ceq_u32(tmp
, tmp
, tmp2
); break;
6024 tcg_temp_free_i32(tmp2
);
6028 case 0: gen_helper_neon_abs_s8(tmp
, tmp
); break;
6029 case 1: gen_helper_neon_abs_s16(tmp
, tmp
); break;
6030 case 2: tcg_gen_abs_i32(tmp
, tmp
); break;
6035 tmp2
= tcg_const_i32(0);
6036 gen_neon_rsb(size
, tmp
, tmp2
);
6037 tcg_temp_free_i32(tmp2
);
6039 case NEON_2RM_VCGT0_F
:
6041 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6042 tmp2
= tcg_const_i32(0);
6043 gen_helper_neon_cgt_f32(tmp
, tmp
, tmp2
, fpstatus
);
6044 tcg_temp_free_i32(tmp2
);
6045 tcg_temp_free_ptr(fpstatus
);
6048 case NEON_2RM_VCGE0_F
:
6050 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6051 tmp2
= tcg_const_i32(0);
6052 gen_helper_neon_cge_f32(tmp
, tmp
, tmp2
, fpstatus
);
6053 tcg_temp_free_i32(tmp2
);
6054 tcg_temp_free_ptr(fpstatus
);
6057 case NEON_2RM_VCEQ0_F
:
6059 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6060 tmp2
= tcg_const_i32(0);
6061 gen_helper_neon_ceq_f32(tmp
, tmp
, tmp2
, fpstatus
);
6062 tcg_temp_free_i32(tmp2
);
6063 tcg_temp_free_ptr(fpstatus
);
6066 case NEON_2RM_VCLE0_F
:
6068 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6069 tmp2
= tcg_const_i32(0);
6070 gen_helper_neon_cge_f32(tmp
, tmp2
, tmp
, fpstatus
);
6071 tcg_temp_free_i32(tmp2
);
6072 tcg_temp_free_ptr(fpstatus
);
6075 case NEON_2RM_VCLT0_F
:
6077 TCGv_ptr fpstatus
= get_fpstatus_ptr(1);
6078 tmp2
= tcg_const_i32(0);
6079 gen_helper_neon_cgt_f32(tmp
, tmp2
, tmp
, fpstatus
);
6080 tcg_temp_free_i32(tmp2
);
6081 tcg_temp_free_ptr(fpstatus
);
6084 case NEON_2RM_VABS_F
:
6087 case NEON_2RM_VNEG_F
:
6091 tmp2
= neon_load_reg(rd
, pass
);
6092 neon_store_reg(rm
, pass
, tmp2
);
6095 tmp2
= neon_load_reg(rd
, pass
);
6097 case 0: gen_neon_trn_u8(tmp
, tmp2
); break;
6098 case 1: gen_neon_trn_u16(tmp
, tmp2
); break;
6101 neon_store_reg(rm
, pass
, tmp2
);
6103 case NEON_2RM_VRECPE
:
6104 gen_helper_recpe_u32(tmp
, tmp
, cpu_env
);
6106 case NEON_2RM_VRSQRTE
:
6107 gen_helper_rsqrte_u32(tmp
, tmp
, cpu_env
);
6109 case NEON_2RM_VRECPE_F
:
6110 gen_helper_recpe_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
6112 case NEON_2RM_VRSQRTE_F
:
6113 gen_helper_rsqrte_f32(cpu_F0s
, cpu_F0s
, cpu_env
);
6115 case NEON_2RM_VCVT_FS
: /* VCVT.F32.S32 */
6118 case NEON_2RM_VCVT_FU
: /* VCVT.F32.U32 */
6121 case NEON_2RM_VCVT_SF
: /* VCVT.S32.F32 */
6122 gen_vfp_tosiz(0, 1);
6124 case NEON_2RM_VCVT_UF
: /* VCVT.U32.F32 */
6125 gen_vfp_touiz(0, 1);
6128 /* Reserved op values were caught by the
6129 * neon_2rm_sizes[] check earlier.
6133 if (neon_2rm_is_float_op(op
)) {
6134 tcg_gen_st_f32(cpu_F0s
, cpu_env
,
6135 neon_reg_offset(rd
, pass
));
6137 neon_store_reg(rd
, pass
, tmp
);
6142 } else if ((insn
& (1 << 10)) == 0) {
6144 int n
= ((insn
>> 8) & 3) + 1;
6145 if ((rn
+ n
) > 32) {
6146 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6147 * helper function running off the end of the register file.
6152 if (insn
& (1 << 6)) {
6153 tmp
= neon_load_reg(rd
, 0);
6155 tmp
= tcg_temp_new_i32();
6156 tcg_gen_movi_i32(tmp
, 0);
6158 tmp2
= neon_load_reg(rm
, 0);
6159 tmp4
= tcg_const_i32(rn
);
6160 tmp5
= tcg_const_i32(n
);
6161 gen_helper_neon_tbl(tmp2
, cpu_env
, tmp2
, tmp
, tmp4
, tmp5
);
6162 tcg_temp_free_i32(tmp
);
6163 if (insn
& (1 << 6)) {
6164 tmp
= neon_load_reg(rd
, 1);
6166 tmp
= tcg_temp_new_i32();
6167 tcg_gen_movi_i32(tmp
, 0);
6169 tmp3
= neon_load_reg(rm
, 1);
6170 gen_helper_neon_tbl(tmp3
, cpu_env
, tmp3
, tmp
, tmp4
, tmp5
);
6171 tcg_temp_free_i32(tmp5
);
6172 tcg_temp_free_i32(tmp4
);
6173 neon_store_reg(rd
, 0, tmp2
);
6174 neon_store_reg(rd
, 1, tmp3
);
6175 tcg_temp_free_i32(tmp
);
6176 } else if ((insn
& 0x380) == 0) {
6178 if ((insn
& (7 << 16)) == 0 || (q
&& (rd
& 1))) {
6181 if (insn
& (1 << 19)) {
6182 tmp
= neon_load_reg(rm
, 1);
6184 tmp
= neon_load_reg(rm
, 0);
6186 if (insn
& (1 << 16)) {
6187 gen_neon_dup_u8(tmp
, ((insn
>> 17) & 3) * 8);
6188 } else if (insn
& (1 << 17)) {
6189 if ((insn
>> 18) & 1)
6190 gen_neon_dup_high16(tmp
);
6192 gen_neon_dup_low16(tmp
);
6194 for (pass
= 0; pass
< (q
? 4 : 2); pass
++) {
6195 tmp2
= tcg_temp_new_i32();
6196 tcg_gen_mov_i32(tmp2
, tmp
);
6197 neon_store_reg(rd
, pass
, tmp2
);
6199 tcg_temp_free_i32(tmp
);
6208 static int disas_coproc_insn(CPUARMState
* env
, DisasContext
*s
, uint32_t insn
)
6210 int cpnum
, is64
, crn
, crm
, opc1
, opc2
, isread
, rt
, rt2
;
6211 const ARMCPRegInfo
*ri
;
6212 ARMCPU
*cpu
= arm_env_get_cpu(env
);
6214 cpnum
= (insn
>> 8) & 0xf;
6215 if (arm_feature(env
, ARM_FEATURE_XSCALE
)
6216 && ((env
->cp15
.c15_cpar
^ 0x3fff) & (1 << cpnum
)))
6219 /* First check for coprocessor space used for actual instructions */
6223 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
6224 return disas_iwmmxt_insn(env
, s
, insn
);
6225 } else if (arm_feature(env
, ARM_FEATURE_XSCALE
)) {
6226 return disas_dsp_insn(env
, s
, insn
);
6231 return disas_vfp_insn (env
, s
, insn
);
6236 /* Otherwise treat as a generic register access */
6237 is64
= (insn
& (1 << 25)) == 0;
6238 if (!is64
&& ((insn
& (1 << 4)) == 0)) {
6246 opc1
= (insn
>> 4) & 0xf;
6248 rt2
= (insn
>> 16) & 0xf;
6250 crn
= (insn
>> 16) & 0xf;
6251 opc1
= (insn
>> 21) & 7;
6252 opc2
= (insn
>> 5) & 7;
6255 isread
= (insn
>> 20) & 1;
6256 rt
= (insn
>> 12) & 0xf;
6258 ri
= get_arm_cp_reginfo(cpu
,
6259 ENCODE_CP_REG(cpnum
, is64
, crn
, crm
, opc1
, opc2
));
6261 /* Check access permissions */
6262 if (!cp_access_ok(env
, ri
, isread
)) {
6266 /* Handle special cases first */
6267 switch (ri
->type
& ~(ARM_CP_FLAG_MASK
& ~ARM_CP_SPECIAL
)) {
6274 gen_set_pc_im(s
->pc
);
6275 s
->is_jmp
= DISAS_WFI
;
6286 if (ri
->type
& ARM_CP_CONST
) {
6287 tmp64
= tcg_const_i64(ri
->resetvalue
);
6288 } else if (ri
->readfn
) {
6290 gen_set_pc_im(s
->pc
);
6291 tmp64
= tcg_temp_new_i64();
6292 tmpptr
= tcg_const_ptr(ri
);
6293 gen_helper_get_cp_reg64(tmp64
, cpu_env
, tmpptr
);
6294 tcg_temp_free_ptr(tmpptr
);
6296 tmp64
= tcg_temp_new_i64();
6297 tcg_gen_ld_i64(tmp64
, cpu_env
, ri
->fieldoffset
);
6299 tmp
= tcg_temp_new_i32();
6300 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6301 store_reg(s
, rt
, tmp
);
6302 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
6303 tmp
= tcg_temp_new_i32();
6304 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6305 tcg_temp_free_i64(tmp64
);
6306 store_reg(s
, rt2
, tmp
);
6309 if (ri
->type
& ARM_CP_CONST
) {
6310 tmp
= tcg_const_i32(ri
->resetvalue
);
6311 } else if (ri
->readfn
) {
6313 gen_set_pc_im(s
->pc
);
6314 tmp
= tcg_temp_new_i32();
6315 tmpptr
= tcg_const_ptr(ri
);
6316 gen_helper_get_cp_reg(tmp
, cpu_env
, tmpptr
);
6317 tcg_temp_free_ptr(tmpptr
);
6319 tmp
= load_cpu_offset(ri
->fieldoffset
);
6322 /* Destination register of r15 for 32 bit loads sets
6323 * the condition codes from the high 4 bits of the value
6326 tcg_temp_free_i32(tmp
);
6328 store_reg(s
, rt
, tmp
);
6333 if (ri
->type
& ARM_CP_CONST
) {
6334 /* If not forbidden by access permissions, treat as WI */
6339 TCGv_i32 tmplo
, tmphi
;
6340 TCGv_i64 tmp64
= tcg_temp_new_i64();
6341 tmplo
= load_reg(s
, rt
);
6342 tmphi
= load_reg(s
, rt2
);
6343 tcg_gen_concat_i32_i64(tmp64
, tmplo
, tmphi
);
6344 tcg_temp_free_i32(tmplo
);
6345 tcg_temp_free_i32(tmphi
);
6347 TCGv_ptr tmpptr
= tcg_const_ptr(ri
);
6348 gen_set_pc_im(s
->pc
);
6349 gen_helper_set_cp_reg64(cpu_env
, tmpptr
, tmp64
);
6350 tcg_temp_free_ptr(tmpptr
);
6352 tcg_gen_st_i64(tmp64
, cpu_env
, ri
->fieldoffset
);
6354 tcg_temp_free_i64(tmp64
);
6359 gen_set_pc_im(s
->pc
);
6360 tmp
= load_reg(s
, rt
);
6361 tmpptr
= tcg_const_ptr(ri
);
6362 gen_helper_set_cp_reg(cpu_env
, tmpptr
, tmp
);
6363 tcg_temp_free_ptr(tmpptr
);
6364 tcg_temp_free_i32(tmp
);
6366 TCGv_i32 tmp
= load_reg(s
, rt
);
6367 store_cpu_offset(tmp
, ri
->fieldoffset
);
6370 /* We default to ending the TB on a coprocessor register write,
6371 * but allow this to be suppressed by the register definition
6372 * (usually only necessary to work around guest bugs).
6374 if (!(ri
->type
& ARM_CP_SUPPRESS_TB_END
)) {
6385 /* Store a 64-bit value to a register pair. Clobbers val. */
6386 static void gen_storeq_reg(DisasContext
*s
, int rlow
, int rhigh
, TCGv_i64 val
)
6389 tmp
= tcg_temp_new_i32();
6390 tcg_gen_trunc_i64_i32(tmp
, val
);
6391 store_reg(s
, rlow
, tmp
);
6392 tmp
= tcg_temp_new_i32();
6393 tcg_gen_shri_i64(val
, val
, 32);
6394 tcg_gen_trunc_i64_i32(tmp
, val
);
6395 store_reg(s
, rhigh
, tmp
);
6398 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6399 static void gen_addq_lo(DisasContext
*s
, TCGv_i64 val
, int rlow
)
6404 /* Load value and extend to 64 bits. */
6405 tmp
= tcg_temp_new_i64();
6406 tmp2
= load_reg(s
, rlow
);
6407 tcg_gen_extu_i32_i64(tmp
, tmp2
);
6408 tcg_temp_free_i32(tmp2
);
6409 tcg_gen_add_i64(val
, val
, tmp
);
6410 tcg_temp_free_i64(tmp
);
6413 /* load and add a 64-bit value from a register pair. */
6414 static void gen_addq(DisasContext
*s
, TCGv_i64 val
, int rlow
, int rhigh
)
6420 /* Load 64-bit value rd:rn. */
6421 tmpl
= load_reg(s
, rlow
);
6422 tmph
= load_reg(s
, rhigh
);
6423 tmp
= tcg_temp_new_i64();
6424 tcg_gen_concat_i32_i64(tmp
, tmpl
, tmph
);
6425 tcg_temp_free_i32(tmpl
);
6426 tcg_temp_free_i32(tmph
);
6427 tcg_gen_add_i64(val
, val
, tmp
);
6428 tcg_temp_free_i64(tmp
);
6431 /* Set N and Z flags from hi|lo. */
6432 static void gen_logicq_cc(TCGv_i32 lo
, TCGv_i32 hi
)
6434 tcg_gen_mov_i32(cpu_NF
, hi
);
6435 tcg_gen_or_i32(cpu_ZF
, lo
, hi
);
6438 /* Load/Store exclusive instructions are implemented by remembering
6439 the value/address loaded, and seeing if these are the same
6440 when the store is performed. This should be sufficient to implement
6441 the architecturally mandated semantics, and avoids having to monitor
6444 In system emulation mode only one CPU will be running at once, so
6445 this sequence is effectively atomic. In user emulation mode we
6446 throw an exception and handle the atomic operation elsewhere. */
6447 static void gen_load_exclusive(DisasContext
*s
, int rt
, int rt2
,
6448 TCGv_i32 addr
, int size
)
6450 TCGv_i32 tmp
= tcg_temp_new_i32();
6454 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
6457 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
6461 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
6466 tcg_gen_mov_i32(cpu_exclusive_val
, tmp
);
6467 store_reg(s
, rt
, tmp
);
6469 TCGv_i32 tmp2
= tcg_temp_new_i32();
6470 tcg_gen_addi_i32(tmp2
, addr
, 4);
6471 tmp
= tcg_temp_new_i32();
6472 tcg_gen_qemu_ld32u(tmp
, tmp2
, IS_USER(s
));
6473 tcg_temp_free_i32(tmp2
);
6474 tcg_gen_mov_i32(cpu_exclusive_high
, tmp
);
6475 store_reg(s
, rt2
, tmp
);
6477 tcg_gen_mov_i32(cpu_exclusive_addr
, addr
);
6480 static void gen_clrex(DisasContext
*s
)
6482 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
6485 #ifdef CONFIG_USER_ONLY
6486 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
6487 TCGv_i32 addr
, int size
)
6489 tcg_gen_mov_i32(cpu_exclusive_test
, addr
);
6490 tcg_gen_movi_i32(cpu_exclusive_info
,
6491 size
| (rd
<< 4) | (rt
<< 8) | (rt2
<< 12));
6492 gen_exception_insn(s
, 4, EXCP_STREX
);
6495 static void gen_store_exclusive(DisasContext
*s
, int rd
, int rt
, int rt2
,
6496 TCGv_i32 addr
, int size
)
6502 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6508 fail_label
= gen_new_label();
6509 done_label
= gen_new_label();
6510 tcg_gen_brcond_i32(TCG_COND_NE
, addr
, cpu_exclusive_addr
, fail_label
);
6511 tmp
= tcg_temp_new_i32();
6514 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
6517 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
6521 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
6526 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_val
, fail_label
);
6527 tcg_temp_free_i32(tmp
);
6529 TCGv_i32 tmp2
= tcg_temp_new_i32();
6530 tcg_gen_addi_i32(tmp2
, addr
, 4);
6531 tmp
= tcg_temp_new_i32();
6532 tcg_gen_qemu_ld32u(tmp
, tmp2
, IS_USER(s
));
6533 tcg_temp_free_i32(tmp2
);
6534 tcg_gen_brcond_i32(TCG_COND_NE
, tmp
, cpu_exclusive_high
, fail_label
);
6535 tcg_temp_free_i32(tmp
);
6537 tmp
= load_reg(s
, rt
);
6540 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
6543 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
6547 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
6552 tcg_temp_free_i32(tmp
);
6554 tcg_gen_addi_i32(addr
, addr
, 4);
6555 tmp
= load_reg(s
, rt2
);
6556 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
6557 tcg_temp_free_i32(tmp
);
6559 tcg_gen_movi_i32(cpu_R
[rd
], 0);
6560 tcg_gen_br(done_label
);
6561 gen_set_label(fail_label
);
6562 tcg_gen_movi_i32(cpu_R
[rd
], 1);
6563 gen_set_label(done_label
);
6564 tcg_gen_movi_i32(cpu_exclusive_addr
, -1);
6571 * @mode: mode field from insn (which stack to store to)
6572 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
6573 * @writeback: true if writeback bit set
6575 * Generate code for the SRS (Store Return State) insn.
6577 static void gen_srs(DisasContext
*s
,
6578 uint32_t mode
, uint32_t amode
, bool writeback
)
6581 TCGv_i32 addr
= tcg_temp_new_i32();
6582 TCGv_i32 tmp
= tcg_const_i32(mode
);
6583 gen_helper_get_r13_banked(addr
, cpu_env
, tmp
);
6584 tcg_temp_free_i32(tmp
);
6601 tcg_gen_addi_i32(addr
, addr
, offset
);
6602 tmp
= load_reg(s
, 14);
6603 tcg_gen_qemu_st32(tmp
, addr
, 0);
6604 tcg_temp_free_i32(tmp
);
6605 tmp
= load_cpu_field(spsr
);
6606 tcg_gen_addi_i32(addr
, addr
, 4);
6607 tcg_gen_qemu_st32(tmp
, addr
, 0);
6608 tcg_temp_free_i32(tmp
);
6626 tcg_gen_addi_i32(addr
, addr
, offset
);
6627 tmp
= tcg_const_i32(mode
);
6628 gen_helper_set_r13_banked(cpu_env
, tmp
, addr
);
6629 tcg_temp_free_i32(tmp
);
6631 tcg_temp_free_i32(addr
);
6634 static void disas_arm_insn(CPUARMState
* env
, DisasContext
*s
)
6636 unsigned int cond
, insn
, val
, op1
, i
, shift
, rm
, rs
, rn
, rd
, sh
;
6643 insn
= arm_ldl_code(env
, s
->pc
, s
->bswap_code
);
6646 /* M variants do not implement ARM mode. */
6651 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6652 * choose to UNDEF. In ARMv5 and above the space is used
6653 * for miscellaneous unconditional instructions.
6657 /* Unconditional instructions. */
6658 if (((insn
>> 25) & 7) == 1) {
6659 /* NEON Data processing. */
6660 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6663 if (disas_neon_data_insn(env
, s
, insn
))
6667 if ((insn
& 0x0f100000) == 0x04000000) {
6668 /* NEON load/store. */
6669 if (!arm_feature(env
, ARM_FEATURE_NEON
))
6672 if (disas_neon_ls_insn(env
, s
, insn
))
6676 if (((insn
& 0x0f30f000) == 0x0510f000) ||
6677 ((insn
& 0x0f30f010) == 0x0710f000)) {
6678 if ((insn
& (1 << 22)) == 0) {
6680 if (!arm_feature(env
, ARM_FEATURE_V7MP
)) {
6684 /* Otherwise PLD; v5TE+ */
6688 if (((insn
& 0x0f70f000) == 0x0450f000) ||
6689 ((insn
& 0x0f70f010) == 0x0650f000)) {
6691 return; /* PLI; V7 */
6693 if (((insn
& 0x0f700000) == 0x04100000) ||
6694 ((insn
& 0x0f700010) == 0x06100000)) {
6695 if (!arm_feature(env
, ARM_FEATURE_V7MP
)) {
6698 return; /* v7MP: Unallocated memory hint: must NOP */
6701 if ((insn
& 0x0ffffdff) == 0x01010000) {
6704 if (((insn
>> 9) & 1) != s
->bswap_code
) {
6705 /* Dynamic endianness switching not implemented. */
6709 } else if ((insn
& 0x0fffff00) == 0x057ff000) {
6710 switch ((insn
>> 4) & 0xf) {
6719 /* We don't emulate caches so these are a no-op. */
6724 } else if ((insn
& 0x0e5fffe0) == 0x084d0500) {
6730 gen_srs(s
, (insn
& 0x1f), (insn
>> 23) & 3, insn
& (1 << 21));
6732 } else if ((insn
& 0x0e50ffe0) == 0x08100a00) {
6738 rn
= (insn
>> 16) & 0xf;
6739 addr
= load_reg(s
, rn
);
6740 i
= (insn
>> 23) & 3;
6742 case 0: offset
= -4; break; /* DA */
6743 case 1: offset
= 0; break; /* IA */
6744 case 2: offset
= -8; break; /* DB */
6745 case 3: offset
= 4; break; /* IB */
6749 tcg_gen_addi_i32(addr
, addr
, offset
);
6750 /* Load PC into tmp and CPSR into tmp2. */
6751 tmp
= tcg_temp_new_i32();
6752 tcg_gen_qemu_ld32u(tmp
, addr
, 0);
6753 tcg_gen_addi_i32(addr
, addr
, 4);
6754 tmp2
= tcg_temp_new_i32();
6755 tcg_gen_qemu_ld32u(tmp
, addr
, 0);
6756 if (insn
& (1 << 21)) {
6757 /* Base writeback. */
6759 case 0: offset
= -8; break;
6760 case 1: offset
= 4; break;
6761 case 2: offset
= -4; break;
6762 case 3: offset
= 0; break;
6766 tcg_gen_addi_i32(addr
, addr
, offset
);
6767 store_reg(s
, rn
, addr
);
6769 tcg_temp_free_i32(addr
);
6771 gen_rfe(s
, tmp
, tmp2
);
6773 } else if ((insn
& 0x0e000000) == 0x0a000000) {
6774 /* branch link and change to thumb (blx <offset>) */
6777 val
= (uint32_t)s
->pc
;
6778 tmp
= tcg_temp_new_i32();
6779 tcg_gen_movi_i32(tmp
, val
);
6780 store_reg(s
, 14, tmp
);
6781 /* Sign-extend the 24-bit offset */
6782 offset
= (((int32_t)insn
) << 8) >> 8;
6783 /* offset * 4 + bit24 * 2 + (thumb bit) */
6784 val
+= (offset
<< 2) | ((insn
>> 23) & 2) | 1;
6785 /* pipeline offset */
6787 /* protected by ARCH(5); above, near the start of uncond block */
6790 } else if ((insn
& 0x0e000f00) == 0x0c000100) {
6791 if (arm_feature(env
, ARM_FEATURE_IWMMXT
)) {
6792 /* iWMMXt register transfer. */
6793 if (env
->cp15
.c15_cpar
& (1 << 1))
6794 if (!disas_iwmmxt_insn(env
, s
, insn
))
6797 } else if ((insn
& 0x0fe00000) == 0x0c400000) {
6798 /* Coprocessor double register transfer. */
6800 } else if ((insn
& 0x0f000010) == 0x0e000010) {
6801 /* Additional coprocessor register transfer. */
6802 } else if ((insn
& 0x0ff10020) == 0x01000000) {
6805 /* cps (privileged) */
6809 if (insn
& (1 << 19)) {
6810 if (insn
& (1 << 8))
6812 if (insn
& (1 << 7))
6814 if (insn
& (1 << 6))
6816 if (insn
& (1 << 18))
6819 if (insn
& (1 << 17)) {
6821 val
|= (insn
& 0x1f);
6824 gen_set_psr_im(s
, mask
, 0, val
);
6831 /* if not always execute, we generate a conditional jump to
6833 s
->condlabel
= gen_new_label();
6834 gen_test_cc(cond
^ 1, s
->condlabel
);
6837 if ((insn
& 0x0f900000) == 0x03000000) {
6838 if ((insn
& (1 << 21)) == 0) {
6840 rd
= (insn
>> 12) & 0xf;
6841 val
= ((insn
>> 4) & 0xf000) | (insn
& 0xfff);
6842 if ((insn
& (1 << 22)) == 0) {
6844 tmp
= tcg_temp_new_i32();
6845 tcg_gen_movi_i32(tmp
, val
);
6848 tmp
= load_reg(s
, rd
);
6849 tcg_gen_ext16u_i32(tmp
, tmp
);
6850 tcg_gen_ori_i32(tmp
, tmp
, val
<< 16);
6852 store_reg(s
, rd
, tmp
);
6854 if (((insn
>> 12) & 0xf) != 0xf)
6856 if (((insn
>> 16) & 0xf) == 0) {
6857 gen_nop_hint(s
, insn
& 0xff);
6859 /* CPSR = immediate */
6861 shift
= ((insn
>> 8) & 0xf) * 2;
6863 val
= (val
>> shift
) | (val
<< (32 - shift
));
6864 i
= ((insn
& (1 << 22)) != 0);
6865 if (gen_set_psr_im(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, val
))
6869 } else if ((insn
& 0x0f900000) == 0x01000000
6870 && (insn
& 0x00000090) != 0x00000090) {
6871 /* miscellaneous instructions */
6872 op1
= (insn
>> 21) & 3;
6873 sh
= (insn
>> 4) & 0xf;
6876 case 0x0: /* move program status register */
6879 tmp
= load_reg(s
, rm
);
6880 i
= ((op1
& 2) != 0);
6881 if (gen_set_psr(s
, msr_mask(env
, s
, (insn
>> 16) & 0xf, i
), i
, tmp
))
6885 rd
= (insn
>> 12) & 0xf;
6889 tmp
= load_cpu_field(spsr
);
6891 tmp
= tcg_temp_new_i32();
6892 gen_helper_cpsr_read(tmp
, cpu_env
);
6894 store_reg(s
, rd
, tmp
);
6899 /* branch/exchange thumb (bx). */
6901 tmp
= load_reg(s
, rm
);
6903 } else if (op1
== 3) {
6906 rd
= (insn
>> 12) & 0xf;
6907 tmp
= load_reg(s
, rm
);
6908 gen_helper_clz(tmp
, tmp
);
6909 store_reg(s
, rd
, tmp
);
6917 /* Trivial implementation equivalent to bx. */
6918 tmp
= load_reg(s
, rm
);
6929 /* branch link/exchange thumb (blx) */
6930 tmp
= load_reg(s
, rm
);
6931 tmp2
= tcg_temp_new_i32();
6932 tcg_gen_movi_i32(tmp2
, s
->pc
);
6933 store_reg(s
, 14, tmp2
);
6936 case 0x5: /* saturating add/subtract */
6938 rd
= (insn
>> 12) & 0xf;
6939 rn
= (insn
>> 16) & 0xf;
6940 tmp
= load_reg(s
, rm
);
6941 tmp2
= load_reg(s
, rn
);
6943 gen_helper_double_saturate(tmp2
, cpu_env
, tmp2
);
6945 gen_helper_sub_saturate(tmp
, cpu_env
, tmp
, tmp2
);
6947 gen_helper_add_saturate(tmp
, cpu_env
, tmp
, tmp2
);
6948 tcg_temp_free_i32(tmp2
);
6949 store_reg(s
, rd
, tmp
);
6952 /* SMC instruction (op1 == 3)
6953 and undefined instructions (op1 == 0 || op1 == 2)
6960 gen_exception_insn(s
, 4, EXCP_BKPT
);
6962 case 0x8: /* signed multiply */
6967 rs
= (insn
>> 8) & 0xf;
6968 rn
= (insn
>> 12) & 0xf;
6969 rd
= (insn
>> 16) & 0xf;
6971 /* (32 * 16) >> 16 */
6972 tmp
= load_reg(s
, rm
);
6973 tmp2
= load_reg(s
, rs
);
6975 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
6978 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
6979 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
6980 tmp
= tcg_temp_new_i32();
6981 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
6982 tcg_temp_free_i64(tmp64
);
6983 if ((sh
& 2) == 0) {
6984 tmp2
= load_reg(s
, rn
);
6985 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
6986 tcg_temp_free_i32(tmp2
);
6988 store_reg(s
, rd
, tmp
);
6991 tmp
= load_reg(s
, rm
);
6992 tmp2
= load_reg(s
, rs
);
6993 gen_mulxy(tmp
, tmp2
, sh
& 2, sh
& 4);
6994 tcg_temp_free_i32(tmp2
);
6996 tmp64
= tcg_temp_new_i64();
6997 tcg_gen_ext_i32_i64(tmp64
, tmp
);
6998 tcg_temp_free_i32(tmp
);
6999 gen_addq(s
, tmp64
, rn
, rd
);
7000 gen_storeq_reg(s
, rn
, rd
, tmp64
);
7001 tcg_temp_free_i64(tmp64
);
7004 tmp2
= load_reg(s
, rn
);
7005 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
7006 tcg_temp_free_i32(tmp2
);
7008 store_reg(s
, rd
, tmp
);
7015 } else if (((insn
& 0x0e000000) == 0 &&
7016 (insn
& 0x00000090) != 0x90) ||
7017 ((insn
& 0x0e000000) == (1 << 25))) {
7018 int set_cc
, logic_cc
, shiftop
;
7020 op1
= (insn
>> 21) & 0xf;
7021 set_cc
= (insn
>> 20) & 1;
7022 logic_cc
= table_logic_cc
[op1
] & set_cc
;
7024 /* data processing instruction */
7025 if (insn
& (1 << 25)) {
7026 /* immediate operand */
7028 shift
= ((insn
>> 8) & 0xf) * 2;
7030 val
= (val
>> shift
) | (val
<< (32 - shift
));
7032 tmp2
= tcg_temp_new_i32();
7033 tcg_gen_movi_i32(tmp2
, val
);
7034 if (logic_cc
&& shift
) {
7035 gen_set_CF_bit31(tmp2
);
7040 tmp2
= load_reg(s
, rm
);
7041 shiftop
= (insn
>> 5) & 3;
7042 if (!(insn
& (1 << 4))) {
7043 shift
= (insn
>> 7) & 0x1f;
7044 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
7046 rs
= (insn
>> 8) & 0xf;
7047 tmp
= load_reg(s
, rs
);
7048 gen_arm_shift_reg(tmp2
, shiftop
, tmp
, logic_cc
);
7051 if (op1
!= 0x0f && op1
!= 0x0d) {
7052 rn
= (insn
>> 16) & 0xf;
7053 tmp
= load_reg(s
, rn
);
7055 TCGV_UNUSED_I32(tmp
);
7057 rd
= (insn
>> 12) & 0xf;
7060 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
7064 store_reg_bx(env
, s
, rd
, tmp
);
7067 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
7071 store_reg_bx(env
, s
, rd
, tmp
);
7074 if (set_cc
&& rd
== 15) {
7075 /* SUBS r15, ... is used for exception return. */
7079 gen_sub_CC(tmp
, tmp
, tmp2
);
7080 gen_exception_return(s
, tmp
);
7083 gen_sub_CC(tmp
, tmp
, tmp2
);
7085 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7087 store_reg_bx(env
, s
, rd
, tmp
);
7092 gen_sub_CC(tmp
, tmp2
, tmp
);
7094 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7096 store_reg_bx(env
, s
, rd
, tmp
);
7100 gen_add_CC(tmp
, tmp
, tmp2
);
7102 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7104 store_reg_bx(env
, s
, rd
, tmp
);
7108 gen_adc_CC(tmp
, tmp
, tmp2
);
7110 gen_add_carry(tmp
, tmp
, tmp2
);
7112 store_reg_bx(env
, s
, rd
, tmp
);
7116 gen_sbc_CC(tmp
, tmp
, tmp2
);
7118 gen_sub_carry(tmp
, tmp
, tmp2
);
7120 store_reg_bx(env
, s
, rd
, tmp
);
7124 gen_sbc_CC(tmp
, tmp2
, tmp
);
7126 gen_sub_carry(tmp
, tmp2
, tmp
);
7128 store_reg_bx(env
, s
, rd
, tmp
);
7132 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
7135 tcg_temp_free_i32(tmp
);
7139 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
7142 tcg_temp_free_i32(tmp
);
7146 gen_sub_CC(tmp
, tmp
, tmp2
);
7148 tcg_temp_free_i32(tmp
);
7152 gen_add_CC(tmp
, tmp
, tmp2
);
7154 tcg_temp_free_i32(tmp
);
7157 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
7161 store_reg_bx(env
, s
, rd
, tmp
);
7164 if (logic_cc
&& rd
== 15) {
7165 /* MOVS r15, ... is used for exception return. */
7169 gen_exception_return(s
, tmp2
);
7174 store_reg_bx(env
, s
, rd
, tmp2
);
7178 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
7182 store_reg_bx(env
, s
, rd
, tmp
);
7186 tcg_gen_not_i32(tmp2
, tmp2
);
7190 store_reg_bx(env
, s
, rd
, tmp2
);
7193 if (op1
!= 0x0f && op1
!= 0x0d) {
7194 tcg_temp_free_i32(tmp2
);
7197 /* other instructions */
7198 op1
= (insn
>> 24) & 0xf;
7202 /* multiplies, extra load/stores */
7203 sh
= (insn
>> 5) & 3;
7206 rd
= (insn
>> 16) & 0xf;
7207 rn
= (insn
>> 12) & 0xf;
7208 rs
= (insn
>> 8) & 0xf;
7210 op1
= (insn
>> 20) & 0xf;
7212 case 0: case 1: case 2: case 3: case 6:
7214 tmp
= load_reg(s
, rs
);
7215 tmp2
= load_reg(s
, rm
);
7216 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
7217 tcg_temp_free_i32(tmp2
);
7218 if (insn
& (1 << 22)) {
7219 /* Subtract (mls) */
7221 tmp2
= load_reg(s
, rn
);
7222 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
7223 tcg_temp_free_i32(tmp2
);
7224 } else if (insn
& (1 << 21)) {
7226 tmp2
= load_reg(s
, rn
);
7227 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7228 tcg_temp_free_i32(tmp2
);
7230 if (insn
& (1 << 20))
7232 store_reg(s
, rd
, tmp
);
7235 /* 64 bit mul double accumulate (UMAAL) */
7237 tmp
= load_reg(s
, rs
);
7238 tmp2
= load_reg(s
, rm
);
7239 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
7240 gen_addq_lo(s
, tmp64
, rn
);
7241 gen_addq_lo(s
, tmp64
, rd
);
7242 gen_storeq_reg(s
, rn
, rd
, tmp64
);
7243 tcg_temp_free_i64(tmp64
);
7245 case 8: case 9: case 10: case 11:
7246 case 12: case 13: case 14: case 15:
7247 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7248 tmp
= load_reg(s
, rs
);
7249 tmp2
= load_reg(s
, rm
);
7250 if (insn
& (1 << 22)) {
7251 tcg_gen_muls2_i32(tmp
, tmp2
, tmp
, tmp2
);
7253 tcg_gen_mulu2_i32(tmp
, tmp2
, tmp
, tmp2
);
7255 if (insn
& (1 << 21)) { /* mult accumulate */
7256 TCGv_i32 al
= load_reg(s
, rn
);
7257 TCGv_i32 ah
= load_reg(s
, rd
);
7258 tcg_gen_add2_i32(tmp
, tmp2
, tmp
, tmp2
, al
, ah
);
7259 tcg_temp_free_i32(al
);
7260 tcg_temp_free_i32(ah
);
7262 if (insn
& (1 << 20)) {
7263 gen_logicq_cc(tmp
, tmp2
);
7265 store_reg(s
, rn
, tmp
);
7266 store_reg(s
, rd
, tmp2
);
7272 rn
= (insn
>> 16) & 0xf;
7273 rd
= (insn
>> 12) & 0xf;
7274 if (insn
& (1 << 23)) {
7275 /* load/store exclusive */
7276 op1
= (insn
>> 21) & 0x3;
7281 addr
= tcg_temp_local_new_i32();
7282 load_reg_var(s
, addr
, rn
);
7283 if (insn
& (1 << 20)) {
7286 gen_load_exclusive(s
, rd
, 15, addr
, 2);
7288 case 1: /* ldrexd */
7289 gen_load_exclusive(s
, rd
, rd
+ 1, addr
, 3);
7291 case 2: /* ldrexb */
7292 gen_load_exclusive(s
, rd
, 15, addr
, 0);
7294 case 3: /* ldrexh */
7295 gen_load_exclusive(s
, rd
, 15, addr
, 1);
7304 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 2);
7306 case 1: /* strexd */
7307 gen_store_exclusive(s
, rd
, rm
, rm
+ 1, addr
, 3);
7309 case 2: /* strexb */
7310 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 0);
7312 case 3: /* strexh */
7313 gen_store_exclusive(s
, rd
, rm
, 15, addr
, 1);
7319 tcg_temp_free_i32(addr
);
7321 /* SWP instruction */
7324 /* ??? This is not really atomic. However we know
7325 we never have multiple CPUs running in parallel,
7326 so it is good enough. */
7327 addr
= load_reg(s
, rn
);
7328 tmp
= load_reg(s
, rm
);
7329 tmp2
= tcg_temp_new_i32();
7330 if (insn
& (1 << 22)) {
7331 tcg_gen_qemu_ld8u(tmp2
, addr
, IS_USER(s
));
7332 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
7334 tcg_gen_qemu_ld32u(tmp2
, addr
, IS_USER(s
));
7335 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
7337 tcg_temp_free_i32(tmp
);
7338 tcg_temp_free_i32(addr
);
7339 store_reg(s
, rd
, tmp2
);
7345 /* Misc load/store */
7346 rn
= (insn
>> 16) & 0xf;
7347 rd
= (insn
>> 12) & 0xf;
7348 addr
= load_reg(s
, rn
);
7349 if (insn
& (1 << 24))
7350 gen_add_datah_offset(s
, insn
, 0, addr
);
7352 if (insn
& (1 << 20)) {
7354 tmp
= tcg_temp_new_i32();
7357 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
7360 tcg_gen_qemu_ld8s(tmp
, addr
, IS_USER(s
));
7364 tcg_gen_qemu_ld16s(tmp
, addr
, IS_USER(s
));
7368 } else if (sh
& 2) {
7373 tmp
= load_reg(s
, rd
);
7374 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
7375 tcg_temp_free_i32(tmp
);
7376 tcg_gen_addi_i32(addr
, addr
, 4);
7377 tmp
= load_reg(s
, rd
+ 1);
7378 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
7379 tcg_temp_free_i32(tmp
);
7383 tmp
= tcg_temp_new_i32();
7384 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
7385 store_reg(s
, rd
, tmp
);
7386 tcg_gen_addi_i32(addr
, addr
, 4);
7387 tmp
= tcg_temp_new_i32();
7388 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
7392 address_offset
= -4;
7395 tmp
= load_reg(s
, rd
);
7396 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
7397 tcg_temp_free_i32(tmp
);
7400 /* Perform base writeback before the loaded value to
7401 ensure correct behavior with overlapping index registers.
7402 ldrd with base writeback is is undefined if the
7403 destination and index registers overlap. */
7404 if (!(insn
& (1 << 24))) {
7405 gen_add_datah_offset(s
, insn
, address_offset
, addr
);
7406 store_reg(s
, rn
, addr
);
7407 } else if (insn
& (1 << 21)) {
7409 tcg_gen_addi_i32(addr
, addr
, address_offset
);
7410 store_reg(s
, rn
, addr
);
7412 tcg_temp_free_i32(addr
);
7415 /* Complete the load. */
7416 store_reg(s
, rd
, tmp
);
7425 if (insn
& (1 << 4)) {
7427 /* Armv6 Media instructions. */
7429 rn
= (insn
>> 16) & 0xf;
7430 rd
= (insn
>> 12) & 0xf;
7431 rs
= (insn
>> 8) & 0xf;
7432 switch ((insn
>> 23) & 3) {
7433 case 0: /* Parallel add/subtract. */
7434 op1
= (insn
>> 20) & 7;
7435 tmp
= load_reg(s
, rn
);
7436 tmp2
= load_reg(s
, rm
);
7437 sh
= (insn
>> 5) & 7;
7438 if ((op1
& 3) == 0 || sh
== 5 || sh
== 6)
7440 gen_arm_parallel_addsub(op1
, sh
, tmp
, tmp2
);
7441 tcg_temp_free_i32(tmp2
);
7442 store_reg(s
, rd
, tmp
);
7445 if ((insn
& 0x00700020) == 0) {
7446 /* Halfword pack. */
7447 tmp
= load_reg(s
, rn
);
7448 tmp2
= load_reg(s
, rm
);
7449 shift
= (insn
>> 7) & 0x1f;
7450 if (insn
& (1 << 6)) {
7454 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
7455 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
7456 tcg_gen_ext16u_i32(tmp2
, tmp2
);
7460 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
7461 tcg_gen_ext16u_i32(tmp
, tmp
);
7462 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
7464 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
7465 tcg_temp_free_i32(tmp2
);
7466 store_reg(s
, rd
, tmp
);
7467 } else if ((insn
& 0x00200020) == 0x00200000) {
7469 tmp
= load_reg(s
, rm
);
7470 shift
= (insn
>> 7) & 0x1f;
7471 if (insn
& (1 << 6)) {
7474 tcg_gen_sari_i32(tmp
, tmp
, shift
);
7476 tcg_gen_shli_i32(tmp
, tmp
, shift
);
7478 sh
= (insn
>> 16) & 0x1f;
7479 tmp2
= tcg_const_i32(sh
);
7480 if (insn
& (1 << 22))
7481 gen_helper_usat(tmp
, cpu_env
, tmp
, tmp2
);
7483 gen_helper_ssat(tmp
, cpu_env
, tmp
, tmp2
);
7484 tcg_temp_free_i32(tmp2
);
7485 store_reg(s
, rd
, tmp
);
7486 } else if ((insn
& 0x00300fe0) == 0x00200f20) {
7488 tmp
= load_reg(s
, rm
);
7489 sh
= (insn
>> 16) & 0x1f;
7490 tmp2
= tcg_const_i32(sh
);
7491 if (insn
& (1 << 22))
7492 gen_helper_usat16(tmp
, cpu_env
, tmp
, tmp2
);
7494 gen_helper_ssat16(tmp
, cpu_env
, tmp
, tmp2
);
7495 tcg_temp_free_i32(tmp2
);
7496 store_reg(s
, rd
, tmp
);
7497 } else if ((insn
& 0x00700fe0) == 0x00000fa0) {
7499 tmp
= load_reg(s
, rn
);
7500 tmp2
= load_reg(s
, rm
);
7501 tmp3
= tcg_temp_new_i32();
7502 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUARMState
, GE
));
7503 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
7504 tcg_temp_free_i32(tmp3
);
7505 tcg_temp_free_i32(tmp2
);
7506 store_reg(s
, rd
, tmp
);
7507 } else if ((insn
& 0x000003e0) == 0x00000060) {
7508 tmp
= load_reg(s
, rm
);
7509 shift
= (insn
>> 10) & 3;
7510 /* ??? In many cases it's not necessary to do a
7511 rotate, a shift is sufficient. */
7513 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
7514 op1
= (insn
>> 20) & 7;
7516 case 0: gen_sxtb16(tmp
); break;
7517 case 2: gen_sxtb(tmp
); break;
7518 case 3: gen_sxth(tmp
); break;
7519 case 4: gen_uxtb16(tmp
); break;
7520 case 6: gen_uxtb(tmp
); break;
7521 case 7: gen_uxth(tmp
); break;
7522 default: goto illegal_op
;
7525 tmp2
= load_reg(s
, rn
);
7526 if ((op1
& 3) == 0) {
7527 gen_add16(tmp
, tmp2
);
7529 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7530 tcg_temp_free_i32(tmp2
);
7533 store_reg(s
, rd
, tmp
);
7534 } else if ((insn
& 0x003f0f60) == 0x003f0f20) {
7536 tmp
= load_reg(s
, rm
);
7537 if (insn
& (1 << 22)) {
7538 if (insn
& (1 << 7)) {
7542 gen_helper_rbit(tmp
, tmp
);
7545 if (insn
& (1 << 7))
7548 tcg_gen_bswap32_i32(tmp
, tmp
);
7550 store_reg(s
, rd
, tmp
);
7555 case 2: /* Multiplies (Type 3). */
7556 switch ((insn
>> 20) & 0x7) {
7558 if (((insn
>> 6) ^ (insn
>> 7)) & 1) {
7559 /* op2 not 00x or 11x : UNDEF */
7562 /* Signed multiply most significant [accumulate].
7563 (SMMUL, SMMLA, SMMLS) */
7564 tmp
= load_reg(s
, rm
);
7565 tmp2
= load_reg(s
, rs
);
7566 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
7569 tmp
= load_reg(s
, rd
);
7570 if (insn
& (1 << 6)) {
7571 tmp64
= gen_subq_msw(tmp64
, tmp
);
7573 tmp64
= gen_addq_msw(tmp64
, tmp
);
7576 if (insn
& (1 << 5)) {
7577 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
7579 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
7580 tmp
= tcg_temp_new_i32();
7581 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
7582 tcg_temp_free_i64(tmp64
);
7583 store_reg(s
, rn
, tmp
);
7587 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
7588 if (insn
& (1 << 7)) {
7591 tmp
= load_reg(s
, rm
);
7592 tmp2
= load_reg(s
, rs
);
7593 if (insn
& (1 << 5))
7594 gen_swap_half(tmp2
);
7595 gen_smul_dual(tmp
, tmp2
);
7596 if (insn
& (1 << 6)) {
7597 /* This subtraction cannot overflow. */
7598 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
7600 /* This addition cannot overflow 32 bits;
7601 * however it may overflow considered as a signed
7602 * operation, in which case we must set the Q flag.
7604 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
7606 tcg_temp_free_i32(tmp2
);
7607 if (insn
& (1 << 22)) {
7608 /* smlald, smlsld */
7609 tmp64
= tcg_temp_new_i64();
7610 tcg_gen_ext_i32_i64(tmp64
, tmp
);
7611 tcg_temp_free_i32(tmp
);
7612 gen_addq(s
, tmp64
, rd
, rn
);
7613 gen_storeq_reg(s
, rd
, rn
, tmp64
);
7614 tcg_temp_free_i64(tmp64
);
7616 /* smuad, smusd, smlad, smlsd */
7619 tmp2
= load_reg(s
, rd
);
7620 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
7621 tcg_temp_free_i32(tmp2
);
7623 store_reg(s
, rn
, tmp
);
7629 if (!arm_feature(env
, ARM_FEATURE_ARM_DIV
)) {
7632 if (((insn
>> 5) & 7) || (rd
!= 15)) {
7635 tmp
= load_reg(s
, rm
);
7636 tmp2
= load_reg(s
, rs
);
7637 if (insn
& (1 << 21)) {
7638 gen_helper_udiv(tmp
, tmp
, tmp2
);
7640 gen_helper_sdiv(tmp
, tmp
, tmp2
);
7642 tcg_temp_free_i32(tmp2
);
7643 store_reg(s
, rn
, tmp
);
7650 op1
= ((insn
>> 17) & 0x38) | ((insn
>> 5) & 7);
7652 case 0: /* Unsigned sum of absolute differences. */
7654 tmp
= load_reg(s
, rm
);
7655 tmp2
= load_reg(s
, rs
);
7656 gen_helper_usad8(tmp
, tmp
, tmp2
);
7657 tcg_temp_free_i32(tmp2
);
7659 tmp2
= load_reg(s
, rd
);
7660 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
7661 tcg_temp_free_i32(tmp2
);
7663 store_reg(s
, rn
, tmp
);
7665 case 0x20: case 0x24: case 0x28: case 0x2c:
7666 /* Bitfield insert/clear. */
7668 shift
= (insn
>> 7) & 0x1f;
7669 i
= (insn
>> 16) & 0x1f;
7672 tmp
= tcg_temp_new_i32();
7673 tcg_gen_movi_i32(tmp
, 0);
7675 tmp
= load_reg(s
, rm
);
7678 tmp2
= load_reg(s
, rd
);
7679 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
, shift
, i
);
7680 tcg_temp_free_i32(tmp2
);
7682 store_reg(s
, rd
, tmp
);
7684 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
7685 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
7687 tmp
= load_reg(s
, rm
);
7688 shift
= (insn
>> 7) & 0x1f;
7689 i
= ((insn
>> 16) & 0x1f) + 1;
7694 gen_ubfx(tmp
, shift
, (1u << i
) - 1);
7696 gen_sbfx(tmp
, shift
, i
);
7699 store_reg(s
, rd
, tmp
);
7709 /* Check for undefined extension instructions
7710 * per the ARM Bible IE:
7711 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
7713 sh
= (0xf << 20) | (0xf << 4);
7714 if (op1
== 0x7 && ((insn
& sh
) == sh
))
7718 /* load/store byte/word */
7719 rn
= (insn
>> 16) & 0xf;
7720 rd
= (insn
>> 12) & 0xf;
7721 tmp2
= load_reg(s
, rn
);
7722 i
= (IS_USER(s
) || (insn
& 0x01200000) == 0x00200000);
7723 if (insn
& (1 << 24))
7724 gen_add_data_offset(s
, insn
, tmp2
);
7725 if (insn
& (1 << 20)) {
7727 tmp
= tcg_temp_new_i32();
7728 if (insn
& (1 << 22)) {
7729 tcg_gen_qemu_ld8u(tmp
, tmp2
, i
);
7731 tcg_gen_qemu_ld32u(tmp
, tmp2
, i
);
7735 tmp
= load_reg(s
, rd
);
7736 if (insn
& (1 << 22)) {
7737 tcg_gen_qemu_st8(tmp
, tmp2
, i
);
7739 tcg_gen_qemu_st32(tmp
, tmp2
, i
);
7741 tcg_temp_free_i32(tmp
);
7743 if (!(insn
& (1 << 24))) {
7744 gen_add_data_offset(s
, insn
, tmp2
);
7745 store_reg(s
, rn
, tmp2
);
7746 } else if (insn
& (1 << 21)) {
7747 store_reg(s
, rn
, tmp2
);
7749 tcg_temp_free_i32(tmp2
);
7751 if (insn
& (1 << 20)) {
7752 /* Complete the load. */
7753 store_reg_from_load(env
, s
, rd
, tmp
);
7759 int j
, n
, user
, loaded_base
;
7760 TCGv_i32 loaded_var
;
7761 /* load/store multiple words */
7762 /* XXX: store correct base if write back */
7764 if (insn
& (1 << 22)) {
7766 goto illegal_op
; /* only usable in supervisor mode */
7768 if ((insn
& (1 << 15)) == 0)
7771 rn
= (insn
>> 16) & 0xf;
7772 addr
= load_reg(s
, rn
);
7774 /* compute total size */
7776 TCGV_UNUSED_I32(loaded_var
);
7779 if (insn
& (1 << i
))
7782 /* XXX: test invalid n == 0 case ? */
7783 if (insn
& (1 << 23)) {
7784 if (insn
& (1 << 24)) {
7786 tcg_gen_addi_i32(addr
, addr
, 4);
7788 /* post increment */
7791 if (insn
& (1 << 24)) {
7793 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7795 /* post decrement */
7797 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7802 if (insn
& (1 << i
)) {
7803 if (insn
& (1 << 20)) {
7805 tmp
= tcg_temp_new_i32();
7806 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
7808 tmp2
= tcg_const_i32(i
);
7809 gen_helper_set_user_reg(cpu_env
, tmp2
, tmp
);
7810 tcg_temp_free_i32(tmp2
);
7811 tcg_temp_free_i32(tmp
);
7812 } else if (i
== rn
) {
7816 store_reg_from_load(env
, s
, i
, tmp
);
7821 /* special case: r15 = PC + 8 */
7822 val
= (long)s
->pc
+ 4;
7823 tmp
= tcg_temp_new_i32();
7824 tcg_gen_movi_i32(tmp
, val
);
7826 tmp
= tcg_temp_new_i32();
7827 tmp2
= tcg_const_i32(i
);
7828 gen_helper_get_user_reg(tmp
, cpu_env
, tmp2
);
7829 tcg_temp_free_i32(tmp2
);
7831 tmp
= load_reg(s
, i
);
7833 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
7834 tcg_temp_free_i32(tmp
);
7837 /* no need to add after the last transfer */
7839 tcg_gen_addi_i32(addr
, addr
, 4);
7842 if (insn
& (1 << 21)) {
7844 if (insn
& (1 << 23)) {
7845 if (insn
& (1 << 24)) {
7848 /* post increment */
7849 tcg_gen_addi_i32(addr
, addr
, 4);
7852 if (insn
& (1 << 24)) {
7855 tcg_gen_addi_i32(addr
, addr
, -((n
- 1) * 4));
7857 /* post decrement */
7858 tcg_gen_addi_i32(addr
, addr
, -(n
* 4));
7861 store_reg(s
, rn
, addr
);
7863 tcg_temp_free_i32(addr
);
7866 store_reg(s
, rn
, loaded_var
);
7868 if ((insn
& (1 << 22)) && !user
) {
7869 /* Restore CPSR from SPSR. */
7870 tmp
= load_cpu_field(spsr
);
7871 gen_set_cpsr(tmp
, 0xffffffff);
7872 tcg_temp_free_i32(tmp
);
7873 s
->is_jmp
= DISAS_UPDATE
;
7882 /* branch (and link) */
7883 val
= (int32_t)s
->pc
;
7884 if (insn
& (1 << 24)) {
7885 tmp
= tcg_temp_new_i32();
7886 tcg_gen_movi_i32(tmp
, val
);
7887 store_reg(s
, 14, tmp
);
7889 offset
= (((int32_t)insn
<< 8) >> 8);
7890 val
+= (offset
<< 2) + 4;
7898 if (disas_coproc_insn(env
, s
, insn
))
7903 gen_set_pc_im(s
->pc
);
7904 s
->is_jmp
= DISAS_SWI
;
7908 gen_exception_insn(s
, 4, EXCP_UDEF
);
7914 /* Return true if this is a Thumb-2 logical op. */
7916 thumb2_logic_op(int op
)
7921 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
7922 then set condition code flags based on the result of the operation.
7923 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
7924 to the high bit of T1.
7925 Returns zero if the opcode is valid. */
7928 gen_thumb2_data_op(DisasContext
*s
, int op
, int conds
, uint32_t shifter_out
,
7929 TCGv_i32 t0
, TCGv_i32 t1
)
7936 tcg_gen_and_i32(t0
, t0
, t1
);
7940 tcg_gen_andc_i32(t0
, t0
, t1
);
7944 tcg_gen_or_i32(t0
, t0
, t1
);
7948 tcg_gen_orc_i32(t0
, t0
, t1
);
7952 tcg_gen_xor_i32(t0
, t0
, t1
);
7957 gen_add_CC(t0
, t0
, t1
);
7959 tcg_gen_add_i32(t0
, t0
, t1
);
7963 gen_adc_CC(t0
, t0
, t1
);
7969 gen_sbc_CC(t0
, t0
, t1
);
7971 gen_sub_carry(t0
, t0
, t1
);
7976 gen_sub_CC(t0
, t0
, t1
);
7978 tcg_gen_sub_i32(t0
, t0
, t1
);
7982 gen_sub_CC(t0
, t1
, t0
);
7984 tcg_gen_sub_i32(t0
, t1
, t0
);
7986 default: /* 5, 6, 7, 9, 12, 15. */
7992 gen_set_CF_bit31(t1
);
7997 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
7999 static int disas_thumb2_insn(CPUARMState
*env
, DisasContext
*s
, uint16_t insn_hw1
)
8001 uint32_t insn
, imm
, shift
, offset
;
8002 uint32_t rd
, rn
, rm
, rs
;
8013 if (!(arm_feature(env
, ARM_FEATURE_THUMB2
)
8014 || arm_feature (env
, ARM_FEATURE_M
))) {
8015 /* Thumb-1 cores may need to treat bl and blx as a pair of
8016 16-bit instructions to get correct prefetch abort behavior. */
8018 if ((insn
& (1 << 12)) == 0) {
8020 /* Second half of blx. */
8021 offset
= ((insn
& 0x7ff) << 1);
8022 tmp
= load_reg(s
, 14);
8023 tcg_gen_addi_i32(tmp
, tmp
, offset
);
8024 tcg_gen_andi_i32(tmp
, tmp
, 0xfffffffc);
8026 tmp2
= tcg_temp_new_i32();
8027 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
8028 store_reg(s
, 14, tmp2
);
8032 if (insn
& (1 << 11)) {
8033 /* Second half of bl. */
8034 offset
= ((insn
& 0x7ff) << 1) | 1;
8035 tmp
= load_reg(s
, 14);
8036 tcg_gen_addi_i32(tmp
, tmp
, offset
);
8038 tmp2
= tcg_temp_new_i32();
8039 tcg_gen_movi_i32(tmp2
, s
->pc
| 1);
8040 store_reg(s
, 14, tmp2
);
8044 if ((s
->pc
& ~TARGET_PAGE_MASK
) == 0) {
8045 /* Instruction spans a page boundary. Implement it as two
8046 16-bit instructions in case the second half causes an
8048 offset
= ((int32_t)insn
<< 21) >> 9;
8049 tcg_gen_movi_i32(cpu_R
[14], s
->pc
+ 2 + offset
);
8052 /* Fall through to 32-bit decode. */
8055 insn
= arm_lduw_code(env
, s
->pc
, s
->bswap_code
);
8057 insn
|= (uint32_t)insn_hw1
<< 16;
8059 if ((insn
& 0xf800e800) != 0xf000e800) {
8063 rn
= (insn
>> 16) & 0xf;
8064 rs
= (insn
>> 12) & 0xf;
8065 rd
= (insn
>> 8) & 0xf;
8067 switch ((insn
>> 25) & 0xf) {
8068 case 0: case 1: case 2: case 3:
8069 /* 16-bit instructions. Should never happen. */
8072 if (insn
& (1 << 22)) {
8073 /* Other load/store, table branch. */
8074 if (insn
& 0x01200000) {
8075 /* Load/store doubleword. */
8077 addr
= tcg_temp_new_i32();
8078 tcg_gen_movi_i32(addr
, s
->pc
& ~3);
8080 addr
= load_reg(s
, rn
);
8082 offset
= (insn
& 0xff) * 4;
8083 if ((insn
& (1 << 23)) == 0)
8085 if (insn
& (1 << 24)) {
8086 tcg_gen_addi_i32(addr
, addr
, offset
);
8089 if (insn
& (1 << 20)) {
8091 tmp
= tcg_temp_new_i32();
8092 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
8093 store_reg(s
, rs
, tmp
);
8094 tcg_gen_addi_i32(addr
, addr
, 4);
8095 tmp
= tcg_temp_new_i32();
8096 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
8097 store_reg(s
, rd
, tmp
);
8100 tmp
= load_reg(s
, rs
);
8101 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
8102 tcg_temp_free_i32(tmp
);
8103 tcg_gen_addi_i32(addr
, addr
, 4);
8104 tmp
= load_reg(s
, rd
);
8105 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
8106 tcg_temp_free_i32(tmp
);
8108 if (insn
& (1 << 21)) {
8109 /* Base writeback. */
8112 tcg_gen_addi_i32(addr
, addr
, offset
- 4);
8113 store_reg(s
, rn
, addr
);
8115 tcg_temp_free_i32(addr
);
8117 } else if ((insn
& (1 << 23)) == 0) {
8118 /* Load/store exclusive word. */
8119 addr
= tcg_temp_local_new_i32();
8120 load_reg_var(s
, addr
, rn
);
8121 tcg_gen_addi_i32(addr
, addr
, (insn
& 0xff) << 2);
8122 if (insn
& (1 << 20)) {
8123 gen_load_exclusive(s
, rs
, 15, addr
, 2);
8125 gen_store_exclusive(s
, rd
, rs
, 15, addr
, 2);
8127 tcg_temp_free_i32(addr
);
8128 } else if ((insn
& (1 << 6)) == 0) {
8131 addr
= tcg_temp_new_i32();
8132 tcg_gen_movi_i32(addr
, s
->pc
);
8134 addr
= load_reg(s
, rn
);
8136 tmp
= load_reg(s
, rm
);
8137 tcg_gen_add_i32(addr
, addr
, tmp
);
8138 if (insn
& (1 << 4)) {
8140 tcg_gen_add_i32(addr
, addr
, tmp
);
8141 tcg_temp_free_i32(tmp
);
8142 tmp
= tcg_temp_new_i32();
8143 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
8145 tcg_temp_free_i32(tmp
);
8146 tmp
= tcg_temp_new_i32();
8147 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
8149 tcg_temp_free_i32(addr
);
8150 tcg_gen_shli_i32(tmp
, tmp
, 1);
8151 tcg_gen_addi_i32(tmp
, tmp
, s
->pc
);
8152 store_reg(s
, 15, tmp
);
8154 /* Load/store exclusive byte/halfword/doubleword. */
8156 op
= (insn
>> 4) & 0x3;
8160 addr
= tcg_temp_local_new_i32();
8161 load_reg_var(s
, addr
, rn
);
8162 if (insn
& (1 << 20)) {
8163 gen_load_exclusive(s
, rs
, rd
, addr
, op
);
8165 gen_store_exclusive(s
, rm
, rs
, rd
, addr
, op
);
8167 tcg_temp_free_i32(addr
);
8170 /* Load/store multiple, RFE, SRS. */
8171 if (((insn
>> 23) & 1) == ((insn
>> 24) & 1)) {
8172 /* RFE, SRS: not available in user mode or on M profile */
8173 if (IS_USER(s
) || IS_M(env
)) {
8176 if (insn
& (1 << 20)) {
8178 addr
= load_reg(s
, rn
);
8179 if ((insn
& (1 << 24)) == 0)
8180 tcg_gen_addi_i32(addr
, addr
, -8);
8181 /* Load PC into tmp and CPSR into tmp2. */
8182 tmp
= tcg_temp_new_i32();
8183 tcg_gen_qemu_ld32u(tmp
, addr
, 0);
8184 tcg_gen_addi_i32(addr
, addr
, 4);
8185 tmp2
= tcg_temp_new_i32();
8186 tcg_gen_qemu_ld32u(tmp2
, addr
, 0);
8187 if (insn
& (1 << 21)) {
8188 /* Base writeback. */
8189 if (insn
& (1 << 24)) {
8190 tcg_gen_addi_i32(addr
, addr
, 4);
8192 tcg_gen_addi_i32(addr
, addr
, -4);
8194 store_reg(s
, rn
, addr
);
8196 tcg_temp_free_i32(addr
);
8198 gen_rfe(s
, tmp
, tmp2
);
8201 gen_srs(s
, (insn
& 0x1f), (insn
& (1 << 24)) ? 1 : 2,
8205 int i
, loaded_base
= 0;
8206 TCGv_i32 loaded_var
;
8207 /* Load/store multiple. */
8208 addr
= load_reg(s
, rn
);
8210 for (i
= 0; i
< 16; i
++) {
8211 if (insn
& (1 << i
))
8214 if (insn
& (1 << 24)) {
8215 tcg_gen_addi_i32(addr
, addr
, -offset
);
8218 TCGV_UNUSED_I32(loaded_var
);
8219 for (i
= 0; i
< 16; i
++) {
8220 if ((insn
& (1 << i
)) == 0)
8222 if (insn
& (1 << 20)) {
8224 tmp
= tcg_temp_new_i32();
8225 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
8228 } else if (i
== rn
) {
8232 store_reg(s
, i
, tmp
);
8236 tmp
= load_reg(s
, i
);
8237 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
8238 tcg_temp_free_i32(tmp
);
8240 tcg_gen_addi_i32(addr
, addr
, 4);
8243 store_reg(s
, rn
, loaded_var
);
8245 if (insn
& (1 << 21)) {
8246 /* Base register writeback. */
8247 if (insn
& (1 << 24)) {
8248 tcg_gen_addi_i32(addr
, addr
, -offset
);
8250 /* Fault if writeback register is in register list. */
8251 if (insn
& (1 << rn
))
8253 store_reg(s
, rn
, addr
);
8255 tcg_temp_free_i32(addr
);
8262 op
= (insn
>> 21) & 0xf;
8264 /* Halfword pack. */
8265 tmp
= load_reg(s
, rn
);
8266 tmp2
= load_reg(s
, rm
);
8267 shift
= ((insn
>> 10) & 0x1c) | ((insn
>> 6) & 0x3);
8268 if (insn
& (1 << 5)) {
8272 tcg_gen_sari_i32(tmp2
, tmp2
, shift
);
8273 tcg_gen_andi_i32(tmp
, tmp
, 0xffff0000);
8274 tcg_gen_ext16u_i32(tmp2
, tmp2
);
8278 tcg_gen_shli_i32(tmp2
, tmp2
, shift
);
8279 tcg_gen_ext16u_i32(tmp
, tmp
);
8280 tcg_gen_andi_i32(tmp2
, tmp2
, 0xffff0000);
8282 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
8283 tcg_temp_free_i32(tmp2
);
8284 store_reg(s
, rd
, tmp
);
8286 /* Data processing register constant shift. */
8288 tmp
= tcg_temp_new_i32();
8289 tcg_gen_movi_i32(tmp
, 0);
8291 tmp
= load_reg(s
, rn
);
8293 tmp2
= load_reg(s
, rm
);
8295 shiftop
= (insn
>> 4) & 3;
8296 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
8297 conds
= (insn
& (1 << 20)) != 0;
8298 logic_cc
= (conds
&& thumb2_logic_op(op
));
8299 gen_arm_shift_im(tmp2
, shiftop
, shift
, logic_cc
);
8300 if (gen_thumb2_data_op(s
, op
, conds
, 0, tmp
, tmp2
))
8302 tcg_temp_free_i32(tmp2
);
8304 store_reg(s
, rd
, tmp
);
8306 tcg_temp_free_i32(tmp
);
8310 case 13: /* Misc data processing. */
8311 op
= ((insn
>> 22) & 6) | ((insn
>> 7) & 1);
8312 if (op
< 4 && (insn
& 0xf000) != 0xf000)
8315 case 0: /* Register controlled shift. */
8316 tmp
= load_reg(s
, rn
);
8317 tmp2
= load_reg(s
, rm
);
8318 if ((insn
& 0x70) != 0)
8320 op
= (insn
>> 21) & 3;
8321 logic_cc
= (insn
& (1 << 20)) != 0;
8322 gen_arm_shift_reg(tmp
, op
, tmp2
, logic_cc
);
8325 store_reg_bx(env
, s
, rd
, tmp
);
8327 case 1: /* Sign/zero extend. */
8328 tmp
= load_reg(s
, rm
);
8329 shift
= (insn
>> 4) & 3;
8330 /* ??? In many cases it's not necessary to do a
8331 rotate, a shift is sufficient. */
8333 tcg_gen_rotri_i32(tmp
, tmp
, shift
* 8);
8334 op
= (insn
>> 20) & 7;
8336 case 0: gen_sxth(tmp
); break;
8337 case 1: gen_uxth(tmp
); break;
8338 case 2: gen_sxtb16(tmp
); break;
8339 case 3: gen_uxtb16(tmp
); break;
8340 case 4: gen_sxtb(tmp
); break;
8341 case 5: gen_uxtb(tmp
); break;
8342 default: goto illegal_op
;
8345 tmp2
= load_reg(s
, rn
);
8346 if ((op
>> 1) == 1) {
8347 gen_add16(tmp
, tmp2
);
8349 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8350 tcg_temp_free_i32(tmp2
);
8353 store_reg(s
, rd
, tmp
);
8355 case 2: /* SIMD add/subtract. */
8356 op
= (insn
>> 20) & 7;
8357 shift
= (insn
>> 4) & 7;
8358 if ((op
& 3) == 3 || (shift
& 3) == 3)
8360 tmp
= load_reg(s
, rn
);
8361 tmp2
= load_reg(s
, rm
);
8362 gen_thumb2_parallel_addsub(op
, shift
, tmp
, tmp2
);
8363 tcg_temp_free_i32(tmp2
);
8364 store_reg(s
, rd
, tmp
);
8366 case 3: /* Other data processing. */
8367 op
= ((insn
>> 17) & 0x38) | ((insn
>> 4) & 7);
8369 /* Saturating add/subtract. */
8370 tmp
= load_reg(s
, rn
);
8371 tmp2
= load_reg(s
, rm
);
8373 gen_helper_double_saturate(tmp
, cpu_env
, tmp
);
8375 gen_helper_sub_saturate(tmp
, cpu_env
, tmp2
, tmp
);
8377 gen_helper_add_saturate(tmp
, cpu_env
, tmp
, tmp2
);
8378 tcg_temp_free_i32(tmp2
);
8380 tmp
= load_reg(s
, rn
);
8382 case 0x0a: /* rbit */
8383 gen_helper_rbit(tmp
, tmp
);
8385 case 0x08: /* rev */
8386 tcg_gen_bswap32_i32(tmp
, tmp
);
8388 case 0x09: /* rev16 */
8391 case 0x0b: /* revsh */
8394 case 0x10: /* sel */
8395 tmp2
= load_reg(s
, rm
);
8396 tmp3
= tcg_temp_new_i32();
8397 tcg_gen_ld_i32(tmp3
, cpu_env
, offsetof(CPUARMState
, GE
));
8398 gen_helper_sel_flags(tmp
, tmp3
, tmp
, tmp2
);
8399 tcg_temp_free_i32(tmp3
);
8400 tcg_temp_free_i32(tmp2
);
8402 case 0x18: /* clz */
8403 gen_helper_clz(tmp
, tmp
);
8409 store_reg(s
, rd
, tmp
);
8411 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
8412 op
= (insn
>> 4) & 0xf;
8413 tmp
= load_reg(s
, rn
);
8414 tmp2
= load_reg(s
, rm
);
8415 switch ((insn
>> 20) & 7) {
8416 case 0: /* 32 x 32 -> 32 */
8417 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
8418 tcg_temp_free_i32(tmp2
);
8420 tmp2
= load_reg(s
, rs
);
8422 tcg_gen_sub_i32(tmp
, tmp2
, tmp
);
8424 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8425 tcg_temp_free_i32(tmp2
);
8428 case 1: /* 16 x 16 -> 32 */
8429 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
8430 tcg_temp_free_i32(tmp2
);
8432 tmp2
= load_reg(s
, rs
);
8433 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
8434 tcg_temp_free_i32(tmp2
);
8437 case 2: /* Dual multiply add. */
8438 case 4: /* Dual multiply subtract. */
8440 gen_swap_half(tmp2
);
8441 gen_smul_dual(tmp
, tmp2
);
8442 if (insn
& (1 << 22)) {
8443 /* This subtraction cannot overflow. */
8444 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8446 /* This addition cannot overflow 32 bits;
8447 * however it may overflow considered as a signed
8448 * operation, in which case we must set the Q flag.
8450 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
8452 tcg_temp_free_i32(tmp2
);
8455 tmp2
= load_reg(s
, rs
);
8456 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
8457 tcg_temp_free_i32(tmp2
);
8460 case 3: /* 32 * 16 -> 32msb */
8462 tcg_gen_sari_i32(tmp2
, tmp2
, 16);
8465 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
8466 tcg_gen_shri_i64(tmp64
, tmp64
, 16);
8467 tmp
= tcg_temp_new_i32();
8468 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
8469 tcg_temp_free_i64(tmp64
);
8472 tmp2
= load_reg(s
, rs
);
8473 gen_helper_add_setq(tmp
, cpu_env
, tmp
, tmp2
);
8474 tcg_temp_free_i32(tmp2
);
8477 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8478 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
8480 tmp
= load_reg(s
, rs
);
8481 if (insn
& (1 << 20)) {
8482 tmp64
= gen_addq_msw(tmp64
, tmp
);
8484 tmp64
= gen_subq_msw(tmp64
, tmp
);
8487 if (insn
& (1 << 4)) {
8488 tcg_gen_addi_i64(tmp64
, tmp64
, 0x80000000u
);
8490 tcg_gen_shri_i64(tmp64
, tmp64
, 32);
8491 tmp
= tcg_temp_new_i32();
8492 tcg_gen_trunc_i64_i32(tmp
, tmp64
);
8493 tcg_temp_free_i64(tmp64
);
8495 case 7: /* Unsigned sum of absolute differences. */
8496 gen_helper_usad8(tmp
, tmp
, tmp2
);
8497 tcg_temp_free_i32(tmp2
);
8499 tmp2
= load_reg(s
, rs
);
8500 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8501 tcg_temp_free_i32(tmp2
);
8505 store_reg(s
, rd
, tmp
);
8507 case 6: case 7: /* 64-bit multiply, Divide. */
8508 op
= ((insn
>> 4) & 0xf) | ((insn
>> 16) & 0x70);
8509 tmp
= load_reg(s
, rn
);
8510 tmp2
= load_reg(s
, rm
);
8511 if ((op
& 0x50) == 0x10) {
8513 if (!arm_feature(env
, ARM_FEATURE_THUMB_DIV
)) {
8517 gen_helper_udiv(tmp
, tmp
, tmp2
);
8519 gen_helper_sdiv(tmp
, tmp
, tmp2
);
8520 tcg_temp_free_i32(tmp2
);
8521 store_reg(s
, rd
, tmp
);
8522 } else if ((op
& 0xe) == 0xc) {
8523 /* Dual multiply accumulate long. */
8525 gen_swap_half(tmp2
);
8526 gen_smul_dual(tmp
, tmp2
);
8528 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
8530 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
8532 tcg_temp_free_i32(tmp2
);
8534 tmp64
= tcg_temp_new_i64();
8535 tcg_gen_ext_i32_i64(tmp64
, tmp
);
8536 tcg_temp_free_i32(tmp
);
8537 gen_addq(s
, tmp64
, rs
, rd
);
8538 gen_storeq_reg(s
, rs
, rd
, tmp64
);
8539 tcg_temp_free_i64(tmp64
);
8542 /* Unsigned 64-bit multiply */
8543 tmp64
= gen_mulu_i64_i32(tmp
, tmp2
);
8547 gen_mulxy(tmp
, tmp2
, op
& 2, op
& 1);
8548 tcg_temp_free_i32(tmp2
);
8549 tmp64
= tcg_temp_new_i64();
8550 tcg_gen_ext_i32_i64(tmp64
, tmp
);
8551 tcg_temp_free_i32(tmp
);
8553 /* Signed 64-bit multiply */
8554 tmp64
= gen_muls_i64_i32(tmp
, tmp2
);
8559 gen_addq_lo(s
, tmp64
, rs
);
8560 gen_addq_lo(s
, tmp64
, rd
);
8561 } else if (op
& 0x40) {
8562 /* 64-bit accumulate. */
8563 gen_addq(s
, tmp64
, rs
, rd
);
8565 gen_storeq_reg(s
, rs
, rd
, tmp64
);
8566 tcg_temp_free_i64(tmp64
);
8571 case 6: case 7: case 14: case 15:
8573 if (((insn
>> 24) & 3) == 3) {
8574 /* Translate into the equivalent ARM encoding. */
8575 insn
= (insn
& 0xe2ffffff) | ((insn
& (1 << 28)) >> 4) | (1 << 28);
8576 if (disas_neon_data_insn(env
, s
, insn
))
8579 if (insn
& (1 << 28))
8581 if (disas_coproc_insn (env
, s
, insn
))
8585 case 8: case 9: case 10: case 11:
8586 if (insn
& (1 << 15)) {
8587 /* Branches, misc control. */
8588 if (insn
& 0x5000) {
8589 /* Unconditional branch. */
8590 /* signextend(hw1[10:0]) -> offset[:12]. */
8591 offset
= ((int32_t)insn
<< 5) >> 9 & ~(int32_t)0xfff;
8592 /* hw1[10:0] -> offset[11:1]. */
8593 offset
|= (insn
& 0x7ff) << 1;
8594 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
8595 offset[24:22] already have the same value because of the
8596 sign extension above. */
8597 offset
^= ((~insn
) & (1 << 13)) << 10;
8598 offset
^= ((~insn
) & (1 << 11)) << 11;
8600 if (insn
& (1 << 14)) {
8601 /* Branch and link. */
8602 tcg_gen_movi_i32(cpu_R
[14], s
->pc
| 1);
8606 if (insn
& (1 << 12)) {
8611 offset
&= ~(uint32_t)2;
8612 /* thumb2 bx, no need to check */
8613 gen_bx_im(s
, offset
);
8615 } else if (((insn
>> 23) & 7) == 7) {
8617 if (insn
& (1 << 13))
8620 if (insn
& (1 << 26)) {
8621 /* Secure monitor call (v6Z) */
8622 goto illegal_op
; /* not implemented. */
8624 op
= (insn
>> 20) & 7;
8626 case 0: /* msr cpsr. */
8628 tmp
= load_reg(s
, rn
);
8629 addr
= tcg_const_i32(insn
& 0xff);
8630 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
8631 tcg_temp_free_i32(addr
);
8632 tcg_temp_free_i32(tmp
);
8637 case 1: /* msr spsr. */
8640 tmp
= load_reg(s
, rn
);
8642 msr_mask(env
, s
, (insn
>> 8) & 0xf, op
== 1),
8646 case 2: /* cps, nop-hint. */
8647 if (((insn
>> 8) & 7) == 0) {
8648 gen_nop_hint(s
, insn
& 0xff);
8650 /* Implemented as NOP in user mode. */
8655 if (insn
& (1 << 10)) {
8656 if (insn
& (1 << 7))
8658 if (insn
& (1 << 6))
8660 if (insn
& (1 << 5))
8662 if (insn
& (1 << 9))
8663 imm
= CPSR_A
| CPSR_I
| CPSR_F
;
8665 if (insn
& (1 << 8)) {
8667 imm
|= (insn
& 0x1f);
8670 gen_set_psr_im(s
, offset
, 0, imm
);
8673 case 3: /* Special control operations. */
8675 op
= (insn
>> 4) & 0xf;
8683 /* These execute as NOPs. */
8690 /* Trivial implementation equivalent to bx. */
8691 tmp
= load_reg(s
, rn
);
8694 case 5: /* Exception return. */
8698 if (rn
!= 14 || rd
!= 15) {
8701 tmp
= load_reg(s
, rn
);
8702 tcg_gen_subi_i32(tmp
, tmp
, insn
& 0xff);
8703 gen_exception_return(s
, tmp
);
8705 case 6: /* mrs cpsr. */
8706 tmp
= tcg_temp_new_i32();
8708 addr
= tcg_const_i32(insn
& 0xff);
8709 gen_helper_v7m_mrs(tmp
, cpu_env
, addr
);
8710 tcg_temp_free_i32(addr
);
8712 gen_helper_cpsr_read(tmp
, cpu_env
);
8714 store_reg(s
, rd
, tmp
);
8716 case 7: /* mrs spsr. */
8717 /* Not accessible in user mode. */
8718 if (IS_USER(s
) || IS_M(env
))
8720 tmp
= load_cpu_field(spsr
);
8721 store_reg(s
, rd
, tmp
);
8726 /* Conditional branch. */
8727 op
= (insn
>> 22) & 0xf;
8728 /* Generate a conditional jump to next instruction. */
8729 s
->condlabel
= gen_new_label();
8730 gen_test_cc(op
^ 1, s
->condlabel
);
8733 /* offset[11:1] = insn[10:0] */
8734 offset
= (insn
& 0x7ff) << 1;
8735 /* offset[17:12] = insn[21:16]. */
8736 offset
|= (insn
& 0x003f0000) >> 4;
8737 /* offset[31:20] = insn[26]. */
8738 offset
|= ((int32_t)((insn
<< 5) & 0x80000000)) >> 11;
8739 /* offset[18] = insn[13]. */
8740 offset
|= (insn
& (1 << 13)) << 5;
8741 /* offset[19] = insn[11]. */
8742 offset
|= (insn
& (1 << 11)) << 8;
8744 /* jump to the offset */
8745 gen_jmp(s
, s
->pc
+ offset
);
8748 /* Data processing immediate. */
8749 if (insn
& (1 << 25)) {
8750 if (insn
& (1 << 24)) {
8751 if (insn
& (1 << 20))
8753 /* Bitfield/Saturate. */
8754 op
= (insn
>> 21) & 7;
8756 shift
= ((insn
>> 6) & 3) | ((insn
>> 10) & 0x1c);
8758 tmp
= tcg_temp_new_i32();
8759 tcg_gen_movi_i32(tmp
, 0);
8761 tmp
= load_reg(s
, rn
);
8764 case 2: /* Signed bitfield extract. */
8766 if (shift
+ imm
> 32)
8769 gen_sbfx(tmp
, shift
, imm
);
8771 case 6: /* Unsigned bitfield extract. */
8773 if (shift
+ imm
> 32)
8776 gen_ubfx(tmp
, shift
, (1u << imm
) - 1);
8778 case 3: /* Bitfield insert/clear. */
8781 imm
= imm
+ 1 - shift
;
8783 tmp2
= load_reg(s
, rd
);
8784 tcg_gen_deposit_i32(tmp
, tmp2
, tmp
, shift
, imm
);
8785 tcg_temp_free_i32(tmp2
);
8790 default: /* Saturate. */
8793 tcg_gen_sari_i32(tmp
, tmp
, shift
);
8795 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8797 tmp2
= tcg_const_i32(imm
);
8800 if ((op
& 1) && shift
== 0)
8801 gen_helper_usat16(tmp
, cpu_env
, tmp
, tmp2
);
8803 gen_helper_usat(tmp
, cpu_env
, tmp
, tmp2
);
8806 if ((op
& 1) && shift
== 0)
8807 gen_helper_ssat16(tmp
, cpu_env
, tmp
, tmp2
);
8809 gen_helper_ssat(tmp
, cpu_env
, tmp
, tmp2
);
8811 tcg_temp_free_i32(tmp2
);
8814 store_reg(s
, rd
, tmp
);
8816 imm
= ((insn
& 0x04000000) >> 15)
8817 | ((insn
& 0x7000) >> 4) | (insn
& 0xff);
8818 if (insn
& (1 << 22)) {
8819 /* 16-bit immediate. */
8820 imm
|= (insn
>> 4) & 0xf000;
8821 if (insn
& (1 << 23)) {
8823 tmp
= load_reg(s
, rd
);
8824 tcg_gen_ext16u_i32(tmp
, tmp
);
8825 tcg_gen_ori_i32(tmp
, tmp
, imm
<< 16);
8828 tmp
= tcg_temp_new_i32();
8829 tcg_gen_movi_i32(tmp
, imm
);
8832 /* Add/sub 12-bit immediate. */
8834 offset
= s
->pc
& ~(uint32_t)3;
8835 if (insn
& (1 << 23))
8839 tmp
= tcg_temp_new_i32();
8840 tcg_gen_movi_i32(tmp
, offset
);
8842 tmp
= load_reg(s
, rn
);
8843 if (insn
& (1 << 23))
8844 tcg_gen_subi_i32(tmp
, tmp
, imm
);
8846 tcg_gen_addi_i32(tmp
, tmp
, imm
);
8849 store_reg(s
, rd
, tmp
);
8852 int shifter_out
= 0;
8853 /* modified 12-bit immediate. */
8854 shift
= ((insn
& 0x04000000) >> 23) | ((insn
& 0x7000) >> 12);
8855 imm
= (insn
& 0xff);
8858 /* Nothing to do. */
8860 case 1: /* 00XY00XY */
8863 case 2: /* XY00XY00 */
8867 case 3: /* XYXYXYXY */
8871 default: /* Rotated constant. */
8872 shift
= (shift
<< 1) | (imm
>> 7);
8874 imm
= imm
<< (32 - shift
);
8878 tmp2
= tcg_temp_new_i32();
8879 tcg_gen_movi_i32(tmp2
, imm
);
8880 rn
= (insn
>> 16) & 0xf;
8882 tmp
= tcg_temp_new_i32();
8883 tcg_gen_movi_i32(tmp
, 0);
8885 tmp
= load_reg(s
, rn
);
8887 op
= (insn
>> 21) & 0xf;
8888 if (gen_thumb2_data_op(s
, op
, (insn
& (1 << 20)) != 0,
8889 shifter_out
, tmp
, tmp2
))
8891 tcg_temp_free_i32(tmp2
);
8892 rd
= (insn
>> 8) & 0xf;
8894 store_reg(s
, rd
, tmp
);
8896 tcg_temp_free_i32(tmp
);
8901 case 12: /* Load/store single data item. */
8906 if ((insn
& 0x01100000) == 0x01000000) {
8907 if (disas_neon_ls_insn(env
, s
, insn
))
8911 op
= ((insn
>> 21) & 3) | ((insn
>> 22) & 4);
8913 if (!(insn
& (1 << 20))) {
8917 /* Byte or halfword load space with dest == r15 : memory hints.
8918 * Catch them early so we don't emit pointless addressing code.
8919 * This space is a mix of:
8920 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
8921 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
8923 * unallocated hints, which must be treated as NOPs
8924 * UNPREDICTABLE space, which we NOP or UNDEF depending on
8925 * which is easiest for the decoding logic
8926 * Some space which must UNDEF
8928 int op1
= (insn
>> 23) & 3;
8929 int op2
= (insn
>> 6) & 0x3f;
8934 /* UNPREDICTABLE, unallocated hint or
8935 * PLD/PLDW/PLI (literal)
8940 return 0; /* PLD/PLDW/PLI or unallocated hint */
8942 if ((op2
== 0) || ((op2
& 0x3c) == 0x30)) {
8943 return 0; /* PLD/PLDW/PLI or unallocated hint */
8945 /* UNDEF space, or an UNPREDICTABLE */
8951 addr
= tcg_temp_new_i32();
8953 /* s->pc has already been incremented by 4. */
8954 imm
= s
->pc
& 0xfffffffc;
8955 if (insn
& (1 << 23))
8956 imm
+= insn
& 0xfff;
8958 imm
-= insn
& 0xfff;
8959 tcg_gen_movi_i32(addr
, imm
);
8961 addr
= load_reg(s
, rn
);
8962 if (insn
& (1 << 23)) {
8963 /* Positive offset. */
8965 tcg_gen_addi_i32(addr
, addr
, imm
);
8968 switch ((insn
>> 8) & 0xf) {
8969 case 0x0: /* Shifted Register. */
8970 shift
= (insn
>> 4) & 0xf;
8972 tcg_temp_free_i32(addr
);
8975 tmp
= load_reg(s
, rm
);
8977 tcg_gen_shli_i32(tmp
, tmp
, shift
);
8978 tcg_gen_add_i32(addr
, addr
, tmp
);
8979 tcg_temp_free_i32(tmp
);
8981 case 0xc: /* Negative offset. */
8982 tcg_gen_addi_i32(addr
, addr
, -imm
);
8984 case 0xe: /* User privilege. */
8985 tcg_gen_addi_i32(addr
, addr
, imm
);
8988 case 0x9: /* Post-decrement. */
8991 case 0xb: /* Post-increment. */
8995 case 0xd: /* Pre-decrement. */
8998 case 0xf: /* Pre-increment. */
8999 tcg_gen_addi_i32(addr
, addr
, imm
);
9003 tcg_temp_free_i32(addr
);
9008 if (insn
& (1 << 20)) {
9010 tmp
= tcg_temp_new_i32();
9013 tcg_gen_qemu_ld8u(tmp
, addr
, user
);
9016 tcg_gen_qemu_ld8s(tmp
, addr
, user
);
9019 tcg_gen_qemu_ld16u(tmp
, addr
, user
);
9022 tcg_gen_qemu_ld16s(tmp
, addr
, user
);
9025 tcg_gen_qemu_ld32u(tmp
, addr
, user
);
9028 tcg_temp_free_i32(tmp
);
9029 tcg_temp_free_i32(addr
);
9035 store_reg(s
, rs
, tmp
);
9039 tmp
= load_reg(s
, rs
);
9042 tcg_gen_qemu_st8(tmp
, addr
, user
);
9045 tcg_gen_qemu_st16(tmp
, addr
, user
);
9048 tcg_gen_qemu_st32(tmp
, addr
, user
);
9051 tcg_temp_free_i32(tmp
);
9052 tcg_temp_free_i32(addr
);
9055 tcg_temp_free_i32(tmp
);
9058 tcg_gen_addi_i32(addr
, addr
, imm
);
9060 store_reg(s
, rn
, addr
);
9062 tcg_temp_free_i32(addr
);
9074 static void disas_thumb_insn(CPUARMState
*env
, DisasContext
*s
)
9076 uint32_t val
, insn
, op
, rm
, rn
, rd
, shift
, cond
;
9083 if (s
->condexec_mask
) {
9084 cond
= s
->condexec_cond
;
9085 if (cond
!= 0x0e) { /* Skip conditional when condition is AL. */
9086 s
->condlabel
= gen_new_label();
9087 gen_test_cc(cond
^ 1, s
->condlabel
);
9092 insn
= arm_lduw_code(env
, s
->pc
, s
->bswap_code
);
9095 switch (insn
>> 12) {
9099 op
= (insn
>> 11) & 3;
9102 rn
= (insn
>> 3) & 7;
9103 tmp
= load_reg(s
, rn
);
9104 if (insn
& (1 << 10)) {
9106 tmp2
= tcg_temp_new_i32();
9107 tcg_gen_movi_i32(tmp2
, (insn
>> 6) & 7);
9110 rm
= (insn
>> 6) & 7;
9111 tmp2
= load_reg(s
, rm
);
9113 if (insn
& (1 << 9)) {
9114 if (s
->condexec_mask
)
9115 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
9117 gen_sub_CC(tmp
, tmp
, tmp2
);
9119 if (s
->condexec_mask
)
9120 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
9122 gen_add_CC(tmp
, tmp
, tmp2
);
9124 tcg_temp_free_i32(tmp2
);
9125 store_reg(s
, rd
, tmp
);
9127 /* shift immediate */
9128 rm
= (insn
>> 3) & 7;
9129 shift
= (insn
>> 6) & 0x1f;
9130 tmp
= load_reg(s
, rm
);
9131 gen_arm_shift_im(tmp
, op
, shift
, s
->condexec_mask
== 0);
9132 if (!s
->condexec_mask
)
9134 store_reg(s
, rd
, tmp
);
9138 /* arithmetic large immediate */
9139 op
= (insn
>> 11) & 3;
9140 rd
= (insn
>> 8) & 0x7;
9141 if (op
== 0) { /* mov */
9142 tmp
= tcg_temp_new_i32();
9143 tcg_gen_movi_i32(tmp
, insn
& 0xff);
9144 if (!s
->condexec_mask
)
9146 store_reg(s
, rd
, tmp
);
9148 tmp
= load_reg(s
, rd
);
9149 tmp2
= tcg_temp_new_i32();
9150 tcg_gen_movi_i32(tmp2
, insn
& 0xff);
9153 gen_sub_CC(tmp
, tmp
, tmp2
);
9154 tcg_temp_free_i32(tmp
);
9155 tcg_temp_free_i32(tmp2
);
9158 if (s
->condexec_mask
)
9159 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
9161 gen_add_CC(tmp
, tmp
, tmp2
);
9162 tcg_temp_free_i32(tmp2
);
9163 store_reg(s
, rd
, tmp
);
9166 if (s
->condexec_mask
)
9167 tcg_gen_sub_i32(tmp
, tmp
, tmp2
);
9169 gen_sub_CC(tmp
, tmp
, tmp2
);
9170 tcg_temp_free_i32(tmp2
);
9171 store_reg(s
, rd
, tmp
);
9177 if (insn
& (1 << 11)) {
9178 rd
= (insn
>> 8) & 7;
9179 /* load pc-relative. Bit 1 of PC is ignored. */
9180 val
= s
->pc
+ 2 + ((insn
& 0xff) * 4);
9181 val
&= ~(uint32_t)2;
9182 addr
= tcg_temp_new_i32();
9183 tcg_gen_movi_i32(addr
, val
);
9184 tmp
= tcg_temp_new_i32();
9185 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
9186 tcg_temp_free_i32(addr
);
9187 store_reg(s
, rd
, tmp
);
9190 if (insn
& (1 << 10)) {
9191 /* data processing extended or blx */
9192 rd
= (insn
& 7) | ((insn
>> 4) & 8);
9193 rm
= (insn
>> 3) & 0xf;
9194 op
= (insn
>> 8) & 3;
9197 tmp
= load_reg(s
, rd
);
9198 tmp2
= load_reg(s
, rm
);
9199 tcg_gen_add_i32(tmp
, tmp
, tmp2
);
9200 tcg_temp_free_i32(tmp2
);
9201 store_reg(s
, rd
, tmp
);
9204 tmp
= load_reg(s
, rd
);
9205 tmp2
= load_reg(s
, rm
);
9206 gen_sub_CC(tmp
, tmp
, tmp2
);
9207 tcg_temp_free_i32(tmp2
);
9208 tcg_temp_free_i32(tmp
);
9210 case 2: /* mov/cpy */
9211 tmp
= load_reg(s
, rm
);
9212 store_reg(s
, rd
, tmp
);
9214 case 3:/* branch [and link] exchange thumb register */
9215 tmp
= load_reg(s
, rm
);
9216 if (insn
& (1 << 7)) {
9218 val
= (uint32_t)s
->pc
| 1;
9219 tmp2
= tcg_temp_new_i32();
9220 tcg_gen_movi_i32(tmp2
, val
);
9221 store_reg(s
, 14, tmp2
);
9223 /* already thumb, no need to check */
9230 /* data processing register */
9232 rm
= (insn
>> 3) & 7;
9233 op
= (insn
>> 6) & 0xf;
9234 if (op
== 2 || op
== 3 || op
== 4 || op
== 7) {
9235 /* the shift/rotate ops want the operands backwards */
9244 if (op
== 9) { /* neg */
9245 tmp
= tcg_temp_new_i32();
9246 tcg_gen_movi_i32(tmp
, 0);
9247 } else if (op
!= 0xf) { /* mvn doesn't read its first operand */
9248 tmp
= load_reg(s
, rd
);
9250 TCGV_UNUSED_I32(tmp
);
9253 tmp2
= load_reg(s
, rm
);
9256 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
9257 if (!s
->condexec_mask
)
9261 tcg_gen_xor_i32(tmp
, tmp
, tmp2
);
9262 if (!s
->condexec_mask
)
9266 if (s
->condexec_mask
) {
9267 gen_shl(tmp2
, tmp2
, tmp
);
9269 gen_helper_shl_cc(tmp2
, cpu_env
, tmp2
, tmp
);
9274 if (s
->condexec_mask
) {
9275 gen_shr(tmp2
, tmp2
, tmp
);
9277 gen_helper_shr_cc(tmp2
, cpu_env
, tmp2
, tmp
);
9282 if (s
->condexec_mask
) {
9283 gen_sar(tmp2
, tmp2
, tmp
);
9285 gen_helper_sar_cc(tmp2
, cpu_env
, tmp2
, tmp
);
9290 if (s
->condexec_mask
) {
9293 gen_adc_CC(tmp
, tmp
, tmp2
);
9297 if (s
->condexec_mask
) {
9298 gen_sub_carry(tmp
, tmp
, tmp2
);
9300 gen_sbc_CC(tmp
, tmp
, tmp2
);
9304 if (s
->condexec_mask
) {
9305 tcg_gen_andi_i32(tmp
, tmp
, 0x1f);
9306 tcg_gen_rotr_i32(tmp2
, tmp2
, tmp
);
9308 gen_helper_ror_cc(tmp2
, cpu_env
, tmp2
, tmp
);
9313 tcg_gen_and_i32(tmp
, tmp
, tmp2
);
9318 if (s
->condexec_mask
)
9319 tcg_gen_neg_i32(tmp
, tmp2
);
9321 gen_sub_CC(tmp
, tmp
, tmp2
);
9324 gen_sub_CC(tmp
, tmp
, tmp2
);
9328 gen_add_CC(tmp
, tmp
, tmp2
);
9332 tcg_gen_or_i32(tmp
, tmp
, tmp2
);
9333 if (!s
->condexec_mask
)
9337 tcg_gen_mul_i32(tmp
, tmp
, tmp2
);
9338 if (!s
->condexec_mask
)
9342 tcg_gen_andc_i32(tmp
, tmp
, tmp2
);
9343 if (!s
->condexec_mask
)
9347 tcg_gen_not_i32(tmp2
, tmp2
);
9348 if (!s
->condexec_mask
)
9356 store_reg(s
, rm
, tmp2
);
9358 tcg_temp_free_i32(tmp
);
9360 store_reg(s
, rd
, tmp
);
9361 tcg_temp_free_i32(tmp2
);
9364 tcg_temp_free_i32(tmp
);
9365 tcg_temp_free_i32(tmp2
);
9370 /* load/store register offset. */
9372 rn
= (insn
>> 3) & 7;
9373 rm
= (insn
>> 6) & 7;
9374 op
= (insn
>> 9) & 7;
9375 addr
= load_reg(s
, rn
);
9376 tmp
= load_reg(s
, rm
);
9377 tcg_gen_add_i32(addr
, addr
, tmp
);
9378 tcg_temp_free_i32(tmp
);
9380 if (op
< 3) { /* store */
9381 tmp
= load_reg(s
, rd
);
9383 tmp
= tcg_temp_new_i32();
9388 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
9391 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
9394 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
9397 tcg_gen_qemu_ld8s(tmp
, addr
, IS_USER(s
));
9400 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
9403 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
9406 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
9409 tcg_gen_qemu_ld16s(tmp
, addr
, IS_USER(s
));
9412 if (op
>= 3) { /* load */
9413 store_reg(s
, rd
, tmp
);
9415 tcg_temp_free_i32(tmp
);
9417 tcg_temp_free_i32(addr
);
9421 /* load/store word immediate offset */
9423 rn
= (insn
>> 3) & 7;
9424 addr
= load_reg(s
, rn
);
9425 val
= (insn
>> 4) & 0x7c;
9426 tcg_gen_addi_i32(addr
, addr
, val
);
9428 if (insn
& (1 << 11)) {
9430 tmp
= tcg_temp_new_i32();
9431 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
9432 store_reg(s
, rd
, tmp
);
9435 tmp
= load_reg(s
, rd
);
9436 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
9437 tcg_temp_free_i32(tmp
);
9439 tcg_temp_free_i32(addr
);
9443 /* load/store byte immediate offset */
9445 rn
= (insn
>> 3) & 7;
9446 addr
= load_reg(s
, rn
);
9447 val
= (insn
>> 6) & 0x1f;
9448 tcg_gen_addi_i32(addr
, addr
, val
);
9450 if (insn
& (1 << 11)) {
9452 tmp
= tcg_temp_new_i32();
9453 tcg_gen_qemu_ld8u(tmp
, addr
, IS_USER(s
));
9454 store_reg(s
, rd
, tmp
);
9457 tmp
= load_reg(s
, rd
);
9458 tcg_gen_qemu_st8(tmp
, addr
, IS_USER(s
));
9459 tcg_temp_free_i32(tmp
);
9461 tcg_temp_free_i32(addr
);
9465 /* load/store halfword immediate offset */
9467 rn
= (insn
>> 3) & 7;
9468 addr
= load_reg(s
, rn
);
9469 val
= (insn
>> 5) & 0x3e;
9470 tcg_gen_addi_i32(addr
, addr
, val
);
9472 if (insn
& (1 << 11)) {
9474 tmp
= tcg_temp_new_i32();
9475 tcg_gen_qemu_ld16u(tmp
, addr
, IS_USER(s
));
9476 store_reg(s
, rd
, tmp
);
9479 tmp
= load_reg(s
, rd
);
9480 tcg_gen_qemu_st16(tmp
, addr
, IS_USER(s
));
9481 tcg_temp_free_i32(tmp
);
9483 tcg_temp_free_i32(addr
);
9487 /* load/store from stack */
9488 rd
= (insn
>> 8) & 7;
9489 addr
= load_reg(s
, 13);
9490 val
= (insn
& 0xff) * 4;
9491 tcg_gen_addi_i32(addr
, addr
, val
);
9493 if (insn
& (1 << 11)) {
9495 tmp
= tcg_temp_new_i32();
9496 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
9497 store_reg(s
, rd
, tmp
);
9500 tmp
= load_reg(s
, rd
);
9501 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
9502 tcg_temp_free_i32(tmp
);
9504 tcg_temp_free_i32(addr
);
9508 /* add to high reg */
9509 rd
= (insn
>> 8) & 7;
9510 if (insn
& (1 << 11)) {
9512 tmp
= load_reg(s
, 13);
9514 /* PC. bit 1 is ignored. */
9515 tmp
= tcg_temp_new_i32();
9516 tcg_gen_movi_i32(tmp
, (s
->pc
+ 2) & ~(uint32_t)2);
9518 val
= (insn
& 0xff) * 4;
9519 tcg_gen_addi_i32(tmp
, tmp
, val
);
9520 store_reg(s
, rd
, tmp
);
9525 op
= (insn
>> 8) & 0xf;
9528 /* adjust stack pointer */
9529 tmp
= load_reg(s
, 13);
9530 val
= (insn
& 0x7f) * 4;
9531 if (insn
& (1 << 7))
9532 val
= -(int32_t)val
;
9533 tcg_gen_addi_i32(tmp
, tmp
, val
);
9534 store_reg(s
, 13, tmp
);
9537 case 2: /* sign/zero extend. */
9540 rm
= (insn
>> 3) & 7;
9541 tmp
= load_reg(s
, rm
);
9542 switch ((insn
>> 6) & 3) {
9543 case 0: gen_sxth(tmp
); break;
9544 case 1: gen_sxtb(tmp
); break;
9545 case 2: gen_uxth(tmp
); break;
9546 case 3: gen_uxtb(tmp
); break;
9548 store_reg(s
, rd
, tmp
);
9550 case 4: case 5: case 0xc: case 0xd:
9552 addr
= load_reg(s
, 13);
9553 if (insn
& (1 << 8))
9557 for (i
= 0; i
< 8; i
++) {
9558 if (insn
& (1 << i
))
9561 if ((insn
& (1 << 11)) == 0) {
9562 tcg_gen_addi_i32(addr
, addr
, -offset
);
9564 for (i
= 0; i
< 8; i
++) {
9565 if (insn
& (1 << i
)) {
9566 if (insn
& (1 << 11)) {
9568 tmp
= tcg_temp_new_i32();
9569 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
9570 store_reg(s
, i
, tmp
);
9573 tmp
= load_reg(s
, i
);
9574 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
9575 tcg_temp_free_i32(tmp
);
9577 /* advance to the next address. */
9578 tcg_gen_addi_i32(addr
, addr
, 4);
9581 TCGV_UNUSED_I32(tmp
);
9582 if (insn
& (1 << 8)) {
9583 if (insn
& (1 << 11)) {
9585 tmp
= tcg_temp_new_i32();
9586 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
9587 /* don't set the pc until the rest of the instruction
9591 tmp
= load_reg(s
, 14);
9592 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
9593 tcg_temp_free_i32(tmp
);
9595 tcg_gen_addi_i32(addr
, addr
, 4);
9597 if ((insn
& (1 << 11)) == 0) {
9598 tcg_gen_addi_i32(addr
, addr
, -offset
);
9600 /* write back the new stack pointer */
9601 store_reg(s
, 13, addr
);
9602 /* set the new PC value */
9603 if ((insn
& 0x0900) == 0x0900) {
9604 store_reg_from_load(env
, s
, 15, tmp
);
9608 case 1: case 3: case 9: case 11: /* czb */
9610 tmp
= load_reg(s
, rm
);
9611 s
->condlabel
= gen_new_label();
9613 if (insn
& (1 << 11))
9614 tcg_gen_brcondi_i32(TCG_COND_EQ
, tmp
, 0, s
->condlabel
);
9616 tcg_gen_brcondi_i32(TCG_COND_NE
, tmp
, 0, s
->condlabel
);
9617 tcg_temp_free_i32(tmp
);
9618 offset
= ((insn
& 0xf8) >> 2) | (insn
& 0x200) >> 3;
9619 val
= (uint32_t)s
->pc
+ 2;
9624 case 15: /* IT, nop-hint. */
9625 if ((insn
& 0xf) == 0) {
9626 gen_nop_hint(s
, (insn
>> 4) & 0xf);
9630 s
->condexec_cond
= (insn
>> 4) & 0xe;
9631 s
->condexec_mask
= insn
& 0x1f;
9632 /* No actual code generated for this insn, just setup state. */
9635 case 0xe: /* bkpt */
9637 gen_exception_insn(s
, 2, EXCP_BKPT
);
9642 rn
= (insn
>> 3) & 0x7;
9644 tmp
= load_reg(s
, rn
);
9645 switch ((insn
>> 6) & 3) {
9646 case 0: tcg_gen_bswap32_i32(tmp
, tmp
); break;
9647 case 1: gen_rev16(tmp
); break;
9648 case 3: gen_revsh(tmp
); break;
9649 default: goto illegal_op
;
9651 store_reg(s
, rd
, tmp
);
9655 switch ((insn
>> 5) & 7) {
9659 if (((insn
>> 3) & 1) != s
->bswap_code
) {
9660 /* Dynamic endianness switching not implemented. */
9671 tmp
= tcg_const_i32((insn
& (1 << 4)) != 0);
9674 addr
= tcg_const_i32(19);
9675 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
9676 tcg_temp_free_i32(addr
);
9680 addr
= tcg_const_i32(16);
9681 gen_helper_v7m_msr(cpu_env
, addr
, tmp
);
9682 tcg_temp_free_i32(addr
);
9684 tcg_temp_free_i32(tmp
);
9687 if (insn
& (1 << 4)) {
9688 shift
= CPSR_A
| CPSR_I
| CPSR_F
;
9692 gen_set_psr_im(s
, ((insn
& 7) << 6), 0, shift
);
9707 /* load/store multiple */
9708 TCGv_i32 loaded_var
;
9709 TCGV_UNUSED_I32(loaded_var
);
9710 rn
= (insn
>> 8) & 0x7;
9711 addr
= load_reg(s
, rn
);
9712 for (i
= 0; i
< 8; i
++) {
9713 if (insn
& (1 << i
)) {
9714 if (insn
& (1 << 11)) {
9716 tmp
= tcg_temp_new_i32();
9717 tcg_gen_qemu_ld32u(tmp
, addr
, IS_USER(s
));
9721 store_reg(s
, i
, tmp
);
9725 tmp
= load_reg(s
, i
);
9726 tcg_gen_qemu_st32(tmp
, addr
, IS_USER(s
));
9727 tcg_temp_free_i32(tmp
);
9729 /* advance to the next address */
9730 tcg_gen_addi_i32(addr
, addr
, 4);
9733 if ((insn
& (1 << rn
)) == 0) {
9734 /* base reg not in list: base register writeback */
9735 store_reg(s
, rn
, addr
);
9737 /* base reg in list: if load, complete it now */
9738 if (insn
& (1 << 11)) {
9739 store_reg(s
, rn
, loaded_var
);
9741 tcg_temp_free_i32(addr
);
9746 /* conditional branch or swi */
9747 cond
= (insn
>> 8) & 0xf;
9753 gen_set_pc_im(s
->pc
);
9754 s
->is_jmp
= DISAS_SWI
;
9757 /* generate a conditional jump to next instruction */
9758 s
->condlabel
= gen_new_label();
9759 gen_test_cc(cond
^ 1, s
->condlabel
);
9762 /* jump to the offset */
9763 val
= (uint32_t)s
->pc
+ 2;
9764 offset
= ((int32_t)insn
<< 24) >> 24;
9770 if (insn
& (1 << 11)) {
9771 if (disas_thumb2_insn(env
, s
, insn
))
9775 /* unconditional branch */
9776 val
= (uint32_t)s
->pc
;
9777 offset
= ((int32_t)insn
<< 21) >> 21;
9778 val
+= (offset
<< 1) + 2;
9783 if (disas_thumb2_insn(env
, s
, insn
))
9789 gen_exception_insn(s
, 4, EXCP_UDEF
);
9793 gen_exception_insn(s
, 2, EXCP_UDEF
);
9796 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
9797 basic block 'tb'. If search_pc is TRUE, also generate PC
9798 information for each intermediate instruction. */
9799 static inline void gen_intermediate_code_internal(CPUARMState
*env
,
9800 TranslationBlock
*tb
,
9803 DisasContext dc1
, *dc
= &dc1
;
9805 uint16_t *gen_opc_end
;
9807 target_ulong pc_start
;
9808 uint32_t next_page_start
;
9812 /* generate intermediate code */
9817 gen_opc_end
= tcg_ctx
.gen_opc_buf
+ OPC_MAX_SIZE
;
9819 dc
->is_jmp
= DISAS_NEXT
;
9821 dc
->singlestep_enabled
= env
->singlestep_enabled
;
9823 dc
->thumb
= ARM_TBFLAG_THUMB(tb
->flags
);
9824 dc
->bswap_code
= ARM_TBFLAG_BSWAP_CODE(tb
->flags
);
9825 dc
->condexec_mask
= (ARM_TBFLAG_CONDEXEC(tb
->flags
) & 0xf) << 1;
9826 dc
->condexec_cond
= ARM_TBFLAG_CONDEXEC(tb
->flags
) >> 4;
9827 #if !defined(CONFIG_USER_ONLY)
9828 dc
->user
= (ARM_TBFLAG_PRIV(tb
->flags
) == 0);
9830 dc
->vfp_enabled
= ARM_TBFLAG_VFPEN(tb
->flags
);
9831 dc
->vec_len
= ARM_TBFLAG_VECLEN(tb
->flags
);
9832 dc
->vec_stride
= ARM_TBFLAG_VECSTRIDE(tb
->flags
);
9833 cpu_F0s
= tcg_temp_new_i32();
9834 cpu_F1s
= tcg_temp_new_i32();
9835 cpu_F0d
= tcg_temp_new_i64();
9836 cpu_F1d
= tcg_temp_new_i64();
9839 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
9840 cpu_M0
= tcg_temp_new_i64();
9841 next_page_start
= (pc_start
& TARGET_PAGE_MASK
) + TARGET_PAGE_SIZE
;
9844 max_insns
= tb
->cflags
& CF_COUNT_MASK
;
9846 max_insns
= CF_COUNT_MASK
;
9850 tcg_clear_temp_count();
9852 /* A note on handling of the condexec (IT) bits:
9854 * We want to avoid the overhead of having to write the updated condexec
9855 * bits back to the CPUARMState for every instruction in an IT block. So:
9856 * (1) if the condexec bits are not already zero then we write
9857 * zero back into the CPUARMState now. This avoids complications trying
9858 * to do it at the end of the block. (For example if we don't do this
9859 * it's hard to identify whether we can safely skip writing condexec
9860 * at the end of the TB, which we definitely want to do for the case
9861 * where a TB doesn't do anything with the IT state at all.)
9862 * (2) if we are going to leave the TB then we call gen_set_condexec()
9863 * which will write the correct value into CPUARMState if zero is wrong.
9864 * This is done both for leaving the TB at the end, and for leaving
9865 * it because of an exception we know will happen, which is done in
9866 * gen_exception_insn(). The latter is necessary because we need to
9867 * leave the TB with the PC/IT state just prior to execution of the
9868 * instruction which caused the exception.
9869 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
9870 * then the CPUARMState will be wrong and we need to reset it.
9871 * This is handled in the same way as restoration of the
9872 * PC in these situations: we will be called again with search_pc=1
9873 * and generate a mapping of the condexec bits for each PC in
9874 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
9875 * this to restore the condexec bits.
9877 * Note that there are no instructions which can read the condexec
9878 * bits, and none which can write non-static values to them, so
9879 * we don't need to care about whether CPUARMState is correct in the
9883 /* Reset the conditional execution bits immediately. This avoids
9884 complications trying to do it at the end of the block. */
9885 if (dc
->condexec_mask
|| dc
->condexec_cond
)
9887 TCGv_i32 tmp
= tcg_temp_new_i32();
9888 tcg_gen_movi_i32(tmp
, 0);
9889 store_cpu_field(tmp
, condexec_bits
);
9892 #ifdef CONFIG_USER_ONLY
9893 /* Intercept jump to the magic kernel page. */
9894 if (dc
->pc
>= 0xffff0000) {
9895 /* We always get here via a jump, so know we are not in a
9896 conditional execution block. */
9897 gen_exception(EXCP_KERNEL_TRAP
);
9898 dc
->is_jmp
= DISAS_UPDATE
;
9902 if (dc
->pc
>= 0xfffffff0 && IS_M(env
)) {
9903 /* We always get here via a jump, so know we are not in a
9904 conditional execution block. */
9905 gen_exception(EXCP_EXCEPTION_EXIT
);
9906 dc
->is_jmp
= DISAS_UPDATE
;
9911 if (unlikely(!QTAILQ_EMPTY(&env
->breakpoints
))) {
9912 QTAILQ_FOREACH(bp
, &env
->breakpoints
, entry
) {
9913 if (bp
->pc
== dc
->pc
) {
9914 gen_exception_insn(dc
, 0, EXCP_DEBUG
);
9915 /* Advance PC so that clearing the breakpoint will
9916 invalidate this TB. */
9918 goto done_generating
;
9924 j
= tcg_ctx
.gen_opc_ptr
- tcg_ctx
.gen_opc_buf
;
9928 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
9930 tcg_ctx
.gen_opc_pc
[lj
] = dc
->pc
;
9931 gen_opc_condexec_bits
[lj
] = (dc
->condexec_cond
<< 4) | (dc
->condexec_mask
>> 1);
9932 tcg_ctx
.gen_opc_instr_start
[lj
] = 1;
9933 tcg_ctx
.gen_opc_icount
[lj
] = num_insns
;
9936 if (num_insns
+ 1 == max_insns
&& (tb
->cflags
& CF_LAST_IO
))
9939 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP
| CPU_LOG_TB_OP_OPT
))) {
9940 tcg_gen_debug_insn_start(dc
->pc
);
9944 disas_thumb_insn(env
, dc
);
9945 if (dc
->condexec_mask
) {
9946 dc
->condexec_cond
= (dc
->condexec_cond
& 0xe)
9947 | ((dc
->condexec_mask
>> 4) & 1);
9948 dc
->condexec_mask
= (dc
->condexec_mask
<< 1) & 0x1f;
9949 if (dc
->condexec_mask
== 0) {
9950 dc
->condexec_cond
= 0;
9954 disas_arm_insn(env
, dc
);
9957 if (dc
->condjmp
&& !dc
->is_jmp
) {
9958 gen_set_label(dc
->condlabel
);
9962 if (tcg_check_temp_count()) {
9963 fprintf(stderr
, "TCG temporary leak before %08x\n", dc
->pc
);
9966 /* Translation stops when a conditional branch is encountered.
9967 * Otherwise the subsequent code could get translated several times.
9968 * Also stop translation when a page boundary is reached. This
9969 * ensures prefetch aborts occur at the right place. */
9971 } while (!dc
->is_jmp
&& tcg_ctx
.gen_opc_ptr
< gen_opc_end
&&
9972 !env
->singlestep_enabled
&&
9974 dc
->pc
< next_page_start
&&
9975 num_insns
< max_insns
);
9977 if (tb
->cflags
& CF_LAST_IO
) {
9979 /* FIXME: This can theoretically happen with self-modifying
9981 cpu_abort(env
, "IO on conditional branch instruction");
9986 /* At this stage dc->condjmp will only be set when the skipped
9987 instruction was a conditional branch or trap, and the PC has
9988 already been written. */
9989 if (unlikely(env
->singlestep_enabled
)) {
9990 /* Make sure the pc is updated, and raise a debug exception. */
9992 gen_set_condexec(dc
);
9993 if (dc
->is_jmp
== DISAS_SWI
) {
9994 gen_exception(EXCP_SWI
);
9996 gen_exception(EXCP_DEBUG
);
9998 gen_set_label(dc
->condlabel
);
10000 if (dc
->condjmp
|| !dc
->is_jmp
) {
10001 gen_set_pc_im(dc
->pc
);
10004 gen_set_condexec(dc
);
10005 if (dc
->is_jmp
== DISAS_SWI
&& !dc
->condjmp
) {
10006 gen_exception(EXCP_SWI
);
10008 /* FIXME: Single stepping a WFI insn will not halt
10010 gen_exception(EXCP_DEBUG
);
10013 /* While branches must always occur at the end of an IT block,
10014 there are a few other things that can cause us to terminate
10015 the TB in the middle of an IT block:
10016 - Exception generating instructions (bkpt, swi, undefined).
10018 - Hardware watchpoints.
10019 Hardware breakpoints have already been handled and skip this code.
10021 gen_set_condexec(dc
);
10022 switch(dc
->is_jmp
) {
10024 gen_goto_tb(dc
, 1, dc
->pc
);
10029 /* indicate that the hash table must be used to find the next TB */
10030 tcg_gen_exit_tb(0);
10032 case DISAS_TB_JUMP
:
10033 /* nothing more to generate */
10036 gen_helper_wfi(cpu_env
);
10039 gen_exception(EXCP_SWI
);
10043 gen_set_label(dc
->condlabel
);
10044 gen_set_condexec(dc
);
10045 gen_goto_tb(dc
, 1, dc
->pc
);
10051 gen_tb_end(tb
, num_insns
);
10052 *tcg_ctx
.gen_opc_ptr
= INDEX_op_end
;
10055 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM
)) {
10056 qemu_log("----------------\n");
10057 qemu_log("IN: %s\n", lookup_symbol(pc_start
));
10058 log_target_disas(env
, pc_start
, dc
->pc
- pc_start
,
10059 dc
->thumb
| (dc
->bswap_code
<< 1));
10064 j
= tcg_ctx
.gen_opc_ptr
- tcg_ctx
.gen_opc_buf
;
10067 tcg_ctx
.gen_opc_instr_start
[lj
++] = 0;
10069 tb
->size
= dc
->pc
- pc_start
;
10070 tb
->icount
= num_insns
;
10074 void gen_intermediate_code(CPUARMState
*env
, TranslationBlock
*tb
)
10076 gen_intermediate_code_internal(env
, tb
, 0);
10079 void gen_intermediate_code_pc(CPUARMState
*env
, TranslationBlock
*tb
)
10081 gen_intermediate_code_internal(env
, tb
, 1);
10084 static const char *cpu_mode_names
[16] = {
10085 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
10086 "???", "???", "???", "und", "???", "???", "???", "sys"
10089 void cpu_dump_state(CPUARMState
*env
, FILE *f
, fprintf_function cpu_fprintf
,
10095 for(i
=0;i
<16;i
++) {
10096 cpu_fprintf(f
, "R%02d=%08x", i
, env
->regs
[i
]);
10098 cpu_fprintf(f
, "\n");
10100 cpu_fprintf(f
, " ");
10102 psr
= cpsr_read(env
);
10103 cpu_fprintf(f
, "PSR=%08x %c%c%c%c %c %s%d\n",
10105 psr
& (1 << 31) ? 'N' : '-',
10106 psr
& (1 << 30) ? 'Z' : '-',
10107 psr
& (1 << 29) ? 'C' : '-',
10108 psr
& (1 << 28) ? 'V' : '-',
10109 psr
& CPSR_T
? 'T' : 'A',
10110 cpu_mode_names
[psr
& 0xf], (psr
& 0x10) ? 32 : 26);
10112 if (flags
& CPU_DUMP_FPU
) {
10113 int numvfpregs
= 0;
10114 if (arm_feature(env
, ARM_FEATURE_VFP
)) {
10117 if (arm_feature(env
, ARM_FEATURE_VFP3
)) {
10120 for (i
= 0; i
< numvfpregs
; i
++) {
10121 uint64_t v
= float64_val(env
->vfp
.regs
[i
]);
10122 cpu_fprintf(f
, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64
"\n",
10123 i
* 2, (uint32_t)v
,
10124 i
* 2 + 1, (uint32_t)(v
>> 32),
10127 cpu_fprintf(f
, "FPSCR: %08x\n", (int)env
->vfp
.xregs
[ARM_VFP_FPSCR
]);
10131 void restore_state_to_opc(CPUARMState
*env
, TranslationBlock
*tb
, int pc_pos
)
10133 env
->regs
[15] = tcg_ctx
.gen_opc_pc
[pc_pos
];
10134 env
->condexec_bits
= gen_opc_condexec_bits
[pc_pos
];