exec: Make stq_*_phys input an AddressSpace
[qemu/ar7.git] / target-arm / translate.c
blob782aab8b58e9bc9a68fde1efa7420ed4203f8b9b
1 /*
2 * ARM translation
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/>.
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
27 #include "cpu.h"
28 #include "disas/disas.h"
29 #include "tcg-op.h"
30 #include "qemu/log.h"
31 #include "qemu/bitops.h"
33 #include "helper.h"
34 #define GEN_HELPER 1
35 #include "helper.h"
37 #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
38 #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
39 /* currently all emulated v5 cores are also v5TE, so don't bother */
40 #define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5)
41 #define ENABLE_ARCH_5J 0
42 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
43 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
44 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
45 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
46 #define ENABLE_ARCH_8 arm_feature(env, ARM_FEATURE_V8)
48 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
50 #include "translate.h"
51 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
53 #if defined(CONFIG_USER_ONLY)
54 #define IS_USER(s) 1
55 #else
56 #define IS_USER(s) (s->user)
57 #endif
59 TCGv_ptr cpu_env;
60 /* We reuse the same 64-bit temporaries for efficiency. */
61 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
62 static TCGv_i32 cpu_R[16];
63 static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
64 static TCGv_i64 cpu_exclusive_addr;
65 static TCGv_i64 cpu_exclusive_val;
66 #ifdef CONFIG_USER_ONLY
67 static TCGv_i64 cpu_exclusive_test;
68 static TCGv_i32 cpu_exclusive_info;
69 #endif
71 /* FIXME: These should be removed. */
72 static TCGv_i32 cpu_F0s, cpu_F1s;
73 static TCGv_i64 cpu_F0d, cpu_F1d;
75 #include "exec/gen-icount.h"
77 static const char *regnames[] =
78 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
79 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
81 /* initialize TCG globals. */
82 void arm_translate_init(void)
84 int i;
86 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
88 for (i = 0; i < 16; i++) {
89 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
90 offsetof(CPUARMState, regs[i]),
91 regnames[i]);
93 cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
94 cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
95 cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
96 cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
98 cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
99 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
100 cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
101 offsetof(CPUARMState, exclusive_val), "exclusive_val");
102 #ifdef CONFIG_USER_ONLY
103 cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
104 offsetof(CPUARMState, exclusive_test), "exclusive_test");
105 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
106 offsetof(CPUARMState, exclusive_info), "exclusive_info");
107 #endif
109 a64_translate_init();
112 static inline TCGv_i32 load_cpu_offset(int offset)
114 TCGv_i32 tmp = tcg_temp_new_i32();
115 tcg_gen_ld_i32(tmp, cpu_env, offset);
116 return tmp;
119 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
121 static inline void store_cpu_offset(TCGv_i32 var, int offset)
123 tcg_gen_st_i32(var, cpu_env, offset);
124 tcg_temp_free_i32(var);
127 #define store_cpu_field(var, name) \
128 store_cpu_offset(var, offsetof(CPUARMState, name))
130 /* Set a variable to the value of a CPU register. */
131 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
133 if (reg == 15) {
134 uint32_t addr;
135 /* normally, since we updated PC, we need only to add one insn */
136 if (s->thumb)
137 addr = (long)s->pc + 2;
138 else
139 addr = (long)s->pc + 4;
140 tcg_gen_movi_i32(var, addr);
141 } else {
142 tcg_gen_mov_i32(var, cpu_R[reg]);
146 /* Create a new temporary and set it to the value of a CPU register. */
147 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
149 TCGv_i32 tmp = tcg_temp_new_i32();
150 load_reg_var(s, tmp, reg);
151 return tmp;
154 /* Set a CPU register. The source must be a temporary and will be
155 marked as dead. */
156 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
158 if (reg == 15) {
159 tcg_gen_andi_i32(var, var, ~1);
160 s->is_jmp = DISAS_JUMP;
162 tcg_gen_mov_i32(cpu_R[reg], var);
163 tcg_temp_free_i32(var);
166 /* Value extensions. */
167 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
168 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
169 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
170 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
172 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
173 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
176 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
178 TCGv_i32 tmp_mask = tcg_const_i32(mask);
179 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
180 tcg_temp_free_i32(tmp_mask);
182 /* Set NZCV flags from the high 4 bits of var. */
183 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
185 static void gen_exception(int excp)
187 TCGv_i32 tmp = tcg_temp_new_i32();
188 tcg_gen_movi_i32(tmp, excp);
189 gen_helper_exception(cpu_env, tmp);
190 tcg_temp_free_i32(tmp);
193 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
195 TCGv_i32 tmp1 = tcg_temp_new_i32();
196 TCGv_i32 tmp2 = tcg_temp_new_i32();
197 tcg_gen_ext16s_i32(tmp1, a);
198 tcg_gen_ext16s_i32(tmp2, b);
199 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
200 tcg_temp_free_i32(tmp2);
201 tcg_gen_sari_i32(a, a, 16);
202 tcg_gen_sari_i32(b, b, 16);
203 tcg_gen_mul_i32(b, b, a);
204 tcg_gen_mov_i32(a, tmp1);
205 tcg_temp_free_i32(tmp1);
208 /* Byteswap each halfword. */
209 static void gen_rev16(TCGv_i32 var)
211 TCGv_i32 tmp = tcg_temp_new_i32();
212 tcg_gen_shri_i32(tmp, var, 8);
213 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
214 tcg_gen_shli_i32(var, var, 8);
215 tcg_gen_andi_i32(var, var, 0xff00ff00);
216 tcg_gen_or_i32(var, var, tmp);
217 tcg_temp_free_i32(tmp);
220 /* Byteswap low halfword and sign extend. */
221 static void gen_revsh(TCGv_i32 var)
223 tcg_gen_ext16u_i32(var, var);
224 tcg_gen_bswap16_i32(var, var);
225 tcg_gen_ext16s_i32(var, var);
228 /* Unsigned bitfield extract. */
229 static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask)
231 if (shift)
232 tcg_gen_shri_i32(var, var, shift);
233 tcg_gen_andi_i32(var, var, mask);
236 /* Signed bitfield extract. */
237 static void gen_sbfx(TCGv_i32 var, int shift, int width)
239 uint32_t signbit;
241 if (shift)
242 tcg_gen_sari_i32(var, var, shift);
243 if (shift + width < 32) {
244 signbit = 1u << (width - 1);
245 tcg_gen_andi_i32(var, var, (1u << width) - 1);
246 tcg_gen_xori_i32(var, var, signbit);
247 tcg_gen_subi_i32(var, var, signbit);
251 /* Return (b << 32) + a. Mark inputs as dead */
252 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
254 TCGv_i64 tmp64 = tcg_temp_new_i64();
256 tcg_gen_extu_i32_i64(tmp64, b);
257 tcg_temp_free_i32(b);
258 tcg_gen_shli_i64(tmp64, tmp64, 32);
259 tcg_gen_add_i64(a, tmp64, a);
261 tcg_temp_free_i64(tmp64);
262 return a;
265 /* Return (b << 32) - a. Mark inputs as dead. */
266 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
268 TCGv_i64 tmp64 = tcg_temp_new_i64();
270 tcg_gen_extu_i32_i64(tmp64, b);
271 tcg_temp_free_i32(b);
272 tcg_gen_shli_i64(tmp64, tmp64, 32);
273 tcg_gen_sub_i64(a, tmp64, a);
275 tcg_temp_free_i64(tmp64);
276 return a;
279 /* 32x32->64 multiply. Marks inputs as dead. */
280 static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
282 TCGv_i32 lo = tcg_temp_new_i32();
283 TCGv_i32 hi = tcg_temp_new_i32();
284 TCGv_i64 ret;
286 tcg_gen_mulu2_i32(lo, hi, a, b);
287 tcg_temp_free_i32(a);
288 tcg_temp_free_i32(b);
290 ret = tcg_temp_new_i64();
291 tcg_gen_concat_i32_i64(ret, lo, hi);
292 tcg_temp_free_i32(lo);
293 tcg_temp_free_i32(hi);
295 return ret;
298 static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
300 TCGv_i32 lo = tcg_temp_new_i32();
301 TCGv_i32 hi = tcg_temp_new_i32();
302 TCGv_i64 ret;
304 tcg_gen_muls2_i32(lo, hi, a, b);
305 tcg_temp_free_i32(a);
306 tcg_temp_free_i32(b);
308 ret = tcg_temp_new_i64();
309 tcg_gen_concat_i32_i64(ret, lo, hi);
310 tcg_temp_free_i32(lo);
311 tcg_temp_free_i32(hi);
313 return ret;
316 /* Swap low and high halfwords. */
317 static void gen_swap_half(TCGv_i32 var)
319 TCGv_i32 tmp = tcg_temp_new_i32();
320 tcg_gen_shri_i32(tmp, var, 16);
321 tcg_gen_shli_i32(var, var, 16);
322 tcg_gen_or_i32(var, var, tmp);
323 tcg_temp_free_i32(tmp);
326 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
327 tmp = (t0 ^ t1) & 0x8000;
328 t0 &= ~0x8000;
329 t1 &= ~0x8000;
330 t0 = (t0 + t1) ^ tmp;
333 static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
335 TCGv_i32 tmp = tcg_temp_new_i32();
336 tcg_gen_xor_i32(tmp, t0, t1);
337 tcg_gen_andi_i32(tmp, tmp, 0x8000);
338 tcg_gen_andi_i32(t0, t0, ~0x8000);
339 tcg_gen_andi_i32(t1, t1, ~0x8000);
340 tcg_gen_add_i32(t0, t0, t1);
341 tcg_gen_xor_i32(t0, t0, tmp);
342 tcg_temp_free_i32(tmp);
343 tcg_temp_free_i32(t1);
346 /* Set CF to the top bit of var. */
347 static void gen_set_CF_bit31(TCGv_i32 var)
349 tcg_gen_shri_i32(cpu_CF, var, 31);
352 /* Set N and Z flags from var. */
353 static inline void gen_logic_CC(TCGv_i32 var)
355 tcg_gen_mov_i32(cpu_NF, var);
356 tcg_gen_mov_i32(cpu_ZF, var);
359 /* T0 += T1 + CF. */
360 static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
362 tcg_gen_add_i32(t0, t0, t1);
363 tcg_gen_add_i32(t0, t0, cpu_CF);
366 /* dest = T0 + T1 + CF. */
367 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
369 tcg_gen_add_i32(dest, t0, t1);
370 tcg_gen_add_i32(dest, dest, cpu_CF);
373 /* dest = T0 - T1 + CF - 1. */
374 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
376 tcg_gen_sub_i32(dest, t0, t1);
377 tcg_gen_add_i32(dest, dest, cpu_CF);
378 tcg_gen_subi_i32(dest, dest, 1);
381 /* dest = T0 + T1. Compute C, N, V and Z flags */
382 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
384 TCGv_i32 tmp = tcg_temp_new_i32();
385 tcg_gen_movi_i32(tmp, 0);
386 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
387 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
388 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
389 tcg_gen_xor_i32(tmp, t0, t1);
390 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
391 tcg_temp_free_i32(tmp);
392 tcg_gen_mov_i32(dest, cpu_NF);
395 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
396 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
398 TCGv_i32 tmp = tcg_temp_new_i32();
399 if (TCG_TARGET_HAS_add2_i32) {
400 tcg_gen_movi_i32(tmp, 0);
401 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
402 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
403 } else {
404 TCGv_i64 q0 = tcg_temp_new_i64();
405 TCGv_i64 q1 = tcg_temp_new_i64();
406 tcg_gen_extu_i32_i64(q0, t0);
407 tcg_gen_extu_i32_i64(q1, t1);
408 tcg_gen_add_i64(q0, q0, q1);
409 tcg_gen_extu_i32_i64(q1, cpu_CF);
410 tcg_gen_add_i64(q0, q0, q1);
411 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
412 tcg_temp_free_i64(q0);
413 tcg_temp_free_i64(q1);
415 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
416 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
417 tcg_gen_xor_i32(tmp, t0, t1);
418 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
419 tcg_temp_free_i32(tmp);
420 tcg_gen_mov_i32(dest, cpu_NF);
423 /* dest = T0 - T1. Compute C, N, V and Z flags */
424 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
426 TCGv_i32 tmp;
427 tcg_gen_sub_i32(cpu_NF, t0, t1);
428 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
429 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
430 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
431 tmp = tcg_temp_new_i32();
432 tcg_gen_xor_i32(tmp, t0, t1);
433 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
434 tcg_temp_free_i32(tmp);
435 tcg_gen_mov_i32(dest, cpu_NF);
438 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
439 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
441 TCGv_i32 tmp = tcg_temp_new_i32();
442 tcg_gen_not_i32(tmp, t1);
443 gen_adc_CC(dest, t0, tmp);
444 tcg_temp_free_i32(tmp);
447 #define GEN_SHIFT(name) \
448 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
450 TCGv_i32 tmp1, tmp2, tmp3; \
451 tmp1 = tcg_temp_new_i32(); \
452 tcg_gen_andi_i32(tmp1, t1, 0xff); \
453 tmp2 = tcg_const_i32(0); \
454 tmp3 = tcg_const_i32(0x1f); \
455 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
456 tcg_temp_free_i32(tmp3); \
457 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
458 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
459 tcg_temp_free_i32(tmp2); \
460 tcg_temp_free_i32(tmp1); \
462 GEN_SHIFT(shl)
463 GEN_SHIFT(shr)
464 #undef GEN_SHIFT
466 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
468 TCGv_i32 tmp1, tmp2;
469 tmp1 = tcg_temp_new_i32();
470 tcg_gen_andi_i32(tmp1, t1, 0xff);
471 tmp2 = tcg_const_i32(0x1f);
472 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
473 tcg_temp_free_i32(tmp2);
474 tcg_gen_sar_i32(dest, t0, tmp1);
475 tcg_temp_free_i32(tmp1);
478 static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
480 TCGv_i32 c0 = tcg_const_i32(0);
481 TCGv_i32 tmp = tcg_temp_new_i32();
482 tcg_gen_neg_i32(tmp, src);
483 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
484 tcg_temp_free_i32(c0);
485 tcg_temp_free_i32(tmp);
488 static void shifter_out_im(TCGv_i32 var, int shift)
490 if (shift == 0) {
491 tcg_gen_andi_i32(cpu_CF, var, 1);
492 } else {
493 tcg_gen_shri_i32(cpu_CF, var, shift);
494 if (shift != 31) {
495 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
500 /* Shift by immediate. Includes special handling for shift == 0. */
501 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
502 int shift, int flags)
504 switch (shiftop) {
505 case 0: /* LSL */
506 if (shift != 0) {
507 if (flags)
508 shifter_out_im(var, 32 - shift);
509 tcg_gen_shli_i32(var, var, shift);
511 break;
512 case 1: /* LSR */
513 if (shift == 0) {
514 if (flags) {
515 tcg_gen_shri_i32(cpu_CF, var, 31);
517 tcg_gen_movi_i32(var, 0);
518 } else {
519 if (flags)
520 shifter_out_im(var, shift - 1);
521 tcg_gen_shri_i32(var, var, shift);
523 break;
524 case 2: /* ASR */
525 if (shift == 0)
526 shift = 32;
527 if (flags)
528 shifter_out_im(var, shift - 1);
529 if (shift == 32)
530 shift = 31;
531 tcg_gen_sari_i32(var, var, shift);
532 break;
533 case 3: /* ROR/RRX */
534 if (shift != 0) {
535 if (flags)
536 shifter_out_im(var, shift - 1);
537 tcg_gen_rotri_i32(var, var, shift); break;
538 } else {
539 TCGv_i32 tmp = tcg_temp_new_i32();
540 tcg_gen_shli_i32(tmp, cpu_CF, 31);
541 if (flags)
542 shifter_out_im(var, 0);
543 tcg_gen_shri_i32(var, var, 1);
544 tcg_gen_or_i32(var, var, tmp);
545 tcg_temp_free_i32(tmp);
550 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
551 TCGv_i32 shift, int flags)
553 if (flags) {
554 switch (shiftop) {
555 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
556 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
557 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
558 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
560 } else {
561 switch (shiftop) {
562 case 0:
563 gen_shl(var, var, shift);
564 break;
565 case 1:
566 gen_shr(var, var, shift);
567 break;
568 case 2:
569 gen_sar(var, var, shift);
570 break;
571 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
572 tcg_gen_rotr_i32(var, var, shift); break;
575 tcg_temp_free_i32(shift);
578 #define PAS_OP(pfx) \
579 switch (op2) { \
580 case 0: gen_pas_helper(glue(pfx,add16)); break; \
581 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
582 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
583 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
584 case 4: gen_pas_helper(glue(pfx,add8)); break; \
585 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
587 static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
589 TCGv_ptr tmp;
591 switch (op1) {
592 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
593 case 1:
594 tmp = tcg_temp_new_ptr();
595 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
596 PAS_OP(s)
597 tcg_temp_free_ptr(tmp);
598 break;
599 case 5:
600 tmp = tcg_temp_new_ptr();
601 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
602 PAS_OP(u)
603 tcg_temp_free_ptr(tmp);
604 break;
605 #undef gen_pas_helper
606 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
607 case 2:
608 PAS_OP(q);
609 break;
610 case 3:
611 PAS_OP(sh);
612 break;
613 case 6:
614 PAS_OP(uq);
615 break;
616 case 7:
617 PAS_OP(uh);
618 break;
619 #undef gen_pas_helper
622 #undef PAS_OP
624 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
625 #define PAS_OP(pfx) \
626 switch (op1) { \
627 case 0: gen_pas_helper(glue(pfx,add8)); break; \
628 case 1: gen_pas_helper(glue(pfx,add16)); break; \
629 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
630 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
631 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
632 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
634 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
636 TCGv_ptr tmp;
638 switch (op2) {
639 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
640 case 0:
641 tmp = tcg_temp_new_ptr();
642 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
643 PAS_OP(s)
644 tcg_temp_free_ptr(tmp);
645 break;
646 case 4:
647 tmp = tcg_temp_new_ptr();
648 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
649 PAS_OP(u)
650 tcg_temp_free_ptr(tmp);
651 break;
652 #undef gen_pas_helper
653 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
654 case 1:
655 PAS_OP(q);
656 break;
657 case 2:
658 PAS_OP(sh);
659 break;
660 case 5:
661 PAS_OP(uq);
662 break;
663 case 6:
664 PAS_OP(uh);
665 break;
666 #undef gen_pas_helper
669 #undef PAS_OP
672 * generate a conditional branch based on ARM condition code cc.
673 * This is common between ARM and Aarch64 targets.
675 void arm_gen_test_cc(int cc, int label)
677 TCGv_i32 tmp;
678 int inv;
680 switch (cc) {
681 case 0: /* eq: Z */
682 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
683 break;
684 case 1: /* ne: !Z */
685 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
686 break;
687 case 2: /* cs: C */
688 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label);
689 break;
690 case 3: /* cc: !C */
691 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
692 break;
693 case 4: /* mi: N */
694 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label);
695 break;
696 case 5: /* pl: !N */
697 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label);
698 break;
699 case 6: /* vs: V */
700 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label);
701 break;
702 case 7: /* vc: !V */
703 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label);
704 break;
705 case 8: /* hi: C && !Z */
706 inv = gen_new_label();
707 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv);
708 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
709 gen_set_label(inv);
710 break;
711 case 9: /* ls: !C || Z */
712 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
713 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
714 break;
715 case 10: /* ge: N == V -> N ^ V == 0 */
716 tmp = tcg_temp_new_i32();
717 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
718 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
719 tcg_temp_free_i32(tmp);
720 break;
721 case 11: /* lt: N != V -> N ^ V != 0 */
722 tmp = tcg_temp_new_i32();
723 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
724 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
725 tcg_temp_free_i32(tmp);
726 break;
727 case 12: /* gt: !Z && N == V */
728 inv = gen_new_label();
729 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv);
730 tmp = tcg_temp_new_i32();
731 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
732 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
733 tcg_temp_free_i32(tmp);
734 gen_set_label(inv);
735 break;
736 case 13: /* le: Z || N != V */
737 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
738 tmp = tcg_temp_new_i32();
739 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
740 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
741 tcg_temp_free_i32(tmp);
742 break;
743 default:
744 fprintf(stderr, "Bad condition code 0x%x\n", cc);
745 abort();
749 static const uint8_t table_logic_cc[16] = {
750 1, /* and */
751 1, /* xor */
752 0, /* sub */
753 0, /* rsb */
754 0, /* add */
755 0, /* adc */
756 0, /* sbc */
757 0, /* rsc */
758 1, /* andl */
759 1, /* xorl */
760 0, /* cmp */
761 0, /* cmn */
762 1, /* orr */
763 1, /* mov */
764 1, /* bic */
765 1, /* mvn */
768 /* Set PC and Thumb state from an immediate address. */
769 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
771 TCGv_i32 tmp;
773 s->is_jmp = DISAS_UPDATE;
774 if (s->thumb != (addr & 1)) {
775 tmp = tcg_temp_new_i32();
776 tcg_gen_movi_i32(tmp, addr & 1);
777 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
778 tcg_temp_free_i32(tmp);
780 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
783 /* Set PC and Thumb state from var. var is marked as dead. */
784 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
786 s->is_jmp = DISAS_UPDATE;
787 tcg_gen_andi_i32(cpu_R[15], var, ~1);
788 tcg_gen_andi_i32(var, var, 1);
789 store_cpu_field(var, thumb);
792 /* Variant of store_reg which uses branch&exchange logic when storing
793 to r15 in ARM architecture v7 and above. The source must be a temporary
794 and will be marked as dead. */
795 static inline void store_reg_bx(CPUARMState *env, DisasContext *s,
796 int reg, TCGv_i32 var)
798 if (reg == 15 && ENABLE_ARCH_7) {
799 gen_bx(s, var);
800 } else {
801 store_reg(s, reg, var);
805 /* Variant of store_reg which uses branch&exchange logic when storing
806 * to r15 in ARM architecture v5T and above. This is used for storing
807 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
808 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
809 static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
810 int reg, TCGv_i32 var)
812 if (reg == 15 && ENABLE_ARCH_5) {
813 gen_bx(s, var);
814 } else {
815 store_reg(s, reg, var);
819 /* Abstractions of "generate code to do a guest load/store for
820 * AArch32", where a vaddr is always 32 bits (and is zero
821 * extended if we're a 64 bit core) and data is also
822 * 32 bits unless specifically doing a 64 bit access.
823 * These functions work like tcg_gen_qemu_{ld,st}* except
824 * that the address argument is TCGv_i32 rather than TCGv.
826 #if TARGET_LONG_BITS == 32
828 #define DO_GEN_LD(SUFF, OPC) \
829 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
831 tcg_gen_qemu_ld_i32(val, addr, index, OPC); \
834 #define DO_GEN_ST(SUFF, OPC) \
835 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
837 tcg_gen_qemu_st_i32(val, addr, index, OPC); \
840 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
842 tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
845 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
847 tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
850 #else
852 #define DO_GEN_LD(SUFF, OPC) \
853 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
855 TCGv addr64 = tcg_temp_new(); \
856 tcg_gen_extu_i32_i64(addr64, addr); \
857 tcg_gen_qemu_ld_i32(val, addr64, index, OPC); \
858 tcg_temp_free(addr64); \
861 #define DO_GEN_ST(SUFF, OPC) \
862 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
864 TCGv addr64 = tcg_temp_new(); \
865 tcg_gen_extu_i32_i64(addr64, addr); \
866 tcg_gen_qemu_st_i32(val, addr64, index, OPC); \
867 tcg_temp_free(addr64); \
870 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
872 TCGv addr64 = tcg_temp_new();
873 tcg_gen_extu_i32_i64(addr64, addr);
874 tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
875 tcg_temp_free(addr64);
878 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
880 TCGv addr64 = tcg_temp_new();
881 tcg_gen_extu_i32_i64(addr64, addr);
882 tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
883 tcg_temp_free(addr64);
886 #endif
888 DO_GEN_LD(8s, MO_SB)
889 DO_GEN_LD(8u, MO_UB)
890 DO_GEN_LD(16s, MO_TESW)
891 DO_GEN_LD(16u, MO_TEUW)
892 DO_GEN_LD(32u, MO_TEUL)
893 DO_GEN_ST(8, MO_UB)
894 DO_GEN_ST(16, MO_TEUW)
895 DO_GEN_ST(32, MO_TEUL)
897 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
899 tcg_gen_movi_i32(cpu_R[15], val);
902 /* Force a TB lookup after an instruction that changes the CPU state. */
903 static inline void gen_lookup_tb(DisasContext *s)
905 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
906 s->is_jmp = DISAS_UPDATE;
909 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
910 TCGv_i32 var)
912 int val, rm, shift, shiftop;
913 TCGv_i32 offset;
915 if (!(insn & (1 << 25))) {
916 /* immediate */
917 val = insn & 0xfff;
918 if (!(insn & (1 << 23)))
919 val = -val;
920 if (val != 0)
921 tcg_gen_addi_i32(var, var, val);
922 } else {
923 /* shift/register */
924 rm = (insn) & 0xf;
925 shift = (insn >> 7) & 0x1f;
926 shiftop = (insn >> 5) & 3;
927 offset = load_reg(s, rm);
928 gen_arm_shift_im(offset, shiftop, shift, 0);
929 if (!(insn & (1 << 23)))
930 tcg_gen_sub_i32(var, var, offset);
931 else
932 tcg_gen_add_i32(var, var, offset);
933 tcg_temp_free_i32(offset);
937 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
938 int extra, TCGv_i32 var)
940 int val, rm;
941 TCGv_i32 offset;
943 if (insn & (1 << 22)) {
944 /* immediate */
945 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
946 if (!(insn & (1 << 23)))
947 val = -val;
948 val += extra;
949 if (val != 0)
950 tcg_gen_addi_i32(var, var, val);
951 } else {
952 /* register */
953 if (extra)
954 tcg_gen_addi_i32(var, var, extra);
955 rm = (insn) & 0xf;
956 offset = load_reg(s, rm);
957 if (!(insn & (1 << 23)))
958 tcg_gen_sub_i32(var, var, offset);
959 else
960 tcg_gen_add_i32(var, var, offset);
961 tcg_temp_free_i32(offset);
965 static TCGv_ptr get_fpstatus_ptr(int neon)
967 TCGv_ptr statusptr = tcg_temp_new_ptr();
968 int offset;
969 if (neon) {
970 offset = offsetof(CPUARMState, vfp.standard_fp_status);
971 } else {
972 offset = offsetof(CPUARMState, vfp.fp_status);
974 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
975 return statusptr;
978 #define VFP_OP2(name) \
979 static inline void gen_vfp_##name(int dp) \
981 TCGv_ptr fpst = get_fpstatus_ptr(0); \
982 if (dp) { \
983 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
984 } else { \
985 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
987 tcg_temp_free_ptr(fpst); \
990 VFP_OP2(add)
991 VFP_OP2(sub)
992 VFP_OP2(mul)
993 VFP_OP2(div)
995 #undef VFP_OP2
997 static inline void gen_vfp_F1_mul(int dp)
999 /* Like gen_vfp_mul() but put result in F1 */
1000 TCGv_ptr fpst = get_fpstatus_ptr(0);
1001 if (dp) {
1002 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1003 } else {
1004 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1006 tcg_temp_free_ptr(fpst);
1009 static inline void gen_vfp_F1_neg(int dp)
1011 /* Like gen_vfp_neg() but put result in F1 */
1012 if (dp) {
1013 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1014 } else {
1015 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1019 static inline void gen_vfp_abs(int dp)
1021 if (dp)
1022 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1023 else
1024 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1027 static inline void gen_vfp_neg(int dp)
1029 if (dp)
1030 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1031 else
1032 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1035 static inline void gen_vfp_sqrt(int dp)
1037 if (dp)
1038 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1039 else
1040 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1043 static inline void gen_vfp_cmp(int dp)
1045 if (dp)
1046 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1047 else
1048 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1051 static inline void gen_vfp_cmpe(int dp)
1053 if (dp)
1054 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1055 else
1056 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1059 static inline void gen_vfp_F1_ld0(int dp)
1061 if (dp)
1062 tcg_gen_movi_i64(cpu_F1d, 0);
1063 else
1064 tcg_gen_movi_i32(cpu_F1s, 0);
1067 #define VFP_GEN_ITOF(name) \
1068 static inline void gen_vfp_##name(int dp, int neon) \
1070 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1071 if (dp) { \
1072 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1073 } else { \
1074 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1076 tcg_temp_free_ptr(statusptr); \
1079 VFP_GEN_ITOF(uito)
1080 VFP_GEN_ITOF(sito)
1081 #undef VFP_GEN_ITOF
1083 #define VFP_GEN_FTOI(name) \
1084 static inline void gen_vfp_##name(int dp, int neon) \
1086 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1087 if (dp) { \
1088 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1089 } else { \
1090 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1092 tcg_temp_free_ptr(statusptr); \
1095 VFP_GEN_FTOI(toui)
1096 VFP_GEN_FTOI(touiz)
1097 VFP_GEN_FTOI(tosi)
1098 VFP_GEN_FTOI(tosiz)
1099 #undef VFP_GEN_FTOI
1101 #define VFP_GEN_FIX(name, round) \
1102 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1104 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1105 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1106 if (dp) { \
1107 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1108 statusptr); \
1109 } else { \
1110 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1111 statusptr); \
1113 tcg_temp_free_i32(tmp_shift); \
1114 tcg_temp_free_ptr(statusptr); \
1116 VFP_GEN_FIX(tosh, _round_to_zero)
1117 VFP_GEN_FIX(tosl, _round_to_zero)
1118 VFP_GEN_FIX(touh, _round_to_zero)
1119 VFP_GEN_FIX(toul, _round_to_zero)
1120 VFP_GEN_FIX(shto, )
1121 VFP_GEN_FIX(slto, )
1122 VFP_GEN_FIX(uhto, )
1123 VFP_GEN_FIX(ulto, )
1124 #undef VFP_GEN_FIX
1126 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1128 if (dp) {
1129 gen_aa32_ld64(cpu_F0d, addr, IS_USER(s));
1130 } else {
1131 gen_aa32_ld32u(cpu_F0s, addr, IS_USER(s));
1135 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1137 if (dp) {
1138 gen_aa32_st64(cpu_F0d, addr, IS_USER(s));
1139 } else {
1140 gen_aa32_st32(cpu_F0s, addr, IS_USER(s));
1144 static inline long
1145 vfp_reg_offset (int dp, int reg)
1147 if (dp)
1148 return offsetof(CPUARMState, vfp.regs[reg]);
1149 else if (reg & 1) {
1150 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1151 + offsetof(CPU_DoubleU, l.upper);
1152 } else {
1153 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1154 + offsetof(CPU_DoubleU, l.lower);
1158 /* Return the offset of a 32-bit piece of a NEON register.
1159 zero is the least significant end of the register. */
1160 static inline long
1161 neon_reg_offset (int reg, int n)
1163 int sreg;
1164 sreg = reg * 2 + n;
1165 return vfp_reg_offset(0, sreg);
1168 static TCGv_i32 neon_load_reg(int reg, int pass)
1170 TCGv_i32 tmp = tcg_temp_new_i32();
1171 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1172 return tmp;
1175 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1177 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1178 tcg_temp_free_i32(var);
1181 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1183 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1186 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1188 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1191 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1192 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1193 #define tcg_gen_st_f32 tcg_gen_st_i32
1194 #define tcg_gen_st_f64 tcg_gen_st_i64
1196 static inline void gen_mov_F0_vreg(int dp, int reg)
1198 if (dp)
1199 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1200 else
1201 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1204 static inline void gen_mov_F1_vreg(int dp, int reg)
1206 if (dp)
1207 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1208 else
1209 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1212 static inline void gen_mov_vreg_F0(int dp, int reg)
1214 if (dp)
1215 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1216 else
1217 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1220 #define ARM_CP_RW_BIT (1 << 20)
1222 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1224 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1227 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1229 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1232 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1234 TCGv_i32 var = tcg_temp_new_i32();
1235 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1236 return var;
1239 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1241 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1242 tcg_temp_free_i32(var);
1245 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1247 iwmmxt_store_reg(cpu_M0, rn);
1250 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1252 iwmmxt_load_reg(cpu_M0, rn);
1255 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1257 iwmmxt_load_reg(cpu_V1, rn);
1258 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1261 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1263 iwmmxt_load_reg(cpu_V1, rn);
1264 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1267 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1269 iwmmxt_load_reg(cpu_V1, rn);
1270 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1273 #define IWMMXT_OP(name) \
1274 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1276 iwmmxt_load_reg(cpu_V1, rn); \
1277 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1280 #define IWMMXT_OP_ENV(name) \
1281 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1283 iwmmxt_load_reg(cpu_V1, rn); \
1284 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1287 #define IWMMXT_OP_ENV_SIZE(name) \
1288 IWMMXT_OP_ENV(name##b) \
1289 IWMMXT_OP_ENV(name##w) \
1290 IWMMXT_OP_ENV(name##l)
1292 #define IWMMXT_OP_ENV1(name) \
1293 static inline void gen_op_iwmmxt_##name##_M0(void) \
1295 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1298 IWMMXT_OP(maddsq)
1299 IWMMXT_OP(madduq)
1300 IWMMXT_OP(sadb)
1301 IWMMXT_OP(sadw)
1302 IWMMXT_OP(mulslw)
1303 IWMMXT_OP(mulshw)
1304 IWMMXT_OP(mululw)
1305 IWMMXT_OP(muluhw)
1306 IWMMXT_OP(macsw)
1307 IWMMXT_OP(macuw)
1309 IWMMXT_OP_ENV_SIZE(unpackl)
1310 IWMMXT_OP_ENV_SIZE(unpackh)
1312 IWMMXT_OP_ENV1(unpacklub)
1313 IWMMXT_OP_ENV1(unpackluw)
1314 IWMMXT_OP_ENV1(unpacklul)
1315 IWMMXT_OP_ENV1(unpackhub)
1316 IWMMXT_OP_ENV1(unpackhuw)
1317 IWMMXT_OP_ENV1(unpackhul)
1318 IWMMXT_OP_ENV1(unpacklsb)
1319 IWMMXT_OP_ENV1(unpacklsw)
1320 IWMMXT_OP_ENV1(unpacklsl)
1321 IWMMXT_OP_ENV1(unpackhsb)
1322 IWMMXT_OP_ENV1(unpackhsw)
1323 IWMMXT_OP_ENV1(unpackhsl)
1325 IWMMXT_OP_ENV_SIZE(cmpeq)
1326 IWMMXT_OP_ENV_SIZE(cmpgtu)
1327 IWMMXT_OP_ENV_SIZE(cmpgts)
1329 IWMMXT_OP_ENV_SIZE(mins)
1330 IWMMXT_OP_ENV_SIZE(minu)
1331 IWMMXT_OP_ENV_SIZE(maxs)
1332 IWMMXT_OP_ENV_SIZE(maxu)
1334 IWMMXT_OP_ENV_SIZE(subn)
1335 IWMMXT_OP_ENV_SIZE(addn)
1336 IWMMXT_OP_ENV_SIZE(subu)
1337 IWMMXT_OP_ENV_SIZE(addu)
1338 IWMMXT_OP_ENV_SIZE(subs)
1339 IWMMXT_OP_ENV_SIZE(adds)
1341 IWMMXT_OP_ENV(avgb0)
1342 IWMMXT_OP_ENV(avgb1)
1343 IWMMXT_OP_ENV(avgw0)
1344 IWMMXT_OP_ENV(avgw1)
1346 IWMMXT_OP(msadb)
1348 IWMMXT_OP_ENV(packuw)
1349 IWMMXT_OP_ENV(packul)
1350 IWMMXT_OP_ENV(packuq)
1351 IWMMXT_OP_ENV(packsw)
1352 IWMMXT_OP_ENV(packsl)
1353 IWMMXT_OP_ENV(packsq)
1355 static void gen_op_iwmmxt_set_mup(void)
1357 TCGv_i32 tmp;
1358 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1359 tcg_gen_ori_i32(tmp, tmp, 2);
1360 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1363 static void gen_op_iwmmxt_set_cup(void)
1365 TCGv_i32 tmp;
1366 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1367 tcg_gen_ori_i32(tmp, tmp, 1);
1368 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1371 static void gen_op_iwmmxt_setpsr_nz(void)
1373 TCGv_i32 tmp = tcg_temp_new_i32();
1374 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1375 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1378 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1380 iwmmxt_load_reg(cpu_V1, rn);
1381 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1382 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1385 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1386 TCGv_i32 dest)
1388 int rd;
1389 uint32_t offset;
1390 TCGv_i32 tmp;
1392 rd = (insn >> 16) & 0xf;
1393 tmp = load_reg(s, rd);
1395 offset = (insn & 0xff) << ((insn >> 7) & 2);
1396 if (insn & (1 << 24)) {
1397 /* Pre indexed */
1398 if (insn & (1 << 23))
1399 tcg_gen_addi_i32(tmp, tmp, offset);
1400 else
1401 tcg_gen_addi_i32(tmp, tmp, -offset);
1402 tcg_gen_mov_i32(dest, tmp);
1403 if (insn & (1 << 21))
1404 store_reg(s, rd, tmp);
1405 else
1406 tcg_temp_free_i32(tmp);
1407 } else if (insn & (1 << 21)) {
1408 /* Post indexed */
1409 tcg_gen_mov_i32(dest, tmp);
1410 if (insn & (1 << 23))
1411 tcg_gen_addi_i32(tmp, tmp, offset);
1412 else
1413 tcg_gen_addi_i32(tmp, tmp, -offset);
1414 store_reg(s, rd, tmp);
1415 } else if (!(insn & (1 << 23)))
1416 return 1;
1417 return 0;
1420 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1422 int rd = (insn >> 0) & 0xf;
1423 TCGv_i32 tmp;
1425 if (insn & (1 << 8)) {
1426 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1427 return 1;
1428 } else {
1429 tmp = iwmmxt_load_creg(rd);
1431 } else {
1432 tmp = tcg_temp_new_i32();
1433 iwmmxt_load_reg(cpu_V0, rd);
1434 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1436 tcg_gen_andi_i32(tmp, tmp, mask);
1437 tcg_gen_mov_i32(dest, tmp);
1438 tcg_temp_free_i32(tmp);
1439 return 0;
1442 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1443 (ie. an undefined instruction). */
1444 static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
1446 int rd, wrd;
1447 int rdhi, rdlo, rd0, rd1, i;
1448 TCGv_i32 addr;
1449 TCGv_i32 tmp, tmp2, tmp3;
1451 if ((insn & 0x0e000e00) == 0x0c000000) {
1452 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1453 wrd = insn & 0xf;
1454 rdlo = (insn >> 12) & 0xf;
1455 rdhi = (insn >> 16) & 0xf;
1456 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1457 iwmmxt_load_reg(cpu_V0, wrd);
1458 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1459 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1460 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1461 } else { /* TMCRR */
1462 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1463 iwmmxt_store_reg(cpu_V0, wrd);
1464 gen_op_iwmmxt_set_mup();
1466 return 0;
1469 wrd = (insn >> 12) & 0xf;
1470 addr = tcg_temp_new_i32();
1471 if (gen_iwmmxt_address(s, insn, addr)) {
1472 tcg_temp_free_i32(addr);
1473 return 1;
1475 if (insn & ARM_CP_RW_BIT) {
1476 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1477 tmp = tcg_temp_new_i32();
1478 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1479 iwmmxt_store_creg(wrd, tmp);
1480 } else {
1481 i = 1;
1482 if (insn & (1 << 8)) {
1483 if (insn & (1 << 22)) { /* WLDRD */
1484 gen_aa32_ld64(cpu_M0, addr, IS_USER(s));
1485 i = 0;
1486 } else { /* WLDRW wRd */
1487 tmp = tcg_temp_new_i32();
1488 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1490 } else {
1491 tmp = tcg_temp_new_i32();
1492 if (insn & (1 << 22)) { /* WLDRH */
1493 gen_aa32_ld16u(tmp, addr, IS_USER(s));
1494 } else { /* WLDRB */
1495 gen_aa32_ld8u(tmp, addr, IS_USER(s));
1498 if (i) {
1499 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1500 tcg_temp_free_i32(tmp);
1502 gen_op_iwmmxt_movq_wRn_M0(wrd);
1504 } else {
1505 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1506 tmp = iwmmxt_load_creg(wrd);
1507 gen_aa32_st32(tmp, addr, IS_USER(s));
1508 } else {
1509 gen_op_iwmmxt_movq_M0_wRn(wrd);
1510 tmp = tcg_temp_new_i32();
1511 if (insn & (1 << 8)) {
1512 if (insn & (1 << 22)) { /* WSTRD */
1513 gen_aa32_st64(cpu_M0, addr, IS_USER(s));
1514 } else { /* WSTRW wRd */
1515 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1516 gen_aa32_st32(tmp, addr, IS_USER(s));
1518 } else {
1519 if (insn & (1 << 22)) { /* WSTRH */
1520 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1521 gen_aa32_st16(tmp, addr, IS_USER(s));
1522 } else { /* WSTRB */
1523 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1524 gen_aa32_st8(tmp, addr, IS_USER(s));
1528 tcg_temp_free_i32(tmp);
1530 tcg_temp_free_i32(addr);
1531 return 0;
1534 if ((insn & 0x0f000000) != 0x0e000000)
1535 return 1;
1537 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1538 case 0x000: /* WOR */
1539 wrd = (insn >> 12) & 0xf;
1540 rd0 = (insn >> 0) & 0xf;
1541 rd1 = (insn >> 16) & 0xf;
1542 gen_op_iwmmxt_movq_M0_wRn(rd0);
1543 gen_op_iwmmxt_orq_M0_wRn(rd1);
1544 gen_op_iwmmxt_setpsr_nz();
1545 gen_op_iwmmxt_movq_wRn_M0(wrd);
1546 gen_op_iwmmxt_set_mup();
1547 gen_op_iwmmxt_set_cup();
1548 break;
1549 case 0x011: /* TMCR */
1550 if (insn & 0xf)
1551 return 1;
1552 rd = (insn >> 12) & 0xf;
1553 wrd = (insn >> 16) & 0xf;
1554 switch (wrd) {
1555 case ARM_IWMMXT_wCID:
1556 case ARM_IWMMXT_wCASF:
1557 break;
1558 case ARM_IWMMXT_wCon:
1559 gen_op_iwmmxt_set_cup();
1560 /* Fall through. */
1561 case ARM_IWMMXT_wCSSF:
1562 tmp = iwmmxt_load_creg(wrd);
1563 tmp2 = load_reg(s, rd);
1564 tcg_gen_andc_i32(tmp, tmp, tmp2);
1565 tcg_temp_free_i32(tmp2);
1566 iwmmxt_store_creg(wrd, tmp);
1567 break;
1568 case ARM_IWMMXT_wCGR0:
1569 case ARM_IWMMXT_wCGR1:
1570 case ARM_IWMMXT_wCGR2:
1571 case ARM_IWMMXT_wCGR3:
1572 gen_op_iwmmxt_set_cup();
1573 tmp = load_reg(s, rd);
1574 iwmmxt_store_creg(wrd, tmp);
1575 break;
1576 default:
1577 return 1;
1579 break;
1580 case 0x100: /* WXOR */
1581 wrd = (insn >> 12) & 0xf;
1582 rd0 = (insn >> 0) & 0xf;
1583 rd1 = (insn >> 16) & 0xf;
1584 gen_op_iwmmxt_movq_M0_wRn(rd0);
1585 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1586 gen_op_iwmmxt_setpsr_nz();
1587 gen_op_iwmmxt_movq_wRn_M0(wrd);
1588 gen_op_iwmmxt_set_mup();
1589 gen_op_iwmmxt_set_cup();
1590 break;
1591 case 0x111: /* TMRC */
1592 if (insn & 0xf)
1593 return 1;
1594 rd = (insn >> 12) & 0xf;
1595 wrd = (insn >> 16) & 0xf;
1596 tmp = iwmmxt_load_creg(wrd);
1597 store_reg(s, rd, tmp);
1598 break;
1599 case 0x300: /* WANDN */
1600 wrd = (insn >> 12) & 0xf;
1601 rd0 = (insn >> 0) & 0xf;
1602 rd1 = (insn >> 16) & 0xf;
1603 gen_op_iwmmxt_movq_M0_wRn(rd0);
1604 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1605 gen_op_iwmmxt_andq_M0_wRn(rd1);
1606 gen_op_iwmmxt_setpsr_nz();
1607 gen_op_iwmmxt_movq_wRn_M0(wrd);
1608 gen_op_iwmmxt_set_mup();
1609 gen_op_iwmmxt_set_cup();
1610 break;
1611 case 0x200: /* WAND */
1612 wrd = (insn >> 12) & 0xf;
1613 rd0 = (insn >> 0) & 0xf;
1614 rd1 = (insn >> 16) & 0xf;
1615 gen_op_iwmmxt_movq_M0_wRn(rd0);
1616 gen_op_iwmmxt_andq_M0_wRn(rd1);
1617 gen_op_iwmmxt_setpsr_nz();
1618 gen_op_iwmmxt_movq_wRn_M0(wrd);
1619 gen_op_iwmmxt_set_mup();
1620 gen_op_iwmmxt_set_cup();
1621 break;
1622 case 0x810: case 0xa10: /* WMADD */
1623 wrd = (insn >> 12) & 0xf;
1624 rd0 = (insn >> 0) & 0xf;
1625 rd1 = (insn >> 16) & 0xf;
1626 gen_op_iwmmxt_movq_M0_wRn(rd0);
1627 if (insn & (1 << 21))
1628 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1629 else
1630 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1631 gen_op_iwmmxt_movq_wRn_M0(wrd);
1632 gen_op_iwmmxt_set_mup();
1633 break;
1634 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1635 wrd = (insn >> 12) & 0xf;
1636 rd0 = (insn >> 16) & 0xf;
1637 rd1 = (insn >> 0) & 0xf;
1638 gen_op_iwmmxt_movq_M0_wRn(rd0);
1639 switch ((insn >> 22) & 3) {
1640 case 0:
1641 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1642 break;
1643 case 1:
1644 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1645 break;
1646 case 2:
1647 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1648 break;
1649 case 3:
1650 return 1;
1652 gen_op_iwmmxt_movq_wRn_M0(wrd);
1653 gen_op_iwmmxt_set_mup();
1654 gen_op_iwmmxt_set_cup();
1655 break;
1656 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1657 wrd = (insn >> 12) & 0xf;
1658 rd0 = (insn >> 16) & 0xf;
1659 rd1 = (insn >> 0) & 0xf;
1660 gen_op_iwmmxt_movq_M0_wRn(rd0);
1661 switch ((insn >> 22) & 3) {
1662 case 0:
1663 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1664 break;
1665 case 1:
1666 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1667 break;
1668 case 2:
1669 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1670 break;
1671 case 3:
1672 return 1;
1674 gen_op_iwmmxt_movq_wRn_M0(wrd);
1675 gen_op_iwmmxt_set_mup();
1676 gen_op_iwmmxt_set_cup();
1677 break;
1678 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1679 wrd = (insn >> 12) & 0xf;
1680 rd0 = (insn >> 16) & 0xf;
1681 rd1 = (insn >> 0) & 0xf;
1682 gen_op_iwmmxt_movq_M0_wRn(rd0);
1683 if (insn & (1 << 22))
1684 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1685 else
1686 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1687 if (!(insn & (1 << 20)))
1688 gen_op_iwmmxt_addl_M0_wRn(wrd);
1689 gen_op_iwmmxt_movq_wRn_M0(wrd);
1690 gen_op_iwmmxt_set_mup();
1691 break;
1692 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
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 << 21)) {
1698 if (insn & (1 << 20))
1699 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1700 else
1701 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1702 } else {
1703 if (insn & (1 << 20))
1704 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1705 else
1706 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1708 gen_op_iwmmxt_movq_wRn_M0(wrd);
1709 gen_op_iwmmxt_set_mup();
1710 break;
1711 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1712 wrd = (insn >> 12) & 0xf;
1713 rd0 = (insn >> 16) & 0xf;
1714 rd1 = (insn >> 0) & 0xf;
1715 gen_op_iwmmxt_movq_M0_wRn(rd0);
1716 if (insn & (1 << 21))
1717 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1718 else
1719 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1720 if (!(insn & (1 << 20))) {
1721 iwmmxt_load_reg(cpu_V1, wrd);
1722 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1724 gen_op_iwmmxt_movq_wRn_M0(wrd);
1725 gen_op_iwmmxt_set_mup();
1726 break;
1727 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1728 wrd = (insn >> 12) & 0xf;
1729 rd0 = (insn >> 16) & 0xf;
1730 rd1 = (insn >> 0) & 0xf;
1731 gen_op_iwmmxt_movq_M0_wRn(rd0);
1732 switch ((insn >> 22) & 3) {
1733 case 0:
1734 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1735 break;
1736 case 1:
1737 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1738 break;
1739 case 2:
1740 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1741 break;
1742 case 3:
1743 return 1;
1745 gen_op_iwmmxt_movq_wRn_M0(wrd);
1746 gen_op_iwmmxt_set_mup();
1747 gen_op_iwmmxt_set_cup();
1748 break;
1749 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1750 wrd = (insn >> 12) & 0xf;
1751 rd0 = (insn >> 16) & 0xf;
1752 rd1 = (insn >> 0) & 0xf;
1753 gen_op_iwmmxt_movq_M0_wRn(rd0);
1754 if (insn & (1 << 22)) {
1755 if (insn & (1 << 20))
1756 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1757 else
1758 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1759 } else {
1760 if (insn & (1 << 20))
1761 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1762 else
1763 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1765 gen_op_iwmmxt_movq_wRn_M0(wrd);
1766 gen_op_iwmmxt_set_mup();
1767 gen_op_iwmmxt_set_cup();
1768 break;
1769 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1770 wrd = (insn >> 12) & 0xf;
1771 rd0 = (insn >> 16) & 0xf;
1772 rd1 = (insn >> 0) & 0xf;
1773 gen_op_iwmmxt_movq_M0_wRn(rd0);
1774 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1775 tcg_gen_andi_i32(tmp, tmp, 7);
1776 iwmmxt_load_reg(cpu_V1, rd1);
1777 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1778 tcg_temp_free_i32(tmp);
1779 gen_op_iwmmxt_movq_wRn_M0(wrd);
1780 gen_op_iwmmxt_set_mup();
1781 break;
1782 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1783 if (((insn >> 6) & 3) == 3)
1784 return 1;
1785 rd = (insn >> 12) & 0xf;
1786 wrd = (insn >> 16) & 0xf;
1787 tmp = load_reg(s, rd);
1788 gen_op_iwmmxt_movq_M0_wRn(wrd);
1789 switch ((insn >> 6) & 3) {
1790 case 0:
1791 tmp2 = tcg_const_i32(0xff);
1792 tmp3 = tcg_const_i32((insn & 7) << 3);
1793 break;
1794 case 1:
1795 tmp2 = tcg_const_i32(0xffff);
1796 tmp3 = tcg_const_i32((insn & 3) << 4);
1797 break;
1798 case 2:
1799 tmp2 = tcg_const_i32(0xffffffff);
1800 tmp3 = tcg_const_i32((insn & 1) << 5);
1801 break;
1802 default:
1803 TCGV_UNUSED_I32(tmp2);
1804 TCGV_UNUSED_I32(tmp3);
1806 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1807 tcg_temp_free_i32(tmp3);
1808 tcg_temp_free_i32(tmp2);
1809 tcg_temp_free_i32(tmp);
1810 gen_op_iwmmxt_movq_wRn_M0(wrd);
1811 gen_op_iwmmxt_set_mup();
1812 break;
1813 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1814 rd = (insn >> 12) & 0xf;
1815 wrd = (insn >> 16) & 0xf;
1816 if (rd == 15 || ((insn >> 22) & 3) == 3)
1817 return 1;
1818 gen_op_iwmmxt_movq_M0_wRn(wrd);
1819 tmp = tcg_temp_new_i32();
1820 switch ((insn >> 22) & 3) {
1821 case 0:
1822 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1823 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1824 if (insn & 8) {
1825 tcg_gen_ext8s_i32(tmp, tmp);
1826 } else {
1827 tcg_gen_andi_i32(tmp, tmp, 0xff);
1829 break;
1830 case 1:
1831 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1832 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1833 if (insn & 8) {
1834 tcg_gen_ext16s_i32(tmp, tmp);
1835 } else {
1836 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1838 break;
1839 case 2:
1840 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1841 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1842 break;
1844 store_reg(s, rd, tmp);
1845 break;
1846 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1847 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1848 return 1;
1849 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1850 switch ((insn >> 22) & 3) {
1851 case 0:
1852 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1853 break;
1854 case 1:
1855 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1856 break;
1857 case 2:
1858 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1859 break;
1861 tcg_gen_shli_i32(tmp, tmp, 28);
1862 gen_set_nzcv(tmp);
1863 tcg_temp_free_i32(tmp);
1864 break;
1865 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1866 if (((insn >> 6) & 3) == 3)
1867 return 1;
1868 rd = (insn >> 12) & 0xf;
1869 wrd = (insn >> 16) & 0xf;
1870 tmp = load_reg(s, rd);
1871 switch ((insn >> 6) & 3) {
1872 case 0:
1873 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1874 break;
1875 case 1:
1876 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1877 break;
1878 case 2:
1879 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1880 break;
1882 tcg_temp_free_i32(tmp);
1883 gen_op_iwmmxt_movq_wRn_M0(wrd);
1884 gen_op_iwmmxt_set_mup();
1885 break;
1886 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1887 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1888 return 1;
1889 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1890 tmp2 = tcg_temp_new_i32();
1891 tcg_gen_mov_i32(tmp2, tmp);
1892 switch ((insn >> 22) & 3) {
1893 case 0:
1894 for (i = 0; i < 7; i ++) {
1895 tcg_gen_shli_i32(tmp2, tmp2, 4);
1896 tcg_gen_and_i32(tmp, tmp, tmp2);
1898 break;
1899 case 1:
1900 for (i = 0; i < 3; i ++) {
1901 tcg_gen_shli_i32(tmp2, tmp2, 8);
1902 tcg_gen_and_i32(tmp, tmp, tmp2);
1904 break;
1905 case 2:
1906 tcg_gen_shli_i32(tmp2, tmp2, 16);
1907 tcg_gen_and_i32(tmp, tmp, tmp2);
1908 break;
1910 gen_set_nzcv(tmp);
1911 tcg_temp_free_i32(tmp2);
1912 tcg_temp_free_i32(tmp);
1913 break;
1914 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1915 wrd = (insn >> 12) & 0xf;
1916 rd0 = (insn >> 16) & 0xf;
1917 gen_op_iwmmxt_movq_M0_wRn(rd0);
1918 switch ((insn >> 22) & 3) {
1919 case 0:
1920 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1921 break;
1922 case 1:
1923 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1924 break;
1925 case 2:
1926 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1927 break;
1928 case 3:
1929 return 1;
1931 gen_op_iwmmxt_movq_wRn_M0(wrd);
1932 gen_op_iwmmxt_set_mup();
1933 break;
1934 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1935 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1936 return 1;
1937 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1938 tmp2 = tcg_temp_new_i32();
1939 tcg_gen_mov_i32(tmp2, tmp);
1940 switch ((insn >> 22) & 3) {
1941 case 0:
1942 for (i = 0; i < 7; i ++) {
1943 tcg_gen_shli_i32(tmp2, tmp2, 4);
1944 tcg_gen_or_i32(tmp, tmp, tmp2);
1946 break;
1947 case 1:
1948 for (i = 0; i < 3; i ++) {
1949 tcg_gen_shli_i32(tmp2, tmp2, 8);
1950 tcg_gen_or_i32(tmp, tmp, tmp2);
1952 break;
1953 case 2:
1954 tcg_gen_shli_i32(tmp2, tmp2, 16);
1955 tcg_gen_or_i32(tmp, tmp, tmp2);
1956 break;
1958 gen_set_nzcv(tmp);
1959 tcg_temp_free_i32(tmp2);
1960 tcg_temp_free_i32(tmp);
1961 break;
1962 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1963 rd = (insn >> 12) & 0xf;
1964 rd0 = (insn >> 16) & 0xf;
1965 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1966 return 1;
1967 gen_op_iwmmxt_movq_M0_wRn(rd0);
1968 tmp = tcg_temp_new_i32();
1969 switch ((insn >> 22) & 3) {
1970 case 0:
1971 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1972 break;
1973 case 1:
1974 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1975 break;
1976 case 2:
1977 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1978 break;
1980 store_reg(s, rd, tmp);
1981 break;
1982 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1983 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1984 wrd = (insn >> 12) & 0xf;
1985 rd0 = (insn >> 16) & 0xf;
1986 rd1 = (insn >> 0) & 0xf;
1987 gen_op_iwmmxt_movq_M0_wRn(rd0);
1988 switch ((insn >> 22) & 3) {
1989 case 0:
1990 if (insn & (1 << 21))
1991 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1992 else
1993 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1994 break;
1995 case 1:
1996 if (insn & (1 << 21))
1997 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1998 else
1999 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2000 break;
2001 case 2:
2002 if (insn & (1 << 21))
2003 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2004 else
2005 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2006 break;
2007 case 3:
2008 return 1;
2010 gen_op_iwmmxt_movq_wRn_M0(wrd);
2011 gen_op_iwmmxt_set_mup();
2012 gen_op_iwmmxt_set_cup();
2013 break;
2014 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2015 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2016 wrd = (insn >> 12) & 0xf;
2017 rd0 = (insn >> 16) & 0xf;
2018 gen_op_iwmmxt_movq_M0_wRn(rd0);
2019 switch ((insn >> 22) & 3) {
2020 case 0:
2021 if (insn & (1 << 21))
2022 gen_op_iwmmxt_unpacklsb_M0();
2023 else
2024 gen_op_iwmmxt_unpacklub_M0();
2025 break;
2026 case 1:
2027 if (insn & (1 << 21))
2028 gen_op_iwmmxt_unpacklsw_M0();
2029 else
2030 gen_op_iwmmxt_unpackluw_M0();
2031 break;
2032 case 2:
2033 if (insn & (1 << 21))
2034 gen_op_iwmmxt_unpacklsl_M0();
2035 else
2036 gen_op_iwmmxt_unpacklul_M0();
2037 break;
2038 case 3:
2039 return 1;
2041 gen_op_iwmmxt_movq_wRn_M0(wrd);
2042 gen_op_iwmmxt_set_mup();
2043 gen_op_iwmmxt_set_cup();
2044 break;
2045 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2046 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2047 wrd = (insn >> 12) & 0xf;
2048 rd0 = (insn >> 16) & 0xf;
2049 gen_op_iwmmxt_movq_M0_wRn(rd0);
2050 switch ((insn >> 22) & 3) {
2051 case 0:
2052 if (insn & (1 << 21))
2053 gen_op_iwmmxt_unpackhsb_M0();
2054 else
2055 gen_op_iwmmxt_unpackhub_M0();
2056 break;
2057 case 1:
2058 if (insn & (1 << 21))
2059 gen_op_iwmmxt_unpackhsw_M0();
2060 else
2061 gen_op_iwmmxt_unpackhuw_M0();
2062 break;
2063 case 2:
2064 if (insn & (1 << 21))
2065 gen_op_iwmmxt_unpackhsl_M0();
2066 else
2067 gen_op_iwmmxt_unpackhul_M0();
2068 break;
2069 case 3:
2070 return 1;
2072 gen_op_iwmmxt_movq_wRn_M0(wrd);
2073 gen_op_iwmmxt_set_mup();
2074 gen_op_iwmmxt_set_cup();
2075 break;
2076 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2077 case 0x214: case 0x614: case 0xa14: case 0xe14:
2078 if (((insn >> 22) & 3) == 0)
2079 return 1;
2080 wrd = (insn >> 12) & 0xf;
2081 rd0 = (insn >> 16) & 0xf;
2082 gen_op_iwmmxt_movq_M0_wRn(rd0);
2083 tmp = tcg_temp_new_i32();
2084 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2085 tcg_temp_free_i32(tmp);
2086 return 1;
2088 switch ((insn >> 22) & 3) {
2089 case 1:
2090 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2091 break;
2092 case 2:
2093 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2094 break;
2095 case 3:
2096 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2097 break;
2099 tcg_temp_free_i32(tmp);
2100 gen_op_iwmmxt_movq_wRn_M0(wrd);
2101 gen_op_iwmmxt_set_mup();
2102 gen_op_iwmmxt_set_cup();
2103 break;
2104 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2105 case 0x014: case 0x414: case 0x814: case 0xc14:
2106 if (((insn >> 22) & 3) == 0)
2107 return 1;
2108 wrd = (insn >> 12) & 0xf;
2109 rd0 = (insn >> 16) & 0xf;
2110 gen_op_iwmmxt_movq_M0_wRn(rd0);
2111 tmp = tcg_temp_new_i32();
2112 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2113 tcg_temp_free_i32(tmp);
2114 return 1;
2116 switch ((insn >> 22) & 3) {
2117 case 1:
2118 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2119 break;
2120 case 2:
2121 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2122 break;
2123 case 3:
2124 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2125 break;
2127 tcg_temp_free_i32(tmp);
2128 gen_op_iwmmxt_movq_wRn_M0(wrd);
2129 gen_op_iwmmxt_set_mup();
2130 gen_op_iwmmxt_set_cup();
2131 break;
2132 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2133 case 0x114: case 0x514: case 0x914: case 0xd14:
2134 if (((insn >> 22) & 3) == 0)
2135 return 1;
2136 wrd = (insn >> 12) & 0xf;
2137 rd0 = (insn >> 16) & 0xf;
2138 gen_op_iwmmxt_movq_M0_wRn(rd0);
2139 tmp = tcg_temp_new_i32();
2140 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2141 tcg_temp_free_i32(tmp);
2142 return 1;
2144 switch ((insn >> 22) & 3) {
2145 case 1:
2146 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2147 break;
2148 case 2:
2149 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2150 break;
2151 case 3:
2152 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2153 break;
2155 tcg_temp_free_i32(tmp);
2156 gen_op_iwmmxt_movq_wRn_M0(wrd);
2157 gen_op_iwmmxt_set_mup();
2158 gen_op_iwmmxt_set_cup();
2159 break;
2160 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2161 case 0x314: case 0x714: case 0xb14: case 0xf14:
2162 if (((insn >> 22) & 3) == 0)
2163 return 1;
2164 wrd = (insn >> 12) & 0xf;
2165 rd0 = (insn >> 16) & 0xf;
2166 gen_op_iwmmxt_movq_M0_wRn(rd0);
2167 tmp = tcg_temp_new_i32();
2168 switch ((insn >> 22) & 3) {
2169 case 1:
2170 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2171 tcg_temp_free_i32(tmp);
2172 return 1;
2174 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2175 break;
2176 case 2:
2177 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2178 tcg_temp_free_i32(tmp);
2179 return 1;
2181 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2182 break;
2183 case 3:
2184 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2185 tcg_temp_free_i32(tmp);
2186 return 1;
2188 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2189 break;
2191 tcg_temp_free_i32(tmp);
2192 gen_op_iwmmxt_movq_wRn_M0(wrd);
2193 gen_op_iwmmxt_set_mup();
2194 gen_op_iwmmxt_set_cup();
2195 break;
2196 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2197 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2198 wrd = (insn >> 12) & 0xf;
2199 rd0 = (insn >> 16) & 0xf;
2200 rd1 = (insn >> 0) & 0xf;
2201 gen_op_iwmmxt_movq_M0_wRn(rd0);
2202 switch ((insn >> 22) & 3) {
2203 case 0:
2204 if (insn & (1 << 21))
2205 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2206 else
2207 gen_op_iwmmxt_minub_M0_wRn(rd1);
2208 break;
2209 case 1:
2210 if (insn & (1 << 21))
2211 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2212 else
2213 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2214 break;
2215 case 2:
2216 if (insn & (1 << 21))
2217 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2218 else
2219 gen_op_iwmmxt_minul_M0_wRn(rd1);
2220 break;
2221 case 3:
2222 return 1;
2224 gen_op_iwmmxt_movq_wRn_M0(wrd);
2225 gen_op_iwmmxt_set_mup();
2226 break;
2227 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2228 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2229 wrd = (insn >> 12) & 0xf;
2230 rd0 = (insn >> 16) & 0xf;
2231 rd1 = (insn >> 0) & 0xf;
2232 gen_op_iwmmxt_movq_M0_wRn(rd0);
2233 switch ((insn >> 22) & 3) {
2234 case 0:
2235 if (insn & (1 << 21))
2236 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2237 else
2238 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2239 break;
2240 case 1:
2241 if (insn & (1 << 21))
2242 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2243 else
2244 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2245 break;
2246 case 2:
2247 if (insn & (1 << 21))
2248 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2249 else
2250 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2251 break;
2252 case 3:
2253 return 1;
2255 gen_op_iwmmxt_movq_wRn_M0(wrd);
2256 gen_op_iwmmxt_set_mup();
2257 break;
2258 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2259 case 0x402: case 0x502: case 0x602: case 0x702:
2260 wrd = (insn >> 12) & 0xf;
2261 rd0 = (insn >> 16) & 0xf;
2262 rd1 = (insn >> 0) & 0xf;
2263 gen_op_iwmmxt_movq_M0_wRn(rd0);
2264 tmp = tcg_const_i32((insn >> 20) & 3);
2265 iwmmxt_load_reg(cpu_V1, rd1);
2266 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2267 tcg_temp_free_i32(tmp);
2268 gen_op_iwmmxt_movq_wRn_M0(wrd);
2269 gen_op_iwmmxt_set_mup();
2270 break;
2271 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2272 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2273 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2274 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
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) {
2280 case 0x0:
2281 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2282 break;
2283 case 0x1:
2284 gen_op_iwmmxt_subub_M0_wRn(rd1);
2285 break;
2286 case 0x3:
2287 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2288 break;
2289 case 0x4:
2290 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2291 break;
2292 case 0x5:
2293 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2294 break;
2295 case 0x7:
2296 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2297 break;
2298 case 0x8:
2299 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2300 break;
2301 case 0x9:
2302 gen_op_iwmmxt_subul_M0_wRn(rd1);
2303 break;
2304 case 0xb:
2305 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2306 break;
2307 default:
2308 return 1;
2310 gen_op_iwmmxt_movq_wRn_M0(wrd);
2311 gen_op_iwmmxt_set_mup();
2312 gen_op_iwmmxt_set_cup();
2313 break;
2314 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2315 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2316 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2317 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2318 wrd = (insn >> 12) & 0xf;
2319 rd0 = (insn >> 16) & 0xf;
2320 gen_op_iwmmxt_movq_M0_wRn(rd0);
2321 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2322 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2323 tcg_temp_free_i32(tmp);
2324 gen_op_iwmmxt_movq_wRn_M0(wrd);
2325 gen_op_iwmmxt_set_mup();
2326 gen_op_iwmmxt_set_cup();
2327 break;
2328 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2329 case 0x418: case 0x518: case 0x618: case 0x718:
2330 case 0x818: case 0x918: case 0xa18: case 0xb18:
2331 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2332 wrd = (insn >> 12) & 0xf;
2333 rd0 = (insn >> 16) & 0xf;
2334 rd1 = (insn >> 0) & 0xf;
2335 gen_op_iwmmxt_movq_M0_wRn(rd0);
2336 switch ((insn >> 20) & 0xf) {
2337 case 0x0:
2338 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2339 break;
2340 case 0x1:
2341 gen_op_iwmmxt_addub_M0_wRn(rd1);
2342 break;
2343 case 0x3:
2344 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2345 break;
2346 case 0x4:
2347 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2348 break;
2349 case 0x5:
2350 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2351 break;
2352 case 0x7:
2353 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2354 break;
2355 case 0x8:
2356 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2357 break;
2358 case 0x9:
2359 gen_op_iwmmxt_addul_M0_wRn(rd1);
2360 break;
2361 case 0xb:
2362 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2363 break;
2364 default:
2365 return 1;
2367 gen_op_iwmmxt_movq_wRn_M0(wrd);
2368 gen_op_iwmmxt_set_mup();
2369 gen_op_iwmmxt_set_cup();
2370 break;
2371 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2372 case 0x408: case 0x508: case 0x608: case 0x708:
2373 case 0x808: case 0x908: case 0xa08: case 0xb08:
2374 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2375 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2376 return 1;
2377 wrd = (insn >> 12) & 0xf;
2378 rd0 = (insn >> 16) & 0xf;
2379 rd1 = (insn >> 0) & 0xf;
2380 gen_op_iwmmxt_movq_M0_wRn(rd0);
2381 switch ((insn >> 22) & 3) {
2382 case 1:
2383 if (insn & (1 << 21))
2384 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2385 else
2386 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2387 break;
2388 case 2:
2389 if (insn & (1 << 21))
2390 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2391 else
2392 gen_op_iwmmxt_packul_M0_wRn(rd1);
2393 break;
2394 case 3:
2395 if (insn & (1 << 21))
2396 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2397 else
2398 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2399 break;
2401 gen_op_iwmmxt_movq_wRn_M0(wrd);
2402 gen_op_iwmmxt_set_mup();
2403 gen_op_iwmmxt_set_cup();
2404 break;
2405 case 0x201: case 0x203: case 0x205: case 0x207:
2406 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2407 case 0x211: case 0x213: case 0x215: case 0x217:
2408 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2409 wrd = (insn >> 5) & 0xf;
2410 rd0 = (insn >> 12) & 0xf;
2411 rd1 = (insn >> 0) & 0xf;
2412 if (rd0 == 0xf || rd1 == 0xf)
2413 return 1;
2414 gen_op_iwmmxt_movq_M0_wRn(wrd);
2415 tmp = load_reg(s, rd0);
2416 tmp2 = load_reg(s, rd1);
2417 switch ((insn >> 16) & 0xf) {
2418 case 0x0: /* TMIA */
2419 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2420 break;
2421 case 0x8: /* TMIAPH */
2422 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2423 break;
2424 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2425 if (insn & (1 << 16))
2426 tcg_gen_shri_i32(tmp, tmp, 16);
2427 if (insn & (1 << 17))
2428 tcg_gen_shri_i32(tmp2, tmp2, 16);
2429 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2430 break;
2431 default:
2432 tcg_temp_free_i32(tmp2);
2433 tcg_temp_free_i32(tmp);
2434 return 1;
2436 tcg_temp_free_i32(tmp2);
2437 tcg_temp_free_i32(tmp);
2438 gen_op_iwmmxt_movq_wRn_M0(wrd);
2439 gen_op_iwmmxt_set_mup();
2440 break;
2441 default:
2442 return 1;
2445 return 0;
2448 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2449 (ie. an undefined instruction). */
2450 static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2452 int acc, rd0, rd1, rdhi, rdlo;
2453 TCGv_i32 tmp, tmp2;
2455 if ((insn & 0x0ff00f10) == 0x0e200010) {
2456 /* Multiply with Internal Accumulate Format */
2457 rd0 = (insn >> 12) & 0xf;
2458 rd1 = insn & 0xf;
2459 acc = (insn >> 5) & 7;
2461 if (acc != 0)
2462 return 1;
2464 tmp = load_reg(s, rd0);
2465 tmp2 = load_reg(s, rd1);
2466 switch ((insn >> 16) & 0xf) {
2467 case 0x0: /* MIA */
2468 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2469 break;
2470 case 0x8: /* MIAPH */
2471 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2472 break;
2473 case 0xc: /* MIABB */
2474 case 0xd: /* MIABT */
2475 case 0xe: /* MIATB */
2476 case 0xf: /* MIATT */
2477 if (insn & (1 << 16))
2478 tcg_gen_shri_i32(tmp, tmp, 16);
2479 if (insn & (1 << 17))
2480 tcg_gen_shri_i32(tmp2, tmp2, 16);
2481 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2482 break;
2483 default:
2484 return 1;
2486 tcg_temp_free_i32(tmp2);
2487 tcg_temp_free_i32(tmp);
2489 gen_op_iwmmxt_movq_wRn_M0(acc);
2490 return 0;
2493 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2494 /* Internal Accumulator Access Format */
2495 rdhi = (insn >> 16) & 0xf;
2496 rdlo = (insn >> 12) & 0xf;
2497 acc = insn & 7;
2499 if (acc != 0)
2500 return 1;
2502 if (insn & ARM_CP_RW_BIT) { /* MRA */
2503 iwmmxt_load_reg(cpu_V0, acc);
2504 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2505 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2506 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2507 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2508 } else { /* MAR */
2509 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2510 iwmmxt_store_reg(cpu_V0, acc);
2512 return 0;
2515 return 1;
2518 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2519 #define VFP_SREG(insn, bigbit, smallbit) \
2520 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2521 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2522 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2523 reg = (((insn) >> (bigbit)) & 0x0f) \
2524 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2525 } else { \
2526 if (insn & (1 << (smallbit))) \
2527 return 1; \
2528 reg = ((insn) >> (bigbit)) & 0x0f; \
2529 }} while (0)
2531 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2532 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2533 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2534 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2535 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2536 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2538 /* Move between integer and VFP cores. */
2539 static TCGv_i32 gen_vfp_mrs(void)
2541 TCGv_i32 tmp = tcg_temp_new_i32();
2542 tcg_gen_mov_i32(tmp, cpu_F0s);
2543 return tmp;
2546 static void gen_vfp_msr(TCGv_i32 tmp)
2548 tcg_gen_mov_i32(cpu_F0s, tmp);
2549 tcg_temp_free_i32(tmp);
2552 static void gen_neon_dup_u8(TCGv_i32 var, int shift)
2554 TCGv_i32 tmp = tcg_temp_new_i32();
2555 if (shift)
2556 tcg_gen_shri_i32(var, var, shift);
2557 tcg_gen_ext8u_i32(var, var);
2558 tcg_gen_shli_i32(tmp, var, 8);
2559 tcg_gen_or_i32(var, var, tmp);
2560 tcg_gen_shli_i32(tmp, var, 16);
2561 tcg_gen_or_i32(var, var, tmp);
2562 tcg_temp_free_i32(tmp);
2565 static void gen_neon_dup_low16(TCGv_i32 var)
2567 TCGv_i32 tmp = tcg_temp_new_i32();
2568 tcg_gen_ext16u_i32(var, var);
2569 tcg_gen_shli_i32(tmp, var, 16);
2570 tcg_gen_or_i32(var, var, tmp);
2571 tcg_temp_free_i32(tmp);
2574 static void gen_neon_dup_high16(TCGv_i32 var)
2576 TCGv_i32 tmp = tcg_temp_new_i32();
2577 tcg_gen_andi_i32(var, var, 0xffff0000);
2578 tcg_gen_shri_i32(tmp, var, 16);
2579 tcg_gen_or_i32(var, var, tmp);
2580 tcg_temp_free_i32(tmp);
2583 static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
2585 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2586 TCGv_i32 tmp = tcg_temp_new_i32();
2587 switch (size) {
2588 case 0:
2589 gen_aa32_ld8u(tmp, addr, IS_USER(s));
2590 gen_neon_dup_u8(tmp, 0);
2591 break;
2592 case 1:
2593 gen_aa32_ld16u(tmp, addr, IS_USER(s));
2594 gen_neon_dup_low16(tmp);
2595 break;
2596 case 2:
2597 gen_aa32_ld32u(tmp, addr, IS_USER(s));
2598 break;
2599 default: /* Avoid compiler warnings. */
2600 abort();
2602 return tmp;
2605 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2606 uint32_t dp)
2608 uint32_t cc = extract32(insn, 20, 2);
2610 if (dp) {
2611 TCGv_i64 frn, frm, dest;
2612 TCGv_i64 tmp, zero, zf, nf, vf;
2614 zero = tcg_const_i64(0);
2616 frn = tcg_temp_new_i64();
2617 frm = tcg_temp_new_i64();
2618 dest = tcg_temp_new_i64();
2620 zf = tcg_temp_new_i64();
2621 nf = tcg_temp_new_i64();
2622 vf = tcg_temp_new_i64();
2624 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2625 tcg_gen_ext_i32_i64(nf, cpu_NF);
2626 tcg_gen_ext_i32_i64(vf, cpu_VF);
2628 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2629 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2630 switch (cc) {
2631 case 0: /* eq: Z */
2632 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2633 frn, frm);
2634 break;
2635 case 1: /* vs: V */
2636 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2637 frn, frm);
2638 break;
2639 case 2: /* ge: N == V -> N ^ V == 0 */
2640 tmp = tcg_temp_new_i64();
2641 tcg_gen_xor_i64(tmp, vf, nf);
2642 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2643 frn, frm);
2644 tcg_temp_free_i64(tmp);
2645 break;
2646 case 3: /* gt: !Z && N == V */
2647 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2648 frn, frm);
2649 tmp = tcg_temp_new_i64();
2650 tcg_gen_xor_i64(tmp, vf, nf);
2651 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2652 dest, frm);
2653 tcg_temp_free_i64(tmp);
2654 break;
2656 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2657 tcg_temp_free_i64(frn);
2658 tcg_temp_free_i64(frm);
2659 tcg_temp_free_i64(dest);
2661 tcg_temp_free_i64(zf);
2662 tcg_temp_free_i64(nf);
2663 tcg_temp_free_i64(vf);
2665 tcg_temp_free_i64(zero);
2666 } else {
2667 TCGv_i32 frn, frm, dest;
2668 TCGv_i32 tmp, zero;
2670 zero = tcg_const_i32(0);
2672 frn = tcg_temp_new_i32();
2673 frm = tcg_temp_new_i32();
2674 dest = tcg_temp_new_i32();
2675 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2676 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2677 switch (cc) {
2678 case 0: /* eq: Z */
2679 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2680 frn, frm);
2681 break;
2682 case 1: /* vs: V */
2683 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2684 frn, frm);
2685 break;
2686 case 2: /* ge: N == V -> N ^ V == 0 */
2687 tmp = tcg_temp_new_i32();
2688 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2689 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2690 frn, frm);
2691 tcg_temp_free_i32(tmp);
2692 break;
2693 case 3: /* gt: !Z && N == V */
2694 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2695 frn, frm);
2696 tmp = tcg_temp_new_i32();
2697 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2698 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2699 dest, frm);
2700 tcg_temp_free_i32(tmp);
2701 break;
2703 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2704 tcg_temp_free_i32(frn);
2705 tcg_temp_free_i32(frm);
2706 tcg_temp_free_i32(dest);
2708 tcg_temp_free_i32(zero);
2711 return 0;
2714 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2715 uint32_t rm, uint32_t dp)
2717 uint32_t vmin = extract32(insn, 6, 1);
2718 TCGv_ptr fpst = get_fpstatus_ptr(0);
2720 if (dp) {
2721 TCGv_i64 frn, frm, dest;
2723 frn = tcg_temp_new_i64();
2724 frm = tcg_temp_new_i64();
2725 dest = tcg_temp_new_i64();
2727 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2728 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2729 if (vmin) {
2730 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
2731 } else {
2732 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
2734 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2735 tcg_temp_free_i64(frn);
2736 tcg_temp_free_i64(frm);
2737 tcg_temp_free_i64(dest);
2738 } else {
2739 TCGv_i32 frn, frm, dest;
2741 frn = tcg_temp_new_i32();
2742 frm = tcg_temp_new_i32();
2743 dest = tcg_temp_new_i32();
2745 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2746 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2747 if (vmin) {
2748 gen_helper_vfp_minnums(dest, frn, frm, fpst);
2749 } else {
2750 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
2752 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2753 tcg_temp_free_i32(frn);
2754 tcg_temp_free_i32(frm);
2755 tcg_temp_free_i32(dest);
2758 tcg_temp_free_ptr(fpst);
2759 return 0;
2762 static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2763 int rounding)
2765 TCGv_ptr fpst = get_fpstatus_ptr(0);
2766 TCGv_i32 tcg_rmode;
2768 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2769 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2771 if (dp) {
2772 TCGv_i64 tcg_op;
2773 TCGv_i64 tcg_res;
2774 tcg_op = tcg_temp_new_i64();
2775 tcg_res = tcg_temp_new_i64();
2776 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2777 gen_helper_rintd(tcg_res, tcg_op, fpst);
2778 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2779 tcg_temp_free_i64(tcg_op);
2780 tcg_temp_free_i64(tcg_res);
2781 } else {
2782 TCGv_i32 tcg_op;
2783 TCGv_i32 tcg_res;
2784 tcg_op = tcg_temp_new_i32();
2785 tcg_res = tcg_temp_new_i32();
2786 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2787 gen_helper_rints(tcg_res, tcg_op, fpst);
2788 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2789 tcg_temp_free_i32(tcg_op);
2790 tcg_temp_free_i32(tcg_res);
2793 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2794 tcg_temp_free_i32(tcg_rmode);
2796 tcg_temp_free_ptr(fpst);
2797 return 0;
2800 static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2801 int rounding)
2803 bool is_signed = extract32(insn, 7, 1);
2804 TCGv_ptr fpst = get_fpstatus_ptr(0);
2805 TCGv_i32 tcg_rmode, tcg_shift;
2807 tcg_shift = tcg_const_i32(0);
2809 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2810 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2812 if (dp) {
2813 TCGv_i64 tcg_double, tcg_res;
2814 TCGv_i32 tcg_tmp;
2815 /* Rd is encoded as a single precision register even when the source
2816 * is double precision.
2818 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
2819 tcg_double = tcg_temp_new_i64();
2820 tcg_res = tcg_temp_new_i64();
2821 tcg_tmp = tcg_temp_new_i32();
2822 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
2823 if (is_signed) {
2824 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
2825 } else {
2826 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
2828 tcg_gen_trunc_i64_i32(tcg_tmp, tcg_res);
2829 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
2830 tcg_temp_free_i32(tcg_tmp);
2831 tcg_temp_free_i64(tcg_res);
2832 tcg_temp_free_i64(tcg_double);
2833 } else {
2834 TCGv_i32 tcg_single, tcg_res;
2835 tcg_single = tcg_temp_new_i32();
2836 tcg_res = tcg_temp_new_i32();
2837 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
2838 if (is_signed) {
2839 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
2840 } else {
2841 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
2843 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
2844 tcg_temp_free_i32(tcg_res);
2845 tcg_temp_free_i32(tcg_single);
2848 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2849 tcg_temp_free_i32(tcg_rmode);
2851 tcg_temp_free_i32(tcg_shift);
2853 tcg_temp_free_ptr(fpst);
2855 return 0;
2858 /* Table for converting the most common AArch32 encoding of
2859 * rounding mode to arm_fprounding order (which matches the
2860 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
2862 static const uint8_t fp_decode_rm[] = {
2863 FPROUNDING_TIEAWAY,
2864 FPROUNDING_TIEEVEN,
2865 FPROUNDING_POSINF,
2866 FPROUNDING_NEGINF,
2869 static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2871 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
2873 if (!arm_feature(env, ARM_FEATURE_V8)) {
2874 return 1;
2877 if (dp) {
2878 VFP_DREG_D(rd, insn);
2879 VFP_DREG_N(rn, insn);
2880 VFP_DREG_M(rm, insn);
2881 } else {
2882 rd = VFP_SREG_D(insn);
2883 rn = VFP_SREG_N(insn);
2884 rm = VFP_SREG_M(insn);
2887 if ((insn & 0x0f800e50) == 0x0e000a00) {
2888 return handle_vsel(insn, rd, rn, rm, dp);
2889 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
2890 return handle_vminmaxnm(insn, rd, rn, rm, dp);
2891 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
2892 /* VRINTA, VRINTN, VRINTP, VRINTM */
2893 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2894 return handle_vrint(insn, rd, rm, dp, rounding);
2895 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
2896 /* VCVTA, VCVTN, VCVTP, VCVTM */
2897 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2898 return handle_vcvt(insn, rd, rm, dp, rounding);
2900 return 1;
2903 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2904 (ie. an undefined instruction). */
2905 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
2907 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2908 int dp, veclen;
2909 TCGv_i32 addr;
2910 TCGv_i32 tmp;
2911 TCGv_i32 tmp2;
2913 if (!arm_feature(env, ARM_FEATURE_VFP))
2914 return 1;
2916 if (!s->vfp_enabled) {
2917 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2918 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2919 return 1;
2920 rn = (insn >> 16) & 0xf;
2921 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2922 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2923 return 1;
2926 if (extract32(insn, 28, 4) == 0xf) {
2927 /* Encodings with T=1 (Thumb) or unconditional (ARM):
2928 * only used in v8 and above.
2930 return disas_vfp_v8_insn(env, s, insn);
2933 dp = ((insn & 0xf00) == 0xb00);
2934 switch ((insn >> 24) & 0xf) {
2935 case 0xe:
2936 if (insn & (1 << 4)) {
2937 /* single register transfer */
2938 rd = (insn >> 12) & 0xf;
2939 if (dp) {
2940 int size;
2941 int pass;
2943 VFP_DREG_N(rn, insn);
2944 if (insn & 0xf)
2945 return 1;
2946 if (insn & 0x00c00060
2947 && !arm_feature(env, ARM_FEATURE_NEON))
2948 return 1;
2950 pass = (insn >> 21) & 1;
2951 if (insn & (1 << 22)) {
2952 size = 0;
2953 offset = ((insn >> 5) & 3) * 8;
2954 } else if (insn & (1 << 5)) {
2955 size = 1;
2956 offset = (insn & (1 << 6)) ? 16 : 0;
2957 } else {
2958 size = 2;
2959 offset = 0;
2961 if (insn & ARM_CP_RW_BIT) {
2962 /* vfp->arm */
2963 tmp = neon_load_reg(rn, pass);
2964 switch (size) {
2965 case 0:
2966 if (offset)
2967 tcg_gen_shri_i32(tmp, tmp, offset);
2968 if (insn & (1 << 23))
2969 gen_uxtb(tmp);
2970 else
2971 gen_sxtb(tmp);
2972 break;
2973 case 1:
2974 if (insn & (1 << 23)) {
2975 if (offset) {
2976 tcg_gen_shri_i32(tmp, tmp, 16);
2977 } else {
2978 gen_uxth(tmp);
2980 } else {
2981 if (offset) {
2982 tcg_gen_sari_i32(tmp, tmp, 16);
2983 } else {
2984 gen_sxth(tmp);
2987 break;
2988 case 2:
2989 break;
2991 store_reg(s, rd, tmp);
2992 } else {
2993 /* arm->vfp */
2994 tmp = load_reg(s, rd);
2995 if (insn & (1 << 23)) {
2996 /* VDUP */
2997 if (size == 0) {
2998 gen_neon_dup_u8(tmp, 0);
2999 } else if (size == 1) {
3000 gen_neon_dup_low16(tmp);
3002 for (n = 0; n <= pass * 2; n++) {
3003 tmp2 = tcg_temp_new_i32();
3004 tcg_gen_mov_i32(tmp2, tmp);
3005 neon_store_reg(rn, n, tmp2);
3007 neon_store_reg(rn, n, tmp);
3008 } else {
3009 /* VMOV */
3010 switch (size) {
3011 case 0:
3012 tmp2 = neon_load_reg(rn, pass);
3013 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
3014 tcg_temp_free_i32(tmp2);
3015 break;
3016 case 1:
3017 tmp2 = neon_load_reg(rn, pass);
3018 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
3019 tcg_temp_free_i32(tmp2);
3020 break;
3021 case 2:
3022 break;
3024 neon_store_reg(rn, pass, tmp);
3027 } else { /* !dp */
3028 if ((insn & 0x6f) != 0x00)
3029 return 1;
3030 rn = VFP_SREG_N(insn);
3031 if (insn & ARM_CP_RW_BIT) {
3032 /* vfp->arm */
3033 if (insn & (1 << 21)) {
3034 /* system register */
3035 rn >>= 1;
3037 switch (rn) {
3038 case ARM_VFP_FPSID:
3039 /* VFP2 allows access to FSID from userspace.
3040 VFP3 restricts all id registers to privileged
3041 accesses. */
3042 if (IS_USER(s)
3043 && arm_feature(env, ARM_FEATURE_VFP3))
3044 return 1;
3045 tmp = load_cpu_field(vfp.xregs[rn]);
3046 break;
3047 case ARM_VFP_FPEXC:
3048 if (IS_USER(s))
3049 return 1;
3050 tmp = load_cpu_field(vfp.xregs[rn]);
3051 break;
3052 case ARM_VFP_FPINST:
3053 case ARM_VFP_FPINST2:
3054 /* Not present in VFP3. */
3055 if (IS_USER(s)
3056 || arm_feature(env, ARM_FEATURE_VFP3))
3057 return 1;
3058 tmp = load_cpu_field(vfp.xregs[rn]);
3059 break;
3060 case ARM_VFP_FPSCR:
3061 if (rd == 15) {
3062 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3063 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3064 } else {
3065 tmp = tcg_temp_new_i32();
3066 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3068 break;
3069 case ARM_VFP_MVFR0:
3070 case ARM_VFP_MVFR1:
3071 if (IS_USER(s)
3072 || !arm_feature(env, ARM_FEATURE_MVFR))
3073 return 1;
3074 tmp = load_cpu_field(vfp.xregs[rn]);
3075 break;
3076 default:
3077 return 1;
3079 } else {
3080 gen_mov_F0_vreg(0, rn);
3081 tmp = gen_vfp_mrs();
3083 if (rd == 15) {
3084 /* Set the 4 flag bits in the CPSR. */
3085 gen_set_nzcv(tmp);
3086 tcg_temp_free_i32(tmp);
3087 } else {
3088 store_reg(s, rd, tmp);
3090 } else {
3091 /* arm->vfp */
3092 if (insn & (1 << 21)) {
3093 rn >>= 1;
3094 /* system register */
3095 switch (rn) {
3096 case ARM_VFP_FPSID:
3097 case ARM_VFP_MVFR0:
3098 case ARM_VFP_MVFR1:
3099 /* Writes are ignored. */
3100 break;
3101 case ARM_VFP_FPSCR:
3102 tmp = load_reg(s, rd);
3103 gen_helper_vfp_set_fpscr(cpu_env, tmp);
3104 tcg_temp_free_i32(tmp);
3105 gen_lookup_tb(s);
3106 break;
3107 case ARM_VFP_FPEXC:
3108 if (IS_USER(s))
3109 return 1;
3110 /* TODO: VFP subarchitecture support.
3111 * For now, keep the EN bit only */
3112 tmp = load_reg(s, rd);
3113 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3114 store_cpu_field(tmp, vfp.xregs[rn]);
3115 gen_lookup_tb(s);
3116 break;
3117 case ARM_VFP_FPINST:
3118 case ARM_VFP_FPINST2:
3119 tmp = load_reg(s, rd);
3120 store_cpu_field(tmp, vfp.xregs[rn]);
3121 break;
3122 default:
3123 return 1;
3125 } else {
3126 tmp = load_reg(s, rd);
3127 gen_vfp_msr(tmp);
3128 gen_mov_vreg_F0(0, rn);
3132 } else {
3133 /* data processing */
3134 /* The opcode is in bits 23, 21, 20 and 6. */
3135 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3136 if (dp) {
3137 if (op == 15) {
3138 /* rn is opcode */
3139 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3140 } else {
3141 /* rn is register number */
3142 VFP_DREG_N(rn, insn);
3145 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
3146 ((rn & 0x1e) == 0x6))) {
3147 /* Integer or single/half precision destination. */
3148 rd = VFP_SREG_D(insn);
3149 } else {
3150 VFP_DREG_D(rd, insn);
3152 if (op == 15 &&
3153 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
3154 ((rn & 0x1e) == 0x4))) {
3155 /* VCVT from int or half precision is always from S reg
3156 * regardless of dp bit. VCVT with immediate frac_bits
3157 * has same format as SREG_M.
3159 rm = VFP_SREG_M(insn);
3160 } else {
3161 VFP_DREG_M(rm, insn);
3163 } else {
3164 rn = VFP_SREG_N(insn);
3165 if (op == 15 && rn == 15) {
3166 /* Double precision destination. */
3167 VFP_DREG_D(rd, insn);
3168 } else {
3169 rd = VFP_SREG_D(insn);
3171 /* NB that we implicitly rely on the encoding for the frac_bits
3172 * in VCVT of fixed to float being the same as that of an SREG_M
3174 rm = VFP_SREG_M(insn);
3177 veclen = s->vec_len;
3178 if (op == 15 && rn > 3)
3179 veclen = 0;
3181 /* Shut up compiler warnings. */
3182 delta_m = 0;
3183 delta_d = 0;
3184 bank_mask = 0;
3186 if (veclen > 0) {
3187 if (dp)
3188 bank_mask = 0xc;
3189 else
3190 bank_mask = 0x18;
3192 /* Figure out what type of vector operation this is. */
3193 if ((rd & bank_mask) == 0) {
3194 /* scalar */
3195 veclen = 0;
3196 } else {
3197 if (dp)
3198 delta_d = (s->vec_stride >> 1) + 1;
3199 else
3200 delta_d = s->vec_stride + 1;
3202 if ((rm & bank_mask) == 0) {
3203 /* mixed scalar/vector */
3204 delta_m = 0;
3205 } else {
3206 /* vector */
3207 delta_m = delta_d;
3212 /* Load the initial operands. */
3213 if (op == 15) {
3214 switch (rn) {
3215 case 16:
3216 case 17:
3217 /* Integer source */
3218 gen_mov_F0_vreg(0, rm);
3219 break;
3220 case 8:
3221 case 9:
3222 /* Compare */
3223 gen_mov_F0_vreg(dp, rd);
3224 gen_mov_F1_vreg(dp, rm);
3225 break;
3226 case 10:
3227 case 11:
3228 /* Compare with zero */
3229 gen_mov_F0_vreg(dp, rd);
3230 gen_vfp_F1_ld0(dp);
3231 break;
3232 case 20:
3233 case 21:
3234 case 22:
3235 case 23:
3236 case 28:
3237 case 29:
3238 case 30:
3239 case 31:
3240 /* Source and destination the same. */
3241 gen_mov_F0_vreg(dp, rd);
3242 break;
3243 case 4:
3244 case 5:
3245 case 6:
3246 case 7:
3247 /* VCVTB, VCVTT: only present with the halfprec extension
3248 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3249 * (we choose to UNDEF)
3251 if ((dp && !arm_feature(env, ARM_FEATURE_V8)) ||
3252 !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3253 return 1;
3255 if (!extract32(rn, 1, 1)) {
3256 /* Half precision source. */
3257 gen_mov_F0_vreg(0, rm);
3258 break;
3260 /* Otherwise fall through */
3261 default:
3262 /* One source operand. */
3263 gen_mov_F0_vreg(dp, rm);
3264 break;
3266 } else {
3267 /* Two source operands. */
3268 gen_mov_F0_vreg(dp, rn);
3269 gen_mov_F1_vreg(dp, rm);
3272 for (;;) {
3273 /* Perform the calculation. */
3274 switch (op) {
3275 case 0: /* VMLA: fd + (fn * fm) */
3276 /* Note that order of inputs to the add matters for NaNs */
3277 gen_vfp_F1_mul(dp);
3278 gen_mov_F0_vreg(dp, rd);
3279 gen_vfp_add(dp);
3280 break;
3281 case 1: /* VMLS: fd + -(fn * fm) */
3282 gen_vfp_mul(dp);
3283 gen_vfp_F1_neg(dp);
3284 gen_mov_F0_vreg(dp, rd);
3285 gen_vfp_add(dp);
3286 break;
3287 case 2: /* VNMLS: -fd + (fn * fm) */
3288 /* Note that it isn't valid to replace (-A + B) with (B - A)
3289 * or similar plausible looking simplifications
3290 * because this will give wrong results for NaNs.
3292 gen_vfp_F1_mul(dp);
3293 gen_mov_F0_vreg(dp, rd);
3294 gen_vfp_neg(dp);
3295 gen_vfp_add(dp);
3296 break;
3297 case 3: /* VNMLA: -fd + -(fn * fm) */
3298 gen_vfp_mul(dp);
3299 gen_vfp_F1_neg(dp);
3300 gen_mov_F0_vreg(dp, rd);
3301 gen_vfp_neg(dp);
3302 gen_vfp_add(dp);
3303 break;
3304 case 4: /* mul: fn * fm */
3305 gen_vfp_mul(dp);
3306 break;
3307 case 5: /* nmul: -(fn * fm) */
3308 gen_vfp_mul(dp);
3309 gen_vfp_neg(dp);
3310 break;
3311 case 6: /* add: fn + fm */
3312 gen_vfp_add(dp);
3313 break;
3314 case 7: /* sub: fn - fm */
3315 gen_vfp_sub(dp);
3316 break;
3317 case 8: /* div: fn / fm */
3318 gen_vfp_div(dp);
3319 break;
3320 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3321 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3322 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3323 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3324 /* These are fused multiply-add, and must be done as one
3325 * floating point operation with no rounding between the
3326 * multiplication and addition steps.
3327 * NB that doing the negations here as separate steps is
3328 * correct : an input NaN should come out with its sign bit
3329 * flipped if it is a negated-input.
3331 if (!arm_feature(env, ARM_FEATURE_VFP4)) {
3332 return 1;
3334 if (dp) {
3335 TCGv_ptr fpst;
3336 TCGv_i64 frd;
3337 if (op & 1) {
3338 /* VFNMS, VFMS */
3339 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3341 frd = tcg_temp_new_i64();
3342 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3343 if (op & 2) {
3344 /* VFNMA, VFNMS */
3345 gen_helper_vfp_negd(frd, frd);
3347 fpst = get_fpstatus_ptr(0);
3348 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3349 cpu_F1d, frd, fpst);
3350 tcg_temp_free_ptr(fpst);
3351 tcg_temp_free_i64(frd);
3352 } else {
3353 TCGv_ptr fpst;
3354 TCGv_i32 frd;
3355 if (op & 1) {
3356 /* VFNMS, VFMS */
3357 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3359 frd = tcg_temp_new_i32();
3360 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3361 if (op & 2) {
3362 gen_helper_vfp_negs(frd, frd);
3364 fpst = get_fpstatus_ptr(0);
3365 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3366 cpu_F1s, frd, fpst);
3367 tcg_temp_free_ptr(fpst);
3368 tcg_temp_free_i32(frd);
3370 break;
3371 case 14: /* fconst */
3372 if (!arm_feature(env, ARM_FEATURE_VFP3))
3373 return 1;
3375 n = (insn << 12) & 0x80000000;
3376 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3377 if (dp) {
3378 if (i & 0x40)
3379 i |= 0x3f80;
3380 else
3381 i |= 0x4000;
3382 n |= i << 16;
3383 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3384 } else {
3385 if (i & 0x40)
3386 i |= 0x780;
3387 else
3388 i |= 0x800;
3389 n |= i << 19;
3390 tcg_gen_movi_i32(cpu_F0s, n);
3392 break;
3393 case 15: /* extension space */
3394 switch (rn) {
3395 case 0: /* cpy */
3396 /* no-op */
3397 break;
3398 case 1: /* abs */
3399 gen_vfp_abs(dp);
3400 break;
3401 case 2: /* neg */
3402 gen_vfp_neg(dp);
3403 break;
3404 case 3: /* sqrt */
3405 gen_vfp_sqrt(dp);
3406 break;
3407 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
3408 tmp = gen_vfp_mrs();
3409 tcg_gen_ext16u_i32(tmp, tmp);
3410 if (dp) {
3411 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3412 cpu_env);
3413 } else {
3414 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3415 cpu_env);
3417 tcg_temp_free_i32(tmp);
3418 break;
3419 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
3420 tmp = gen_vfp_mrs();
3421 tcg_gen_shri_i32(tmp, tmp, 16);
3422 if (dp) {
3423 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3424 cpu_env);
3425 } else {
3426 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3427 cpu_env);
3429 tcg_temp_free_i32(tmp);
3430 break;
3431 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3432 tmp = tcg_temp_new_i32();
3433 if (dp) {
3434 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3435 cpu_env);
3436 } else {
3437 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3438 cpu_env);
3440 gen_mov_F0_vreg(0, rd);
3441 tmp2 = gen_vfp_mrs();
3442 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3443 tcg_gen_or_i32(tmp, tmp, tmp2);
3444 tcg_temp_free_i32(tmp2);
3445 gen_vfp_msr(tmp);
3446 break;
3447 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3448 tmp = tcg_temp_new_i32();
3449 if (dp) {
3450 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3451 cpu_env);
3452 } else {
3453 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3454 cpu_env);
3456 tcg_gen_shli_i32(tmp, tmp, 16);
3457 gen_mov_F0_vreg(0, rd);
3458 tmp2 = gen_vfp_mrs();
3459 tcg_gen_ext16u_i32(tmp2, tmp2);
3460 tcg_gen_or_i32(tmp, tmp, tmp2);
3461 tcg_temp_free_i32(tmp2);
3462 gen_vfp_msr(tmp);
3463 break;
3464 case 8: /* cmp */
3465 gen_vfp_cmp(dp);
3466 break;
3467 case 9: /* cmpe */
3468 gen_vfp_cmpe(dp);
3469 break;
3470 case 10: /* cmpz */
3471 gen_vfp_cmp(dp);
3472 break;
3473 case 11: /* cmpez */
3474 gen_vfp_F1_ld0(dp);
3475 gen_vfp_cmpe(dp);
3476 break;
3477 case 12: /* vrintr */
3479 TCGv_ptr fpst = get_fpstatus_ptr(0);
3480 if (dp) {
3481 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3482 } else {
3483 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3485 tcg_temp_free_ptr(fpst);
3486 break;
3488 case 13: /* vrintz */
3490 TCGv_ptr fpst = get_fpstatus_ptr(0);
3491 TCGv_i32 tcg_rmode;
3492 tcg_rmode = tcg_const_i32(float_round_to_zero);
3493 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3494 if (dp) {
3495 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3496 } else {
3497 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3499 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3500 tcg_temp_free_i32(tcg_rmode);
3501 tcg_temp_free_ptr(fpst);
3502 break;
3504 case 14: /* vrintx */
3506 TCGv_ptr fpst = get_fpstatus_ptr(0);
3507 if (dp) {
3508 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3509 } else {
3510 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3512 tcg_temp_free_ptr(fpst);
3513 break;
3515 case 15: /* single<->double conversion */
3516 if (dp)
3517 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3518 else
3519 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3520 break;
3521 case 16: /* fuito */
3522 gen_vfp_uito(dp, 0);
3523 break;
3524 case 17: /* fsito */
3525 gen_vfp_sito(dp, 0);
3526 break;
3527 case 20: /* fshto */
3528 if (!arm_feature(env, ARM_FEATURE_VFP3))
3529 return 1;
3530 gen_vfp_shto(dp, 16 - rm, 0);
3531 break;
3532 case 21: /* fslto */
3533 if (!arm_feature(env, ARM_FEATURE_VFP3))
3534 return 1;
3535 gen_vfp_slto(dp, 32 - rm, 0);
3536 break;
3537 case 22: /* fuhto */
3538 if (!arm_feature(env, ARM_FEATURE_VFP3))
3539 return 1;
3540 gen_vfp_uhto(dp, 16 - rm, 0);
3541 break;
3542 case 23: /* fulto */
3543 if (!arm_feature(env, ARM_FEATURE_VFP3))
3544 return 1;
3545 gen_vfp_ulto(dp, 32 - rm, 0);
3546 break;
3547 case 24: /* ftoui */
3548 gen_vfp_toui(dp, 0);
3549 break;
3550 case 25: /* ftouiz */
3551 gen_vfp_touiz(dp, 0);
3552 break;
3553 case 26: /* ftosi */
3554 gen_vfp_tosi(dp, 0);
3555 break;
3556 case 27: /* ftosiz */
3557 gen_vfp_tosiz(dp, 0);
3558 break;
3559 case 28: /* ftosh */
3560 if (!arm_feature(env, ARM_FEATURE_VFP3))
3561 return 1;
3562 gen_vfp_tosh(dp, 16 - rm, 0);
3563 break;
3564 case 29: /* ftosl */
3565 if (!arm_feature(env, ARM_FEATURE_VFP3))
3566 return 1;
3567 gen_vfp_tosl(dp, 32 - rm, 0);
3568 break;
3569 case 30: /* ftouh */
3570 if (!arm_feature(env, ARM_FEATURE_VFP3))
3571 return 1;
3572 gen_vfp_touh(dp, 16 - rm, 0);
3573 break;
3574 case 31: /* ftoul */
3575 if (!arm_feature(env, ARM_FEATURE_VFP3))
3576 return 1;
3577 gen_vfp_toul(dp, 32 - rm, 0);
3578 break;
3579 default: /* undefined */
3580 return 1;
3582 break;
3583 default: /* undefined */
3584 return 1;
3587 /* Write back the result. */
3588 if (op == 15 && (rn >= 8 && rn <= 11)) {
3589 /* Comparison, do nothing. */
3590 } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
3591 (rn & 0x1e) == 0x6)) {
3592 /* VCVT double to int: always integer result.
3593 * VCVT double to half precision is always a single
3594 * precision result.
3596 gen_mov_vreg_F0(0, rd);
3597 } else if (op == 15 && rn == 15) {
3598 /* conversion */
3599 gen_mov_vreg_F0(!dp, rd);
3600 } else {
3601 gen_mov_vreg_F0(dp, rd);
3604 /* break out of the loop if we have finished */
3605 if (veclen == 0)
3606 break;
3608 if (op == 15 && delta_m == 0) {
3609 /* single source one-many */
3610 while (veclen--) {
3611 rd = ((rd + delta_d) & (bank_mask - 1))
3612 | (rd & bank_mask);
3613 gen_mov_vreg_F0(dp, rd);
3615 break;
3617 /* Setup the next operands. */
3618 veclen--;
3619 rd = ((rd + delta_d) & (bank_mask - 1))
3620 | (rd & bank_mask);
3622 if (op == 15) {
3623 /* One source operand. */
3624 rm = ((rm + delta_m) & (bank_mask - 1))
3625 | (rm & bank_mask);
3626 gen_mov_F0_vreg(dp, rm);
3627 } else {
3628 /* Two source operands. */
3629 rn = ((rn + delta_d) & (bank_mask - 1))
3630 | (rn & bank_mask);
3631 gen_mov_F0_vreg(dp, rn);
3632 if (delta_m) {
3633 rm = ((rm + delta_m) & (bank_mask - 1))
3634 | (rm & bank_mask);
3635 gen_mov_F1_vreg(dp, rm);
3640 break;
3641 case 0xc:
3642 case 0xd:
3643 if ((insn & 0x03e00000) == 0x00400000) {
3644 /* two-register transfer */
3645 rn = (insn >> 16) & 0xf;
3646 rd = (insn >> 12) & 0xf;
3647 if (dp) {
3648 VFP_DREG_M(rm, insn);
3649 } else {
3650 rm = VFP_SREG_M(insn);
3653 if (insn & ARM_CP_RW_BIT) {
3654 /* vfp->arm */
3655 if (dp) {
3656 gen_mov_F0_vreg(0, rm * 2);
3657 tmp = gen_vfp_mrs();
3658 store_reg(s, rd, tmp);
3659 gen_mov_F0_vreg(0, rm * 2 + 1);
3660 tmp = gen_vfp_mrs();
3661 store_reg(s, rn, tmp);
3662 } else {
3663 gen_mov_F0_vreg(0, rm);
3664 tmp = gen_vfp_mrs();
3665 store_reg(s, rd, tmp);
3666 gen_mov_F0_vreg(0, rm + 1);
3667 tmp = gen_vfp_mrs();
3668 store_reg(s, rn, tmp);
3670 } else {
3671 /* arm->vfp */
3672 if (dp) {
3673 tmp = load_reg(s, rd);
3674 gen_vfp_msr(tmp);
3675 gen_mov_vreg_F0(0, rm * 2);
3676 tmp = load_reg(s, rn);
3677 gen_vfp_msr(tmp);
3678 gen_mov_vreg_F0(0, rm * 2 + 1);
3679 } else {
3680 tmp = load_reg(s, rd);
3681 gen_vfp_msr(tmp);
3682 gen_mov_vreg_F0(0, rm);
3683 tmp = load_reg(s, rn);
3684 gen_vfp_msr(tmp);
3685 gen_mov_vreg_F0(0, rm + 1);
3688 } else {
3689 /* Load/store */
3690 rn = (insn >> 16) & 0xf;
3691 if (dp)
3692 VFP_DREG_D(rd, insn);
3693 else
3694 rd = VFP_SREG_D(insn);
3695 if ((insn & 0x01200000) == 0x01000000) {
3696 /* Single load/store */
3697 offset = (insn & 0xff) << 2;
3698 if ((insn & (1 << 23)) == 0)
3699 offset = -offset;
3700 if (s->thumb && rn == 15) {
3701 /* This is actually UNPREDICTABLE */
3702 addr = tcg_temp_new_i32();
3703 tcg_gen_movi_i32(addr, s->pc & ~2);
3704 } else {
3705 addr = load_reg(s, rn);
3707 tcg_gen_addi_i32(addr, addr, offset);
3708 if (insn & (1 << 20)) {
3709 gen_vfp_ld(s, dp, addr);
3710 gen_mov_vreg_F0(dp, rd);
3711 } else {
3712 gen_mov_F0_vreg(dp, rd);
3713 gen_vfp_st(s, dp, addr);
3715 tcg_temp_free_i32(addr);
3716 } else {
3717 /* load/store multiple */
3718 int w = insn & (1 << 21);
3719 if (dp)
3720 n = (insn >> 1) & 0x7f;
3721 else
3722 n = insn & 0xff;
3724 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3725 /* P == U , W == 1 => UNDEF */
3726 return 1;
3728 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3729 /* UNPREDICTABLE cases for bad immediates: we choose to
3730 * UNDEF to avoid generating huge numbers of TCG ops
3732 return 1;
3734 if (rn == 15 && w) {
3735 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3736 return 1;
3739 if (s->thumb && rn == 15) {
3740 /* This is actually UNPREDICTABLE */
3741 addr = tcg_temp_new_i32();
3742 tcg_gen_movi_i32(addr, s->pc & ~2);
3743 } else {
3744 addr = load_reg(s, rn);
3746 if (insn & (1 << 24)) /* pre-decrement */
3747 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3749 if (dp)
3750 offset = 8;
3751 else
3752 offset = 4;
3753 for (i = 0; i < n; i++) {
3754 if (insn & ARM_CP_RW_BIT) {
3755 /* load */
3756 gen_vfp_ld(s, dp, addr);
3757 gen_mov_vreg_F0(dp, rd + i);
3758 } else {
3759 /* store */
3760 gen_mov_F0_vreg(dp, rd + i);
3761 gen_vfp_st(s, dp, addr);
3763 tcg_gen_addi_i32(addr, addr, offset);
3765 if (w) {
3766 /* writeback */
3767 if (insn & (1 << 24))
3768 offset = -offset * n;
3769 else if (dp && (insn & 1))
3770 offset = 4;
3771 else
3772 offset = 0;
3774 if (offset != 0)
3775 tcg_gen_addi_i32(addr, addr, offset);
3776 store_reg(s, rn, addr);
3777 } else {
3778 tcg_temp_free_i32(addr);
3782 break;
3783 default:
3784 /* Should never happen. */
3785 return 1;
3787 return 0;
3790 static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
3792 TranslationBlock *tb;
3794 tb = s->tb;
3795 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3796 tcg_gen_goto_tb(n);
3797 gen_set_pc_im(s, dest);
3798 tcg_gen_exit_tb((uintptr_t)tb + n);
3799 } else {
3800 gen_set_pc_im(s, dest);
3801 tcg_gen_exit_tb(0);
3805 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3807 if (unlikely(s->singlestep_enabled)) {
3808 /* An indirect jump so that we still trigger the debug exception. */
3809 if (s->thumb)
3810 dest |= 1;
3811 gen_bx_im(s, dest);
3812 } else {
3813 gen_goto_tb(s, 0, dest);
3814 s->is_jmp = DISAS_TB_JUMP;
3818 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
3820 if (x)
3821 tcg_gen_sari_i32(t0, t0, 16);
3822 else
3823 gen_sxth(t0);
3824 if (y)
3825 tcg_gen_sari_i32(t1, t1, 16);
3826 else
3827 gen_sxth(t1);
3828 tcg_gen_mul_i32(t0, t0, t1);
3831 /* Return the mask of PSR bits set by a MSR instruction. */
3832 static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
3833 uint32_t mask;
3835 mask = 0;
3836 if (flags & (1 << 0))
3837 mask |= 0xff;
3838 if (flags & (1 << 1))
3839 mask |= 0xff00;
3840 if (flags & (1 << 2))
3841 mask |= 0xff0000;
3842 if (flags & (1 << 3))
3843 mask |= 0xff000000;
3845 /* Mask out undefined bits. */
3846 mask &= ~CPSR_RESERVED;
3847 if (!arm_feature(env, ARM_FEATURE_V4T))
3848 mask &= ~CPSR_T;
3849 if (!arm_feature(env, ARM_FEATURE_V5))
3850 mask &= ~CPSR_Q; /* V5TE in reality*/
3851 if (!arm_feature(env, ARM_FEATURE_V6))
3852 mask &= ~(CPSR_E | CPSR_GE);
3853 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3854 mask &= ~CPSR_IT;
3855 /* Mask out execution state bits. */
3856 if (!spsr)
3857 mask &= ~CPSR_EXEC;
3858 /* Mask out privileged bits. */
3859 if (IS_USER(s))
3860 mask &= CPSR_USER;
3861 return mask;
3864 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3865 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
3867 TCGv_i32 tmp;
3868 if (spsr) {
3869 /* ??? This is also undefined in system mode. */
3870 if (IS_USER(s))
3871 return 1;
3873 tmp = load_cpu_field(spsr);
3874 tcg_gen_andi_i32(tmp, tmp, ~mask);
3875 tcg_gen_andi_i32(t0, t0, mask);
3876 tcg_gen_or_i32(tmp, tmp, t0);
3877 store_cpu_field(tmp, spsr);
3878 } else {
3879 gen_set_cpsr(t0, mask);
3881 tcg_temp_free_i32(t0);
3882 gen_lookup_tb(s);
3883 return 0;
3886 /* Returns nonzero if access to the PSR is not permitted. */
3887 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3889 TCGv_i32 tmp;
3890 tmp = tcg_temp_new_i32();
3891 tcg_gen_movi_i32(tmp, val);
3892 return gen_set_psr(s, mask, spsr, tmp);
3895 /* Generate an old-style exception return. Marks pc as dead. */
3896 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3898 TCGv_i32 tmp;
3899 store_reg(s, 15, pc);
3900 tmp = load_cpu_field(spsr);
3901 gen_set_cpsr(tmp, 0xffffffff);
3902 tcg_temp_free_i32(tmp);
3903 s->is_jmp = DISAS_UPDATE;
3906 /* Generate a v6 exception return. Marks both values as dead. */
3907 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
3909 gen_set_cpsr(cpsr, 0xffffffff);
3910 tcg_temp_free_i32(cpsr);
3911 store_reg(s, 15, pc);
3912 s->is_jmp = DISAS_UPDATE;
3915 static inline void
3916 gen_set_condexec (DisasContext *s)
3918 if (s->condexec_mask) {
3919 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3920 TCGv_i32 tmp = tcg_temp_new_i32();
3921 tcg_gen_movi_i32(tmp, val);
3922 store_cpu_field(tmp, condexec_bits);
3926 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3928 gen_set_condexec(s);
3929 gen_set_pc_im(s, s->pc - offset);
3930 gen_exception(excp);
3931 s->is_jmp = DISAS_JUMP;
3934 static void gen_nop_hint(DisasContext *s, int val)
3936 switch (val) {
3937 case 3: /* wfi */
3938 gen_set_pc_im(s, s->pc);
3939 s->is_jmp = DISAS_WFI;
3940 break;
3941 case 2: /* wfe */
3942 case 4: /* sev */
3943 case 5: /* sevl */
3944 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
3945 default: /* nop */
3946 break;
3950 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3952 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
3954 switch (size) {
3955 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3956 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3957 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3958 default: abort();
3962 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
3964 switch (size) {
3965 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3966 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3967 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3968 default: return;
3972 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3973 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3974 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3975 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3976 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3978 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3979 switch ((size << 1) | u) { \
3980 case 0: \
3981 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3982 break; \
3983 case 1: \
3984 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3985 break; \
3986 case 2: \
3987 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3988 break; \
3989 case 3: \
3990 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3991 break; \
3992 case 4: \
3993 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3994 break; \
3995 case 5: \
3996 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3997 break; \
3998 default: return 1; \
3999 }} while (0)
4001 #define GEN_NEON_INTEGER_OP(name) do { \
4002 switch ((size << 1) | u) { \
4003 case 0: \
4004 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4005 break; \
4006 case 1: \
4007 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4008 break; \
4009 case 2: \
4010 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4011 break; \
4012 case 3: \
4013 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4014 break; \
4015 case 4: \
4016 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4017 break; \
4018 case 5: \
4019 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4020 break; \
4021 default: return 1; \
4022 }} while (0)
4024 static TCGv_i32 neon_load_scratch(int scratch)
4026 TCGv_i32 tmp = tcg_temp_new_i32();
4027 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4028 return tmp;
4031 static void neon_store_scratch(int scratch, TCGv_i32 var)
4033 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4034 tcg_temp_free_i32(var);
4037 static inline TCGv_i32 neon_get_scalar(int size, int reg)
4039 TCGv_i32 tmp;
4040 if (size == 1) {
4041 tmp = neon_load_reg(reg & 7, reg >> 4);
4042 if (reg & 8) {
4043 gen_neon_dup_high16(tmp);
4044 } else {
4045 gen_neon_dup_low16(tmp);
4047 } else {
4048 tmp = neon_load_reg(reg & 15, reg >> 4);
4050 return tmp;
4053 static int gen_neon_unzip(int rd, int rm, int size, int q)
4055 TCGv_i32 tmp, tmp2;
4056 if (!q && size == 2) {
4057 return 1;
4059 tmp = tcg_const_i32(rd);
4060 tmp2 = tcg_const_i32(rm);
4061 if (q) {
4062 switch (size) {
4063 case 0:
4064 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
4065 break;
4066 case 1:
4067 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
4068 break;
4069 case 2:
4070 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
4071 break;
4072 default:
4073 abort();
4075 } else {
4076 switch (size) {
4077 case 0:
4078 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
4079 break;
4080 case 1:
4081 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
4082 break;
4083 default:
4084 abort();
4087 tcg_temp_free_i32(tmp);
4088 tcg_temp_free_i32(tmp2);
4089 return 0;
4092 static int gen_neon_zip(int rd, int rm, int size, int q)
4094 TCGv_i32 tmp, tmp2;
4095 if (!q && size == 2) {
4096 return 1;
4098 tmp = tcg_const_i32(rd);
4099 tmp2 = tcg_const_i32(rm);
4100 if (q) {
4101 switch (size) {
4102 case 0:
4103 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
4104 break;
4105 case 1:
4106 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
4107 break;
4108 case 2:
4109 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
4110 break;
4111 default:
4112 abort();
4114 } else {
4115 switch (size) {
4116 case 0:
4117 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
4118 break;
4119 case 1:
4120 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
4121 break;
4122 default:
4123 abort();
4126 tcg_temp_free_i32(tmp);
4127 tcg_temp_free_i32(tmp2);
4128 return 0;
4131 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
4133 TCGv_i32 rd, tmp;
4135 rd = tcg_temp_new_i32();
4136 tmp = tcg_temp_new_i32();
4138 tcg_gen_shli_i32(rd, t0, 8);
4139 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4140 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4141 tcg_gen_or_i32(rd, rd, tmp);
4143 tcg_gen_shri_i32(t1, t1, 8);
4144 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4145 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4146 tcg_gen_or_i32(t1, t1, tmp);
4147 tcg_gen_mov_i32(t0, rd);
4149 tcg_temp_free_i32(tmp);
4150 tcg_temp_free_i32(rd);
4153 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
4155 TCGv_i32 rd, tmp;
4157 rd = tcg_temp_new_i32();
4158 tmp = tcg_temp_new_i32();
4160 tcg_gen_shli_i32(rd, t0, 16);
4161 tcg_gen_andi_i32(tmp, t1, 0xffff);
4162 tcg_gen_or_i32(rd, rd, tmp);
4163 tcg_gen_shri_i32(t1, t1, 16);
4164 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4165 tcg_gen_or_i32(t1, t1, tmp);
4166 tcg_gen_mov_i32(t0, rd);
4168 tcg_temp_free_i32(tmp);
4169 tcg_temp_free_i32(rd);
4173 static struct {
4174 int nregs;
4175 int interleave;
4176 int spacing;
4177 } neon_ls_element_type[11] = {
4178 {4, 4, 1},
4179 {4, 4, 2},
4180 {4, 1, 1},
4181 {4, 2, 1},
4182 {3, 3, 1},
4183 {3, 3, 2},
4184 {3, 1, 1},
4185 {1, 1, 1},
4186 {2, 2, 1},
4187 {2, 2, 2},
4188 {2, 1, 1}
4191 /* Translate a NEON load/store element instruction. Return nonzero if the
4192 instruction is invalid. */
4193 static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4195 int rd, rn, rm;
4196 int op;
4197 int nregs;
4198 int interleave;
4199 int spacing;
4200 int stride;
4201 int size;
4202 int reg;
4203 int pass;
4204 int load;
4205 int shift;
4206 int n;
4207 TCGv_i32 addr;
4208 TCGv_i32 tmp;
4209 TCGv_i32 tmp2;
4210 TCGv_i64 tmp64;
4212 if (!s->vfp_enabled)
4213 return 1;
4214 VFP_DREG_D(rd, insn);
4215 rn = (insn >> 16) & 0xf;
4216 rm = insn & 0xf;
4217 load = (insn & (1 << 21)) != 0;
4218 if ((insn & (1 << 23)) == 0) {
4219 /* Load store all elements. */
4220 op = (insn >> 8) & 0xf;
4221 size = (insn >> 6) & 3;
4222 if (op > 10)
4223 return 1;
4224 /* Catch UNDEF cases for bad values of align field */
4225 switch (op & 0xc) {
4226 case 4:
4227 if (((insn >> 5) & 1) == 1) {
4228 return 1;
4230 break;
4231 case 8:
4232 if (((insn >> 4) & 3) == 3) {
4233 return 1;
4235 break;
4236 default:
4237 break;
4239 nregs = neon_ls_element_type[op].nregs;
4240 interleave = neon_ls_element_type[op].interleave;
4241 spacing = neon_ls_element_type[op].spacing;
4242 if (size == 3 && (interleave | spacing) != 1)
4243 return 1;
4244 addr = tcg_temp_new_i32();
4245 load_reg_var(s, addr, rn);
4246 stride = (1 << size) * interleave;
4247 for (reg = 0; reg < nregs; reg++) {
4248 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
4249 load_reg_var(s, addr, rn);
4250 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
4251 } else if (interleave == 2 && nregs == 4 && reg == 2) {
4252 load_reg_var(s, addr, rn);
4253 tcg_gen_addi_i32(addr, addr, 1 << size);
4255 if (size == 3) {
4256 tmp64 = tcg_temp_new_i64();
4257 if (load) {
4258 gen_aa32_ld64(tmp64, addr, IS_USER(s));
4259 neon_store_reg64(tmp64, rd);
4260 } else {
4261 neon_load_reg64(tmp64, rd);
4262 gen_aa32_st64(tmp64, addr, IS_USER(s));
4264 tcg_temp_free_i64(tmp64);
4265 tcg_gen_addi_i32(addr, addr, stride);
4266 } else {
4267 for (pass = 0; pass < 2; pass++) {
4268 if (size == 2) {
4269 if (load) {
4270 tmp = tcg_temp_new_i32();
4271 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4272 neon_store_reg(rd, pass, tmp);
4273 } else {
4274 tmp = neon_load_reg(rd, pass);
4275 gen_aa32_st32(tmp, addr, IS_USER(s));
4276 tcg_temp_free_i32(tmp);
4278 tcg_gen_addi_i32(addr, addr, stride);
4279 } else if (size == 1) {
4280 if (load) {
4281 tmp = tcg_temp_new_i32();
4282 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4283 tcg_gen_addi_i32(addr, addr, stride);
4284 tmp2 = tcg_temp_new_i32();
4285 gen_aa32_ld16u(tmp2, addr, IS_USER(s));
4286 tcg_gen_addi_i32(addr, addr, stride);
4287 tcg_gen_shli_i32(tmp2, tmp2, 16);
4288 tcg_gen_or_i32(tmp, tmp, tmp2);
4289 tcg_temp_free_i32(tmp2);
4290 neon_store_reg(rd, pass, tmp);
4291 } else {
4292 tmp = neon_load_reg(rd, pass);
4293 tmp2 = tcg_temp_new_i32();
4294 tcg_gen_shri_i32(tmp2, tmp, 16);
4295 gen_aa32_st16(tmp, addr, IS_USER(s));
4296 tcg_temp_free_i32(tmp);
4297 tcg_gen_addi_i32(addr, addr, stride);
4298 gen_aa32_st16(tmp2, addr, IS_USER(s));
4299 tcg_temp_free_i32(tmp2);
4300 tcg_gen_addi_i32(addr, addr, stride);
4302 } else /* size == 0 */ {
4303 if (load) {
4304 TCGV_UNUSED_I32(tmp2);
4305 for (n = 0; n < 4; n++) {
4306 tmp = tcg_temp_new_i32();
4307 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4308 tcg_gen_addi_i32(addr, addr, stride);
4309 if (n == 0) {
4310 tmp2 = tmp;
4311 } else {
4312 tcg_gen_shli_i32(tmp, tmp, n * 8);
4313 tcg_gen_or_i32(tmp2, tmp2, tmp);
4314 tcg_temp_free_i32(tmp);
4317 neon_store_reg(rd, pass, tmp2);
4318 } else {
4319 tmp2 = neon_load_reg(rd, pass);
4320 for (n = 0; n < 4; n++) {
4321 tmp = tcg_temp_new_i32();
4322 if (n == 0) {
4323 tcg_gen_mov_i32(tmp, tmp2);
4324 } else {
4325 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4327 gen_aa32_st8(tmp, addr, IS_USER(s));
4328 tcg_temp_free_i32(tmp);
4329 tcg_gen_addi_i32(addr, addr, stride);
4331 tcg_temp_free_i32(tmp2);
4336 rd += spacing;
4338 tcg_temp_free_i32(addr);
4339 stride = nregs * 8;
4340 } else {
4341 size = (insn >> 10) & 3;
4342 if (size == 3) {
4343 /* Load single element to all lanes. */
4344 int a = (insn >> 4) & 1;
4345 if (!load) {
4346 return 1;
4348 size = (insn >> 6) & 3;
4349 nregs = ((insn >> 8) & 3) + 1;
4351 if (size == 3) {
4352 if (nregs != 4 || a == 0) {
4353 return 1;
4355 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4356 size = 2;
4358 if (nregs == 1 && a == 1 && size == 0) {
4359 return 1;
4361 if (nregs == 3 && a == 1) {
4362 return 1;
4364 addr = tcg_temp_new_i32();
4365 load_reg_var(s, addr, rn);
4366 if (nregs == 1) {
4367 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4368 tmp = gen_load_and_replicate(s, addr, size);
4369 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4370 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4371 if (insn & (1 << 5)) {
4372 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4373 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4375 tcg_temp_free_i32(tmp);
4376 } else {
4377 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4378 stride = (insn & (1 << 5)) ? 2 : 1;
4379 for (reg = 0; reg < nregs; reg++) {
4380 tmp = gen_load_and_replicate(s, addr, size);
4381 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4382 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4383 tcg_temp_free_i32(tmp);
4384 tcg_gen_addi_i32(addr, addr, 1 << size);
4385 rd += stride;
4388 tcg_temp_free_i32(addr);
4389 stride = (1 << size) * nregs;
4390 } else {
4391 /* Single element. */
4392 int idx = (insn >> 4) & 0xf;
4393 pass = (insn >> 7) & 1;
4394 switch (size) {
4395 case 0:
4396 shift = ((insn >> 5) & 3) * 8;
4397 stride = 1;
4398 break;
4399 case 1:
4400 shift = ((insn >> 6) & 1) * 16;
4401 stride = (insn & (1 << 5)) ? 2 : 1;
4402 break;
4403 case 2:
4404 shift = 0;
4405 stride = (insn & (1 << 6)) ? 2 : 1;
4406 break;
4407 default:
4408 abort();
4410 nregs = ((insn >> 8) & 3) + 1;
4411 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4412 switch (nregs) {
4413 case 1:
4414 if (((idx & (1 << size)) != 0) ||
4415 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4416 return 1;
4418 break;
4419 case 3:
4420 if ((idx & 1) != 0) {
4421 return 1;
4423 /* fall through */
4424 case 2:
4425 if (size == 2 && (idx & 2) != 0) {
4426 return 1;
4428 break;
4429 case 4:
4430 if ((size == 2) && ((idx & 3) == 3)) {
4431 return 1;
4433 break;
4434 default:
4435 abort();
4437 if ((rd + stride * (nregs - 1)) > 31) {
4438 /* Attempts to write off the end of the register file
4439 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4440 * the neon_load_reg() would write off the end of the array.
4442 return 1;
4444 addr = tcg_temp_new_i32();
4445 load_reg_var(s, addr, rn);
4446 for (reg = 0; reg < nregs; reg++) {
4447 if (load) {
4448 tmp = tcg_temp_new_i32();
4449 switch (size) {
4450 case 0:
4451 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4452 break;
4453 case 1:
4454 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4455 break;
4456 case 2:
4457 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4458 break;
4459 default: /* Avoid compiler warnings. */
4460 abort();
4462 if (size != 2) {
4463 tmp2 = neon_load_reg(rd, pass);
4464 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4465 shift, size ? 16 : 8);
4466 tcg_temp_free_i32(tmp2);
4468 neon_store_reg(rd, pass, tmp);
4469 } else { /* Store */
4470 tmp = neon_load_reg(rd, pass);
4471 if (shift)
4472 tcg_gen_shri_i32(tmp, tmp, shift);
4473 switch (size) {
4474 case 0:
4475 gen_aa32_st8(tmp, addr, IS_USER(s));
4476 break;
4477 case 1:
4478 gen_aa32_st16(tmp, addr, IS_USER(s));
4479 break;
4480 case 2:
4481 gen_aa32_st32(tmp, addr, IS_USER(s));
4482 break;
4484 tcg_temp_free_i32(tmp);
4486 rd += stride;
4487 tcg_gen_addi_i32(addr, addr, 1 << size);
4489 tcg_temp_free_i32(addr);
4490 stride = nregs * (1 << size);
4493 if (rm != 15) {
4494 TCGv_i32 base;
4496 base = load_reg(s, rn);
4497 if (rm == 13) {
4498 tcg_gen_addi_i32(base, base, stride);
4499 } else {
4500 TCGv_i32 index;
4501 index = load_reg(s, rm);
4502 tcg_gen_add_i32(base, base, index);
4503 tcg_temp_free_i32(index);
4505 store_reg(s, rn, base);
4507 return 0;
4510 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4511 static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
4513 tcg_gen_and_i32(t, t, c);
4514 tcg_gen_andc_i32(f, f, c);
4515 tcg_gen_or_i32(dest, t, f);
4518 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4520 switch (size) {
4521 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4522 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4523 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4524 default: abort();
4528 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4530 switch (size) {
4531 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4532 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4533 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4534 default: abort();
4538 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
4540 switch (size) {
4541 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4542 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4543 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4544 default: abort();
4548 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4550 switch (size) {
4551 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4552 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4553 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4554 default: abort();
4558 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
4559 int q, int u)
4561 if (q) {
4562 if (u) {
4563 switch (size) {
4564 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4565 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4566 default: abort();
4568 } else {
4569 switch (size) {
4570 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4571 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4572 default: abort();
4575 } else {
4576 if (u) {
4577 switch (size) {
4578 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4579 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4580 default: abort();
4582 } else {
4583 switch (size) {
4584 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4585 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4586 default: abort();
4592 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
4594 if (u) {
4595 switch (size) {
4596 case 0: gen_helper_neon_widen_u8(dest, src); break;
4597 case 1: gen_helper_neon_widen_u16(dest, src); break;
4598 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4599 default: abort();
4601 } else {
4602 switch (size) {
4603 case 0: gen_helper_neon_widen_s8(dest, src); break;
4604 case 1: gen_helper_neon_widen_s16(dest, src); break;
4605 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4606 default: abort();
4609 tcg_temp_free_i32(src);
4612 static inline void gen_neon_addl(int size)
4614 switch (size) {
4615 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4616 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4617 case 2: tcg_gen_add_i64(CPU_V001); break;
4618 default: abort();
4622 static inline void gen_neon_subl(int size)
4624 switch (size) {
4625 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4626 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4627 case 2: tcg_gen_sub_i64(CPU_V001); break;
4628 default: abort();
4632 static inline void gen_neon_negl(TCGv_i64 var, int size)
4634 switch (size) {
4635 case 0: gen_helper_neon_negl_u16(var, var); break;
4636 case 1: gen_helper_neon_negl_u32(var, var); break;
4637 case 2:
4638 tcg_gen_neg_i64(var, var);
4639 break;
4640 default: abort();
4644 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4646 switch (size) {
4647 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4648 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4649 default: abort();
4653 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4654 int size, int u)
4656 TCGv_i64 tmp;
4658 switch ((size << 1) | u) {
4659 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4660 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4661 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4662 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4663 case 4:
4664 tmp = gen_muls_i64_i32(a, b);
4665 tcg_gen_mov_i64(dest, tmp);
4666 tcg_temp_free_i64(tmp);
4667 break;
4668 case 5:
4669 tmp = gen_mulu_i64_i32(a, b);
4670 tcg_gen_mov_i64(dest, tmp);
4671 tcg_temp_free_i64(tmp);
4672 break;
4673 default: abort();
4676 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4677 Don't forget to clean them now. */
4678 if (size < 2) {
4679 tcg_temp_free_i32(a);
4680 tcg_temp_free_i32(b);
4684 static void gen_neon_narrow_op(int op, int u, int size,
4685 TCGv_i32 dest, TCGv_i64 src)
4687 if (op) {
4688 if (u) {
4689 gen_neon_unarrow_sats(size, dest, src);
4690 } else {
4691 gen_neon_narrow(size, dest, src);
4693 } else {
4694 if (u) {
4695 gen_neon_narrow_satu(size, dest, src);
4696 } else {
4697 gen_neon_narrow_sats(size, dest, src);
4702 /* Symbolic constants for op fields for Neon 3-register same-length.
4703 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4704 * table A7-9.
4706 #define NEON_3R_VHADD 0
4707 #define NEON_3R_VQADD 1
4708 #define NEON_3R_VRHADD 2
4709 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4710 #define NEON_3R_VHSUB 4
4711 #define NEON_3R_VQSUB 5
4712 #define NEON_3R_VCGT 6
4713 #define NEON_3R_VCGE 7
4714 #define NEON_3R_VSHL 8
4715 #define NEON_3R_VQSHL 9
4716 #define NEON_3R_VRSHL 10
4717 #define NEON_3R_VQRSHL 11
4718 #define NEON_3R_VMAX 12
4719 #define NEON_3R_VMIN 13
4720 #define NEON_3R_VABD 14
4721 #define NEON_3R_VABA 15
4722 #define NEON_3R_VADD_VSUB 16
4723 #define NEON_3R_VTST_VCEQ 17
4724 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4725 #define NEON_3R_VMUL 19
4726 #define NEON_3R_VPMAX 20
4727 #define NEON_3R_VPMIN 21
4728 #define NEON_3R_VQDMULH_VQRDMULH 22
4729 #define NEON_3R_VPADD 23
4730 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4731 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4732 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4733 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4734 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4735 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4736 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
4738 static const uint8_t neon_3r_sizes[] = {
4739 [NEON_3R_VHADD] = 0x7,
4740 [NEON_3R_VQADD] = 0xf,
4741 [NEON_3R_VRHADD] = 0x7,
4742 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4743 [NEON_3R_VHSUB] = 0x7,
4744 [NEON_3R_VQSUB] = 0xf,
4745 [NEON_3R_VCGT] = 0x7,
4746 [NEON_3R_VCGE] = 0x7,
4747 [NEON_3R_VSHL] = 0xf,
4748 [NEON_3R_VQSHL] = 0xf,
4749 [NEON_3R_VRSHL] = 0xf,
4750 [NEON_3R_VQRSHL] = 0xf,
4751 [NEON_3R_VMAX] = 0x7,
4752 [NEON_3R_VMIN] = 0x7,
4753 [NEON_3R_VABD] = 0x7,
4754 [NEON_3R_VABA] = 0x7,
4755 [NEON_3R_VADD_VSUB] = 0xf,
4756 [NEON_3R_VTST_VCEQ] = 0x7,
4757 [NEON_3R_VML] = 0x7,
4758 [NEON_3R_VMUL] = 0x7,
4759 [NEON_3R_VPMAX] = 0x7,
4760 [NEON_3R_VPMIN] = 0x7,
4761 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4762 [NEON_3R_VPADD] = 0x7,
4763 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
4764 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4765 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4766 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4767 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4768 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4769 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
4772 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4773 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4774 * table A7-13.
4776 #define NEON_2RM_VREV64 0
4777 #define NEON_2RM_VREV32 1
4778 #define NEON_2RM_VREV16 2
4779 #define NEON_2RM_VPADDL 4
4780 #define NEON_2RM_VPADDL_U 5
4781 #define NEON_2RM_AESE 6 /* Includes AESD */
4782 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
4783 #define NEON_2RM_VCLS 8
4784 #define NEON_2RM_VCLZ 9
4785 #define NEON_2RM_VCNT 10
4786 #define NEON_2RM_VMVN 11
4787 #define NEON_2RM_VPADAL 12
4788 #define NEON_2RM_VPADAL_U 13
4789 #define NEON_2RM_VQABS 14
4790 #define NEON_2RM_VQNEG 15
4791 #define NEON_2RM_VCGT0 16
4792 #define NEON_2RM_VCGE0 17
4793 #define NEON_2RM_VCEQ0 18
4794 #define NEON_2RM_VCLE0 19
4795 #define NEON_2RM_VCLT0 20
4796 #define NEON_2RM_VABS 22
4797 #define NEON_2RM_VNEG 23
4798 #define NEON_2RM_VCGT0_F 24
4799 #define NEON_2RM_VCGE0_F 25
4800 #define NEON_2RM_VCEQ0_F 26
4801 #define NEON_2RM_VCLE0_F 27
4802 #define NEON_2RM_VCLT0_F 28
4803 #define NEON_2RM_VABS_F 30
4804 #define NEON_2RM_VNEG_F 31
4805 #define NEON_2RM_VSWP 32
4806 #define NEON_2RM_VTRN 33
4807 #define NEON_2RM_VUZP 34
4808 #define NEON_2RM_VZIP 35
4809 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4810 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4811 #define NEON_2RM_VSHLL 38
4812 #define NEON_2RM_VRINTN 40
4813 #define NEON_2RM_VRINTX 41
4814 #define NEON_2RM_VRINTA 42
4815 #define NEON_2RM_VRINTZ 43
4816 #define NEON_2RM_VCVT_F16_F32 44
4817 #define NEON_2RM_VRINTM 45
4818 #define NEON_2RM_VCVT_F32_F16 46
4819 #define NEON_2RM_VRINTP 47
4820 #define NEON_2RM_VCVTAU 48
4821 #define NEON_2RM_VCVTAS 49
4822 #define NEON_2RM_VCVTNU 50
4823 #define NEON_2RM_VCVTNS 51
4824 #define NEON_2RM_VCVTPU 52
4825 #define NEON_2RM_VCVTPS 53
4826 #define NEON_2RM_VCVTMU 54
4827 #define NEON_2RM_VCVTMS 55
4828 #define NEON_2RM_VRECPE 56
4829 #define NEON_2RM_VRSQRTE 57
4830 #define NEON_2RM_VRECPE_F 58
4831 #define NEON_2RM_VRSQRTE_F 59
4832 #define NEON_2RM_VCVT_FS 60
4833 #define NEON_2RM_VCVT_FU 61
4834 #define NEON_2RM_VCVT_SF 62
4835 #define NEON_2RM_VCVT_UF 63
4837 static int neon_2rm_is_float_op(int op)
4839 /* Return true if this neon 2reg-misc op is float-to-float */
4840 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4841 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
4842 op == NEON_2RM_VRINTM ||
4843 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
4844 op >= NEON_2RM_VRECPE_F);
4847 /* Each entry in this array has bit n set if the insn allows
4848 * size value n (otherwise it will UNDEF). Since unallocated
4849 * op values will have no bits set they always UNDEF.
4851 static const uint8_t neon_2rm_sizes[] = {
4852 [NEON_2RM_VREV64] = 0x7,
4853 [NEON_2RM_VREV32] = 0x3,
4854 [NEON_2RM_VREV16] = 0x1,
4855 [NEON_2RM_VPADDL] = 0x7,
4856 [NEON_2RM_VPADDL_U] = 0x7,
4857 [NEON_2RM_AESE] = 0x1,
4858 [NEON_2RM_AESMC] = 0x1,
4859 [NEON_2RM_VCLS] = 0x7,
4860 [NEON_2RM_VCLZ] = 0x7,
4861 [NEON_2RM_VCNT] = 0x1,
4862 [NEON_2RM_VMVN] = 0x1,
4863 [NEON_2RM_VPADAL] = 0x7,
4864 [NEON_2RM_VPADAL_U] = 0x7,
4865 [NEON_2RM_VQABS] = 0x7,
4866 [NEON_2RM_VQNEG] = 0x7,
4867 [NEON_2RM_VCGT0] = 0x7,
4868 [NEON_2RM_VCGE0] = 0x7,
4869 [NEON_2RM_VCEQ0] = 0x7,
4870 [NEON_2RM_VCLE0] = 0x7,
4871 [NEON_2RM_VCLT0] = 0x7,
4872 [NEON_2RM_VABS] = 0x7,
4873 [NEON_2RM_VNEG] = 0x7,
4874 [NEON_2RM_VCGT0_F] = 0x4,
4875 [NEON_2RM_VCGE0_F] = 0x4,
4876 [NEON_2RM_VCEQ0_F] = 0x4,
4877 [NEON_2RM_VCLE0_F] = 0x4,
4878 [NEON_2RM_VCLT0_F] = 0x4,
4879 [NEON_2RM_VABS_F] = 0x4,
4880 [NEON_2RM_VNEG_F] = 0x4,
4881 [NEON_2RM_VSWP] = 0x1,
4882 [NEON_2RM_VTRN] = 0x7,
4883 [NEON_2RM_VUZP] = 0x7,
4884 [NEON_2RM_VZIP] = 0x7,
4885 [NEON_2RM_VMOVN] = 0x7,
4886 [NEON_2RM_VQMOVN] = 0x7,
4887 [NEON_2RM_VSHLL] = 0x7,
4888 [NEON_2RM_VRINTN] = 0x4,
4889 [NEON_2RM_VRINTX] = 0x4,
4890 [NEON_2RM_VRINTA] = 0x4,
4891 [NEON_2RM_VRINTZ] = 0x4,
4892 [NEON_2RM_VCVT_F16_F32] = 0x2,
4893 [NEON_2RM_VRINTM] = 0x4,
4894 [NEON_2RM_VCVT_F32_F16] = 0x2,
4895 [NEON_2RM_VRINTP] = 0x4,
4896 [NEON_2RM_VCVTAU] = 0x4,
4897 [NEON_2RM_VCVTAS] = 0x4,
4898 [NEON_2RM_VCVTNU] = 0x4,
4899 [NEON_2RM_VCVTNS] = 0x4,
4900 [NEON_2RM_VCVTPU] = 0x4,
4901 [NEON_2RM_VCVTPS] = 0x4,
4902 [NEON_2RM_VCVTMU] = 0x4,
4903 [NEON_2RM_VCVTMS] = 0x4,
4904 [NEON_2RM_VRECPE] = 0x4,
4905 [NEON_2RM_VRSQRTE] = 0x4,
4906 [NEON_2RM_VRECPE_F] = 0x4,
4907 [NEON_2RM_VRSQRTE_F] = 0x4,
4908 [NEON_2RM_VCVT_FS] = 0x4,
4909 [NEON_2RM_VCVT_FU] = 0x4,
4910 [NEON_2RM_VCVT_SF] = 0x4,
4911 [NEON_2RM_VCVT_UF] = 0x4,
4914 /* Translate a NEON data processing instruction. Return nonzero if the
4915 instruction is invalid.
4916 We process data in a mixture of 32-bit and 64-bit chunks.
4917 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4919 static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4921 int op;
4922 int q;
4923 int rd, rn, rm;
4924 int size;
4925 int shift;
4926 int pass;
4927 int count;
4928 int pairwise;
4929 int u;
4930 uint32_t imm, mask;
4931 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
4932 TCGv_i64 tmp64;
4934 if (!s->vfp_enabled)
4935 return 1;
4936 q = (insn & (1 << 6)) != 0;
4937 u = (insn >> 24) & 1;
4938 VFP_DREG_D(rd, insn);
4939 VFP_DREG_N(rn, insn);
4940 VFP_DREG_M(rm, insn);
4941 size = (insn >> 20) & 3;
4942 if ((insn & (1 << 23)) == 0) {
4943 /* Three register same length. */
4944 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4945 /* Catch invalid op and bad size combinations: UNDEF */
4946 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4947 return 1;
4949 /* All insns of this form UNDEF for either this condition or the
4950 * superset of cases "Q==1"; we catch the latter later.
4952 if (q && ((rd | rn | rm) & 1)) {
4953 return 1;
4955 if (size == 3 && op != NEON_3R_LOGIC) {
4956 /* 64-bit element instructions. */
4957 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4958 neon_load_reg64(cpu_V0, rn + pass);
4959 neon_load_reg64(cpu_V1, rm + pass);
4960 switch (op) {
4961 case NEON_3R_VQADD:
4962 if (u) {
4963 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4964 cpu_V0, cpu_V1);
4965 } else {
4966 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4967 cpu_V0, cpu_V1);
4969 break;
4970 case NEON_3R_VQSUB:
4971 if (u) {
4972 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4973 cpu_V0, cpu_V1);
4974 } else {
4975 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4976 cpu_V0, cpu_V1);
4978 break;
4979 case NEON_3R_VSHL:
4980 if (u) {
4981 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4982 } else {
4983 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4985 break;
4986 case NEON_3R_VQSHL:
4987 if (u) {
4988 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4989 cpu_V1, cpu_V0);
4990 } else {
4991 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4992 cpu_V1, cpu_V0);
4994 break;
4995 case NEON_3R_VRSHL:
4996 if (u) {
4997 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4998 } else {
4999 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5001 break;
5002 case NEON_3R_VQRSHL:
5003 if (u) {
5004 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5005 cpu_V1, cpu_V0);
5006 } else {
5007 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5008 cpu_V1, cpu_V0);
5010 break;
5011 case NEON_3R_VADD_VSUB:
5012 if (u) {
5013 tcg_gen_sub_i64(CPU_V001);
5014 } else {
5015 tcg_gen_add_i64(CPU_V001);
5017 break;
5018 default:
5019 abort();
5021 neon_store_reg64(cpu_V0, rd + pass);
5023 return 0;
5025 pairwise = 0;
5026 switch (op) {
5027 case NEON_3R_VSHL:
5028 case NEON_3R_VQSHL:
5029 case NEON_3R_VRSHL:
5030 case NEON_3R_VQRSHL:
5032 int rtmp;
5033 /* Shift instruction operands are reversed. */
5034 rtmp = rn;
5035 rn = rm;
5036 rm = rtmp;
5038 break;
5039 case NEON_3R_VPADD:
5040 if (u) {
5041 return 1;
5043 /* Fall through */
5044 case NEON_3R_VPMAX:
5045 case NEON_3R_VPMIN:
5046 pairwise = 1;
5047 break;
5048 case NEON_3R_FLOAT_ARITH:
5049 pairwise = (u && size < 2); /* if VPADD (float) */
5050 break;
5051 case NEON_3R_FLOAT_MINMAX:
5052 pairwise = u; /* if VPMIN/VPMAX (float) */
5053 break;
5054 case NEON_3R_FLOAT_CMP:
5055 if (!u && size) {
5056 /* no encoding for U=0 C=1x */
5057 return 1;
5059 break;
5060 case NEON_3R_FLOAT_ACMP:
5061 if (!u) {
5062 return 1;
5064 break;
5065 case NEON_3R_FLOAT_MISC:
5066 /* VMAXNM/VMINNM in ARMv8 */
5067 if (u && !arm_feature(env, ARM_FEATURE_V8)) {
5068 return 1;
5070 break;
5071 case NEON_3R_VMUL:
5072 if (u && (size != 0)) {
5073 /* UNDEF on invalid size for polynomial subcase */
5074 return 1;
5076 break;
5077 case NEON_3R_VFM:
5078 if (!arm_feature(env, ARM_FEATURE_VFP4) || u) {
5079 return 1;
5081 break;
5082 default:
5083 break;
5086 if (pairwise && q) {
5087 /* All the pairwise insns UNDEF if Q is set */
5088 return 1;
5091 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5093 if (pairwise) {
5094 /* Pairwise. */
5095 if (pass < 1) {
5096 tmp = neon_load_reg(rn, 0);
5097 tmp2 = neon_load_reg(rn, 1);
5098 } else {
5099 tmp = neon_load_reg(rm, 0);
5100 tmp2 = neon_load_reg(rm, 1);
5102 } else {
5103 /* Elementwise. */
5104 tmp = neon_load_reg(rn, pass);
5105 tmp2 = neon_load_reg(rm, pass);
5107 switch (op) {
5108 case NEON_3R_VHADD:
5109 GEN_NEON_INTEGER_OP(hadd);
5110 break;
5111 case NEON_3R_VQADD:
5112 GEN_NEON_INTEGER_OP_ENV(qadd);
5113 break;
5114 case NEON_3R_VRHADD:
5115 GEN_NEON_INTEGER_OP(rhadd);
5116 break;
5117 case NEON_3R_LOGIC: /* Logic ops. */
5118 switch ((u << 2) | size) {
5119 case 0: /* VAND */
5120 tcg_gen_and_i32(tmp, tmp, tmp2);
5121 break;
5122 case 1: /* BIC */
5123 tcg_gen_andc_i32(tmp, tmp, tmp2);
5124 break;
5125 case 2: /* VORR */
5126 tcg_gen_or_i32(tmp, tmp, tmp2);
5127 break;
5128 case 3: /* VORN */
5129 tcg_gen_orc_i32(tmp, tmp, tmp2);
5130 break;
5131 case 4: /* VEOR */
5132 tcg_gen_xor_i32(tmp, tmp, tmp2);
5133 break;
5134 case 5: /* VBSL */
5135 tmp3 = neon_load_reg(rd, pass);
5136 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
5137 tcg_temp_free_i32(tmp3);
5138 break;
5139 case 6: /* VBIT */
5140 tmp3 = neon_load_reg(rd, pass);
5141 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
5142 tcg_temp_free_i32(tmp3);
5143 break;
5144 case 7: /* VBIF */
5145 tmp3 = neon_load_reg(rd, pass);
5146 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
5147 tcg_temp_free_i32(tmp3);
5148 break;
5150 break;
5151 case NEON_3R_VHSUB:
5152 GEN_NEON_INTEGER_OP(hsub);
5153 break;
5154 case NEON_3R_VQSUB:
5155 GEN_NEON_INTEGER_OP_ENV(qsub);
5156 break;
5157 case NEON_3R_VCGT:
5158 GEN_NEON_INTEGER_OP(cgt);
5159 break;
5160 case NEON_3R_VCGE:
5161 GEN_NEON_INTEGER_OP(cge);
5162 break;
5163 case NEON_3R_VSHL:
5164 GEN_NEON_INTEGER_OP(shl);
5165 break;
5166 case NEON_3R_VQSHL:
5167 GEN_NEON_INTEGER_OP_ENV(qshl);
5168 break;
5169 case NEON_3R_VRSHL:
5170 GEN_NEON_INTEGER_OP(rshl);
5171 break;
5172 case NEON_3R_VQRSHL:
5173 GEN_NEON_INTEGER_OP_ENV(qrshl);
5174 break;
5175 case NEON_3R_VMAX:
5176 GEN_NEON_INTEGER_OP(max);
5177 break;
5178 case NEON_3R_VMIN:
5179 GEN_NEON_INTEGER_OP(min);
5180 break;
5181 case NEON_3R_VABD:
5182 GEN_NEON_INTEGER_OP(abd);
5183 break;
5184 case NEON_3R_VABA:
5185 GEN_NEON_INTEGER_OP(abd);
5186 tcg_temp_free_i32(tmp2);
5187 tmp2 = neon_load_reg(rd, pass);
5188 gen_neon_add(size, tmp, tmp2);
5189 break;
5190 case NEON_3R_VADD_VSUB:
5191 if (!u) { /* VADD */
5192 gen_neon_add(size, tmp, tmp2);
5193 } else { /* VSUB */
5194 switch (size) {
5195 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
5196 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
5197 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
5198 default: abort();
5201 break;
5202 case NEON_3R_VTST_VCEQ:
5203 if (!u) { /* VTST */
5204 switch (size) {
5205 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
5206 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
5207 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
5208 default: abort();
5210 } else { /* VCEQ */
5211 switch (size) {
5212 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5213 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5214 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5215 default: abort();
5218 break;
5219 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
5220 switch (size) {
5221 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5222 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5223 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5224 default: abort();
5226 tcg_temp_free_i32(tmp2);
5227 tmp2 = neon_load_reg(rd, pass);
5228 if (u) { /* VMLS */
5229 gen_neon_rsb(size, tmp, tmp2);
5230 } else { /* VMLA */
5231 gen_neon_add(size, tmp, tmp2);
5233 break;
5234 case NEON_3R_VMUL:
5235 if (u) { /* polynomial */
5236 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
5237 } else { /* Integer */
5238 switch (size) {
5239 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5240 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5241 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5242 default: abort();
5245 break;
5246 case NEON_3R_VPMAX:
5247 GEN_NEON_INTEGER_OP(pmax);
5248 break;
5249 case NEON_3R_VPMIN:
5250 GEN_NEON_INTEGER_OP(pmin);
5251 break;
5252 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
5253 if (!u) { /* VQDMULH */
5254 switch (size) {
5255 case 1:
5256 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5257 break;
5258 case 2:
5259 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5260 break;
5261 default: abort();
5263 } else { /* VQRDMULH */
5264 switch (size) {
5265 case 1:
5266 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5267 break;
5268 case 2:
5269 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5270 break;
5271 default: abort();
5274 break;
5275 case NEON_3R_VPADD:
5276 switch (size) {
5277 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5278 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5279 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5280 default: abort();
5282 break;
5283 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
5285 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5286 switch ((u << 2) | size) {
5287 case 0: /* VADD */
5288 case 4: /* VPADD */
5289 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5290 break;
5291 case 2: /* VSUB */
5292 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
5293 break;
5294 case 6: /* VABD */
5295 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
5296 break;
5297 default:
5298 abort();
5300 tcg_temp_free_ptr(fpstatus);
5301 break;
5303 case NEON_3R_FLOAT_MULTIPLY:
5305 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5306 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5307 if (!u) {
5308 tcg_temp_free_i32(tmp2);
5309 tmp2 = neon_load_reg(rd, pass);
5310 if (size == 0) {
5311 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5312 } else {
5313 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5316 tcg_temp_free_ptr(fpstatus);
5317 break;
5319 case NEON_3R_FLOAT_CMP:
5321 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5322 if (!u) {
5323 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5324 } else {
5325 if (size == 0) {
5326 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5327 } else {
5328 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5331 tcg_temp_free_ptr(fpstatus);
5332 break;
5334 case NEON_3R_FLOAT_ACMP:
5336 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5337 if (size == 0) {
5338 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5339 } else {
5340 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5342 tcg_temp_free_ptr(fpstatus);
5343 break;
5345 case NEON_3R_FLOAT_MINMAX:
5347 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5348 if (size == 0) {
5349 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
5350 } else {
5351 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
5353 tcg_temp_free_ptr(fpstatus);
5354 break;
5356 case NEON_3R_FLOAT_MISC:
5357 if (u) {
5358 /* VMAXNM/VMINNM */
5359 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5360 if (size == 0) {
5361 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
5362 } else {
5363 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
5365 tcg_temp_free_ptr(fpstatus);
5366 } else {
5367 if (size == 0) {
5368 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5369 } else {
5370 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5373 break;
5374 case NEON_3R_VFM:
5376 /* VFMA, VFMS: fused multiply-add */
5377 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5378 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5379 if (size) {
5380 /* VFMS */
5381 gen_helper_vfp_negs(tmp, tmp);
5383 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5384 tcg_temp_free_i32(tmp3);
5385 tcg_temp_free_ptr(fpstatus);
5386 break;
5388 default:
5389 abort();
5391 tcg_temp_free_i32(tmp2);
5393 /* Save the result. For elementwise operations we can put it
5394 straight into the destination register. For pairwise operations
5395 we have to be careful to avoid clobbering the source operands. */
5396 if (pairwise && rd == rm) {
5397 neon_store_scratch(pass, tmp);
5398 } else {
5399 neon_store_reg(rd, pass, tmp);
5402 } /* for pass */
5403 if (pairwise && rd == rm) {
5404 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5405 tmp = neon_load_scratch(pass);
5406 neon_store_reg(rd, pass, tmp);
5409 /* End of 3 register same size operations. */
5410 } else if (insn & (1 << 4)) {
5411 if ((insn & 0x00380080) != 0) {
5412 /* Two registers and shift. */
5413 op = (insn >> 8) & 0xf;
5414 if (insn & (1 << 7)) {
5415 /* 64-bit shift. */
5416 if (op > 7) {
5417 return 1;
5419 size = 3;
5420 } else {
5421 size = 2;
5422 while ((insn & (1 << (size + 19))) == 0)
5423 size--;
5425 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5426 /* To avoid excessive duplication of ops we implement shift
5427 by immediate using the variable shift operations. */
5428 if (op < 8) {
5429 /* Shift by immediate:
5430 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5431 if (q && ((rd | rm) & 1)) {
5432 return 1;
5434 if (!u && (op == 4 || op == 6)) {
5435 return 1;
5437 /* Right shifts are encoded as N - shift, where N is the
5438 element size in bits. */
5439 if (op <= 4)
5440 shift = shift - (1 << (size + 3));
5441 if (size == 3) {
5442 count = q + 1;
5443 } else {
5444 count = q ? 4: 2;
5446 switch (size) {
5447 case 0:
5448 imm = (uint8_t) shift;
5449 imm |= imm << 8;
5450 imm |= imm << 16;
5451 break;
5452 case 1:
5453 imm = (uint16_t) shift;
5454 imm |= imm << 16;
5455 break;
5456 case 2:
5457 case 3:
5458 imm = shift;
5459 break;
5460 default:
5461 abort();
5464 for (pass = 0; pass < count; pass++) {
5465 if (size == 3) {
5466 neon_load_reg64(cpu_V0, rm + pass);
5467 tcg_gen_movi_i64(cpu_V1, imm);
5468 switch (op) {
5469 case 0: /* VSHR */
5470 case 1: /* VSRA */
5471 if (u)
5472 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5473 else
5474 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5475 break;
5476 case 2: /* VRSHR */
5477 case 3: /* VRSRA */
5478 if (u)
5479 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5480 else
5481 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5482 break;
5483 case 4: /* VSRI */
5484 case 5: /* VSHL, VSLI */
5485 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5486 break;
5487 case 6: /* VQSHLU */
5488 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5489 cpu_V0, cpu_V1);
5490 break;
5491 case 7: /* VQSHL */
5492 if (u) {
5493 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5494 cpu_V0, cpu_V1);
5495 } else {
5496 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5497 cpu_V0, cpu_V1);
5499 break;
5501 if (op == 1 || op == 3) {
5502 /* Accumulate. */
5503 neon_load_reg64(cpu_V1, rd + pass);
5504 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5505 } else if (op == 4 || (op == 5 && u)) {
5506 /* Insert */
5507 neon_load_reg64(cpu_V1, rd + pass);
5508 uint64_t mask;
5509 if (shift < -63 || shift > 63) {
5510 mask = 0;
5511 } else {
5512 if (op == 4) {
5513 mask = 0xffffffffffffffffull >> -shift;
5514 } else {
5515 mask = 0xffffffffffffffffull << shift;
5518 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5519 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5521 neon_store_reg64(cpu_V0, rd + pass);
5522 } else { /* size < 3 */
5523 /* Operands in T0 and T1. */
5524 tmp = neon_load_reg(rm, pass);
5525 tmp2 = tcg_temp_new_i32();
5526 tcg_gen_movi_i32(tmp2, imm);
5527 switch (op) {
5528 case 0: /* VSHR */
5529 case 1: /* VSRA */
5530 GEN_NEON_INTEGER_OP(shl);
5531 break;
5532 case 2: /* VRSHR */
5533 case 3: /* VRSRA */
5534 GEN_NEON_INTEGER_OP(rshl);
5535 break;
5536 case 4: /* VSRI */
5537 case 5: /* VSHL, VSLI */
5538 switch (size) {
5539 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5540 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5541 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5542 default: abort();
5544 break;
5545 case 6: /* VQSHLU */
5546 switch (size) {
5547 case 0:
5548 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5549 tmp, tmp2);
5550 break;
5551 case 1:
5552 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5553 tmp, tmp2);
5554 break;
5555 case 2:
5556 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5557 tmp, tmp2);
5558 break;
5559 default:
5560 abort();
5562 break;
5563 case 7: /* VQSHL */
5564 GEN_NEON_INTEGER_OP_ENV(qshl);
5565 break;
5567 tcg_temp_free_i32(tmp2);
5569 if (op == 1 || op == 3) {
5570 /* Accumulate. */
5571 tmp2 = neon_load_reg(rd, pass);
5572 gen_neon_add(size, tmp, tmp2);
5573 tcg_temp_free_i32(tmp2);
5574 } else if (op == 4 || (op == 5 && u)) {
5575 /* Insert */
5576 switch (size) {
5577 case 0:
5578 if (op == 4)
5579 mask = 0xff >> -shift;
5580 else
5581 mask = (uint8_t)(0xff << shift);
5582 mask |= mask << 8;
5583 mask |= mask << 16;
5584 break;
5585 case 1:
5586 if (op == 4)
5587 mask = 0xffff >> -shift;
5588 else
5589 mask = (uint16_t)(0xffff << shift);
5590 mask |= mask << 16;
5591 break;
5592 case 2:
5593 if (shift < -31 || shift > 31) {
5594 mask = 0;
5595 } else {
5596 if (op == 4)
5597 mask = 0xffffffffu >> -shift;
5598 else
5599 mask = 0xffffffffu << shift;
5601 break;
5602 default:
5603 abort();
5605 tmp2 = neon_load_reg(rd, pass);
5606 tcg_gen_andi_i32(tmp, tmp, mask);
5607 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5608 tcg_gen_or_i32(tmp, tmp, tmp2);
5609 tcg_temp_free_i32(tmp2);
5611 neon_store_reg(rd, pass, tmp);
5613 } /* for pass */
5614 } else if (op < 10) {
5615 /* Shift by immediate and narrow:
5616 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5617 int input_unsigned = (op == 8) ? !u : u;
5618 if (rm & 1) {
5619 return 1;
5621 shift = shift - (1 << (size + 3));
5622 size++;
5623 if (size == 3) {
5624 tmp64 = tcg_const_i64(shift);
5625 neon_load_reg64(cpu_V0, rm);
5626 neon_load_reg64(cpu_V1, rm + 1);
5627 for (pass = 0; pass < 2; pass++) {
5628 TCGv_i64 in;
5629 if (pass == 0) {
5630 in = cpu_V0;
5631 } else {
5632 in = cpu_V1;
5634 if (q) {
5635 if (input_unsigned) {
5636 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5637 } else {
5638 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5640 } else {
5641 if (input_unsigned) {
5642 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5643 } else {
5644 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5647 tmp = tcg_temp_new_i32();
5648 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5649 neon_store_reg(rd, pass, tmp);
5650 } /* for pass */
5651 tcg_temp_free_i64(tmp64);
5652 } else {
5653 if (size == 1) {
5654 imm = (uint16_t)shift;
5655 imm |= imm << 16;
5656 } else {
5657 /* size == 2 */
5658 imm = (uint32_t)shift;
5660 tmp2 = tcg_const_i32(imm);
5661 tmp4 = neon_load_reg(rm + 1, 0);
5662 tmp5 = neon_load_reg(rm + 1, 1);
5663 for (pass = 0; pass < 2; pass++) {
5664 if (pass == 0) {
5665 tmp = neon_load_reg(rm, 0);
5666 } else {
5667 tmp = tmp4;
5669 gen_neon_shift_narrow(size, tmp, tmp2, q,
5670 input_unsigned);
5671 if (pass == 0) {
5672 tmp3 = neon_load_reg(rm, 1);
5673 } else {
5674 tmp3 = tmp5;
5676 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5677 input_unsigned);
5678 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5679 tcg_temp_free_i32(tmp);
5680 tcg_temp_free_i32(tmp3);
5681 tmp = tcg_temp_new_i32();
5682 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5683 neon_store_reg(rd, pass, tmp);
5684 } /* for pass */
5685 tcg_temp_free_i32(tmp2);
5687 } else if (op == 10) {
5688 /* VSHLL, VMOVL */
5689 if (q || (rd & 1)) {
5690 return 1;
5692 tmp = neon_load_reg(rm, 0);
5693 tmp2 = neon_load_reg(rm, 1);
5694 for (pass = 0; pass < 2; pass++) {
5695 if (pass == 1)
5696 tmp = tmp2;
5698 gen_neon_widen(cpu_V0, tmp, size, u);
5700 if (shift != 0) {
5701 /* The shift is less than the width of the source
5702 type, so we can just shift the whole register. */
5703 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5704 /* Widen the result of shift: we need to clear
5705 * the potential overflow bits resulting from
5706 * left bits of the narrow input appearing as
5707 * right bits of left the neighbour narrow
5708 * input. */
5709 if (size < 2 || !u) {
5710 uint64_t imm64;
5711 if (size == 0) {
5712 imm = (0xffu >> (8 - shift));
5713 imm |= imm << 16;
5714 } else if (size == 1) {
5715 imm = 0xffff >> (16 - shift);
5716 } else {
5717 /* size == 2 */
5718 imm = 0xffffffff >> (32 - shift);
5720 if (size < 2) {
5721 imm64 = imm | (((uint64_t)imm) << 32);
5722 } else {
5723 imm64 = imm;
5725 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5728 neon_store_reg64(cpu_V0, rd + pass);
5730 } else if (op >= 14) {
5731 /* VCVT fixed-point. */
5732 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5733 return 1;
5735 /* We have already masked out the must-be-1 top bit of imm6,
5736 * hence this 32-shift where the ARM ARM has 64-imm6.
5738 shift = 32 - shift;
5739 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5740 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5741 if (!(op & 1)) {
5742 if (u)
5743 gen_vfp_ulto(0, shift, 1);
5744 else
5745 gen_vfp_slto(0, shift, 1);
5746 } else {
5747 if (u)
5748 gen_vfp_toul(0, shift, 1);
5749 else
5750 gen_vfp_tosl(0, shift, 1);
5752 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5754 } else {
5755 return 1;
5757 } else { /* (insn & 0x00380080) == 0 */
5758 int invert;
5759 if (q && (rd & 1)) {
5760 return 1;
5763 op = (insn >> 8) & 0xf;
5764 /* One register and immediate. */
5765 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5766 invert = (insn & (1 << 5)) != 0;
5767 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5768 * We choose to not special-case this and will behave as if a
5769 * valid constant encoding of 0 had been given.
5771 switch (op) {
5772 case 0: case 1:
5773 /* no-op */
5774 break;
5775 case 2: case 3:
5776 imm <<= 8;
5777 break;
5778 case 4: case 5:
5779 imm <<= 16;
5780 break;
5781 case 6: case 7:
5782 imm <<= 24;
5783 break;
5784 case 8: case 9:
5785 imm |= imm << 16;
5786 break;
5787 case 10: case 11:
5788 imm = (imm << 8) | (imm << 24);
5789 break;
5790 case 12:
5791 imm = (imm << 8) | 0xff;
5792 break;
5793 case 13:
5794 imm = (imm << 16) | 0xffff;
5795 break;
5796 case 14:
5797 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5798 if (invert)
5799 imm = ~imm;
5800 break;
5801 case 15:
5802 if (invert) {
5803 return 1;
5805 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5806 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5807 break;
5809 if (invert)
5810 imm = ~imm;
5812 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5813 if (op & 1 && op < 12) {
5814 tmp = neon_load_reg(rd, pass);
5815 if (invert) {
5816 /* The immediate value has already been inverted, so
5817 BIC becomes AND. */
5818 tcg_gen_andi_i32(tmp, tmp, imm);
5819 } else {
5820 tcg_gen_ori_i32(tmp, tmp, imm);
5822 } else {
5823 /* VMOV, VMVN. */
5824 tmp = tcg_temp_new_i32();
5825 if (op == 14 && invert) {
5826 int n;
5827 uint32_t val;
5828 val = 0;
5829 for (n = 0; n < 4; n++) {
5830 if (imm & (1 << (n + (pass & 1) * 4)))
5831 val |= 0xff << (n * 8);
5833 tcg_gen_movi_i32(tmp, val);
5834 } else {
5835 tcg_gen_movi_i32(tmp, imm);
5838 neon_store_reg(rd, pass, tmp);
5841 } else { /* (insn & 0x00800010 == 0x00800000) */
5842 if (size != 3) {
5843 op = (insn >> 8) & 0xf;
5844 if ((insn & (1 << 6)) == 0) {
5845 /* Three registers of different lengths. */
5846 int src1_wide;
5847 int src2_wide;
5848 int prewiden;
5849 /* undefreq: bit 0 : UNDEF if size != 0
5850 * bit 1 : UNDEF if size == 0
5851 * bit 2 : UNDEF if U == 1
5852 * Note that [1:0] set implies 'always UNDEF'
5854 int undefreq;
5855 /* prewiden, src1_wide, src2_wide, undefreq */
5856 static const int neon_3reg_wide[16][4] = {
5857 {1, 0, 0, 0}, /* VADDL */
5858 {1, 1, 0, 0}, /* VADDW */
5859 {1, 0, 0, 0}, /* VSUBL */
5860 {1, 1, 0, 0}, /* VSUBW */
5861 {0, 1, 1, 0}, /* VADDHN */
5862 {0, 0, 0, 0}, /* VABAL */
5863 {0, 1, 1, 0}, /* VSUBHN */
5864 {0, 0, 0, 0}, /* VABDL */
5865 {0, 0, 0, 0}, /* VMLAL */
5866 {0, 0, 0, 6}, /* VQDMLAL */
5867 {0, 0, 0, 0}, /* VMLSL */
5868 {0, 0, 0, 6}, /* VQDMLSL */
5869 {0, 0, 0, 0}, /* Integer VMULL */
5870 {0, 0, 0, 2}, /* VQDMULL */
5871 {0, 0, 0, 5}, /* Polynomial VMULL */
5872 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5875 prewiden = neon_3reg_wide[op][0];
5876 src1_wide = neon_3reg_wide[op][1];
5877 src2_wide = neon_3reg_wide[op][2];
5878 undefreq = neon_3reg_wide[op][3];
5880 if (((undefreq & 1) && (size != 0)) ||
5881 ((undefreq & 2) && (size == 0)) ||
5882 ((undefreq & 4) && u)) {
5883 return 1;
5885 if ((src1_wide && (rn & 1)) ||
5886 (src2_wide && (rm & 1)) ||
5887 (!src2_wide && (rd & 1))) {
5888 return 1;
5891 /* Avoid overlapping operands. Wide source operands are
5892 always aligned so will never overlap with wide
5893 destinations in problematic ways. */
5894 if (rd == rm && !src2_wide) {
5895 tmp = neon_load_reg(rm, 1);
5896 neon_store_scratch(2, tmp);
5897 } else if (rd == rn && !src1_wide) {
5898 tmp = neon_load_reg(rn, 1);
5899 neon_store_scratch(2, tmp);
5901 TCGV_UNUSED_I32(tmp3);
5902 for (pass = 0; pass < 2; pass++) {
5903 if (src1_wide) {
5904 neon_load_reg64(cpu_V0, rn + pass);
5905 TCGV_UNUSED_I32(tmp);
5906 } else {
5907 if (pass == 1 && rd == rn) {
5908 tmp = neon_load_scratch(2);
5909 } else {
5910 tmp = neon_load_reg(rn, pass);
5912 if (prewiden) {
5913 gen_neon_widen(cpu_V0, tmp, size, u);
5916 if (src2_wide) {
5917 neon_load_reg64(cpu_V1, rm + pass);
5918 TCGV_UNUSED_I32(tmp2);
5919 } else {
5920 if (pass == 1 && rd == rm) {
5921 tmp2 = neon_load_scratch(2);
5922 } else {
5923 tmp2 = neon_load_reg(rm, pass);
5925 if (prewiden) {
5926 gen_neon_widen(cpu_V1, tmp2, size, u);
5929 switch (op) {
5930 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5931 gen_neon_addl(size);
5932 break;
5933 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5934 gen_neon_subl(size);
5935 break;
5936 case 5: case 7: /* VABAL, VABDL */
5937 switch ((size << 1) | u) {
5938 case 0:
5939 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5940 break;
5941 case 1:
5942 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5943 break;
5944 case 2:
5945 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5946 break;
5947 case 3:
5948 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5949 break;
5950 case 4:
5951 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5952 break;
5953 case 5:
5954 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5955 break;
5956 default: abort();
5958 tcg_temp_free_i32(tmp2);
5959 tcg_temp_free_i32(tmp);
5960 break;
5961 case 8: case 9: case 10: case 11: case 12: case 13:
5962 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5963 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5964 break;
5965 case 14: /* Polynomial VMULL */
5966 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5967 tcg_temp_free_i32(tmp2);
5968 tcg_temp_free_i32(tmp);
5969 break;
5970 default: /* 15 is RESERVED: caught earlier */
5971 abort();
5973 if (op == 13) {
5974 /* VQDMULL */
5975 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5976 neon_store_reg64(cpu_V0, rd + pass);
5977 } else if (op == 5 || (op >= 8 && op <= 11)) {
5978 /* Accumulate. */
5979 neon_load_reg64(cpu_V1, rd + pass);
5980 switch (op) {
5981 case 10: /* VMLSL */
5982 gen_neon_negl(cpu_V0, size);
5983 /* Fall through */
5984 case 5: case 8: /* VABAL, VMLAL */
5985 gen_neon_addl(size);
5986 break;
5987 case 9: case 11: /* VQDMLAL, VQDMLSL */
5988 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5989 if (op == 11) {
5990 gen_neon_negl(cpu_V0, size);
5992 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5993 break;
5994 default:
5995 abort();
5997 neon_store_reg64(cpu_V0, rd + pass);
5998 } else if (op == 4 || op == 6) {
5999 /* Narrowing operation. */
6000 tmp = tcg_temp_new_i32();
6001 if (!u) {
6002 switch (size) {
6003 case 0:
6004 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6005 break;
6006 case 1:
6007 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6008 break;
6009 case 2:
6010 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6011 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
6012 break;
6013 default: abort();
6015 } else {
6016 switch (size) {
6017 case 0:
6018 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6019 break;
6020 case 1:
6021 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6022 break;
6023 case 2:
6024 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6025 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6026 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
6027 break;
6028 default: abort();
6031 if (pass == 0) {
6032 tmp3 = tmp;
6033 } else {
6034 neon_store_reg(rd, 0, tmp3);
6035 neon_store_reg(rd, 1, tmp);
6037 } else {
6038 /* Write back the result. */
6039 neon_store_reg64(cpu_V0, rd + pass);
6042 } else {
6043 /* Two registers and a scalar. NB that for ops of this form
6044 * the ARM ARM labels bit 24 as Q, but it is in our variable
6045 * 'u', not 'q'.
6047 if (size == 0) {
6048 return 1;
6050 switch (op) {
6051 case 1: /* Float VMLA scalar */
6052 case 5: /* Floating point VMLS scalar */
6053 case 9: /* Floating point VMUL scalar */
6054 if (size == 1) {
6055 return 1;
6057 /* fall through */
6058 case 0: /* Integer VMLA scalar */
6059 case 4: /* Integer VMLS scalar */
6060 case 8: /* Integer VMUL scalar */
6061 case 12: /* VQDMULH scalar */
6062 case 13: /* VQRDMULH scalar */
6063 if (u && ((rd | rn) & 1)) {
6064 return 1;
6066 tmp = neon_get_scalar(size, rm);
6067 neon_store_scratch(0, tmp);
6068 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6069 tmp = neon_load_scratch(0);
6070 tmp2 = neon_load_reg(rn, pass);
6071 if (op == 12) {
6072 if (size == 1) {
6073 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6074 } else {
6075 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6077 } else if (op == 13) {
6078 if (size == 1) {
6079 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6080 } else {
6081 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6083 } else if (op & 1) {
6084 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6085 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6086 tcg_temp_free_ptr(fpstatus);
6087 } else {
6088 switch (size) {
6089 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6090 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6091 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
6092 default: abort();
6095 tcg_temp_free_i32(tmp2);
6096 if (op < 8) {
6097 /* Accumulate. */
6098 tmp2 = neon_load_reg(rd, pass);
6099 switch (op) {
6100 case 0:
6101 gen_neon_add(size, tmp, tmp2);
6102 break;
6103 case 1:
6105 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6106 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6107 tcg_temp_free_ptr(fpstatus);
6108 break;
6110 case 4:
6111 gen_neon_rsb(size, tmp, tmp2);
6112 break;
6113 case 5:
6115 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6116 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6117 tcg_temp_free_ptr(fpstatus);
6118 break;
6120 default:
6121 abort();
6123 tcg_temp_free_i32(tmp2);
6125 neon_store_reg(rd, pass, tmp);
6127 break;
6128 case 3: /* VQDMLAL scalar */
6129 case 7: /* VQDMLSL scalar */
6130 case 11: /* VQDMULL scalar */
6131 if (u == 1) {
6132 return 1;
6134 /* fall through */
6135 case 2: /* VMLAL sclar */
6136 case 6: /* VMLSL scalar */
6137 case 10: /* VMULL scalar */
6138 if (rd & 1) {
6139 return 1;
6141 tmp2 = neon_get_scalar(size, rm);
6142 /* We need a copy of tmp2 because gen_neon_mull
6143 * deletes it during pass 0. */
6144 tmp4 = tcg_temp_new_i32();
6145 tcg_gen_mov_i32(tmp4, tmp2);
6146 tmp3 = neon_load_reg(rn, 1);
6148 for (pass = 0; pass < 2; pass++) {
6149 if (pass == 0) {
6150 tmp = neon_load_reg(rn, 0);
6151 } else {
6152 tmp = tmp3;
6153 tmp2 = tmp4;
6155 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6156 if (op != 11) {
6157 neon_load_reg64(cpu_V1, rd + pass);
6159 switch (op) {
6160 case 6:
6161 gen_neon_negl(cpu_V0, size);
6162 /* Fall through */
6163 case 2:
6164 gen_neon_addl(size);
6165 break;
6166 case 3: case 7:
6167 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6168 if (op == 7) {
6169 gen_neon_negl(cpu_V0, size);
6171 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6172 break;
6173 case 10:
6174 /* no-op */
6175 break;
6176 case 11:
6177 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6178 break;
6179 default:
6180 abort();
6182 neon_store_reg64(cpu_V0, rd + pass);
6186 break;
6187 default: /* 14 and 15 are RESERVED */
6188 return 1;
6191 } else { /* size == 3 */
6192 if (!u) {
6193 /* Extract. */
6194 imm = (insn >> 8) & 0xf;
6196 if (imm > 7 && !q)
6197 return 1;
6199 if (q && ((rd | rn | rm) & 1)) {
6200 return 1;
6203 if (imm == 0) {
6204 neon_load_reg64(cpu_V0, rn);
6205 if (q) {
6206 neon_load_reg64(cpu_V1, rn + 1);
6208 } else if (imm == 8) {
6209 neon_load_reg64(cpu_V0, rn + 1);
6210 if (q) {
6211 neon_load_reg64(cpu_V1, rm);
6213 } else if (q) {
6214 tmp64 = tcg_temp_new_i64();
6215 if (imm < 8) {
6216 neon_load_reg64(cpu_V0, rn);
6217 neon_load_reg64(tmp64, rn + 1);
6218 } else {
6219 neon_load_reg64(cpu_V0, rn + 1);
6220 neon_load_reg64(tmp64, rm);
6222 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
6223 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
6224 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6225 if (imm < 8) {
6226 neon_load_reg64(cpu_V1, rm);
6227 } else {
6228 neon_load_reg64(cpu_V1, rm + 1);
6229 imm -= 8;
6231 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6232 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6233 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
6234 tcg_temp_free_i64(tmp64);
6235 } else {
6236 /* BUGFIX */
6237 neon_load_reg64(cpu_V0, rn);
6238 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
6239 neon_load_reg64(cpu_V1, rm);
6240 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6241 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6243 neon_store_reg64(cpu_V0, rd);
6244 if (q) {
6245 neon_store_reg64(cpu_V1, rd + 1);
6247 } else if ((insn & (1 << 11)) == 0) {
6248 /* Two register misc. */
6249 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6250 size = (insn >> 18) & 3;
6251 /* UNDEF for unknown op values and bad op-size combinations */
6252 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6253 return 1;
6255 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6256 q && ((rm | rd) & 1)) {
6257 return 1;
6259 switch (op) {
6260 case NEON_2RM_VREV64:
6261 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6262 tmp = neon_load_reg(rm, pass * 2);
6263 tmp2 = neon_load_reg(rm, pass * 2 + 1);
6264 switch (size) {
6265 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6266 case 1: gen_swap_half(tmp); break;
6267 case 2: /* no-op */ break;
6268 default: abort();
6270 neon_store_reg(rd, pass * 2 + 1, tmp);
6271 if (size == 2) {
6272 neon_store_reg(rd, pass * 2, tmp2);
6273 } else {
6274 switch (size) {
6275 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6276 case 1: gen_swap_half(tmp2); break;
6277 default: abort();
6279 neon_store_reg(rd, pass * 2, tmp2);
6282 break;
6283 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6284 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
6285 for (pass = 0; pass < q + 1; pass++) {
6286 tmp = neon_load_reg(rm, pass * 2);
6287 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6288 tmp = neon_load_reg(rm, pass * 2 + 1);
6289 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6290 switch (size) {
6291 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6292 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6293 case 2: tcg_gen_add_i64(CPU_V001); break;
6294 default: abort();
6296 if (op >= NEON_2RM_VPADAL) {
6297 /* Accumulate. */
6298 neon_load_reg64(cpu_V1, rd + pass);
6299 gen_neon_addl(size);
6301 neon_store_reg64(cpu_V0, rd + pass);
6303 break;
6304 case NEON_2RM_VTRN:
6305 if (size == 2) {
6306 int n;
6307 for (n = 0; n < (q ? 4 : 2); n += 2) {
6308 tmp = neon_load_reg(rm, n);
6309 tmp2 = neon_load_reg(rd, n + 1);
6310 neon_store_reg(rm, n, tmp2);
6311 neon_store_reg(rd, n + 1, tmp);
6313 } else {
6314 goto elementwise;
6316 break;
6317 case NEON_2RM_VUZP:
6318 if (gen_neon_unzip(rd, rm, size, q)) {
6319 return 1;
6321 break;
6322 case NEON_2RM_VZIP:
6323 if (gen_neon_zip(rd, rm, size, q)) {
6324 return 1;
6326 break;
6327 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6328 /* also VQMOVUN; op field and mnemonics don't line up */
6329 if (rm & 1) {
6330 return 1;
6332 TCGV_UNUSED_I32(tmp2);
6333 for (pass = 0; pass < 2; pass++) {
6334 neon_load_reg64(cpu_V0, rm + pass);
6335 tmp = tcg_temp_new_i32();
6336 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6337 tmp, cpu_V0);
6338 if (pass == 0) {
6339 tmp2 = tmp;
6340 } else {
6341 neon_store_reg(rd, 0, tmp2);
6342 neon_store_reg(rd, 1, tmp);
6345 break;
6346 case NEON_2RM_VSHLL:
6347 if (q || (rd & 1)) {
6348 return 1;
6350 tmp = neon_load_reg(rm, 0);
6351 tmp2 = neon_load_reg(rm, 1);
6352 for (pass = 0; pass < 2; pass++) {
6353 if (pass == 1)
6354 tmp = tmp2;
6355 gen_neon_widen(cpu_V0, tmp, size, 1);
6356 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
6357 neon_store_reg64(cpu_V0, rd + pass);
6359 break;
6360 case NEON_2RM_VCVT_F16_F32:
6361 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6362 q || (rm & 1)) {
6363 return 1;
6365 tmp = tcg_temp_new_i32();
6366 tmp2 = tcg_temp_new_i32();
6367 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
6368 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6369 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
6370 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6371 tcg_gen_shli_i32(tmp2, tmp2, 16);
6372 tcg_gen_or_i32(tmp2, tmp2, tmp);
6373 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
6374 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6375 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6376 neon_store_reg(rd, 0, tmp2);
6377 tmp2 = tcg_temp_new_i32();
6378 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6379 tcg_gen_shli_i32(tmp2, tmp2, 16);
6380 tcg_gen_or_i32(tmp2, tmp2, tmp);
6381 neon_store_reg(rd, 1, tmp2);
6382 tcg_temp_free_i32(tmp);
6383 break;
6384 case NEON_2RM_VCVT_F32_F16:
6385 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6386 q || (rd & 1)) {
6387 return 1;
6389 tmp3 = tcg_temp_new_i32();
6390 tmp = neon_load_reg(rm, 0);
6391 tmp2 = neon_load_reg(rm, 1);
6392 tcg_gen_ext16u_i32(tmp3, tmp);
6393 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6394 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6395 tcg_gen_shri_i32(tmp3, tmp, 16);
6396 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6397 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6398 tcg_temp_free_i32(tmp);
6399 tcg_gen_ext16u_i32(tmp3, tmp2);
6400 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6401 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6402 tcg_gen_shri_i32(tmp3, tmp2, 16);
6403 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6404 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6405 tcg_temp_free_i32(tmp2);
6406 tcg_temp_free_i32(tmp3);
6407 break;
6408 case NEON_2RM_AESE: case NEON_2RM_AESMC:
6409 if (!arm_feature(env, ARM_FEATURE_V8_AES)
6410 || ((rm | rd) & 1)) {
6411 return 1;
6413 tmp = tcg_const_i32(rd);
6414 tmp2 = tcg_const_i32(rm);
6416 /* Bit 6 is the lowest opcode bit; it distinguishes between
6417 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6419 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6421 if (op == NEON_2RM_AESE) {
6422 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6423 } else {
6424 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6426 tcg_temp_free_i32(tmp);
6427 tcg_temp_free_i32(tmp2);
6428 tcg_temp_free_i32(tmp3);
6429 break;
6430 default:
6431 elementwise:
6432 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6433 if (neon_2rm_is_float_op(op)) {
6434 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6435 neon_reg_offset(rm, pass));
6436 TCGV_UNUSED_I32(tmp);
6437 } else {
6438 tmp = neon_load_reg(rm, pass);
6440 switch (op) {
6441 case NEON_2RM_VREV32:
6442 switch (size) {
6443 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6444 case 1: gen_swap_half(tmp); break;
6445 default: abort();
6447 break;
6448 case NEON_2RM_VREV16:
6449 gen_rev16(tmp);
6450 break;
6451 case NEON_2RM_VCLS:
6452 switch (size) {
6453 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6454 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6455 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6456 default: abort();
6458 break;
6459 case NEON_2RM_VCLZ:
6460 switch (size) {
6461 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6462 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6463 case 2: gen_helper_clz(tmp, tmp); break;
6464 default: abort();
6466 break;
6467 case NEON_2RM_VCNT:
6468 gen_helper_neon_cnt_u8(tmp, tmp);
6469 break;
6470 case NEON_2RM_VMVN:
6471 tcg_gen_not_i32(tmp, tmp);
6472 break;
6473 case NEON_2RM_VQABS:
6474 switch (size) {
6475 case 0:
6476 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6477 break;
6478 case 1:
6479 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6480 break;
6481 case 2:
6482 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6483 break;
6484 default: abort();
6486 break;
6487 case NEON_2RM_VQNEG:
6488 switch (size) {
6489 case 0:
6490 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6491 break;
6492 case 1:
6493 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6494 break;
6495 case 2:
6496 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6497 break;
6498 default: abort();
6500 break;
6501 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6502 tmp2 = tcg_const_i32(0);
6503 switch(size) {
6504 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6505 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6506 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6507 default: abort();
6509 tcg_temp_free_i32(tmp2);
6510 if (op == NEON_2RM_VCLE0) {
6511 tcg_gen_not_i32(tmp, tmp);
6513 break;
6514 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6515 tmp2 = tcg_const_i32(0);
6516 switch(size) {
6517 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6518 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6519 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6520 default: abort();
6522 tcg_temp_free_i32(tmp2);
6523 if (op == NEON_2RM_VCLT0) {
6524 tcg_gen_not_i32(tmp, tmp);
6526 break;
6527 case NEON_2RM_VCEQ0:
6528 tmp2 = tcg_const_i32(0);
6529 switch(size) {
6530 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6531 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6532 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6533 default: abort();
6535 tcg_temp_free_i32(tmp2);
6536 break;
6537 case NEON_2RM_VABS:
6538 switch(size) {
6539 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6540 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6541 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6542 default: abort();
6544 break;
6545 case NEON_2RM_VNEG:
6546 tmp2 = tcg_const_i32(0);
6547 gen_neon_rsb(size, tmp, tmp2);
6548 tcg_temp_free_i32(tmp2);
6549 break;
6550 case NEON_2RM_VCGT0_F:
6552 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6553 tmp2 = tcg_const_i32(0);
6554 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6555 tcg_temp_free_i32(tmp2);
6556 tcg_temp_free_ptr(fpstatus);
6557 break;
6559 case NEON_2RM_VCGE0_F:
6561 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6562 tmp2 = tcg_const_i32(0);
6563 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6564 tcg_temp_free_i32(tmp2);
6565 tcg_temp_free_ptr(fpstatus);
6566 break;
6568 case NEON_2RM_VCEQ0_F:
6570 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6571 tmp2 = tcg_const_i32(0);
6572 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6573 tcg_temp_free_i32(tmp2);
6574 tcg_temp_free_ptr(fpstatus);
6575 break;
6577 case NEON_2RM_VCLE0_F:
6579 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6580 tmp2 = tcg_const_i32(0);
6581 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6582 tcg_temp_free_i32(tmp2);
6583 tcg_temp_free_ptr(fpstatus);
6584 break;
6586 case NEON_2RM_VCLT0_F:
6588 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6589 tmp2 = tcg_const_i32(0);
6590 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6591 tcg_temp_free_i32(tmp2);
6592 tcg_temp_free_ptr(fpstatus);
6593 break;
6595 case NEON_2RM_VABS_F:
6596 gen_vfp_abs(0);
6597 break;
6598 case NEON_2RM_VNEG_F:
6599 gen_vfp_neg(0);
6600 break;
6601 case NEON_2RM_VSWP:
6602 tmp2 = neon_load_reg(rd, pass);
6603 neon_store_reg(rm, pass, tmp2);
6604 break;
6605 case NEON_2RM_VTRN:
6606 tmp2 = neon_load_reg(rd, pass);
6607 switch (size) {
6608 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6609 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6610 default: abort();
6612 neon_store_reg(rm, pass, tmp2);
6613 break;
6614 case NEON_2RM_VRINTN:
6615 case NEON_2RM_VRINTA:
6616 case NEON_2RM_VRINTM:
6617 case NEON_2RM_VRINTP:
6618 case NEON_2RM_VRINTZ:
6620 TCGv_i32 tcg_rmode;
6621 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6622 int rmode;
6624 if (op == NEON_2RM_VRINTZ) {
6625 rmode = FPROUNDING_ZERO;
6626 } else {
6627 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6630 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6631 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6632 cpu_env);
6633 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
6634 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6635 cpu_env);
6636 tcg_temp_free_ptr(fpstatus);
6637 tcg_temp_free_i32(tcg_rmode);
6638 break;
6640 case NEON_2RM_VRINTX:
6642 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6643 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
6644 tcg_temp_free_ptr(fpstatus);
6645 break;
6647 case NEON_2RM_VCVTAU:
6648 case NEON_2RM_VCVTAS:
6649 case NEON_2RM_VCVTNU:
6650 case NEON_2RM_VCVTNS:
6651 case NEON_2RM_VCVTPU:
6652 case NEON_2RM_VCVTPS:
6653 case NEON_2RM_VCVTMU:
6654 case NEON_2RM_VCVTMS:
6656 bool is_signed = !extract32(insn, 7, 1);
6657 TCGv_ptr fpst = get_fpstatus_ptr(1);
6658 TCGv_i32 tcg_rmode, tcg_shift;
6659 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6661 tcg_shift = tcg_const_i32(0);
6662 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6663 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6664 cpu_env);
6666 if (is_signed) {
6667 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
6668 tcg_shift, fpst);
6669 } else {
6670 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
6671 tcg_shift, fpst);
6674 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6675 cpu_env);
6676 tcg_temp_free_i32(tcg_rmode);
6677 tcg_temp_free_i32(tcg_shift);
6678 tcg_temp_free_ptr(fpst);
6679 break;
6681 case NEON_2RM_VRECPE:
6682 gen_helper_recpe_u32(tmp, tmp, cpu_env);
6683 break;
6684 case NEON_2RM_VRSQRTE:
6685 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
6686 break;
6687 case NEON_2RM_VRECPE_F:
6688 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
6689 break;
6690 case NEON_2RM_VRSQRTE_F:
6691 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
6692 break;
6693 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6694 gen_vfp_sito(0, 1);
6695 break;
6696 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6697 gen_vfp_uito(0, 1);
6698 break;
6699 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6700 gen_vfp_tosiz(0, 1);
6701 break;
6702 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6703 gen_vfp_touiz(0, 1);
6704 break;
6705 default:
6706 /* Reserved op values were caught by the
6707 * neon_2rm_sizes[] check earlier.
6709 abort();
6711 if (neon_2rm_is_float_op(op)) {
6712 tcg_gen_st_f32(cpu_F0s, cpu_env,
6713 neon_reg_offset(rd, pass));
6714 } else {
6715 neon_store_reg(rd, pass, tmp);
6718 break;
6720 } else if ((insn & (1 << 10)) == 0) {
6721 /* VTBL, VTBX. */
6722 int n = ((insn >> 8) & 3) + 1;
6723 if ((rn + n) > 32) {
6724 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6725 * helper function running off the end of the register file.
6727 return 1;
6729 n <<= 3;
6730 if (insn & (1 << 6)) {
6731 tmp = neon_load_reg(rd, 0);
6732 } else {
6733 tmp = tcg_temp_new_i32();
6734 tcg_gen_movi_i32(tmp, 0);
6736 tmp2 = neon_load_reg(rm, 0);
6737 tmp4 = tcg_const_i32(rn);
6738 tmp5 = tcg_const_i32(n);
6739 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
6740 tcg_temp_free_i32(tmp);
6741 if (insn & (1 << 6)) {
6742 tmp = neon_load_reg(rd, 1);
6743 } else {
6744 tmp = tcg_temp_new_i32();
6745 tcg_gen_movi_i32(tmp, 0);
6747 tmp3 = neon_load_reg(rm, 1);
6748 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
6749 tcg_temp_free_i32(tmp5);
6750 tcg_temp_free_i32(tmp4);
6751 neon_store_reg(rd, 0, tmp2);
6752 neon_store_reg(rd, 1, tmp3);
6753 tcg_temp_free_i32(tmp);
6754 } else if ((insn & 0x380) == 0) {
6755 /* VDUP */
6756 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6757 return 1;
6759 if (insn & (1 << 19)) {
6760 tmp = neon_load_reg(rm, 1);
6761 } else {
6762 tmp = neon_load_reg(rm, 0);
6764 if (insn & (1 << 16)) {
6765 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6766 } else if (insn & (1 << 17)) {
6767 if ((insn >> 18) & 1)
6768 gen_neon_dup_high16(tmp);
6769 else
6770 gen_neon_dup_low16(tmp);
6772 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6773 tmp2 = tcg_temp_new_i32();
6774 tcg_gen_mov_i32(tmp2, tmp);
6775 neon_store_reg(rd, pass, tmp2);
6777 tcg_temp_free_i32(tmp);
6778 } else {
6779 return 1;
6783 return 0;
6786 static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
6788 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
6789 const ARMCPRegInfo *ri;
6791 cpnum = (insn >> 8) & 0xf;
6792 if (arm_feature(env, ARM_FEATURE_XSCALE)
6793 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6794 return 1;
6796 /* First check for coprocessor space used for actual instructions */
6797 switch (cpnum) {
6798 case 0:
6799 case 1:
6800 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6801 return disas_iwmmxt_insn(env, s, insn);
6802 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6803 return disas_dsp_insn(env, s, insn);
6805 return 1;
6806 default:
6807 break;
6810 /* Otherwise treat as a generic register access */
6811 is64 = (insn & (1 << 25)) == 0;
6812 if (!is64 && ((insn & (1 << 4)) == 0)) {
6813 /* cdp */
6814 return 1;
6817 crm = insn & 0xf;
6818 if (is64) {
6819 crn = 0;
6820 opc1 = (insn >> 4) & 0xf;
6821 opc2 = 0;
6822 rt2 = (insn >> 16) & 0xf;
6823 } else {
6824 crn = (insn >> 16) & 0xf;
6825 opc1 = (insn >> 21) & 7;
6826 opc2 = (insn >> 5) & 7;
6827 rt2 = 0;
6829 isread = (insn >> 20) & 1;
6830 rt = (insn >> 12) & 0xf;
6832 ri = get_arm_cp_reginfo(s->cp_regs,
6833 ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
6834 if (ri) {
6835 /* Check access permissions */
6836 if (!cp_access_ok(s->current_pl, ri, isread)) {
6837 return 1;
6840 /* Handle special cases first */
6841 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
6842 case ARM_CP_NOP:
6843 return 0;
6844 case ARM_CP_WFI:
6845 if (isread) {
6846 return 1;
6848 gen_set_pc_im(s, s->pc);
6849 s->is_jmp = DISAS_WFI;
6850 return 0;
6851 default:
6852 break;
6855 if (use_icount && (ri->type & ARM_CP_IO)) {
6856 gen_io_start();
6859 if (isread) {
6860 /* Read */
6861 if (is64) {
6862 TCGv_i64 tmp64;
6863 TCGv_i32 tmp;
6864 if (ri->type & ARM_CP_CONST) {
6865 tmp64 = tcg_const_i64(ri->resetvalue);
6866 } else if (ri->readfn) {
6867 TCGv_ptr tmpptr;
6868 gen_set_pc_im(s, s->pc);
6869 tmp64 = tcg_temp_new_i64();
6870 tmpptr = tcg_const_ptr(ri);
6871 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
6872 tcg_temp_free_ptr(tmpptr);
6873 } else {
6874 tmp64 = tcg_temp_new_i64();
6875 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
6877 tmp = tcg_temp_new_i32();
6878 tcg_gen_trunc_i64_i32(tmp, tmp64);
6879 store_reg(s, rt, tmp);
6880 tcg_gen_shri_i64(tmp64, tmp64, 32);
6881 tmp = tcg_temp_new_i32();
6882 tcg_gen_trunc_i64_i32(tmp, tmp64);
6883 tcg_temp_free_i64(tmp64);
6884 store_reg(s, rt2, tmp);
6885 } else {
6886 TCGv_i32 tmp;
6887 if (ri->type & ARM_CP_CONST) {
6888 tmp = tcg_const_i32(ri->resetvalue);
6889 } else if (ri->readfn) {
6890 TCGv_ptr tmpptr;
6891 gen_set_pc_im(s, s->pc);
6892 tmp = tcg_temp_new_i32();
6893 tmpptr = tcg_const_ptr(ri);
6894 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
6895 tcg_temp_free_ptr(tmpptr);
6896 } else {
6897 tmp = load_cpu_offset(ri->fieldoffset);
6899 if (rt == 15) {
6900 /* Destination register of r15 for 32 bit loads sets
6901 * the condition codes from the high 4 bits of the value
6903 gen_set_nzcv(tmp);
6904 tcg_temp_free_i32(tmp);
6905 } else {
6906 store_reg(s, rt, tmp);
6909 } else {
6910 /* Write */
6911 if (ri->type & ARM_CP_CONST) {
6912 /* If not forbidden by access permissions, treat as WI */
6913 return 0;
6916 if (is64) {
6917 TCGv_i32 tmplo, tmphi;
6918 TCGv_i64 tmp64 = tcg_temp_new_i64();
6919 tmplo = load_reg(s, rt);
6920 tmphi = load_reg(s, rt2);
6921 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
6922 tcg_temp_free_i32(tmplo);
6923 tcg_temp_free_i32(tmphi);
6924 if (ri->writefn) {
6925 TCGv_ptr tmpptr = tcg_const_ptr(ri);
6926 gen_set_pc_im(s, s->pc);
6927 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
6928 tcg_temp_free_ptr(tmpptr);
6929 } else {
6930 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
6932 tcg_temp_free_i64(tmp64);
6933 } else {
6934 if (ri->writefn) {
6935 TCGv_i32 tmp;
6936 TCGv_ptr tmpptr;
6937 gen_set_pc_im(s, s->pc);
6938 tmp = load_reg(s, rt);
6939 tmpptr = tcg_const_ptr(ri);
6940 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
6941 tcg_temp_free_ptr(tmpptr);
6942 tcg_temp_free_i32(tmp);
6943 } else {
6944 TCGv_i32 tmp = load_reg(s, rt);
6945 store_cpu_offset(tmp, ri->fieldoffset);
6950 if (use_icount && (ri->type & ARM_CP_IO)) {
6951 /* I/O operations must end the TB here (whether read or write) */
6952 gen_io_end();
6953 gen_lookup_tb(s);
6954 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
6955 /* We default to ending the TB on a coprocessor register write,
6956 * but allow this to be suppressed by the register definition
6957 * (usually only necessary to work around guest bugs).
6959 gen_lookup_tb(s);
6962 return 0;
6965 return 1;
6969 /* Store a 64-bit value to a register pair. Clobbers val. */
6970 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6972 TCGv_i32 tmp;
6973 tmp = tcg_temp_new_i32();
6974 tcg_gen_trunc_i64_i32(tmp, val);
6975 store_reg(s, rlow, tmp);
6976 tmp = tcg_temp_new_i32();
6977 tcg_gen_shri_i64(val, val, 32);
6978 tcg_gen_trunc_i64_i32(tmp, val);
6979 store_reg(s, rhigh, tmp);
6982 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6983 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
6985 TCGv_i64 tmp;
6986 TCGv_i32 tmp2;
6988 /* Load value and extend to 64 bits. */
6989 tmp = tcg_temp_new_i64();
6990 tmp2 = load_reg(s, rlow);
6991 tcg_gen_extu_i32_i64(tmp, tmp2);
6992 tcg_temp_free_i32(tmp2);
6993 tcg_gen_add_i64(val, val, tmp);
6994 tcg_temp_free_i64(tmp);
6997 /* load and add a 64-bit value from a register pair. */
6998 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
7000 TCGv_i64 tmp;
7001 TCGv_i32 tmpl;
7002 TCGv_i32 tmph;
7004 /* Load 64-bit value rd:rn. */
7005 tmpl = load_reg(s, rlow);
7006 tmph = load_reg(s, rhigh);
7007 tmp = tcg_temp_new_i64();
7008 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7009 tcg_temp_free_i32(tmpl);
7010 tcg_temp_free_i32(tmph);
7011 tcg_gen_add_i64(val, val, tmp);
7012 tcg_temp_free_i64(tmp);
7015 /* Set N and Z flags from hi|lo. */
7016 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
7018 tcg_gen_mov_i32(cpu_NF, hi);
7019 tcg_gen_or_i32(cpu_ZF, lo, hi);
7022 /* Load/Store exclusive instructions are implemented by remembering
7023 the value/address loaded, and seeing if these are the same
7024 when the store is performed. This should be sufficient to implement
7025 the architecturally mandated semantics, and avoids having to monitor
7026 regular stores.
7028 In system emulation mode only one CPU will be running at once, so
7029 this sequence is effectively atomic. In user emulation mode we
7030 throw an exception and handle the atomic operation elsewhere. */
7031 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
7032 TCGv_i32 addr, int size)
7034 TCGv_i32 tmp = tcg_temp_new_i32();
7036 switch (size) {
7037 case 0:
7038 gen_aa32_ld8u(tmp, addr, IS_USER(s));
7039 break;
7040 case 1:
7041 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7042 break;
7043 case 2:
7044 case 3:
7045 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7046 break;
7047 default:
7048 abort();
7051 if (size == 3) {
7052 TCGv_i32 tmp2 = tcg_temp_new_i32();
7053 TCGv_i32 tmp3 = tcg_temp_new_i32();
7055 tcg_gen_addi_i32(tmp2, addr, 4);
7056 gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
7057 tcg_temp_free_i32(tmp2);
7058 tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
7059 store_reg(s, rt2, tmp3);
7060 } else {
7061 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
7064 store_reg(s, rt, tmp);
7065 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
7068 static void gen_clrex(DisasContext *s)
7070 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7073 #ifdef CONFIG_USER_ONLY
7074 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7075 TCGv_i32 addr, int size)
7077 tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
7078 tcg_gen_movi_i32(cpu_exclusive_info,
7079 size | (rd << 4) | (rt << 8) | (rt2 << 12));
7080 gen_exception_insn(s, 4, EXCP_STREX);
7082 #else
7083 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7084 TCGv_i32 addr, int size)
7086 TCGv_i32 tmp;
7087 TCGv_i64 val64, extaddr;
7088 int done_label;
7089 int fail_label;
7091 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7092 [addr] = {Rt};
7093 {Rd} = 0;
7094 } else {
7095 {Rd} = 1;
7096 } */
7097 fail_label = gen_new_label();
7098 done_label = gen_new_label();
7099 extaddr = tcg_temp_new_i64();
7100 tcg_gen_extu_i32_i64(extaddr, addr);
7101 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7102 tcg_temp_free_i64(extaddr);
7104 tmp = tcg_temp_new_i32();
7105 switch (size) {
7106 case 0:
7107 gen_aa32_ld8u(tmp, addr, IS_USER(s));
7108 break;
7109 case 1:
7110 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7111 break;
7112 case 2:
7113 case 3:
7114 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7115 break;
7116 default:
7117 abort();
7120 val64 = tcg_temp_new_i64();
7121 if (size == 3) {
7122 TCGv_i32 tmp2 = tcg_temp_new_i32();
7123 TCGv_i32 tmp3 = tcg_temp_new_i32();
7124 tcg_gen_addi_i32(tmp2, addr, 4);
7125 gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
7126 tcg_temp_free_i32(tmp2);
7127 tcg_gen_concat_i32_i64(val64, tmp, tmp3);
7128 tcg_temp_free_i32(tmp3);
7129 } else {
7130 tcg_gen_extu_i32_i64(val64, tmp);
7132 tcg_temp_free_i32(tmp);
7134 tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
7135 tcg_temp_free_i64(val64);
7137 tmp = load_reg(s, rt);
7138 switch (size) {
7139 case 0:
7140 gen_aa32_st8(tmp, addr, IS_USER(s));
7141 break;
7142 case 1:
7143 gen_aa32_st16(tmp, addr, IS_USER(s));
7144 break;
7145 case 2:
7146 case 3:
7147 gen_aa32_st32(tmp, addr, IS_USER(s));
7148 break;
7149 default:
7150 abort();
7152 tcg_temp_free_i32(tmp);
7153 if (size == 3) {
7154 tcg_gen_addi_i32(addr, addr, 4);
7155 tmp = load_reg(s, rt2);
7156 gen_aa32_st32(tmp, addr, IS_USER(s));
7157 tcg_temp_free_i32(tmp);
7159 tcg_gen_movi_i32(cpu_R[rd], 0);
7160 tcg_gen_br(done_label);
7161 gen_set_label(fail_label);
7162 tcg_gen_movi_i32(cpu_R[rd], 1);
7163 gen_set_label(done_label);
7164 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7166 #endif
7168 /* gen_srs:
7169 * @env: CPUARMState
7170 * @s: DisasContext
7171 * @mode: mode field from insn (which stack to store to)
7172 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7173 * @writeback: true if writeback bit set
7175 * Generate code for the SRS (Store Return State) insn.
7177 static void gen_srs(DisasContext *s,
7178 uint32_t mode, uint32_t amode, bool writeback)
7180 int32_t offset;
7181 TCGv_i32 addr = tcg_temp_new_i32();
7182 TCGv_i32 tmp = tcg_const_i32(mode);
7183 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7184 tcg_temp_free_i32(tmp);
7185 switch (amode) {
7186 case 0: /* DA */
7187 offset = -4;
7188 break;
7189 case 1: /* IA */
7190 offset = 0;
7191 break;
7192 case 2: /* DB */
7193 offset = -8;
7194 break;
7195 case 3: /* IB */
7196 offset = 4;
7197 break;
7198 default:
7199 abort();
7201 tcg_gen_addi_i32(addr, addr, offset);
7202 tmp = load_reg(s, 14);
7203 gen_aa32_st32(tmp, addr, 0);
7204 tcg_temp_free_i32(tmp);
7205 tmp = load_cpu_field(spsr);
7206 tcg_gen_addi_i32(addr, addr, 4);
7207 gen_aa32_st32(tmp, addr, 0);
7208 tcg_temp_free_i32(tmp);
7209 if (writeback) {
7210 switch (amode) {
7211 case 0:
7212 offset = -8;
7213 break;
7214 case 1:
7215 offset = 4;
7216 break;
7217 case 2:
7218 offset = -4;
7219 break;
7220 case 3:
7221 offset = 0;
7222 break;
7223 default:
7224 abort();
7226 tcg_gen_addi_i32(addr, addr, offset);
7227 tmp = tcg_const_i32(mode);
7228 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7229 tcg_temp_free_i32(tmp);
7231 tcg_temp_free_i32(addr);
7234 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
7236 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
7237 TCGv_i32 tmp;
7238 TCGv_i32 tmp2;
7239 TCGv_i32 tmp3;
7240 TCGv_i32 addr;
7241 TCGv_i64 tmp64;
7243 insn = arm_ldl_code(env, s->pc, s->bswap_code);
7244 s->pc += 4;
7246 /* M variants do not implement ARM mode. */
7247 if (IS_M(env))
7248 goto illegal_op;
7249 cond = insn >> 28;
7250 if (cond == 0xf){
7251 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
7252 * choose to UNDEF. In ARMv5 and above the space is used
7253 * for miscellaneous unconditional instructions.
7255 ARCH(5);
7257 /* Unconditional instructions. */
7258 if (((insn >> 25) & 7) == 1) {
7259 /* NEON Data processing. */
7260 if (!arm_feature(env, ARM_FEATURE_NEON))
7261 goto illegal_op;
7263 if (disas_neon_data_insn(env, s, insn))
7264 goto illegal_op;
7265 return;
7267 if ((insn & 0x0f100000) == 0x04000000) {
7268 /* NEON load/store. */
7269 if (!arm_feature(env, ARM_FEATURE_NEON))
7270 goto illegal_op;
7272 if (disas_neon_ls_insn(env, s, insn))
7273 goto illegal_op;
7274 return;
7276 if ((insn & 0x0f000e10) == 0x0e000a00) {
7277 /* VFP. */
7278 if (disas_vfp_insn(env, s, insn)) {
7279 goto illegal_op;
7281 return;
7283 if (((insn & 0x0f30f000) == 0x0510f000) ||
7284 ((insn & 0x0f30f010) == 0x0710f000)) {
7285 if ((insn & (1 << 22)) == 0) {
7286 /* PLDW; v7MP */
7287 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7288 goto illegal_op;
7291 /* Otherwise PLD; v5TE+ */
7292 ARCH(5TE);
7293 return;
7295 if (((insn & 0x0f70f000) == 0x0450f000) ||
7296 ((insn & 0x0f70f010) == 0x0650f000)) {
7297 ARCH(7);
7298 return; /* PLI; V7 */
7300 if (((insn & 0x0f700000) == 0x04100000) ||
7301 ((insn & 0x0f700010) == 0x06100000)) {
7302 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7303 goto illegal_op;
7305 return; /* v7MP: Unallocated memory hint: must NOP */
7308 if ((insn & 0x0ffffdff) == 0x01010000) {
7309 ARCH(6);
7310 /* setend */
7311 if (((insn >> 9) & 1) != s->bswap_code) {
7312 /* Dynamic endianness switching not implemented. */
7313 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
7314 goto illegal_op;
7316 return;
7317 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7318 switch ((insn >> 4) & 0xf) {
7319 case 1: /* clrex */
7320 ARCH(6K);
7321 gen_clrex(s);
7322 return;
7323 case 4: /* dsb */
7324 case 5: /* dmb */
7325 case 6: /* isb */
7326 ARCH(7);
7327 /* We don't emulate caches so these are a no-op. */
7328 return;
7329 default:
7330 goto illegal_op;
7332 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7333 /* srs */
7334 if (IS_USER(s)) {
7335 goto illegal_op;
7337 ARCH(6);
7338 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
7339 return;
7340 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
7341 /* rfe */
7342 int32_t offset;
7343 if (IS_USER(s))
7344 goto illegal_op;
7345 ARCH(6);
7346 rn = (insn >> 16) & 0xf;
7347 addr = load_reg(s, rn);
7348 i = (insn >> 23) & 3;
7349 switch (i) {
7350 case 0: offset = -4; break; /* DA */
7351 case 1: offset = 0; break; /* IA */
7352 case 2: offset = -8; break; /* DB */
7353 case 3: offset = 4; break; /* IB */
7354 default: abort();
7356 if (offset)
7357 tcg_gen_addi_i32(addr, addr, offset);
7358 /* Load PC into tmp and CPSR into tmp2. */
7359 tmp = tcg_temp_new_i32();
7360 gen_aa32_ld32u(tmp, addr, 0);
7361 tcg_gen_addi_i32(addr, addr, 4);
7362 tmp2 = tcg_temp_new_i32();
7363 gen_aa32_ld32u(tmp2, addr, 0);
7364 if (insn & (1 << 21)) {
7365 /* Base writeback. */
7366 switch (i) {
7367 case 0: offset = -8; break;
7368 case 1: offset = 4; break;
7369 case 2: offset = -4; break;
7370 case 3: offset = 0; break;
7371 default: abort();
7373 if (offset)
7374 tcg_gen_addi_i32(addr, addr, offset);
7375 store_reg(s, rn, addr);
7376 } else {
7377 tcg_temp_free_i32(addr);
7379 gen_rfe(s, tmp, tmp2);
7380 return;
7381 } else if ((insn & 0x0e000000) == 0x0a000000) {
7382 /* branch link and change to thumb (blx <offset>) */
7383 int32_t offset;
7385 val = (uint32_t)s->pc;
7386 tmp = tcg_temp_new_i32();
7387 tcg_gen_movi_i32(tmp, val);
7388 store_reg(s, 14, tmp);
7389 /* Sign-extend the 24-bit offset */
7390 offset = (((int32_t)insn) << 8) >> 8;
7391 /* offset * 4 + bit24 * 2 + (thumb bit) */
7392 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7393 /* pipeline offset */
7394 val += 4;
7395 /* protected by ARCH(5); above, near the start of uncond block */
7396 gen_bx_im(s, val);
7397 return;
7398 } else if ((insn & 0x0e000f00) == 0x0c000100) {
7399 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7400 /* iWMMXt register transfer. */
7401 if (env->cp15.c15_cpar & (1 << 1))
7402 if (!disas_iwmmxt_insn(env, s, insn))
7403 return;
7405 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7406 /* Coprocessor double register transfer. */
7407 ARCH(5TE);
7408 } else if ((insn & 0x0f000010) == 0x0e000010) {
7409 /* Additional coprocessor register transfer. */
7410 } else if ((insn & 0x0ff10020) == 0x01000000) {
7411 uint32_t mask;
7412 uint32_t val;
7413 /* cps (privileged) */
7414 if (IS_USER(s))
7415 return;
7416 mask = val = 0;
7417 if (insn & (1 << 19)) {
7418 if (insn & (1 << 8))
7419 mask |= CPSR_A;
7420 if (insn & (1 << 7))
7421 mask |= CPSR_I;
7422 if (insn & (1 << 6))
7423 mask |= CPSR_F;
7424 if (insn & (1 << 18))
7425 val |= mask;
7427 if (insn & (1 << 17)) {
7428 mask |= CPSR_M;
7429 val |= (insn & 0x1f);
7431 if (mask) {
7432 gen_set_psr_im(s, mask, 0, val);
7434 return;
7436 goto illegal_op;
7438 if (cond != 0xe) {
7439 /* if not always execute, we generate a conditional jump to
7440 next instruction */
7441 s->condlabel = gen_new_label();
7442 arm_gen_test_cc(cond ^ 1, s->condlabel);
7443 s->condjmp = 1;
7445 if ((insn & 0x0f900000) == 0x03000000) {
7446 if ((insn & (1 << 21)) == 0) {
7447 ARCH(6T2);
7448 rd = (insn >> 12) & 0xf;
7449 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7450 if ((insn & (1 << 22)) == 0) {
7451 /* MOVW */
7452 tmp = tcg_temp_new_i32();
7453 tcg_gen_movi_i32(tmp, val);
7454 } else {
7455 /* MOVT */
7456 tmp = load_reg(s, rd);
7457 tcg_gen_ext16u_i32(tmp, tmp);
7458 tcg_gen_ori_i32(tmp, tmp, val << 16);
7460 store_reg(s, rd, tmp);
7461 } else {
7462 if (((insn >> 12) & 0xf) != 0xf)
7463 goto illegal_op;
7464 if (((insn >> 16) & 0xf) == 0) {
7465 gen_nop_hint(s, insn & 0xff);
7466 } else {
7467 /* CPSR = immediate */
7468 val = insn & 0xff;
7469 shift = ((insn >> 8) & 0xf) * 2;
7470 if (shift)
7471 val = (val >> shift) | (val << (32 - shift));
7472 i = ((insn & (1 << 22)) != 0);
7473 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
7474 goto illegal_op;
7477 } else if ((insn & 0x0f900000) == 0x01000000
7478 && (insn & 0x00000090) != 0x00000090) {
7479 /* miscellaneous instructions */
7480 op1 = (insn >> 21) & 3;
7481 sh = (insn >> 4) & 0xf;
7482 rm = insn & 0xf;
7483 switch (sh) {
7484 case 0x0: /* move program status register */
7485 if (op1 & 1) {
7486 /* PSR = reg */
7487 tmp = load_reg(s, rm);
7488 i = ((op1 & 2) != 0);
7489 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
7490 goto illegal_op;
7491 } else {
7492 /* reg = PSR */
7493 rd = (insn >> 12) & 0xf;
7494 if (op1 & 2) {
7495 if (IS_USER(s))
7496 goto illegal_op;
7497 tmp = load_cpu_field(spsr);
7498 } else {
7499 tmp = tcg_temp_new_i32();
7500 gen_helper_cpsr_read(tmp, cpu_env);
7502 store_reg(s, rd, tmp);
7504 break;
7505 case 0x1:
7506 if (op1 == 1) {
7507 /* branch/exchange thumb (bx). */
7508 ARCH(4T);
7509 tmp = load_reg(s, rm);
7510 gen_bx(s, tmp);
7511 } else if (op1 == 3) {
7512 /* clz */
7513 ARCH(5);
7514 rd = (insn >> 12) & 0xf;
7515 tmp = load_reg(s, rm);
7516 gen_helper_clz(tmp, tmp);
7517 store_reg(s, rd, tmp);
7518 } else {
7519 goto illegal_op;
7521 break;
7522 case 0x2:
7523 if (op1 == 1) {
7524 ARCH(5J); /* bxj */
7525 /* Trivial implementation equivalent to bx. */
7526 tmp = load_reg(s, rm);
7527 gen_bx(s, tmp);
7528 } else {
7529 goto illegal_op;
7531 break;
7532 case 0x3:
7533 if (op1 != 1)
7534 goto illegal_op;
7536 ARCH(5);
7537 /* branch link/exchange thumb (blx) */
7538 tmp = load_reg(s, rm);
7539 tmp2 = tcg_temp_new_i32();
7540 tcg_gen_movi_i32(tmp2, s->pc);
7541 store_reg(s, 14, tmp2);
7542 gen_bx(s, tmp);
7543 break;
7544 case 0x5: /* saturating add/subtract */
7545 ARCH(5TE);
7546 rd = (insn >> 12) & 0xf;
7547 rn = (insn >> 16) & 0xf;
7548 tmp = load_reg(s, rm);
7549 tmp2 = load_reg(s, rn);
7550 if (op1 & 2)
7551 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
7552 if (op1 & 1)
7553 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
7554 else
7555 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7556 tcg_temp_free_i32(tmp2);
7557 store_reg(s, rd, tmp);
7558 break;
7559 case 7:
7560 /* SMC instruction (op1 == 3)
7561 and undefined instructions (op1 == 0 || op1 == 2)
7562 will trap */
7563 if (op1 != 1) {
7564 goto illegal_op;
7566 /* bkpt */
7567 ARCH(5);
7568 gen_exception_insn(s, 4, EXCP_BKPT);
7569 break;
7570 case 0x8: /* signed multiply */
7571 case 0xa:
7572 case 0xc:
7573 case 0xe:
7574 ARCH(5TE);
7575 rs = (insn >> 8) & 0xf;
7576 rn = (insn >> 12) & 0xf;
7577 rd = (insn >> 16) & 0xf;
7578 if (op1 == 1) {
7579 /* (32 * 16) >> 16 */
7580 tmp = load_reg(s, rm);
7581 tmp2 = load_reg(s, rs);
7582 if (sh & 4)
7583 tcg_gen_sari_i32(tmp2, tmp2, 16);
7584 else
7585 gen_sxth(tmp2);
7586 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7587 tcg_gen_shri_i64(tmp64, tmp64, 16);
7588 tmp = tcg_temp_new_i32();
7589 tcg_gen_trunc_i64_i32(tmp, tmp64);
7590 tcg_temp_free_i64(tmp64);
7591 if ((sh & 2) == 0) {
7592 tmp2 = load_reg(s, rn);
7593 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7594 tcg_temp_free_i32(tmp2);
7596 store_reg(s, rd, tmp);
7597 } else {
7598 /* 16 * 16 */
7599 tmp = load_reg(s, rm);
7600 tmp2 = load_reg(s, rs);
7601 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7602 tcg_temp_free_i32(tmp2);
7603 if (op1 == 2) {
7604 tmp64 = tcg_temp_new_i64();
7605 tcg_gen_ext_i32_i64(tmp64, tmp);
7606 tcg_temp_free_i32(tmp);
7607 gen_addq(s, tmp64, rn, rd);
7608 gen_storeq_reg(s, rn, rd, tmp64);
7609 tcg_temp_free_i64(tmp64);
7610 } else {
7611 if (op1 == 0) {
7612 tmp2 = load_reg(s, rn);
7613 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7614 tcg_temp_free_i32(tmp2);
7616 store_reg(s, rd, tmp);
7619 break;
7620 default:
7621 goto illegal_op;
7623 } else if (((insn & 0x0e000000) == 0 &&
7624 (insn & 0x00000090) != 0x90) ||
7625 ((insn & 0x0e000000) == (1 << 25))) {
7626 int set_cc, logic_cc, shiftop;
7628 op1 = (insn >> 21) & 0xf;
7629 set_cc = (insn >> 20) & 1;
7630 logic_cc = table_logic_cc[op1] & set_cc;
7632 /* data processing instruction */
7633 if (insn & (1 << 25)) {
7634 /* immediate operand */
7635 val = insn & 0xff;
7636 shift = ((insn >> 8) & 0xf) * 2;
7637 if (shift) {
7638 val = (val >> shift) | (val << (32 - shift));
7640 tmp2 = tcg_temp_new_i32();
7641 tcg_gen_movi_i32(tmp2, val);
7642 if (logic_cc && shift) {
7643 gen_set_CF_bit31(tmp2);
7645 } else {
7646 /* register */
7647 rm = (insn) & 0xf;
7648 tmp2 = load_reg(s, rm);
7649 shiftop = (insn >> 5) & 3;
7650 if (!(insn & (1 << 4))) {
7651 shift = (insn >> 7) & 0x1f;
7652 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7653 } else {
7654 rs = (insn >> 8) & 0xf;
7655 tmp = load_reg(s, rs);
7656 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7659 if (op1 != 0x0f && op1 != 0x0d) {
7660 rn = (insn >> 16) & 0xf;
7661 tmp = load_reg(s, rn);
7662 } else {
7663 TCGV_UNUSED_I32(tmp);
7665 rd = (insn >> 12) & 0xf;
7666 switch(op1) {
7667 case 0x00:
7668 tcg_gen_and_i32(tmp, tmp, tmp2);
7669 if (logic_cc) {
7670 gen_logic_CC(tmp);
7672 store_reg_bx(env, s, rd, tmp);
7673 break;
7674 case 0x01:
7675 tcg_gen_xor_i32(tmp, tmp, tmp2);
7676 if (logic_cc) {
7677 gen_logic_CC(tmp);
7679 store_reg_bx(env, s, rd, tmp);
7680 break;
7681 case 0x02:
7682 if (set_cc && rd == 15) {
7683 /* SUBS r15, ... is used for exception return. */
7684 if (IS_USER(s)) {
7685 goto illegal_op;
7687 gen_sub_CC(tmp, tmp, tmp2);
7688 gen_exception_return(s, tmp);
7689 } else {
7690 if (set_cc) {
7691 gen_sub_CC(tmp, tmp, tmp2);
7692 } else {
7693 tcg_gen_sub_i32(tmp, tmp, tmp2);
7695 store_reg_bx(env, s, rd, tmp);
7697 break;
7698 case 0x03:
7699 if (set_cc) {
7700 gen_sub_CC(tmp, tmp2, tmp);
7701 } else {
7702 tcg_gen_sub_i32(tmp, tmp2, tmp);
7704 store_reg_bx(env, s, rd, tmp);
7705 break;
7706 case 0x04:
7707 if (set_cc) {
7708 gen_add_CC(tmp, tmp, tmp2);
7709 } else {
7710 tcg_gen_add_i32(tmp, tmp, tmp2);
7712 store_reg_bx(env, s, rd, tmp);
7713 break;
7714 case 0x05:
7715 if (set_cc) {
7716 gen_adc_CC(tmp, tmp, tmp2);
7717 } else {
7718 gen_add_carry(tmp, tmp, tmp2);
7720 store_reg_bx(env, s, rd, tmp);
7721 break;
7722 case 0x06:
7723 if (set_cc) {
7724 gen_sbc_CC(tmp, tmp, tmp2);
7725 } else {
7726 gen_sub_carry(tmp, tmp, tmp2);
7728 store_reg_bx(env, s, rd, tmp);
7729 break;
7730 case 0x07:
7731 if (set_cc) {
7732 gen_sbc_CC(tmp, tmp2, tmp);
7733 } else {
7734 gen_sub_carry(tmp, tmp2, tmp);
7736 store_reg_bx(env, s, rd, tmp);
7737 break;
7738 case 0x08:
7739 if (set_cc) {
7740 tcg_gen_and_i32(tmp, tmp, tmp2);
7741 gen_logic_CC(tmp);
7743 tcg_temp_free_i32(tmp);
7744 break;
7745 case 0x09:
7746 if (set_cc) {
7747 tcg_gen_xor_i32(tmp, tmp, tmp2);
7748 gen_logic_CC(tmp);
7750 tcg_temp_free_i32(tmp);
7751 break;
7752 case 0x0a:
7753 if (set_cc) {
7754 gen_sub_CC(tmp, tmp, tmp2);
7756 tcg_temp_free_i32(tmp);
7757 break;
7758 case 0x0b:
7759 if (set_cc) {
7760 gen_add_CC(tmp, tmp, tmp2);
7762 tcg_temp_free_i32(tmp);
7763 break;
7764 case 0x0c:
7765 tcg_gen_or_i32(tmp, tmp, tmp2);
7766 if (logic_cc) {
7767 gen_logic_CC(tmp);
7769 store_reg_bx(env, s, rd, tmp);
7770 break;
7771 case 0x0d:
7772 if (logic_cc && rd == 15) {
7773 /* MOVS r15, ... is used for exception return. */
7774 if (IS_USER(s)) {
7775 goto illegal_op;
7777 gen_exception_return(s, tmp2);
7778 } else {
7779 if (logic_cc) {
7780 gen_logic_CC(tmp2);
7782 store_reg_bx(env, s, rd, tmp2);
7784 break;
7785 case 0x0e:
7786 tcg_gen_andc_i32(tmp, tmp, tmp2);
7787 if (logic_cc) {
7788 gen_logic_CC(tmp);
7790 store_reg_bx(env, s, rd, tmp);
7791 break;
7792 default:
7793 case 0x0f:
7794 tcg_gen_not_i32(tmp2, tmp2);
7795 if (logic_cc) {
7796 gen_logic_CC(tmp2);
7798 store_reg_bx(env, s, rd, tmp2);
7799 break;
7801 if (op1 != 0x0f && op1 != 0x0d) {
7802 tcg_temp_free_i32(tmp2);
7804 } else {
7805 /* other instructions */
7806 op1 = (insn >> 24) & 0xf;
7807 switch(op1) {
7808 case 0x0:
7809 case 0x1:
7810 /* multiplies, extra load/stores */
7811 sh = (insn >> 5) & 3;
7812 if (sh == 0) {
7813 if (op1 == 0x0) {
7814 rd = (insn >> 16) & 0xf;
7815 rn = (insn >> 12) & 0xf;
7816 rs = (insn >> 8) & 0xf;
7817 rm = (insn) & 0xf;
7818 op1 = (insn >> 20) & 0xf;
7819 switch (op1) {
7820 case 0: case 1: case 2: case 3: case 6:
7821 /* 32 bit mul */
7822 tmp = load_reg(s, rs);
7823 tmp2 = load_reg(s, rm);
7824 tcg_gen_mul_i32(tmp, tmp, tmp2);
7825 tcg_temp_free_i32(tmp2);
7826 if (insn & (1 << 22)) {
7827 /* Subtract (mls) */
7828 ARCH(6T2);
7829 tmp2 = load_reg(s, rn);
7830 tcg_gen_sub_i32(tmp, tmp2, tmp);
7831 tcg_temp_free_i32(tmp2);
7832 } else if (insn & (1 << 21)) {
7833 /* Add */
7834 tmp2 = load_reg(s, rn);
7835 tcg_gen_add_i32(tmp, tmp, tmp2);
7836 tcg_temp_free_i32(tmp2);
7838 if (insn & (1 << 20))
7839 gen_logic_CC(tmp);
7840 store_reg(s, rd, tmp);
7841 break;
7842 case 4:
7843 /* 64 bit mul double accumulate (UMAAL) */
7844 ARCH(6);
7845 tmp = load_reg(s, rs);
7846 tmp2 = load_reg(s, rm);
7847 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7848 gen_addq_lo(s, tmp64, rn);
7849 gen_addq_lo(s, tmp64, rd);
7850 gen_storeq_reg(s, rn, rd, tmp64);
7851 tcg_temp_free_i64(tmp64);
7852 break;
7853 case 8: case 9: case 10: case 11:
7854 case 12: case 13: case 14: case 15:
7855 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7856 tmp = load_reg(s, rs);
7857 tmp2 = load_reg(s, rm);
7858 if (insn & (1 << 22)) {
7859 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
7860 } else {
7861 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
7863 if (insn & (1 << 21)) { /* mult accumulate */
7864 TCGv_i32 al = load_reg(s, rn);
7865 TCGv_i32 ah = load_reg(s, rd);
7866 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
7867 tcg_temp_free_i32(al);
7868 tcg_temp_free_i32(ah);
7870 if (insn & (1 << 20)) {
7871 gen_logicq_cc(tmp, tmp2);
7873 store_reg(s, rn, tmp);
7874 store_reg(s, rd, tmp2);
7875 break;
7876 default:
7877 goto illegal_op;
7879 } else {
7880 rn = (insn >> 16) & 0xf;
7881 rd = (insn >> 12) & 0xf;
7882 if (insn & (1 << 23)) {
7883 /* load/store exclusive */
7884 int op2 = (insn >> 8) & 3;
7885 op1 = (insn >> 21) & 0x3;
7887 switch (op2) {
7888 case 0: /* lda/stl */
7889 if (op1 == 1) {
7890 goto illegal_op;
7892 ARCH(8);
7893 break;
7894 case 1: /* reserved */
7895 goto illegal_op;
7896 case 2: /* ldaex/stlex */
7897 ARCH(8);
7898 break;
7899 case 3: /* ldrex/strex */
7900 if (op1) {
7901 ARCH(6K);
7902 } else {
7903 ARCH(6);
7905 break;
7908 addr = tcg_temp_local_new_i32();
7909 load_reg_var(s, addr, rn);
7911 /* Since the emulation does not have barriers,
7912 the acquire/release semantics need no special
7913 handling */
7914 if (op2 == 0) {
7915 if (insn & (1 << 20)) {
7916 tmp = tcg_temp_new_i32();
7917 switch (op1) {
7918 case 0: /* lda */
7919 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7920 break;
7921 case 2: /* ldab */
7922 gen_aa32_ld8u(tmp, addr, IS_USER(s));
7923 break;
7924 case 3: /* ldah */
7925 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7926 break;
7927 default:
7928 abort();
7930 store_reg(s, rd, tmp);
7931 } else {
7932 rm = insn & 0xf;
7933 tmp = load_reg(s, rm);
7934 switch (op1) {
7935 case 0: /* stl */
7936 gen_aa32_st32(tmp, addr, IS_USER(s));
7937 break;
7938 case 2: /* stlb */
7939 gen_aa32_st8(tmp, addr, IS_USER(s));
7940 break;
7941 case 3: /* stlh */
7942 gen_aa32_st16(tmp, addr, IS_USER(s));
7943 break;
7944 default:
7945 abort();
7947 tcg_temp_free_i32(tmp);
7949 } else if (insn & (1 << 20)) {
7950 switch (op1) {
7951 case 0: /* ldrex */
7952 gen_load_exclusive(s, rd, 15, addr, 2);
7953 break;
7954 case 1: /* ldrexd */
7955 gen_load_exclusive(s, rd, rd + 1, addr, 3);
7956 break;
7957 case 2: /* ldrexb */
7958 gen_load_exclusive(s, rd, 15, addr, 0);
7959 break;
7960 case 3: /* ldrexh */
7961 gen_load_exclusive(s, rd, 15, addr, 1);
7962 break;
7963 default:
7964 abort();
7966 } else {
7967 rm = insn & 0xf;
7968 switch (op1) {
7969 case 0: /* strex */
7970 gen_store_exclusive(s, rd, rm, 15, addr, 2);
7971 break;
7972 case 1: /* strexd */
7973 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
7974 break;
7975 case 2: /* strexb */
7976 gen_store_exclusive(s, rd, rm, 15, addr, 0);
7977 break;
7978 case 3: /* strexh */
7979 gen_store_exclusive(s, rd, rm, 15, addr, 1);
7980 break;
7981 default:
7982 abort();
7985 tcg_temp_free_i32(addr);
7986 } else {
7987 /* SWP instruction */
7988 rm = (insn) & 0xf;
7990 /* ??? This is not really atomic. However we know
7991 we never have multiple CPUs running in parallel,
7992 so it is good enough. */
7993 addr = load_reg(s, rn);
7994 tmp = load_reg(s, rm);
7995 tmp2 = tcg_temp_new_i32();
7996 if (insn & (1 << 22)) {
7997 gen_aa32_ld8u(tmp2, addr, IS_USER(s));
7998 gen_aa32_st8(tmp, addr, IS_USER(s));
7999 } else {
8000 gen_aa32_ld32u(tmp2, addr, IS_USER(s));
8001 gen_aa32_st32(tmp, addr, IS_USER(s));
8003 tcg_temp_free_i32(tmp);
8004 tcg_temp_free_i32(addr);
8005 store_reg(s, rd, tmp2);
8008 } else {
8009 int address_offset;
8010 int load;
8011 /* Misc load/store */
8012 rn = (insn >> 16) & 0xf;
8013 rd = (insn >> 12) & 0xf;
8014 addr = load_reg(s, rn);
8015 if (insn & (1 << 24))
8016 gen_add_datah_offset(s, insn, 0, addr);
8017 address_offset = 0;
8018 if (insn & (1 << 20)) {
8019 /* load */
8020 tmp = tcg_temp_new_i32();
8021 switch(sh) {
8022 case 1:
8023 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8024 break;
8025 case 2:
8026 gen_aa32_ld8s(tmp, addr, IS_USER(s));
8027 break;
8028 default:
8029 case 3:
8030 gen_aa32_ld16s(tmp, addr, IS_USER(s));
8031 break;
8033 load = 1;
8034 } else if (sh & 2) {
8035 ARCH(5TE);
8036 /* doubleword */
8037 if (sh & 1) {
8038 /* store */
8039 tmp = load_reg(s, rd);
8040 gen_aa32_st32(tmp, addr, IS_USER(s));
8041 tcg_temp_free_i32(tmp);
8042 tcg_gen_addi_i32(addr, addr, 4);
8043 tmp = load_reg(s, rd + 1);
8044 gen_aa32_st32(tmp, addr, IS_USER(s));
8045 tcg_temp_free_i32(tmp);
8046 load = 0;
8047 } else {
8048 /* load */
8049 tmp = tcg_temp_new_i32();
8050 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8051 store_reg(s, rd, tmp);
8052 tcg_gen_addi_i32(addr, addr, 4);
8053 tmp = tcg_temp_new_i32();
8054 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8055 rd++;
8056 load = 1;
8058 address_offset = -4;
8059 } else {
8060 /* store */
8061 tmp = load_reg(s, rd);
8062 gen_aa32_st16(tmp, addr, IS_USER(s));
8063 tcg_temp_free_i32(tmp);
8064 load = 0;
8066 /* Perform base writeback before the loaded value to
8067 ensure correct behavior with overlapping index registers.
8068 ldrd with base writeback is is undefined if the
8069 destination and index registers overlap. */
8070 if (!(insn & (1 << 24))) {
8071 gen_add_datah_offset(s, insn, address_offset, addr);
8072 store_reg(s, rn, addr);
8073 } else if (insn & (1 << 21)) {
8074 if (address_offset)
8075 tcg_gen_addi_i32(addr, addr, address_offset);
8076 store_reg(s, rn, addr);
8077 } else {
8078 tcg_temp_free_i32(addr);
8080 if (load) {
8081 /* Complete the load. */
8082 store_reg(s, rd, tmp);
8085 break;
8086 case 0x4:
8087 case 0x5:
8088 goto do_ldst;
8089 case 0x6:
8090 case 0x7:
8091 if (insn & (1 << 4)) {
8092 ARCH(6);
8093 /* Armv6 Media instructions. */
8094 rm = insn & 0xf;
8095 rn = (insn >> 16) & 0xf;
8096 rd = (insn >> 12) & 0xf;
8097 rs = (insn >> 8) & 0xf;
8098 switch ((insn >> 23) & 3) {
8099 case 0: /* Parallel add/subtract. */
8100 op1 = (insn >> 20) & 7;
8101 tmp = load_reg(s, rn);
8102 tmp2 = load_reg(s, rm);
8103 sh = (insn >> 5) & 7;
8104 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8105 goto illegal_op;
8106 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
8107 tcg_temp_free_i32(tmp2);
8108 store_reg(s, rd, tmp);
8109 break;
8110 case 1:
8111 if ((insn & 0x00700020) == 0) {
8112 /* Halfword pack. */
8113 tmp = load_reg(s, rn);
8114 tmp2 = load_reg(s, rm);
8115 shift = (insn >> 7) & 0x1f;
8116 if (insn & (1 << 6)) {
8117 /* pkhtb */
8118 if (shift == 0)
8119 shift = 31;
8120 tcg_gen_sari_i32(tmp2, tmp2, shift);
8121 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8122 tcg_gen_ext16u_i32(tmp2, tmp2);
8123 } else {
8124 /* pkhbt */
8125 if (shift)
8126 tcg_gen_shli_i32(tmp2, tmp2, shift);
8127 tcg_gen_ext16u_i32(tmp, tmp);
8128 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8130 tcg_gen_or_i32(tmp, tmp, tmp2);
8131 tcg_temp_free_i32(tmp2);
8132 store_reg(s, rd, tmp);
8133 } else if ((insn & 0x00200020) == 0x00200000) {
8134 /* [us]sat */
8135 tmp = load_reg(s, rm);
8136 shift = (insn >> 7) & 0x1f;
8137 if (insn & (1 << 6)) {
8138 if (shift == 0)
8139 shift = 31;
8140 tcg_gen_sari_i32(tmp, tmp, shift);
8141 } else {
8142 tcg_gen_shli_i32(tmp, tmp, shift);
8144 sh = (insn >> 16) & 0x1f;
8145 tmp2 = tcg_const_i32(sh);
8146 if (insn & (1 << 22))
8147 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
8148 else
8149 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
8150 tcg_temp_free_i32(tmp2);
8151 store_reg(s, rd, tmp);
8152 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8153 /* [us]sat16 */
8154 tmp = load_reg(s, rm);
8155 sh = (insn >> 16) & 0x1f;
8156 tmp2 = tcg_const_i32(sh);
8157 if (insn & (1 << 22))
8158 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
8159 else
8160 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
8161 tcg_temp_free_i32(tmp2);
8162 store_reg(s, rd, tmp);
8163 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8164 /* Select bytes. */
8165 tmp = load_reg(s, rn);
8166 tmp2 = load_reg(s, rm);
8167 tmp3 = tcg_temp_new_i32();
8168 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8169 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8170 tcg_temp_free_i32(tmp3);
8171 tcg_temp_free_i32(tmp2);
8172 store_reg(s, rd, tmp);
8173 } else if ((insn & 0x000003e0) == 0x00000060) {
8174 tmp = load_reg(s, rm);
8175 shift = (insn >> 10) & 3;
8176 /* ??? In many cases it's not necessary to do a
8177 rotate, a shift is sufficient. */
8178 if (shift != 0)
8179 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8180 op1 = (insn >> 20) & 7;
8181 switch (op1) {
8182 case 0: gen_sxtb16(tmp); break;
8183 case 2: gen_sxtb(tmp); break;
8184 case 3: gen_sxth(tmp); break;
8185 case 4: gen_uxtb16(tmp); break;
8186 case 6: gen_uxtb(tmp); break;
8187 case 7: gen_uxth(tmp); break;
8188 default: goto illegal_op;
8190 if (rn != 15) {
8191 tmp2 = load_reg(s, rn);
8192 if ((op1 & 3) == 0) {
8193 gen_add16(tmp, tmp2);
8194 } else {
8195 tcg_gen_add_i32(tmp, tmp, tmp2);
8196 tcg_temp_free_i32(tmp2);
8199 store_reg(s, rd, tmp);
8200 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
8201 /* rev */
8202 tmp = load_reg(s, rm);
8203 if (insn & (1 << 22)) {
8204 if (insn & (1 << 7)) {
8205 gen_revsh(tmp);
8206 } else {
8207 ARCH(6T2);
8208 gen_helper_rbit(tmp, tmp);
8210 } else {
8211 if (insn & (1 << 7))
8212 gen_rev16(tmp);
8213 else
8214 tcg_gen_bswap32_i32(tmp, tmp);
8216 store_reg(s, rd, tmp);
8217 } else {
8218 goto illegal_op;
8220 break;
8221 case 2: /* Multiplies (Type 3). */
8222 switch ((insn >> 20) & 0x7) {
8223 case 5:
8224 if (((insn >> 6) ^ (insn >> 7)) & 1) {
8225 /* op2 not 00x or 11x : UNDEF */
8226 goto illegal_op;
8228 /* Signed multiply most significant [accumulate].
8229 (SMMUL, SMMLA, SMMLS) */
8230 tmp = load_reg(s, rm);
8231 tmp2 = load_reg(s, rs);
8232 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8234 if (rd != 15) {
8235 tmp = load_reg(s, rd);
8236 if (insn & (1 << 6)) {
8237 tmp64 = gen_subq_msw(tmp64, tmp);
8238 } else {
8239 tmp64 = gen_addq_msw(tmp64, tmp);
8242 if (insn & (1 << 5)) {
8243 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8245 tcg_gen_shri_i64(tmp64, tmp64, 32);
8246 tmp = tcg_temp_new_i32();
8247 tcg_gen_trunc_i64_i32(tmp, tmp64);
8248 tcg_temp_free_i64(tmp64);
8249 store_reg(s, rn, tmp);
8250 break;
8251 case 0:
8252 case 4:
8253 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
8254 if (insn & (1 << 7)) {
8255 goto illegal_op;
8257 tmp = load_reg(s, rm);
8258 tmp2 = load_reg(s, rs);
8259 if (insn & (1 << 5))
8260 gen_swap_half(tmp2);
8261 gen_smul_dual(tmp, tmp2);
8262 if (insn & (1 << 6)) {
8263 /* This subtraction cannot overflow. */
8264 tcg_gen_sub_i32(tmp, tmp, tmp2);
8265 } else {
8266 /* This addition cannot overflow 32 bits;
8267 * however it may overflow considered as a signed
8268 * operation, in which case we must set the Q flag.
8270 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8272 tcg_temp_free_i32(tmp2);
8273 if (insn & (1 << 22)) {
8274 /* smlald, smlsld */
8275 tmp64 = tcg_temp_new_i64();
8276 tcg_gen_ext_i32_i64(tmp64, tmp);
8277 tcg_temp_free_i32(tmp);
8278 gen_addq(s, tmp64, rd, rn);
8279 gen_storeq_reg(s, rd, rn, tmp64);
8280 tcg_temp_free_i64(tmp64);
8281 } else {
8282 /* smuad, smusd, smlad, smlsd */
8283 if (rd != 15)
8285 tmp2 = load_reg(s, rd);
8286 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8287 tcg_temp_free_i32(tmp2);
8289 store_reg(s, rn, tmp);
8291 break;
8292 case 1:
8293 case 3:
8294 /* SDIV, UDIV */
8295 if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
8296 goto illegal_op;
8298 if (((insn >> 5) & 7) || (rd != 15)) {
8299 goto illegal_op;
8301 tmp = load_reg(s, rm);
8302 tmp2 = load_reg(s, rs);
8303 if (insn & (1 << 21)) {
8304 gen_helper_udiv(tmp, tmp, tmp2);
8305 } else {
8306 gen_helper_sdiv(tmp, tmp, tmp2);
8308 tcg_temp_free_i32(tmp2);
8309 store_reg(s, rn, tmp);
8310 break;
8311 default:
8312 goto illegal_op;
8314 break;
8315 case 3:
8316 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8317 switch (op1) {
8318 case 0: /* Unsigned sum of absolute differences. */
8319 ARCH(6);
8320 tmp = load_reg(s, rm);
8321 tmp2 = load_reg(s, rs);
8322 gen_helper_usad8(tmp, tmp, tmp2);
8323 tcg_temp_free_i32(tmp2);
8324 if (rd != 15) {
8325 tmp2 = load_reg(s, rd);
8326 tcg_gen_add_i32(tmp, tmp, tmp2);
8327 tcg_temp_free_i32(tmp2);
8329 store_reg(s, rn, tmp);
8330 break;
8331 case 0x20: case 0x24: case 0x28: case 0x2c:
8332 /* Bitfield insert/clear. */
8333 ARCH(6T2);
8334 shift = (insn >> 7) & 0x1f;
8335 i = (insn >> 16) & 0x1f;
8336 i = i + 1 - shift;
8337 if (rm == 15) {
8338 tmp = tcg_temp_new_i32();
8339 tcg_gen_movi_i32(tmp, 0);
8340 } else {
8341 tmp = load_reg(s, rm);
8343 if (i != 32) {
8344 tmp2 = load_reg(s, rd);
8345 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
8346 tcg_temp_free_i32(tmp2);
8348 store_reg(s, rd, tmp);
8349 break;
8350 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8351 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
8352 ARCH(6T2);
8353 tmp = load_reg(s, rm);
8354 shift = (insn >> 7) & 0x1f;
8355 i = ((insn >> 16) & 0x1f) + 1;
8356 if (shift + i > 32)
8357 goto illegal_op;
8358 if (i < 32) {
8359 if (op1 & 0x20) {
8360 gen_ubfx(tmp, shift, (1u << i) - 1);
8361 } else {
8362 gen_sbfx(tmp, shift, i);
8365 store_reg(s, rd, tmp);
8366 break;
8367 default:
8368 goto illegal_op;
8370 break;
8372 break;
8374 do_ldst:
8375 /* Check for undefined extension instructions
8376 * per the ARM Bible IE:
8377 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
8379 sh = (0xf << 20) | (0xf << 4);
8380 if (op1 == 0x7 && ((insn & sh) == sh))
8382 goto illegal_op;
8384 /* load/store byte/word */
8385 rn = (insn >> 16) & 0xf;
8386 rd = (insn >> 12) & 0xf;
8387 tmp2 = load_reg(s, rn);
8388 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
8389 if (insn & (1 << 24))
8390 gen_add_data_offset(s, insn, tmp2);
8391 if (insn & (1 << 20)) {
8392 /* load */
8393 tmp = tcg_temp_new_i32();
8394 if (insn & (1 << 22)) {
8395 gen_aa32_ld8u(tmp, tmp2, i);
8396 } else {
8397 gen_aa32_ld32u(tmp, tmp2, i);
8399 } else {
8400 /* store */
8401 tmp = load_reg(s, rd);
8402 if (insn & (1 << 22)) {
8403 gen_aa32_st8(tmp, tmp2, i);
8404 } else {
8405 gen_aa32_st32(tmp, tmp2, i);
8407 tcg_temp_free_i32(tmp);
8409 if (!(insn & (1 << 24))) {
8410 gen_add_data_offset(s, insn, tmp2);
8411 store_reg(s, rn, tmp2);
8412 } else if (insn & (1 << 21)) {
8413 store_reg(s, rn, tmp2);
8414 } else {
8415 tcg_temp_free_i32(tmp2);
8417 if (insn & (1 << 20)) {
8418 /* Complete the load. */
8419 store_reg_from_load(env, s, rd, tmp);
8421 break;
8422 case 0x08:
8423 case 0x09:
8425 int j, n, user, loaded_base;
8426 TCGv_i32 loaded_var;
8427 /* load/store multiple words */
8428 /* XXX: store correct base if write back */
8429 user = 0;
8430 if (insn & (1 << 22)) {
8431 if (IS_USER(s))
8432 goto illegal_op; /* only usable in supervisor mode */
8434 if ((insn & (1 << 15)) == 0)
8435 user = 1;
8437 rn = (insn >> 16) & 0xf;
8438 addr = load_reg(s, rn);
8440 /* compute total size */
8441 loaded_base = 0;
8442 TCGV_UNUSED_I32(loaded_var);
8443 n = 0;
8444 for(i=0;i<16;i++) {
8445 if (insn & (1 << i))
8446 n++;
8448 /* XXX: test invalid n == 0 case ? */
8449 if (insn & (1 << 23)) {
8450 if (insn & (1 << 24)) {
8451 /* pre increment */
8452 tcg_gen_addi_i32(addr, addr, 4);
8453 } else {
8454 /* post increment */
8456 } else {
8457 if (insn & (1 << 24)) {
8458 /* pre decrement */
8459 tcg_gen_addi_i32(addr, addr, -(n * 4));
8460 } else {
8461 /* post decrement */
8462 if (n != 1)
8463 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8466 j = 0;
8467 for(i=0;i<16;i++) {
8468 if (insn & (1 << i)) {
8469 if (insn & (1 << 20)) {
8470 /* load */
8471 tmp = tcg_temp_new_i32();
8472 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8473 if (user) {
8474 tmp2 = tcg_const_i32(i);
8475 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
8476 tcg_temp_free_i32(tmp2);
8477 tcg_temp_free_i32(tmp);
8478 } else if (i == rn) {
8479 loaded_var = tmp;
8480 loaded_base = 1;
8481 } else {
8482 store_reg_from_load(env, s, i, tmp);
8484 } else {
8485 /* store */
8486 if (i == 15) {
8487 /* special case: r15 = PC + 8 */
8488 val = (long)s->pc + 4;
8489 tmp = tcg_temp_new_i32();
8490 tcg_gen_movi_i32(tmp, val);
8491 } else if (user) {
8492 tmp = tcg_temp_new_i32();
8493 tmp2 = tcg_const_i32(i);
8494 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
8495 tcg_temp_free_i32(tmp2);
8496 } else {
8497 tmp = load_reg(s, i);
8499 gen_aa32_st32(tmp, addr, IS_USER(s));
8500 tcg_temp_free_i32(tmp);
8502 j++;
8503 /* no need to add after the last transfer */
8504 if (j != n)
8505 tcg_gen_addi_i32(addr, addr, 4);
8508 if (insn & (1 << 21)) {
8509 /* write back */
8510 if (insn & (1 << 23)) {
8511 if (insn & (1 << 24)) {
8512 /* pre increment */
8513 } else {
8514 /* post increment */
8515 tcg_gen_addi_i32(addr, addr, 4);
8517 } else {
8518 if (insn & (1 << 24)) {
8519 /* pre decrement */
8520 if (n != 1)
8521 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8522 } else {
8523 /* post decrement */
8524 tcg_gen_addi_i32(addr, addr, -(n * 4));
8527 store_reg(s, rn, addr);
8528 } else {
8529 tcg_temp_free_i32(addr);
8531 if (loaded_base) {
8532 store_reg(s, rn, loaded_var);
8534 if ((insn & (1 << 22)) && !user) {
8535 /* Restore CPSR from SPSR. */
8536 tmp = load_cpu_field(spsr);
8537 gen_set_cpsr(tmp, 0xffffffff);
8538 tcg_temp_free_i32(tmp);
8539 s->is_jmp = DISAS_UPDATE;
8542 break;
8543 case 0xa:
8544 case 0xb:
8546 int32_t offset;
8548 /* branch (and link) */
8549 val = (int32_t)s->pc;
8550 if (insn & (1 << 24)) {
8551 tmp = tcg_temp_new_i32();
8552 tcg_gen_movi_i32(tmp, val);
8553 store_reg(s, 14, tmp);
8555 offset = sextract32(insn << 2, 0, 26);
8556 val += offset + 4;
8557 gen_jmp(s, val);
8559 break;
8560 case 0xc:
8561 case 0xd:
8562 case 0xe:
8563 if (((insn >> 8) & 0xe) == 10) {
8564 /* VFP. */
8565 if (disas_vfp_insn(env, s, insn)) {
8566 goto illegal_op;
8568 } else if (disas_coproc_insn(env, s, insn)) {
8569 /* Coprocessor. */
8570 goto illegal_op;
8572 break;
8573 case 0xf:
8574 /* swi */
8575 gen_set_pc_im(s, s->pc);
8576 s->is_jmp = DISAS_SWI;
8577 break;
8578 default:
8579 illegal_op:
8580 gen_exception_insn(s, 4, EXCP_UDEF);
8581 break;
8586 /* Return true if this is a Thumb-2 logical op. */
8587 static int
8588 thumb2_logic_op(int op)
8590 return (op < 8);
8593 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
8594 then set condition code flags based on the result of the operation.
8595 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
8596 to the high bit of T1.
8597 Returns zero if the opcode is valid. */
8599 static int
8600 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
8601 TCGv_i32 t0, TCGv_i32 t1)
8603 int logic_cc;
8605 logic_cc = 0;
8606 switch (op) {
8607 case 0: /* and */
8608 tcg_gen_and_i32(t0, t0, t1);
8609 logic_cc = conds;
8610 break;
8611 case 1: /* bic */
8612 tcg_gen_andc_i32(t0, t0, t1);
8613 logic_cc = conds;
8614 break;
8615 case 2: /* orr */
8616 tcg_gen_or_i32(t0, t0, t1);
8617 logic_cc = conds;
8618 break;
8619 case 3: /* orn */
8620 tcg_gen_orc_i32(t0, t0, t1);
8621 logic_cc = conds;
8622 break;
8623 case 4: /* eor */
8624 tcg_gen_xor_i32(t0, t0, t1);
8625 logic_cc = conds;
8626 break;
8627 case 8: /* add */
8628 if (conds)
8629 gen_add_CC(t0, t0, t1);
8630 else
8631 tcg_gen_add_i32(t0, t0, t1);
8632 break;
8633 case 10: /* adc */
8634 if (conds)
8635 gen_adc_CC(t0, t0, t1);
8636 else
8637 gen_adc(t0, t1);
8638 break;
8639 case 11: /* sbc */
8640 if (conds) {
8641 gen_sbc_CC(t0, t0, t1);
8642 } else {
8643 gen_sub_carry(t0, t0, t1);
8645 break;
8646 case 13: /* sub */
8647 if (conds)
8648 gen_sub_CC(t0, t0, t1);
8649 else
8650 tcg_gen_sub_i32(t0, t0, t1);
8651 break;
8652 case 14: /* rsb */
8653 if (conds)
8654 gen_sub_CC(t0, t1, t0);
8655 else
8656 tcg_gen_sub_i32(t0, t1, t0);
8657 break;
8658 default: /* 5, 6, 7, 9, 12, 15. */
8659 return 1;
8661 if (logic_cc) {
8662 gen_logic_CC(t0);
8663 if (shifter_out)
8664 gen_set_CF_bit31(t1);
8666 return 0;
8669 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
8670 is not legal. */
8671 static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
8673 uint32_t insn, imm, shift, offset;
8674 uint32_t rd, rn, rm, rs;
8675 TCGv_i32 tmp;
8676 TCGv_i32 tmp2;
8677 TCGv_i32 tmp3;
8678 TCGv_i32 addr;
8679 TCGv_i64 tmp64;
8680 int op;
8681 int shiftop;
8682 int conds;
8683 int logic_cc;
8685 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
8686 || arm_feature (env, ARM_FEATURE_M))) {
8687 /* Thumb-1 cores may need to treat bl and blx as a pair of
8688 16-bit instructions to get correct prefetch abort behavior. */
8689 insn = insn_hw1;
8690 if ((insn & (1 << 12)) == 0) {
8691 ARCH(5);
8692 /* Second half of blx. */
8693 offset = ((insn & 0x7ff) << 1);
8694 tmp = load_reg(s, 14);
8695 tcg_gen_addi_i32(tmp, tmp, offset);
8696 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8698 tmp2 = tcg_temp_new_i32();
8699 tcg_gen_movi_i32(tmp2, s->pc | 1);
8700 store_reg(s, 14, tmp2);
8701 gen_bx(s, tmp);
8702 return 0;
8704 if (insn & (1 << 11)) {
8705 /* Second half of bl. */
8706 offset = ((insn & 0x7ff) << 1) | 1;
8707 tmp = load_reg(s, 14);
8708 tcg_gen_addi_i32(tmp, tmp, offset);
8710 tmp2 = tcg_temp_new_i32();
8711 tcg_gen_movi_i32(tmp2, s->pc | 1);
8712 store_reg(s, 14, tmp2);
8713 gen_bx(s, tmp);
8714 return 0;
8716 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
8717 /* Instruction spans a page boundary. Implement it as two
8718 16-bit instructions in case the second half causes an
8719 prefetch abort. */
8720 offset = ((int32_t)insn << 21) >> 9;
8721 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
8722 return 0;
8724 /* Fall through to 32-bit decode. */
8727 insn = arm_lduw_code(env, s->pc, s->bswap_code);
8728 s->pc += 2;
8729 insn |= (uint32_t)insn_hw1 << 16;
8731 if ((insn & 0xf800e800) != 0xf000e800) {
8732 ARCH(6T2);
8735 rn = (insn >> 16) & 0xf;
8736 rs = (insn >> 12) & 0xf;
8737 rd = (insn >> 8) & 0xf;
8738 rm = insn & 0xf;
8739 switch ((insn >> 25) & 0xf) {
8740 case 0: case 1: case 2: case 3:
8741 /* 16-bit instructions. Should never happen. */
8742 abort();
8743 case 4:
8744 if (insn & (1 << 22)) {
8745 /* Other load/store, table branch. */
8746 if (insn & 0x01200000) {
8747 /* Load/store doubleword. */
8748 if (rn == 15) {
8749 addr = tcg_temp_new_i32();
8750 tcg_gen_movi_i32(addr, s->pc & ~3);
8751 } else {
8752 addr = load_reg(s, rn);
8754 offset = (insn & 0xff) * 4;
8755 if ((insn & (1 << 23)) == 0)
8756 offset = -offset;
8757 if (insn & (1 << 24)) {
8758 tcg_gen_addi_i32(addr, addr, offset);
8759 offset = 0;
8761 if (insn & (1 << 20)) {
8762 /* ldrd */
8763 tmp = tcg_temp_new_i32();
8764 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8765 store_reg(s, rs, tmp);
8766 tcg_gen_addi_i32(addr, addr, 4);
8767 tmp = tcg_temp_new_i32();
8768 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8769 store_reg(s, rd, tmp);
8770 } else {
8771 /* strd */
8772 tmp = load_reg(s, rs);
8773 gen_aa32_st32(tmp, addr, IS_USER(s));
8774 tcg_temp_free_i32(tmp);
8775 tcg_gen_addi_i32(addr, addr, 4);
8776 tmp = load_reg(s, rd);
8777 gen_aa32_st32(tmp, addr, IS_USER(s));
8778 tcg_temp_free_i32(tmp);
8780 if (insn & (1 << 21)) {
8781 /* Base writeback. */
8782 if (rn == 15)
8783 goto illegal_op;
8784 tcg_gen_addi_i32(addr, addr, offset - 4);
8785 store_reg(s, rn, addr);
8786 } else {
8787 tcg_temp_free_i32(addr);
8789 } else if ((insn & (1 << 23)) == 0) {
8790 /* Load/store exclusive word. */
8791 addr = tcg_temp_local_new_i32();
8792 load_reg_var(s, addr, rn);
8793 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
8794 if (insn & (1 << 20)) {
8795 gen_load_exclusive(s, rs, 15, addr, 2);
8796 } else {
8797 gen_store_exclusive(s, rd, rs, 15, addr, 2);
8799 tcg_temp_free_i32(addr);
8800 } else if ((insn & (7 << 5)) == 0) {
8801 /* Table Branch. */
8802 if (rn == 15) {
8803 addr = tcg_temp_new_i32();
8804 tcg_gen_movi_i32(addr, s->pc);
8805 } else {
8806 addr = load_reg(s, rn);
8808 tmp = load_reg(s, rm);
8809 tcg_gen_add_i32(addr, addr, tmp);
8810 if (insn & (1 << 4)) {
8811 /* tbh */
8812 tcg_gen_add_i32(addr, addr, tmp);
8813 tcg_temp_free_i32(tmp);
8814 tmp = tcg_temp_new_i32();
8815 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8816 } else { /* tbb */
8817 tcg_temp_free_i32(tmp);
8818 tmp = tcg_temp_new_i32();
8819 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8821 tcg_temp_free_i32(addr);
8822 tcg_gen_shli_i32(tmp, tmp, 1);
8823 tcg_gen_addi_i32(tmp, tmp, s->pc);
8824 store_reg(s, 15, tmp);
8825 } else {
8826 int op2 = (insn >> 6) & 0x3;
8827 op = (insn >> 4) & 0x3;
8828 switch (op2) {
8829 case 0:
8830 goto illegal_op;
8831 case 1:
8832 /* Load/store exclusive byte/halfword/doubleword */
8833 if (op == 2) {
8834 goto illegal_op;
8836 ARCH(7);
8837 break;
8838 case 2:
8839 /* Load-acquire/store-release */
8840 if (op == 3) {
8841 goto illegal_op;
8843 /* Fall through */
8844 case 3:
8845 /* Load-acquire/store-release exclusive */
8846 ARCH(8);
8847 break;
8849 addr = tcg_temp_local_new_i32();
8850 load_reg_var(s, addr, rn);
8851 if (!(op2 & 1)) {
8852 if (insn & (1 << 20)) {
8853 tmp = tcg_temp_new_i32();
8854 switch (op) {
8855 case 0: /* ldab */
8856 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8857 break;
8858 case 1: /* ldah */
8859 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8860 break;
8861 case 2: /* lda */
8862 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8863 break;
8864 default:
8865 abort();
8867 store_reg(s, rs, tmp);
8868 } else {
8869 tmp = load_reg(s, rs);
8870 switch (op) {
8871 case 0: /* stlb */
8872 gen_aa32_st8(tmp, addr, IS_USER(s));
8873 break;
8874 case 1: /* stlh */
8875 gen_aa32_st16(tmp, addr, IS_USER(s));
8876 break;
8877 case 2: /* stl */
8878 gen_aa32_st32(tmp, addr, IS_USER(s));
8879 break;
8880 default:
8881 abort();
8883 tcg_temp_free_i32(tmp);
8885 } else if (insn & (1 << 20)) {
8886 gen_load_exclusive(s, rs, rd, addr, op);
8887 } else {
8888 gen_store_exclusive(s, rm, rs, rd, addr, op);
8890 tcg_temp_free_i32(addr);
8892 } else {
8893 /* Load/store multiple, RFE, SRS. */
8894 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
8895 /* RFE, SRS: not available in user mode or on M profile */
8896 if (IS_USER(s) || IS_M(env)) {
8897 goto illegal_op;
8899 if (insn & (1 << 20)) {
8900 /* rfe */
8901 addr = load_reg(s, rn);
8902 if ((insn & (1 << 24)) == 0)
8903 tcg_gen_addi_i32(addr, addr, -8);
8904 /* Load PC into tmp and CPSR into tmp2. */
8905 tmp = tcg_temp_new_i32();
8906 gen_aa32_ld32u(tmp, addr, 0);
8907 tcg_gen_addi_i32(addr, addr, 4);
8908 tmp2 = tcg_temp_new_i32();
8909 gen_aa32_ld32u(tmp2, addr, 0);
8910 if (insn & (1 << 21)) {
8911 /* Base writeback. */
8912 if (insn & (1 << 24)) {
8913 tcg_gen_addi_i32(addr, addr, 4);
8914 } else {
8915 tcg_gen_addi_i32(addr, addr, -4);
8917 store_reg(s, rn, addr);
8918 } else {
8919 tcg_temp_free_i32(addr);
8921 gen_rfe(s, tmp, tmp2);
8922 } else {
8923 /* srs */
8924 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
8925 insn & (1 << 21));
8927 } else {
8928 int i, loaded_base = 0;
8929 TCGv_i32 loaded_var;
8930 /* Load/store multiple. */
8931 addr = load_reg(s, rn);
8932 offset = 0;
8933 for (i = 0; i < 16; i++) {
8934 if (insn & (1 << i))
8935 offset += 4;
8937 if (insn & (1 << 24)) {
8938 tcg_gen_addi_i32(addr, addr, -offset);
8941 TCGV_UNUSED_I32(loaded_var);
8942 for (i = 0; i < 16; i++) {
8943 if ((insn & (1 << i)) == 0)
8944 continue;
8945 if (insn & (1 << 20)) {
8946 /* Load. */
8947 tmp = tcg_temp_new_i32();
8948 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8949 if (i == 15) {
8950 gen_bx(s, tmp);
8951 } else if (i == rn) {
8952 loaded_var = tmp;
8953 loaded_base = 1;
8954 } else {
8955 store_reg(s, i, tmp);
8957 } else {
8958 /* Store. */
8959 tmp = load_reg(s, i);
8960 gen_aa32_st32(tmp, addr, IS_USER(s));
8961 tcg_temp_free_i32(tmp);
8963 tcg_gen_addi_i32(addr, addr, 4);
8965 if (loaded_base) {
8966 store_reg(s, rn, loaded_var);
8968 if (insn & (1 << 21)) {
8969 /* Base register writeback. */
8970 if (insn & (1 << 24)) {
8971 tcg_gen_addi_i32(addr, addr, -offset);
8973 /* Fault if writeback register is in register list. */
8974 if (insn & (1 << rn))
8975 goto illegal_op;
8976 store_reg(s, rn, addr);
8977 } else {
8978 tcg_temp_free_i32(addr);
8982 break;
8983 case 5:
8985 op = (insn >> 21) & 0xf;
8986 if (op == 6) {
8987 /* Halfword pack. */
8988 tmp = load_reg(s, rn);
8989 tmp2 = load_reg(s, rm);
8990 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
8991 if (insn & (1 << 5)) {
8992 /* pkhtb */
8993 if (shift == 0)
8994 shift = 31;
8995 tcg_gen_sari_i32(tmp2, tmp2, shift);
8996 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8997 tcg_gen_ext16u_i32(tmp2, tmp2);
8998 } else {
8999 /* pkhbt */
9000 if (shift)
9001 tcg_gen_shli_i32(tmp2, tmp2, shift);
9002 tcg_gen_ext16u_i32(tmp, tmp);
9003 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9005 tcg_gen_or_i32(tmp, tmp, tmp2);
9006 tcg_temp_free_i32(tmp2);
9007 store_reg(s, rd, tmp);
9008 } else {
9009 /* Data processing register constant shift. */
9010 if (rn == 15) {
9011 tmp = tcg_temp_new_i32();
9012 tcg_gen_movi_i32(tmp, 0);
9013 } else {
9014 tmp = load_reg(s, rn);
9016 tmp2 = load_reg(s, rm);
9018 shiftop = (insn >> 4) & 3;
9019 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9020 conds = (insn & (1 << 20)) != 0;
9021 logic_cc = (conds && thumb2_logic_op(op));
9022 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9023 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9024 goto illegal_op;
9025 tcg_temp_free_i32(tmp2);
9026 if (rd != 15) {
9027 store_reg(s, rd, tmp);
9028 } else {
9029 tcg_temp_free_i32(tmp);
9032 break;
9033 case 13: /* Misc data processing. */
9034 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9035 if (op < 4 && (insn & 0xf000) != 0xf000)
9036 goto illegal_op;
9037 switch (op) {
9038 case 0: /* Register controlled shift. */
9039 tmp = load_reg(s, rn);
9040 tmp2 = load_reg(s, rm);
9041 if ((insn & 0x70) != 0)
9042 goto illegal_op;
9043 op = (insn >> 21) & 3;
9044 logic_cc = (insn & (1 << 20)) != 0;
9045 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9046 if (logic_cc)
9047 gen_logic_CC(tmp);
9048 store_reg_bx(env, s, rd, tmp);
9049 break;
9050 case 1: /* Sign/zero extend. */
9051 tmp = load_reg(s, rm);
9052 shift = (insn >> 4) & 3;
9053 /* ??? In many cases it's not necessary to do a
9054 rotate, a shift is sufficient. */
9055 if (shift != 0)
9056 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9057 op = (insn >> 20) & 7;
9058 switch (op) {
9059 case 0: gen_sxth(tmp); break;
9060 case 1: gen_uxth(tmp); break;
9061 case 2: gen_sxtb16(tmp); break;
9062 case 3: gen_uxtb16(tmp); break;
9063 case 4: gen_sxtb(tmp); break;
9064 case 5: gen_uxtb(tmp); break;
9065 default: goto illegal_op;
9067 if (rn != 15) {
9068 tmp2 = load_reg(s, rn);
9069 if ((op >> 1) == 1) {
9070 gen_add16(tmp, tmp2);
9071 } else {
9072 tcg_gen_add_i32(tmp, tmp, tmp2);
9073 tcg_temp_free_i32(tmp2);
9076 store_reg(s, rd, tmp);
9077 break;
9078 case 2: /* SIMD add/subtract. */
9079 op = (insn >> 20) & 7;
9080 shift = (insn >> 4) & 7;
9081 if ((op & 3) == 3 || (shift & 3) == 3)
9082 goto illegal_op;
9083 tmp = load_reg(s, rn);
9084 tmp2 = load_reg(s, rm);
9085 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
9086 tcg_temp_free_i32(tmp2);
9087 store_reg(s, rd, tmp);
9088 break;
9089 case 3: /* Other data processing. */
9090 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9091 if (op < 4) {
9092 /* Saturating add/subtract. */
9093 tmp = load_reg(s, rn);
9094 tmp2 = load_reg(s, rm);
9095 if (op & 1)
9096 gen_helper_double_saturate(tmp, cpu_env, tmp);
9097 if (op & 2)
9098 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9099 else
9100 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
9101 tcg_temp_free_i32(tmp2);
9102 } else {
9103 tmp = load_reg(s, rn);
9104 switch (op) {
9105 case 0x0a: /* rbit */
9106 gen_helper_rbit(tmp, tmp);
9107 break;
9108 case 0x08: /* rev */
9109 tcg_gen_bswap32_i32(tmp, tmp);
9110 break;
9111 case 0x09: /* rev16 */
9112 gen_rev16(tmp);
9113 break;
9114 case 0x0b: /* revsh */
9115 gen_revsh(tmp);
9116 break;
9117 case 0x10: /* sel */
9118 tmp2 = load_reg(s, rm);
9119 tmp3 = tcg_temp_new_i32();
9120 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
9121 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
9122 tcg_temp_free_i32(tmp3);
9123 tcg_temp_free_i32(tmp2);
9124 break;
9125 case 0x18: /* clz */
9126 gen_helper_clz(tmp, tmp);
9127 break;
9128 default:
9129 goto illegal_op;
9132 store_reg(s, rd, tmp);
9133 break;
9134 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
9135 op = (insn >> 4) & 0xf;
9136 tmp = load_reg(s, rn);
9137 tmp2 = load_reg(s, rm);
9138 switch ((insn >> 20) & 7) {
9139 case 0: /* 32 x 32 -> 32 */
9140 tcg_gen_mul_i32(tmp, tmp, tmp2);
9141 tcg_temp_free_i32(tmp2);
9142 if (rs != 15) {
9143 tmp2 = load_reg(s, rs);
9144 if (op)
9145 tcg_gen_sub_i32(tmp, tmp2, tmp);
9146 else
9147 tcg_gen_add_i32(tmp, tmp, tmp2);
9148 tcg_temp_free_i32(tmp2);
9150 break;
9151 case 1: /* 16 x 16 -> 32 */
9152 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9153 tcg_temp_free_i32(tmp2);
9154 if (rs != 15) {
9155 tmp2 = load_reg(s, rs);
9156 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9157 tcg_temp_free_i32(tmp2);
9159 break;
9160 case 2: /* Dual multiply add. */
9161 case 4: /* Dual multiply subtract. */
9162 if (op)
9163 gen_swap_half(tmp2);
9164 gen_smul_dual(tmp, tmp2);
9165 if (insn & (1 << 22)) {
9166 /* This subtraction cannot overflow. */
9167 tcg_gen_sub_i32(tmp, tmp, tmp2);
9168 } else {
9169 /* This addition cannot overflow 32 bits;
9170 * however it may overflow considered as a signed
9171 * operation, in which case we must set the Q flag.
9173 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9175 tcg_temp_free_i32(tmp2);
9176 if (rs != 15)
9178 tmp2 = load_reg(s, rs);
9179 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9180 tcg_temp_free_i32(tmp2);
9182 break;
9183 case 3: /* 32 * 16 -> 32msb */
9184 if (op)
9185 tcg_gen_sari_i32(tmp2, tmp2, 16);
9186 else
9187 gen_sxth(tmp2);
9188 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9189 tcg_gen_shri_i64(tmp64, tmp64, 16);
9190 tmp = tcg_temp_new_i32();
9191 tcg_gen_trunc_i64_i32(tmp, tmp64);
9192 tcg_temp_free_i64(tmp64);
9193 if (rs != 15)
9195 tmp2 = load_reg(s, rs);
9196 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9197 tcg_temp_free_i32(tmp2);
9199 break;
9200 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
9201 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9202 if (rs != 15) {
9203 tmp = load_reg(s, rs);
9204 if (insn & (1 << 20)) {
9205 tmp64 = gen_addq_msw(tmp64, tmp);
9206 } else {
9207 tmp64 = gen_subq_msw(tmp64, tmp);
9210 if (insn & (1 << 4)) {
9211 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9213 tcg_gen_shri_i64(tmp64, tmp64, 32);
9214 tmp = tcg_temp_new_i32();
9215 tcg_gen_trunc_i64_i32(tmp, tmp64);
9216 tcg_temp_free_i64(tmp64);
9217 break;
9218 case 7: /* Unsigned sum of absolute differences. */
9219 gen_helper_usad8(tmp, tmp, tmp2);
9220 tcg_temp_free_i32(tmp2);
9221 if (rs != 15) {
9222 tmp2 = load_reg(s, rs);
9223 tcg_gen_add_i32(tmp, tmp, tmp2);
9224 tcg_temp_free_i32(tmp2);
9226 break;
9228 store_reg(s, rd, tmp);
9229 break;
9230 case 6: case 7: /* 64-bit multiply, Divide. */
9231 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
9232 tmp = load_reg(s, rn);
9233 tmp2 = load_reg(s, rm);
9234 if ((op & 0x50) == 0x10) {
9235 /* sdiv, udiv */
9236 if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
9237 goto illegal_op;
9239 if (op & 0x20)
9240 gen_helper_udiv(tmp, tmp, tmp2);
9241 else
9242 gen_helper_sdiv(tmp, tmp, tmp2);
9243 tcg_temp_free_i32(tmp2);
9244 store_reg(s, rd, tmp);
9245 } else if ((op & 0xe) == 0xc) {
9246 /* Dual multiply accumulate long. */
9247 if (op & 1)
9248 gen_swap_half(tmp2);
9249 gen_smul_dual(tmp, tmp2);
9250 if (op & 0x10) {
9251 tcg_gen_sub_i32(tmp, tmp, tmp2);
9252 } else {
9253 tcg_gen_add_i32(tmp, tmp, tmp2);
9255 tcg_temp_free_i32(tmp2);
9256 /* BUGFIX */
9257 tmp64 = tcg_temp_new_i64();
9258 tcg_gen_ext_i32_i64(tmp64, tmp);
9259 tcg_temp_free_i32(tmp);
9260 gen_addq(s, tmp64, rs, rd);
9261 gen_storeq_reg(s, rs, rd, tmp64);
9262 tcg_temp_free_i64(tmp64);
9263 } else {
9264 if (op & 0x20) {
9265 /* Unsigned 64-bit multiply */
9266 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9267 } else {
9268 if (op & 8) {
9269 /* smlalxy */
9270 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9271 tcg_temp_free_i32(tmp2);
9272 tmp64 = tcg_temp_new_i64();
9273 tcg_gen_ext_i32_i64(tmp64, tmp);
9274 tcg_temp_free_i32(tmp);
9275 } else {
9276 /* Signed 64-bit multiply */
9277 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9280 if (op & 4) {
9281 /* umaal */
9282 gen_addq_lo(s, tmp64, rs);
9283 gen_addq_lo(s, tmp64, rd);
9284 } else if (op & 0x40) {
9285 /* 64-bit accumulate. */
9286 gen_addq(s, tmp64, rs, rd);
9288 gen_storeq_reg(s, rs, rd, tmp64);
9289 tcg_temp_free_i64(tmp64);
9291 break;
9293 break;
9294 case 6: case 7: case 14: case 15:
9295 /* Coprocessor. */
9296 if (((insn >> 24) & 3) == 3) {
9297 /* Translate into the equivalent ARM encoding. */
9298 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
9299 if (disas_neon_data_insn(env, s, insn))
9300 goto illegal_op;
9301 } else if (((insn >> 8) & 0xe) == 10) {
9302 if (disas_vfp_insn(env, s, insn)) {
9303 goto illegal_op;
9305 } else {
9306 if (insn & (1 << 28))
9307 goto illegal_op;
9308 if (disas_coproc_insn (env, s, insn))
9309 goto illegal_op;
9311 break;
9312 case 8: case 9: case 10: case 11:
9313 if (insn & (1 << 15)) {
9314 /* Branches, misc control. */
9315 if (insn & 0x5000) {
9316 /* Unconditional branch. */
9317 /* signextend(hw1[10:0]) -> offset[:12]. */
9318 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
9319 /* hw1[10:0] -> offset[11:1]. */
9320 offset |= (insn & 0x7ff) << 1;
9321 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
9322 offset[24:22] already have the same value because of the
9323 sign extension above. */
9324 offset ^= ((~insn) & (1 << 13)) << 10;
9325 offset ^= ((~insn) & (1 << 11)) << 11;
9327 if (insn & (1 << 14)) {
9328 /* Branch and link. */
9329 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
9332 offset += s->pc;
9333 if (insn & (1 << 12)) {
9334 /* b/bl */
9335 gen_jmp(s, offset);
9336 } else {
9337 /* blx */
9338 offset &= ~(uint32_t)2;
9339 /* thumb2 bx, no need to check */
9340 gen_bx_im(s, offset);
9342 } else if (((insn >> 23) & 7) == 7) {
9343 /* Misc control */
9344 if (insn & (1 << 13))
9345 goto illegal_op;
9347 if (insn & (1 << 26)) {
9348 /* Secure monitor call (v6Z) */
9349 qemu_log_mask(LOG_UNIMP,
9350 "arm: unimplemented secure monitor call\n");
9351 goto illegal_op; /* not implemented. */
9352 } else {
9353 op = (insn >> 20) & 7;
9354 switch (op) {
9355 case 0: /* msr cpsr. */
9356 if (IS_M(env)) {
9357 tmp = load_reg(s, rn);
9358 addr = tcg_const_i32(insn & 0xff);
9359 gen_helper_v7m_msr(cpu_env, addr, tmp);
9360 tcg_temp_free_i32(addr);
9361 tcg_temp_free_i32(tmp);
9362 gen_lookup_tb(s);
9363 break;
9365 /* fall through */
9366 case 1: /* msr spsr. */
9367 if (IS_M(env))
9368 goto illegal_op;
9369 tmp = load_reg(s, rn);
9370 if (gen_set_psr(s,
9371 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
9372 op == 1, tmp))
9373 goto illegal_op;
9374 break;
9375 case 2: /* cps, nop-hint. */
9376 if (((insn >> 8) & 7) == 0) {
9377 gen_nop_hint(s, insn & 0xff);
9379 /* Implemented as NOP in user mode. */
9380 if (IS_USER(s))
9381 break;
9382 offset = 0;
9383 imm = 0;
9384 if (insn & (1 << 10)) {
9385 if (insn & (1 << 7))
9386 offset |= CPSR_A;
9387 if (insn & (1 << 6))
9388 offset |= CPSR_I;
9389 if (insn & (1 << 5))
9390 offset |= CPSR_F;
9391 if (insn & (1 << 9))
9392 imm = CPSR_A | CPSR_I | CPSR_F;
9394 if (insn & (1 << 8)) {
9395 offset |= 0x1f;
9396 imm |= (insn & 0x1f);
9398 if (offset) {
9399 gen_set_psr_im(s, offset, 0, imm);
9401 break;
9402 case 3: /* Special control operations. */
9403 ARCH(7);
9404 op = (insn >> 4) & 0xf;
9405 switch (op) {
9406 case 2: /* clrex */
9407 gen_clrex(s);
9408 break;
9409 case 4: /* dsb */
9410 case 5: /* dmb */
9411 case 6: /* isb */
9412 /* These execute as NOPs. */
9413 break;
9414 default:
9415 goto illegal_op;
9417 break;
9418 case 4: /* bxj */
9419 /* Trivial implementation equivalent to bx. */
9420 tmp = load_reg(s, rn);
9421 gen_bx(s, tmp);
9422 break;
9423 case 5: /* Exception return. */
9424 if (IS_USER(s)) {
9425 goto illegal_op;
9427 if (rn != 14 || rd != 15) {
9428 goto illegal_op;
9430 tmp = load_reg(s, rn);
9431 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
9432 gen_exception_return(s, tmp);
9433 break;
9434 case 6: /* mrs cpsr. */
9435 tmp = tcg_temp_new_i32();
9436 if (IS_M(env)) {
9437 addr = tcg_const_i32(insn & 0xff);
9438 gen_helper_v7m_mrs(tmp, cpu_env, addr);
9439 tcg_temp_free_i32(addr);
9440 } else {
9441 gen_helper_cpsr_read(tmp, cpu_env);
9443 store_reg(s, rd, tmp);
9444 break;
9445 case 7: /* mrs spsr. */
9446 /* Not accessible in user mode. */
9447 if (IS_USER(s) || IS_M(env))
9448 goto illegal_op;
9449 tmp = load_cpu_field(spsr);
9450 store_reg(s, rd, tmp);
9451 break;
9454 } else {
9455 /* Conditional branch. */
9456 op = (insn >> 22) & 0xf;
9457 /* Generate a conditional jump to next instruction. */
9458 s->condlabel = gen_new_label();
9459 arm_gen_test_cc(op ^ 1, s->condlabel);
9460 s->condjmp = 1;
9462 /* offset[11:1] = insn[10:0] */
9463 offset = (insn & 0x7ff) << 1;
9464 /* offset[17:12] = insn[21:16]. */
9465 offset |= (insn & 0x003f0000) >> 4;
9466 /* offset[31:20] = insn[26]. */
9467 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
9468 /* offset[18] = insn[13]. */
9469 offset |= (insn & (1 << 13)) << 5;
9470 /* offset[19] = insn[11]. */
9471 offset |= (insn & (1 << 11)) << 8;
9473 /* jump to the offset */
9474 gen_jmp(s, s->pc + offset);
9476 } else {
9477 /* Data processing immediate. */
9478 if (insn & (1 << 25)) {
9479 if (insn & (1 << 24)) {
9480 if (insn & (1 << 20))
9481 goto illegal_op;
9482 /* Bitfield/Saturate. */
9483 op = (insn >> 21) & 7;
9484 imm = insn & 0x1f;
9485 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9486 if (rn == 15) {
9487 tmp = tcg_temp_new_i32();
9488 tcg_gen_movi_i32(tmp, 0);
9489 } else {
9490 tmp = load_reg(s, rn);
9492 switch (op) {
9493 case 2: /* Signed bitfield extract. */
9494 imm++;
9495 if (shift + imm > 32)
9496 goto illegal_op;
9497 if (imm < 32)
9498 gen_sbfx(tmp, shift, imm);
9499 break;
9500 case 6: /* Unsigned bitfield extract. */
9501 imm++;
9502 if (shift + imm > 32)
9503 goto illegal_op;
9504 if (imm < 32)
9505 gen_ubfx(tmp, shift, (1u << imm) - 1);
9506 break;
9507 case 3: /* Bitfield insert/clear. */
9508 if (imm < shift)
9509 goto illegal_op;
9510 imm = imm + 1 - shift;
9511 if (imm != 32) {
9512 tmp2 = load_reg(s, rd);
9513 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
9514 tcg_temp_free_i32(tmp2);
9516 break;
9517 case 7:
9518 goto illegal_op;
9519 default: /* Saturate. */
9520 if (shift) {
9521 if (op & 1)
9522 tcg_gen_sari_i32(tmp, tmp, shift);
9523 else
9524 tcg_gen_shli_i32(tmp, tmp, shift);
9526 tmp2 = tcg_const_i32(imm);
9527 if (op & 4) {
9528 /* Unsigned. */
9529 if ((op & 1) && shift == 0)
9530 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9531 else
9532 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9533 } else {
9534 /* Signed. */
9535 if ((op & 1) && shift == 0)
9536 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9537 else
9538 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9540 tcg_temp_free_i32(tmp2);
9541 break;
9543 store_reg(s, rd, tmp);
9544 } else {
9545 imm = ((insn & 0x04000000) >> 15)
9546 | ((insn & 0x7000) >> 4) | (insn & 0xff);
9547 if (insn & (1 << 22)) {
9548 /* 16-bit immediate. */
9549 imm |= (insn >> 4) & 0xf000;
9550 if (insn & (1 << 23)) {
9551 /* movt */
9552 tmp = load_reg(s, rd);
9553 tcg_gen_ext16u_i32(tmp, tmp);
9554 tcg_gen_ori_i32(tmp, tmp, imm << 16);
9555 } else {
9556 /* movw */
9557 tmp = tcg_temp_new_i32();
9558 tcg_gen_movi_i32(tmp, imm);
9560 } else {
9561 /* Add/sub 12-bit immediate. */
9562 if (rn == 15) {
9563 offset = s->pc & ~(uint32_t)3;
9564 if (insn & (1 << 23))
9565 offset -= imm;
9566 else
9567 offset += imm;
9568 tmp = tcg_temp_new_i32();
9569 tcg_gen_movi_i32(tmp, offset);
9570 } else {
9571 tmp = load_reg(s, rn);
9572 if (insn & (1 << 23))
9573 tcg_gen_subi_i32(tmp, tmp, imm);
9574 else
9575 tcg_gen_addi_i32(tmp, tmp, imm);
9578 store_reg(s, rd, tmp);
9580 } else {
9581 int shifter_out = 0;
9582 /* modified 12-bit immediate. */
9583 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
9584 imm = (insn & 0xff);
9585 switch (shift) {
9586 case 0: /* XY */
9587 /* Nothing to do. */
9588 break;
9589 case 1: /* 00XY00XY */
9590 imm |= imm << 16;
9591 break;
9592 case 2: /* XY00XY00 */
9593 imm |= imm << 16;
9594 imm <<= 8;
9595 break;
9596 case 3: /* XYXYXYXY */
9597 imm |= imm << 16;
9598 imm |= imm << 8;
9599 break;
9600 default: /* Rotated constant. */
9601 shift = (shift << 1) | (imm >> 7);
9602 imm |= 0x80;
9603 imm = imm << (32 - shift);
9604 shifter_out = 1;
9605 break;
9607 tmp2 = tcg_temp_new_i32();
9608 tcg_gen_movi_i32(tmp2, imm);
9609 rn = (insn >> 16) & 0xf;
9610 if (rn == 15) {
9611 tmp = tcg_temp_new_i32();
9612 tcg_gen_movi_i32(tmp, 0);
9613 } else {
9614 tmp = load_reg(s, rn);
9616 op = (insn >> 21) & 0xf;
9617 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
9618 shifter_out, tmp, tmp2))
9619 goto illegal_op;
9620 tcg_temp_free_i32(tmp2);
9621 rd = (insn >> 8) & 0xf;
9622 if (rd != 15) {
9623 store_reg(s, rd, tmp);
9624 } else {
9625 tcg_temp_free_i32(tmp);
9629 break;
9630 case 12: /* Load/store single data item. */
9632 int postinc = 0;
9633 int writeback = 0;
9634 int user;
9635 if ((insn & 0x01100000) == 0x01000000) {
9636 if (disas_neon_ls_insn(env, s, insn))
9637 goto illegal_op;
9638 break;
9640 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
9641 if (rs == 15) {
9642 if (!(insn & (1 << 20))) {
9643 goto illegal_op;
9645 if (op != 2) {
9646 /* Byte or halfword load space with dest == r15 : memory hints.
9647 * Catch them early so we don't emit pointless addressing code.
9648 * This space is a mix of:
9649 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
9650 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
9651 * cores)
9652 * unallocated hints, which must be treated as NOPs
9653 * UNPREDICTABLE space, which we NOP or UNDEF depending on
9654 * which is easiest for the decoding logic
9655 * Some space which must UNDEF
9657 int op1 = (insn >> 23) & 3;
9658 int op2 = (insn >> 6) & 0x3f;
9659 if (op & 2) {
9660 goto illegal_op;
9662 if (rn == 15) {
9663 /* UNPREDICTABLE, unallocated hint or
9664 * PLD/PLDW/PLI (literal)
9666 return 0;
9668 if (op1 & 1) {
9669 return 0; /* PLD/PLDW/PLI or unallocated hint */
9671 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
9672 return 0; /* PLD/PLDW/PLI or unallocated hint */
9674 /* UNDEF space, or an UNPREDICTABLE */
9675 return 1;
9678 user = IS_USER(s);
9679 if (rn == 15) {
9680 addr = tcg_temp_new_i32();
9681 /* PC relative. */
9682 /* s->pc has already been incremented by 4. */
9683 imm = s->pc & 0xfffffffc;
9684 if (insn & (1 << 23))
9685 imm += insn & 0xfff;
9686 else
9687 imm -= insn & 0xfff;
9688 tcg_gen_movi_i32(addr, imm);
9689 } else {
9690 addr = load_reg(s, rn);
9691 if (insn & (1 << 23)) {
9692 /* Positive offset. */
9693 imm = insn & 0xfff;
9694 tcg_gen_addi_i32(addr, addr, imm);
9695 } else {
9696 imm = insn & 0xff;
9697 switch ((insn >> 8) & 0xf) {
9698 case 0x0: /* Shifted Register. */
9699 shift = (insn >> 4) & 0xf;
9700 if (shift > 3) {
9701 tcg_temp_free_i32(addr);
9702 goto illegal_op;
9704 tmp = load_reg(s, rm);
9705 if (shift)
9706 tcg_gen_shli_i32(tmp, tmp, shift);
9707 tcg_gen_add_i32(addr, addr, tmp);
9708 tcg_temp_free_i32(tmp);
9709 break;
9710 case 0xc: /* Negative offset. */
9711 tcg_gen_addi_i32(addr, addr, -imm);
9712 break;
9713 case 0xe: /* User privilege. */
9714 tcg_gen_addi_i32(addr, addr, imm);
9715 user = 1;
9716 break;
9717 case 0x9: /* Post-decrement. */
9718 imm = -imm;
9719 /* Fall through. */
9720 case 0xb: /* Post-increment. */
9721 postinc = 1;
9722 writeback = 1;
9723 break;
9724 case 0xd: /* Pre-decrement. */
9725 imm = -imm;
9726 /* Fall through. */
9727 case 0xf: /* Pre-increment. */
9728 tcg_gen_addi_i32(addr, addr, imm);
9729 writeback = 1;
9730 break;
9731 default:
9732 tcg_temp_free_i32(addr);
9733 goto illegal_op;
9737 if (insn & (1 << 20)) {
9738 /* Load. */
9739 tmp = tcg_temp_new_i32();
9740 switch (op) {
9741 case 0:
9742 gen_aa32_ld8u(tmp, addr, user);
9743 break;
9744 case 4:
9745 gen_aa32_ld8s(tmp, addr, user);
9746 break;
9747 case 1:
9748 gen_aa32_ld16u(tmp, addr, user);
9749 break;
9750 case 5:
9751 gen_aa32_ld16s(tmp, addr, user);
9752 break;
9753 case 2:
9754 gen_aa32_ld32u(tmp, addr, user);
9755 break;
9756 default:
9757 tcg_temp_free_i32(tmp);
9758 tcg_temp_free_i32(addr);
9759 goto illegal_op;
9761 if (rs == 15) {
9762 gen_bx(s, tmp);
9763 } else {
9764 store_reg(s, rs, tmp);
9766 } else {
9767 /* Store. */
9768 tmp = load_reg(s, rs);
9769 switch (op) {
9770 case 0:
9771 gen_aa32_st8(tmp, addr, user);
9772 break;
9773 case 1:
9774 gen_aa32_st16(tmp, addr, user);
9775 break;
9776 case 2:
9777 gen_aa32_st32(tmp, addr, user);
9778 break;
9779 default:
9780 tcg_temp_free_i32(tmp);
9781 tcg_temp_free_i32(addr);
9782 goto illegal_op;
9784 tcg_temp_free_i32(tmp);
9786 if (postinc)
9787 tcg_gen_addi_i32(addr, addr, imm);
9788 if (writeback) {
9789 store_reg(s, rn, addr);
9790 } else {
9791 tcg_temp_free_i32(addr);
9794 break;
9795 default:
9796 goto illegal_op;
9798 return 0;
9799 illegal_op:
9800 return 1;
9803 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
9805 uint32_t val, insn, op, rm, rn, rd, shift, cond;
9806 int32_t offset;
9807 int i;
9808 TCGv_i32 tmp;
9809 TCGv_i32 tmp2;
9810 TCGv_i32 addr;
9812 if (s->condexec_mask) {
9813 cond = s->condexec_cond;
9814 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
9815 s->condlabel = gen_new_label();
9816 arm_gen_test_cc(cond ^ 1, s->condlabel);
9817 s->condjmp = 1;
9821 insn = arm_lduw_code(env, s->pc, s->bswap_code);
9822 s->pc += 2;
9824 switch (insn >> 12) {
9825 case 0: case 1:
9827 rd = insn & 7;
9828 op = (insn >> 11) & 3;
9829 if (op == 3) {
9830 /* add/subtract */
9831 rn = (insn >> 3) & 7;
9832 tmp = load_reg(s, rn);
9833 if (insn & (1 << 10)) {
9834 /* immediate */
9835 tmp2 = tcg_temp_new_i32();
9836 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
9837 } else {
9838 /* reg */
9839 rm = (insn >> 6) & 7;
9840 tmp2 = load_reg(s, rm);
9842 if (insn & (1 << 9)) {
9843 if (s->condexec_mask)
9844 tcg_gen_sub_i32(tmp, tmp, tmp2);
9845 else
9846 gen_sub_CC(tmp, tmp, tmp2);
9847 } else {
9848 if (s->condexec_mask)
9849 tcg_gen_add_i32(tmp, tmp, tmp2);
9850 else
9851 gen_add_CC(tmp, tmp, tmp2);
9853 tcg_temp_free_i32(tmp2);
9854 store_reg(s, rd, tmp);
9855 } else {
9856 /* shift immediate */
9857 rm = (insn >> 3) & 7;
9858 shift = (insn >> 6) & 0x1f;
9859 tmp = load_reg(s, rm);
9860 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
9861 if (!s->condexec_mask)
9862 gen_logic_CC(tmp);
9863 store_reg(s, rd, tmp);
9865 break;
9866 case 2: case 3:
9867 /* arithmetic large immediate */
9868 op = (insn >> 11) & 3;
9869 rd = (insn >> 8) & 0x7;
9870 if (op == 0) { /* mov */
9871 tmp = tcg_temp_new_i32();
9872 tcg_gen_movi_i32(tmp, insn & 0xff);
9873 if (!s->condexec_mask)
9874 gen_logic_CC(tmp);
9875 store_reg(s, rd, tmp);
9876 } else {
9877 tmp = load_reg(s, rd);
9878 tmp2 = tcg_temp_new_i32();
9879 tcg_gen_movi_i32(tmp2, insn & 0xff);
9880 switch (op) {
9881 case 1: /* cmp */
9882 gen_sub_CC(tmp, tmp, tmp2);
9883 tcg_temp_free_i32(tmp);
9884 tcg_temp_free_i32(tmp2);
9885 break;
9886 case 2: /* add */
9887 if (s->condexec_mask)
9888 tcg_gen_add_i32(tmp, tmp, tmp2);
9889 else
9890 gen_add_CC(tmp, tmp, tmp2);
9891 tcg_temp_free_i32(tmp2);
9892 store_reg(s, rd, tmp);
9893 break;
9894 case 3: /* sub */
9895 if (s->condexec_mask)
9896 tcg_gen_sub_i32(tmp, tmp, tmp2);
9897 else
9898 gen_sub_CC(tmp, tmp, tmp2);
9899 tcg_temp_free_i32(tmp2);
9900 store_reg(s, rd, tmp);
9901 break;
9904 break;
9905 case 4:
9906 if (insn & (1 << 11)) {
9907 rd = (insn >> 8) & 7;
9908 /* load pc-relative. Bit 1 of PC is ignored. */
9909 val = s->pc + 2 + ((insn & 0xff) * 4);
9910 val &= ~(uint32_t)2;
9911 addr = tcg_temp_new_i32();
9912 tcg_gen_movi_i32(addr, val);
9913 tmp = tcg_temp_new_i32();
9914 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9915 tcg_temp_free_i32(addr);
9916 store_reg(s, rd, tmp);
9917 break;
9919 if (insn & (1 << 10)) {
9920 /* data processing extended or blx */
9921 rd = (insn & 7) | ((insn >> 4) & 8);
9922 rm = (insn >> 3) & 0xf;
9923 op = (insn >> 8) & 3;
9924 switch (op) {
9925 case 0: /* add */
9926 tmp = load_reg(s, rd);
9927 tmp2 = load_reg(s, rm);
9928 tcg_gen_add_i32(tmp, tmp, tmp2);
9929 tcg_temp_free_i32(tmp2);
9930 store_reg(s, rd, tmp);
9931 break;
9932 case 1: /* cmp */
9933 tmp = load_reg(s, rd);
9934 tmp2 = load_reg(s, rm);
9935 gen_sub_CC(tmp, tmp, tmp2);
9936 tcg_temp_free_i32(tmp2);
9937 tcg_temp_free_i32(tmp);
9938 break;
9939 case 2: /* mov/cpy */
9940 tmp = load_reg(s, rm);
9941 store_reg(s, rd, tmp);
9942 break;
9943 case 3:/* branch [and link] exchange thumb register */
9944 tmp = load_reg(s, rm);
9945 if (insn & (1 << 7)) {
9946 ARCH(5);
9947 val = (uint32_t)s->pc | 1;
9948 tmp2 = tcg_temp_new_i32();
9949 tcg_gen_movi_i32(tmp2, val);
9950 store_reg(s, 14, tmp2);
9952 /* already thumb, no need to check */
9953 gen_bx(s, tmp);
9954 break;
9956 break;
9959 /* data processing register */
9960 rd = insn & 7;
9961 rm = (insn >> 3) & 7;
9962 op = (insn >> 6) & 0xf;
9963 if (op == 2 || op == 3 || op == 4 || op == 7) {
9964 /* the shift/rotate ops want the operands backwards */
9965 val = rm;
9966 rm = rd;
9967 rd = val;
9968 val = 1;
9969 } else {
9970 val = 0;
9973 if (op == 9) { /* neg */
9974 tmp = tcg_temp_new_i32();
9975 tcg_gen_movi_i32(tmp, 0);
9976 } else if (op != 0xf) { /* mvn doesn't read its first operand */
9977 tmp = load_reg(s, rd);
9978 } else {
9979 TCGV_UNUSED_I32(tmp);
9982 tmp2 = load_reg(s, rm);
9983 switch (op) {
9984 case 0x0: /* and */
9985 tcg_gen_and_i32(tmp, tmp, tmp2);
9986 if (!s->condexec_mask)
9987 gen_logic_CC(tmp);
9988 break;
9989 case 0x1: /* eor */
9990 tcg_gen_xor_i32(tmp, tmp, tmp2);
9991 if (!s->condexec_mask)
9992 gen_logic_CC(tmp);
9993 break;
9994 case 0x2: /* lsl */
9995 if (s->condexec_mask) {
9996 gen_shl(tmp2, tmp2, tmp);
9997 } else {
9998 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
9999 gen_logic_CC(tmp2);
10001 break;
10002 case 0x3: /* lsr */
10003 if (s->condexec_mask) {
10004 gen_shr(tmp2, tmp2, tmp);
10005 } else {
10006 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
10007 gen_logic_CC(tmp2);
10009 break;
10010 case 0x4: /* asr */
10011 if (s->condexec_mask) {
10012 gen_sar(tmp2, tmp2, tmp);
10013 } else {
10014 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
10015 gen_logic_CC(tmp2);
10017 break;
10018 case 0x5: /* adc */
10019 if (s->condexec_mask) {
10020 gen_adc(tmp, tmp2);
10021 } else {
10022 gen_adc_CC(tmp, tmp, tmp2);
10024 break;
10025 case 0x6: /* sbc */
10026 if (s->condexec_mask) {
10027 gen_sub_carry(tmp, tmp, tmp2);
10028 } else {
10029 gen_sbc_CC(tmp, tmp, tmp2);
10031 break;
10032 case 0x7: /* ror */
10033 if (s->condexec_mask) {
10034 tcg_gen_andi_i32(tmp, tmp, 0x1f);
10035 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
10036 } else {
10037 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
10038 gen_logic_CC(tmp2);
10040 break;
10041 case 0x8: /* tst */
10042 tcg_gen_and_i32(tmp, tmp, tmp2);
10043 gen_logic_CC(tmp);
10044 rd = 16;
10045 break;
10046 case 0x9: /* neg */
10047 if (s->condexec_mask)
10048 tcg_gen_neg_i32(tmp, tmp2);
10049 else
10050 gen_sub_CC(tmp, tmp, tmp2);
10051 break;
10052 case 0xa: /* cmp */
10053 gen_sub_CC(tmp, tmp, tmp2);
10054 rd = 16;
10055 break;
10056 case 0xb: /* cmn */
10057 gen_add_CC(tmp, tmp, tmp2);
10058 rd = 16;
10059 break;
10060 case 0xc: /* orr */
10061 tcg_gen_or_i32(tmp, tmp, tmp2);
10062 if (!s->condexec_mask)
10063 gen_logic_CC(tmp);
10064 break;
10065 case 0xd: /* mul */
10066 tcg_gen_mul_i32(tmp, tmp, tmp2);
10067 if (!s->condexec_mask)
10068 gen_logic_CC(tmp);
10069 break;
10070 case 0xe: /* bic */
10071 tcg_gen_andc_i32(tmp, tmp, tmp2);
10072 if (!s->condexec_mask)
10073 gen_logic_CC(tmp);
10074 break;
10075 case 0xf: /* mvn */
10076 tcg_gen_not_i32(tmp2, tmp2);
10077 if (!s->condexec_mask)
10078 gen_logic_CC(tmp2);
10079 val = 1;
10080 rm = rd;
10081 break;
10083 if (rd != 16) {
10084 if (val) {
10085 store_reg(s, rm, tmp2);
10086 if (op != 0xf)
10087 tcg_temp_free_i32(tmp);
10088 } else {
10089 store_reg(s, rd, tmp);
10090 tcg_temp_free_i32(tmp2);
10092 } else {
10093 tcg_temp_free_i32(tmp);
10094 tcg_temp_free_i32(tmp2);
10096 break;
10098 case 5:
10099 /* load/store register offset. */
10100 rd = insn & 7;
10101 rn = (insn >> 3) & 7;
10102 rm = (insn >> 6) & 7;
10103 op = (insn >> 9) & 7;
10104 addr = load_reg(s, rn);
10105 tmp = load_reg(s, rm);
10106 tcg_gen_add_i32(addr, addr, tmp);
10107 tcg_temp_free_i32(tmp);
10109 if (op < 3) { /* store */
10110 tmp = load_reg(s, rd);
10111 } else {
10112 tmp = tcg_temp_new_i32();
10115 switch (op) {
10116 case 0: /* str */
10117 gen_aa32_st32(tmp, addr, IS_USER(s));
10118 break;
10119 case 1: /* strh */
10120 gen_aa32_st16(tmp, addr, IS_USER(s));
10121 break;
10122 case 2: /* strb */
10123 gen_aa32_st8(tmp, addr, IS_USER(s));
10124 break;
10125 case 3: /* ldrsb */
10126 gen_aa32_ld8s(tmp, addr, IS_USER(s));
10127 break;
10128 case 4: /* ldr */
10129 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10130 break;
10131 case 5: /* ldrh */
10132 gen_aa32_ld16u(tmp, addr, IS_USER(s));
10133 break;
10134 case 6: /* ldrb */
10135 gen_aa32_ld8u(tmp, addr, IS_USER(s));
10136 break;
10137 case 7: /* ldrsh */
10138 gen_aa32_ld16s(tmp, addr, IS_USER(s));
10139 break;
10141 if (op >= 3) { /* load */
10142 store_reg(s, rd, tmp);
10143 } else {
10144 tcg_temp_free_i32(tmp);
10146 tcg_temp_free_i32(addr);
10147 break;
10149 case 6:
10150 /* load/store word immediate offset */
10151 rd = insn & 7;
10152 rn = (insn >> 3) & 7;
10153 addr = load_reg(s, rn);
10154 val = (insn >> 4) & 0x7c;
10155 tcg_gen_addi_i32(addr, addr, val);
10157 if (insn & (1 << 11)) {
10158 /* load */
10159 tmp = tcg_temp_new_i32();
10160 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10161 store_reg(s, rd, tmp);
10162 } else {
10163 /* store */
10164 tmp = load_reg(s, rd);
10165 gen_aa32_st32(tmp, addr, IS_USER(s));
10166 tcg_temp_free_i32(tmp);
10168 tcg_temp_free_i32(addr);
10169 break;
10171 case 7:
10172 /* load/store byte immediate offset */
10173 rd = insn & 7;
10174 rn = (insn >> 3) & 7;
10175 addr = load_reg(s, rn);
10176 val = (insn >> 6) & 0x1f;
10177 tcg_gen_addi_i32(addr, addr, val);
10179 if (insn & (1 << 11)) {
10180 /* load */
10181 tmp = tcg_temp_new_i32();
10182 gen_aa32_ld8u(tmp, addr, IS_USER(s));
10183 store_reg(s, rd, tmp);
10184 } else {
10185 /* store */
10186 tmp = load_reg(s, rd);
10187 gen_aa32_st8(tmp, addr, IS_USER(s));
10188 tcg_temp_free_i32(tmp);
10190 tcg_temp_free_i32(addr);
10191 break;
10193 case 8:
10194 /* load/store halfword immediate offset */
10195 rd = insn & 7;
10196 rn = (insn >> 3) & 7;
10197 addr = load_reg(s, rn);
10198 val = (insn >> 5) & 0x3e;
10199 tcg_gen_addi_i32(addr, addr, val);
10201 if (insn & (1 << 11)) {
10202 /* load */
10203 tmp = tcg_temp_new_i32();
10204 gen_aa32_ld16u(tmp, addr, IS_USER(s));
10205 store_reg(s, rd, tmp);
10206 } else {
10207 /* store */
10208 tmp = load_reg(s, rd);
10209 gen_aa32_st16(tmp, addr, IS_USER(s));
10210 tcg_temp_free_i32(tmp);
10212 tcg_temp_free_i32(addr);
10213 break;
10215 case 9:
10216 /* load/store from stack */
10217 rd = (insn >> 8) & 7;
10218 addr = load_reg(s, 13);
10219 val = (insn & 0xff) * 4;
10220 tcg_gen_addi_i32(addr, addr, val);
10222 if (insn & (1 << 11)) {
10223 /* load */
10224 tmp = tcg_temp_new_i32();
10225 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10226 store_reg(s, rd, tmp);
10227 } else {
10228 /* store */
10229 tmp = load_reg(s, rd);
10230 gen_aa32_st32(tmp, addr, IS_USER(s));
10231 tcg_temp_free_i32(tmp);
10233 tcg_temp_free_i32(addr);
10234 break;
10236 case 10:
10237 /* add to high reg */
10238 rd = (insn >> 8) & 7;
10239 if (insn & (1 << 11)) {
10240 /* SP */
10241 tmp = load_reg(s, 13);
10242 } else {
10243 /* PC. bit 1 is ignored. */
10244 tmp = tcg_temp_new_i32();
10245 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
10247 val = (insn & 0xff) * 4;
10248 tcg_gen_addi_i32(tmp, tmp, val);
10249 store_reg(s, rd, tmp);
10250 break;
10252 case 11:
10253 /* misc */
10254 op = (insn >> 8) & 0xf;
10255 switch (op) {
10256 case 0:
10257 /* adjust stack pointer */
10258 tmp = load_reg(s, 13);
10259 val = (insn & 0x7f) * 4;
10260 if (insn & (1 << 7))
10261 val = -(int32_t)val;
10262 tcg_gen_addi_i32(tmp, tmp, val);
10263 store_reg(s, 13, tmp);
10264 break;
10266 case 2: /* sign/zero extend. */
10267 ARCH(6);
10268 rd = insn & 7;
10269 rm = (insn >> 3) & 7;
10270 tmp = load_reg(s, rm);
10271 switch ((insn >> 6) & 3) {
10272 case 0: gen_sxth(tmp); break;
10273 case 1: gen_sxtb(tmp); break;
10274 case 2: gen_uxth(tmp); break;
10275 case 3: gen_uxtb(tmp); break;
10277 store_reg(s, rd, tmp);
10278 break;
10279 case 4: case 5: case 0xc: case 0xd:
10280 /* push/pop */
10281 addr = load_reg(s, 13);
10282 if (insn & (1 << 8))
10283 offset = 4;
10284 else
10285 offset = 0;
10286 for (i = 0; i < 8; i++) {
10287 if (insn & (1 << i))
10288 offset += 4;
10290 if ((insn & (1 << 11)) == 0) {
10291 tcg_gen_addi_i32(addr, addr, -offset);
10293 for (i = 0; i < 8; i++) {
10294 if (insn & (1 << i)) {
10295 if (insn & (1 << 11)) {
10296 /* pop */
10297 tmp = tcg_temp_new_i32();
10298 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10299 store_reg(s, i, tmp);
10300 } else {
10301 /* push */
10302 tmp = load_reg(s, i);
10303 gen_aa32_st32(tmp, addr, IS_USER(s));
10304 tcg_temp_free_i32(tmp);
10306 /* advance to the next address. */
10307 tcg_gen_addi_i32(addr, addr, 4);
10310 TCGV_UNUSED_I32(tmp);
10311 if (insn & (1 << 8)) {
10312 if (insn & (1 << 11)) {
10313 /* pop pc */
10314 tmp = tcg_temp_new_i32();
10315 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10316 /* don't set the pc until the rest of the instruction
10317 has completed */
10318 } else {
10319 /* push lr */
10320 tmp = load_reg(s, 14);
10321 gen_aa32_st32(tmp, addr, IS_USER(s));
10322 tcg_temp_free_i32(tmp);
10324 tcg_gen_addi_i32(addr, addr, 4);
10326 if ((insn & (1 << 11)) == 0) {
10327 tcg_gen_addi_i32(addr, addr, -offset);
10329 /* write back the new stack pointer */
10330 store_reg(s, 13, addr);
10331 /* set the new PC value */
10332 if ((insn & 0x0900) == 0x0900) {
10333 store_reg_from_load(env, s, 15, tmp);
10335 break;
10337 case 1: case 3: case 9: case 11: /* czb */
10338 rm = insn & 7;
10339 tmp = load_reg(s, rm);
10340 s->condlabel = gen_new_label();
10341 s->condjmp = 1;
10342 if (insn & (1 << 11))
10343 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
10344 else
10345 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
10346 tcg_temp_free_i32(tmp);
10347 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
10348 val = (uint32_t)s->pc + 2;
10349 val += offset;
10350 gen_jmp(s, val);
10351 break;
10353 case 15: /* IT, nop-hint. */
10354 if ((insn & 0xf) == 0) {
10355 gen_nop_hint(s, (insn >> 4) & 0xf);
10356 break;
10358 /* If Then. */
10359 s->condexec_cond = (insn >> 4) & 0xe;
10360 s->condexec_mask = insn & 0x1f;
10361 /* No actual code generated for this insn, just setup state. */
10362 break;
10364 case 0xe: /* bkpt */
10365 ARCH(5);
10366 gen_exception_insn(s, 2, EXCP_BKPT);
10367 break;
10369 case 0xa: /* rev */
10370 ARCH(6);
10371 rn = (insn >> 3) & 0x7;
10372 rd = insn & 0x7;
10373 tmp = load_reg(s, rn);
10374 switch ((insn >> 6) & 3) {
10375 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
10376 case 1: gen_rev16(tmp); break;
10377 case 3: gen_revsh(tmp); break;
10378 default: goto illegal_op;
10380 store_reg(s, rd, tmp);
10381 break;
10383 case 6:
10384 switch ((insn >> 5) & 7) {
10385 case 2:
10386 /* setend */
10387 ARCH(6);
10388 if (((insn >> 3) & 1) != s->bswap_code) {
10389 /* Dynamic endianness switching not implemented. */
10390 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
10391 goto illegal_op;
10393 break;
10394 case 3:
10395 /* cps */
10396 ARCH(6);
10397 if (IS_USER(s)) {
10398 break;
10400 if (IS_M(env)) {
10401 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
10402 /* FAULTMASK */
10403 if (insn & 1) {
10404 addr = tcg_const_i32(19);
10405 gen_helper_v7m_msr(cpu_env, addr, tmp);
10406 tcg_temp_free_i32(addr);
10408 /* PRIMASK */
10409 if (insn & 2) {
10410 addr = tcg_const_i32(16);
10411 gen_helper_v7m_msr(cpu_env, addr, tmp);
10412 tcg_temp_free_i32(addr);
10414 tcg_temp_free_i32(tmp);
10415 gen_lookup_tb(s);
10416 } else {
10417 if (insn & (1 << 4)) {
10418 shift = CPSR_A | CPSR_I | CPSR_F;
10419 } else {
10420 shift = 0;
10422 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
10424 break;
10425 default:
10426 goto undef;
10428 break;
10430 default:
10431 goto undef;
10433 break;
10435 case 12:
10437 /* load/store multiple */
10438 TCGv_i32 loaded_var;
10439 TCGV_UNUSED_I32(loaded_var);
10440 rn = (insn >> 8) & 0x7;
10441 addr = load_reg(s, rn);
10442 for (i = 0; i < 8; i++) {
10443 if (insn & (1 << i)) {
10444 if (insn & (1 << 11)) {
10445 /* load */
10446 tmp = tcg_temp_new_i32();
10447 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10448 if (i == rn) {
10449 loaded_var = tmp;
10450 } else {
10451 store_reg(s, i, tmp);
10453 } else {
10454 /* store */
10455 tmp = load_reg(s, i);
10456 gen_aa32_st32(tmp, addr, IS_USER(s));
10457 tcg_temp_free_i32(tmp);
10459 /* advance to the next address */
10460 tcg_gen_addi_i32(addr, addr, 4);
10463 if ((insn & (1 << rn)) == 0) {
10464 /* base reg not in list: base register writeback */
10465 store_reg(s, rn, addr);
10466 } else {
10467 /* base reg in list: if load, complete it now */
10468 if (insn & (1 << 11)) {
10469 store_reg(s, rn, loaded_var);
10471 tcg_temp_free_i32(addr);
10473 break;
10475 case 13:
10476 /* conditional branch or swi */
10477 cond = (insn >> 8) & 0xf;
10478 if (cond == 0xe)
10479 goto undef;
10481 if (cond == 0xf) {
10482 /* swi */
10483 gen_set_pc_im(s, s->pc);
10484 s->is_jmp = DISAS_SWI;
10485 break;
10487 /* generate a conditional jump to next instruction */
10488 s->condlabel = gen_new_label();
10489 arm_gen_test_cc(cond ^ 1, s->condlabel);
10490 s->condjmp = 1;
10492 /* jump to the offset */
10493 val = (uint32_t)s->pc + 2;
10494 offset = ((int32_t)insn << 24) >> 24;
10495 val += offset << 1;
10496 gen_jmp(s, val);
10497 break;
10499 case 14:
10500 if (insn & (1 << 11)) {
10501 if (disas_thumb2_insn(env, s, insn))
10502 goto undef32;
10503 break;
10505 /* unconditional branch */
10506 val = (uint32_t)s->pc;
10507 offset = ((int32_t)insn << 21) >> 21;
10508 val += (offset << 1) + 2;
10509 gen_jmp(s, val);
10510 break;
10512 case 15:
10513 if (disas_thumb2_insn(env, s, insn))
10514 goto undef32;
10515 break;
10517 return;
10518 undef32:
10519 gen_exception_insn(s, 4, EXCP_UDEF);
10520 return;
10521 illegal_op:
10522 undef:
10523 gen_exception_insn(s, 2, EXCP_UDEF);
10526 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
10527 basic block 'tb'. If search_pc is TRUE, also generate PC
10528 information for each intermediate instruction. */
10529 static inline void gen_intermediate_code_internal(ARMCPU *cpu,
10530 TranslationBlock *tb,
10531 bool search_pc)
10533 CPUState *cs = CPU(cpu);
10534 CPUARMState *env = &cpu->env;
10535 DisasContext dc1, *dc = &dc1;
10536 CPUBreakpoint *bp;
10537 uint16_t *gen_opc_end;
10538 int j, lj;
10539 target_ulong pc_start;
10540 target_ulong next_page_start;
10541 int num_insns;
10542 int max_insns;
10544 /* generate intermediate code */
10546 /* The A64 decoder has its own top level loop, because it doesn't need
10547 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
10549 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
10550 gen_intermediate_code_internal_a64(cpu, tb, search_pc);
10551 return;
10554 pc_start = tb->pc;
10556 dc->tb = tb;
10558 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
10560 dc->is_jmp = DISAS_NEXT;
10561 dc->pc = pc_start;
10562 dc->singlestep_enabled = cs->singlestep_enabled;
10563 dc->condjmp = 0;
10565 dc->aarch64 = 0;
10566 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
10567 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
10568 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
10569 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
10570 #if !defined(CONFIG_USER_ONLY)
10571 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
10572 #endif
10573 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
10574 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
10575 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
10576 dc->cp_regs = cpu->cp_regs;
10577 dc->current_pl = arm_current_pl(env);
10579 cpu_F0s = tcg_temp_new_i32();
10580 cpu_F1s = tcg_temp_new_i32();
10581 cpu_F0d = tcg_temp_new_i64();
10582 cpu_F1d = tcg_temp_new_i64();
10583 cpu_V0 = cpu_F0d;
10584 cpu_V1 = cpu_F1d;
10585 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
10586 cpu_M0 = tcg_temp_new_i64();
10587 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
10588 lj = -1;
10589 num_insns = 0;
10590 max_insns = tb->cflags & CF_COUNT_MASK;
10591 if (max_insns == 0)
10592 max_insns = CF_COUNT_MASK;
10594 gen_tb_start();
10596 tcg_clear_temp_count();
10598 /* A note on handling of the condexec (IT) bits:
10600 * We want to avoid the overhead of having to write the updated condexec
10601 * bits back to the CPUARMState for every instruction in an IT block. So:
10602 * (1) if the condexec bits are not already zero then we write
10603 * zero back into the CPUARMState now. This avoids complications trying
10604 * to do it at the end of the block. (For example if we don't do this
10605 * it's hard to identify whether we can safely skip writing condexec
10606 * at the end of the TB, which we definitely want to do for the case
10607 * where a TB doesn't do anything with the IT state at all.)
10608 * (2) if we are going to leave the TB then we call gen_set_condexec()
10609 * which will write the correct value into CPUARMState if zero is wrong.
10610 * This is done both for leaving the TB at the end, and for leaving
10611 * it because of an exception we know will happen, which is done in
10612 * gen_exception_insn(). The latter is necessary because we need to
10613 * leave the TB with the PC/IT state just prior to execution of the
10614 * instruction which caused the exception.
10615 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
10616 * then the CPUARMState will be wrong and we need to reset it.
10617 * This is handled in the same way as restoration of the
10618 * PC in these situations: we will be called again with search_pc=1
10619 * and generate a mapping of the condexec bits for each PC in
10620 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
10621 * this to restore the condexec bits.
10623 * Note that there are no instructions which can read the condexec
10624 * bits, and none which can write non-static values to them, so
10625 * we don't need to care about whether CPUARMState is correct in the
10626 * middle of a TB.
10629 /* Reset the conditional execution bits immediately. This avoids
10630 complications trying to do it at the end of the block. */
10631 if (dc->condexec_mask || dc->condexec_cond)
10633 TCGv_i32 tmp = tcg_temp_new_i32();
10634 tcg_gen_movi_i32(tmp, 0);
10635 store_cpu_field(tmp, condexec_bits);
10637 do {
10638 #ifdef CONFIG_USER_ONLY
10639 /* Intercept jump to the magic kernel page. */
10640 if (dc->pc >= 0xffff0000) {
10641 /* We always get here via a jump, so know we are not in a
10642 conditional execution block. */
10643 gen_exception(EXCP_KERNEL_TRAP);
10644 dc->is_jmp = DISAS_UPDATE;
10645 break;
10647 #else
10648 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
10649 /* We always get here via a jump, so know we are not in a
10650 conditional execution block. */
10651 gen_exception(EXCP_EXCEPTION_EXIT);
10652 dc->is_jmp = DISAS_UPDATE;
10653 break;
10655 #endif
10657 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
10658 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
10659 if (bp->pc == dc->pc) {
10660 gen_exception_insn(dc, 0, EXCP_DEBUG);
10661 /* Advance PC so that clearing the breakpoint will
10662 invalidate this TB. */
10663 dc->pc += 2;
10664 goto done_generating;
10668 if (search_pc) {
10669 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10670 if (lj < j) {
10671 lj++;
10672 while (lj < j)
10673 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10675 tcg_ctx.gen_opc_pc[lj] = dc->pc;
10676 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
10677 tcg_ctx.gen_opc_instr_start[lj] = 1;
10678 tcg_ctx.gen_opc_icount[lj] = num_insns;
10681 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
10682 gen_io_start();
10684 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
10685 tcg_gen_debug_insn_start(dc->pc);
10688 if (dc->thumb) {
10689 disas_thumb_insn(env, dc);
10690 if (dc->condexec_mask) {
10691 dc->condexec_cond = (dc->condexec_cond & 0xe)
10692 | ((dc->condexec_mask >> 4) & 1);
10693 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
10694 if (dc->condexec_mask == 0) {
10695 dc->condexec_cond = 0;
10698 } else {
10699 disas_arm_insn(env, dc);
10702 if (dc->condjmp && !dc->is_jmp) {
10703 gen_set_label(dc->condlabel);
10704 dc->condjmp = 0;
10707 if (tcg_check_temp_count()) {
10708 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
10709 dc->pc);
10712 /* Translation stops when a conditional branch is encountered.
10713 * Otherwise the subsequent code could get translated several times.
10714 * Also stop translation when a page boundary is reached. This
10715 * ensures prefetch aborts occur at the right place. */
10716 num_insns ++;
10717 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
10718 !cs->singlestep_enabled &&
10719 !singlestep &&
10720 dc->pc < next_page_start &&
10721 num_insns < max_insns);
10723 if (tb->cflags & CF_LAST_IO) {
10724 if (dc->condjmp) {
10725 /* FIXME: This can theoretically happen with self-modifying
10726 code. */
10727 cpu_abort(env, "IO on conditional branch instruction");
10729 gen_io_end();
10732 /* At this stage dc->condjmp will only be set when the skipped
10733 instruction was a conditional branch or trap, and the PC has
10734 already been written. */
10735 if (unlikely(cs->singlestep_enabled)) {
10736 /* Make sure the pc is updated, and raise a debug exception. */
10737 if (dc->condjmp) {
10738 gen_set_condexec(dc);
10739 if (dc->is_jmp == DISAS_SWI) {
10740 gen_exception(EXCP_SWI);
10741 } else {
10742 gen_exception(EXCP_DEBUG);
10744 gen_set_label(dc->condlabel);
10746 if (dc->condjmp || !dc->is_jmp) {
10747 gen_set_pc_im(dc, dc->pc);
10748 dc->condjmp = 0;
10750 gen_set_condexec(dc);
10751 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
10752 gen_exception(EXCP_SWI);
10753 } else {
10754 /* FIXME: Single stepping a WFI insn will not halt
10755 the CPU. */
10756 gen_exception(EXCP_DEBUG);
10758 } else {
10759 /* While branches must always occur at the end of an IT block,
10760 there are a few other things that can cause us to terminate
10761 the TB in the middle of an IT block:
10762 - Exception generating instructions (bkpt, swi, undefined).
10763 - Page boundaries.
10764 - Hardware watchpoints.
10765 Hardware breakpoints have already been handled and skip this code.
10767 gen_set_condexec(dc);
10768 switch(dc->is_jmp) {
10769 case DISAS_NEXT:
10770 gen_goto_tb(dc, 1, dc->pc);
10771 break;
10772 default:
10773 case DISAS_JUMP:
10774 case DISAS_UPDATE:
10775 /* indicate that the hash table must be used to find the next TB */
10776 tcg_gen_exit_tb(0);
10777 break;
10778 case DISAS_TB_JUMP:
10779 /* nothing more to generate */
10780 break;
10781 case DISAS_WFI:
10782 gen_helper_wfi(cpu_env);
10783 break;
10784 case DISAS_SWI:
10785 gen_exception(EXCP_SWI);
10786 break;
10788 if (dc->condjmp) {
10789 gen_set_label(dc->condlabel);
10790 gen_set_condexec(dc);
10791 gen_goto_tb(dc, 1, dc->pc);
10792 dc->condjmp = 0;
10796 done_generating:
10797 gen_tb_end(tb, num_insns);
10798 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
10800 #ifdef DEBUG_DISAS
10801 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
10802 qemu_log("----------------\n");
10803 qemu_log("IN: %s\n", lookup_symbol(pc_start));
10804 log_target_disas(env, pc_start, dc->pc - pc_start,
10805 dc->thumb | (dc->bswap_code << 1));
10806 qemu_log("\n");
10808 #endif
10809 if (search_pc) {
10810 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10811 lj++;
10812 while (lj <= j)
10813 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10814 } else {
10815 tb->size = dc->pc - pc_start;
10816 tb->icount = num_insns;
10820 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
10822 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
10825 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
10827 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
10830 static const char *cpu_mode_names[16] = {
10831 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
10832 "???", "???", "???", "und", "???", "???", "???", "sys"
10835 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
10836 int flags)
10838 ARMCPU *cpu = ARM_CPU(cs);
10839 CPUARMState *env = &cpu->env;
10840 int i;
10841 uint32_t psr;
10843 for(i=0;i<16;i++) {
10844 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
10845 if ((i % 4) == 3)
10846 cpu_fprintf(f, "\n");
10847 else
10848 cpu_fprintf(f, " ");
10850 psr = cpsr_read(env);
10851 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
10852 psr,
10853 psr & (1 << 31) ? 'N' : '-',
10854 psr & (1 << 30) ? 'Z' : '-',
10855 psr & (1 << 29) ? 'C' : '-',
10856 psr & (1 << 28) ? 'V' : '-',
10857 psr & CPSR_T ? 'T' : 'A',
10858 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
10860 if (flags & CPU_DUMP_FPU) {
10861 int numvfpregs = 0;
10862 if (arm_feature(env, ARM_FEATURE_VFP)) {
10863 numvfpregs += 16;
10865 if (arm_feature(env, ARM_FEATURE_VFP3)) {
10866 numvfpregs += 16;
10868 for (i = 0; i < numvfpregs; i++) {
10869 uint64_t v = float64_val(env->vfp.regs[i]);
10870 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
10871 i * 2, (uint32_t)v,
10872 i * 2 + 1, (uint32_t)(v >> 32),
10873 i, v);
10875 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
10879 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
10881 if (is_a64(env)) {
10882 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
10883 env->condexec_bits = 0;
10884 } else {
10885 env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
10886 env->condexec_bits = gen_opc_condexec_bits[pc_pos];