target-i386: kvm_cpu_fill_host(): No need to check xlevel2
[qemu/ar7.git] / target-arm / translate.c
blob8d240e160dea3980afcf5857af1569243080d5ea
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 disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2764 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
2766 if (!arm_feature(env, ARM_FEATURE_V8)) {
2767 return 1;
2770 if (dp) {
2771 VFP_DREG_D(rd, insn);
2772 VFP_DREG_N(rn, insn);
2773 VFP_DREG_M(rm, insn);
2774 } else {
2775 rd = VFP_SREG_D(insn);
2776 rn = VFP_SREG_N(insn);
2777 rm = VFP_SREG_M(insn);
2780 if ((insn & 0x0f800e50) == 0x0e000a00) {
2781 return handle_vsel(insn, rd, rn, rm, dp);
2782 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
2783 return handle_vminmaxnm(insn, rd, rn, rm, dp);
2785 return 1;
2788 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2789 (ie. an undefined instruction). */
2790 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
2792 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2793 int dp, veclen;
2794 TCGv_i32 addr;
2795 TCGv_i32 tmp;
2796 TCGv_i32 tmp2;
2798 if (!arm_feature(env, ARM_FEATURE_VFP))
2799 return 1;
2801 if (!s->vfp_enabled) {
2802 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2803 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2804 return 1;
2805 rn = (insn >> 16) & 0xf;
2806 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2807 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2808 return 1;
2811 if (extract32(insn, 28, 4) == 0xf) {
2812 /* Encodings with T=1 (Thumb) or unconditional (ARM):
2813 * only used in v8 and above.
2815 return disas_vfp_v8_insn(env, s, insn);
2818 dp = ((insn & 0xf00) == 0xb00);
2819 switch ((insn >> 24) & 0xf) {
2820 case 0xe:
2821 if (insn & (1 << 4)) {
2822 /* single register transfer */
2823 rd = (insn >> 12) & 0xf;
2824 if (dp) {
2825 int size;
2826 int pass;
2828 VFP_DREG_N(rn, insn);
2829 if (insn & 0xf)
2830 return 1;
2831 if (insn & 0x00c00060
2832 && !arm_feature(env, ARM_FEATURE_NEON))
2833 return 1;
2835 pass = (insn >> 21) & 1;
2836 if (insn & (1 << 22)) {
2837 size = 0;
2838 offset = ((insn >> 5) & 3) * 8;
2839 } else if (insn & (1 << 5)) {
2840 size = 1;
2841 offset = (insn & (1 << 6)) ? 16 : 0;
2842 } else {
2843 size = 2;
2844 offset = 0;
2846 if (insn & ARM_CP_RW_BIT) {
2847 /* vfp->arm */
2848 tmp = neon_load_reg(rn, pass);
2849 switch (size) {
2850 case 0:
2851 if (offset)
2852 tcg_gen_shri_i32(tmp, tmp, offset);
2853 if (insn & (1 << 23))
2854 gen_uxtb(tmp);
2855 else
2856 gen_sxtb(tmp);
2857 break;
2858 case 1:
2859 if (insn & (1 << 23)) {
2860 if (offset) {
2861 tcg_gen_shri_i32(tmp, tmp, 16);
2862 } else {
2863 gen_uxth(tmp);
2865 } else {
2866 if (offset) {
2867 tcg_gen_sari_i32(tmp, tmp, 16);
2868 } else {
2869 gen_sxth(tmp);
2872 break;
2873 case 2:
2874 break;
2876 store_reg(s, rd, tmp);
2877 } else {
2878 /* arm->vfp */
2879 tmp = load_reg(s, rd);
2880 if (insn & (1 << 23)) {
2881 /* VDUP */
2882 if (size == 0) {
2883 gen_neon_dup_u8(tmp, 0);
2884 } else if (size == 1) {
2885 gen_neon_dup_low16(tmp);
2887 for (n = 0; n <= pass * 2; n++) {
2888 tmp2 = tcg_temp_new_i32();
2889 tcg_gen_mov_i32(tmp2, tmp);
2890 neon_store_reg(rn, n, tmp2);
2892 neon_store_reg(rn, n, tmp);
2893 } else {
2894 /* VMOV */
2895 switch (size) {
2896 case 0:
2897 tmp2 = neon_load_reg(rn, pass);
2898 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
2899 tcg_temp_free_i32(tmp2);
2900 break;
2901 case 1:
2902 tmp2 = neon_load_reg(rn, pass);
2903 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
2904 tcg_temp_free_i32(tmp2);
2905 break;
2906 case 2:
2907 break;
2909 neon_store_reg(rn, pass, tmp);
2912 } else { /* !dp */
2913 if ((insn & 0x6f) != 0x00)
2914 return 1;
2915 rn = VFP_SREG_N(insn);
2916 if (insn & ARM_CP_RW_BIT) {
2917 /* vfp->arm */
2918 if (insn & (1 << 21)) {
2919 /* system register */
2920 rn >>= 1;
2922 switch (rn) {
2923 case ARM_VFP_FPSID:
2924 /* VFP2 allows access to FSID from userspace.
2925 VFP3 restricts all id registers to privileged
2926 accesses. */
2927 if (IS_USER(s)
2928 && arm_feature(env, ARM_FEATURE_VFP3))
2929 return 1;
2930 tmp = load_cpu_field(vfp.xregs[rn]);
2931 break;
2932 case ARM_VFP_FPEXC:
2933 if (IS_USER(s))
2934 return 1;
2935 tmp = load_cpu_field(vfp.xregs[rn]);
2936 break;
2937 case ARM_VFP_FPINST:
2938 case ARM_VFP_FPINST2:
2939 /* Not present in VFP3. */
2940 if (IS_USER(s)
2941 || arm_feature(env, ARM_FEATURE_VFP3))
2942 return 1;
2943 tmp = load_cpu_field(vfp.xregs[rn]);
2944 break;
2945 case ARM_VFP_FPSCR:
2946 if (rd == 15) {
2947 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2948 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2949 } else {
2950 tmp = tcg_temp_new_i32();
2951 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2953 break;
2954 case ARM_VFP_MVFR0:
2955 case ARM_VFP_MVFR1:
2956 if (IS_USER(s)
2957 || !arm_feature(env, ARM_FEATURE_MVFR))
2958 return 1;
2959 tmp = load_cpu_field(vfp.xregs[rn]);
2960 break;
2961 default:
2962 return 1;
2964 } else {
2965 gen_mov_F0_vreg(0, rn);
2966 tmp = gen_vfp_mrs();
2968 if (rd == 15) {
2969 /* Set the 4 flag bits in the CPSR. */
2970 gen_set_nzcv(tmp);
2971 tcg_temp_free_i32(tmp);
2972 } else {
2973 store_reg(s, rd, tmp);
2975 } else {
2976 /* arm->vfp */
2977 if (insn & (1 << 21)) {
2978 rn >>= 1;
2979 /* system register */
2980 switch (rn) {
2981 case ARM_VFP_FPSID:
2982 case ARM_VFP_MVFR0:
2983 case ARM_VFP_MVFR1:
2984 /* Writes are ignored. */
2985 break;
2986 case ARM_VFP_FPSCR:
2987 tmp = load_reg(s, rd);
2988 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2989 tcg_temp_free_i32(tmp);
2990 gen_lookup_tb(s);
2991 break;
2992 case ARM_VFP_FPEXC:
2993 if (IS_USER(s))
2994 return 1;
2995 /* TODO: VFP subarchitecture support.
2996 * For now, keep the EN bit only */
2997 tmp = load_reg(s, rd);
2998 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2999 store_cpu_field(tmp, vfp.xregs[rn]);
3000 gen_lookup_tb(s);
3001 break;
3002 case ARM_VFP_FPINST:
3003 case ARM_VFP_FPINST2:
3004 tmp = load_reg(s, rd);
3005 store_cpu_field(tmp, vfp.xregs[rn]);
3006 break;
3007 default:
3008 return 1;
3010 } else {
3011 tmp = load_reg(s, rd);
3012 gen_vfp_msr(tmp);
3013 gen_mov_vreg_F0(0, rn);
3017 } else {
3018 /* data processing */
3019 /* The opcode is in bits 23, 21, 20 and 6. */
3020 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3021 if (dp) {
3022 if (op == 15) {
3023 /* rn is opcode */
3024 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3025 } else {
3026 /* rn is register number */
3027 VFP_DREG_N(rn, insn);
3030 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
3031 /* Integer or single precision destination. */
3032 rd = VFP_SREG_D(insn);
3033 } else {
3034 VFP_DREG_D(rd, insn);
3036 if (op == 15 &&
3037 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
3038 /* VCVT from int is always from S reg regardless of dp bit.
3039 * VCVT with immediate frac_bits has same format as SREG_M
3041 rm = VFP_SREG_M(insn);
3042 } else {
3043 VFP_DREG_M(rm, insn);
3045 } else {
3046 rn = VFP_SREG_N(insn);
3047 if (op == 15 && rn == 15) {
3048 /* Double precision destination. */
3049 VFP_DREG_D(rd, insn);
3050 } else {
3051 rd = VFP_SREG_D(insn);
3053 /* NB that we implicitly rely on the encoding for the frac_bits
3054 * in VCVT of fixed to float being the same as that of an SREG_M
3056 rm = VFP_SREG_M(insn);
3059 veclen = s->vec_len;
3060 if (op == 15 && rn > 3)
3061 veclen = 0;
3063 /* Shut up compiler warnings. */
3064 delta_m = 0;
3065 delta_d = 0;
3066 bank_mask = 0;
3068 if (veclen > 0) {
3069 if (dp)
3070 bank_mask = 0xc;
3071 else
3072 bank_mask = 0x18;
3074 /* Figure out what type of vector operation this is. */
3075 if ((rd & bank_mask) == 0) {
3076 /* scalar */
3077 veclen = 0;
3078 } else {
3079 if (dp)
3080 delta_d = (s->vec_stride >> 1) + 1;
3081 else
3082 delta_d = s->vec_stride + 1;
3084 if ((rm & bank_mask) == 0) {
3085 /* mixed scalar/vector */
3086 delta_m = 0;
3087 } else {
3088 /* vector */
3089 delta_m = delta_d;
3094 /* Load the initial operands. */
3095 if (op == 15) {
3096 switch (rn) {
3097 case 16:
3098 case 17:
3099 /* Integer source */
3100 gen_mov_F0_vreg(0, rm);
3101 break;
3102 case 8:
3103 case 9:
3104 /* Compare */
3105 gen_mov_F0_vreg(dp, rd);
3106 gen_mov_F1_vreg(dp, rm);
3107 break;
3108 case 10:
3109 case 11:
3110 /* Compare with zero */
3111 gen_mov_F0_vreg(dp, rd);
3112 gen_vfp_F1_ld0(dp);
3113 break;
3114 case 20:
3115 case 21:
3116 case 22:
3117 case 23:
3118 case 28:
3119 case 29:
3120 case 30:
3121 case 31:
3122 /* Source and destination the same. */
3123 gen_mov_F0_vreg(dp, rd);
3124 break;
3125 case 4:
3126 case 5:
3127 case 6:
3128 case 7:
3129 /* VCVTB, VCVTT: only present with the halfprec extension,
3130 * UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
3132 if (dp || !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3133 return 1;
3135 /* Otherwise fall through */
3136 default:
3137 /* One source operand. */
3138 gen_mov_F0_vreg(dp, rm);
3139 break;
3141 } else {
3142 /* Two source operands. */
3143 gen_mov_F0_vreg(dp, rn);
3144 gen_mov_F1_vreg(dp, rm);
3147 for (;;) {
3148 /* Perform the calculation. */
3149 switch (op) {
3150 case 0: /* VMLA: fd + (fn * fm) */
3151 /* Note that order of inputs to the add matters for NaNs */
3152 gen_vfp_F1_mul(dp);
3153 gen_mov_F0_vreg(dp, rd);
3154 gen_vfp_add(dp);
3155 break;
3156 case 1: /* VMLS: fd + -(fn * fm) */
3157 gen_vfp_mul(dp);
3158 gen_vfp_F1_neg(dp);
3159 gen_mov_F0_vreg(dp, rd);
3160 gen_vfp_add(dp);
3161 break;
3162 case 2: /* VNMLS: -fd + (fn * fm) */
3163 /* Note that it isn't valid to replace (-A + B) with (B - A)
3164 * or similar plausible looking simplifications
3165 * because this will give wrong results for NaNs.
3167 gen_vfp_F1_mul(dp);
3168 gen_mov_F0_vreg(dp, rd);
3169 gen_vfp_neg(dp);
3170 gen_vfp_add(dp);
3171 break;
3172 case 3: /* VNMLA: -fd + -(fn * fm) */
3173 gen_vfp_mul(dp);
3174 gen_vfp_F1_neg(dp);
3175 gen_mov_F0_vreg(dp, rd);
3176 gen_vfp_neg(dp);
3177 gen_vfp_add(dp);
3178 break;
3179 case 4: /* mul: fn * fm */
3180 gen_vfp_mul(dp);
3181 break;
3182 case 5: /* nmul: -(fn * fm) */
3183 gen_vfp_mul(dp);
3184 gen_vfp_neg(dp);
3185 break;
3186 case 6: /* add: fn + fm */
3187 gen_vfp_add(dp);
3188 break;
3189 case 7: /* sub: fn - fm */
3190 gen_vfp_sub(dp);
3191 break;
3192 case 8: /* div: fn / fm */
3193 gen_vfp_div(dp);
3194 break;
3195 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3196 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3197 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3198 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3199 /* These are fused multiply-add, and must be done as one
3200 * floating point operation with no rounding between the
3201 * multiplication and addition steps.
3202 * NB that doing the negations here as separate steps is
3203 * correct : an input NaN should come out with its sign bit
3204 * flipped if it is a negated-input.
3206 if (!arm_feature(env, ARM_FEATURE_VFP4)) {
3207 return 1;
3209 if (dp) {
3210 TCGv_ptr fpst;
3211 TCGv_i64 frd;
3212 if (op & 1) {
3213 /* VFNMS, VFMS */
3214 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3216 frd = tcg_temp_new_i64();
3217 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3218 if (op & 2) {
3219 /* VFNMA, VFNMS */
3220 gen_helper_vfp_negd(frd, frd);
3222 fpst = get_fpstatus_ptr(0);
3223 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3224 cpu_F1d, frd, fpst);
3225 tcg_temp_free_ptr(fpst);
3226 tcg_temp_free_i64(frd);
3227 } else {
3228 TCGv_ptr fpst;
3229 TCGv_i32 frd;
3230 if (op & 1) {
3231 /* VFNMS, VFMS */
3232 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3234 frd = tcg_temp_new_i32();
3235 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3236 if (op & 2) {
3237 gen_helper_vfp_negs(frd, frd);
3239 fpst = get_fpstatus_ptr(0);
3240 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3241 cpu_F1s, frd, fpst);
3242 tcg_temp_free_ptr(fpst);
3243 tcg_temp_free_i32(frd);
3245 break;
3246 case 14: /* fconst */
3247 if (!arm_feature(env, ARM_FEATURE_VFP3))
3248 return 1;
3250 n = (insn << 12) & 0x80000000;
3251 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3252 if (dp) {
3253 if (i & 0x40)
3254 i |= 0x3f80;
3255 else
3256 i |= 0x4000;
3257 n |= i << 16;
3258 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3259 } else {
3260 if (i & 0x40)
3261 i |= 0x780;
3262 else
3263 i |= 0x800;
3264 n |= i << 19;
3265 tcg_gen_movi_i32(cpu_F0s, n);
3267 break;
3268 case 15: /* extension space */
3269 switch (rn) {
3270 case 0: /* cpy */
3271 /* no-op */
3272 break;
3273 case 1: /* abs */
3274 gen_vfp_abs(dp);
3275 break;
3276 case 2: /* neg */
3277 gen_vfp_neg(dp);
3278 break;
3279 case 3: /* sqrt */
3280 gen_vfp_sqrt(dp);
3281 break;
3282 case 4: /* vcvtb.f32.f16 */
3283 tmp = gen_vfp_mrs();
3284 tcg_gen_ext16u_i32(tmp, tmp);
3285 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3286 tcg_temp_free_i32(tmp);
3287 break;
3288 case 5: /* vcvtt.f32.f16 */
3289 tmp = gen_vfp_mrs();
3290 tcg_gen_shri_i32(tmp, tmp, 16);
3291 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3292 tcg_temp_free_i32(tmp);
3293 break;
3294 case 6: /* vcvtb.f16.f32 */
3295 tmp = tcg_temp_new_i32();
3296 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3297 gen_mov_F0_vreg(0, rd);
3298 tmp2 = gen_vfp_mrs();
3299 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3300 tcg_gen_or_i32(tmp, tmp, tmp2);
3301 tcg_temp_free_i32(tmp2);
3302 gen_vfp_msr(tmp);
3303 break;
3304 case 7: /* vcvtt.f16.f32 */
3305 tmp = tcg_temp_new_i32();
3306 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3307 tcg_gen_shli_i32(tmp, tmp, 16);
3308 gen_mov_F0_vreg(0, rd);
3309 tmp2 = gen_vfp_mrs();
3310 tcg_gen_ext16u_i32(tmp2, tmp2);
3311 tcg_gen_or_i32(tmp, tmp, tmp2);
3312 tcg_temp_free_i32(tmp2);
3313 gen_vfp_msr(tmp);
3314 break;
3315 case 8: /* cmp */
3316 gen_vfp_cmp(dp);
3317 break;
3318 case 9: /* cmpe */
3319 gen_vfp_cmpe(dp);
3320 break;
3321 case 10: /* cmpz */
3322 gen_vfp_cmp(dp);
3323 break;
3324 case 11: /* cmpez */
3325 gen_vfp_F1_ld0(dp);
3326 gen_vfp_cmpe(dp);
3327 break;
3328 case 15: /* single<->double conversion */
3329 if (dp)
3330 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3331 else
3332 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3333 break;
3334 case 16: /* fuito */
3335 gen_vfp_uito(dp, 0);
3336 break;
3337 case 17: /* fsito */
3338 gen_vfp_sito(dp, 0);
3339 break;
3340 case 20: /* fshto */
3341 if (!arm_feature(env, ARM_FEATURE_VFP3))
3342 return 1;
3343 gen_vfp_shto(dp, 16 - rm, 0);
3344 break;
3345 case 21: /* fslto */
3346 if (!arm_feature(env, ARM_FEATURE_VFP3))
3347 return 1;
3348 gen_vfp_slto(dp, 32 - rm, 0);
3349 break;
3350 case 22: /* fuhto */
3351 if (!arm_feature(env, ARM_FEATURE_VFP3))
3352 return 1;
3353 gen_vfp_uhto(dp, 16 - rm, 0);
3354 break;
3355 case 23: /* fulto */
3356 if (!arm_feature(env, ARM_FEATURE_VFP3))
3357 return 1;
3358 gen_vfp_ulto(dp, 32 - rm, 0);
3359 break;
3360 case 24: /* ftoui */
3361 gen_vfp_toui(dp, 0);
3362 break;
3363 case 25: /* ftouiz */
3364 gen_vfp_touiz(dp, 0);
3365 break;
3366 case 26: /* ftosi */
3367 gen_vfp_tosi(dp, 0);
3368 break;
3369 case 27: /* ftosiz */
3370 gen_vfp_tosiz(dp, 0);
3371 break;
3372 case 28: /* ftosh */
3373 if (!arm_feature(env, ARM_FEATURE_VFP3))
3374 return 1;
3375 gen_vfp_tosh(dp, 16 - rm, 0);
3376 break;
3377 case 29: /* ftosl */
3378 if (!arm_feature(env, ARM_FEATURE_VFP3))
3379 return 1;
3380 gen_vfp_tosl(dp, 32 - rm, 0);
3381 break;
3382 case 30: /* ftouh */
3383 if (!arm_feature(env, ARM_FEATURE_VFP3))
3384 return 1;
3385 gen_vfp_touh(dp, 16 - rm, 0);
3386 break;
3387 case 31: /* ftoul */
3388 if (!arm_feature(env, ARM_FEATURE_VFP3))
3389 return 1;
3390 gen_vfp_toul(dp, 32 - rm, 0);
3391 break;
3392 default: /* undefined */
3393 return 1;
3395 break;
3396 default: /* undefined */
3397 return 1;
3400 /* Write back the result. */
3401 if (op == 15 && (rn >= 8 && rn <= 11))
3402 ; /* Comparison, do nothing. */
3403 else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3404 /* VCVT double to int: always integer result. */
3405 gen_mov_vreg_F0(0, rd);
3406 else if (op == 15 && rn == 15)
3407 /* conversion */
3408 gen_mov_vreg_F0(!dp, rd);
3409 else
3410 gen_mov_vreg_F0(dp, rd);
3412 /* break out of the loop if we have finished */
3413 if (veclen == 0)
3414 break;
3416 if (op == 15 && delta_m == 0) {
3417 /* single source one-many */
3418 while (veclen--) {
3419 rd = ((rd + delta_d) & (bank_mask - 1))
3420 | (rd & bank_mask);
3421 gen_mov_vreg_F0(dp, rd);
3423 break;
3425 /* Setup the next operands. */
3426 veclen--;
3427 rd = ((rd + delta_d) & (bank_mask - 1))
3428 | (rd & bank_mask);
3430 if (op == 15) {
3431 /* One source operand. */
3432 rm = ((rm + delta_m) & (bank_mask - 1))
3433 | (rm & bank_mask);
3434 gen_mov_F0_vreg(dp, rm);
3435 } else {
3436 /* Two source operands. */
3437 rn = ((rn + delta_d) & (bank_mask - 1))
3438 | (rn & bank_mask);
3439 gen_mov_F0_vreg(dp, rn);
3440 if (delta_m) {
3441 rm = ((rm + delta_m) & (bank_mask - 1))
3442 | (rm & bank_mask);
3443 gen_mov_F1_vreg(dp, rm);
3448 break;
3449 case 0xc:
3450 case 0xd:
3451 if ((insn & 0x03e00000) == 0x00400000) {
3452 /* two-register transfer */
3453 rn = (insn >> 16) & 0xf;
3454 rd = (insn >> 12) & 0xf;
3455 if (dp) {
3456 VFP_DREG_M(rm, insn);
3457 } else {
3458 rm = VFP_SREG_M(insn);
3461 if (insn & ARM_CP_RW_BIT) {
3462 /* vfp->arm */
3463 if (dp) {
3464 gen_mov_F0_vreg(0, rm * 2);
3465 tmp = gen_vfp_mrs();
3466 store_reg(s, rd, tmp);
3467 gen_mov_F0_vreg(0, rm * 2 + 1);
3468 tmp = gen_vfp_mrs();
3469 store_reg(s, rn, tmp);
3470 } else {
3471 gen_mov_F0_vreg(0, rm);
3472 tmp = gen_vfp_mrs();
3473 store_reg(s, rd, tmp);
3474 gen_mov_F0_vreg(0, rm + 1);
3475 tmp = gen_vfp_mrs();
3476 store_reg(s, rn, tmp);
3478 } else {
3479 /* arm->vfp */
3480 if (dp) {
3481 tmp = load_reg(s, rd);
3482 gen_vfp_msr(tmp);
3483 gen_mov_vreg_F0(0, rm * 2);
3484 tmp = load_reg(s, rn);
3485 gen_vfp_msr(tmp);
3486 gen_mov_vreg_F0(0, rm * 2 + 1);
3487 } else {
3488 tmp = load_reg(s, rd);
3489 gen_vfp_msr(tmp);
3490 gen_mov_vreg_F0(0, rm);
3491 tmp = load_reg(s, rn);
3492 gen_vfp_msr(tmp);
3493 gen_mov_vreg_F0(0, rm + 1);
3496 } else {
3497 /* Load/store */
3498 rn = (insn >> 16) & 0xf;
3499 if (dp)
3500 VFP_DREG_D(rd, insn);
3501 else
3502 rd = VFP_SREG_D(insn);
3503 if ((insn & 0x01200000) == 0x01000000) {
3504 /* Single load/store */
3505 offset = (insn & 0xff) << 2;
3506 if ((insn & (1 << 23)) == 0)
3507 offset = -offset;
3508 if (s->thumb && rn == 15) {
3509 /* This is actually UNPREDICTABLE */
3510 addr = tcg_temp_new_i32();
3511 tcg_gen_movi_i32(addr, s->pc & ~2);
3512 } else {
3513 addr = load_reg(s, rn);
3515 tcg_gen_addi_i32(addr, addr, offset);
3516 if (insn & (1 << 20)) {
3517 gen_vfp_ld(s, dp, addr);
3518 gen_mov_vreg_F0(dp, rd);
3519 } else {
3520 gen_mov_F0_vreg(dp, rd);
3521 gen_vfp_st(s, dp, addr);
3523 tcg_temp_free_i32(addr);
3524 } else {
3525 /* load/store multiple */
3526 int w = insn & (1 << 21);
3527 if (dp)
3528 n = (insn >> 1) & 0x7f;
3529 else
3530 n = insn & 0xff;
3532 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3533 /* P == U , W == 1 => UNDEF */
3534 return 1;
3536 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3537 /* UNPREDICTABLE cases for bad immediates: we choose to
3538 * UNDEF to avoid generating huge numbers of TCG ops
3540 return 1;
3542 if (rn == 15 && w) {
3543 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3544 return 1;
3547 if (s->thumb && rn == 15) {
3548 /* This is actually UNPREDICTABLE */
3549 addr = tcg_temp_new_i32();
3550 tcg_gen_movi_i32(addr, s->pc & ~2);
3551 } else {
3552 addr = load_reg(s, rn);
3554 if (insn & (1 << 24)) /* pre-decrement */
3555 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3557 if (dp)
3558 offset = 8;
3559 else
3560 offset = 4;
3561 for (i = 0; i < n; i++) {
3562 if (insn & ARM_CP_RW_BIT) {
3563 /* load */
3564 gen_vfp_ld(s, dp, addr);
3565 gen_mov_vreg_F0(dp, rd + i);
3566 } else {
3567 /* store */
3568 gen_mov_F0_vreg(dp, rd + i);
3569 gen_vfp_st(s, dp, addr);
3571 tcg_gen_addi_i32(addr, addr, offset);
3573 if (w) {
3574 /* writeback */
3575 if (insn & (1 << 24))
3576 offset = -offset * n;
3577 else if (dp && (insn & 1))
3578 offset = 4;
3579 else
3580 offset = 0;
3582 if (offset != 0)
3583 tcg_gen_addi_i32(addr, addr, offset);
3584 store_reg(s, rn, addr);
3585 } else {
3586 tcg_temp_free_i32(addr);
3590 break;
3591 default:
3592 /* Should never happen. */
3593 return 1;
3595 return 0;
3598 static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
3600 TranslationBlock *tb;
3602 tb = s->tb;
3603 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3604 tcg_gen_goto_tb(n);
3605 gen_set_pc_im(s, dest);
3606 tcg_gen_exit_tb((uintptr_t)tb + n);
3607 } else {
3608 gen_set_pc_im(s, dest);
3609 tcg_gen_exit_tb(0);
3613 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3615 if (unlikely(s->singlestep_enabled)) {
3616 /* An indirect jump so that we still trigger the debug exception. */
3617 if (s->thumb)
3618 dest |= 1;
3619 gen_bx_im(s, dest);
3620 } else {
3621 gen_goto_tb(s, 0, dest);
3622 s->is_jmp = DISAS_TB_JUMP;
3626 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
3628 if (x)
3629 tcg_gen_sari_i32(t0, t0, 16);
3630 else
3631 gen_sxth(t0);
3632 if (y)
3633 tcg_gen_sari_i32(t1, t1, 16);
3634 else
3635 gen_sxth(t1);
3636 tcg_gen_mul_i32(t0, t0, t1);
3639 /* Return the mask of PSR bits set by a MSR instruction. */
3640 static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
3641 uint32_t mask;
3643 mask = 0;
3644 if (flags & (1 << 0))
3645 mask |= 0xff;
3646 if (flags & (1 << 1))
3647 mask |= 0xff00;
3648 if (flags & (1 << 2))
3649 mask |= 0xff0000;
3650 if (flags & (1 << 3))
3651 mask |= 0xff000000;
3653 /* Mask out undefined bits. */
3654 mask &= ~CPSR_RESERVED;
3655 if (!arm_feature(env, ARM_FEATURE_V4T))
3656 mask &= ~CPSR_T;
3657 if (!arm_feature(env, ARM_FEATURE_V5))
3658 mask &= ~CPSR_Q; /* V5TE in reality*/
3659 if (!arm_feature(env, ARM_FEATURE_V6))
3660 mask &= ~(CPSR_E | CPSR_GE);
3661 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3662 mask &= ~CPSR_IT;
3663 /* Mask out execution state bits. */
3664 if (!spsr)
3665 mask &= ~CPSR_EXEC;
3666 /* Mask out privileged bits. */
3667 if (IS_USER(s))
3668 mask &= CPSR_USER;
3669 return mask;
3672 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3673 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
3675 TCGv_i32 tmp;
3676 if (spsr) {
3677 /* ??? This is also undefined in system mode. */
3678 if (IS_USER(s))
3679 return 1;
3681 tmp = load_cpu_field(spsr);
3682 tcg_gen_andi_i32(tmp, tmp, ~mask);
3683 tcg_gen_andi_i32(t0, t0, mask);
3684 tcg_gen_or_i32(tmp, tmp, t0);
3685 store_cpu_field(tmp, spsr);
3686 } else {
3687 gen_set_cpsr(t0, mask);
3689 tcg_temp_free_i32(t0);
3690 gen_lookup_tb(s);
3691 return 0;
3694 /* Returns nonzero if access to the PSR is not permitted. */
3695 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3697 TCGv_i32 tmp;
3698 tmp = tcg_temp_new_i32();
3699 tcg_gen_movi_i32(tmp, val);
3700 return gen_set_psr(s, mask, spsr, tmp);
3703 /* Generate an old-style exception return. Marks pc as dead. */
3704 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3706 TCGv_i32 tmp;
3707 store_reg(s, 15, pc);
3708 tmp = load_cpu_field(spsr);
3709 gen_set_cpsr(tmp, 0xffffffff);
3710 tcg_temp_free_i32(tmp);
3711 s->is_jmp = DISAS_UPDATE;
3714 /* Generate a v6 exception return. Marks both values as dead. */
3715 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
3717 gen_set_cpsr(cpsr, 0xffffffff);
3718 tcg_temp_free_i32(cpsr);
3719 store_reg(s, 15, pc);
3720 s->is_jmp = DISAS_UPDATE;
3723 static inline void
3724 gen_set_condexec (DisasContext *s)
3726 if (s->condexec_mask) {
3727 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3728 TCGv_i32 tmp = tcg_temp_new_i32();
3729 tcg_gen_movi_i32(tmp, val);
3730 store_cpu_field(tmp, condexec_bits);
3734 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3736 gen_set_condexec(s);
3737 gen_set_pc_im(s, s->pc - offset);
3738 gen_exception(excp);
3739 s->is_jmp = DISAS_JUMP;
3742 static void gen_nop_hint(DisasContext *s, int val)
3744 switch (val) {
3745 case 3: /* wfi */
3746 gen_set_pc_im(s, s->pc);
3747 s->is_jmp = DISAS_WFI;
3748 break;
3749 case 2: /* wfe */
3750 case 4: /* sev */
3751 case 5: /* sevl */
3752 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
3753 default: /* nop */
3754 break;
3758 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3760 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
3762 switch (size) {
3763 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3764 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3765 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3766 default: abort();
3770 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
3772 switch (size) {
3773 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3774 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3775 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3776 default: return;
3780 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3781 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3782 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3783 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3784 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3786 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3787 switch ((size << 1) | u) { \
3788 case 0: \
3789 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3790 break; \
3791 case 1: \
3792 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3793 break; \
3794 case 2: \
3795 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3796 break; \
3797 case 3: \
3798 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3799 break; \
3800 case 4: \
3801 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3802 break; \
3803 case 5: \
3804 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3805 break; \
3806 default: return 1; \
3807 }} while (0)
3809 #define GEN_NEON_INTEGER_OP(name) do { \
3810 switch ((size << 1) | u) { \
3811 case 0: \
3812 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3813 break; \
3814 case 1: \
3815 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3816 break; \
3817 case 2: \
3818 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3819 break; \
3820 case 3: \
3821 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3822 break; \
3823 case 4: \
3824 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3825 break; \
3826 case 5: \
3827 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3828 break; \
3829 default: return 1; \
3830 }} while (0)
3832 static TCGv_i32 neon_load_scratch(int scratch)
3834 TCGv_i32 tmp = tcg_temp_new_i32();
3835 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3836 return tmp;
3839 static void neon_store_scratch(int scratch, TCGv_i32 var)
3841 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3842 tcg_temp_free_i32(var);
3845 static inline TCGv_i32 neon_get_scalar(int size, int reg)
3847 TCGv_i32 tmp;
3848 if (size == 1) {
3849 tmp = neon_load_reg(reg & 7, reg >> 4);
3850 if (reg & 8) {
3851 gen_neon_dup_high16(tmp);
3852 } else {
3853 gen_neon_dup_low16(tmp);
3855 } else {
3856 tmp = neon_load_reg(reg & 15, reg >> 4);
3858 return tmp;
3861 static int gen_neon_unzip(int rd, int rm, int size, int q)
3863 TCGv_i32 tmp, tmp2;
3864 if (!q && size == 2) {
3865 return 1;
3867 tmp = tcg_const_i32(rd);
3868 tmp2 = tcg_const_i32(rm);
3869 if (q) {
3870 switch (size) {
3871 case 0:
3872 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3873 break;
3874 case 1:
3875 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3876 break;
3877 case 2:
3878 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3879 break;
3880 default:
3881 abort();
3883 } else {
3884 switch (size) {
3885 case 0:
3886 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3887 break;
3888 case 1:
3889 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3890 break;
3891 default:
3892 abort();
3895 tcg_temp_free_i32(tmp);
3896 tcg_temp_free_i32(tmp2);
3897 return 0;
3900 static int gen_neon_zip(int rd, int rm, int size, int q)
3902 TCGv_i32 tmp, tmp2;
3903 if (!q && size == 2) {
3904 return 1;
3906 tmp = tcg_const_i32(rd);
3907 tmp2 = tcg_const_i32(rm);
3908 if (q) {
3909 switch (size) {
3910 case 0:
3911 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3912 break;
3913 case 1:
3914 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3915 break;
3916 case 2:
3917 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3918 break;
3919 default:
3920 abort();
3922 } else {
3923 switch (size) {
3924 case 0:
3925 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3926 break;
3927 case 1:
3928 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3929 break;
3930 default:
3931 abort();
3934 tcg_temp_free_i32(tmp);
3935 tcg_temp_free_i32(tmp2);
3936 return 0;
3939 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
3941 TCGv_i32 rd, tmp;
3943 rd = tcg_temp_new_i32();
3944 tmp = tcg_temp_new_i32();
3946 tcg_gen_shli_i32(rd, t0, 8);
3947 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3948 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3949 tcg_gen_or_i32(rd, rd, tmp);
3951 tcg_gen_shri_i32(t1, t1, 8);
3952 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3953 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3954 tcg_gen_or_i32(t1, t1, tmp);
3955 tcg_gen_mov_i32(t0, rd);
3957 tcg_temp_free_i32(tmp);
3958 tcg_temp_free_i32(rd);
3961 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
3963 TCGv_i32 rd, tmp;
3965 rd = tcg_temp_new_i32();
3966 tmp = tcg_temp_new_i32();
3968 tcg_gen_shli_i32(rd, t0, 16);
3969 tcg_gen_andi_i32(tmp, t1, 0xffff);
3970 tcg_gen_or_i32(rd, rd, tmp);
3971 tcg_gen_shri_i32(t1, t1, 16);
3972 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3973 tcg_gen_or_i32(t1, t1, tmp);
3974 tcg_gen_mov_i32(t0, rd);
3976 tcg_temp_free_i32(tmp);
3977 tcg_temp_free_i32(rd);
3981 static struct {
3982 int nregs;
3983 int interleave;
3984 int spacing;
3985 } neon_ls_element_type[11] = {
3986 {4, 4, 1},
3987 {4, 4, 2},
3988 {4, 1, 1},
3989 {4, 2, 1},
3990 {3, 3, 1},
3991 {3, 3, 2},
3992 {3, 1, 1},
3993 {1, 1, 1},
3994 {2, 2, 1},
3995 {2, 2, 2},
3996 {2, 1, 1}
3999 /* Translate a NEON load/store element instruction. Return nonzero if the
4000 instruction is invalid. */
4001 static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4003 int rd, rn, rm;
4004 int op;
4005 int nregs;
4006 int interleave;
4007 int spacing;
4008 int stride;
4009 int size;
4010 int reg;
4011 int pass;
4012 int load;
4013 int shift;
4014 int n;
4015 TCGv_i32 addr;
4016 TCGv_i32 tmp;
4017 TCGv_i32 tmp2;
4018 TCGv_i64 tmp64;
4020 if (!s->vfp_enabled)
4021 return 1;
4022 VFP_DREG_D(rd, insn);
4023 rn = (insn >> 16) & 0xf;
4024 rm = insn & 0xf;
4025 load = (insn & (1 << 21)) != 0;
4026 if ((insn & (1 << 23)) == 0) {
4027 /* Load store all elements. */
4028 op = (insn >> 8) & 0xf;
4029 size = (insn >> 6) & 3;
4030 if (op > 10)
4031 return 1;
4032 /* Catch UNDEF cases for bad values of align field */
4033 switch (op & 0xc) {
4034 case 4:
4035 if (((insn >> 5) & 1) == 1) {
4036 return 1;
4038 break;
4039 case 8:
4040 if (((insn >> 4) & 3) == 3) {
4041 return 1;
4043 break;
4044 default:
4045 break;
4047 nregs = neon_ls_element_type[op].nregs;
4048 interleave = neon_ls_element_type[op].interleave;
4049 spacing = neon_ls_element_type[op].spacing;
4050 if (size == 3 && (interleave | spacing) != 1)
4051 return 1;
4052 addr = tcg_temp_new_i32();
4053 load_reg_var(s, addr, rn);
4054 stride = (1 << size) * interleave;
4055 for (reg = 0; reg < nregs; reg++) {
4056 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
4057 load_reg_var(s, addr, rn);
4058 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
4059 } else if (interleave == 2 && nregs == 4 && reg == 2) {
4060 load_reg_var(s, addr, rn);
4061 tcg_gen_addi_i32(addr, addr, 1 << size);
4063 if (size == 3) {
4064 tmp64 = tcg_temp_new_i64();
4065 if (load) {
4066 gen_aa32_ld64(tmp64, addr, IS_USER(s));
4067 neon_store_reg64(tmp64, rd);
4068 } else {
4069 neon_load_reg64(tmp64, rd);
4070 gen_aa32_st64(tmp64, addr, IS_USER(s));
4072 tcg_temp_free_i64(tmp64);
4073 tcg_gen_addi_i32(addr, addr, stride);
4074 } else {
4075 for (pass = 0; pass < 2; pass++) {
4076 if (size == 2) {
4077 if (load) {
4078 tmp = tcg_temp_new_i32();
4079 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4080 neon_store_reg(rd, pass, tmp);
4081 } else {
4082 tmp = neon_load_reg(rd, pass);
4083 gen_aa32_st32(tmp, addr, IS_USER(s));
4084 tcg_temp_free_i32(tmp);
4086 tcg_gen_addi_i32(addr, addr, stride);
4087 } else if (size == 1) {
4088 if (load) {
4089 tmp = tcg_temp_new_i32();
4090 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4091 tcg_gen_addi_i32(addr, addr, stride);
4092 tmp2 = tcg_temp_new_i32();
4093 gen_aa32_ld16u(tmp2, addr, IS_USER(s));
4094 tcg_gen_addi_i32(addr, addr, stride);
4095 tcg_gen_shli_i32(tmp2, tmp2, 16);
4096 tcg_gen_or_i32(tmp, tmp, tmp2);
4097 tcg_temp_free_i32(tmp2);
4098 neon_store_reg(rd, pass, tmp);
4099 } else {
4100 tmp = neon_load_reg(rd, pass);
4101 tmp2 = tcg_temp_new_i32();
4102 tcg_gen_shri_i32(tmp2, tmp, 16);
4103 gen_aa32_st16(tmp, addr, IS_USER(s));
4104 tcg_temp_free_i32(tmp);
4105 tcg_gen_addi_i32(addr, addr, stride);
4106 gen_aa32_st16(tmp2, addr, IS_USER(s));
4107 tcg_temp_free_i32(tmp2);
4108 tcg_gen_addi_i32(addr, addr, stride);
4110 } else /* size == 0 */ {
4111 if (load) {
4112 TCGV_UNUSED_I32(tmp2);
4113 for (n = 0; n < 4; n++) {
4114 tmp = tcg_temp_new_i32();
4115 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4116 tcg_gen_addi_i32(addr, addr, stride);
4117 if (n == 0) {
4118 tmp2 = tmp;
4119 } else {
4120 tcg_gen_shli_i32(tmp, tmp, n * 8);
4121 tcg_gen_or_i32(tmp2, tmp2, tmp);
4122 tcg_temp_free_i32(tmp);
4125 neon_store_reg(rd, pass, tmp2);
4126 } else {
4127 tmp2 = neon_load_reg(rd, pass);
4128 for (n = 0; n < 4; n++) {
4129 tmp = tcg_temp_new_i32();
4130 if (n == 0) {
4131 tcg_gen_mov_i32(tmp, tmp2);
4132 } else {
4133 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4135 gen_aa32_st8(tmp, addr, IS_USER(s));
4136 tcg_temp_free_i32(tmp);
4137 tcg_gen_addi_i32(addr, addr, stride);
4139 tcg_temp_free_i32(tmp2);
4144 rd += spacing;
4146 tcg_temp_free_i32(addr);
4147 stride = nregs * 8;
4148 } else {
4149 size = (insn >> 10) & 3;
4150 if (size == 3) {
4151 /* Load single element to all lanes. */
4152 int a = (insn >> 4) & 1;
4153 if (!load) {
4154 return 1;
4156 size = (insn >> 6) & 3;
4157 nregs = ((insn >> 8) & 3) + 1;
4159 if (size == 3) {
4160 if (nregs != 4 || a == 0) {
4161 return 1;
4163 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4164 size = 2;
4166 if (nregs == 1 && a == 1 && size == 0) {
4167 return 1;
4169 if (nregs == 3 && a == 1) {
4170 return 1;
4172 addr = tcg_temp_new_i32();
4173 load_reg_var(s, addr, rn);
4174 if (nregs == 1) {
4175 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4176 tmp = gen_load_and_replicate(s, addr, size);
4177 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4178 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4179 if (insn & (1 << 5)) {
4180 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4181 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4183 tcg_temp_free_i32(tmp);
4184 } else {
4185 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4186 stride = (insn & (1 << 5)) ? 2 : 1;
4187 for (reg = 0; reg < nregs; reg++) {
4188 tmp = gen_load_and_replicate(s, addr, size);
4189 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4190 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4191 tcg_temp_free_i32(tmp);
4192 tcg_gen_addi_i32(addr, addr, 1 << size);
4193 rd += stride;
4196 tcg_temp_free_i32(addr);
4197 stride = (1 << size) * nregs;
4198 } else {
4199 /* Single element. */
4200 int idx = (insn >> 4) & 0xf;
4201 pass = (insn >> 7) & 1;
4202 switch (size) {
4203 case 0:
4204 shift = ((insn >> 5) & 3) * 8;
4205 stride = 1;
4206 break;
4207 case 1:
4208 shift = ((insn >> 6) & 1) * 16;
4209 stride = (insn & (1 << 5)) ? 2 : 1;
4210 break;
4211 case 2:
4212 shift = 0;
4213 stride = (insn & (1 << 6)) ? 2 : 1;
4214 break;
4215 default:
4216 abort();
4218 nregs = ((insn >> 8) & 3) + 1;
4219 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4220 switch (nregs) {
4221 case 1:
4222 if (((idx & (1 << size)) != 0) ||
4223 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4224 return 1;
4226 break;
4227 case 3:
4228 if ((idx & 1) != 0) {
4229 return 1;
4231 /* fall through */
4232 case 2:
4233 if (size == 2 && (idx & 2) != 0) {
4234 return 1;
4236 break;
4237 case 4:
4238 if ((size == 2) && ((idx & 3) == 3)) {
4239 return 1;
4241 break;
4242 default:
4243 abort();
4245 if ((rd + stride * (nregs - 1)) > 31) {
4246 /* Attempts to write off the end of the register file
4247 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4248 * the neon_load_reg() would write off the end of the array.
4250 return 1;
4252 addr = tcg_temp_new_i32();
4253 load_reg_var(s, addr, rn);
4254 for (reg = 0; reg < nregs; reg++) {
4255 if (load) {
4256 tmp = tcg_temp_new_i32();
4257 switch (size) {
4258 case 0:
4259 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4260 break;
4261 case 1:
4262 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4263 break;
4264 case 2:
4265 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4266 break;
4267 default: /* Avoid compiler warnings. */
4268 abort();
4270 if (size != 2) {
4271 tmp2 = neon_load_reg(rd, pass);
4272 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4273 shift, size ? 16 : 8);
4274 tcg_temp_free_i32(tmp2);
4276 neon_store_reg(rd, pass, tmp);
4277 } else { /* Store */
4278 tmp = neon_load_reg(rd, pass);
4279 if (shift)
4280 tcg_gen_shri_i32(tmp, tmp, shift);
4281 switch (size) {
4282 case 0:
4283 gen_aa32_st8(tmp, addr, IS_USER(s));
4284 break;
4285 case 1:
4286 gen_aa32_st16(tmp, addr, IS_USER(s));
4287 break;
4288 case 2:
4289 gen_aa32_st32(tmp, addr, IS_USER(s));
4290 break;
4292 tcg_temp_free_i32(tmp);
4294 rd += stride;
4295 tcg_gen_addi_i32(addr, addr, 1 << size);
4297 tcg_temp_free_i32(addr);
4298 stride = nregs * (1 << size);
4301 if (rm != 15) {
4302 TCGv_i32 base;
4304 base = load_reg(s, rn);
4305 if (rm == 13) {
4306 tcg_gen_addi_i32(base, base, stride);
4307 } else {
4308 TCGv_i32 index;
4309 index = load_reg(s, rm);
4310 tcg_gen_add_i32(base, base, index);
4311 tcg_temp_free_i32(index);
4313 store_reg(s, rn, base);
4315 return 0;
4318 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4319 static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
4321 tcg_gen_and_i32(t, t, c);
4322 tcg_gen_andc_i32(f, f, c);
4323 tcg_gen_or_i32(dest, t, f);
4326 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4328 switch (size) {
4329 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4330 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4331 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4332 default: abort();
4336 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4338 switch (size) {
4339 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4340 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4341 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4342 default: abort();
4346 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
4348 switch (size) {
4349 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4350 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4351 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4352 default: abort();
4356 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4358 switch (size) {
4359 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4360 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4361 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4362 default: abort();
4366 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
4367 int q, int u)
4369 if (q) {
4370 if (u) {
4371 switch (size) {
4372 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4373 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4374 default: abort();
4376 } else {
4377 switch (size) {
4378 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4379 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4380 default: abort();
4383 } else {
4384 if (u) {
4385 switch (size) {
4386 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4387 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4388 default: abort();
4390 } else {
4391 switch (size) {
4392 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4393 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4394 default: abort();
4400 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
4402 if (u) {
4403 switch (size) {
4404 case 0: gen_helper_neon_widen_u8(dest, src); break;
4405 case 1: gen_helper_neon_widen_u16(dest, src); break;
4406 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4407 default: abort();
4409 } else {
4410 switch (size) {
4411 case 0: gen_helper_neon_widen_s8(dest, src); break;
4412 case 1: gen_helper_neon_widen_s16(dest, src); break;
4413 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4414 default: abort();
4417 tcg_temp_free_i32(src);
4420 static inline void gen_neon_addl(int size)
4422 switch (size) {
4423 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4424 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4425 case 2: tcg_gen_add_i64(CPU_V001); break;
4426 default: abort();
4430 static inline void gen_neon_subl(int size)
4432 switch (size) {
4433 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4434 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4435 case 2: tcg_gen_sub_i64(CPU_V001); break;
4436 default: abort();
4440 static inline void gen_neon_negl(TCGv_i64 var, int size)
4442 switch (size) {
4443 case 0: gen_helper_neon_negl_u16(var, var); break;
4444 case 1: gen_helper_neon_negl_u32(var, var); break;
4445 case 2:
4446 tcg_gen_neg_i64(var, var);
4447 break;
4448 default: abort();
4452 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4454 switch (size) {
4455 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4456 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4457 default: abort();
4461 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4462 int size, int u)
4464 TCGv_i64 tmp;
4466 switch ((size << 1) | u) {
4467 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4468 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4469 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4470 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4471 case 4:
4472 tmp = gen_muls_i64_i32(a, b);
4473 tcg_gen_mov_i64(dest, tmp);
4474 tcg_temp_free_i64(tmp);
4475 break;
4476 case 5:
4477 tmp = gen_mulu_i64_i32(a, b);
4478 tcg_gen_mov_i64(dest, tmp);
4479 tcg_temp_free_i64(tmp);
4480 break;
4481 default: abort();
4484 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4485 Don't forget to clean them now. */
4486 if (size < 2) {
4487 tcg_temp_free_i32(a);
4488 tcg_temp_free_i32(b);
4492 static void gen_neon_narrow_op(int op, int u, int size,
4493 TCGv_i32 dest, TCGv_i64 src)
4495 if (op) {
4496 if (u) {
4497 gen_neon_unarrow_sats(size, dest, src);
4498 } else {
4499 gen_neon_narrow(size, dest, src);
4501 } else {
4502 if (u) {
4503 gen_neon_narrow_satu(size, dest, src);
4504 } else {
4505 gen_neon_narrow_sats(size, dest, src);
4510 /* Symbolic constants for op fields for Neon 3-register same-length.
4511 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4512 * table A7-9.
4514 #define NEON_3R_VHADD 0
4515 #define NEON_3R_VQADD 1
4516 #define NEON_3R_VRHADD 2
4517 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4518 #define NEON_3R_VHSUB 4
4519 #define NEON_3R_VQSUB 5
4520 #define NEON_3R_VCGT 6
4521 #define NEON_3R_VCGE 7
4522 #define NEON_3R_VSHL 8
4523 #define NEON_3R_VQSHL 9
4524 #define NEON_3R_VRSHL 10
4525 #define NEON_3R_VQRSHL 11
4526 #define NEON_3R_VMAX 12
4527 #define NEON_3R_VMIN 13
4528 #define NEON_3R_VABD 14
4529 #define NEON_3R_VABA 15
4530 #define NEON_3R_VADD_VSUB 16
4531 #define NEON_3R_VTST_VCEQ 17
4532 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4533 #define NEON_3R_VMUL 19
4534 #define NEON_3R_VPMAX 20
4535 #define NEON_3R_VPMIN 21
4536 #define NEON_3R_VQDMULH_VQRDMULH 22
4537 #define NEON_3R_VPADD 23
4538 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4539 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4540 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4541 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4542 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4543 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4544 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
4546 static const uint8_t neon_3r_sizes[] = {
4547 [NEON_3R_VHADD] = 0x7,
4548 [NEON_3R_VQADD] = 0xf,
4549 [NEON_3R_VRHADD] = 0x7,
4550 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4551 [NEON_3R_VHSUB] = 0x7,
4552 [NEON_3R_VQSUB] = 0xf,
4553 [NEON_3R_VCGT] = 0x7,
4554 [NEON_3R_VCGE] = 0x7,
4555 [NEON_3R_VSHL] = 0xf,
4556 [NEON_3R_VQSHL] = 0xf,
4557 [NEON_3R_VRSHL] = 0xf,
4558 [NEON_3R_VQRSHL] = 0xf,
4559 [NEON_3R_VMAX] = 0x7,
4560 [NEON_3R_VMIN] = 0x7,
4561 [NEON_3R_VABD] = 0x7,
4562 [NEON_3R_VABA] = 0x7,
4563 [NEON_3R_VADD_VSUB] = 0xf,
4564 [NEON_3R_VTST_VCEQ] = 0x7,
4565 [NEON_3R_VML] = 0x7,
4566 [NEON_3R_VMUL] = 0x7,
4567 [NEON_3R_VPMAX] = 0x7,
4568 [NEON_3R_VPMIN] = 0x7,
4569 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4570 [NEON_3R_VPADD] = 0x7,
4571 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
4572 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4573 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4574 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4575 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4576 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4577 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
4580 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4581 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4582 * table A7-13.
4584 #define NEON_2RM_VREV64 0
4585 #define NEON_2RM_VREV32 1
4586 #define NEON_2RM_VREV16 2
4587 #define NEON_2RM_VPADDL 4
4588 #define NEON_2RM_VPADDL_U 5
4589 #define NEON_2RM_AESE 6 /* Includes AESD */
4590 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
4591 #define NEON_2RM_VCLS 8
4592 #define NEON_2RM_VCLZ 9
4593 #define NEON_2RM_VCNT 10
4594 #define NEON_2RM_VMVN 11
4595 #define NEON_2RM_VPADAL 12
4596 #define NEON_2RM_VPADAL_U 13
4597 #define NEON_2RM_VQABS 14
4598 #define NEON_2RM_VQNEG 15
4599 #define NEON_2RM_VCGT0 16
4600 #define NEON_2RM_VCGE0 17
4601 #define NEON_2RM_VCEQ0 18
4602 #define NEON_2RM_VCLE0 19
4603 #define NEON_2RM_VCLT0 20
4604 #define NEON_2RM_VABS 22
4605 #define NEON_2RM_VNEG 23
4606 #define NEON_2RM_VCGT0_F 24
4607 #define NEON_2RM_VCGE0_F 25
4608 #define NEON_2RM_VCEQ0_F 26
4609 #define NEON_2RM_VCLE0_F 27
4610 #define NEON_2RM_VCLT0_F 28
4611 #define NEON_2RM_VABS_F 30
4612 #define NEON_2RM_VNEG_F 31
4613 #define NEON_2RM_VSWP 32
4614 #define NEON_2RM_VTRN 33
4615 #define NEON_2RM_VUZP 34
4616 #define NEON_2RM_VZIP 35
4617 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4618 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4619 #define NEON_2RM_VSHLL 38
4620 #define NEON_2RM_VCVT_F16_F32 44
4621 #define NEON_2RM_VCVT_F32_F16 46
4622 #define NEON_2RM_VRECPE 56
4623 #define NEON_2RM_VRSQRTE 57
4624 #define NEON_2RM_VRECPE_F 58
4625 #define NEON_2RM_VRSQRTE_F 59
4626 #define NEON_2RM_VCVT_FS 60
4627 #define NEON_2RM_VCVT_FU 61
4628 #define NEON_2RM_VCVT_SF 62
4629 #define NEON_2RM_VCVT_UF 63
4631 static int neon_2rm_is_float_op(int op)
4633 /* Return true if this neon 2reg-misc op is float-to-float */
4634 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4635 op >= NEON_2RM_VRECPE_F);
4638 /* Each entry in this array has bit n set if the insn allows
4639 * size value n (otherwise it will UNDEF). Since unallocated
4640 * op values will have no bits set they always UNDEF.
4642 static const uint8_t neon_2rm_sizes[] = {
4643 [NEON_2RM_VREV64] = 0x7,
4644 [NEON_2RM_VREV32] = 0x3,
4645 [NEON_2RM_VREV16] = 0x1,
4646 [NEON_2RM_VPADDL] = 0x7,
4647 [NEON_2RM_VPADDL_U] = 0x7,
4648 [NEON_2RM_AESE] = 0x1,
4649 [NEON_2RM_AESMC] = 0x1,
4650 [NEON_2RM_VCLS] = 0x7,
4651 [NEON_2RM_VCLZ] = 0x7,
4652 [NEON_2RM_VCNT] = 0x1,
4653 [NEON_2RM_VMVN] = 0x1,
4654 [NEON_2RM_VPADAL] = 0x7,
4655 [NEON_2RM_VPADAL_U] = 0x7,
4656 [NEON_2RM_VQABS] = 0x7,
4657 [NEON_2RM_VQNEG] = 0x7,
4658 [NEON_2RM_VCGT0] = 0x7,
4659 [NEON_2RM_VCGE0] = 0x7,
4660 [NEON_2RM_VCEQ0] = 0x7,
4661 [NEON_2RM_VCLE0] = 0x7,
4662 [NEON_2RM_VCLT0] = 0x7,
4663 [NEON_2RM_VABS] = 0x7,
4664 [NEON_2RM_VNEG] = 0x7,
4665 [NEON_2RM_VCGT0_F] = 0x4,
4666 [NEON_2RM_VCGE0_F] = 0x4,
4667 [NEON_2RM_VCEQ0_F] = 0x4,
4668 [NEON_2RM_VCLE0_F] = 0x4,
4669 [NEON_2RM_VCLT0_F] = 0x4,
4670 [NEON_2RM_VABS_F] = 0x4,
4671 [NEON_2RM_VNEG_F] = 0x4,
4672 [NEON_2RM_VSWP] = 0x1,
4673 [NEON_2RM_VTRN] = 0x7,
4674 [NEON_2RM_VUZP] = 0x7,
4675 [NEON_2RM_VZIP] = 0x7,
4676 [NEON_2RM_VMOVN] = 0x7,
4677 [NEON_2RM_VQMOVN] = 0x7,
4678 [NEON_2RM_VSHLL] = 0x7,
4679 [NEON_2RM_VCVT_F16_F32] = 0x2,
4680 [NEON_2RM_VCVT_F32_F16] = 0x2,
4681 [NEON_2RM_VRECPE] = 0x4,
4682 [NEON_2RM_VRSQRTE] = 0x4,
4683 [NEON_2RM_VRECPE_F] = 0x4,
4684 [NEON_2RM_VRSQRTE_F] = 0x4,
4685 [NEON_2RM_VCVT_FS] = 0x4,
4686 [NEON_2RM_VCVT_FU] = 0x4,
4687 [NEON_2RM_VCVT_SF] = 0x4,
4688 [NEON_2RM_VCVT_UF] = 0x4,
4691 /* Translate a NEON data processing instruction. Return nonzero if the
4692 instruction is invalid.
4693 We process data in a mixture of 32-bit and 64-bit chunks.
4694 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4696 static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4698 int op;
4699 int q;
4700 int rd, rn, rm;
4701 int size;
4702 int shift;
4703 int pass;
4704 int count;
4705 int pairwise;
4706 int u;
4707 uint32_t imm, mask;
4708 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
4709 TCGv_i64 tmp64;
4711 if (!s->vfp_enabled)
4712 return 1;
4713 q = (insn & (1 << 6)) != 0;
4714 u = (insn >> 24) & 1;
4715 VFP_DREG_D(rd, insn);
4716 VFP_DREG_N(rn, insn);
4717 VFP_DREG_M(rm, insn);
4718 size = (insn >> 20) & 3;
4719 if ((insn & (1 << 23)) == 0) {
4720 /* Three register same length. */
4721 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4722 /* Catch invalid op and bad size combinations: UNDEF */
4723 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4724 return 1;
4726 /* All insns of this form UNDEF for either this condition or the
4727 * superset of cases "Q==1"; we catch the latter later.
4729 if (q && ((rd | rn | rm) & 1)) {
4730 return 1;
4732 if (size == 3 && op != NEON_3R_LOGIC) {
4733 /* 64-bit element instructions. */
4734 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4735 neon_load_reg64(cpu_V0, rn + pass);
4736 neon_load_reg64(cpu_V1, rm + pass);
4737 switch (op) {
4738 case NEON_3R_VQADD:
4739 if (u) {
4740 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4741 cpu_V0, cpu_V1);
4742 } else {
4743 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4744 cpu_V0, cpu_V1);
4746 break;
4747 case NEON_3R_VQSUB:
4748 if (u) {
4749 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4750 cpu_V0, cpu_V1);
4751 } else {
4752 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4753 cpu_V0, cpu_V1);
4755 break;
4756 case NEON_3R_VSHL:
4757 if (u) {
4758 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4759 } else {
4760 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4762 break;
4763 case NEON_3R_VQSHL:
4764 if (u) {
4765 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4766 cpu_V1, cpu_V0);
4767 } else {
4768 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4769 cpu_V1, cpu_V0);
4771 break;
4772 case NEON_3R_VRSHL:
4773 if (u) {
4774 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4775 } else {
4776 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4778 break;
4779 case NEON_3R_VQRSHL:
4780 if (u) {
4781 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4782 cpu_V1, cpu_V0);
4783 } else {
4784 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4785 cpu_V1, cpu_V0);
4787 break;
4788 case NEON_3R_VADD_VSUB:
4789 if (u) {
4790 tcg_gen_sub_i64(CPU_V001);
4791 } else {
4792 tcg_gen_add_i64(CPU_V001);
4794 break;
4795 default:
4796 abort();
4798 neon_store_reg64(cpu_V0, rd + pass);
4800 return 0;
4802 pairwise = 0;
4803 switch (op) {
4804 case NEON_3R_VSHL:
4805 case NEON_3R_VQSHL:
4806 case NEON_3R_VRSHL:
4807 case NEON_3R_VQRSHL:
4809 int rtmp;
4810 /* Shift instruction operands are reversed. */
4811 rtmp = rn;
4812 rn = rm;
4813 rm = rtmp;
4815 break;
4816 case NEON_3R_VPADD:
4817 if (u) {
4818 return 1;
4820 /* Fall through */
4821 case NEON_3R_VPMAX:
4822 case NEON_3R_VPMIN:
4823 pairwise = 1;
4824 break;
4825 case NEON_3R_FLOAT_ARITH:
4826 pairwise = (u && size < 2); /* if VPADD (float) */
4827 break;
4828 case NEON_3R_FLOAT_MINMAX:
4829 pairwise = u; /* if VPMIN/VPMAX (float) */
4830 break;
4831 case NEON_3R_FLOAT_CMP:
4832 if (!u && size) {
4833 /* no encoding for U=0 C=1x */
4834 return 1;
4836 break;
4837 case NEON_3R_FLOAT_ACMP:
4838 if (!u) {
4839 return 1;
4841 break;
4842 case NEON_3R_FLOAT_MISC:
4843 /* VMAXNM/VMINNM in ARMv8 */
4844 if (u && !arm_feature(env, ARM_FEATURE_V8)) {
4845 return 1;
4847 break;
4848 case NEON_3R_VMUL:
4849 if (u && (size != 0)) {
4850 /* UNDEF on invalid size for polynomial subcase */
4851 return 1;
4853 break;
4854 case NEON_3R_VFM:
4855 if (!arm_feature(env, ARM_FEATURE_VFP4) || u) {
4856 return 1;
4858 break;
4859 default:
4860 break;
4863 if (pairwise && q) {
4864 /* All the pairwise insns UNDEF if Q is set */
4865 return 1;
4868 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4870 if (pairwise) {
4871 /* Pairwise. */
4872 if (pass < 1) {
4873 tmp = neon_load_reg(rn, 0);
4874 tmp2 = neon_load_reg(rn, 1);
4875 } else {
4876 tmp = neon_load_reg(rm, 0);
4877 tmp2 = neon_load_reg(rm, 1);
4879 } else {
4880 /* Elementwise. */
4881 tmp = neon_load_reg(rn, pass);
4882 tmp2 = neon_load_reg(rm, pass);
4884 switch (op) {
4885 case NEON_3R_VHADD:
4886 GEN_NEON_INTEGER_OP(hadd);
4887 break;
4888 case NEON_3R_VQADD:
4889 GEN_NEON_INTEGER_OP_ENV(qadd);
4890 break;
4891 case NEON_3R_VRHADD:
4892 GEN_NEON_INTEGER_OP(rhadd);
4893 break;
4894 case NEON_3R_LOGIC: /* Logic ops. */
4895 switch ((u << 2) | size) {
4896 case 0: /* VAND */
4897 tcg_gen_and_i32(tmp, tmp, tmp2);
4898 break;
4899 case 1: /* BIC */
4900 tcg_gen_andc_i32(tmp, tmp, tmp2);
4901 break;
4902 case 2: /* VORR */
4903 tcg_gen_or_i32(tmp, tmp, tmp2);
4904 break;
4905 case 3: /* VORN */
4906 tcg_gen_orc_i32(tmp, tmp, tmp2);
4907 break;
4908 case 4: /* VEOR */
4909 tcg_gen_xor_i32(tmp, tmp, tmp2);
4910 break;
4911 case 5: /* VBSL */
4912 tmp3 = neon_load_reg(rd, pass);
4913 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4914 tcg_temp_free_i32(tmp3);
4915 break;
4916 case 6: /* VBIT */
4917 tmp3 = neon_load_reg(rd, pass);
4918 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4919 tcg_temp_free_i32(tmp3);
4920 break;
4921 case 7: /* VBIF */
4922 tmp3 = neon_load_reg(rd, pass);
4923 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4924 tcg_temp_free_i32(tmp3);
4925 break;
4927 break;
4928 case NEON_3R_VHSUB:
4929 GEN_NEON_INTEGER_OP(hsub);
4930 break;
4931 case NEON_3R_VQSUB:
4932 GEN_NEON_INTEGER_OP_ENV(qsub);
4933 break;
4934 case NEON_3R_VCGT:
4935 GEN_NEON_INTEGER_OP(cgt);
4936 break;
4937 case NEON_3R_VCGE:
4938 GEN_NEON_INTEGER_OP(cge);
4939 break;
4940 case NEON_3R_VSHL:
4941 GEN_NEON_INTEGER_OP(shl);
4942 break;
4943 case NEON_3R_VQSHL:
4944 GEN_NEON_INTEGER_OP_ENV(qshl);
4945 break;
4946 case NEON_3R_VRSHL:
4947 GEN_NEON_INTEGER_OP(rshl);
4948 break;
4949 case NEON_3R_VQRSHL:
4950 GEN_NEON_INTEGER_OP_ENV(qrshl);
4951 break;
4952 case NEON_3R_VMAX:
4953 GEN_NEON_INTEGER_OP(max);
4954 break;
4955 case NEON_3R_VMIN:
4956 GEN_NEON_INTEGER_OP(min);
4957 break;
4958 case NEON_3R_VABD:
4959 GEN_NEON_INTEGER_OP(abd);
4960 break;
4961 case NEON_3R_VABA:
4962 GEN_NEON_INTEGER_OP(abd);
4963 tcg_temp_free_i32(tmp2);
4964 tmp2 = neon_load_reg(rd, pass);
4965 gen_neon_add(size, tmp, tmp2);
4966 break;
4967 case NEON_3R_VADD_VSUB:
4968 if (!u) { /* VADD */
4969 gen_neon_add(size, tmp, tmp2);
4970 } else { /* VSUB */
4971 switch (size) {
4972 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4973 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4974 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4975 default: abort();
4978 break;
4979 case NEON_3R_VTST_VCEQ:
4980 if (!u) { /* VTST */
4981 switch (size) {
4982 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4983 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4984 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4985 default: abort();
4987 } else { /* VCEQ */
4988 switch (size) {
4989 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4990 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4991 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4992 default: abort();
4995 break;
4996 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
4997 switch (size) {
4998 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4999 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5000 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5001 default: abort();
5003 tcg_temp_free_i32(tmp2);
5004 tmp2 = neon_load_reg(rd, pass);
5005 if (u) { /* VMLS */
5006 gen_neon_rsb(size, tmp, tmp2);
5007 } else { /* VMLA */
5008 gen_neon_add(size, tmp, tmp2);
5010 break;
5011 case NEON_3R_VMUL:
5012 if (u) { /* polynomial */
5013 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
5014 } else { /* Integer */
5015 switch (size) {
5016 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5017 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5018 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5019 default: abort();
5022 break;
5023 case NEON_3R_VPMAX:
5024 GEN_NEON_INTEGER_OP(pmax);
5025 break;
5026 case NEON_3R_VPMIN:
5027 GEN_NEON_INTEGER_OP(pmin);
5028 break;
5029 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
5030 if (!u) { /* VQDMULH */
5031 switch (size) {
5032 case 1:
5033 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5034 break;
5035 case 2:
5036 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5037 break;
5038 default: abort();
5040 } else { /* VQRDMULH */
5041 switch (size) {
5042 case 1:
5043 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5044 break;
5045 case 2:
5046 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5047 break;
5048 default: abort();
5051 break;
5052 case NEON_3R_VPADD:
5053 switch (size) {
5054 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5055 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5056 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5057 default: abort();
5059 break;
5060 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
5062 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5063 switch ((u << 2) | size) {
5064 case 0: /* VADD */
5065 case 4: /* VPADD */
5066 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5067 break;
5068 case 2: /* VSUB */
5069 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
5070 break;
5071 case 6: /* VABD */
5072 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
5073 break;
5074 default:
5075 abort();
5077 tcg_temp_free_ptr(fpstatus);
5078 break;
5080 case NEON_3R_FLOAT_MULTIPLY:
5082 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5083 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5084 if (!u) {
5085 tcg_temp_free_i32(tmp2);
5086 tmp2 = neon_load_reg(rd, pass);
5087 if (size == 0) {
5088 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5089 } else {
5090 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5093 tcg_temp_free_ptr(fpstatus);
5094 break;
5096 case NEON_3R_FLOAT_CMP:
5098 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5099 if (!u) {
5100 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5101 } else {
5102 if (size == 0) {
5103 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5104 } else {
5105 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5108 tcg_temp_free_ptr(fpstatus);
5109 break;
5111 case NEON_3R_FLOAT_ACMP:
5113 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5114 if (size == 0) {
5115 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5116 } else {
5117 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5119 tcg_temp_free_ptr(fpstatus);
5120 break;
5122 case NEON_3R_FLOAT_MINMAX:
5124 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5125 if (size == 0) {
5126 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
5127 } else {
5128 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
5130 tcg_temp_free_ptr(fpstatus);
5131 break;
5133 case NEON_3R_FLOAT_MISC:
5134 if (u) {
5135 /* VMAXNM/VMINNM */
5136 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5137 if (size == 0) {
5138 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
5139 } else {
5140 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
5142 tcg_temp_free_ptr(fpstatus);
5143 } else {
5144 if (size == 0) {
5145 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5146 } else {
5147 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5150 break;
5151 case NEON_3R_VFM:
5153 /* VFMA, VFMS: fused multiply-add */
5154 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5155 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5156 if (size) {
5157 /* VFMS */
5158 gen_helper_vfp_negs(tmp, tmp);
5160 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5161 tcg_temp_free_i32(tmp3);
5162 tcg_temp_free_ptr(fpstatus);
5163 break;
5165 default:
5166 abort();
5168 tcg_temp_free_i32(tmp2);
5170 /* Save the result. For elementwise operations we can put it
5171 straight into the destination register. For pairwise operations
5172 we have to be careful to avoid clobbering the source operands. */
5173 if (pairwise && rd == rm) {
5174 neon_store_scratch(pass, tmp);
5175 } else {
5176 neon_store_reg(rd, pass, tmp);
5179 } /* for pass */
5180 if (pairwise && rd == rm) {
5181 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5182 tmp = neon_load_scratch(pass);
5183 neon_store_reg(rd, pass, tmp);
5186 /* End of 3 register same size operations. */
5187 } else if (insn & (1 << 4)) {
5188 if ((insn & 0x00380080) != 0) {
5189 /* Two registers and shift. */
5190 op = (insn >> 8) & 0xf;
5191 if (insn & (1 << 7)) {
5192 /* 64-bit shift. */
5193 if (op > 7) {
5194 return 1;
5196 size = 3;
5197 } else {
5198 size = 2;
5199 while ((insn & (1 << (size + 19))) == 0)
5200 size--;
5202 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5203 /* To avoid excessive duplication of ops we implement shift
5204 by immediate using the variable shift operations. */
5205 if (op < 8) {
5206 /* Shift by immediate:
5207 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5208 if (q && ((rd | rm) & 1)) {
5209 return 1;
5211 if (!u && (op == 4 || op == 6)) {
5212 return 1;
5214 /* Right shifts are encoded as N - shift, where N is the
5215 element size in bits. */
5216 if (op <= 4)
5217 shift = shift - (1 << (size + 3));
5218 if (size == 3) {
5219 count = q + 1;
5220 } else {
5221 count = q ? 4: 2;
5223 switch (size) {
5224 case 0:
5225 imm = (uint8_t) shift;
5226 imm |= imm << 8;
5227 imm |= imm << 16;
5228 break;
5229 case 1:
5230 imm = (uint16_t) shift;
5231 imm |= imm << 16;
5232 break;
5233 case 2:
5234 case 3:
5235 imm = shift;
5236 break;
5237 default:
5238 abort();
5241 for (pass = 0; pass < count; pass++) {
5242 if (size == 3) {
5243 neon_load_reg64(cpu_V0, rm + pass);
5244 tcg_gen_movi_i64(cpu_V1, imm);
5245 switch (op) {
5246 case 0: /* VSHR */
5247 case 1: /* VSRA */
5248 if (u)
5249 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5250 else
5251 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5252 break;
5253 case 2: /* VRSHR */
5254 case 3: /* VRSRA */
5255 if (u)
5256 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5257 else
5258 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5259 break;
5260 case 4: /* VSRI */
5261 case 5: /* VSHL, VSLI */
5262 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5263 break;
5264 case 6: /* VQSHLU */
5265 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5266 cpu_V0, cpu_V1);
5267 break;
5268 case 7: /* VQSHL */
5269 if (u) {
5270 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5271 cpu_V0, cpu_V1);
5272 } else {
5273 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5274 cpu_V0, cpu_V1);
5276 break;
5278 if (op == 1 || op == 3) {
5279 /* Accumulate. */
5280 neon_load_reg64(cpu_V1, rd + pass);
5281 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5282 } else if (op == 4 || (op == 5 && u)) {
5283 /* Insert */
5284 neon_load_reg64(cpu_V1, rd + pass);
5285 uint64_t mask;
5286 if (shift < -63 || shift > 63) {
5287 mask = 0;
5288 } else {
5289 if (op == 4) {
5290 mask = 0xffffffffffffffffull >> -shift;
5291 } else {
5292 mask = 0xffffffffffffffffull << shift;
5295 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5296 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5298 neon_store_reg64(cpu_V0, rd + pass);
5299 } else { /* size < 3 */
5300 /* Operands in T0 and T1. */
5301 tmp = neon_load_reg(rm, pass);
5302 tmp2 = tcg_temp_new_i32();
5303 tcg_gen_movi_i32(tmp2, imm);
5304 switch (op) {
5305 case 0: /* VSHR */
5306 case 1: /* VSRA */
5307 GEN_NEON_INTEGER_OP(shl);
5308 break;
5309 case 2: /* VRSHR */
5310 case 3: /* VRSRA */
5311 GEN_NEON_INTEGER_OP(rshl);
5312 break;
5313 case 4: /* VSRI */
5314 case 5: /* VSHL, VSLI */
5315 switch (size) {
5316 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5317 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5318 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5319 default: abort();
5321 break;
5322 case 6: /* VQSHLU */
5323 switch (size) {
5324 case 0:
5325 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5326 tmp, tmp2);
5327 break;
5328 case 1:
5329 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5330 tmp, tmp2);
5331 break;
5332 case 2:
5333 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5334 tmp, tmp2);
5335 break;
5336 default:
5337 abort();
5339 break;
5340 case 7: /* VQSHL */
5341 GEN_NEON_INTEGER_OP_ENV(qshl);
5342 break;
5344 tcg_temp_free_i32(tmp2);
5346 if (op == 1 || op == 3) {
5347 /* Accumulate. */
5348 tmp2 = neon_load_reg(rd, pass);
5349 gen_neon_add(size, tmp, tmp2);
5350 tcg_temp_free_i32(tmp2);
5351 } else if (op == 4 || (op == 5 && u)) {
5352 /* Insert */
5353 switch (size) {
5354 case 0:
5355 if (op == 4)
5356 mask = 0xff >> -shift;
5357 else
5358 mask = (uint8_t)(0xff << shift);
5359 mask |= mask << 8;
5360 mask |= mask << 16;
5361 break;
5362 case 1:
5363 if (op == 4)
5364 mask = 0xffff >> -shift;
5365 else
5366 mask = (uint16_t)(0xffff << shift);
5367 mask |= mask << 16;
5368 break;
5369 case 2:
5370 if (shift < -31 || shift > 31) {
5371 mask = 0;
5372 } else {
5373 if (op == 4)
5374 mask = 0xffffffffu >> -shift;
5375 else
5376 mask = 0xffffffffu << shift;
5378 break;
5379 default:
5380 abort();
5382 tmp2 = neon_load_reg(rd, pass);
5383 tcg_gen_andi_i32(tmp, tmp, mask);
5384 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5385 tcg_gen_or_i32(tmp, tmp, tmp2);
5386 tcg_temp_free_i32(tmp2);
5388 neon_store_reg(rd, pass, tmp);
5390 } /* for pass */
5391 } else if (op < 10) {
5392 /* Shift by immediate and narrow:
5393 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5394 int input_unsigned = (op == 8) ? !u : u;
5395 if (rm & 1) {
5396 return 1;
5398 shift = shift - (1 << (size + 3));
5399 size++;
5400 if (size == 3) {
5401 tmp64 = tcg_const_i64(shift);
5402 neon_load_reg64(cpu_V0, rm);
5403 neon_load_reg64(cpu_V1, rm + 1);
5404 for (pass = 0; pass < 2; pass++) {
5405 TCGv_i64 in;
5406 if (pass == 0) {
5407 in = cpu_V0;
5408 } else {
5409 in = cpu_V1;
5411 if (q) {
5412 if (input_unsigned) {
5413 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5414 } else {
5415 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5417 } else {
5418 if (input_unsigned) {
5419 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5420 } else {
5421 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5424 tmp = tcg_temp_new_i32();
5425 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5426 neon_store_reg(rd, pass, tmp);
5427 } /* for pass */
5428 tcg_temp_free_i64(tmp64);
5429 } else {
5430 if (size == 1) {
5431 imm = (uint16_t)shift;
5432 imm |= imm << 16;
5433 } else {
5434 /* size == 2 */
5435 imm = (uint32_t)shift;
5437 tmp2 = tcg_const_i32(imm);
5438 tmp4 = neon_load_reg(rm + 1, 0);
5439 tmp5 = neon_load_reg(rm + 1, 1);
5440 for (pass = 0; pass < 2; pass++) {
5441 if (pass == 0) {
5442 tmp = neon_load_reg(rm, 0);
5443 } else {
5444 tmp = tmp4;
5446 gen_neon_shift_narrow(size, tmp, tmp2, q,
5447 input_unsigned);
5448 if (pass == 0) {
5449 tmp3 = neon_load_reg(rm, 1);
5450 } else {
5451 tmp3 = tmp5;
5453 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5454 input_unsigned);
5455 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5456 tcg_temp_free_i32(tmp);
5457 tcg_temp_free_i32(tmp3);
5458 tmp = tcg_temp_new_i32();
5459 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5460 neon_store_reg(rd, pass, tmp);
5461 } /* for pass */
5462 tcg_temp_free_i32(tmp2);
5464 } else if (op == 10) {
5465 /* VSHLL, VMOVL */
5466 if (q || (rd & 1)) {
5467 return 1;
5469 tmp = neon_load_reg(rm, 0);
5470 tmp2 = neon_load_reg(rm, 1);
5471 for (pass = 0; pass < 2; pass++) {
5472 if (pass == 1)
5473 tmp = tmp2;
5475 gen_neon_widen(cpu_V0, tmp, size, u);
5477 if (shift != 0) {
5478 /* The shift is less than the width of the source
5479 type, so we can just shift the whole register. */
5480 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5481 /* Widen the result of shift: we need to clear
5482 * the potential overflow bits resulting from
5483 * left bits of the narrow input appearing as
5484 * right bits of left the neighbour narrow
5485 * input. */
5486 if (size < 2 || !u) {
5487 uint64_t imm64;
5488 if (size == 0) {
5489 imm = (0xffu >> (8 - shift));
5490 imm |= imm << 16;
5491 } else if (size == 1) {
5492 imm = 0xffff >> (16 - shift);
5493 } else {
5494 /* size == 2 */
5495 imm = 0xffffffff >> (32 - shift);
5497 if (size < 2) {
5498 imm64 = imm | (((uint64_t)imm) << 32);
5499 } else {
5500 imm64 = imm;
5502 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5505 neon_store_reg64(cpu_V0, rd + pass);
5507 } else if (op >= 14) {
5508 /* VCVT fixed-point. */
5509 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5510 return 1;
5512 /* We have already masked out the must-be-1 top bit of imm6,
5513 * hence this 32-shift where the ARM ARM has 64-imm6.
5515 shift = 32 - shift;
5516 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5517 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5518 if (!(op & 1)) {
5519 if (u)
5520 gen_vfp_ulto(0, shift, 1);
5521 else
5522 gen_vfp_slto(0, shift, 1);
5523 } else {
5524 if (u)
5525 gen_vfp_toul(0, shift, 1);
5526 else
5527 gen_vfp_tosl(0, shift, 1);
5529 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5531 } else {
5532 return 1;
5534 } else { /* (insn & 0x00380080) == 0 */
5535 int invert;
5536 if (q && (rd & 1)) {
5537 return 1;
5540 op = (insn >> 8) & 0xf;
5541 /* One register and immediate. */
5542 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5543 invert = (insn & (1 << 5)) != 0;
5544 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5545 * We choose to not special-case this and will behave as if a
5546 * valid constant encoding of 0 had been given.
5548 switch (op) {
5549 case 0: case 1:
5550 /* no-op */
5551 break;
5552 case 2: case 3:
5553 imm <<= 8;
5554 break;
5555 case 4: case 5:
5556 imm <<= 16;
5557 break;
5558 case 6: case 7:
5559 imm <<= 24;
5560 break;
5561 case 8: case 9:
5562 imm |= imm << 16;
5563 break;
5564 case 10: case 11:
5565 imm = (imm << 8) | (imm << 24);
5566 break;
5567 case 12:
5568 imm = (imm << 8) | 0xff;
5569 break;
5570 case 13:
5571 imm = (imm << 16) | 0xffff;
5572 break;
5573 case 14:
5574 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5575 if (invert)
5576 imm = ~imm;
5577 break;
5578 case 15:
5579 if (invert) {
5580 return 1;
5582 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5583 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5584 break;
5586 if (invert)
5587 imm = ~imm;
5589 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5590 if (op & 1 && op < 12) {
5591 tmp = neon_load_reg(rd, pass);
5592 if (invert) {
5593 /* The immediate value has already been inverted, so
5594 BIC becomes AND. */
5595 tcg_gen_andi_i32(tmp, tmp, imm);
5596 } else {
5597 tcg_gen_ori_i32(tmp, tmp, imm);
5599 } else {
5600 /* VMOV, VMVN. */
5601 tmp = tcg_temp_new_i32();
5602 if (op == 14 && invert) {
5603 int n;
5604 uint32_t val;
5605 val = 0;
5606 for (n = 0; n < 4; n++) {
5607 if (imm & (1 << (n + (pass & 1) * 4)))
5608 val |= 0xff << (n * 8);
5610 tcg_gen_movi_i32(tmp, val);
5611 } else {
5612 tcg_gen_movi_i32(tmp, imm);
5615 neon_store_reg(rd, pass, tmp);
5618 } else { /* (insn & 0x00800010 == 0x00800000) */
5619 if (size != 3) {
5620 op = (insn >> 8) & 0xf;
5621 if ((insn & (1 << 6)) == 0) {
5622 /* Three registers of different lengths. */
5623 int src1_wide;
5624 int src2_wide;
5625 int prewiden;
5626 /* undefreq: bit 0 : UNDEF if size != 0
5627 * bit 1 : UNDEF if size == 0
5628 * bit 2 : UNDEF if U == 1
5629 * Note that [1:0] set implies 'always UNDEF'
5631 int undefreq;
5632 /* prewiden, src1_wide, src2_wide, undefreq */
5633 static const int neon_3reg_wide[16][4] = {
5634 {1, 0, 0, 0}, /* VADDL */
5635 {1, 1, 0, 0}, /* VADDW */
5636 {1, 0, 0, 0}, /* VSUBL */
5637 {1, 1, 0, 0}, /* VSUBW */
5638 {0, 1, 1, 0}, /* VADDHN */
5639 {0, 0, 0, 0}, /* VABAL */
5640 {0, 1, 1, 0}, /* VSUBHN */
5641 {0, 0, 0, 0}, /* VABDL */
5642 {0, 0, 0, 0}, /* VMLAL */
5643 {0, 0, 0, 6}, /* VQDMLAL */
5644 {0, 0, 0, 0}, /* VMLSL */
5645 {0, 0, 0, 6}, /* VQDMLSL */
5646 {0, 0, 0, 0}, /* Integer VMULL */
5647 {0, 0, 0, 2}, /* VQDMULL */
5648 {0, 0, 0, 5}, /* Polynomial VMULL */
5649 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5652 prewiden = neon_3reg_wide[op][0];
5653 src1_wide = neon_3reg_wide[op][1];
5654 src2_wide = neon_3reg_wide[op][2];
5655 undefreq = neon_3reg_wide[op][3];
5657 if (((undefreq & 1) && (size != 0)) ||
5658 ((undefreq & 2) && (size == 0)) ||
5659 ((undefreq & 4) && u)) {
5660 return 1;
5662 if ((src1_wide && (rn & 1)) ||
5663 (src2_wide && (rm & 1)) ||
5664 (!src2_wide && (rd & 1))) {
5665 return 1;
5668 /* Avoid overlapping operands. Wide source operands are
5669 always aligned so will never overlap with wide
5670 destinations in problematic ways. */
5671 if (rd == rm && !src2_wide) {
5672 tmp = neon_load_reg(rm, 1);
5673 neon_store_scratch(2, tmp);
5674 } else if (rd == rn && !src1_wide) {
5675 tmp = neon_load_reg(rn, 1);
5676 neon_store_scratch(2, tmp);
5678 TCGV_UNUSED_I32(tmp3);
5679 for (pass = 0; pass < 2; pass++) {
5680 if (src1_wide) {
5681 neon_load_reg64(cpu_V0, rn + pass);
5682 TCGV_UNUSED_I32(tmp);
5683 } else {
5684 if (pass == 1 && rd == rn) {
5685 tmp = neon_load_scratch(2);
5686 } else {
5687 tmp = neon_load_reg(rn, pass);
5689 if (prewiden) {
5690 gen_neon_widen(cpu_V0, tmp, size, u);
5693 if (src2_wide) {
5694 neon_load_reg64(cpu_V1, rm + pass);
5695 TCGV_UNUSED_I32(tmp2);
5696 } else {
5697 if (pass == 1 && rd == rm) {
5698 tmp2 = neon_load_scratch(2);
5699 } else {
5700 tmp2 = neon_load_reg(rm, pass);
5702 if (prewiden) {
5703 gen_neon_widen(cpu_V1, tmp2, size, u);
5706 switch (op) {
5707 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5708 gen_neon_addl(size);
5709 break;
5710 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5711 gen_neon_subl(size);
5712 break;
5713 case 5: case 7: /* VABAL, VABDL */
5714 switch ((size << 1) | u) {
5715 case 0:
5716 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5717 break;
5718 case 1:
5719 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5720 break;
5721 case 2:
5722 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5723 break;
5724 case 3:
5725 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5726 break;
5727 case 4:
5728 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5729 break;
5730 case 5:
5731 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5732 break;
5733 default: abort();
5735 tcg_temp_free_i32(tmp2);
5736 tcg_temp_free_i32(tmp);
5737 break;
5738 case 8: case 9: case 10: case 11: case 12: case 13:
5739 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5740 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5741 break;
5742 case 14: /* Polynomial VMULL */
5743 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5744 tcg_temp_free_i32(tmp2);
5745 tcg_temp_free_i32(tmp);
5746 break;
5747 default: /* 15 is RESERVED: caught earlier */
5748 abort();
5750 if (op == 13) {
5751 /* VQDMULL */
5752 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5753 neon_store_reg64(cpu_V0, rd + pass);
5754 } else if (op == 5 || (op >= 8 && op <= 11)) {
5755 /* Accumulate. */
5756 neon_load_reg64(cpu_V1, rd + pass);
5757 switch (op) {
5758 case 10: /* VMLSL */
5759 gen_neon_negl(cpu_V0, size);
5760 /* Fall through */
5761 case 5: case 8: /* VABAL, VMLAL */
5762 gen_neon_addl(size);
5763 break;
5764 case 9: case 11: /* VQDMLAL, VQDMLSL */
5765 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5766 if (op == 11) {
5767 gen_neon_negl(cpu_V0, size);
5769 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5770 break;
5771 default:
5772 abort();
5774 neon_store_reg64(cpu_V0, rd + pass);
5775 } else if (op == 4 || op == 6) {
5776 /* Narrowing operation. */
5777 tmp = tcg_temp_new_i32();
5778 if (!u) {
5779 switch (size) {
5780 case 0:
5781 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5782 break;
5783 case 1:
5784 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5785 break;
5786 case 2:
5787 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5788 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5789 break;
5790 default: abort();
5792 } else {
5793 switch (size) {
5794 case 0:
5795 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5796 break;
5797 case 1:
5798 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5799 break;
5800 case 2:
5801 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5802 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5803 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5804 break;
5805 default: abort();
5808 if (pass == 0) {
5809 tmp3 = tmp;
5810 } else {
5811 neon_store_reg(rd, 0, tmp3);
5812 neon_store_reg(rd, 1, tmp);
5814 } else {
5815 /* Write back the result. */
5816 neon_store_reg64(cpu_V0, rd + pass);
5819 } else {
5820 /* Two registers and a scalar. NB that for ops of this form
5821 * the ARM ARM labels bit 24 as Q, but it is in our variable
5822 * 'u', not 'q'.
5824 if (size == 0) {
5825 return 1;
5827 switch (op) {
5828 case 1: /* Float VMLA scalar */
5829 case 5: /* Floating point VMLS scalar */
5830 case 9: /* Floating point VMUL scalar */
5831 if (size == 1) {
5832 return 1;
5834 /* fall through */
5835 case 0: /* Integer VMLA scalar */
5836 case 4: /* Integer VMLS scalar */
5837 case 8: /* Integer VMUL scalar */
5838 case 12: /* VQDMULH scalar */
5839 case 13: /* VQRDMULH scalar */
5840 if (u && ((rd | rn) & 1)) {
5841 return 1;
5843 tmp = neon_get_scalar(size, rm);
5844 neon_store_scratch(0, tmp);
5845 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5846 tmp = neon_load_scratch(0);
5847 tmp2 = neon_load_reg(rn, pass);
5848 if (op == 12) {
5849 if (size == 1) {
5850 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5851 } else {
5852 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5854 } else if (op == 13) {
5855 if (size == 1) {
5856 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5857 } else {
5858 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5860 } else if (op & 1) {
5861 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5862 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5863 tcg_temp_free_ptr(fpstatus);
5864 } else {
5865 switch (size) {
5866 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5867 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5868 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5869 default: abort();
5872 tcg_temp_free_i32(tmp2);
5873 if (op < 8) {
5874 /* Accumulate. */
5875 tmp2 = neon_load_reg(rd, pass);
5876 switch (op) {
5877 case 0:
5878 gen_neon_add(size, tmp, tmp2);
5879 break;
5880 case 1:
5882 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5883 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5884 tcg_temp_free_ptr(fpstatus);
5885 break;
5887 case 4:
5888 gen_neon_rsb(size, tmp, tmp2);
5889 break;
5890 case 5:
5892 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5893 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5894 tcg_temp_free_ptr(fpstatus);
5895 break;
5897 default:
5898 abort();
5900 tcg_temp_free_i32(tmp2);
5902 neon_store_reg(rd, pass, tmp);
5904 break;
5905 case 3: /* VQDMLAL scalar */
5906 case 7: /* VQDMLSL scalar */
5907 case 11: /* VQDMULL scalar */
5908 if (u == 1) {
5909 return 1;
5911 /* fall through */
5912 case 2: /* VMLAL sclar */
5913 case 6: /* VMLSL scalar */
5914 case 10: /* VMULL scalar */
5915 if (rd & 1) {
5916 return 1;
5918 tmp2 = neon_get_scalar(size, rm);
5919 /* We need a copy of tmp2 because gen_neon_mull
5920 * deletes it during pass 0. */
5921 tmp4 = tcg_temp_new_i32();
5922 tcg_gen_mov_i32(tmp4, tmp2);
5923 tmp3 = neon_load_reg(rn, 1);
5925 for (pass = 0; pass < 2; pass++) {
5926 if (pass == 0) {
5927 tmp = neon_load_reg(rn, 0);
5928 } else {
5929 tmp = tmp3;
5930 tmp2 = tmp4;
5932 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5933 if (op != 11) {
5934 neon_load_reg64(cpu_V1, rd + pass);
5936 switch (op) {
5937 case 6:
5938 gen_neon_negl(cpu_V0, size);
5939 /* Fall through */
5940 case 2:
5941 gen_neon_addl(size);
5942 break;
5943 case 3: case 7:
5944 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5945 if (op == 7) {
5946 gen_neon_negl(cpu_V0, size);
5948 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5949 break;
5950 case 10:
5951 /* no-op */
5952 break;
5953 case 11:
5954 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5955 break;
5956 default:
5957 abort();
5959 neon_store_reg64(cpu_V0, rd + pass);
5963 break;
5964 default: /* 14 and 15 are RESERVED */
5965 return 1;
5968 } else { /* size == 3 */
5969 if (!u) {
5970 /* Extract. */
5971 imm = (insn >> 8) & 0xf;
5973 if (imm > 7 && !q)
5974 return 1;
5976 if (q && ((rd | rn | rm) & 1)) {
5977 return 1;
5980 if (imm == 0) {
5981 neon_load_reg64(cpu_V0, rn);
5982 if (q) {
5983 neon_load_reg64(cpu_V1, rn + 1);
5985 } else if (imm == 8) {
5986 neon_load_reg64(cpu_V0, rn + 1);
5987 if (q) {
5988 neon_load_reg64(cpu_V1, rm);
5990 } else if (q) {
5991 tmp64 = tcg_temp_new_i64();
5992 if (imm < 8) {
5993 neon_load_reg64(cpu_V0, rn);
5994 neon_load_reg64(tmp64, rn + 1);
5995 } else {
5996 neon_load_reg64(cpu_V0, rn + 1);
5997 neon_load_reg64(tmp64, rm);
5999 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
6000 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
6001 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6002 if (imm < 8) {
6003 neon_load_reg64(cpu_V1, rm);
6004 } else {
6005 neon_load_reg64(cpu_V1, rm + 1);
6006 imm -= 8;
6008 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6009 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6010 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
6011 tcg_temp_free_i64(tmp64);
6012 } else {
6013 /* BUGFIX */
6014 neon_load_reg64(cpu_V0, rn);
6015 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
6016 neon_load_reg64(cpu_V1, rm);
6017 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6018 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6020 neon_store_reg64(cpu_V0, rd);
6021 if (q) {
6022 neon_store_reg64(cpu_V1, rd + 1);
6024 } else if ((insn & (1 << 11)) == 0) {
6025 /* Two register misc. */
6026 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6027 size = (insn >> 18) & 3;
6028 /* UNDEF for unknown op values and bad op-size combinations */
6029 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6030 return 1;
6032 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6033 q && ((rm | rd) & 1)) {
6034 return 1;
6036 switch (op) {
6037 case NEON_2RM_VREV64:
6038 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6039 tmp = neon_load_reg(rm, pass * 2);
6040 tmp2 = neon_load_reg(rm, pass * 2 + 1);
6041 switch (size) {
6042 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6043 case 1: gen_swap_half(tmp); break;
6044 case 2: /* no-op */ break;
6045 default: abort();
6047 neon_store_reg(rd, pass * 2 + 1, tmp);
6048 if (size == 2) {
6049 neon_store_reg(rd, pass * 2, tmp2);
6050 } else {
6051 switch (size) {
6052 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6053 case 1: gen_swap_half(tmp2); break;
6054 default: abort();
6056 neon_store_reg(rd, pass * 2, tmp2);
6059 break;
6060 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6061 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
6062 for (pass = 0; pass < q + 1; pass++) {
6063 tmp = neon_load_reg(rm, pass * 2);
6064 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6065 tmp = neon_load_reg(rm, pass * 2 + 1);
6066 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6067 switch (size) {
6068 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6069 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6070 case 2: tcg_gen_add_i64(CPU_V001); break;
6071 default: abort();
6073 if (op >= NEON_2RM_VPADAL) {
6074 /* Accumulate. */
6075 neon_load_reg64(cpu_V1, rd + pass);
6076 gen_neon_addl(size);
6078 neon_store_reg64(cpu_V0, rd + pass);
6080 break;
6081 case NEON_2RM_VTRN:
6082 if (size == 2) {
6083 int n;
6084 for (n = 0; n < (q ? 4 : 2); n += 2) {
6085 tmp = neon_load_reg(rm, n);
6086 tmp2 = neon_load_reg(rd, n + 1);
6087 neon_store_reg(rm, n, tmp2);
6088 neon_store_reg(rd, n + 1, tmp);
6090 } else {
6091 goto elementwise;
6093 break;
6094 case NEON_2RM_VUZP:
6095 if (gen_neon_unzip(rd, rm, size, q)) {
6096 return 1;
6098 break;
6099 case NEON_2RM_VZIP:
6100 if (gen_neon_zip(rd, rm, size, q)) {
6101 return 1;
6103 break;
6104 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6105 /* also VQMOVUN; op field and mnemonics don't line up */
6106 if (rm & 1) {
6107 return 1;
6109 TCGV_UNUSED_I32(tmp2);
6110 for (pass = 0; pass < 2; pass++) {
6111 neon_load_reg64(cpu_V0, rm + pass);
6112 tmp = tcg_temp_new_i32();
6113 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6114 tmp, cpu_V0);
6115 if (pass == 0) {
6116 tmp2 = tmp;
6117 } else {
6118 neon_store_reg(rd, 0, tmp2);
6119 neon_store_reg(rd, 1, tmp);
6122 break;
6123 case NEON_2RM_VSHLL:
6124 if (q || (rd & 1)) {
6125 return 1;
6127 tmp = neon_load_reg(rm, 0);
6128 tmp2 = neon_load_reg(rm, 1);
6129 for (pass = 0; pass < 2; pass++) {
6130 if (pass == 1)
6131 tmp = tmp2;
6132 gen_neon_widen(cpu_V0, tmp, size, 1);
6133 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
6134 neon_store_reg64(cpu_V0, rd + pass);
6136 break;
6137 case NEON_2RM_VCVT_F16_F32:
6138 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6139 q || (rm & 1)) {
6140 return 1;
6142 tmp = tcg_temp_new_i32();
6143 tmp2 = tcg_temp_new_i32();
6144 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
6145 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6146 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
6147 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6148 tcg_gen_shli_i32(tmp2, tmp2, 16);
6149 tcg_gen_or_i32(tmp2, tmp2, tmp);
6150 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
6151 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6152 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6153 neon_store_reg(rd, 0, tmp2);
6154 tmp2 = tcg_temp_new_i32();
6155 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6156 tcg_gen_shli_i32(tmp2, tmp2, 16);
6157 tcg_gen_or_i32(tmp2, tmp2, tmp);
6158 neon_store_reg(rd, 1, tmp2);
6159 tcg_temp_free_i32(tmp);
6160 break;
6161 case NEON_2RM_VCVT_F32_F16:
6162 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6163 q || (rd & 1)) {
6164 return 1;
6166 tmp3 = tcg_temp_new_i32();
6167 tmp = neon_load_reg(rm, 0);
6168 tmp2 = neon_load_reg(rm, 1);
6169 tcg_gen_ext16u_i32(tmp3, tmp);
6170 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6171 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6172 tcg_gen_shri_i32(tmp3, tmp, 16);
6173 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6174 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6175 tcg_temp_free_i32(tmp);
6176 tcg_gen_ext16u_i32(tmp3, tmp2);
6177 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6178 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6179 tcg_gen_shri_i32(tmp3, tmp2, 16);
6180 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6181 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6182 tcg_temp_free_i32(tmp2);
6183 tcg_temp_free_i32(tmp3);
6184 break;
6185 case NEON_2RM_AESE: case NEON_2RM_AESMC:
6186 if (!arm_feature(env, ARM_FEATURE_V8_AES)
6187 || ((rm | rd) & 1)) {
6188 return 1;
6190 tmp = tcg_const_i32(rd);
6191 tmp2 = tcg_const_i32(rm);
6193 /* Bit 6 is the lowest opcode bit; it distinguishes between
6194 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6196 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6198 if (op == NEON_2RM_AESE) {
6199 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6200 } else {
6201 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6203 tcg_temp_free_i32(tmp);
6204 tcg_temp_free_i32(tmp2);
6205 tcg_temp_free_i32(tmp3);
6206 break;
6207 default:
6208 elementwise:
6209 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6210 if (neon_2rm_is_float_op(op)) {
6211 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6212 neon_reg_offset(rm, pass));
6213 TCGV_UNUSED_I32(tmp);
6214 } else {
6215 tmp = neon_load_reg(rm, pass);
6217 switch (op) {
6218 case NEON_2RM_VREV32:
6219 switch (size) {
6220 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6221 case 1: gen_swap_half(tmp); break;
6222 default: abort();
6224 break;
6225 case NEON_2RM_VREV16:
6226 gen_rev16(tmp);
6227 break;
6228 case NEON_2RM_VCLS:
6229 switch (size) {
6230 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6231 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6232 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6233 default: abort();
6235 break;
6236 case NEON_2RM_VCLZ:
6237 switch (size) {
6238 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6239 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6240 case 2: gen_helper_clz(tmp, tmp); break;
6241 default: abort();
6243 break;
6244 case NEON_2RM_VCNT:
6245 gen_helper_neon_cnt_u8(tmp, tmp);
6246 break;
6247 case NEON_2RM_VMVN:
6248 tcg_gen_not_i32(tmp, tmp);
6249 break;
6250 case NEON_2RM_VQABS:
6251 switch (size) {
6252 case 0:
6253 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6254 break;
6255 case 1:
6256 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6257 break;
6258 case 2:
6259 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6260 break;
6261 default: abort();
6263 break;
6264 case NEON_2RM_VQNEG:
6265 switch (size) {
6266 case 0:
6267 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6268 break;
6269 case 1:
6270 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6271 break;
6272 case 2:
6273 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6274 break;
6275 default: abort();
6277 break;
6278 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6279 tmp2 = tcg_const_i32(0);
6280 switch(size) {
6281 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6282 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6283 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6284 default: abort();
6286 tcg_temp_free_i32(tmp2);
6287 if (op == NEON_2RM_VCLE0) {
6288 tcg_gen_not_i32(tmp, tmp);
6290 break;
6291 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6292 tmp2 = tcg_const_i32(0);
6293 switch(size) {
6294 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6295 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6296 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6297 default: abort();
6299 tcg_temp_free_i32(tmp2);
6300 if (op == NEON_2RM_VCLT0) {
6301 tcg_gen_not_i32(tmp, tmp);
6303 break;
6304 case NEON_2RM_VCEQ0:
6305 tmp2 = tcg_const_i32(0);
6306 switch(size) {
6307 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6308 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6309 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6310 default: abort();
6312 tcg_temp_free_i32(tmp2);
6313 break;
6314 case NEON_2RM_VABS:
6315 switch(size) {
6316 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6317 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6318 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6319 default: abort();
6321 break;
6322 case NEON_2RM_VNEG:
6323 tmp2 = tcg_const_i32(0);
6324 gen_neon_rsb(size, tmp, tmp2);
6325 tcg_temp_free_i32(tmp2);
6326 break;
6327 case NEON_2RM_VCGT0_F:
6329 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6330 tmp2 = tcg_const_i32(0);
6331 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6332 tcg_temp_free_i32(tmp2);
6333 tcg_temp_free_ptr(fpstatus);
6334 break;
6336 case NEON_2RM_VCGE0_F:
6338 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6339 tmp2 = tcg_const_i32(0);
6340 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6341 tcg_temp_free_i32(tmp2);
6342 tcg_temp_free_ptr(fpstatus);
6343 break;
6345 case NEON_2RM_VCEQ0_F:
6347 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6348 tmp2 = tcg_const_i32(0);
6349 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6350 tcg_temp_free_i32(tmp2);
6351 tcg_temp_free_ptr(fpstatus);
6352 break;
6354 case NEON_2RM_VCLE0_F:
6356 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6357 tmp2 = tcg_const_i32(0);
6358 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6359 tcg_temp_free_i32(tmp2);
6360 tcg_temp_free_ptr(fpstatus);
6361 break;
6363 case NEON_2RM_VCLT0_F:
6365 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6366 tmp2 = tcg_const_i32(0);
6367 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6368 tcg_temp_free_i32(tmp2);
6369 tcg_temp_free_ptr(fpstatus);
6370 break;
6372 case NEON_2RM_VABS_F:
6373 gen_vfp_abs(0);
6374 break;
6375 case NEON_2RM_VNEG_F:
6376 gen_vfp_neg(0);
6377 break;
6378 case NEON_2RM_VSWP:
6379 tmp2 = neon_load_reg(rd, pass);
6380 neon_store_reg(rm, pass, tmp2);
6381 break;
6382 case NEON_2RM_VTRN:
6383 tmp2 = neon_load_reg(rd, pass);
6384 switch (size) {
6385 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6386 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6387 default: abort();
6389 neon_store_reg(rm, pass, tmp2);
6390 break;
6391 case NEON_2RM_VRECPE:
6392 gen_helper_recpe_u32(tmp, tmp, cpu_env);
6393 break;
6394 case NEON_2RM_VRSQRTE:
6395 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
6396 break;
6397 case NEON_2RM_VRECPE_F:
6398 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
6399 break;
6400 case NEON_2RM_VRSQRTE_F:
6401 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
6402 break;
6403 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6404 gen_vfp_sito(0, 1);
6405 break;
6406 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6407 gen_vfp_uito(0, 1);
6408 break;
6409 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6410 gen_vfp_tosiz(0, 1);
6411 break;
6412 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6413 gen_vfp_touiz(0, 1);
6414 break;
6415 default:
6416 /* Reserved op values were caught by the
6417 * neon_2rm_sizes[] check earlier.
6419 abort();
6421 if (neon_2rm_is_float_op(op)) {
6422 tcg_gen_st_f32(cpu_F0s, cpu_env,
6423 neon_reg_offset(rd, pass));
6424 } else {
6425 neon_store_reg(rd, pass, tmp);
6428 break;
6430 } else if ((insn & (1 << 10)) == 0) {
6431 /* VTBL, VTBX. */
6432 int n = ((insn >> 8) & 3) + 1;
6433 if ((rn + n) > 32) {
6434 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6435 * helper function running off the end of the register file.
6437 return 1;
6439 n <<= 3;
6440 if (insn & (1 << 6)) {
6441 tmp = neon_load_reg(rd, 0);
6442 } else {
6443 tmp = tcg_temp_new_i32();
6444 tcg_gen_movi_i32(tmp, 0);
6446 tmp2 = neon_load_reg(rm, 0);
6447 tmp4 = tcg_const_i32(rn);
6448 tmp5 = tcg_const_i32(n);
6449 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
6450 tcg_temp_free_i32(tmp);
6451 if (insn & (1 << 6)) {
6452 tmp = neon_load_reg(rd, 1);
6453 } else {
6454 tmp = tcg_temp_new_i32();
6455 tcg_gen_movi_i32(tmp, 0);
6457 tmp3 = neon_load_reg(rm, 1);
6458 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
6459 tcg_temp_free_i32(tmp5);
6460 tcg_temp_free_i32(tmp4);
6461 neon_store_reg(rd, 0, tmp2);
6462 neon_store_reg(rd, 1, tmp3);
6463 tcg_temp_free_i32(tmp);
6464 } else if ((insn & 0x380) == 0) {
6465 /* VDUP */
6466 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6467 return 1;
6469 if (insn & (1 << 19)) {
6470 tmp = neon_load_reg(rm, 1);
6471 } else {
6472 tmp = neon_load_reg(rm, 0);
6474 if (insn & (1 << 16)) {
6475 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6476 } else if (insn & (1 << 17)) {
6477 if ((insn >> 18) & 1)
6478 gen_neon_dup_high16(tmp);
6479 else
6480 gen_neon_dup_low16(tmp);
6482 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6483 tmp2 = tcg_temp_new_i32();
6484 tcg_gen_mov_i32(tmp2, tmp);
6485 neon_store_reg(rd, pass, tmp2);
6487 tcg_temp_free_i32(tmp);
6488 } else {
6489 return 1;
6493 return 0;
6496 static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
6498 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
6499 const ARMCPRegInfo *ri;
6501 cpnum = (insn >> 8) & 0xf;
6502 if (arm_feature(env, ARM_FEATURE_XSCALE)
6503 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6504 return 1;
6506 /* First check for coprocessor space used for actual instructions */
6507 switch (cpnum) {
6508 case 0:
6509 case 1:
6510 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6511 return disas_iwmmxt_insn(env, s, insn);
6512 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6513 return disas_dsp_insn(env, s, insn);
6515 return 1;
6516 default:
6517 break;
6520 /* Otherwise treat as a generic register access */
6521 is64 = (insn & (1 << 25)) == 0;
6522 if (!is64 && ((insn & (1 << 4)) == 0)) {
6523 /* cdp */
6524 return 1;
6527 crm = insn & 0xf;
6528 if (is64) {
6529 crn = 0;
6530 opc1 = (insn >> 4) & 0xf;
6531 opc2 = 0;
6532 rt2 = (insn >> 16) & 0xf;
6533 } else {
6534 crn = (insn >> 16) & 0xf;
6535 opc1 = (insn >> 21) & 7;
6536 opc2 = (insn >> 5) & 7;
6537 rt2 = 0;
6539 isread = (insn >> 20) & 1;
6540 rt = (insn >> 12) & 0xf;
6542 ri = get_arm_cp_reginfo(s->cp_regs,
6543 ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
6544 if (ri) {
6545 /* Check access permissions */
6546 if (!cp_access_ok(s->current_pl, ri, isread)) {
6547 return 1;
6550 /* Handle special cases first */
6551 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
6552 case ARM_CP_NOP:
6553 return 0;
6554 case ARM_CP_WFI:
6555 if (isread) {
6556 return 1;
6558 gen_set_pc_im(s, s->pc);
6559 s->is_jmp = DISAS_WFI;
6560 return 0;
6561 default:
6562 break;
6565 if (use_icount && (ri->type & ARM_CP_IO)) {
6566 gen_io_start();
6569 if (isread) {
6570 /* Read */
6571 if (is64) {
6572 TCGv_i64 tmp64;
6573 TCGv_i32 tmp;
6574 if (ri->type & ARM_CP_CONST) {
6575 tmp64 = tcg_const_i64(ri->resetvalue);
6576 } else if (ri->readfn) {
6577 TCGv_ptr tmpptr;
6578 gen_set_pc_im(s, s->pc);
6579 tmp64 = tcg_temp_new_i64();
6580 tmpptr = tcg_const_ptr(ri);
6581 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
6582 tcg_temp_free_ptr(tmpptr);
6583 } else {
6584 tmp64 = tcg_temp_new_i64();
6585 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
6587 tmp = tcg_temp_new_i32();
6588 tcg_gen_trunc_i64_i32(tmp, tmp64);
6589 store_reg(s, rt, tmp);
6590 tcg_gen_shri_i64(tmp64, tmp64, 32);
6591 tmp = tcg_temp_new_i32();
6592 tcg_gen_trunc_i64_i32(tmp, tmp64);
6593 tcg_temp_free_i64(tmp64);
6594 store_reg(s, rt2, tmp);
6595 } else {
6596 TCGv_i32 tmp;
6597 if (ri->type & ARM_CP_CONST) {
6598 tmp = tcg_const_i32(ri->resetvalue);
6599 } else if (ri->readfn) {
6600 TCGv_ptr tmpptr;
6601 gen_set_pc_im(s, s->pc);
6602 tmp = tcg_temp_new_i32();
6603 tmpptr = tcg_const_ptr(ri);
6604 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
6605 tcg_temp_free_ptr(tmpptr);
6606 } else {
6607 tmp = load_cpu_offset(ri->fieldoffset);
6609 if (rt == 15) {
6610 /* Destination register of r15 for 32 bit loads sets
6611 * the condition codes from the high 4 bits of the value
6613 gen_set_nzcv(tmp);
6614 tcg_temp_free_i32(tmp);
6615 } else {
6616 store_reg(s, rt, tmp);
6619 } else {
6620 /* Write */
6621 if (ri->type & ARM_CP_CONST) {
6622 /* If not forbidden by access permissions, treat as WI */
6623 return 0;
6626 if (is64) {
6627 TCGv_i32 tmplo, tmphi;
6628 TCGv_i64 tmp64 = tcg_temp_new_i64();
6629 tmplo = load_reg(s, rt);
6630 tmphi = load_reg(s, rt2);
6631 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
6632 tcg_temp_free_i32(tmplo);
6633 tcg_temp_free_i32(tmphi);
6634 if (ri->writefn) {
6635 TCGv_ptr tmpptr = tcg_const_ptr(ri);
6636 gen_set_pc_im(s, s->pc);
6637 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
6638 tcg_temp_free_ptr(tmpptr);
6639 } else {
6640 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
6642 tcg_temp_free_i64(tmp64);
6643 } else {
6644 if (ri->writefn) {
6645 TCGv_i32 tmp;
6646 TCGv_ptr tmpptr;
6647 gen_set_pc_im(s, s->pc);
6648 tmp = load_reg(s, rt);
6649 tmpptr = tcg_const_ptr(ri);
6650 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
6651 tcg_temp_free_ptr(tmpptr);
6652 tcg_temp_free_i32(tmp);
6653 } else {
6654 TCGv_i32 tmp = load_reg(s, rt);
6655 store_cpu_offset(tmp, ri->fieldoffset);
6660 if (use_icount && (ri->type & ARM_CP_IO)) {
6661 /* I/O operations must end the TB here (whether read or write) */
6662 gen_io_end();
6663 gen_lookup_tb(s);
6664 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
6665 /* We default to ending the TB on a coprocessor register write,
6666 * but allow this to be suppressed by the register definition
6667 * (usually only necessary to work around guest bugs).
6669 gen_lookup_tb(s);
6672 return 0;
6675 return 1;
6679 /* Store a 64-bit value to a register pair. Clobbers val. */
6680 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6682 TCGv_i32 tmp;
6683 tmp = tcg_temp_new_i32();
6684 tcg_gen_trunc_i64_i32(tmp, val);
6685 store_reg(s, rlow, tmp);
6686 tmp = tcg_temp_new_i32();
6687 tcg_gen_shri_i64(val, val, 32);
6688 tcg_gen_trunc_i64_i32(tmp, val);
6689 store_reg(s, rhigh, tmp);
6692 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6693 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
6695 TCGv_i64 tmp;
6696 TCGv_i32 tmp2;
6698 /* Load value and extend to 64 bits. */
6699 tmp = tcg_temp_new_i64();
6700 tmp2 = load_reg(s, rlow);
6701 tcg_gen_extu_i32_i64(tmp, tmp2);
6702 tcg_temp_free_i32(tmp2);
6703 tcg_gen_add_i64(val, val, tmp);
6704 tcg_temp_free_i64(tmp);
6707 /* load and add a 64-bit value from a register pair. */
6708 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
6710 TCGv_i64 tmp;
6711 TCGv_i32 tmpl;
6712 TCGv_i32 tmph;
6714 /* Load 64-bit value rd:rn. */
6715 tmpl = load_reg(s, rlow);
6716 tmph = load_reg(s, rhigh);
6717 tmp = tcg_temp_new_i64();
6718 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
6719 tcg_temp_free_i32(tmpl);
6720 tcg_temp_free_i32(tmph);
6721 tcg_gen_add_i64(val, val, tmp);
6722 tcg_temp_free_i64(tmp);
6725 /* Set N and Z flags from hi|lo. */
6726 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
6728 tcg_gen_mov_i32(cpu_NF, hi);
6729 tcg_gen_or_i32(cpu_ZF, lo, hi);
6732 /* Load/Store exclusive instructions are implemented by remembering
6733 the value/address loaded, and seeing if these are the same
6734 when the store is performed. This should be sufficient to implement
6735 the architecturally mandated semantics, and avoids having to monitor
6736 regular stores.
6738 In system emulation mode only one CPU will be running at once, so
6739 this sequence is effectively atomic. In user emulation mode we
6740 throw an exception and handle the atomic operation elsewhere. */
6741 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6742 TCGv_i32 addr, int size)
6744 TCGv_i32 tmp = tcg_temp_new_i32();
6746 switch (size) {
6747 case 0:
6748 gen_aa32_ld8u(tmp, addr, IS_USER(s));
6749 break;
6750 case 1:
6751 gen_aa32_ld16u(tmp, addr, IS_USER(s));
6752 break;
6753 case 2:
6754 case 3:
6755 gen_aa32_ld32u(tmp, addr, IS_USER(s));
6756 break;
6757 default:
6758 abort();
6761 if (size == 3) {
6762 TCGv_i32 tmp2 = tcg_temp_new_i32();
6763 TCGv_i32 tmp3 = tcg_temp_new_i32();
6765 tcg_gen_addi_i32(tmp2, addr, 4);
6766 gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
6767 tcg_temp_free_i32(tmp2);
6768 tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
6769 store_reg(s, rt2, tmp3);
6770 } else {
6771 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
6774 store_reg(s, rt, tmp);
6775 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
6778 static void gen_clrex(DisasContext *s)
6780 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
6783 #ifdef CONFIG_USER_ONLY
6784 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6785 TCGv_i32 addr, int size)
6787 tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
6788 tcg_gen_movi_i32(cpu_exclusive_info,
6789 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6790 gen_exception_insn(s, 4, EXCP_STREX);
6792 #else
6793 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6794 TCGv_i32 addr, int size)
6796 TCGv_i32 tmp;
6797 TCGv_i64 val64, extaddr;
6798 int done_label;
6799 int fail_label;
6801 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6802 [addr] = {Rt};
6803 {Rd} = 0;
6804 } else {
6805 {Rd} = 1;
6806 } */
6807 fail_label = gen_new_label();
6808 done_label = gen_new_label();
6809 extaddr = tcg_temp_new_i64();
6810 tcg_gen_extu_i32_i64(extaddr, addr);
6811 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
6812 tcg_temp_free_i64(extaddr);
6814 tmp = tcg_temp_new_i32();
6815 switch (size) {
6816 case 0:
6817 gen_aa32_ld8u(tmp, addr, IS_USER(s));
6818 break;
6819 case 1:
6820 gen_aa32_ld16u(tmp, addr, IS_USER(s));
6821 break;
6822 case 2:
6823 case 3:
6824 gen_aa32_ld32u(tmp, addr, IS_USER(s));
6825 break;
6826 default:
6827 abort();
6830 val64 = tcg_temp_new_i64();
6831 if (size == 3) {
6832 TCGv_i32 tmp2 = tcg_temp_new_i32();
6833 TCGv_i32 tmp3 = tcg_temp_new_i32();
6834 tcg_gen_addi_i32(tmp2, addr, 4);
6835 gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
6836 tcg_temp_free_i32(tmp2);
6837 tcg_gen_concat_i32_i64(val64, tmp, tmp3);
6838 tcg_temp_free_i32(tmp3);
6839 } else {
6840 tcg_gen_extu_i32_i64(val64, tmp);
6842 tcg_temp_free_i32(tmp);
6844 tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
6845 tcg_temp_free_i64(val64);
6847 tmp = load_reg(s, rt);
6848 switch (size) {
6849 case 0:
6850 gen_aa32_st8(tmp, addr, IS_USER(s));
6851 break;
6852 case 1:
6853 gen_aa32_st16(tmp, addr, IS_USER(s));
6854 break;
6855 case 2:
6856 case 3:
6857 gen_aa32_st32(tmp, addr, IS_USER(s));
6858 break;
6859 default:
6860 abort();
6862 tcg_temp_free_i32(tmp);
6863 if (size == 3) {
6864 tcg_gen_addi_i32(addr, addr, 4);
6865 tmp = load_reg(s, rt2);
6866 gen_aa32_st32(tmp, addr, IS_USER(s));
6867 tcg_temp_free_i32(tmp);
6869 tcg_gen_movi_i32(cpu_R[rd], 0);
6870 tcg_gen_br(done_label);
6871 gen_set_label(fail_label);
6872 tcg_gen_movi_i32(cpu_R[rd], 1);
6873 gen_set_label(done_label);
6874 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
6876 #endif
6878 /* gen_srs:
6879 * @env: CPUARMState
6880 * @s: DisasContext
6881 * @mode: mode field from insn (which stack to store to)
6882 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
6883 * @writeback: true if writeback bit set
6885 * Generate code for the SRS (Store Return State) insn.
6887 static void gen_srs(DisasContext *s,
6888 uint32_t mode, uint32_t amode, bool writeback)
6890 int32_t offset;
6891 TCGv_i32 addr = tcg_temp_new_i32();
6892 TCGv_i32 tmp = tcg_const_i32(mode);
6893 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6894 tcg_temp_free_i32(tmp);
6895 switch (amode) {
6896 case 0: /* DA */
6897 offset = -4;
6898 break;
6899 case 1: /* IA */
6900 offset = 0;
6901 break;
6902 case 2: /* DB */
6903 offset = -8;
6904 break;
6905 case 3: /* IB */
6906 offset = 4;
6907 break;
6908 default:
6909 abort();
6911 tcg_gen_addi_i32(addr, addr, offset);
6912 tmp = load_reg(s, 14);
6913 gen_aa32_st32(tmp, addr, 0);
6914 tcg_temp_free_i32(tmp);
6915 tmp = load_cpu_field(spsr);
6916 tcg_gen_addi_i32(addr, addr, 4);
6917 gen_aa32_st32(tmp, addr, 0);
6918 tcg_temp_free_i32(tmp);
6919 if (writeback) {
6920 switch (amode) {
6921 case 0:
6922 offset = -8;
6923 break;
6924 case 1:
6925 offset = 4;
6926 break;
6927 case 2:
6928 offset = -4;
6929 break;
6930 case 3:
6931 offset = 0;
6932 break;
6933 default:
6934 abort();
6936 tcg_gen_addi_i32(addr, addr, offset);
6937 tmp = tcg_const_i32(mode);
6938 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6939 tcg_temp_free_i32(tmp);
6941 tcg_temp_free_i32(addr);
6944 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
6946 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6947 TCGv_i32 tmp;
6948 TCGv_i32 tmp2;
6949 TCGv_i32 tmp3;
6950 TCGv_i32 addr;
6951 TCGv_i64 tmp64;
6953 insn = arm_ldl_code(env, s->pc, s->bswap_code);
6954 s->pc += 4;
6956 /* M variants do not implement ARM mode. */
6957 if (IS_M(env))
6958 goto illegal_op;
6959 cond = insn >> 28;
6960 if (cond == 0xf){
6961 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6962 * choose to UNDEF. In ARMv5 and above the space is used
6963 * for miscellaneous unconditional instructions.
6965 ARCH(5);
6967 /* Unconditional instructions. */
6968 if (((insn >> 25) & 7) == 1) {
6969 /* NEON Data processing. */
6970 if (!arm_feature(env, ARM_FEATURE_NEON))
6971 goto illegal_op;
6973 if (disas_neon_data_insn(env, s, insn))
6974 goto illegal_op;
6975 return;
6977 if ((insn & 0x0f100000) == 0x04000000) {
6978 /* NEON load/store. */
6979 if (!arm_feature(env, ARM_FEATURE_NEON))
6980 goto illegal_op;
6982 if (disas_neon_ls_insn(env, s, insn))
6983 goto illegal_op;
6984 return;
6986 if ((insn & 0x0f000e10) == 0x0e000a00) {
6987 /* VFP. */
6988 if (disas_vfp_insn(env, s, insn)) {
6989 goto illegal_op;
6991 return;
6993 if (((insn & 0x0f30f000) == 0x0510f000) ||
6994 ((insn & 0x0f30f010) == 0x0710f000)) {
6995 if ((insn & (1 << 22)) == 0) {
6996 /* PLDW; v7MP */
6997 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6998 goto illegal_op;
7001 /* Otherwise PLD; v5TE+ */
7002 ARCH(5TE);
7003 return;
7005 if (((insn & 0x0f70f000) == 0x0450f000) ||
7006 ((insn & 0x0f70f010) == 0x0650f000)) {
7007 ARCH(7);
7008 return; /* PLI; V7 */
7010 if (((insn & 0x0f700000) == 0x04100000) ||
7011 ((insn & 0x0f700010) == 0x06100000)) {
7012 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7013 goto illegal_op;
7015 return; /* v7MP: Unallocated memory hint: must NOP */
7018 if ((insn & 0x0ffffdff) == 0x01010000) {
7019 ARCH(6);
7020 /* setend */
7021 if (((insn >> 9) & 1) != s->bswap_code) {
7022 /* Dynamic endianness switching not implemented. */
7023 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
7024 goto illegal_op;
7026 return;
7027 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7028 switch ((insn >> 4) & 0xf) {
7029 case 1: /* clrex */
7030 ARCH(6K);
7031 gen_clrex(s);
7032 return;
7033 case 4: /* dsb */
7034 case 5: /* dmb */
7035 case 6: /* isb */
7036 ARCH(7);
7037 /* We don't emulate caches so these are a no-op. */
7038 return;
7039 default:
7040 goto illegal_op;
7042 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7043 /* srs */
7044 if (IS_USER(s)) {
7045 goto illegal_op;
7047 ARCH(6);
7048 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
7049 return;
7050 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
7051 /* rfe */
7052 int32_t offset;
7053 if (IS_USER(s))
7054 goto illegal_op;
7055 ARCH(6);
7056 rn = (insn >> 16) & 0xf;
7057 addr = load_reg(s, rn);
7058 i = (insn >> 23) & 3;
7059 switch (i) {
7060 case 0: offset = -4; break; /* DA */
7061 case 1: offset = 0; break; /* IA */
7062 case 2: offset = -8; break; /* DB */
7063 case 3: offset = 4; break; /* IB */
7064 default: abort();
7066 if (offset)
7067 tcg_gen_addi_i32(addr, addr, offset);
7068 /* Load PC into tmp and CPSR into tmp2. */
7069 tmp = tcg_temp_new_i32();
7070 gen_aa32_ld32u(tmp, addr, 0);
7071 tcg_gen_addi_i32(addr, addr, 4);
7072 tmp2 = tcg_temp_new_i32();
7073 gen_aa32_ld32u(tmp2, addr, 0);
7074 if (insn & (1 << 21)) {
7075 /* Base writeback. */
7076 switch (i) {
7077 case 0: offset = -8; break;
7078 case 1: offset = 4; break;
7079 case 2: offset = -4; break;
7080 case 3: offset = 0; break;
7081 default: abort();
7083 if (offset)
7084 tcg_gen_addi_i32(addr, addr, offset);
7085 store_reg(s, rn, addr);
7086 } else {
7087 tcg_temp_free_i32(addr);
7089 gen_rfe(s, tmp, tmp2);
7090 return;
7091 } else if ((insn & 0x0e000000) == 0x0a000000) {
7092 /* branch link and change to thumb (blx <offset>) */
7093 int32_t offset;
7095 val = (uint32_t)s->pc;
7096 tmp = tcg_temp_new_i32();
7097 tcg_gen_movi_i32(tmp, val);
7098 store_reg(s, 14, tmp);
7099 /* Sign-extend the 24-bit offset */
7100 offset = (((int32_t)insn) << 8) >> 8;
7101 /* offset * 4 + bit24 * 2 + (thumb bit) */
7102 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7103 /* pipeline offset */
7104 val += 4;
7105 /* protected by ARCH(5); above, near the start of uncond block */
7106 gen_bx_im(s, val);
7107 return;
7108 } else if ((insn & 0x0e000f00) == 0x0c000100) {
7109 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7110 /* iWMMXt register transfer. */
7111 if (env->cp15.c15_cpar & (1 << 1))
7112 if (!disas_iwmmxt_insn(env, s, insn))
7113 return;
7115 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7116 /* Coprocessor double register transfer. */
7117 ARCH(5TE);
7118 } else if ((insn & 0x0f000010) == 0x0e000010) {
7119 /* Additional coprocessor register transfer. */
7120 } else if ((insn & 0x0ff10020) == 0x01000000) {
7121 uint32_t mask;
7122 uint32_t val;
7123 /* cps (privileged) */
7124 if (IS_USER(s))
7125 return;
7126 mask = val = 0;
7127 if (insn & (1 << 19)) {
7128 if (insn & (1 << 8))
7129 mask |= CPSR_A;
7130 if (insn & (1 << 7))
7131 mask |= CPSR_I;
7132 if (insn & (1 << 6))
7133 mask |= CPSR_F;
7134 if (insn & (1 << 18))
7135 val |= mask;
7137 if (insn & (1 << 17)) {
7138 mask |= CPSR_M;
7139 val |= (insn & 0x1f);
7141 if (mask) {
7142 gen_set_psr_im(s, mask, 0, val);
7144 return;
7146 goto illegal_op;
7148 if (cond != 0xe) {
7149 /* if not always execute, we generate a conditional jump to
7150 next instruction */
7151 s->condlabel = gen_new_label();
7152 arm_gen_test_cc(cond ^ 1, s->condlabel);
7153 s->condjmp = 1;
7155 if ((insn & 0x0f900000) == 0x03000000) {
7156 if ((insn & (1 << 21)) == 0) {
7157 ARCH(6T2);
7158 rd = (insn >> 12) & 0xf;
7159 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7160 if ((insn & (1 << 22)) == 0) {
7161 /* MOVW */
7162 tmp = tcg_temp_new_i32();
7163 tcg_gen_movi_i32(tmp, val);
7164 } else {
7165 /* MOVT */
7166 tmp = load_reg(s, rd);
7167 tcg_gen_ext16u_i32(tmp, tmp);
7168 tcg_gen_ori_i32(tmp, tmp, val << 16);
7170 store_reg(s, rd, tmp);
7171 } else {
7172 if (((insn >> 12) & 0xf) != 0xf)
7173 goto illegal_op;
7174 if (((insn >> 16) & 0xf) == 0) {
7175 gen_nop_hint(s, insn & 0xff);
7176 } else {
7177 /* CPSR = immediate */
7178 val = insn & 0xff;
7179 shift = ((insn >> 8) & 0xf) * 2;
7180 if (shift)
7181 val = (val >> shift) | (val << (32 - shift));
7182 i = ((insn & (1 << 22)) != 0);
7183 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
7184 goto illegal_op;
7187 } else if ((insn & 0x0f900000) == 0x01000000
7188 && (insn & 0x00000090) != 0x00000090) {
7189 /* miscellaneous instructions */
7190 op1 = (insn >> 21) & 3;
7191 sh = (insn >> 4) & 0xf;
7192 rm = insn & 0xf;
7193 switch (sh) {
7194 case 0x0: /* move program status register */
7195 if (op1 & 1) {
7196 /* PSR = reg */
7197 tmp = load_reg(s, rm);
7198 i = ((op1 & 2) != 0);
7199 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
7200 goto illegal_op;
7201 } else {
7202 /* reg = PSR */
7203 rd = (insn >> 12) & 0xf;
7204 if (op1 & 2) {
7205 if (IS_USER(s))
7206 goto illegal_op;
7207 tmp = load_cpu_field(spsr);
7208 } else {
7209 tmp = tcg_temp_new_i32();
7210 gen_helper_cpsr_read(tmp, cpu_env);
7212 store_reg(s, rd, tmp);
7214 break;
7215 case 0x1:
7216 if (op1 == 1) {
7217 /* branch/exchange thumb (bx). */
7218 ARCH(4T);
7219 tmp = load_reg(s, rm);
7220 gen_bx(s, tmp);
7221 } else if (op1 == 3) {
7222 /* clz */
7223 ARCH(5);
7224 rd = (insn >> 12) & 0xf;
7225 tmp = load_reg(s, rm);
7226 gen_helper_clz(tmp, tmp);
7227 store_reg(s, rd, tmp);
7228 } else {
7229 goto illegal_op;
7231 break;
7232 case 0x2:
7233 if (op1 == 1) {
7234 ARCH(5J); /* bxj */
7235 /* Trivial implementation equivalent to bx. */
7236 tmp = load_reg(s, rm);
7237 gen_bx(s, tmp);
7238 } else {
7239 goto illegal_op;
7241 break;
7242 case 0x3:
7243 if (op1 != 1)
7244 goto illegal_op;
7246 ARCH(5);
7247 /* branch link/exchange thumb (blx) */
7248 tmp = load_reg(s, rm);
7249 tmp2 = tcg_temp_new_i32();
7250 tcg_gen_movi_i32(tmp2, s->pc);
7251 store_reg(s, 14, tmp2);
7252 gen_bx(s, tmp);
7253 break;
7254 case 0x5: /* saturating add/subtract */
7255 ARCH(5TE);
7256 rd = (insn >> 12) & 0xf;
7257 rn = (insn >> 16) & 0xf;
7258 tmp = load_reg(s, rm);
7259 tmp2 = load_reg(s, rn);
7260 if (op1 & 2)
7261 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
7262 if (op1 & 1)
7263 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
7264 else
7265 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7266 tcg_temp_free_i32(tmp2);
7267 store_reg(s, rd, tmp);
7268 break;
7269 case 7:
7270 /* SMC instruction (op1 == 3)
7271 and undefined instructions (op1 == 0 || op1 == 2)
7272 will trap */
7273 if (op1 != 1) {
7274 goto illegal_op;
7276 /* bkpt */
7277 ARCH(5);
7278 gen_exception_insn(s, 4, EXCP_BKPT);
7279 break;
7280 case 0x8: /* signed multiply */
7281 case 0xa:
7282 case 0xc:
7283 case 0xe:
7284 ARCH(5TE);
7285 rs = (insn >> 8) & 0xf;
7286 rn = (insn >> 12) & 0xf;
7287 rd = (insn >> 16) & 0xf;
7288 if (op1 == 1) {
7289 /* (32 * 16) >> 16 */
7290 tmp = load_reg(s, rm);
7291 tmp2 = load_reg(s, rs);
7292 if (sh & 4)
7293 tcg_gen_sari_i32(tmp2, tmp2, 16);
7294 else
7295 gen_sxth(tmp2);
7296 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7297 tcg_gen_shri_i64(tmp64, tmp64, 16);
7298 tmp = tcg_temp_new_i32();
7299 tcg_gen_trunc_i64_i32(tmp, tmp64);
7300 tcg_temp_free_i64(tmp64);
7301 if ((sh & 2) == 0) {
7302 tmp2 = load_reg(s, rn);
7303 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7304 tcg_temp_free_i32(tmp2);
7306 store_reg(s, rd, tmp);
7307 } else {
7308 /* 16 * 16 */
7309 tmp = load_reg(s, rm);
7310 tmp2 = load_reg(s, rs);
7311 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7312 tcg_temp_free_i32(tmp2);
7313 if (op1 == 2) {
7314 tmp64 = tcg_temp_new_i64();
7315 tcg_gen_ext_i32_i64(tmp64, tmp);
7316 tcg_temp_free_i32(tmp);
7317 gen_addq(s, tmp64, rn, rd);
7318 gen_storeq_reg(s, rn, rd, tmp64);
7319 tcg_temp_free_i64(tmp64);
7320 } else {
7321 if (op1 == 0) {
7322 tmp2 = load_reg(s, rn);
7323 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7324 tcg_temp_free_i32(tmp2);
7326 store_reg(s, rd, tmp);
7329 break;
7330 default:
7331 goto illegal_op;
7333 } else if (((insn & 0x0e000000) == 0 &&
7334 (insn & 0x00000090) != 0x90) ||
7335 ((insn & 0x0e000000) == (1 << 25))) {
7336 int set_cc, logic_cc, shiftop;
7338 op1 = (insn >> 21) & 0xf;
7339 set_cc = (insn >> 20) & 1;
7340 logic_cc = table_logic_cc[op1] & set_cc;
7342 /* data processing instruction */
7343 if (insn & (1 << 25)) {
7344 /* immediate operand */
7345 val = insn & 0xff;
7346 shift = ((insn >> 8) & 0xf) * 2;
7347 if (shift) {
7348 val = (val >> shift) | (val << (32 - shift));
7350 tmp2 = tcg_temp_new_i32();
7351 tcg_gen_movi_i32(tmp2, val);
7352 if (logic_cc && shift) {
7353 gen_set_CF_bit31(tmp2);
7355 } else {
7356 /* register */
7357 rm = (insn) & 0xf;
7358 tmp2 = load_reg(s, rm);
7359 shiftop = (insn >> 5) & 3;
7360 if (!(insn & (1 << 4))) {
7361 shift = (insn >> 7) & 0x1f;
7362 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7363 } else {
7364 rs = (insn >> 8) & 0xf;
7365 tmp = load_reg(s, rs);
7366 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7369 if (op1 != 0x0f && op1 != 0x0d) {
7370 rn = (insn >> 16) & 0xf;
7371 tmp = load_reg(s, rn);
7372 } else {
7373 TCGV_UNUSED_I32(tmp);
7375 rd = (insn >> 12) & 0xf;
7376 switch(op1) {
7377 case 0x00:
7378 tcg_gen_and_i32(tmp, tmp, tmp2);
7379 if (logic_cc) {
7380 gen_logic_CC(tmp);
7382 store_reg_bx(env, s, rd, tmp);
7383 break;
7384 case 0x01:
7385 tcg_gen_xor_i32(tmp, tmp, tmp2);
7386 if (logic_cc) {
7387 gen_logic_CC(tmp);
7389 store_reg_bx(env, s, rd, tmp);
7390 break;
7391 case 0x02:
7392 if (set_cc && rd == 15) {
7393 /* SUBS r15, ... is used for exception return. */
7394 if (IS_USER(s)) {
7395 goto illegal_op;
7397 gen_sub_CC(tmp, tmp, tmp2);
7398 gen_exception_return(s, tmp);
7399 } else {
7400 if (set_cc) {
7401 gen_sub_CC(tmp, tmp, tmp2);
7402 } else {
7403 tcg_gen_sub_i32(tmp, tmp, tmp2);
7405 store_reg_bx(env, s, rd, tmp);
7407 break;
7408 case 0x03:
7409 if (set_cc) {
7410 gen_sub_CC(tmp, tmp2, tmp);
7411 } else {
7412 tcg_gen_sub_i32(tmp, tmp2, tmp);
7414 store_reg_bx(env, s, rd, tmp);
7415 break;
7416 case 0x04:
7417 if (set_cc) {
7418 gen_add_CC(tmp, tmp, tmp2);
7419 } else {
7420 tcg_gen_add_i32(tmp, tmp, tmp2);
7422 store_reg_bx(env, s, rd, tmp);
7423 break;
7424 case 0x05:
7425 if (set_cc) {
7426 gen_adc_CC(tmp, tmp, tmp2);
7427 } else {
7428 gen_add_carry(tmp, tmp, tmp2);
7430 store_reg_bx(env, s, rd, tmp);
7431 break;
7432 case 0x06:
7433 if (set_cc) {
7434 gen_sbc_CC(tmp, tmp, tmp2);
7435 } else {
7436 gen_sub_carry(tmp, tmp, tmp2);
7438 store_reg_bx(env, s, rd, tmp);
7439 break;
7440 case 0x07:
7441 if (set_cc) {
7442 gen_sbc_CC(tmp, tmp2, tmp);
7443 } else {
7444 gen_sub_carry(tmp, tmp2, tmp);
7446 store_reg_bx(env, s, rd, tmp);
7447 break;
7448 case 0x08:
7449 if (set_cc) {
7450 tcg_gen_and_i32(tmp, tmp, tmp2);
7451 gen_logic_CC(tmp);
7453 tcg_temp_free_i32(tmp);
7454 break;
7455 case 0x09:
7456 if (set_cc) {
7457 tcg_gen_xor_i32(tmp, tmp, tmp2);
7458 gen_logic_CC(tmp);
7460 tcg_temp_free_i32(tmp);
7461 break;
7462 case 0x0a:
7463 if (set_cc) {
7464 gen_sub_CC(tmp, tmp, tmp2);
7466 tcg_temp_free_i32(tmp);
7467 break;
7468 case 0x0b:
7469 if (set_cc) {
7470 gen_add_CC(tmp, tmp, tmp2);
7472 tcg_temp_free_i32(tmp);
7473 break;
7474 case 0x0c:
7475 tcg_gen_or_i32(tmp, tmp, tmp2);
7476 if (logic_cc) {
7477 gen_logic_CC(tmp);
7479 store_reg_bx(env, s, rd, tmp);
7480 break;
7481 case 0x0d:
7482 if (logic_cc && rd == 15) {
7483 /* MOVS r15, ... is used for exception return. */
7484 if (IS_USER(s)) {
7485 goto illegal_op;
7487 gen_exception_return(s, tmp2);
7488 } else {
7489 if (logic_cc) {
7490 gen_logic_CC(tmp2);
7492 store_reg_bx(env, s, rd, tmp2);
7494 break;
7495 case 0x0e:
7496 tcg_gen_andc_i32(tmp, tmp, tmp2);
7497 if (logic_cc) {
7498 gen_logic_CC(tmp);
7500 store_reg_bx(env, s, rd, tmp);
7501 break;
7502 default:
7503 case 0x0f:
7504 tcg_gen_not_i32(tmp2, tmp2);
7505 if (logic_cc) {
7506 gen_logic_CC(tmp2);
7508 store_reg_bx(env, s, rd, tmp2);
7509 break;
7511 if (op1 != 0x0f && op1 != 0x0d) {
7512 tcg_temp_free_i32(tmp2);
7514 } else {
7515 /* other instructions */
7516 op1 = (insn >> 24) & 0xf;
7517 switch(op1) {
7518 case 0x0:
7519 case 0x1:
7520 /* multiplies, extra load/stores */
7521 sh = (insn >> 5) & 3;
7522 if (sh == 0) {
7523 if (op1 == 0x0) {
7524 rd = (insn >> 16) & 0xf;
7525 rn = (insn >> 12) & 0xf;
7526 rs = (insn >> 8) & 0xf;
7527 rm = (insn) & 0xf;
7528 op1 = (insn >> 20) & 0xf;
7529 switch (op1) {
7530 case 0: case 1: case 2: case 3: case 6:
7531 /* 32 bit mul */
7532 tmp = load_reg(s, rs);
7533 tmp2 = load_reg(s, rm);
7534 tcg_gen_mul_i32(tmp, tmp, tmp2);
7535 tcg_temp_free_i32(tmp2);
7536 if (insn & (1 << 22)) {
7537 /* Subtract (mls) */
7538 ARCH(6T2);
7539 tmp2 = load_reg(s, rn);
7540 tcg_gen_sub_i32(tmp, tmp2, tmp);
7541 tcg_temp_free_i32(tmp2);
7542 } else if (insn & (1 << 21)) {
7543 /* Add */
7544 tmp2 = load_reg(s, rn);
7545 tcg_gen_add_i32(tmp, tmp, tmp2);
7546 tcg_temp_free_i32(tmp2);
7548 if (insn & (1 << 20))
7549 gen_logic_CC(tmp);
7550 store_reg(s, rd, tmp);
7551 break;
7552 case 4:
7553 /* 64 bit mul double accumulate (UMAAL) */
7554 ARCH(6);
7555 tmp = load_reg(s, rs);
7556 tmp2 = load_reg(s, rm);
7557 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7558 gen_addq_lo(s, tmp64, rn);
7559 gen_addq_lo(s, tmp64, rd);
7560 gen_storeq_reg(s, rn, rd, tmp64);
7561 tcg_temp_free_i64(tmp64);
7562 break;
7563 case 8: case 9: case 10: case 11:
7564 case 12: case 13: case 14: case 15:
7565 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7566 tmp = load_reg(s, rs);
7567 tmp2 = load_reg(s, rm);
7568 if (insn & (1 << 22)) {
7569 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
7570 } else {
7571 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
7573 if (insn & (1 << 21)) { /* mult accumulate */
7574 TCGv_i32 al = load_reg(s, rn);
7575 TCGv_i32 ah = load_reg(s, rd);
7576 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
7577 tcg_temp_free_i32(al);
7578 tcg_temp_free_i32(ah);
7580 if (insn & (1 << 20)) {
7581 gen_logicq_cc(tmp, tmp2);
7583 store_reg(s, rn, tmp);
7584 store_reg(s, rd, tmp2);
7585 break;
7586 default:
7587 goto illegal_op;
7589 } else {
7590 rn = (insn >> 16) & 0xf;
7591 rd = (insn >> 12) & 0xf;
7592 if (insn & (1 << 23)) {
7593 /* load/store exclusive */
7594 int op2 = (insn >> 8) & 3;
7595 op1 = (insn >> 21) & 0x3;
7597 switch (op2) {
7598 case 0: /* lda/stl */
7599 if (op1 == 1) {
7600 goto illegal_op;
7602 ARCH(8);
7603 break;
7604 case 1: /* reserved */
7605 goto illegal_op;
7606 case 2: /* ldaex/stlex */
7607 ARCH(8);
7608 break;
7609 case 3: /* ldrex/strex */
7610 if (op1) {
7611 ARCH(6K);
7612 } else {
7613 ARCH(6);
7615 break;
7618 addr = tcg_temp_local_new_i32();
7619 load_reg_var(s, addr, rn);
7621 /* Since the emulation does not have barriers,
7622 the acquire/release semantics need no special
7623 handling */
7624 if (op2 == 0) {
7625 if (insn & (1 << 20)) {
7626 tmp = tcg_temp_new_i32();
7627 switch (op1) {
7628 case 0: /* lda */
7629 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7630 break;
7631 case 2: /* ldab */
7632 gen_aa32_ld8u(tmp, addr, IS_USER(s));
7633 break;
7634 case 3: /* ldah */
7635 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7636 break;
7637 default:
7638 abort();
7640 store_reg(s, rd, tmp);
7641 } else {
7642 rm = insn & 0xf;
7643 tmp = load_reg(s, rm);
7644 switch (op1) {
7645 case 0: /* stl */
7646 gen_aa32_st32(tmp, addr, IS_USER(s));
7647 break;
7648 case 2: /* stlb */
7649 gen_aa32_st8(tmp, addr, IS_USER(s));
7650 break;
7651 case 3: /* stlh */
7652 gen_aa32_st16(tmp, addr, IS_USER(s));
7653 break;
7654 default:
7655 abort();
7657 tcg_temp_free_i32(tmp);
7659 } else if (insn & (1 << 20)) {
7660 switch (op1) {
7661 case 0: /* ldrex */
7662 gen_load_exclusive(s, rd, 15, addr, 2);
7663 break;
7664 case 1: /* ldrexd */
7665 gen_load_exclusive(s, rd, rd + 1, addr, 3);
7666 break;
7667 case 2: /* ldrexb */
7668 gen_load_exclusive(s, rd, 15, addr, 0);
7669 break;
7670 case 3: /* ldrexh */
7671 gen_load_exclusive(s, rd, 15, addr, 1);
7672 break;
7673 default:
7674 abort();
7676 } else {
7677 rm = insn & 0xf;
7678 switch (op1) {
7679 case 0: /* strex */
7680 gen_store_exclusive(s, rd, rm, 15, addr, 2);
7681 break;
7682 case 1: /* strexd */
7683 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
7684 break;
7685 case 2: /* strexb */
7686 gen_store_exclusive(s, rd, rm, 15, addr, 0);
7687 break;
7688 case 3: /* strexh */
7689 gen_store_exclusive(s, rd, rm, 15, addr, 1);
7690 break;
7691 default:
7692 abort();
7695 tcg_temp_free_i32(addr);
7696 } else {
7697 /* SWP instruction */
7698 rm = (insn) & 0xf;
7700 /* ??? This is not really atomic. However we know
7701 we never have multiple CPUs running in parallel,
7702 so it is good enough. */
7703 addr = load_reg(s, rn);
7704 tmp = load_reg(s, rm);
7705 tmp2 = tcg_temp_new_i32();
7706 if (insn & (1 << 22)) {
7707 gen_aa32_ld8u(tmp2, addr, IS_USER(s));
7708 gen_aa32_st8(tmp, addr, IS_USER(s));
7709 } else {
7710 gen_aa32_ld32u(tmp2, addr, IS_USER(s));
7711 gen_aa32_st32(tmp, addr, IS_USER(s));
7713 tcg_temp_free_i32(tmp);
7714 tcg_temp_free_i32(addr);
7715 store_reg(s, rd, tmp2);
7718 } else {
7719 int address_offset;
7720 int load;
7721 /* Misc load/store */
7722 rn = (insn >> 16) & 0xf;
7723 rd = (insn >> 12) & 0xf;
7724 addr = load_reg(s, rn);
7725 if (insn & (1 << 24))
7726 gen_add_datah_offset(s, insn, 0, addr);
7727 address_offset = 0;
7728 if (insn & (1 << 20)) {
7729 /* load */
7730 tmp = tcg_temp_new_i32();
7731 switch(sh) {
7732 case 1:
7733 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7734 break;
7735 case 2:
7736 gen_aa32_ld8s(tmp, addr, IS_USER(s));
7737 break;
7738 default:
7739 case 3:
7740 gen_aa32_ld16s(tmp, addr, IS_USER(s));
7741 break;
7743 load = 1;
7744 } else if (sh & 2) {
7745 ARCH(5TE);
7746 /* doubleword */
7747 if (sh & 1) {
7748 /* store */
7749 tmp = load_reg(s, rd);
7750 gen_aa32_st32(tmp, addr, IS_USER(s));
7751 tcg_temp_free_i32(tmp);
7752 tcg_gen_addi_i32(addr, addr, 4);
7753 tmp = load_reg(s, rd + 1);
7754 gen_aa32_st32(tmp, addr, IS_USER(s));
7755 tcg_temp_free_i32(tmp);
7756 load = 0;
7757 } else {
7758 /* load */
7759 tmp = tcg_temp_new_i32();
7760 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7761 store_reg(s, rd, tmp);
7762 tcg_gen_addi_i32(addr, addr, 4);
7763 tmp = tcg_temp_new_i32();
7764 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7765 rd++;
7766 load = 1;
7768 address_offset = -4;
7769 } else {
7770 /* store */
7771 tmp = load_reg(s, rd);
7772 gen_aa32_st16(tmp, addr, IS_USER(s));
7773 tcg_temp_free_i32(tmp);
7774 load = 0;
7776 /* Perform base writeback before the loaded value to
7777 ensure correct behavior with overlapping index registers.
7778 ldrd with base writeback is is undefined if the
7779 destination and index registers overlap. */
7780 if (!(insn & (1 << 24))) {
7781 gen_add_datah_offset(s, insn, address_offset, addr);
7782 store_reg(s, rn, addr);
7783 } else if (insn & (1 << 21)) {
7784 if (address_offset)
7785 tcg_gen_addi_i32(addr, addr, address_offset);
7786 store_reg(s, rn, addr);
7787 } else {
7788 tcg_temp_free_i32(addr);
7790 if (load) {
7791 /* Complete the load. */
7792 store_reg(s, rd, tmp);
7795 break;
7796 case 0x4:
7797 case 0x5:
7798 goto do_ldst;
7799 case 0x6:
7800 case 0x7:
7801 if (insn & (1 << 4)) {
7802 ARCH(6);
7803 /* Armv6 Media instructions. */
7804 rm = insn & 0xf;
7805 rn = (insn >> 16) & 0xf;
7806 rd = (insn >> 12) & 0xf;
7807 rs = (insn >> 8) & 0xf;
7808 switch ((insn >> 23) & 3) {
7809 case 0: /* Parallel add/subtract. */
7810 op1 = (insn >> 20) & 7;
7811 tmp = load_reg(s, rn);
7812 tmp2 = load_reg(s, rm);
7813 sh = (insn >> 5) & 7;
7814 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
7815 goto illegal_op;
7816 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7817 tcg_temp_free_i32(tmp2);
7818 store_reg(s, rd, tmp);
7819 break;
7820 case 1:
7821 if ((insn & 0x00700020) == 0) {
7822 /* Halfword pack. */
7823 tmp = load_reg(s, rn);
7824 tmp2 = load_reg(s, rm);
7825 shift = (insn >> 7) & 0x1f;
7826 if (insn & (1 << 6)) {
7827 /* pkhtb */
7828 if (shift == 0)
7829 shift = 31;
7830 tcg_gen_sari_i32(tmp2, tmp2, shift);
7831 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7832 tcg_gen_ext16u_i32(tmp2, tmp2);
7833 } else {
7834 /* pkhbt */
7835 if (shift)
7836 tcg_gen_shli_i32(tmp2, tmp2, shift);
7837 tcg_gen_ext16u_i32(tmp, tmp);
7838 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7840 tcg_gen_or_i32(tmp, tmp, tmp2);
7841 tcg_temp_free_i32(tmp2);
7842 store_reg(s, rd, tmp);
7843 } else if ((insn & 0x00200020) == 0x00200000) {
7844 /* [us]sat */
7845 tmp = load_reg(s, rm);
7846 shift = (insn >> 7) & 0x1f;
7847 if (insn & (1 << 6)) {
7848 if (shift == 0)
7849 shift = 31;
7850 tcg_gen_sari_i32(tmp, tmp, shift);
7851 } else {
7852 tcg_gen_shli_i32(tmp, tmp, shift);
7854 sh = (insn >> 16) & 0x1f;
7855 tmp2 = tcg_const_i32(sh);
7856 if (insn & (1 << 22))
7857 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
7858 else
7859 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
7860 tcg_temp_free_i32(tmp2);
7861 store_reg(s, rd, tmp);
7862 } else if ((insn & 0x00300fe0) == 0x00200f20) {
7863 /* [us]sat16 */
7864 tmp = load_reg(s, rm);
7865 sh = (insn >> 16) & 0x1f;
7866 tmp2 = tcg_const_i32(sh);
7867 if (insn & (1 << 22))
7868 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
7869 else
7870 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
7871 tcg_temp_free_i32(tmp2);
7872 store_reg(s, rd, tmp);
7873 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
7874 /* Select bytes. */
7875 tmp = load_reg(s, rn);
7876 tmp2 = load_reg(s, rm);
7877 tmp3 = tcg_temp_new_i32();
7878 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
7879 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7880 tcg_temp_free_i32(tmp3);
7881 tcg_temp_free_i32(tmp2);
7882 store_reg(s, rd, tmp);
7883 } else if ((insn & 0x000003e0) == 0x00000060) {
7884 tmp = load_reg(s, rm);
7885 shift = (insn >> 10) & 3;
7886 /* ??? In many cases it's not necessary to do a
7887 rotate, a shift is sufficient. */
7888 if (shift != 0)
7889 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7890 op1 = (insn >> 20) & 7;
7891 switch (op1) {
7892 case 0: gen_sxtb16(tmp); break;
7893 case 2: gen_sxtb(tmp); break;
7894 case 3: gen_sxth(tmp); break;
7895 case 4: gen_uxtb16(tmp); break;
7896 case 6: gen_uxtb(tmp); break;
7897 case 7: gen_uxth(tmp); break;
7898 default: goto illegal_op;
7900 if (rn != 15) {
7901 tmp2 = load_reg(s, rn);
7902 if ((op1 & 3) == 0) {
7903 gen_add16(tmp, tmp2);
7904 } else {
7905 tcg_gen_add_i32(tmp, tmp, tmp2);
7906 tcg_temp_free_i32(tmp2);
7909 store_reg(s, rd, tmp);
7910 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7911 /* rev */
7912 tmp = load_reg(s, rm);
7913 if (insn & (1 << 22)) {
7914 if (insn & (1 << 7)) {
7915 gen_revsh(tmp);
7916 } else {
7917 ARCH(6T2);
7918 gen_helper_rbit(tmp, tmp);
7920 } else {
7921 if (insn & (1 << 7))
7922 gen_rev16(tmp);
7923 else
7924 tcg_gen_bswap32_i32(tmp, tmp);
7926 store_reg(s, rd, tmp);
7927 } else {
7928 goto illegal_op;
7930 break;
7931 case 2: /* Multiplies (Type 3). */
7932 switch ((insn >> 20) & 0x7) {
7933 case 5:
7934 if (((insn >> 6) ^ (insn >> 7)) & 1) {
7935 /* op2 not 00x or 11x : UNDEF */
7936 goto illegal_op;
7938 /* Signed multiply most significant [accumulate].
7939 (SMMUL, SMMLA, SMMLS) */
7940 tmp = load_reg(s, rm);
7941 tmp2 = load_reg(s, rs);
7942 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7944 if (rd != 15) {
7945 tmp = load_reg(s, rd);
7946 if (insn & (1 << 6)) {
7947 tmp64 = gen_subq_msw(tmp64, tmp);
7948 } else {
7949 tmp64 = gen_addq_msw(tmp64, tmp);
7952 if (insn & (1 << 5)) {
7953 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7955 tcg_gen_shri_i64(tmp64, tmp64, 32);
7956 tmp = tcg_temp_new_i32();
7957 tcg_gen_trunc_i64_i32(tmp, tmp64);
7958 tcg_temp_free_i64(tmp64);
7959 store_reg(s, rn, tmp);
7960 break;
7961 case 0:
7962 case 4:
7963 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
7964 if (insn & (1 << 7)) {
7965 goto illegal_op;
7967 tmp = load_reg(s, rm);
7968 tmp2 = load_reg(s, rs);
7969 if (insn & (1 << 5))
7970 gen_swap_half(tmp2);
7971 gen_smul_dual(tmp, tmp2);
7972 if (insn & (1 << 6)) {
7973 /* This subtraction cannot overflow. */
7974 tcg_gen_sub_i32(tmp, tmp, tmp2);
7975 } else {
7976 /* This addition cannot overflow 32 bits;
7977 * however it may overflow considered as a signed
7978 * operation, in which case we must set the Q flag.
7980 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7982 tcg_temp_free_i32(tmp2);
7983 if (insn & (1 << 22)) {
7984 /* smlald, smlsld */
7985 tmp64 = tcg_temp_new_i64();
7986 tcg_gen_ext_i32_i64(tmp64, tmp);
7987 tcg_temp_free_i32(tmp);
7988 gen_addq(s, tmp64, rd, rn);
7989 gen_storeq_reg(s, rd, rn, tmp64);
7990 tcg_temp_free_i64(tmp64);
7991 } else {
7992 /* smuad, smusd, smlad, smlsd */
7993 if (rd != 15)
7995 tmp2 = load_reg(s, rd);
7996 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7997 tcg_temp_free_i32(tmp2);
7999 store_reg(s, rn, tmp);
8001 break;
8002 case 1:
8003 case 3:
8004 /* SDIV, UDIV */
8005 if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
8006 goto illegal_op;
8008 if (((insn >> 5) & 7) || (rd != 15)) {
8009 goto illegal_op;
8011 tmp = load_reg(s, rm);
8012 tmp2 = load_reg(s, rs);
8013 if (insn & (1 << 21)) {
8014 gen_helper_udiv(tmp, tmp, tmp2);
8015 } else {
8016 gen_helper_sdiv(tmp, tmp, tmp2);
8018 tcg_temp_free_i32(tmp2);
8019 store_reg(s, rn, tmp);
8020 break;
8021 default:
8022 goto illegal_op;
8024 break;
8025 case 3:
8026 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8027 switch (op1) {
8028 case 0: /* Unsigned sum of absolute differences. */
8029 ARCH(6);
8030 tmp = load_reg(s, rm);
8031 tmp2 = load_reg(s, rs);
8032 gen_helper_usad8(tmp, tmp, tmp2);
8033 tcg_temp_free_i32(tmp2);
8034 if (rd != 15) {
8035 tmp2 = load_reg(s, rd);
8036 tcg_gen_add_i32(tmp, tmp, tmp2);
8037 tcg_temp_free_i32(tmp2);
8039 store_reg(s, rn, tmp);
8040 break;
8041 case 0x20: case 0x24: case 0x28: case 0x2c:
8042 /* Bitfield insert/clear. */
8043 ARCH(6T2);
8044 shift = (insn >> 7) & 0x1f;
8045 i = (insn >> 16) & 0x1f;
8046 i = i + 1 - shift;
8047 if (rm == 15) {
8048 tmp = tcg_temp_new_i32();
8049 tcg_gen_movi_i32(tmp, 0);
8050 } else {
8051 tmp = load_reg(s, rm);
8053 if (i != 32) {
8054 tmp2 = load_reg(s, rd);
8055 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
8056 tcg_temp_free_i32(tmp2);
8058 store_reg(s, rd, tmp);
8059 break;
8060 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8061 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
8062 ARCH(6T2);
8063 tmp = load_reg(s, rm);
8064 shift = (insn >> 7) & 0x1f;
8065 i = ((insn >> 16) & 0x1f) + 1;
8066 if (shift + i > 32)
8067 goto illegal_op;
8068 if (i < 32) {
8069 if (op1 & 0x20) {
8070 gen_ubfx(tmp, shift, (1u << i) - 1);
8071 } else {
8072 gen_sbfx(tmp, shift, i);
8075 store_reg(s, rd, tmp);
8076 break;
8077 default:
8078 goto illegal_op;
8080 break;
8082 break;
8084 do_ldst:
8085 /* Check for undefined extension instructions
8086 * per the ARM Bible IE:
8087 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
8089 sh = (0xf << 20) | (0xf << 4);
8090 if (op1 == 0x7 && ((insn & sh) == sh))
8092 goto illegal_op;
8094 /* load/store byte/word */
8095 rn = (insn >> 16) & 0xf;
8096 rd = (insn >> 12) & 0xf;
8097 tmp2 = load_reg(s, rn);
8098 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
8099 if (insn & (1 << 24))
8100 gen_add_data_offset(s, insn, tmp2);
8101 if (insn & (1 << 20)) {
8102 /* load */
8103 tmp = tcg_temp_new_i32();
8104 if (insn & (1 << 22)) {
8105 gen_aa32_ld8u(tmp, tmp2, i);
8106 } else {
8107 gen_aa32_ld32u(tmp, tmp2, i);
8109 } else {
8110 /* store */
8111 tmp = load_reg(s, rd);
8112 if (insn & (1 << 22)) {
8113 gen_aa32_st8(tmp, tmp2, i);
8114 } else {
8115 gen_aa32_st32(tmp, tmp2, i);
8117 tcg_temp_free_i32(tmp);
8119 if (!(insn & (1 << 24))) {
8120 gen_add_data_offset(s, insn, tmp2);
8121 store_reg(s, rn, tmp2);
8122 } else if (insn & (1 << 21)) {
8123 store_reg(s, rn, tmp2);
8124 } else {
8125 tcg_temp_free_i32(tmp2);
8127 if (insn & (1 << 20)) {
8128 /* Complete the load. */
8129 store_reg_from_load(env, s, rd, tmp);
8131 break;
8132 case 0x08:
8133 case 0x09:
8135 int j, n, user, loaded_base;
8136 TCGv_i32 loaded_var;
8137 /* load/store multiple words */
8138 /* XXX: store correct base if write back */
8139 user = 0;
8140 if (insn & (1 << 22)) {
8141 if (IS_USER(s))
8142 goto illegal_op; /* only usable in supervisor mode */
8144 if ((insn & (1 << 15)) == 0)
8145 user = 1;
8147 rn = (insn >> 16) & 0xf;
8148 addr = load_reg(s, rn);
8150 /* compute total size */
8151 loaded_base = 0;
8152 TCGV_UNUSED_I32(loaded_var);
8153 n = 0;
8154 for(i=0;i<16;i++) {
8155 if (insn & (1 << i))
8156 n++;
8158 /* XXX: test invalid n == 0 case ? */
8159 if (insn & (1 << 23)) {
8160 if (insn & (1 << 24)) {
8161 /* pre increment */
8162 tcg_gen_addi_i32(addr, addr, 4);
8163 } else {
8164 /* post increment */
8166 } else {
8167 if (insn & (1 << 24)) {
8168 /* pre decrement */
8169 tcg_gen_addi_i32(addr, addr, -(n * 4));
8170 } else {
8171 /* post decrement */
8172 if (n != 1)
8173 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8176 j = 0;
8177 for(i=0;i<16;i++) {
8178 if (insn & (1 << i)) {
8179 if (insn & (1 << 20)) {
8180 /* load */
8181 tmp = tcg_temp_new_i32();
8182 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8183 if (user) {
8184 tmp2 = tcg_const_i32(i);
8185 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
8186 tcg_temp_free_i32(tmp2);
8187 tcg_temp_free_i32(tmp);
8188 } else if (i == rn) {
8189 loaded_var = tmp;
8190 loaded_base = 1;
8191 } else {
8192 store_reg_from_load(env, s, i, tmp);
8194 } else {
8195 /* store */
8196 if (i == 15) {
8197 /* special case: r15 = PC + 8 */
8198 val = (long)s->pc + 4;
8199 tmp = tcg_temp_new_i32();
8200 tcg_gen_movi_i32(tmp, val);
8201 } else if (user) {
8202 tmp = tcg_temp_new_i32();
8203 tmp2 = tcg_const_i32(i);
8204 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
8205 tcg_temp_free_i32(tmp2);
8206 } else {
8207 tmp = load_reg(s, i);
8209 gen_aa32_st32(tmp, addr, IS_USER(s));
8210 tcg_temp_free_i32(tmp);
8212 j++;
8213 /* no need to add after the last transfer */
8214 if (j != n)
8215 tcg_gen_addi_i32(addr, addr, 4);
8218 if (insn & (1 << 21)) {
8219 /* write back */
8220 if (insn & (1 << 23)) {
8221 if (insn & (1 << 24)) {
8222 /* pre increment */
8223 } else {
8224 /* post increment */
8225 tcg_gen_addi_i32(addr, addr, 4);
8227 } else {
8228 if (insn & (1 << 24)) {
8229 /* pre decrement */
8230 if (n != 1)
8231 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8232 } else {
8233 /* post decrement */
8234 tcg_gen_addi_i32(addr, addr, -(n * 4));
8237 store_reg(s, rn, addr);
8238 } else {
8239 tcg_temp_free_i32(addr);
8241 if (loaded_base) {
8242 store_reg(s, rn, loaded_var);
8244 if ((insn & (1 << 22)) && !user) {
8245 /* Restore CPSR from SPSR. */
8246 tmp = load_cpu_field(spsr);
8247 gen_set_cpsr(tmp, 0xffffffff);
8248 tcg_temp_free_i32(tmp);
8249 s->is_jmp = DISAS_UPDATE;
8252 break;
8253 case 0xa:
8254 case 0xb:
8256 int32_t offset;
8258 /* branch (and link) */
8259 val = (int32_t)s->pc;
8260 if (insn & (1 << 24)) {
8261 tmp = tcg_temp_new_i32();
8262 tcg_gen_movi_i32(tmp, val);
8263 store_reg(s, 14, tmp);
8265 offset = sextract32(insn << 2, 0, 26);
8266 val += offset + 4;
8267 gen_jmp(s, val);
8269 break;
8270 case 0xc:
8271 case 0xd:
8272 case 0xe:
8273 if (((insn >> 8) & 0xe) == 10) {
8274 /* VFP. */
8275 if (disas_vfp_insn(env, s, insn)) {
8276 goto illegal_op;
8278 } else if (disas_coproc_insn(env, s, insn)) {
8279 /* Coprocessor. */
8280 goto illegal_op;
8282 break;
8283 case 0xf:
8284 /* swi */
8285 gen_set_pc_im(s, s->pc);
8286 s->is_jmp = DISAS_SWI;
8287 break;
8288 default:
8289 illegal_op:
8290 gen_exception_insn(s, 4, EXCP_UDEF);
8291 break;
8296 /* Return true if this is a Thumb-2 logical op. */
8297 static int
8298 thumb2_logic_op(int op)
8300 return (op < 8);
8303 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
8304 then set condition code flags based on the result of the operation.
8305 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
8306 to the high bit of T1.
8307 Returns zero if the opcode is valid. */
8309 static int
8310 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
8311 TCGv_i32 t0, TCGv_i32 t1)
8313 int logic_cc;
8315 logic_cc = 0;
8316 switch (op) {
8317 case 0: /* and */
8318 tcg_gen_and_i32(t0, t0, t1);
8319 logic_cc = conds;
8320 break;
8321 case 1: /* bic */
8322 tcg_gen_andc_i32(t0, t0, t1);
8323 logic_cc = conds;
8324 break;
8325 case 2: /* orr */
8326 tcg_gen_or_i32(t0, t0, t1);
8327 logic_cc = conds;
8328 break;
8329 case 3: /* orn */
8330 tcg_gen_orc_i32(t0, t0, t1);
8331 logic_cc = conds;
8332 break;
8333 case 4: /* eor */
8334 tcg_gen_xor_i32(t0, t0, t1);
8335 logic_cc = conds;
8336 break;
8337 case 8: /* add */
8338 if (conds)
8339 gen_add_CC(t0, t0, t1);
8340 else
8341 tcg_gen_add_i32(t0, t0, t1);
8342 break;
8343 case 10: /* adc */
8344 if (conds)
8345 gen_adc_CC(t0, t0, t1);
8346 else
8347 gen_adc(t0, t1);
8348 break;
8349 case 11: /* sbc */
8350 if (conds) {
8351 gen_sbc_CC(t0, t0, t1);
8352 } else {
8353 gen_sub_carry(t0, t0, t1);
8355 break;
8356 case 13: /* sub */
8357 if (conds)
8358 gen_sub_CC(t0, t0, t1);
8359 else
8360 tcg_gen_sub_i32(t0, t0, t1);
8361 break;
8362 case 14: /* rsb */
8363 if (conds)
8364 gen_sub_CC(t0, t1, t0);
8365 else
8366 tcg_gen_sub_i32(t0, t1, t0);
8367 break;
8368 default: /* 5, 6, 7, 9, 12, 15. */
8369 return 1;
8371 if (logic_cc) {
8372 gen_logic_CC(t0);
8373 if (shifter_out)
8374 gen_set_CF_bit31(t1);
8376 return 0;
8379 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
8380 is not legal. */
8381 static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
8383 uint32_t insn, imm, shift, offset;
8384 uint32_t rd, rn, rm, rs;
8385 TCGv_i32 tmp;
8386 TCGv_i32 tmp2;
8387 TCGv_i32 tmp3;
8388 TCGv_i32 addr;
8389 TCGv_i64 tmp64;
8390 int op;
8391 int shiftop;
8392 int conds;
8393 int logic_cc;
8395 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
8396 || arm_feature (env, ARM_FEATURE_M))) {
8397 /* Thumb-1 cores may need to treat bl and blx as a pair of
8398 16-bit instructions to get correct prefetch abort behavior. */
8399 insn = insn_hw1;
8400 if ((insn & (1 << 12)) == 0) {
8401 ARCH(5);
8402 /* Second half of blx. */
8403 offset = ((insn & 0x7ff) << 1);
8404 tmp = load_reg(s, 14);
8405 tcg_gen_addi_i32(tmp, tmp, offset);
8406 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8408 tmp2 = tcg_temp_new_i32();
8409 tcg_gen_movi_i32(tmp2, s->pc | 1);
8410 store_reg(s, 14, tmp2);
8411 gen_bx(s, tmp);
8412 return 0;
8414 if (insn & (1 << 11)) {
8415 /* Second half of bl. */
8416 offset = ((insn & 0x7ff) << 1) | 1;
8417 tmp = load_reg(s, 14);
8418 tcg_gen_addi_i32(tmp, tmp, offset);
8420 tmp2 = tcg_temp_new_i32();
8421 tcg_gen_movi_i32(tmp2, s->pc | 1);
8422 store_reg(s, 14, tmp2);
8423 gen_bx(s, tmp);
8424 return 0;
8426 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
8427 /* Instruction spans a page boundary. Implement it as two
8428 16-bit instructions in case the second half causes an
8429 prefetch abort. */
8430 offset = ((int32_t)insn << 21) >> 9;
8431 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
8432 return 0;
8434 /* Fall through to 32-bit decode. */
8437 insn = arm_lduw_code(env, s->pc, s->bswap_code);
8438 s->pc += 2;
8439 insn |= (uint32_t)insn_hw1 << 16;
8441 if ((insn & 0xf800e800) != 0xf000e800) {
8442 ARCH(6T2);
8445 rn = (insn >> 16) & 0xf;
8446 rs = (insn >> 12) & 0xf;
8447 rd = (insn >> 8) & 0xf;
8448 rm = insn & 0xf;
8449 switch ((insn >> 25) & 0xf) {
8450 case 0: case 1: case 2: case 3:
8451 /* 16-bit instructions. Should never happen. */
8452 abort();
8453 case 4:
8454 if (insn & (1 << 22)) {
8455 /* Other load/store, table branch. */
8456 if (insn & 0x01200000) {
8457 /* Load/store doubleword. */
8458 if (rn == 15) {
8459 addr = tcg_temp_new_i32();
8460 tcg_gen_movi_i32(addr, s->pc & ~3);
8461 } else {
8462 addr = load_reg(s, rn);
8464 offset = (insn & 0xff) * 4;
8465 if ((insn & (1 << 23)) == 0)
8466 offset = -offset;
8467 if (insn & (1 << 24)) {
8468 tcg_gen_addi_i32(addr, addr, offset);
8469 offset = 0;
8471 if (insn & (1 << 20)) {
8472 /* ldrd */
8473 tmp = tcg_temp_new_i32();
8474 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8475 store_reg(s, rs, tmp);
8476 tcg_gen_addi_i32(addr, addr, 4);
8477 tmp = tcg_temp_new_i32();
8478 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8479 store_reg(s, rd, tmp);
8480 } else {
8481 /* strd */
8482 tmp = load_reg(s, rs);
8483 gen_aa32_st32(tmp, addr, IS_USER(s));
8484 tcg_temp_free_i32(tmp);
8485 tcg_gen_addi_i32(addr, addr, 4);
8486 tmp = load_reg(s, rd);
8487 gen_aa32_st32(tmp, addr, IS_USER(s));
8488 tcg_temp_free_i32(tmp);
8490 if (insn & (1 << 21)) {
8491 /* Base writeback. */
8492 if (rn == 15)
8493 goto illegal_op;
8494 tcg_gen_addi_i32(addr, addr, offset - 4);
8495 store_reg(s, rn, addr);
8496 } else {
8497 tcg_temp_free_i32(addr);
8499 } else if ((insn & (1 << 23)) == 0) {
8500 /* Load/store exclusive word. */
8501 addr = tcg_temp_local_new_i32();
8502 load_reg_var(s, addr, rn);
8503 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
8504 if (insn & (1 << 20)) {
8505 gen_load_exclusive(s, rs, 15, addr, 2);
8506 } else {
8507 gen_store_exclusive(s, rd, rs, 15, addr, 2);
8509 tcg_temp_free_i32(addr);
8510 } else if ((insn & (7 << 5)) == 0) {
8511 /* Table Branch. */
8512 if (rn == 15) {
8513 addr = tcg_temp_new_i32();
8514 tcg_gen_movi_i32(addr, s->pc);
8515 } else {
8516 addr = load_reg(s, rn);
8518 tmp = load_reg(s, rm);
8519 tcg_gen_add_i32(addr, addr, tmp);
8520 if (insn & (1 << 4)) {
8521 /* tbh */
8522 tcg_gen_add_i32(addr, addr, tmp);
8523 tcg_temp_free_i32(tmp);
8524 tmp = tcg_temp_new_i32();
8525 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8526 } else { /* tbb */
8527 tcg_temp_free_i32(tmp);
8528 tmp = tcg_temp_new_i32();
8529 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8531 tcg_temp_free_i32(addr);
8532 tcg_gen_shli_i32(tmp, tmp, 1);
8533 tcg_gen_addi_i32(tmp, tmp, s->pc);
8534 store_reg(s, 15, tmp);
8535 } else {
8536 int op2 = (insn >> 6) & 0x3;
8537 op = (insn >> 4) & 0x3;
8538 switch (op2) {
8539 case 0:
8540 goto illegal_op;
8541 case 1:
8542 /* Load/store exclusive byte/halfword/doubleword */
8543 if (op == 2) {
8544 goto illegal_op;
8546 ARCH(7);
8547 break;
8548 case 2:
8549 /* Load-acquire/store-release */
8550 if (op == 3) {
8551 goto illegal_op;
8553 /* Fall through */
8554 case 3:
8555 /* Load-acquire/store-release exclusive */
8556 ARCH(8);
8557 break;
8559 addr = tcg_temp_local_new_i32();
8560 load_reg_var(s, addr, rn);
8561 if (!(op2 & 1)) {
8562 if (insn & (1 << 20)) {
8563 tmp = tcg_temp_new_i32();
8564 switch (op) {
8565 case 0: /* ldab */
8566 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8567 break;
8568 case 1: /* ldah */
8569 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8570 break;
8571 case 2: /* lda */
8572 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8573 break;
8574 default:
8575 abort();
8577 store_reg(s, rs, tmp);
8578 } else {
8579 tmp = load_reg(s, rs);
8580 switch (op) {
8581 case 0: /* stlb */
8582 gen_aa32_st8(tmp, addr, IS_USER(s));
8583 break;
8584 case 1: /* stlh */
8585 gen_aa32_st16(tmp, addr, IS_USER(s));
8586 break;
8587 case 2: /* stl */
8588 gen_aa32_st32(tmp, addr, IS_USER(s));
8589 break;
8590 default:
8591 abort();
8593 tcg_temp_free_i32(tmp);
8595 } else if (insn & (1 << 20)) {
8596 gen_load_exclusive(s, rs, rd, addr, op);
8597 } else {
8598 gen_store_exclusive(s, rm, rs, rd, addr, op);
8600 tcg_temp_free_i32(addr);
8602 } else {
8603 /* Load/store multiple, RFE, SRS. */
8604 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
8605 /* RFE, SRS: not available in user mode or on M profile */
8606 if (IS_USER(s) || IS_M(env)) {
8607 goto illegal_op;
8609 if (insn & (1 << 20)) {
8610 /* rfe */
8611 addr = load_reg(s, rn);
8612 if ((insn & (1 << 24)) == 0)
8613 tcg_gen_addi_i32(addr, addr, -8);
8614 /* Load PC into tmp and CPSR into tmp2. */
8615 tmp = tcg_temp_new_i32();
8616 gen_aa32_ld32u(tmp, addr, 0);
8617 tcg_gen_addi_i32(addr, addr, 4);
8618 tmp2 = tcg_temp_new_i32();
8619 gen_aa32_ld32u(tmp2, addr, 0);
8620 if (insn & (1 << 21)) {
8621 /* Base writeback. */
8622 if (insn & (1 << 24)) {
8623 tcg_gen_addi_i32(addr, addr, 4);
8624 } else {
8625 tcg_gen_addi_i32(addr, addr, -4);
8627 store_reg(s, rn, addr);
8628 } else {
8629 tcg_temp_free_i32(addr);
8631 gen_rfe(s, tmp, tmp2);
8632 } else {
8633 /* srs */
8634 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
8635 insn & (1 << 21));
8637 } else {
8638 int i, loaded_base = 0;
8639 TCGv_i32 loaded_var;
8640 /* Load/store multiple. */
8641 addr = load_reg(s, rn);
8642 offset = 0;
8643 for (i = 0; i < 16; i++) {
8644 if (insn & (1 << i))
8645 offset += 4;
8647 if (insn & (1 << 24)) {
8648 tcg_gen_addi_i32(addr, addr, -offset);
8651 TCGV_UNUSED_I32(loaded_var);
8652 for (i = 0; i < 16; i++) {
8653 if ((insn & (1 << i)) == 0)
8654 continue;
8655 if (insn & (1 << 20)) {
8656 /* Load. */
8657 tmp = tcg_temp_new_i32();
8658 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8659 if (i == 15) {
8660 gen_bx(s, tmp);
8661 } else if (i == rn) {
8662 loaded_var = tmp;
8663 loaded_base = 1;
8664 } else {
8665 store_reg(s, i, tmp);
8667 } else {
8668 /* Store. */
8669 tmp = load_reg(s, i);
8670 gen_aa32_st32(tmp, addr, IS_USER(s));
8671 tcg_temp_free_i32(tmp);
8673 tcg_gen_addi_i32(addr, addr, 4);
8675 if (loaded_base) {
8676 store_reg(s, rn, loaded_var);
8678 if (insn & (1 << 21)) {
8679 /* Base register writeback. */
8680 if (insn & (1 << 24)) {
8681 tcg_gen_addi_i32(addr, addr, -offset);
8683 /* Fault if writeback register is in register list. */
8684 if (insn & (1 << rn))
8685 goto illegal_op;
8686 store_reg(s, rn, addr);
8687 } else {
8688 tcg_temp_free_i32(addr);
8692 break;
8693 case 5:
8695 op = (insn >> 21) & 0xf;
8696 if (op == 6) {
8697 /* Halfword pack. */
8698 tmp = load_reg(s, rn);
8699 tmp2 = load_reg(s, rm);
8700 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
8701 if (insn & (1 << 5)) {
8702 /* pkhtb */
8703 if (shift == 0)
8704 shift = 31;
8705 tcg_gen_sari_i32(tmp2, tmp2, shift);
8706 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8707 tcg_gen_ext16u_i32(tmp2, tmp2);
8708 } else {
8709 /* pkhbt */
8710 if (shift)
8711 tcg_gen_shli_i32(tmp2, tmp2, shift);
8712 tcg_gen_ext16u_i32(tmp, tmp);
8713 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8715 tcg_gen_or_i32(tmp, tmp, tmp2);
8716 tcg_temp_free_i32(tmp2);
8717 store_reg(s, rd, tmp);
8718 } else {
8719 /* Data processing register constant shift. */
8720 if (rn == 15) {
8721 tmp = tcg_temp_new_i32();
8722 tcg_gen_movi_i32(tmp, 0);
8723 } else {
8724 tmp = load_reg(s, rn);
8726 tmp2 = load_reg(s, rm);
8728 shiftop = (insn >> 4) & 3;
8729 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8730 conds = (insn & (1 << 20)) != 0;
8731 logic_cc = (conds && thumb2_logic_op(op));
8732 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8733 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
8734 goto illegal_op;
8735 tcg_temp_free_i32(tmp2);
8736 if (rd != 15) {
8737 store_reg(s, rd, tmp);
8738 } else {
8739 tcg_temp_free_i32(tmp);
8742 break;
8743 case 13: /* Misc data processing. */
8744 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
8745 if (op < 4 && (insn & 0xf000) != 0xf000)
8746 goto illegal_op;
8747 switch (op) {
8748 case 0: /* Register controlled shift. */
8749 tmp = load_reg(s, rn);
8750 tmp2 = load_reg(s, rm);
8751 if ((insn & 0x70) != 0)
8752 goto illegal_op;
8753 op = (insn >> 21) & 3;
8754 logic_cc = (insn & (1 << 20)) != 0;
8755 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
8756 if (logic_cc)
8757 gen_logic_CC(tmp);
8758 store_reg_bx(env, s, rd, tmp);
8759 break;
8760 case 1: /* Sign/zero extend. */
8761 tmp = load_reg(s, rm);
8762 shift = (insn >> 4) & 3;
8763 /* ??? In many cases it's not necessary to do a
8764 rotate, a shift is sufficient. */
8765 if (shift != 0)
8766 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8767 op = (insn >> 20) & 7;
8768 switch (op) {
8769 case 0: gen_sxth(tmp); break;
8770 case 1: gen_uxth(tmp); break;
8771 case 2: gen_sxtb16(tmp); break;
8772 case 3: gen_uxtb16(tmp); break;
8773 case 4: gen_sxtb(tmp); break;
8774 case 5: gen_uxtb(tmp); break;
8775 default: goto illegal_op;
8777 if (rn != 15) {
8778 tmp2 = load_reg(s, rn);
8779 if ((op >> 1) == 1) {
8780 gen_add16(tmp, tmp2);
8781 } else {
8782 tcg_gen_add_i32(tmp, tmp, tmp2);
8783 tcg_temp_free_i32(tmp2);
8786 store_reg(s, rd, tmp);
8787 break;
8788 case 2: /* SIMD add/subtract. */
8789 op = (insn >> 20) & 7;
8790 shift = (insn >> 4) & 7;
8791 if ((op & 3) == 3 || (shift & 3) == 3)
8792 goto illegal_op;
8793 tmp = load_reg(s, rn);
8794 tmp2 = load_reg(s, rm);
8795 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
8796 tcg_temp_free_i32(tmp2);
8797 store_reg(s, rd, tmp);
8798 break;
8799 case 3: /* Other data processing. */
8800 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
8801 if (op < 4) {
8802 /* Saturating add/subtract. */
8803 tmp = load_reg(s, rn);
8804 tmp2 = load_reg(s, rm);
8805 if (op & 1)
8806 gen_helper_double_saturate(tmp, cpu_env, tmp);
8807 if (op & 2)
8808 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
8809 else
8810 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
8811 tcg_temp_free_i32(tmp2);
8812 } else {
8813 tmp = load_reg(s, rn);
8814 switch (op) {
8815 case 0x0a: /* rbit */
8816 gen_helper_rbit(tmp, tmp);
8817 break;
8818 case 0x08: /* rev */
8819 tcg_gen_bswap32_i32(tmp, tmp);
8820 break;
8821 case 0x09: /* rev16 */
8822 gen_rev16(tmp);
8823 break;
8824 case 0x0b: /* revsh */
8825 gen_revsh(tmp);
8826 break;
8827 case 0x10: /* sel */
8828 tmp2 = load_reg(s, rm);
8829 tmp3 = tcg_temp_new_i32();
8830 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8831 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8832 tcg_temp_free_i32(tmp3);
8833 tcg_temp_free_i32(tmp2);
8834 break;
8835 case 0x18: /* clz */
8836 gen_helper_clz(tmp, tmp);
8837 break;
8838 default:
8839 goto illegal_op;
8842 store_reg(s, rd, tmp);
8843 break;
8844 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
8845 op = (insn >> 4) & 0xf;
8846 tmp = load_reg(s, rn);
8847 tmp2 = load_reg(s, rm);
8848 switch ((insn >> 20) & 7) {
8849 case 0: /* 32 x 32 -> 32 */
8850 tcg_gen_mul_i32(tmp, tmp, tmp2);
8851 tcg_temp_free_i32(tmp2);
8852 if (rs != 15) {
8853 tmp2 = load_reg(s, rs);
8854 if (op)
8855 tcg_gen_sub_i32(tmp, tmp2, tmp);
8856 else
8857 tcg_gen_add_i32(tmp, tmp, tmp2);
8858 tcg_temp_free_i32(tmp2);
8860 break;
8861 case 1: /* 16 x 16 -> 32 */
8862 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8863 tcg_temp_free_i32(tmp2);
8864 if (rs != 15) {
8865 tmp2 = load_reg(s, rs);
8866 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8867 tcg_temp_free_i32(tmp2);
8869 break;
8870 case 2: /* Dual multiply add. */
8871 case 4: /* Dual multiply subtract. */
8872 if (op)
8873 gen_swap_half(tmp2);
8874 gen_smul_dual(tmp, tmp2);
8875 if (insn & (1 << 22)) {
8876 /* This subtraction cannot overflow. */
8877 tcg_gen_sub_i32(tmp, tmp, tmp2);
8878 } else {
8879 /* This addition cannot overflow 32 bits;
8880 * however it may overflow considered as a signed
8881 * operation, in which case we must set the Q flag.
8883 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8885 tcg_temp_free_i32(tmp2);
8886 if (rs != 15)
8888 tmp2 = load_reg(s, rs);
8889 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8890 tcg_temp_free_i32(tmp2);
8892 break;
8893 case 3: /* 32 * 16 -> 32msb */
8894 if (op)
8895 tcg_gen_sari_i32(tmp2, tmp2, 16);
8896 else
8897 gen_sxth(tmp2);
8898 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8899 tcg_gen_shri_i64(tmp64, tmp64, 16);
8900 tmp = tcg_temp_new_i32();
8901 tcg_gen_trunc_i64_i32(tmp, tmp64);
8902 tcg_temp_free_i64(tmp64);
8903 if (rs != 15)
8905 tmp2 = load_reg(s, rs);
8906 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8907 tcg_temp_free_i32(tmp2);
8909 break;
8910 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8911 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8912 if (rs != 15) {
8913 tmp = load_reg(s, rs);
8914 if (insn & (1 << 20)) {
8915 tmp64 = gen_addq_msw(tmp64, tmp);
8916 } else {
8917 tmp64 = gen_subq_msw(tmp64, tmp);
8920 if (insn & (1 << 4)) {
8921 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8923 tcg_gen_shri_i64(tmp64, tmp64, 32);
8924 tmp = tcg_temp_new_i32();
8925 tcg_gen_trunc_i64_i32(tmp, tmp64);
8926 tcg_temp_free_i64(tmp64);
8927 break;
8928 case 7: /* Unsigned sum of absolute differences. */
8929 gen_helper_usad8(tmp, tmp, tmp2);
8930 tcg_temp_free_i32(tmp2);
8931 if (rs != 15) {
8932 tmp2 = load_reg(s, rs);
8933 tcg_gen_add_i32(tmp, tmp, tmp2);
8934 tcg_temp_free_i32(tmp2);
8936 break;
8938 store_reg(s, rd, tmp);
8939 break;
8940 case 6: case 7: /* 64-bit multiply, Divide. */
8941 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
8942 tmp = load_reg(s, rn);
8943 tmp2 = load_reg(s, rm);
8944 if ((op & 0x50) == 0x10) {
8945 /* sdiv, udiv */
8946 if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
8947 goto illegal_op;
8949 if (op & 0x20)
8950 gen_helper_udiv(tmp, tmp, tmp2);
8951 else
8952 gen_helper_sdiv(tmp, tmp, tmp2);
8953 tcg_temp_free_i32(tmp2);
8954 store_reg(s, rd, tmp);
8955 } else if ((op & 0xe) == 0xc) {
8956 /* Dual multiply accumulate long. */
8957 if (op & 1)
8958 gen_swap_half(tmp2);
8959 gen_smul_dual(tmp, tmp2);
8960 if (op & 0x10) {
8961 tcg_gen_sub_i32(tmp, tmp, tmp2);
8962 } else {
8963 tcg_gen_add_i32(tmp, tmp, tmp2);
8965 tcg_temp_free_i32(tmp2);
8966 /* BUGFIX */
8967 tmp64 = tcg_temp_new_i64();
8968 tcg_gen_ext_i32_i64(tmp64, tmp);
8969 tcg_temp_free_i32(tmp);
8970 gen_addq(s, tmp64, rs, rd);
8971 gen_storeq_reg(s, rs, rd, tmp64);
8972 tcg_temp_free_i64(tmp64);
8973 } else {
8974 if (op & 0x20) {
8975 /* Unsigned 64-bit multiply */
8976 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8977 } else {
8978 if (op & 8) {
8979 /* smlalxy */
8980 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8981 tcg_temp_free_i32(tmp2);
8982 tmp64 = tcg_temp_new_i64();
8983 tcg_gen_ext_i32_i64(tmp64, tmp);
8984 tcg_temp_free_i32(tmp);
8985 } else {
8986 /* Signed 64-bit multiply */
8987 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8990 if (op & 4) {
8991 /* umaal */
8992 gen_addq_lo(s, tmp64, rs);
8993 gen_addq_lo(s, tmp64, rd);
8994 } else if (op & 0x40) {
8995 /* 64-bit accumulate. */
8996 gen_addq(s, tmp64, rs, rd);
8998 gen_storeq_reg(s, rs, rd, tmp64);
8999 tcg_temp_free_i64(tmp64);
9001 break;
9003 break;
9004 case 6: case 7: case 14: case 15:
9005 /* Coprocessor. */
9006 if (((insn >> 24) & 3) == 3) {
9007 /* Translate into the equivalent ARM encoding. */
9008 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
9009 if (disas_neon_data_insn(env, s, insn))
9010 goto illegal_op;
9011 } else if (((insn >> 8) & 0xe) == 10) {
9012 if (disas_vfp_insn(env, s, insn)) {
9013 goto illegal_op;
9015 } else {
9016 if (insn & (1 << 28))
9017 goto illegal_op;
9018 if (disas_coproc_insn (env, s, insn))
9019 goto illegal_op;
9021 break;
9022 case 8: case 9: case 10: case 11:
9023 if (insn & (1 << 15)) {
9024 /* Branches, misc control. */
9025 if (insn & 0x5000) {
9026 /* Unconditional branch. */
9027 /* signextend(hw1[10:0]) -> offset[:12]. */
9028 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
9029 /* hw1[10:0] -> offset[11:1]. */
9030 offset |= (insn & 0x7ff) << 1;
9031 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
9032 offset[24:22] already have the same value because of the
9033 sign extension above. */
9034 offset ^= ((~insn) & (1 << 13)) << 10;
9035 offset ^= ((~insn) & (1 << 11)) << 11;
9037 if (insn & (1 << 14)) {
9038 /* Branch and link. */
9039 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
9042 offset += s->pc;
9043 if (insn & (1 << 12)) {
9044 /* b/bl */
9045 gen_jmp(s, offset);
9046 } else {
9047 /* blx */
9048 offset &= ~(uint32_t)2;
9049 /* thumb2 bx, no need to check */
9050 gen_bx_im(s, offset);
9052 } else if (((insn >> 23) & 7) == 7) {
9053 /* Misc control */
9054 if (insn & (1 << 13))
9055 goto illegal_op;
9057 if (insn & (1 << 26)) {
9058 /* Secure monitor call (v6Z) */
9059 qemu_log_mask(LOG_UNIMP,
9060 "arm: unimplemented secure monitor call\n");
9061 goto illegal_op; /* not implemented. */
9062 } else {
9063 op = (insn >> 20) & 7;
9064 switch (op) {
9065 case 0: /* msr cpsr. */
9066 if (IS_M(env)) {
9067 tmp = load_reg(s, rn);
9068 addr = tcg_const_i32(insn & 0xff);
9069 gen_helper_v7m_msr(cpu_env, addr, tmp);
9070 tcg_temp_free_i32(addr);
9071 tcg_temp_free_i32(tmp);
9072 gen_lookup_tb(s);
9073 break;
9075 /* fall through */
9076 case 1: /* msr spsr. */
9077 if (IS_M(env))
9078 goto illegal_op;
9079 tmp = load_reg(s, rn);
9080 if (gen_set_psr(s,
9081 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
9082 op == 1, tmp))
9083 goto illegal_op;
9084 break;
9085 case 2: /* cps, nop-hint. */
9086 if (((insn >> 8) & 7) == 0) {
9087 gen_nop_hint(s, insn & 0xff);
9089 /* Implemented as NOP in user mode. */
9090 if (IS_USER(s))
9091 break;
9092 offset = 0;
9093 imm = 0;
9094 if (insn & (1 << 10)) {
9095 if (insn & (1 << 7))
9096 offset |= CPSR_A;
9097 if (insn & (1 << 6))
9098 offset |= CPSR_I;
9099 if (insn & (1 << 5))
9100 offset |= CPSR_F;
9101 if (insn & (1 << 9))
9102 imm = CPSR_A | CPSR_I | CPSR_F;
9104 if (insn & (1 << 8)) {
9105 offset |= 0x1f;
9106 imm |= (insn & 0x1f);
9108 if (offset) {
9109 gen_set_psr_im(s, offset, 0, imm);
9111 break;
9112 case 3: /* Special control operations. */
9113 ARCH(7);
9114 op = (insn >> 4) & 0xf;
9115 switch (op) {
9116 case 2: /* clrex */
9117 gen_clrex(s);
9118 break;
9119 case 4: /* dsb */
9120 case 5: /* dmb */
9121 case 6: /* isb */
9122 /* These execute as NOPs. */
9123 break;
9124 default:
9125 goto illegal_op;
9127 break;
9128 case 4: /* bxj */
9129 /* Trivial implementation equivalent to bx. */
9130 tmp = load_reg(s, rn);
9131 gen_bx(s, tmp);
9132 break;
9133 case 5: /* Exception return. */
9134 if (IS_USER(s)) {
9135 goto illegal_op;
9137 if (rn != 14 || rd != 15) {
9138 goto illegal_op;
9140 tmp = load_reg(s, rn);
9141 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
9142 gen_exception_return(s, tmp);
9143 break;
9144 case 6: /* mrs cpsr. */
9145 tmp = tcg_temp_new_i32();
9146 if (IS_M(env)) {
9147 addr = tcg_const_i32(insn & 0xff);
9148 gen_helper_v7m_mrs(tmp, cpu_env, addr);
9149 tcg_temp_free_i32(addr);
9150 } else {
9151 gen_helper_cpsr_read(tmp, cpu_env);
9153 store_reg(s, rd, tmp);
9154 break;
9155 case 7: /* mrs spsr. */
9156 /* Not accessible in user mode. */
9157 if (IS_USER(s) || IS_M(env))
9158 goto illegal_op;
9159 tmp = load_cpu_field(spsr);
9160 store_reg(s, rd, tmp);
9161 break;
9164 } else {
9165 /* Conditional branch. */
9166 op = (insn >> 22) & 0xf;
9167 /* Generate a conditional jump to next instruction. */
9168 s->condlabel = gen_new_label();
9169 arm_gen_test_cc(op ^ 1, s->condlabel);
9170 s->condjmp = 1;
9172 /* offset[11:1] = insn[10:0] */
9173 offset = (insn & 0x7ff) << 1;
9174 /* offset[17:12] = insn[21:16]. */
9175 offset |= (insn & 0x003f0000) >> 4;
9176 /* offset[31:20] = insn[26]. */
9177 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
9178 /* offset[18] = insn[13]. */
9179 offset |= (insn & (1 << 13)) << 5;
9180 /* offset[19] = insn[11]. */
9181 offset |= (insn & (1 << 11)) << 8;
9183 /* jump to the offset */
9184 gen_jmp(s, s->pc + offset);
9186 } else {
9187 /* Data processing immediate. */
9188 if (insn & (1 << 25)) {
9189 if (insn & (1 << 24)) {
9190 if (insn & (1 << 20))
9191 goto illegal_op;
9192 /* Bitfield/Saturate. */
9193 op = (insn >> 21) & 7;
9194 imm = insn & 0x1f;
9195 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9196 if (rn == 15) {
9197 tmp = tcg_temp_new_i32();
9198 tcg_gen_movi_i32(tmp, 0);
9199 } else {
9200 tmp = load_reg(s, rn);
9202 switch (op) {
9203 case 2: /* Signed bitfield extract. */
9204 imm++;
9205 if (shift + imm > 32)
9206 goto illegal_op;
9207 if (imm < 32)
9208 gen_sbfx(tmp, shift, imm);
9209 break;
9210 case 6: /* Unsigned bitfield extract. */
9211 imm++;
9212 if (shift + imm > 32)
9213 goto illegal_op;
9214 if (imm < 32)
9215 gen_ubfx(tmp, shift, (1u << imm) - 1);
9216 break;
9217 case 3: /* Bitfield insert/clear. */
9218 if (imm < shift)
9219 goto illegal_op;
9220 imm = imm + 1 - shift;
9221 if (imm != 32) {
9222 tmp2 = load_reg(s, rd);
9223 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
9224 tcg_temp_free_i32(tmp2);
9226 break;
9227 case 7:
9228 goto illegal_op;
9229 default: /* Saturate. */
9230 if (shift) {
9231 if (op & 1)
9232 tcg_gen_sari_i32(tmp, tmp, shift);
9233 else
9234 tcg_gen_shli_i32(tmp, tmp, shift);
9236 tmp2 = tcg_const_i32(imm);
9237 if (op & 4) {
9238 /* Unsigned. */
9239 if ((op & 1) && shift == 0)
9240 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9241 else
9242 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9243 } else {
9244 /* Signed. */
9245 if ((op & 1) && shift == 0)
9246 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9247 else
9248 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9250 tcg_temp_free_i32(tmp2);
9251 break;
9253 store_reg(s, rd, tmp);
9254 } else {
9255 imm = ((insn & 0x04000000) >> 15)
9256 | ((insn & 0x7000) >> 4) | (insn & 0xff);
9257 if (insn & (1 << 22)) {
9258 /* 16-bit immediate. */
9259 imm |= (insn >> 4) & 0xf000;
9260 if (insn & (1 << 23)) {
9261 /* movt */
9262 tmp = load_reg(s, rd);
9263 tcg_gen_ext16u_i32(tmp, tmp);
9264 tcg_gen_ori_i32(tmp, tmp, imm << 16);
9265 } else {
9266 /* movw */
9267 tmp = tcg_temp_new_i32();
9268 tcg_gen_movi_i32(tmp, imm);
9270 } else {
9271 /* Add/sub 12-bit immediate. */
9272 if (rn == 15) {
9273 offset = s->pc & ~(uint32_t)3;
9274 if (insn & (1 << 23))
9275 offset -= imm;
9276 else
9277 offset += imm;
9278 tmp = tcg_temp_new_i32();
9279 tcg_gen_movi_i32(tmp, offset);
9280 } else {
9281 tmp = load_reg(s, rn);
9282 if (insn & (1 << 23))
9283 tcg_gen_subi_i32(tmp, tmp, imm);
9284 else
9285 tcg_gen_addi_i32(tmp, tmp, imm);
9288 store_reg(s, rd, tmp);
9290 } else {
9291 int shifter_out = 0;
9292 /* modified 12-bit immediate. */
9293 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
9294 imm = (insn & 0xff);
9295 switch (shift) {
9296 case 0: /* XY */
9297 /* Nothing to do. */
9298 break;
9299 case 1: /* 00XY00XY */
9300 imm |= imm << 16;
9301 break;
9302 case 2: /* XY00XY00 */
9303 imm |= imm << 16;
9304 imm <<= 8;
9305 break;
9306 case 3: /* XYXYXYXY */
9307 imm |= imm << 16;
9308 imm |= imm << 8;
9309 break;
9310 default: /* Rotated constant. */
9311 shift = (shift << 1) | (imm >> 7);
9312 imm |= 0x80;
9313 imm = imm << (32 - shift);
9314 shifter_out = 1;
9315 break;
9317 tmp2 = tcg_temp_new_i32();
9318 tcg_gen_movi_i32(tmp2, imm);
9319 rn = (insn >> 16) & 0xf;
9320 if (rn == 15) {
9321 tmp = tcg_temp_new_i32();
9322 tcg_gen_movi_i32(tmp, 0);
9323 } else {
9324 tmp = load_reg(s, rn);
9326 op = (insn >> 21) & 0xf;
9327 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
9328 shifter_out, tmp, tmp2))
9329 goto illegal_op;
9330 tcg_temp_free_i32(tmp2);
9331 rd = (insn >> 8) & 0xf;
9332 if (rd != 15) {
9333 store_reg(s, rd, tmp);
9334 } else {
9335 tcg_temp_free_i32(tmp);
9339 break;
9340 case 12: /* Load/store single data item. */
9342 int postinc = 0;
9343 int writeback = 0;
9344 int user;
9345 if ((insn & 0x01100000) == 0x01000000) {
9346 if (disas_neon_ls_insn(env, s, insn))
9347 goto illegal_op;
9348 break;
9350 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
9351 if (rs == 15) {
9352 if (!(insn & (1 << 20))) {
9353 goto illegal_op;
9355 if (op != 2) {
9356 /* Byte or halfword load space with dest == r15 : memory hints.
9357 * Catch them early so we don't emit pointless addressing code.
9358 * This space is a mix of:
9359 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
9360 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
9361 * cores)
9362 * unallocated hints, which must be treated as NOPs
9363 * UNPREDICTABLE space, which we NOP or UNDEF depending on
9364 * which is easiest for the decoding logic
9365 * Some space which must UNDEF
9367 int op1 = (insn >> 23) & 3;
9368 int op2 = (insn >> 6) & 0x3f;
9369 if (op & 2) {
9370 goto illegal_op;
9372 if (rn == 15) {
9373 /* UNPREDICTABLE, unallocated hint or
9374 * PLD/PLDW/PLI (literal)
9376 return 0;
9378 if (op1 & 1) {
9379 return 0; /* PLD/PLDW/PLI or unallocated hint */
9381 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
9382 return 0; /* PLD/PLDW/PLI or unallocated hint */
9384 /* UNDEF space, or an UNPREDICTABLE */
9385 return 1;
9388 user = IS_USER(s);
9389 if (rn == 15) {
9390 addr = tcg_temp_new_i32();
9391 /* PC relative. */
9392 /* s->pc has already been incremented by 4. */
9393 imm = s->pc & 0xfffffffc;
9394 if (insn & (1 << 23))
9395 imm += insn & 0xfff;
9396 else
9397 imm -= insn & 0xfff;
9398 tcg_gen_movi_i32(addr, imm);
9399 } else {
9400 addr = load_reg(s, rn);
9401 if (insn & (1 << 23)) {
9402 /* Positive offset. */
9403 imm = insn & 0xfff;
9404 tcg_gen_addi_i32(addr, addr, imm);
9405 } else {
9406 imm = insn & 0xff;
9407 switch ((insn >> 8) & 0xf) {
9408 case 0x0: /* Shifted Register. */
9409 shift = (insn >> 4) & 0xf;
9410 if (shift > 3) {
9411 tcg_temp_free_i32(addr);
9412 goto illegal_op;
9414 tmp = load_reg(s, rm);
9415 if (shift)
9416 tcg_gen_shli_i32(tmp, tmp, shift);
9417 tcg_gen_add_i32(addr, addr, tmp);
9418 tcg_temp_free_i32(tmp);
9419 break;
9420 case 0xc: /* Negative offset. */
9421 tcg_gen_addi_i32(addr, addr, -imm);
9422 break;
9423 case 0xe: /* User privilege. */
9424 tcg_gen_addi_i32(addr, addr, imm);
9425 user = 1;
9426 break;
9427 case 0x9: /* Post-decrement. */
9428 imm = -imm;
9429 /* Fall through. */
9430 case 0xb: /* Post-increment. */
9431 postinc = 1;
9432 writeback = 1;
9433 break;
9434 case 0xd: /* Pre-decrement. */
9435 imm = -imm;
9436 /* Fall through. */
9437 case 0xf: /* Pre-increment. */
9438 tcg_gen_addi_i32(addr, addr, imm);
9439 writeback = 1;
9440 break;
9441 default:
9442 tcg_temp_free_i32(addr);
9443 goto illegal_op;
9447 if (insn & (1 << 20)) {
9448 /* Load. */
9449 tmp = tcg_temp_new_i32();
9450 switch (op) {
9451 case 0:
9452 gen_aa32_ld8u(tmp, addr, user);
9453 break;
9454 case 4:
9455 gen_aa32_ld8s(tmp, addr, user);
9456 break;
9457 case 1:
9458 gen_aa32_ld16u(tmp, addr, user);
9459 break;
9460 case 5:
9461 gen_aa32_ld16s(tmp, addr, user);
9462 break;
9463 case 2:
9464 gen_aa32_ld32u(tmp, addr, user);
9465 break;
9466 default:
9467 tcg_temp_free_i32(tmp);
9468 tcg_temp_free_i32(addr);
9469 goto illegal_op;
9471 if (rs == 15) {
9472 gen_bx(s, tmp);
9473 } else {
9474 store_reg(s, rs, tmp);
9476 } else {
9477 /* Store. */
9478 tmp = load_reg(s, rs);
9479 switch (op) {
9480 case 0:
9481 gen_aa32_st8(tmp, addr, user);
9482 break;
9483 case 1:
9484 gen_aa32_st16(tmp, addr, user);
9485 break;
9486 case 2:
9487 gen_aa32_st32(tmp, addr, user);
9488 break;
9489 default:
9490 tcg_temp_free_i32(tmp);
9491 tcg_temp_free_i32(addr);
9492 goto illegal_op;
9494 tcg_temp_free_i32(tmp);
9496 if (postinc)
9497 tcg_gen_addi_i32(addr, addr, imm);
9498 if (writeback) {
9499 store_reg(s, rn, addr);
9500 } else {
9501 tcg_temp_free_i32(addr);
9504 break;
9505 default:
9506 goto illegal_op;
9508 return 0;
9509 illegal_op:
9510 return 1;
9513 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
9515 uint32_t val, insn, op, rm, rn, rd, shift, cond;
9516 int32_t offset;
9517 int i;
9518 TCGv_i32 tmp;
9519 TCGv_i32 tmp2;
9520 TCGv_i32 addr;
9522 if (s->condexec_mask) {
9523 cond = s->condexec_cond;
9524 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
9525 s->condlabel = gen_new_label();
9526 arm_gen_test_cc(cond ^ 1, s->condlabel);
9527 s->condjmp = 1;
9531 insn = arm_lduw_code(env, s->pc, s->bswap_code);
9532 s->pc += 2;
9534 switch (insn >> 12) {
9535 case 0: case 1:
9537 rd = insn & 7;
9538 op = (insn >> 11) & 3;
9539 if (op == 3) {
9540 /* add/subtract */
9541 rn = (insn >> 3) & 7;
9542 tmp = load_reg(s, rn);
9543 if (insn & (1 << 10)) {
9544 /* immediate */
9545 tmp2 = tcg_temp_new_i32();
9546 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
9547 } else {
9548 /* reg */
9549 rm = (insn >> 6) & 7;
9550 tmp2 = load_reg(s, rm);
9552 if (insn & (1 << 9)) {
9553 if (s->condexec_mask)
9554 tcg_gen_sub_i32(tmp, tmp, tmp2);
9555 else
9556 gen_sub_CC(tmp, tmp, tmp2);
9557 } else {
9558 if (s->condexec_mask)
9559 tcg_gen_add_i32(tmp, tmp, tmp2);
9560 else
9561 gen_add_CC(tmp, tmp, tmp2);
9563 tcg_temp_free_i32(tmp2);
9564 store_reg(s, rd, tmp);
9565 } else {
9566 /* shift immediate */
9567 rm = (insn >> 3) & 7;
9568 shift = (insn >> 6) & 0x1f;
9569 tmp = load_reg(s, rm);
9570 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
9571 if (!s->condexec_mask)
9572 gen_logic_CC(tmp);
9573 store_reg(s, rd, tmp);
9575 break;
9576 case 2: case 3:
9577 /* arithmetic large immediate */
9578 op = (insn >> 11) & 3;
9579 rd = (insn >> 8) & 0x7;
9580 if (op == 0) { /* mov */
9581 tmp = tcg_temp_new_i32();
9582 tcg_gen_movi_i32(tmp, insn & 0xff);
9583 if (!s->condexec_mask)
9584 gen_logic_CC(tmp);
9585 store_reg(s, rd, tmp);
9586 } else {
9587 tmp = load_reg(s, rd);
9588 tmp2 = tcg_temp_new_i32();
9589 tcg_gen_movi_i32(tmp2, insn & 0xff);
9590 switch (op) {
9591 case 1: /* cmp */
9592 gen_sub_CC(tmp, tmp, tmp2);
9593 tcg_temp_free_i32(tmp);
9594 tcg_temp_free_i32(tmp2);
9595 break;
9596 case 2: /* add */
9597 if (s->condexec_mask)
9598 tcg_gen_add_i32(tmp, tmp, tmp2);
9599 else
9600 gen_add_CC(tmp, tmp, tmp2);
9601 tcg_temp_free_i32(tmp2);
9602 store_reg(s, rd, tmp);
9603 break;
9604 case 3: /* sub */
9605 if (s->condexec_mask)
9606 tcg_gen_sub_i32(tmp, tmp, tmp2);
9607 else
9608 gen_sub_CC(tmp, tmp, tmp2);
9609 tcg_temp_free_i32(tmp2);
9610 store_reg(s, rd, tmp);
9611 break;
9614 break;
9615 case 4:
9616 if (insn & (1 << 11)) {
9617 rd = (insn >> 8) & 7;
9618 /* load pc-relative. Bit 1 of PC is ignored. */
9619 val = s->pc + 2 + ((insn & 0xff) * 4);
9620 val &= ~(uint32_t)2;
9621 addr = tcg_temp_new_i32();
9622 tcg_gen_movi_i32(addr, val);
9623 tmp = tcg_temp_new_i32();
9624 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9625 tcg_temp_free_i32(addr);
9626 store_reg(s, rd, tmp);
9627 break;
9629 if (insn & (1 << 10)) {
9630 /* data processing extended or blx */
9631 rd = (insn & 7) | ((insn >> 4) & 8);
9632 rm = (insn >> 3) & 0xf;
9633 op = (insn >> 8) & 3;
9634 switch (op) {
9635 case 0: /* add */
9636 tmp = load_reg(s, rd);
9637 tmp2 = load_reg(s, rm);
9638 tcg_gen_add_i32(tmp, tmp, tmp2);
9639 tcg_temp_free_i32(tmp2);
9640 store_reg(s, rd, tmp);
9641 break;
9642 case 1: /* cmp */
9643 tmp = load_reg(s, rd);
9644 tmp2 = load_reg(s, rm);
9645 gen_sub_CC(tmp, tmp, tmp2);
9646 tcg_temp_free_i32(tmp2);
9647 tcg_temp_free_i32(tmp);
9648 break;
9649 case 2: /* mov/cpy */
9650 tmp = load_reg(s, rm);
9651 store_reg(s, rd, tmp);
9652 break;
9653 case 3:/* branch [and link] exchange thumb register */
9654 tmp = load_reg(s, rm);
9655 if (insn & (1 << 7)) {
9656 ARCH(5);
9657 val = (uint32_t)s->pc | 1;
9658 tmp2 = tcg_temp_new_i32();
9659 tcg_gen_movi_i32(tmp2, val);
9660 store_reg(s, 14, tmp2);
9662 /* already thumb, no need to check */
9663 gen_bx(s, tmp);
9664 break;
9666 break;
9669 /* data processing register */
9670 rd = insn & 7;
9671 rm = (insn >> 3) & 7;
9672 op = (insn >> 6) & 0xf;
9673 if (op == 2 || op == 3 || op == 4 || op == 7) {
9674 /* the shift/rotate ops want the operands backwards */
9675 val = rm;
9676 rm = rd;
9677 rd = val;
9678 val = 1;
9679 } else {
9680 val = 0;
9683 if (op == 9) { /* neg */
9684 tmp = tcg_temp_new_i32();
9685 tcg_gen_movi_i32(tmp, 0);
9686 } else if (op != 0xf) { /* mvn doesn't read its first operand */
9687 tmp = load_reg(s, rd);
9688 } else {
9689 TCGV_UNUSED_I32(tmp);
9692 tmp2 = load_reg(s, rm);
9693 switch (op) {
9694 case 0x0: /* and */
9695 tcg_gen_and_i32(tmp, tmp, tmp2);
9696 if (!s->condexec_mask)
9697 gen_logic_CC(tmp);
9698 break;
9699 case 0x1: /* eor */
9700 tcg_gen_xor_i32(tmp, tmp, tmp2);
9701 if (!s->condexec_mask)
9702 gen_logic_CC(tmp);
9703 break;
9704 case 0x2: /* lsl */
9705 if (s->condexec_mask) {
9706 gen_shl(tmp2, tmp2, tmp);
9707 } else {
9708 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
9709 gen_logic_CC(tmp2);
9711 break;
9712 case 0x3: /* lsr */
9713 if (s->condexec_mask) {
9714 gen_shr(tmp2, tmp2, tmp);
9715 } else {
9716 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
9717 gen_logic_CC(tmp2);
9719 break;
9720 case 0x4: /* asr */
9721 if (s->condexec_mask) {
9722 gen_sar(tmp2, tmp2, tmp);
9723 } else {
9724 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
9725 gen_logic_CC(tmp2);
9727 break;
9728 case 0x5: /* adc */
9729 if (s->condexec_mask) {
9730 gen_adc(tmp, tmp2);
9731 } else {
9732 gen_adc_CC(tmp, tmp, tmp2);
9734 break;
9735 case 0x6: /* sbc */
9736 if (s->condexec_mask) {
9737 gen_sub_carry(tmp, tmp, tmp2);
9738 } else {
9739 gen_sbc_CC(tmp, tmp, tmp2);
9741 break;
9742 case 0x7: /* ror */
9743 if (s->condexec_mask) {
9744 tcg_gen_andi_i32(tmp, tmp, 0x1f);
9745 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9746 } else {
9747 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
9748 gen_logic_CC(tmp2);
9750 break;
9751 case 0x8: /* tst */
9752 tcg_gen_and_i32(tmp, tmp, tmp2);
9753 gen_logic_CC(tmp);
9754 rd = 16;
9755 break;
9756 case 0x9: /* neg */
9757 if (s->condexec_mask)
9758 tcg_gen_neg_i32(tmp, tmp2);
9759 else
9760 gen_sub_CC(tmp, tmp, tmp2);
9761 break;
9762 case 0xa: /* cmp */
9763 gen_sub_CC(tmp, tmp, tmp2);
9764 rd = 16;
9765 break;
9766 case 0xb: /* cmn */
9767 gen_add_CC(tmp, tmp, tmp2);
9768 rd = 16;
9769 break;
9770 case 0xc: /* orr */
9771 tcg_gen_or_i32(tmp, tmp, tmp2);
9772 if (!s->condexec_mask)
9773 gen_logic_CC(tmp);
9774 break;
9775 case 0xd: /* mul */
9776 tcg_gen_mul_i32(tmp, tmp, tmp2);
9777 if (!s->condexec_mask)
9778 gen_logic_CC(tmp);
9779 break;
9780 case 0xe: /* bic */
9781 tcg_gen_andc_i32(tmp, tmp, tmp2);
9782 if (!s->condexec_mask)
9783 gen_logic_CC(tmp);
9784 break;
9785 case 0xf: /* mvn */
9786 tcg_gen_not_i32(tmp2, tmp2);
9787 if (!s->condexec_mask)
9788 gen_logic_CC(tmp2);
9789 val = 1;
9790 rm = rd;
9791 break;
9793 if (rd != 16) {
9794 if (val) {
9795 store_reg(s, rm, tmp2);
9796 if (op != 0xf)
9797 tcg_temp_free_i32(tmp);
9798 } else {
9799 store_reg(s, rd, tmp);
9800 tcg_temp_free_i32(tmp2);
9802 } else {
9803 tcg_temp_free_i32(tmp);
9804 tcg_temp_free_i32(tmp2);
9806 break;
9808 case 5:
9809 /* load/store register offset. */
9810 rd = insn & 7;
9811 rn = (insn >> 3) & 7;
9812 rm = (insn >> 6) & 7;
9813 op = (insn >> 9) & 7;
9814 addr = load_reg(s, rn);
9815 tmp = load_reg(s, rm);
9816 tcg_gen_add_i32(addr, addr, tmp);
9817 tcg_temp_free_i32(tmp);
9819 if (op < 3) { /* store */
9820 tmp = load_reg(s, rd);
9821 } else {
9822 tmp = tcg_temp_new_i32();
9825 switch (op) {
9826 case 0: /* str */
9827 gen_aa32_st32(tmp, addr, IS_USER(s));
9828 break;
9829 case 1: /* strh */
9830 gen_aa32_st16(tmp, addr, IS_USER(s));
9831 break;
9832 case 2: /* strb */
9833 gen_aa32_st8(tmp, addr, IS_USER(s));
9834 break;
9835 case 3: /* ldrsb */
9836 gen_aa32_ld8s(tmp, addr, IS_USER(s));
9837 break;
9838 case 4: /* ldr */
9839 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9840 break;
9841 case 5: /* ldrh */
9842 gen_aa32_ld16u(tmp, addr, IS_USER(s));
9843 break;
9844 case 6: /* ldrb */
9845 gen_aa32_ld8u(tmp, addr, IS_USER(s));
9846 break;
9847 case 7: /* ldrsh */
9848 gen_aa32_ld16s(tmp, addr, IS_USER(s));
9849 break;
9851 if (op >= 3) { /* load */
9852 store_reg(s, rd, tmp);
9853 } else {
9854 tcg_temp_free_i32(tmp);
9856 tcg_temp_free_i32(addr);
9857 break;
9859 case 6:
9860 /* load/store word immediate offset */
9861 rd = insn & 7;
9862 rn = (insn >> 3) & 7;
9863 addr = load_reg(s, rn);
9864 val = (insn >> 4) & 0x7c;
9865 tcg_gen_addi_i32(addr, addr, val);
9867 if (insn & (1 << 11)) {
9868 /* load */
9869 tmp = tcg_temp_new_i32();
9870 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9871 store_reg(s, rd, tmp);
9872 } else {
9873 /* store */
9874 tmp = load_reg(s, rd);
9875 gen_aa32_st32(tmp, addr, IS_USER(s));
9876 tcg_temp_free_i32(tmp);
9878 tcg_temp_free_i32(addr);
9879 break;
9881 case 7:
9882 /* load/store byte immediate offset */
9883 rd = insn & 7;
9884 rn = (insn >> 3) & 7;
9885 addr = load_reg(s, rn);
9886 val = (insn >> 6) & 0x1f;
9887 tcg_gen_addi_i32(addr, addr, val);
9889 if (insn & (1 << 11)) {
9890 /* load */
9891 tmp = tcg_temp_new_i32();
9892 gen_aa32_ld8u(tmp, addr, IS_USER(s));
9893 store_reg(s, rd, tmp);
9894 } else {
9895 /* store */
9896 tmp = load_reg(s, rd);
9897 gen_aa32_st8(tmp, addr, IS_USER(s));
9898 tcg_temp_free_i32(tmp);
9900 tcg_temp_free_i32(addr);
9901 break;
9903 case 8:
9904 /* load/store halfword immediate offset */
9905 rd = insn & 7;
9906 rn = (insn >> 3) & 7;
9907 addr = load_reg(s, rn);
9908 val = (insn >> 5) & 0x3e;
9909 tcg_gen_addi_i32(addr, addr, val);
9911 if (insn & (1 << 11)) {
9912 /* load */
9913 tmp = tcg_temp_new_i32();
9914 gen_aa32_ld16u(tmp, addr, IS_USER(s));
9915 store_reg(s, rd, tmp);
9916 } else {
9917 /* store */
9918 tmp = load_reg(s, rd);
9919 gen_aa32_st16(tmp, addr, IS_USER(s));
9920 tcg_temp_free_i32(tmp);
9922 tcg_temp_free_i32(addr);
9923 break;
9925 case 9:
9926 /* load/store from stack */
9927 rd = (insn >> 8) & 7;
9928 addr = load_reg(s, 13);
9929 val = (insn & 0xff) * 4;
9930 tcg_gen_addi_i32(addr, addr, val);
9932 if (insn & (1 << 11)) {
9933 /* load */
9934 tmp = tcg_temp_new_i32();
9935 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9936 store_reg(s, rd, tmp);
9937 } else {
9938 /* store */
9939 tmp = load_reg(s, rd);
9940 gen_aa32_st32(tmp, addr, IS_USER(s));
9941 tcg_temp_free_i32(tmp);
9943 tcg_temp_free_i32(addr);
9944 break;
9946 case 10:
9947 /* add to high reg */
9948 rd = (insn >> 8) & 7;
9949 if (insn & (1 << 11)) {
9950 /* SP */
9951 tmp = load_reg(s, 13);
9952 } else {
9953 /* PC. bit 1 is ignored. */
9954 tmp = tcg_temp_new_i32();
9955 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
9957 val = (insn & 0xff) * 4;
9958 tcg_gen_addi_i32(tmp, tmp, val);
9959 store_reg(s, rd, tmp);
9960 break;
9962 case 11:
9963 /* misc */
9964 op = (insn >> 8) & 0xf;
9965 switch (op) {
9966 case 0:
9967 /* adjust stack pointer */
9968 tmp = load_reg(s, 13);
9969 val = (insn & 0x7f) * 4;
9970 if (insn & (1 << 7))
9971 val = -(int32_t)val;
9972 tcg_gen_addi_i32(tmp, tmp, val);
9973 store_reg(s, 13, tmp);
9974 break;
9976 case 2: /* sign/zero extend. */
9977 ARCH(6);
9978 rd = insn & 7;
9979 rm = (insn >> 3) & 7;
9980 tmp = load_reg(s, rm);
9981 switch ((insn >> 6) & 3) {
9982 case 0: gen_sxth(tmp); break;
9983 case 1: gen_sxtb(tmp); break;
9984 case 2: gen_uxth(tmp); break;
9985 case 3: gen_uxtb(tmp); break;
9987 store_reg(s, rd, tmp);
9988 break;
9989 case 4: case 5: case 0xc: case 0xd:
9990 /* push/pop */
9991 addr = load_reg(s, 13);
9992 if (insn & (1 << 8))
9993 offset = 4;
9994 else
9995 offset = 0;
9996 for (i = 0; i < 8; i++) {
9997 if (insn & (1 << i))
9998 offset += 4;
10000 if ((insn & (1 << 11)) == 0) {
10001 tcg_gen_addi_i32(addr, addr, -offset);
10003 for (i = 0; i < 8; i++) {
10004 if (insn & (1 << i)) {
10005 if (insn & (1 << 11)) {
10006 /* pop */
10007 tmp = tcg_temp_new_i32();
10008 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10009 store_reg(s, i, tmp);
10010 } else {
10011 /* push */
10012 tmp = load_reg(s, i);
10013 gen_aa32_st32(tmp, addr, IS_USER(s));
10014 tcg_temp_free_i32(tmp);
10016 /* advance to the next address. */
10017 tcg_gen_addi_i32(addr, addr, 4);
10020 TCGV_UNUSED_I32(tmp);
10021 if (insn & (1 << 8)) {
10022 if (insn & (1 << 11)) {
10023 /* pop pc */
10024 tmp = tcg_temp_new_i32();
10025 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10026 /* don't set the pc until the rest of the instruction
10027 has completed */
10028 } else {
10029 /* push lr */
10030 tmp = load_reg(s, 14);
10031 gen_aa32_st32(tmp, addr, IS_USER(s));
10032 tcg_temp_free_i32(tmp);
10034 tcg_gen_addi_i32(addr, addr, 4);
10036 if ((insn & (1 << 11)) == 0) {
10037 tcg_gen_addi_i32(addr, addr, -offset);
10039 /* write back the new stack pointer */
10040 store_reg(s, 13, addr);
10041 /* set the new PC value */
10042 if ((insn & 0x0900) == 0x0900) {
10043 store_reg_from_load(env, s, 15, tmp);
10045 break;
10047 case 1: case 3: case 9: case 11: /* czb */
10048 rm = insn & 7;
10049 tmp = load_reg(s, rm);
10050 s->condlabel = gen_new_label();
10051 s->condjmp = 1;
10052 if (insn & (1 << 11))
10053 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
10054 else
10055 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
10056 tcg_temp_free_i32(tmp);
10057 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
10058 val = (uint32_t)s->pc + 2;
10059 val += offset;
10060 gen_jmp(s, val);
10061 break;
10063 case 15: /* IT, nop-hint. */
10064 if ((insn & 0xf) == 0) {
10065 gen_nop_hint(s, (insn >> 4) & 0xf);
10066 break;
10068 /* If Then. */
10069 s->condexec_cond = (insn >> 4) & 0xe;
10070 s->condexec_mask = insn & 0x1f;
10071 /* No actual code generated for this insn, just setup state. */
10072 break;
10074 case 0xe: /* bkpt */
10075 ARCH(5);
10076 gen_exception_insn(s, 2, EXCP_BKPT);
10077 break;
10079 case 0xa: /* rev */
10080 ARCH(6);
10081 rn = (insn >> 3) & 0x7;
10082 rd = insn & 0x7;
10083 tmp = load_reg(s, rn);
10084 switch ((insn >> 6) & 3) {
10085 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
10086 case 1: gen_rev16(tmp); break;
10087 case 3: gen_revsh(tmp); break;
10088 default: goto illegal_op;
10090 store_reg(s, rd, tmp);
10091 break;
10093 case 6:
10094 switch ((insn >> 5) & 7) {
10095 case 2:
10096 /* setend */
10097 ARCH(6);
10098 if (((insn >> 3) & 1) != s->bswap_code) {
10099 /* Dynamic endianness switching not implemented. */
10100 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
10101 goto illegal_op;
10103 break;
10104 case 3:
10105 /* cps */
10106 ARCH(6);
10107 if (IS_USER(s)) {
10108 break;
10110 if (IS_M(env)) {
10111 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
10112 /* FAULTMASK */
10113 if (insn & 1) {
10114 addr = tcg_const_i32(19);
10115 gen_helper_v7m_msr(cpu_env, addr, tmp);
10116 tcg_temp_free_i32(addr);
10118 /* PRIMASK */
10119 if (insn & 2) {
10120 addr = tcg_const_i32(16);
10121 gen_helper_v7m_msr(cpu_env, addr, tmp);
10122 tcg_temp_free_i32(addr);
10124 tcg_temp_free_i32(tmp);
10125 gen_lookup_tb(s);
10126 } else {
10127 if (insn & (1 << 4)) {
10128 shift = CPSR_A | CPSR_I | CPSR_F;
10129 } else {
10130 shift = 0;
10132 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
10134 break;
10135 default:
10136 goto undef;
10138 break;
10140 default:
10141 goto undef;
10143 break;
10145 case 12:
10147 /* load/store multiple */
10148 TCGv_i32 loaded_var;
10149 TCGV_UNUSED_I32(loaded_var);
10150 rn = (insn >> 8) & 0x7;
10151 addr = load_reg(s, rn);
10152 for (i = 0; i < 8; i++) {
10153 if (insn & (1 << i)) {
10154 if (insn & (1 << 11)) {
10155 /* load */
10156 tmp = tcg_temp_new_i32();
10157 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10158 if (i == rn) {
10159 loaded_var = tmp;
10160 } else {
10161 store_reg(s, i, tmp);
10163 } else {
10164 /* store */
10165 tmp = load_reg(s, i);
10166 gen_aa32_st32(tmp, addr, IS_USER(s));
10167 tcg_temp_free_i32(tmp);
10169 /* advance to the next address */
10170 tcg_gen_addi_i32(addr, addr, 4);
10173 if ((insn & (1 << rn)) == 0) {
10174 /* base reg not in list: base register writeback */
10175 store_reg(s, rn, addr);
10176 } else {
10177 /* base reg in list: if load, complete it now */
10178 if (insn & (1 << 11)) {
10179 store_reg(s, rn, loaded_var);
10181 tcg_temp_free_i32(addr);
10183 break;
10185 case 13:
10186 /* conditional branch or swi */
10187 cond = (insn >> 8) & 0xf;
10188 if (cond == 0xe)
10189 goto undef;
10191 if (cond == 0xf) {
10192 /* swi */
10193 gen_set_pc_im(s, s->pc);
10194 s->is_jmp = DISAS_SWI;
10195 break;
10197 /* generate a conditional jump to next instruction */
10198 s->condlabel = gen_new_label();
10199 arm_gen_test_cc(cond ^ 1, s->condlabel);
10200 s->condjmp = 1;
10202 /* jump to the offset */
10203 val = (uint32_t)s->pc + 2;
10204 offset = ((int32_t)insn << 24) >> 24;
10205 val += offset << 1;
10206 gen_jmp(s, val);
10207 break;
10209 case 14:
10210 if (insn & (1 << 11)) {
10211 if (disas_thumb2_insn(env, s, insn))
10212 goto undef32;
10213 break;
10215 /* unconditional branch */
10216 val = (uint32_t)s->pc;
10217 offset = ((int32_t)insn << 21) >> 21;
10218 val += (offset << 1) + 2;
10219 gen_jmp(s, val);
10220 break;
10222 case 15:
10223 if (disas_thumb2_insn(env, s, insn))
10224 goto undef32;
10225 break;
10227 return;
10228 undef32:
10229 gen_exception_insn(s, 4, EXCP_UDEF);
10230 return;
10231 illegal_op:
10232 undef:
10233 gen_exception_insn(s, 2, EXCP_UDEF);
10236 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
10237 basic block 'tb'. If search_pc is TRUE, also generate PC
10238 information for each intermediate instruction. */
10239 static inline void gen_intermediate_code_internal(ARMCPU *cpu,
10240 TranslationBlock *tb,
10241 bool search_pc)
10243 CPUState *cs = CPU(cpu);
10244 CPUARMState *env = &cpu->env;
10245 DisasContext dc1, *dc = &dc1;
10246 CPUBreakpoint *bp;
10247 uint16_t *gen_opc_end;
10248 int j, lj;
10249 target_ulong pc_start;
10250 target_ulong next_page_start;
10251 int num_insns;
10252 int max_insns;
10254 /* generate intermediate code */
10256 /* The A64 decoder has its own top level loop, because it doesn't need
10257 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
10259 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
10260 gen_intermediate_code_internal_a64(cpu, tb, search_pc);
10261 return;
10264 pc_start = tb->pc;
10266 dc->tb = tb;
10268 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
10270 dc->is_jmp = DISAS_NEXT;
10271 dc->pc = pc_start;
10272 dc->singlestep_enabled = cs->singlestep_enabled;
10273 dc->condjmp = 0;
10275 dc->aarch64 = 0;
10276 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
10277 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
10278 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
10279 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
10280 #if !defined(CONFIG_USER_ONLY)
10281 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
10282 #endif
10283 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
10284 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
10285 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
10286 dc->cp_regs = cpu->cp_regs;
10287 dc->current_pl = arm_current_pl(env);
10289 cpu_F0s = tcg_temp_new_i32();
10290 cpu_F1s = tcg_temp_new_i32();
10291 cpu_F0d = tcg_temp_new_i64();
10292 cpu_F1d = tcg_temp_new_i64();
10293 cpu_V0 = cpu_F0d;
10294 cpu_V1 = cpu_F1d;
10295 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
10296 cpu_M0 = tcg_temp_new_i64();
10297 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
10298 lj = -1;
10299 num_insns = 0;
10300 max_insns = tb->cflags & CF_COUNT_MASK;
10301 if (max_insns == 0)
10302 max_insns = CF_COUNT_MASK;
10304 gen_tb_start();
10306 tcg_clear_temp_count();
10308 /* A note on handling of the condexec (IT) bits:
10310 * We want to avoid the overhead of having to write the updated condexec
10311 * bits back to the CPUARMState for every instruction in an IT block. So:
10312 * (1) if the condexec bits are not already zero then we write
10313 * zero back into the CPUARMState now. This avoids complications trying
10314 * to do it at the end of the block. (For example if we don't do this
10315 * it's hard to identify whether we can safely skip writing condexec
10316 * at the end of the TB, which we definitely want to do for the case
10317 * where a TB doesn't do anything with the IT state at all.)
10318 * (2) if we are going to leave the TB then we call gen_set_condexec()
10319 * which will write the correct value into CPUARMState if zero is wrong.
10320 * This is done both for leaving the TB at the end, and for leaving
10321 * it because of an exception we know will happen, which is done in
10322 * gen_exception_insn(). The latter is necessary because we need to
10323 * leave the TB with the PC/IT state just prior to execution of the
10324 * instruction which caused the exception.
10325 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
10326 * then the CPUARMState will be wrong and we need to reset it.
10327 * This is handled in the same way as restoration of the
10328 * PC in these situations: we will be called again with search_pc=1
10329 * and generate a mapping of the condexec bits for each PC in
10330 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
10331 * this to restore the condexec bits.
10333 * Note that there are no instructions which can read the condexec
10334 * bits, and none which can write non-static values to them, so
10335 * we don't need to care about whether CPUARMState is correct in the
10336 * middle of a TB.
10339 /* Reset the conditional execution bits immediately. This avoids
10340 complications trying to do it at the end of the block. */
10341 if (dc->condexec_mask || dc->condexec_cond)
10343 TCGv_i32 tmp = tcg_temp_new_i32();
10344 tcg_gen_movi_i32(tmp, 0);
10345 store_cpu_field(tmp, condexec_bits);
10347 do {
10348 #ifdef CONFIG_USER_ONLY
10349 /* Intercept jump to the magic kernel page. */
10350 if (dc->pc >= 0xffff0000) {
10351 /* We always get here via a jump, so know we are not in a
10352 conditional execution block. */
10353 gen_exception(EXCP_KERNEL_TRAP);
10354 dc->is_jmp = DISAS_UPDATE;
10355 break;
10357 #else
10358 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
10359 /* We always get here via a jump, so know we are not in a
10360 conditional execution block. */
10361 gen_exception(EXCP_EXCEPTION_EXIT);
10362 dc->is_jmp = DISAS_UPDATE;
10363 break;
10365 #endif
10367 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
10368 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
10369 if (bp->pc == dc->pc) {
10370 gen_exception_insn(dc, 0, EXCP_DEBUG);
10371 /* Advance PC so that clearing the breakpoint will
10372 invalidate this TB. */
10373 dc->pc += 2;
10374 goto done_generating;
10378 if (search_pc) {
10379 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10380 if (lj < j) {
10381 lj++;
10382 while (lj < j)
10383 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10385 tcg_ctx.gen_opc_pc[lj] = dc->pc;
10386 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
10387 tcg_ctx.gen_opc_instr_start[lj] = 1;
10388 tcg_ctx.gen_opc_icount[lj] = num_insns;
10391 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
10392 gen_io_start();
10394 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
10395 tcg_gen_debug_insn_start(dc->pc);
10398 if (dc->thumb) {
10399 disas_thumb_insn(env, dc);
10400 if (dc->condexec_mask) {
10401 dc->condexec_cond = (dc->condexec_cond & 0xe)
10402 | ((dc->condexec_mask >> 4) & 1);
10403 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
10404 if (dc->condexec_mask == 0) {
10405 dc->condexec_cond = 0;
10408 } else {
10409 disas_arm_insn(env, dc);
10412 if (dc->condjmp && !dc->is_jmp) {
10413 gen_set_label(dc->condlabel);
10414 dc->condjmp = 0;
10417 if (tcg_check_temp_count()) {
10418 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
10419 dc->pc);
10422 /* Translation stops when a conditional branch is encountered.
10423 * Otherwise the subsequent code could get translated several times.
10424 * Also stop translation when a page boundary is reached. This
10425 * ensures prefetch aborts occur at the right place. */
10426 num_insns ++;
10427 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
10428 !cs->singlestep_enabled &&
10429 !singlestep &&
10430 dc->pc < next_page_start &&
10431 num_insns < max_insns);
10433 if (tb->cflags & CF_LAST_IO) {
10434 if (dc->condjmp) {
10435 /* FIXME: This can theoretically happen with self-modifying
10436 code. */
10437 cpu_abort(env, "IO on conditional branch instruction");
10439 gen_io_end();
10442 /* At this stage dc->condjmp will only be set when the skipped
10443 instruction was a conditional branch or trap, and the PC has
10444 already been written. */
10445 if (unlikely(cs->singlestep_enabled)) {
10446 /* Make sure the pc is updated, and raise a debug exception. */
10447 if (dc->condjmp) {
10448 gen_set_condexec(dc);
10449 if (dc->is_jmp == DISAS_SWI) {
10450 gen_exception(EXCP_SWI);
10451 } else {
10452 gen_exception(EXCP_DEBUG);
10454 gen_set_label(dc->condlabel);
10456 if (dc->condjmp || !dc->is_jmp) {
10457 gen_set_pc_im(dc, dc->pc);
10458 dc->condjmp = 0;
10460 gen_set_condexec(dc);
10461 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
10462 gen_exception(EXCP_SWI);
10463 } else {
10464 /* FIXME: Single stepping a WFI insn will not halt
10465 the CPU. */
10466 gen_exception(EXCP_DEBUG);
10468 } else {
10469 /* While branches must always occur at the end of an IT block,
10470 there are a few other things that can cause us to terminate
10471 the TB in the middle of an IT block:
10472 - Exception generating instructions (bkpt, swi, undefined).
10473 - Page boundaries.
10474 - Hardware watchpoints.
10475 Hardware breakpoints have already been handled and skip this code.
10477 gen_set_condexec(dc);
10478 switch(dc->is_jmp) {
10479 case DISAS_NEXT:
10480 gen_goto_tb(dc, 1, dc->pc);
10481 break;
10482 default:
10483 case DISAS_JUMP:
10484 case DISAS_UPDATE:
10485 /* indicate that the hash table must be used to find the next TB */
10486 tcg_gen_exit_tb(0);
10487 break;
10488 case DISAS_TB_JUMP:
10489 /* nothing more to generate */
10490 break;
10491 case DISAS_WFI:
10492 gen_helper_wfi(cpu_env);
10493 break;
10494 case DISAS_SWI:
10495 gen_exception(EXCP_SWI);
10496 break;
10498 if (dc->condjmp) {
10499 gen_set_label(dc->condlabel);
10500 gen_set_condexec(dc);
10501 gen_goto_tb(dc, 1, dc->pc);
10502 dc->condjmp = 0;
10506 done_generating:
10507 gen_tb_end(tb, num_insns);
10508 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
10510 #ifdef DEBUG_DISAS
10511 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
10512 qemu_log("----------------\n");
10513 qemu_log("IN: %s\n", lookup_symbol(pc_start));
10514 log_target_disas(env, pc_start, dc->pc - pc_start,
10515 dc->thumb | (dc->bswap_code << 1));
10516 qemu_log("\n");
10518 #endif
10519 if (search_pc) {
10520 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10521 lj++;
10522 while (lj <= j)
10523 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10524 } else {
10525 tb->size = dc->pc - pc_start;
10526 tb->icount = num_insns;
10530 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
10532 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
10535 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
10537 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
10540 static const char *cpu_mode_names[16] = {
10541 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
10542 "???", "???", "???", "und", "???", "???", "???", "sys"
10545 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
10546 int flags)
10548 ARMCPU *cpu = ARM_CPU(cs);
10549 CPUARMState *env = &cpu->env;
10550 int i;
10551 uint32_t psr;
10553 for(i=0;i<16;i++) {
10554 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
10555 if ((i % 4) == 3)
10556 cpu_fprintf(f, "\n");
10557 else
10558 cpu_fprintf(f, " ");
10560 psr = cpsr_read(env);
10561 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
10562 psr,
10563 psr & (1 << 31) ? 'N' : '-',
10564 psr & (1 << 30) ? 'Z' : '-',
10565 psr & (1 << 29) ? 'C' : '-',
10566 psr & (1 << 28) ? 'V' : '-',
10567 psr & CPSR_T ? 'T' : 'A',
10568 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
10570 if (flags & CPU_DUMP_FPU) {
10571 int numvfpregs = 0;
10572 if (arm_feature(env, ARM_FEATURE_VFP)) {
10573 numvfpregs += 16;
10575 if (arm_feature(env, ARM_FEATURE_VFP3)) {
10576 numvfpregs += 16;
10578 for (i = 0; i < numvfpregs; i++) {
10579 uint64_t v = float64_val(env->vfp.regs[i]);
10580 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
10581 i * 2, (uint32_t)v,
10582 i * 2 + 1, (uint32_t)(v >> 32),
10583 i, v);
10585 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
10589 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
10591 if (is_a64(env)) {
10592 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
10593 env->condexec_bits = 0;
10594 } else {
10595 env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
10596 env->condexec_bits = gen_opc_condexec_bits[pc_pos];