char/cadence_uart: Delete redundant rx rst logic
[qemu.git] / target-arm / translate.c
blobd04fc9ff41580dbd38a4fe3739561b3b6195c1bb
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) \
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(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
1108 } else { \
1109 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
1111 tcg_temp_free_i32(tmp_shift); \
1112 tcg_temp_free_ptr(statusptr); \
1114 VFP_GEN_FIX(tosh)
1115 VFP_GEN_FIX(tosl)
1116 VFP_GEN_FIX(touh)
1117 VFP_GEN_FIX(toul)
1118 VFP_GEN_FIX(shto)
1119 VFP_GEN_FIX(slto)
1120 VFP_GEN_FIX(uhto)
1121 VFP_GEN_FIX(ulto)
1122 #undef VFP_GEN_FIX
1124 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1126 if (dp) {
1127 gen_aa32_ld64(cpu_F0d, addr, IS_USER(s));
1128 } else {
1129 gen_aa32_ld32u(cpu_F0s, addr, IS_USER(s));
1133 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1135 if (dp) {
1136 gen_aa32_st64(cpu_F0d, addr, IS_USER(s));
1137 } else {
1138 gen_aa32_st32(cpu_F0s, addr, IS_USER(s));
1142 static inline long
1143 vfp_reg_offset (int dp, int reg)
1145 if (dp)
1146 return offsetof(CPUARMState, vfp.regs[reg]);
1147 else if (reg & 1) {
1148 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1149 + offsetof(CPU_DoubleU, l.upper);
1150 } else {
1151 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1152 + offsetof(CPU_DoubleU, l.lower);
1156 /* Return the offset of a 32-bit piece of a NEON register.
1157 zero is the least significant end of the register. */
1158 static inline long
1159 neon_reg_offset (int reg, int n)
1161 int sreg;
1162 sreg = reg * 2 + n;
1163 return vfp_reg_offset(0, sreg);
1166 static TCGv_i32 neon_load_reg(int reg, int pass)
1168 TCGv_i32 tmp = tcg_temp_new_i32();
1169 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1170 return tmp;
1173 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1175 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1176 tcg_temp_free_i32(var);
1179 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1181 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1184 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1186 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1189 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1190 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1191 #define tcg_gen_st_f32 tcg_gen_st_i32
1192 #define tcg_gen_st_f64 tcg_gen_st_i64
1194 static inline void gen_mov_F0_vreg(int dp, int reg)
1196 if (dp)
1197 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1198 else
1199 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1202 static inline void gen_mov_F1_vreg(int dp, int reg)
1204 if (dp)
1205 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1206 else
1207 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1210 static inline void gen_mov_vreg_F0(int dp, int reg)
1212 if (dp)
1213 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1214 else
1215 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1218 #define ARM_CP_RW_BIT (1 << 20)
1220 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1222 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1225 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1227 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1230 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1232 TCGv_i32 var = tcg_temp_new_i32();
1233 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1234 return var;
1237 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1239 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1240 tcg_temp_free_i32(var);
1243 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1245 iwmmxt_store_reg(cpu_M0, rn);
1248 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1250 iwmmxt_load_reg(cpu_M0, rn);
1253 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1255 iwmmxt_load_reg(cpu_V1, rn);
1256 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1259 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1261 iwmmxt_load_reg(cpu_V1, rn);
1262 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1265 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1267 iwmmxt_load_reg(cpu_V1, rn);
1268 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1271 #define IWMMXT_OP(name) \
1272 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1274 iwmmxt_load_reg(cpu_V1, rn); \
1275 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1278 #define IWMMXT_OP_ENV(name) \
1279 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1281 iwmmxt_load_reg(cpu_V1, rn); \
1282 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1285 #define IWMMXT_OP_ENV_SIZE(name) \
1286 IWMMXT_OP_ENV(name##b) \
1287 IWMMXT_OP_ENV(name##w) \
1288 IWMMXT_OP_ENV(name##l)
1290 #define IWMMXT_OP_ENV1(name) \
1291 static inline void gen_op_iwmmxt_##name##_M0(void) \
1293 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1296 IWMMXT_OP(maddsq)
1297 IWMMXT_OP(madduq)
1298 IWMMXT_OP(sadb)
1299 IWMMXT_OP(sadw)
1300 IWMMXT_OP(mulslw)
1301 IWMMXT_OP(mulshw)
1302 IWMMXT_OP(mululw)
1303 IWMMXT_OP(muluhw)
1304 IWMMXT_OP(macsw)
1305 IWMMXT_OP(macuw)
1307 IWMMXT_OP_ENV_SIZE(unpackl)
1308 IWMMXT_OP_ENV_SIZE(unpackh)
1310 IWMMXT_OP_ENV1(unpacklub)
1311 IWMMXT_OP_ENV1(unpackluw)
1312 IWMMXT_OP_ENV1(unpacklul)
1313 IWMMXT_OP_ENV1(unpackhub)
1314 IWMMXT_OP_ENV1(unpackhuw)
1315 IWMMXT_OP_ENV1(unpackhul)
1316 IWMMXT_OP_ENV1(unpacklsb)
1317 IWMMXT_OP_ENV1(unpacklsw)
1318 IWMMXT_OP_ENV1(unpacklsl)
1319 IWMMXT_OP_ENV1(unpackhsb)
1320 IWMMXT_OP_ENV1(unpackhsw)
1321 IWMMXT_OP_ENV1(unpackhsl)
1323 IWMMXT_OP_ENV_SIZE(cmpeq)
1324 IWMMXT_OP_ENV_SIZE(cmpgtu)
1325 IWMMXT_OP_ENV_SIZE(cmpgts)
1327 IWMMXT_OP_ENV_SIZE(mins)
1328 IWMMXT_OP_ENV_SIZE(minu)
1329 IWMMXT_OP_ENV_SIZE(maxs)
1330 IWMMXT_OP_ENV_SIZE(maxu)
1332 IWMMXT_OP_ENV_SIZE(subn)
1333 IWMMXT_OP_ENV_SIZE(addn)
1334 IWMMXT_OP_ENV_SIZE(subu)
1335 IWMMXT_OP_ENV_SIZE(addu)
1336 IWMMXT_OP_ENV_SIZE(subs)
1337 IWMMXT_OP_ENV_SIZE(adds)
1339 IWMMXT_OP_ENV(avgb0)
1340 IWMMXT_OP_ENV(avgb1)
1341 IWMMXT_OP_ENV(avgw0)
1342 IWMMXT_OP_ENV(avgw1)
1344 IWMMXT_OP(msadb)
1346 IWMMXT_OP_ENV(packuw)
1347 IWMMXT_OP_ENV(packul)
1348 IWMMXT_OP_ENV(packuq)
1349 IWMMXT_OP_ENV(packsw)
1350 IWMMXT_OP_ENV(packsl)
1351 IWMMXT_OP_ENV(packsq)
1353 static void gen_op_iwmmxt_set_mup(void)
1355 TCGv_i32 tmp;
1356 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1357 tcg_gen_ori_i32(tmp, tmp, 2);
1358 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1361 static void gen_op_iwmmxt_set_cup(void)
1363 TCGv_i32 tmp;
1364 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1365 tcg_gen_ori_i32(tmp, tmp, 1);
1366 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1369 static void gen_op_iwmmxt_setpsr_nz(void)
1371 TCGv_i32 tmp = tcg_temp_new_i32();
1372 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1373 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1376 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1378 iwmmxt_load_reg(cpu_V1, rn);
1379 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1380 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1383 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1384 TCGv_i32 dest)
1386 int rd;
1387 uint32_t offset;
1388 TCGv_i32 tmp;
1390 rd = (insn >> 16) & 0xf;
1391 tmp = load_reg(s, rd);
1393 offset = (insn & 0xff) << ((insn >> 7) & 2);
1394 if (insn & (1 << 24)) {
1395 /* Pre indexed */
1396 if (insn & (1 << 23))
1397 tcg_gen_addi_i32(tmp, tmp, offset);
1398 else
1399 tcg_gen_addi_i32(tmp, tmp, -offset);
1400 tcg_gen_mov_i32(dest, tmp);
1401 if (insn & (1 << 21))
1402 store_reg(s, rd, tmp);
1403 else
1404 tcg_temp_free_i32(tmp);
1405 } else if (insn & (1 << 21)) {
1406 /* Post indexed */
1407 tcg_gen_mov_i32(dest, tmp);
1408 if (insn & (1 << 23))
1409 tcg_gen_addi_i32(tmp, tmp, offset);
1410 else
1411 tcg_gen_addi_i32(tmp, tmp, -offset);
1412 store_reg(s, rd, tmp);
1413 } else if (!(insn & (1 << 23)))
1414 return 1;
1415 return 0;
1418 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1420 int rd = (insn >> 0) & 0xf;
1421 TCGv_i32 tmp;
1423 if (insn & (1 << 8)) {
1424 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1425 return 1;
1426 } else {
1427 tmp = iwmmxt_load_creg(rd);
1429 } else {
1430 tmp = tcg_temp_new_i32();
1431 iwmmxt_load_reg(cpu_V0, rd);
1432 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1434 tcg_gen_andi_i32(tmp, tmp, mask);
1435 tcg_gen_mov_i32(dest, tmp);
1436 tcg_temp_free_i32(tmp);
1437 return 0;
1440 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1441 (ie. an undefined instruction). */
1442 static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
1444 int rd, wrd;
1445 int rdhi, rdlo, rd0, rd1, i;
1446 TCGv_i32 addr;
1447 TCGv_i32 tmp, tmp2, tmp3;
1449 if ((insn & 0x0e000e00) == 0x0c000000) {
1450 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1451 wrd = insn & 0xf;
1452 rdlo = (insn >> 12) & 0xf;
1453 rdhi = (insn >> 16) & 0xf;
1454 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1455 iwmmxt_load_reg(cpu_V0, wrd);
1456 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1457 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1458 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1459 } else { /* TMCRR */
1460 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1461 iwmmxt_store_reg(cpu_V0, wrd);
1462 gen_op_iwmmxt_set_mup();
1464 return 0;
1467 wrd = (insn >> 12) & 0xf;
1468 addr = tcg_temp_new_i32();
1469 if (gen_iwmmxt_address(s, insn, addr)) {
1470 tcg_temp_free_i32(addr);
1471 return 1;
1473 if (insn & ARM_CP_RW_BIT) {
1474 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1475 tmp = tcg_temp_new_i32();
1476 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1477 iwmmxt_store_creg(wrd, tmp);
1478 } else {
1479 i = 1;
1480 if (insn & (1 << 8)) {
1481 if (insn & (1 << 22)) { /* WLDRD */
1482 gen_aa32_ld64(cpu_M0, addr, IS_USER(s));
1483 i = 0;
1484 } else { /* WLDRW wRd */
1485 tmp = tcg_temp_new_i32();
1486 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1488 } else {
1489 tmp = tcg_temp_new_i32();
1490 if (insn & (1 << 22)) { /* WLDRH */
1491 gen_aa32_ld16u(tmp, addr, IS_USER(s));
1492 } else { /* WLDRB */
1493 gen_aa32_ld8u(tmp, addr, IS_USER(s));
1496 if (i) {
1497 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1498 tcg_temp_free_i32(tmp);
1500 gen_op_iwmmxt_movq_wRn_M0(wrd);
1502 } else {
1503 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1504 tmp = iwmmxt_load_creg(wrd);
1505 gen_aa32_st32(tmp, addr, IS_USER(s));
1506 } else {
1507 gen_op_iwmmxt_movq_M0_wRn(wrd);
1508 tmp = tcg_temp_new_i32();
1509 if (insn & (1 << 8)) {
1510 if (insn & (1 << 22)) { /* WSTRD */
1511 gen_aa32_st64(cpu_M0, addr, IS_USER(s));
1512 } else { /* WSTRW wRd */
1513 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1514 gen_aa32_st32(tmp, addr, IS_USER(s));
1516 } else {
1517 if (insn & (1 << 22)) { /* WSTRH */
1518 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1519 gen_aa32_st16(tmp, addr, IS_USER(s));
1520 } else { /* WSTRB */
1521 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1522 gen_aa32_st8(tmp, addr, IS_USER(s));
1526 tcg_temp_free_i32(tmp);
1528 tcg_temp_free_i32(addr);
1529 return 0;
1532 if ((insn & 0x0f000000) != 0x0e000000)
1533 return 1;
1535 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1536 case 0x000: /* WOR */
1537 wrd = (insn >> 12) & 0xf;
1538 rd0 = (insn >> 0) & 0xf;
1539 rd1 = (insn >> 16) & 0xf;
1540 gen_op_iwmmxt_movq_M0_wRn(rd0);
1541 gen_op_iwmmxt_orq_M0_wRn(rd1);
1542 gen_op_iwmmxt_setpsr_nz();
1543 gen_op_iwmmxt_movq_wRn_M0(wrd);
1544 gen_op_iwmmxt_set_mup();
1545 gen_op_iwmmxt_set_cup();
1546 break;
1547 case 0x011: /* TMCR */
1548 if (insn & 0xf)
1549 return 1;
1550 rd = (insn >> 12) & 0xf;
1551 wrd = (insn >> 16) & 0xf;
1552 switch (wrd) {
1553 case ARM_IWMMXT_wCID:
1554 case ARM_IWMMXT_wCASF:
1555 break;
1556 case ARM_IWMMXT_wCon:
1557 gen_op_iwmmxt_set_cup();
1558 /* Fall through. */
1559 case ARM_IWMMXT_wCSSF:
1560 tmp = iwmmxt_load_creg(wrd);
1561 tmp2 = load_reg(s, rd);
1562 tcg_gen_andc_i32(tmp, tmp, tmp2);
1563 tcg_temp_free_i32(tmp2);
1564 iwmmxt_store_creg(wrd, tmp);
1565 break;
1566 case ARM_IWMMXT_wCGR0:
1567 case ARM_IWMMXT_wCGR1:
1568 case ARM_IWMMXT_wCGR2:
1569 case ARM_IWMMXT_wCGR3:
1570 gen_op_iwmmxt_set_cup();
1571 tmp = load_reg(s, rd);
1572 iwmmxt_store_creg(wrd, tmp);
1573 break;
1574 default:
1575 return 1;
1577 break;
1578 case 0x100: /* WXOR */
1579 wrd = (insn >> 12) & 0xf;
1580 rd0 = (insn >> 0) & 0xf;
1581 rd1 = (insn >> 16) & 0xf;
1582 gen_op_iwmmxt_movq_M0_wRn(rd0);
1583 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1584 gen_op_iwmmxt_setpsr_nz();
1585 gen_op_iwmmxt_movq_wRn_M0(wrd);
1586 gen_op_iwmmxt_set_mup();
1587 gen_op_iwmmxt_set_cup();
1588 break;
1589 case 0x111: /* TMRC */
1590 if (insn & 0xf)
1591 return 1;
1592 rd = (insn >> 12) & 0xf;
1593 wrd = (insn >> 16) & 0xf;
1594 tmp = iwmmxt_load_creg(wrd);
1595 store_reg(s, rd, tmp);
1596 break;
1597 case 0x300: /* WANDN */
1598 wrd = (insn >> 12) & 0xf;
1599 rd0 = (insn >> 0) & 0xf;
1600 rd1 = (insn >> 16) & 0xf;
1601 gen_op_iwmmxt_movq_M0_wRn(rd0);
1602 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1603 gen_op_iwmmxt_andq_M0_wRn(rd1);
1604 gen_op_iwmmxt_setpsr_nz();
1605 gen_op_iwmmxt_movq_wRn_M0(wrd);
1606 gen_op_iwmmxt_set_mup();
1607 gen_op_iwmmxt_set_cup();
1608 break;
1609 case 0x200: /* WAND */
1610 wrd = (insn >> 12) & 0xf;
1611 rd0 = (insn >> 0) & 0xf;
1612 rd1 = (insn >> 16) & 0xf;
1613 gen_op_iwmmxt_movq_M0_wRn(rd0);
1614 gen_op_iwmmxt_andq_M0_wRn(rd1);
1615 gen_op_iwmmxt_setpsr_nz();
1616 gen_op_iwmmxt_movq_wRn_M0(wrd);
1617 gen_op_iwmmxt_set_mup();
1618 gen_op_iwmmxt_set_cup();
1619 break;
1620 case 0x810: case 0xa10: /* WMADD */
1621 wrd = (insn >> 12) & 0xf;
1622 rd0 = (insn >> 0) & 0xf;
1623 rd1 = (insn >> 16) & 0xf;
1624 gen_op_iwmmxt_movq_M0_wRn(rd0);
1625 if (insn & (1 << 21))
1626 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1627 else
1628 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1629 gen_op_iwmmxt_movq_wRn_M0(wrd);
1630 gen_op_iwmmxt_set_mup();
1631 break;
1632 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1633 wrd = (insn >> 12) & 0xf;
1634 rd0 = (insn >> 16) & 0xf;
1635 rd1 = (insn >> 0) & 0xf;
1636 gen_op_iwmmxt_movq_M0_wRn(rd0);
1637 switch ((insn >> 22) & 3) {
1638 case 0:
1639 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1640 break;
1641 case 1:
1642 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1643 break;
1644 case 2:
1645 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1646 break;
1647 case 3:
1648 return 1;
1650 gen_op_iwmmxt_movq_wRn_M0(wrd);
1651 gen_op_iwmmxt_set_mup();
1652 gen_op_iwmmxt_set_cup();
1653 break;
1654 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1655 wrd = (insn >> 12) & 0xf;
1656 rd0 = (insn >> 16) & 0xf;
1657 rd1 = (insn >> 0) & 0xf;
1658 gen_op_iwmmxt_movq_M0_wRn(rd0);
1659 switch ((insn >> 22) & 3) {
1660 case 0:
1661 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1662 break;
1663 case 1:
1664 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1665 break;
1666 case 2:
1667 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1668 break;
1669 case 3:
1670 return 1;
1672 gen_op_iwmmxt_movq_wRn_M0(wrd);
1673 gen_op_iwmmxt_set_mup();
1674 gen_op_iwmmxt_set_cup();
1675 break;
1676 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1677 wrd = (insn >> 12) & 0xf;
1678 rd0 = (insn >> 16) & 0xf;
1679 rd1 = (insn >> 0) & 0xf;
1680 gen_op_iwmmxt_movq_M0_wRn(rd0);
1681 if (insn & (1 << 22))
1682 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1683 else
1684 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1685 if (!(insn & (1 << 20)))
1686 gen_op_iwmmxt_addl_M0_wRn(wrd);
1687 gen_op_iwmmxt_movq_wRn_M0(wrd);
1688 gen_op_iwmmxt_set_mup();
1689 break;
1690 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1691 wrd = (insn >> 12) & 0xf;
1692 rd0 = (insn >> 16) & 0xf;
1693 rd1 = (insn >> 0) & 0xf;
1694 gen_op_iwmmxt_movq_M0_wRn(rd0);
1695 if (insn & (1 << 21)) {
1696 if (insn & (1 << 20))
1697 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1698 else
1699 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1700 } else {
1701 if (insn & (1 << 20))
1702 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1703 else
1704 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1706 gen_op_iwmmxt_movq_wRn_M0(wrd);
1707 gen_op_iwmmxt_set_mup();
1708 break;
1709 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1710 wrd = (insn >> 12) & 0xf;
1711 rd0 = (insn >> 16) & 0xf;
1712 rd1 = (insn >> 0) & 0xf;
1713 gen_op_iwmmxt_movq_M0_wRn(rd0);
1714 if (insn & (1 << 21))
1715 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1716 else
1717 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1718 if (!(insn & (1 << 20))) {
1719 iwmmxt_load_reg(cpu_V1, wrd);
1720 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1722 gen_op_iwmmxt_movq_wRn_M0(wrd);
1723 gen_op_iwmmxt_set_mup();
1724 break;
1725 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1726 wrd = (insn >> 12) & 0xf;
1727 rd0 = (insn >> 16) & 0xf;
1728 rd1 = (insn >> 0) & 0xf;
1729 gen_op_iwmmxt_movq_M0_wRn(rd0);
1730 switch ((insn >> 22) & 3) {
1731 case 0:
1732 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1733 break;
1734 case 1:
1735 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1736 break;
1737 case 2:
1738 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1739 break;
1740 case 3:
1741 return 1;
1743 gen_op_iwmmxt_movq_wRn_M0(wrd);
1744 gen_op_iwmmxt_set_mup();
1745 gen_op_iwmmxt_set_cup();
1746 break;
1747 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1748 wrd = (insn >> 12) & 0xf;
1749 rd0 = (insn >> 16) & 0xf;
1750 rd1 = (insn >> 0) & 0xf;
1751 gen_op_iwmmxt_movq_M0_wRn(rd0);
1752 if (insn & (1 << 22)) {
1753 if (insn & (1 << 20))
1754 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1755 else
1756 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1757 } else {
1758 if (insn & (1 << 20))
1759 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1760 else
1761 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1763 gen_op_iwmmxt_movq_wRn_M0(wrd);
1764 gen_op_iwmmxt_set_mup();
1765 gen_op_iwmmxt_set_cup();
1766 break;
1767 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1768 wrd = (insn >> 12) & 0xf;
1769 rd0 = (insn >> 16) & 0xf;
1770 rd1 = (insn >> 0) & 0xf;
1771 gen_op_iwmmxt_movq_M0_wRn(rd0);
1772 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1773 tcg_gen_andi_i32(tmp, tmp, 7);
1774 iwmmxt_load_reg(cpu_V1, rd1);
1775 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1776 tcg_temp_free_i32(tmp);
1777 gen_op_iwmmxt_movq_wRn_M0(wrd);
1778 gen_op_iwmmxt_set_mup();
1779 break;
1780 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1781 if (((insn >> 6) & 3) == 3)
1782 return 1;
1783 rd = (insn >> 12) & 0xf;
1784 wrd = (insn >> 16) & 0xf;
1785 tmp = load_reg(s, rd);
1786 gen_op_iwmmxt_movq_M0_wRn(wrd);
1787 switch ((insn >> 6) & 3) {
1788 case 0:
1789 tmp2 = tcg_const_i32(0xff);
1790 tmp3 = tcg_const_i32((insn & 7) << 3);
1791 break;
1792 case 1:
1793 tmp2 = tcg_const_i32(0xffff);
1794 tmp3 = tcg_const_i32((insn & 3) << 4);
1795 break;
1796 case 2:
1797 tmp2 = tcg_const_i32(0xffffffff);
1798 tmp3 = tcg_const_i32((insn & 1) << 5);
1799 break;
1800 default:
1801 TCGV_UNUSED_I32(tmp2);
1802 TCGV_UNUSED_I32(tmp3);
1804 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1805 tcg_temp_free_i32(tmp3);
1806 tcg_temp_free_i32(tmp2);
1807 tcg_temp_free_i32(tmp);
1808 gen_op_iwmmxt_movq_wRn_M0(wrd);
1809 gen_op_iwmmxt_set_mup();
1810 break;
1811 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1812 rd = (insn >> 12) & 0xf;
1813 wrd = (insn >> 16) & 0xf;
1814 if (rd == 15 || ((insn >> 22) & 3) == 3)
1815 return 1;
1816 gen_op_iwmmxt_movq_M0_wRn(wrd);
1817 tmp = tcg_temp_new_i32();
1818 switch ((insn >> 22) & 3) {
1819 case 0:
1820 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1821 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1822 if (insn & 8) {
1823 tcg_gen_ext8s_i32(tmp, tmp);
1824 } else {
1825 tcg_gen_andi_i32(tmp, tmp, 0xff);
1827 break;
1828 case 1:
1829 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1830 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1831 if (insn & 8) {
1832 tcg_gen_ext16s_i32(tmp, tmp);
1833 } else {
1834 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1836 break;
1837 case 2:
1838 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1839 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1840 break;
1842 store_reg(s, rd, tmp);
1843 break;
1844 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1845 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1846 return 1;
1847 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1848 switch ((insn >> 22) & 3) {
1849 case 0:
1850 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1851 break;
1852 case 1:
1853 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1854 break;
1855 case 2:
1856 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1857 break;
1859 tcg_gen_shli_i32(tmp, tmp, 28);
1860 gen_set_nzcv(tmp);
1861 tcg_temp_free_i32(tmp);
1862 break;
1863 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1864 if (((insn >> 6) & 3) == 3)
1865 return 1;
1866 rd = (insn >> 12) & 0xf;
1867 wrd = (insn >> 16) & 0xf;
1868 tmp = load_reg(s, rd);
1869 switch ((insn >> 6) & 3) {
1870 case 0:
1871 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1872 break;
1873 case 1:
1874 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1875 break;
1876 case 2:
1877 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1878 break;
1880 tcg_temp_free_i32(tmp);
1881 gen_op_iwmmxt_movq_wRn_M0(wrd);
1882 gen_op_iwmmxt_set_mup();
1883 break;
1884 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1885 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1886 return 1;
1887 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1888 tmp2 = tcg_temp_new_i32();
1889 tcg_gen_mov_i32(tmp2, tmp);
1890 switch ((insn >> 22) & 3) {
1891 case 0:
1892 for (i = 0; i < 7; i ++) {
1893 tcg_gen_shli_i32(tmp2, tmp2, 4);
1894 tcg_gen_and_i32(tmp, tmp, tmp2);
1896 break;
1897 case 1:
1898 for (i = 0; i < 3; i ++) {
1899 tcg_gen_shli_i32(tmp2, tmp2, 8);
1900 tcg_gen_and_i32(tmp, tmp, tmp2);
1902 break;
1903 case 2:
1904 tcg_gen_shli_i32(tmp2, tmp2, 16);
1905 tcg_gen_and_i32(tmp, tmp, tmp2);
1906 break;
1908 gen_set_nzcv(tmp);
1909 tcg_temp_free_i32(tmp2);
1910 tcg_temp_free_i32(tmp);
1911 break;
1912 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1913 wrd = (insn >> 12) & 0xf;
1914 rd0 = (insn >> 16) & 0xf;
1915 gen_op_iwmmxt_movq_M0_wRn(rd0);
1916 switch ((insn >> 22) & 3) {
1917 case 0:
1918 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1919 break;
1920 case 1:
1921 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1922 break;
1923 case 2:
1924 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1925 break;
1926 case 3:
1927 return 1;
1929 gen_op_iwmmxt_movq_wRn_M0(wrd);
1930 gen_op_iwmmxt_set_mup();
1931 break;
1932 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1933 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1934 return 1;
1935 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1936 tmp2 = tcg_temp_new_i32();
1937 tcg_gen_mov_i32(tmp2, tmp);
1938 switch ((insn >> 22) & 3) {
1939 case 0:
1940 for (i = 0; i < 7; i ++) {
1941 tcg_gen_shli_i32(tmp2, tmp2, 4);
1942 tcg_gen_or_i32(tmp, tmp, tmp2);
1944 break;
1945 case 1:
1946 for (i = 0; i < 3; i ++) {
1947 tcg_gen_shli_i32(tmp2, tmp2, 8);
1948 tcg_gen_or_i32(tmp, tmp, tmp2);
1950 break;
1951 case 2:
1952 tcg_gen_shli_i32(tmp2, tmp2, 16);
1953 tcg_gen_or_i32(tmp, tmp, tmp2);
1954 break;
1956 gen_set_nzcv(tmp);
1957 tcg_temp_free_i32(tmp2);
1958 tcg_temp_free_i32(tmp);
1959 break;
1960 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1961 rd = (insn >> 12) & 0xf;
1962 rd0 = (insn >> 16) & 0xf;
1963 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1964 return 1;
1965 gen_op_iwmmxt_movq_M0_wRn(rd0);
1966 tmp = tcg_temp_new_i32();
1967 switch ((insn >> 22) & 3) {
1968 case 0:
1969 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1970 break;
1971 case 1:
1972 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1973 break;
1974 case 2:
1975 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1976 break;
1978 store_reg(s, rd, tmp);
1979 break;
1980 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1981 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1982 wrd = (insn >> 12) & 0xf;
1983 rd0 = (insn >> 16) & 0xf;
1984 rd1 = (insn >> 0) & 0xf;
1985 gen_op_iwmmxt_movq_M0_wRn(rd0);
1986 switch ((insn >> 22) & 3) {
1987 case 0:
1988 if (insn & (1 << 21))
1989 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1990 else
1991 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1992 break;
1993 case 1:
1994 if (insn & (1 << 21))
1995 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1996 else
1997 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
1998 break;
1999 case 2:
2000 if (insn & (1 << 21))
2001 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2002 else
2003 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2004 break;
2005 case 3:
2006 return 1;
2008 gen_op_iwmmxt_movq_wRn_M0(wrd);
2009 gen_op_iwmmxt_set_mup();
2010 gen_op_iwmmxt_set_cup();
2011 break;
2012 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2013 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2014 wrd = (insn >> 12) & 0xf;
2015 rd0 = (insn >> 16) & 0xf;
2016 gen_op_iwmmxt_movq_M0_wRn(rd0);
2017 switch ((insn >> 22) & 3) {
2018 case 0:
2019 if (insn & (1 << 21))
2020 gen_op_iwmmxt_unpacklsb_M0();
2021 else
2022 gen_op_iwmmxt_unpacklub_M0();
2023 break;
2024 case 1:
2025 if (insn & (1 << 21))
2026 gen_op_iwmmxt_unpacklsw_M0();
2027 else
2028 gen_op_iwmmxt_unpackluw_M0();
2029 break;
2030 case 2:
2031 if (insn & (1 << 21))
2032 gen_op_iwmmxt_unpacklsl_M0();
2033 else
2034 gen_op_iwmmxt_unpacklul_M0();
2035 break;
2036 case 3:
2037 return 1;
2039 gen_op_iwmmxt_movq_wRn_M0(wrd);
2040 gen_op_iwmmxt_set_mup();
2041 gen_op_iwmmxt_set_cup();
2042 break;
2043 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2044 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2045 wrd = (insn >> 12) & 0xf;
2046 rd0 = (insn >> 16) & 0xf;
2047 gen_op_iwmmxt_movq_M0_wRn(rd0);
2048 switch ((insn >> 22) & 3) {
2049 case 0:
2050 if (insn & (1 << 21))
2051 gen_op_iwmmxt_unpackhsb_M0();
2052 else
2053 gen_op_iwmmxt_unpackhub_M0();
2054 break;
2055 case 1:
2056 if (insn & (1 << 21))
2057 gen_op_iwmmxt_unpackhsw_M0();
2058 else
2059 gen_op_iwmmxt_unpackhuw_M0();
2060 break;
2061 case 2:
2062 if (insn & (1 << 21))
2063 gen_op_iwmmxt_unpackhsl_M0();
2064 else
2065 gen_op_iwmmxt_unpackhul_M0();
2066 break;
2067 case 3:
2068 return 1;
2070 gen_op_iwmmxt_movq_wRn_M0(wrd);
2071 gen_op_iwmmxt_set_mup();
2072 gen_op_iwmmxt_set_cup();
2073 break;
2074 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2075 case 0x214: case 0x614: case 0xa14: case 0xe14:
2076 if (((insn >> 22) & 3) == 0)
2077 return 1;
2078 wrd = (insn >> 12) & 0xf;
2079 rd0 = (insn >> 16) & 0xf;
2080 gen_op_iwmmxt_movq_M0_wRn(rd0);
2081 tmp = tcg_temp_new_i32();
2082 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2083 tcg_temp_free_i32(tmp);
2084 return 1;
2086 switch ((insn >> 22) & 3) {
2087 case 1:
2088 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2089 break;
2090 case 2:
2091 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2092 break;
2093 case 3:
2094 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2095 break;
2097 tcg_temp_free_i32(tmp);
2098 gen_op_iwmmxt_movq_wRn_M0(wrd);
2099 gen_op_iwmmxt_set_mup();
2100 gen_op_iwmmxt_set_cup();
2101 break;
2102 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2103 case 0x014: case 0x414: case 0x814: case 0xc14:
2104 if (((insn >> 22) & 3) == 0)
2105 return 1;
2106 wrd = (insn >> 12) & 0xf;
2107 rd0 = (insn >> 16) & 0xf;
2108 gen_op_iwmmxt_movq_M0_wRn(rd0);
2109 tmp = tcg_temp_new_i32();
2110 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2111 tcg_temp_free_i32(tmp);
2112 return 1;
2114 switch ((insn >> 22) & 3) {
2115 case 1:
2116 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2117 break;
2118 case 2:
2119 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2120 break;
2121 case 3:
2122 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2123 break;
2125 tcg_temp_free_i32(tmp);
2126 gen_op_iwmmxt_movq_wRn_M0(wrd);
2127 gen_op_iwmmxt_set_mup();
2128 gen_op_iwmmxt_set_cup();
2129 break;
2130 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2131 case 0x114: case 0x514: case 0x914: case 0xd14:
2132 if (((insn >> 22) & 3) == 0)
2133 return 1;
2134 wrd = (insn >> 12) & 0xf;
2135 rd0 = (insn >> 16) & 0xf;
2136 gen_op_iwmmxt_movq_M0_wRn(rd0);
2137 tmp = tcg_temp_new_i32();
2138 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2139 tcg_temp_free_i32(tmp);
2140 return 1;
2142 switch ((insn >> 22) & 3) {
2143 case 1:
2144 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2145 break;
2146 case 2:
2147 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2148 break;
2149 case 3:
2150 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2151 break;
2153 tcg_temp_free_i32(tmp);
2154 gen_op_iwmmxt_movq_wRn_M0(wrd);
2155 gen_op_iwmmxt_set_mup();
2156 gen_op_iwmmxt_set_cup();
2157 break;
2158 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2159 case 0x314: case 0x714: case 0xb14: case 0xf14:
2160 if (((insn >> 22) & 3) == 0)
2161 return 1;
2162 wrd = (insn >> 12) & 0xf;
2163 rd0 = (insn >> 16) & 0xf;
2164 gen_op_iwmmxt_movq_M0_wRn(rd0);
2165 tmp = tcg_temp_new_i32();
2166 switch ((insn >> 22) & 3) {
2167 case 1:
2168 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2169 tcg_temp_free_i32(tmp);
2170 return 1;
2172 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2173 break;
2174 case 2:
2175 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2176 tcg_temp_free_i32(tmp);
2177 return 1;
2179 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2180 break;
2181 case 3:
2182 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2183 tcg_temp_free_i32(tmp);
2184 return 1;
2186 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2187 break;
2189 tcg_temp_free_i32(tmp);
2190 gen_op_iwmmxt_movq_wRn_M0(wrd);
2191 gen_op_iwmmxt_set_mup();
2192 gen_op_iwmmxt_set_cup();
2193 break;
2194 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2195 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2196 wrd = (insn >> 12) & 0xf;
2197 rd0 = (insn >> 16) & 0xf;
2198 rd1 = (insn >> 0) & 0xf;
2199 gen_op_iwmmxt_movq_M0_wRn(rd0);
2200 switch ((insn >> 22) & 3) {
2201 case 0:
2202 if (insn & (1 << 21))
2203 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2204 else
2205 gen_op_iwmmxt_minub_M0_wRn(rd1);
2206 break;
2207 case 1:
2208 if (insn & (1 << 21))
2209 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2210 else
2211 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2212 break;
2213 case 2:
2214 if (insn & (1 << 21))
2215 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2216 else
2217 gen_op_iwmmxt_minul_M0_wRn(rd1);
2218 break;
2219 case 3:
2220 return 1;
2222 gen_op_iwmmxt_movq_wRn_M0(wrd);
2223 gen_op_iwmmxt_set_mup();
2224 break;
2225 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2226 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2227 wrd = (insn >> 12) & 0xf;
2228 rd0 = (insn >> 16) & 0xf;
2229 rd1 = (insn >> 0) & 0xf;
2230 gen_op_iwmmxt_movq_M0_wRn(rd0);
2231 switch ((insn >> 22) & 3) {
2232 case 0:
2233 if (insn & (1 << 21))
2234 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2235 else
2236 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2237 break;
2238 case 1:
2239 if (insn & (1 << 21))
2240 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2241 else
2242 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2243 break;
2244 case 2:
2245 if (insn & (1 << 21))
2246 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2247 else
2248 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2249 break;
2250 case 3:
2251 return 1;
2253 gen_op_iwmmxt_movq_wRn_M0(wrd);
2254 gen_op_iwmmxt_set_mup();
2255 break;
2256 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2257 case 0x402: case 0x502: case 0x602: case 0x702:
2258 wrd = (insn >> 12) & 0xf;
2259 rd0 = (insn >> 16) & 0xf;
2260 rd1 = (insn >> 0) & 0xf;
2261 gen_op_iwmmxt_movq_M0_wRn(rd0);
2262 tmp = tcg_const_i32((insn >> 20) & 3);
2263 iwmmxt_load_reg(cpu_V1, rd1);
2264 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2265 tcg_temp_free_i32(tmp);
2266 gen_op_iwmmxt_movq_wRn_M0(wrd);
2267 gen_op_iwmmxt_set_mup();
2268 break;
2269 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2270 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2271 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2272 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2273 wrd = (insn >> 12) & 0xf;
2274 rd0 = (insn >> 16) & 0xf;
2275 rd1 = (insn >> 0) & 0xf;
2276 gen_op_iwmmxt_movq_M0_wRn(rd0);
2277 switch ((insn >> 20) & 0xf) {
2278 case 0x0:
2279 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2280 break;
2281 case 0x1:
2282 gen_op_iwmmxt_subub_M0_wRn(rd1);
2283 break;
2284 case 0x3:
2285 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2286 break;
2287 case 0x4:
2288 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2289 break;
2290 case 0x5:
2291 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2292 break;
2293 case 0x7:
2294 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2295 break;
2296 case 0x8:
2297 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2298 break;
2299 case 0x9:
2300 gen_op_iwmmxt_subul_M0_wRn(rd1);
2301 break;
2302 case 0xb:
2303 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2304 break;
2305 default:
2306 return 1;
2308 gen_op_iwmmxt_movq_wRn_M0(wrd);
2309 gen_op_iwmmxt_set_mup();
2310 gen_op_iwmmxt_set_cup();
2311 break;
2312 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2313 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2314 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2315 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2316 wrd = (insn >> 12) & 0xf;
2317 rd0 = (insn >> 16) & 0xf;
2318 gen_op_iwmmxt_movq_M0_wRn(rd0);
2319 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2320 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2321 tcg_temp_free_i32(tmp);
2322 gen_op_iwmmxt_movq_wRn_M0(wrd);
2323 gen_op_iwmmxt_set_mup();
2324 gen_op_iwmmxt_set_cup();
2325 break;
2326 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2327 case 0x418: case 0x518: case 0x618: case 0x718:
2328 case 0x818: case 0x918: case 0xa18: case 0xb18:
2329 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2330 wrd = (insn >> 12) & 0xf;
2331 rd0 = (insn >> 16) & 0xf;
2332 rd1 = (insn >> 0) & 0xf;
2333 gen_op_iwmmxt_movq_M0_wRn(rd0);
2334 switch ((insn >> 20) & 0xf) {
2335 case 0x0:
2336 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2337 break;
2338 case 0x1:
2339 gen_op_iwmmxt_addub_M0_wRn(rd1);
2340 break;
2341 case 0x3:
2342 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2343 break;
2344 case 0x4:
2345 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2346 break;
2347 case 0x5:
2348 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2349 break;
2350 case 0x7:
2351 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2352 break;
2353 case 0x8:
2354 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2355 break;
2356 case 0x9:
2357 gen_op_iwmmxt_addul_M0_wRn(rd1);
2358 break;
2359 case 0xb:
2360 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2361 break;
2362 default:
2363 return 1;
2365 gen_op_iwmmxt_movq_wRn_M0(wrd);
2366 gen_op_iwmmxt_set_mup();
2367 gen_op_iwmmxt_set_cup();
2368 break;
2369 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2370 case 0x408: case 0x508: case 0x608: case 0x708:
2371 case 0x808: case 0x908: case 0xa08: case 0xb08:
2372 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2373 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2374 return 1;
2375 wrd = (insn >> 12) & 0xf;
2376 rd0 = (insn >> 16) & 0xf;
2377 rd1 = (insn >> 0) & 0xf;
2378 gen_op_iwmmxt_movq_M0_wRn(rd0);
2379 switch ((insn >> 22) & 3) {
2380 case 1:
2381 if (insn & (1 << 21))
2382 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2383 else
2384 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2385 break;
2386 case 2:
2387 if (insn & (1 << 21))
2388 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2389 else
2390 gen_op_iwmmxt_packul_M0_wRn(rd1);
2391 break;
2392 case 3:
2393 if (insn & (1 << 21))
2394 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2395 else
2396 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2397 break;
2399 gen_op_iwmmxt_movq_wRn_M0(wrd);
2400 gen_op_iwmmxt_set_mup();
2401 gen_op_iwmmxt_set_cup();
2402 break;
2403 case 0x201: case 0x203: case 0x205: case 0x207:
2404 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2405 case 0x211: case 0x213: case 0x215: case 0x217:
2406 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2407 wrd = (insn >> 5) & 0xf;
2408 rd0 = (insn >> 12) & 0xf;
2409 rd1 = (insn >> 0) & 0xf;
2410 if (rd0 == 0xf || rd1 == 0xf)
2411 return 1;
2412 gen_op_iwmmxt_movq_M0_wRn(wrd);
2413 tmp = load_reg(s, rd0);
2414 tmp2 = load_reg(s, rd1);
2415 switch ((insn >> 16) & 0xf) {
2416 case 0x0: /* TMIA */
2417 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2418 break;
2419 case 0x8: /* TMIAPH */
2420 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2421 break;
2422 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2423 if (insn & (1 << 16))
2424 tcg_gen_shri_i32(tmp, tmp, 16);
2425 if (insn & (1 << 17))
2426 tcg_gen_shri_i32(tmp2, tmp2, 16);
2427 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2428 break;
2429 default:
2430 tcg_temp_free_i32(tmp2);
2431 tcg_temp_free_i32(tmp);
2432 return 1;
2434 tcg_temp_free_i32(tmp2);
2435 tcg_temp_free_i32(tmp);
2436 gen_op_iwmmxt_movq_wRn_M0(wrd);
2437 gen_op_iwmmxt_set_mup();
2438 break;
2439 default:
2440 return 1;
2443 return 0;
2446 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2447 (ie. an undefined instruction). */
2448 static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2450 int acc, rd0, rd1, rdhi, rdlo;
2451 TCGv_i32 tmp, tmp2;
2453 if ((insn & 0x0ff00f10) == 0x0e200010) {
2454 /* Multiply with Internal Accumulate Format */
2455 rd0 = (insn >> 12) & 0xf;
2456 rd1 = insn & 0xf;
2457 acc = (insn >> 5) & 7;
2459 if (acc != 0)
2460 return 1;
2462 tmp = load_reg(s, rd0);
2463 tmp2 = load_reg(s, rd1);
2464 switch ((insn >> 16) & 0xf) {
2465 case 0x0: /* MIA */
2466 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2467 break;
2468 case 0x8: /* MIAPH */
2469 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2470 break;
2471 case 0xc: /* MIABB */
2472 case 0xd: /* MIABT */
2473 case 0xe: /* MIATB */
2474 case 0xf: /* MIATT */
2475 if (insn & (1 << 16))
2476 tcg_gen_shri_i32(tmp, tmp, 16);
2477 if (insn & (1 << 17))
2478 tcg_gen_shri_i32(tmp2, tmp2, 16);
2479 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2480 break;
2481 default:
2482 return 1;
2484 tcg_temp_free_i32(tmp2);
2485 tcg_temp_free_i32(tmp);
2487 gen_op_iwmmxt_movq_wRn_M0(acc);
2488 return 0;
2491 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2492 /* Internal Accumulator Access Format */
2493 rdhi = (insn >> 16) & 0xf;
2494 rdlo = (insn >> 12) & 0xf;
2495 acc = insn & 7;
2497 if (acc != 0)
2498 return 1;
2500 if (insn & ARM_CP_RW_BIT) { /* MRA */
2501 iwmmxt_load_reg(cpu_V0, acc);
2502 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2503 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2504 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2505 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2506 } else { /* MAR */
2507 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2508 iwmmxt_store_reg(cpu_V0, acc);
2510 return 0;
2513 return 1;
2516 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2517 #define VFP_SREG(insn, bigbit, smallbit) \
2518 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2519 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2520 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2521 reg = (((insn) >> (bigbit)) & 0x0f) \
2522 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2523 } else { \
2524 if (insn & (1 << (smallbit))) \
2525 return 1; \
2526 reg = ((insn) >> (bigbit)) & 0x0f; \
2527 }} while (0)
2529 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2530 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2531 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2532 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2533 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2534 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2536 /* Move between integer and VFP cores. */
2537 static TCGv_i32 gen_vfp_mrs(void)
2539 TCGv_i32 tmp = tcg_temp_new_i32();
2540 tcg_gen_mov_i32(tmp, cpu_F0s);
2541 return tmp;
2544 static void gen_vfp_msr(TCGv_i32 tmp)
2546 tcg_gen_mov_i32(cpu_F0s, tmp);
2547 tcg_temp_free_i32(tmp);
2550 static void gen_neon_dup_u8(TCGv_i32 var, int shift)
2552 TCGv_i32 tmp = tcg_temp_new_i32();
2553 if (shift)
2554 tcg_gen_shri_i32(var, var, shift);
2555 tcg_gen_ext8u_i32(var, var);
2556 tcg_gen_shli_i32(tmp, var, 8);
2557 tcg_gen_or_i32(var, var, tmp);
2558 tcg_gen_shli_i32(tmp, var, 16);
2559 tcg_gen_or_i32(var, var, tmp);
2560 tcg_temp_free_i32(tmp);
2563 static void gen_neon_dup_low16(TCGv_i32 var)
2565 TCGv_i32 tmp = tcg_temp_new_i32();
2566 tcg_gen_ext16u_i32(var, var);
2567 tcg_gen_shli_i32(tmp, var, 16);
2568 tcg_gen_or_i32(var, var, tmp);
2569 tcg_temp_free_i32(tmp);
2572 static void gen_neon_dup_high16(TCGv_i32 var)
2574 TCGv_i32 tmp = tcg_temp_new_i32();
2575 tcg_gen_andi_i32(var, var, 0xffff0000);
2576 tcg_gen_shri_i32(tmp, var, 16);
2577 tcg_gen_or_i32(var, var, tmp);
2578 tcg_temp_free_i32(tmp);
2581 static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
2583 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2584 TCGv_i32 tmp = tcg_temp_new_i32();
2585 switch (size) {
2586 case 0:
2587 gen_aa32_ld8u(tmp, addr, IS_USER(s));
2588 gen_neon_dup_u8(tmp, 0);
2589 break;
2590 case 1:
2591 gen_aa32_ld16u(tmp, addr, IS_USER(s));
2592 gen_neon_dup_low16(tmp);
2593 break;
2594 case 2:
2595 gen_aa32_ld32u(tmp, addr, IS_USER(s));
2596 break;
2597 default: /* Avoid compiler warnings. */
2598 abort();
2600 return tmp;
2603 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2604 uint32_t dp)
2606 uint32_t cc = extract32(insn, 20, 2);
2608 if (dp) {
2609 TCGv_i64 frn, frm, dest;
2610 TCGv_i64 tmp, zero, zf, nf, vf;
2612 zero = tcg_const_i64(0);
2614 frn = tcg_temp_new_i64();
2615 frm = tcg_temp_new_i64();
2616 dest = tcg_temp_new_i64();
2618 zf = tcg_temp_new_i64();
2619 nf = tcg_temp_new_i64();
2620 vf = tcg_temp_new_i64();
2622 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2623 tcg_gen_ext_i32_i64(nf, cpu_NF);
2624 tcg_gen_ext_i32_i64(vf, cpu_VF);
2626 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2627 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2628 switch (cc) {
2629 case 0: /* eq: Z */
2630 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2631 frn, frm);
2632 break;
2633 case 1: /* vs: V */
2634 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2635 frn, frm);
2636 break;
2637 case 2: /* ge: N == V -> N ^ V == 0 */
2638 tmp = tcg_temp_new_i64();
2639 tcg_gen_xor_i64(tmp, vf, nf);
2640 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2641 frn, frm);
2642 tcg_temp_free_i64(tmp);
2643 break;
2644 case 3: /* gt: !Z && N == V */
2645 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2646 frn, frm);
2647 tmp = tcg_temp_new_i64();
2648 tcg_gen_xor_i64(tmp, vf, nf);
2649 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2650 dest, frm);
2651 tcg_temp_free_i64(tmp);
2652 break;
2654 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2655 tcg_temp_free_i64(frn);
2656 tcg_temp_free_i64(frm);
2657 tcg_temp_free_i64(dest);
2659 tcg_temp_free_i64(zf);
2660 tcg_temp_free_i64(nf);
2661 tcg_temp_free_i64(vf);
2663 tcg_temp_free_i64(zero);
2664 } else {
2665 TCGv_i32 frn, frm, dest;
2666 TCGv_i32 tmp, zero;
2668 zero = tcg_const_i32(0);
2670 frn = tcg_temp_new_i32();
2671 frm = tcg_temp_new_i32();
2672 dest = tcg_temp_new_i32();
2673 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2674 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2675 switch (cc) {
2676 case 0: /* eq: Z */
2677 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2678 frn, frm);
2679 break;
2680 case 1: /* vs: V */
2681 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2682 frn, frm);
2683 break;
2684 case 2: /* ge: N == V -> N ^ V == 0 */
2685 tmp = tcg_temp_new_i32();
2686 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2687 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2688 frn, frm);
2689 tcg_temp_free_i32(tmp);
2690 break;
2691 case 3: /* gt: !Z && N == V */
2692 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2693 frn, frm);
2694 tmp = tcg_temp_new_i32();
2695 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2696 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2697 dest, frm);
2698 tcg_temp_free_i32(tmp);
2699 break;
2701 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2702 tcg_temp_free_i32(frn);
2703 tcg_temp_free_i32(frm);
2704 tcg_temp_free_i32(dest);
2706 tcg_temp_free_i32(zero);
2709 return 0;
2712 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2713 uint32_t rm, uint32_t dp)
2715 uint32_t vmin = extract32(insn, 6, 1);
2716 TCGv_ptr fpst = get_fpstatus_ptr(0);
2718 if (dp) {
2719 TCGv_i64 frn, frm, dest;
2721 frn = tcg_temp_new_i64();
2722 frm = tcg_temp_new_i64();
2723 dest = tcg_temp_new_i64();
2725 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2726 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2727 if (vmin) {
2728 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
2729 } else {
2730 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
2732 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2733 tcg_temp_free_i64(frn);
2734 tcg_temp_free_i64(frm);
2735 tcg_temp_free_i64(dest);
2736 } else {
2737 TCGv_i32 frn, frm, dest;
2739 frn = tcg_temp_new_i32();
2740 frm = tcg_temp_new_i32();
2741 dest = tcg_temp_new_i32();
2743 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2744 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2745 if (vmin) {
2746 gen_helper_vfp_minnums(dest, frn, frm, fpst);
2747 } else {
2748 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
2750 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2751 tcg_temp_free_i32(frn);
2752 tcg_temp_free_i32(frm);
2753 tcg_temp_free_i32(dest);
2756 tcg_temp_free_ptr(fpst);
2757 return 0;
2760 static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2762 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
2764 if (!arm_feature(env, ARM_FEATURE_V8)) {
2765 return 1;
2768 if (dp) {
2769 VFP_DREG_D(rd, insn);
2770 VFP_DREG_N(rn, insn);
2771 VFP_DREG_M(rm, insn);
2772 } else {
2773 rd = VFP_SREG_D(insn);
2774 rn = VFP_SREG_N(insn);
2775 rm = VFP_SREG_M(insn);
2778 if ((insn & 0x0f800e50) == 0x0e000a00) {
2779 return handle_vsel(insn, rd, rn, rm, dp);
2780 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
2781 return handle_vminmaxnm(insn, rd, rn, rm, dp);
2783 return 1;
2786 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2787 (ie. an undefined instruction). */
2788 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
2790 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2791 int dp, veclen;
2792 TCGv_i32 addr;
2793 TCGv_i32 tmp;
2794 TCGv_i32 tmp2;
2796 if (!arm_feature(env, ARM_FEATURE_VFP))
2797 return 1;
2799 if (!s->vfp_enabled) {
2800 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2801 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2802 return 1;
2803 rn = (insn >> 16) & 0xf;
2804 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2805 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2806 return 1;
2809 if (extract32(insn, 28, 4) == 0xf) {
2810 /* Encodings with T=1 (Thumb) or unconditional (ARM):
2811 * only used in v8 and above.
2813 return disas_vfp_v8_insn(env, s, insn);
2816 dp = ((insn & 0xf00) == 0xb00);
2817 switch ((insn >> 24) & 0xf) {
2818 case 0xe:
2819 if (insn & (1 << 4)) {
2820 /* single register transfer */
2821 rd = (insn >> 12) & 0xf;
2822 if (dp) {
2823 int size;
2824 int pass;
2826 VFP_DREG_N(rn, insn);
2827 if (insn & 0xf)
2828 return 1;
2829 if (insn & 0x00c00060
2830 && !arm_feature(env, ARM_FEATURE_NEON))
2831 return 1;
2833 pass = (insn >> 21) & 1;
2834 if (insn & (1 << 22)) {
2835 size = 0;
2836 offset = ((insn >> 5) & 3) * 8;
2837 } else if (insn & (1 << 5)) {
2838 size = 1;
2839 offset = (insn & (1 << 6)) ? 16 : 0;
2840 } else {
2841 size = 2;
2842 offset = 0;
2844 if (insn & ARM_CP_RW_BIT) {
2845 /* vfp->arm */
2846 tmp = neon_load_reg(rn, pass);
2847 switch (size) {
2848 case 0:
2849 if (offset)
2850 tcg_gen_shri_i32(tmp, tmp, offset);
2851 if (insn & (1 << 23))
2852 gen_uxtb(tmp);
2853 else
2854 gen_sxtb(tmp);
2855 break;
2856 case 1:
2857 if (insn & (1 << 23)) {
2858 if (offset) {
2859 tcg_gen_shri_i32(tmp, tmp, 16);
2860 } else {
2861 gen_uxth(tmp);
2863 } else {
2864 if (offset) {
2865 tcg_gen_sari_i32(tmp, tmp, 16);
2866 } else {
2867 gen_sxth(tmp);
2870 break;
2871 case 2:
2872 break;
2874 store_reg(s, rd, tmp);
2875 } else {
2876 /* arm->vfp */
2877 tmp = load_reg(s, rd);
2878 if (insn & (1 << 23)) {
2879 /* VDUP */
2880 if (size == 0) {
2881 gen_neon_dup_u8(tmp, 0);
2882 } else if (size == 1) {
2883 gen_neon_dup_low16(tmp);
2885 for (n = 0; n <= pass * 2; n++) {
2886 tmp2 = tcg_temp_new_i32();
2887 tcg_gen_mov_i32(tmp2, tmp);
2888 neon_store_reg(rn, n, tmp2);
2890 neon_store_reg(rn, n, tmp);
2891 } else {
2892 /* VMOV */
2893 switch (size) {
2894 case 0:
2895 tmp2 = neon_load_reg(rn, pass);
2896 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
2897 tcg_temp_free_i32(tmp2);
2898 break;
2899 case 1:
2900 tmp2 = neon_load_reg(rn, pass);
2901 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
2902 tcg_temp_free_i32(tmp2);
2903 break;
2904 case 2:
2905 break;
2907 neon_store_reg(rn, pass, tmp);
2910 } else { /* !dp */
2911 if ((insn & 0x6f) != 0x00)
2912 return 1;
2913 rn = VFP_SREG_N(insn);
2914 if (insn & ARM_CP_RW_BIT) {
2915 /* vfp->arm */
2916 if (insn & (1 << 21)) {
2917 /* system register */
2918 rn >>= 1;
2920 switch (rn) {
2921 case ARM_VFP_FPSID:
2922 /* VFP2 allows access to FSID from userspace.
2923 VFP3 restricts all id registers to privileged
2924 accesses. */
2925 if (IS_USER(s)
2926 && arm_feature(env, ARM_FEATURE_VFP3))
2927 return 1;
2928 tmp = load_cpu_field(vfp.xregs[rn]);
2929 break;
2930 case ARM_VFP_FPEXC:
2931 if (IS_USER(s))
2932 return 1;
2933 tmp = load_cpu_field(vfp.xregs[rn]);
2934 break;
2935 case ARM_VFP_FPINST:
2936 case ARM_VFP_FPINST2:
2937 /* Not present in VFP3. */
2938 if (IS_USER(s)
2939 || arm_feature(env, ARM_FEATURE_VFP3))
2940 return 1;
2941 tmp = load_cpu_field(vfp.xregs[rn]);
2942 break;
2943 case ARM_VFP_FPSCR:
2944 if (rd == 15) {
2945 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2946 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2947 } else {
2948 tmp = tcg_temp_new_i32();
2949 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2951 break;
2952 case ARM_VFP_MVFR0:
2953 case ARM_VFP_MVFR1:
2954 if (IS_USER(s)
2955 || !arm_feature(env, ARM_FEATURE_MVFR))
2956 return 1;
2957 tmp = load_cpu_field(vfp.xregs[rn]);
2958 break;
2959 default:
2960 return 1;
2962 } else {
2963 gen_mov_F0_vreg(0, rn);
2964 tmp = gen_vfp_mrs();
2966 if (rd == 15) {
2967 /* Set the 4 flag bits in the CPSR. */
2968 gen_set_nzcv(tmp);
2969 tcg_temp_free_i32(tmp);
2970 } else {
2971 store_reg(s, rd, tmp);
2973 } else {
2974 /* arm->vfp */
2975 if (insn & (1 << 21)) {
2976 rn >>= 1;
2977 /* system register */
2978 switch (rn) {
2979 case ARM_VFP_FPSID:
2980 case ARM_VFP_MVFR0:
2981 case ARM_VFP_MVFR1:
2982 /* Writes are ignored. */
2983 break;
2984 case ARM_VFP_FPSCR:
2985 tmp = load_reg(s, rd);
2986 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2987 tcg_temp_free_i32(tmp);
2988 gen_lookup_tb(s);
2989 break;
2990 case ARM_VFP_FPEXC:
2991 if (IS_USER(s))
2992 return 1;
2993 /* TODO: VFP subarchitecture support.
2994 * For now, keep the EN bit only */
2995 tmp = load_reg(s, rd);
2996 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
2997 store_cpu_field(tmp, vfp.xregs[rn]);
2998 gen_lookup_tb(s);
2999 break;
3000 case ARM_VFP_FPINST:
3001 case ARM_VFP_FPINST2:
3002 tmp = load_reg(s, rd);
3003 store_cpu_field(tmp, vfp.xregs[rn]);
3004 break;
3005 default:
3006 return 1;
3008 } else {
3009 tmp = load_reg(s, rd);
3010 gen_vfp_msr(tmp);
3011 gen_mov_vreg_F0(0, rn);
3015 } else {
3016 /* data processing */
3017 /* The opcode is in bits 23, 21, 20 and 6. */
3018 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3019 if (dp) {
3020 if (op == 15) {
3021 /* rn is opcode */
3022 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3023 } else {
3024 /* rn is register number */
3025 VFP_DREG_N(rn, insn);
3028 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
3029 /* Integer or single precision destination. */
3030 rd = VFP_SREG_D(insn);
3031 } else {
3032 VFP_DREG_D(rd, insn);
3034 if (op == 15 &&
3035 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
3036 /* VCVT from int is always from S reg regardless of dp bit.
3037 * VCVT with immediate frac_bits has same format as SREG_M
3039 rm = VFP_SREG_M(insn);
3040 } else {
3041 VFP_DREG_M(rm, insn);
3043 } else {
3044 rn = VFP_SREG_N(insn);
3045 if (op == 15 && rn == 15) {
3046 /* Double precision destination. */
3047 VFP_DREG_D(rd, insn);
3048 } else {
3049 rd = VFP_SREG_D(insn);
3051 /* NB that we implicitly rely on the encoding for the frac_bits
3052 * in VCVT of fixed to float being the same as that of an SREG_M
3054 rm = VFP_SREG_M(insn);
3057 veclen = s->vec_len;
3058 if (op == 15 && rn > 3)
3059 veclen = 0;
3061 /* Shut up compiler warnings. */
3062 delta_m = 0;
3063 delta_d = 0;
3064 bank_mask = 0;
3066 if (veclen > 0) {
3067 if (dp)
3068 bank_mask = 0xc;
3069 else
3070 bank_mask = 0x18;
3072 /* Figure out what type of vector operation this is. */
3073 if ((rd & bank_mask) == 0) {
3074 /* scalar */
3075 veclen = 0;
3076 } else {
3077 if (dp)
3078 delta_d = (s->vec_stride >> 1) + 1;
3079 else
3080 delta_d = s->vec_stride + 1;
3082 if ((rm & bank_mask) == 0) {
3083 /* mixed scalar/vector */
3084 delta_m = 0;
3085 } else {
3086 /* vector */
3087 delta_m = delta_d;
3092 /* Load the initial operands. */
3093 if (op == 15) {
3094 switch (rn) {
3095 case 16:
3096 case 17:
3097 /* Integer source */
3098 gen_mov_F0_vreg(0, rm);
3099 break;
3100 case 8:
3101 case 9:
3102 /* Compare */
3103 gen_mov_F0_vreg(dp, rd);
3104 gen_mov_F1_vreg(dp, rm);
3105 break;
3106 case 10:
3107 case 11:
3108 /* Compare with zero */
3109 gen_mov_F0_vreg(dp, rd);
3110 gen_vfp_F1_ld0(dp);
3111 break;
3112 case 20:
3113 case 21:
3114 case 22:
3115 case 23:
3116 case 28:
3117 case 29:
3118 case 30:
3119 case 31:
3120 /* Source and destination the same. */
3121 gen_mov_F0_vreg(dp, rd);
3122 break;
3123 case 4:
3124 case 5:
3125 case 6:
3126 case 7:
3127 /* VCVTB, VCVTT: only present with the halfprec extension,
3128 * UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
3130 if (dp || !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3131 return 1;
3133 /* Otherwise fall through */
3134 default:
3135 /* One source operand. */
3136 gen_mov_F0_vreg(dp, rm);
3137 break;
3139 } else {
3140 /* Two source operands. */
3141 gen_mov_F0_vreg(dp, rn);
3142 gen_mov_F1_vreg(dp, rm);
3145 for (;;) {
3146 /* Perform the calculation. */
3147 switch (op) {
3148 case 0: /* VMLA: fd + (fn * fm) */
3149 /* Note that order of inputs to the add matters for NaNs */
3150 gen_vfp_F1_mul(dp);
3151 gen_mov_F0_vreg(dp, rd);
3152 gen_vfp_add(dp);
3153 break;
3154 case 1: /* VMLS: fd + -(fn * fm) */
3155 gen_vfp_mul(dp);
3156 gen_vfp_F1_neg(dp);
3157 gen_mov_F0_vreg(dp, rd);
3158 gen_vfp_add(dp);
3159 break;
3160 case 2: /* VNMLS: -fd + (fn * fm) */
3161 /* Note that it isn't valid to replace (-A + B) with (B - A)
3162 * or similar plausible looking simplifications
3163 * because this will give wrong results for NaNs.
3165 gen_vfp_F1_mul(dp);
3166 gen_mov_F0_vreg(dp, rd);
3167 gen_vfp_neg(dp);
3168 gen_vfp_add(dp);
3169 break;
3170 case 3: /* VNMLA: -fd + -(fn * fm) */
3171 gen_vfp_mul(dp);
3172 gen_vfp_F1_neg(dp);
3173 gen_mov_F0_vreg(dp, rd);
3174 gen_vfp_neg(dp);
3175 gen_vfp_add(dp);
3176 break;
3177 case 4: /* mul: fn * fm */
3178 gen_vfp_mul(dp);
3179 break;
3180 case 5: /* nmul: -(fn * fm) */
3181 gen_vfp_mul(dp);
3182 gen_vfp_neg(dp);
3183 break;
3184 case 6: /* add: fn + fm */
3185 gen_vfp_add(dp);
3186 break;
3187 case 7: /* sub: fn - fm */
3188 gen_vfp_sub(dp);
3189 break;
3190 case 8: /* div: fn / fm */
3191 gen_vfp_div(dp);
3192 break;
3193 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3194 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3195 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3196 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3197 /* These are fused multiply-add, and must be done as one
3198 * floating point operation with no rounding between the
3199 * multiplication and addition steps.
3200 * NB that doing the negations here as separate steps is
3201 * correct : an input NaN should come out with its sign bit
3202 * flipped if it is a negated-input.
3204 if (!arm_feature(env, ARM_FEATURE_VFP4)) {
3205 return 1;
3207 if (dp) {
3208 TCGv_ptr fpst;
3209 TCGv_i64 frd;
3210 if (op & 1) {
3211 /* VFNMS, VFMS */
3212 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3214 frd = tcg_temp_new_i64();
3215 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3216 if (op & 2) {
3217 /* VFNMA, VFNMS */
3218 gen_helper_vfp_negd(frd, frd);
3220 fpst = get_fpstatus_ptr(0);
3221 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3222 cpu_F1d, frd, fpst);
3223 tcg_temp_free_ptr(fpst);
3224 tcg_temp_free_i64(frd);
3225 } else {
3226 TCGv_ptr fpst;
3227 TCGv_i32 frd;
3228 if (op & 1) {
3229 /* VFNMS, VFMS */
3230 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3232 frd = tcg_temp_new_i32();
3233 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3234 if (op & 2) {
3235 gen_helper_vfp_negs(frd, frd);
3237 fpst = get_fpstatus_ptr(0);
3238 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3239 cpu_F1s, frd, fpst);
3240 tcg_temp_free_ptr(fpst);
3241 tcg_temp_free_i32(frd);
3243 break;
3244 case 14: /* fconst */
3245 if (!arm_feature(env, ARM_FEATURE_VFP3))
3246 return 1;
3248 n = (insn << 12) & 0x80000000;
3249 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3250 if (dp) {
3251 if (i & 0x40)
3252 i |= 0x3f80;
3253 else
3254 i |= 0x4000;
3255 n |= i << 16;
3256 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3257 } else {
3258 if (i & 0x40)
3259 i |= 0x780;
3260 else
3261 i |= 0x800;
3262 n |= i << 19;
3263 tcg_gen_movi_i32(cpu_F0s, n);
3265 break;
3266 case 15: /* extension space */
3267 switch (rn) {
3268 case 0: /* cpy */
3269 /* no-op */
3270 break;
3271 case 1: /* abs */
3272 gen_vfp_abs(dp);
3273 break;
3274 case 2: /* neg */
3275 gen_vfp_neg(dp);
3276 break;
3277 case 3: /* sqrt */
3278 gen_vfp_sqrt(dp);
3279 break;
3280 case 4: /* vcvtb.f32.f16 */
3281 tmp = gen_vfp_mrs();
3282 tcg_gen_ext16u_i32(tmp, tmp);
3283 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3284 tcg_temp_free_i32(tmp);
3285 break;
3286 case 5: /* vcvtt.f32.f16 */
3287 tmp = gen_vfp_mrs();
3288 tcg_gen_shri_i32(tmp, tmp, 16);
3289 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3290 tcg_temp_free_i32(tmp);
3291 break;
3292 case 6: /* vcvtb.f16.f32 */
3293 tmp = tcg_temp_new_i32();
3294 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3295 gen_mov_F0_vreg(0, rd);
3296 tmp2 = gen_vfp_mrs();
3297 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3298 tcg_gen_or_i32(tmp, tmp, tmp2);
3299 tcg_temp_free_i32(tmp2);
3300 gen_vfp_msr(tmp);
3301 break;
3302 case 7: /* vcvtt.f16.f32 */
3303 tmp = tcg_temp_new_i32();
3304 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3305 tcg_gen_shli_i32(tmp, tmp, 16);
3306 gen_mov_F0_vreg(0, rd);
3307 tmp2 = gen_vfp_mrs();
3308 tcg_gen_ext16u_i32(tmp2, tmp2);
3309 tcg_gen_or_i32(tmp, tmp, tmp2);
3310 tcg_temp_free_i32(tmp2);
3311 gen_vfp_msr(tmp);
3312 break;
3313 case 8: /* cmp */
3314 gen_vfp_cmp(dp);
3315 break;
3316 case 9: /* cmpe */
3317 gen_vfp_cmpe(dp);
3318 break;
3319 case 10: /* cmpz */
3320 gen_vfp_cmp(dp);
3321 break;
3322 case 11: /* cmpez */
3323 gen_vfp_F1_ld0(dp);
3324 gen_vfp_cmpe(dp);
3325 break;
3326 case 15: /* single<->double conversion */
3327 if (dp)
3328 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3329 else
3330 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3331 break;
3332 case 16: /* fuito */
3333 gen_vfp_uito(dp, 0);
3334 break;
3335 case 17: /* fsito */
3336 gen_vfp_sito(dp, 0);
3337 break;
3338 case 20: /* fshto */
3339 if (!arm_feature(env, ARM_FEATURE_VFP3))
3340 return 1;
3341 gen_vfp_shto(dp, 16 - rm, 0);
3342 break;
3343 case 21: /* fslto */
3344 if (!arm_feature(env, ARM_FEATURE_VFP3))
3345 return 1;
3346 gen_vfp_slto(dp, 32 - rm, 0);
3347 break;
3348 case 22: /* fuhto */
3349 if (!arm_feature(env, ARM_FEATURE_VFP3))
3350 return 1;
3351 gen_vfp_uhto(dp, 16 - rm, 0);
3352 break;
3353 case 23: /* fulto */
3354 if (!arm_feature(env, ARM_FEATURE_VFP3))
3355 return 1;
3356 gen_vfp_ulto(dp, 32 - rm, 0);
3357 break;
3358 case 24: /* ftoui */
3359 gen_vfp_toui(dp, 0);
3360 break;
3361 case 25: /* ftouiz */
3362 gen_vfp_touiz(dp, 0);
3363 break;
3364 case 26: /* ftosi */
3365 gen_vfp_tosi(dp, 0);
3366 break;
3367 case 27: /* ftosiz */
3368 gen_vfp_tosiz(dp, 0);
3369 break;
3370 case 28: /* ftosh */
3371 if (!arm_feature(env, ARM_FEATURE_VFP3))
3372 return 1;
3373 gen_vfp_tosh(dp, 16 - rm, 0);
3374 break;
3375 case 29: /* ftosl */
3376 if (!arm_feature(env, ARM_FEATURE_VFP3))
3377 return 1;
3378 gen_vfp_tosl(dp, 32 - rm, 0);
3379 break;
3380 case 30: /* ftouh */
3381 if (!arm_feature(env, ARM_FEATURE_VFP3))
3382 return 1;
3383 gen_vfp_touh(dp, 16 - rm, 0);
3384 break;
3385 case 31: /* ftoul */
3386 if (!arm_feature(env, ARM_FEATURE_VFP3))
3387 return 1;
3388 gen_vfp_toul(dp, 32 - rm, 0);
3389 break;
3390 default: /* undefined */
3391 return 1;
3393 break;
3394 default: /* undefined */
3395 return 1;
3398 /* Write back the result. */
3399 if (op == 15 && (rn >= 8 && rn <= 11))
3400 ; /* Comparison, do nothing. */
3401 else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3402 /* VCVT double to int: always integer result. */
3403 gen_mov_vreg_F0(0, rd);
3404 else if (op == 15 && rn == 15)
3405 /* conversion */
3406 gen_mov_vreg_F0(!dp, rd);
3407 else
3408 gen_mov_vreg_F0(dp, rd);
3410 /* break out of the loop if we have finished */
3411 if (veclen == 0)
3412 break;
3414 if (op == 15 && delta_m == 0) {
3415 /* single source one-many */
3416 while (veclen--) {
3417 rd = ((rd + delta_d) & (bank_mask - 1))
3418 | (rd & bank_mask);
3419 gen_mov_vreg_F0(dp, rd);
3421 break;
3423 /* Setup the next operands. */
3424 veclen--;
3425 rd = ((rd + delta_d) & (bank_mask - 1))
3426 | (rd & bank_mask);
3428 if (op == 15) {
3429 /* One source operand. */
3430 rm = ((rm + delta_m) & (bank_mask - 1))
3431 | (rm & bank_mask);
3432 gen_mov_F0_vreg(dp, rm);
3433 } else {
3434 /* Two source operands. */
3435 rn = ((rn + delta_d) & (bank_mask - 1))
3436 | (rn & bank_mask);
3437 gen_mov_F0_vreg(dp, rn);
3438 if (delta_m) {
3439 rm = ((rm + delta_m) & (bank_mask - 1))
3440 | (rm & bank_mask);
3441 gen_mov_F1_vreg(dp, rm);
3446 break;
3447 case 0xc:
3448 case 0xd:
3449 if ((insn & 0x03e00000) == 0x00400000) {
3450 /* two-register transfer */
3451 rn = (insn >> 16) & 0xf;
3452 rd = (insn >> 12) & 0xf;
3453 if (dp) {
3454 VFP_DREG_M(rm, insn);
3455 } else {
3456 rm = VFP_SREG_M(insn);
3459 if (insn & ARM_CP_RW_BIT) {
3460 /* vfp->arm */
3461 if (dp) {
3462 gen_mov_F0_vreg(0, rm * 2);
3463 tmp = gen_vfp_mrs();
3464 store_reg(s, rd, tmp);
3465 gen_mov_F0_vreg(0, rm * 2 + 1);
3466 tmp = gen_vfp_mrs();
3467 store_reg(s, rn, tmp);
3468 } else {
3469 gen_mov_F0_vreg(0, rm);
3470 tmp = gen_vfp_mrs();
3471 store_reg(s, rd, tmp);
3472 gen_mov_F0_vreg(0, rm + 1);
3473 tmp = gen_vfp_mrs();
3474 store_reg(s, rn, tmp);
3476 } else {
3477 /* arm->vfp */
3478 if (dp) {
3479 tmp = load_reg(s, rd);
3480 gen_vfp_msr(tmp);
3481 gen_mov_vreg_F0(0, rm * 2);
3482 tmp = load_reg(s, rn);
3483 gen_vfp_msr(tmp);
3484 gen_mov_vreg_F0(0, rm * 2 + 1);
3485 } else {
3486 tmp = load_reg(s, rd);
3487 gen_vfp_msr(tmp);
3488 gen_mov_vreg_F0(0, rm);
3489 tmp = load_reg(s, rn);
3490 gen_vfp_msr(tmp);
3491 gen_mov_vreg_F0(0, rm + 1);
3494 } else {
3495 /* Load/store */
3496 rn = (insn >> 16) & 0xf;
3497 if (dp)
3498 VFP_DREG_D(rd, insn);
3499 else
3500 rd = VFP_SREG_D(insn);
3501 if ((insn & 0x01200000) == 0x01000000) {
3502 /* Single load/store */
3503 offset = (insn & 0xff) << 2;
3504 if ((insn & (1 << 23)) == 0)
3505 offset = -offset;
3506 if (s->thumb && rn == 15) {
3507 /* This is actually UNPREDICTABLE */
3508 addr = tcg_temp_new_i32();
3509 tcg_gen_movi_i32(addr, s->pc & ~2);
3510 } else {
3511 addr = load_reg(s, rn);
3513 tcg_gen_addi_i32(addr, addr, offset);
3514 if (insn & (1 << 20)) {
3515 gen_vfp_ld(s, dp, addr);
3516 gen_mov_vreg_F0(dp, rd);
3517 } else {
3518 gen_mov_F0_vreg(dp, rd);
3519 gen_vfp_st(s, dp, addr);
3521 tcg_temp_free_i32(addr);
3522 } else {
3523 /* load/store multiple */
3524 int w = insn & (1 << 21);
3525 if (dp)
3526 n = (insn >> 1) & 0x7f;
3527 else
3528 n = insn & 0xff;
3530 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3531 /* P == U , W == 1 => UNDEF */
3532 return 1;
3534 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3535 /* UNPREDICTABLE cases for bad immediates: we choose to
3536 * UNDEF to avoid generating huge numbers of TCG ops
3538 return 1;
3540 if (rn == 15 && w) {
3541 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3542 return 1;
3545 if (s->thumb && rn == 15) {
3546 /* This is actually UNPREDICTABLE */
3547 addr = tcg_temp_new_i32();
3548 tcg_gen_movi_i32(addr, s->pc & ~2);
3549 } else {
3550 addr = load_reg(s, rn);
3552 if (insn & (1 << 24)) /* pre-decrement */
3553 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3555 if (dp)
3556 offset = 8;
3557 else
3558 offset = 4;
3559 for (i = 0; i < n; i++) {
3560 if (insn & ARM_CP_RW_BIT) {
3561 /* load */
3562 gen_vfp_ld(s, dp, addr);
3563 gen_mov_vreg_F0(dp, rd + i);
3564 } else {
3565 /* store */
3566 gen_mov_F0_vreg(dp, rd + i);
3567 gen_vfp_st(s, dp, addr);
3569 tcg_gen_addi_i32(addr, addr, offset);
3571 if (w) {
3572 /* writeback */
3573 if (insn & (1 << 24))
3574 offset = -offset * n;
3575 else if (dp && (insn & 1))
3576 offset = 4;
3577 else
3578 offset = 0;
3580 if (offset != 0)
3581 tcg_gen_addi_i32(addr, addr, offset);
3582 store_reg(s, rn, addr);
3583 } else {
3584 tcg_temp_free_i32(addr);
3588 break;
3589 default:
3590 /* Should never happen. */
3591 return 1;
3593 return 0;
3596 static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
3598 TranslationBlock *tb;
3600 tb = s->tb;
3601 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3602 tcg_gen_goto_tb(n);
3603 gen_set_pc_im(s, dest);
3604 tcg_gen_exit_tb((uintptr_t)tb + n);
3605 } else {
3606 gen_set_pc_im(s, dest);
3607 tcg_gen_exit_tb(0);
3611 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3613 if (unlikely(s->singlestep_enabled)) {
3614 /* An indirect jump so that we still trigger the debug exception. */
3615 if (s->thumb)
3616 dest |= 1;
3617 gen_bx_im(s, dest);
3618 } else {
3619 gen_goto_tb(s, 0, dest);
3620 s->is_jmp = DISAS_TB_JUMP;
3624 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
3626 if (x)
3627 tcg_gen_sari_i32(t0, t0, 16);
3628 else
3629 gen_sxth(t0);
3630 if (y)
3631 tcg_gen_sari_i32(t1, t1, 16);
3632 else
3633 gen_sxth(t1);
3634 tcg_gen_mul_i32(t0, t0, t1);
3637 /* Return the mask of PSR bits set by a MSR instruction. */
3638 static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
3639 uint32_t mask;
3641 mask = 0;
3642 if (flags & (1 << 0))
3643 mask |= 0xff;
3644 if (flags & (1 << 1))
3645 mask |= 0xff00;
3646 if (flags & (1 << 2))
3647 mask |= 0xff0000;
3648 if (flags & (1 << 3))
3649 mask |= 0xff000000;
3651 /* Mask out undefined bits. */
3652 mask &= ~CPSR_RESERVED;
3653 if (!arm_feature(env, ARM_FEATURE_V4T))
3654 mask &= ~CPSR_T;
3655 if (!arm_feature(env, ARM_FEATURE_V5))
3656 mask &= ~CPSR_Q; /* V5TE in reality*/
3657 if (!arm_feature(env, ARM_FEATURE_V6))
3658 mask &= ~(CPSR_E | CPSR_GE);
3659 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3660 mask &= ~CPSR_IT;
3661 /* Mask out execution state bits. */
3662 if (!spsr)
3663 mask &= ~CPSR_EXEC;
3664 /* Mask out privileged bits. */
3665 if (IS_USER(s))
3666 mask &= CPSR_USER;
3667 return mask;
3670 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3671 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
3673 TCGv_i32 tmp;
3674 if (spsr) {
3675 /* ??? This is also undefined in system mode. */
3676 if (IS_USER(s))
3677 return 1;
3679 tmp = load_cpu_field(spsr);
3680 tcg_gen_andi_i32(tmp, tmp, ~mask);
3681 tcg_gen_andi_i32(t0, t0, mask);
3682 tcg_gen_or_i32(tmp, tmp, t0);
3683 store_cpu_field(tmp, spsr);
3684 } else {
3685 gen_set_cpsr(t0, mask);
3687 tcg_temp_free_i32(t0);
3688 gen_lookup_tb(s);
3689 return 0;
3692 /* Returns nonzero if access to the PSR is not permitted. */
3693 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3695 TCGv_i32 tmp;
3696 tmp = tcg_temp_new_i32();
3697 tcg_gen_movi_i32(tmp, val);
3698 return gen_set_psr(s, mask, spsr, tmp);
3701 /* Generate an old-style exception return. Marks pc as dead. */
3702 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3704 TCGv_i32 tmp;
3705 store_reg(s, 15, pc);
3706 tmp = load_cpu_field(spsr);
3707 gen_set_cpsr(tmp, 0xffffffff);
3708 tcg_temp_free_i32(tmp);
3709 s->is_jmp = DISAS_UPDATE;
3712 /* Generate a v6 exception return. Marks both values as dead. */
3713 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
3715 gen_set_cpsr(cpsr, 0xffffffff);
3716 tcg_temp_free_i32(cpsr);
3717 store_reg(s, 15, pc);
3718 s->is_jmp = DISAS_UPDATE;
3721 static inline void
3722 gen_set_condexec (DisasContext *s)
3724 if (s->condexec_mask) {
3725 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3726 TCGv_i32 tmp = tcg_temp_new_i32();
3727 tcg_gen_movi_i32(tmp, val);
3728 store_cpu_field(tmp, condexec_bits);
3732 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3734 gen_set_condexec(s);
3735 gen_set_pc_im(s, s->pc - offset);
3736 gen_exception(excp);
3737 s->is_jmp = DISAS_JUMP;
3740 static void gen_nop_hint(DisasContext *s, int val)
3742 switch (val) {
3743 case 3: /* wfi */
3744 gen_set_pc_im(s, s->pc);
3745 s->is_jmp = DISAS_WFI;
3746 break;
3747 case 2: /* wfe */
3748 case 4: /* sev */
3749 case 5: /* sevl */
3750 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
3751 default: /* nop */
3752 break;
3756 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3758 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
3760 switch (size) {
3761 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3762 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3763 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3764 default: abort();
3768 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
3770 switch (size) {
3771 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3772 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3773 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3774 default: return;
3778 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3779 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3780 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3781 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3782 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3784 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3785 switch ((size << 1) | u) { \
3786 case 0: \
3787 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3788 break; \
3789 case 1: \
3790 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3791 break; \
3792 case 2: \
3793 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3794 break; \
3795 case 3: \
3796 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3797 break; \
3798 case 4: \
3799 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3800 break; \
3801 case 5: \
3802 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3803 break; \
3804 default: return 1; \
3805 }} while (0)
3807 #define GEN_NEON_INTEGER_OP(name) do { \
3808 switch ((size << 1) | u) { \
3809 case 0: \
3810 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3811 break; \
3812 case 1: \
3813 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3814 break; \
3815 case 2: \
3816 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3817 break; \
3818 case 3: \
3819 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3820 break; \
3821 case 4: \
3822 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3823 break; \
3824 case 5: \
3825 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3826 break; \
3827 default: return 1; \
3828 }} while (0)
3830 static TCGv_i32 neon_load_scratch(int scratch)
3832 TCGv_i32 tmp = tcg_temp_new_i32();
3833 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3834 return tmp;
3837 static void neon_store_scratch(int scratch, TCGv_i32 var)
3839 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3840 tcg_temp_free_i32(var);
3843 static inline TCGv_i32 neon_get_scalar(int size, int reg)
3845 TCGv_i32 tmp;
3846 if (size == 1) {
3847 tmp = neon_load_reg(reg & 7, reg >> 4);
3848 if (reg & 8) {
3849 gen_neon_dup_high16(tmp);
3850 } else {
3851 gen_neon_dup_low16(tmp);
3853 } else {
3854 tmp = neon_load_reg(reg & 15, reg >> 4);
3856 return tmp;
3859 static int gen_neon_unzip(int rd, int rm, int size, int q)
3861 TCGv_i32 tmp, tmp2;
3862 if (!q && size == 2) {
3863 return 1;
3865 tmp = tcg_const_i32(rd);
3866 tmp2 = tcg_const_i32(rm);
3867 if (q) {
3868 switch (size) {
3869 case 0:
3870 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3871 break;
3872 case 1:
3873 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3874 break;
3875 case 2:
3876 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3877 break;
3878 default:
3879 abort();
3881 } else {
3882 switch (size) {
3883 case 0:
3884 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3885 break;
3886 case 1:
3887 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3888 break;
3889 default:
3890 abort();
3893 tcg_temp_free_i32(tmp);
3894 tcg_temp_free_i32(tmp2);
3895 return 0;
3898 static int gen_neon_zip(int rd, int rm, int size, int q)
3900 TCGv_i32 tmp, tmp2;
3901 if (!q && size == 2) {
3902 return 1;
3904 tmp = tcg_const_i32(rd);
3905 tmp2 = tcg_const_i32(rm);
3906 if (q) {
3907 switch (size) {
3908 case 0:
3909 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3910 break;
3911 case 1:
3912 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3913 break;
3914 case 2:
3915 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3916 break;
3917 default:
3918 abort();
3920 } else {
3921 switch (size) {
3922 case 0:
3923 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3924 break;
3925 case 1:
3926 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3927 break;
3928 default:
3929 abort();
3932 tcg_temp_free_i32(tmp);
3933 tcg_temp_free_i32(tmp2);
3934 return 0;
3937 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
3939 TCGv_i32 rd, tmp;
3941 rd = tcg_temp_new_i32();
3942 tmp = tcg_temp_new_i32();
3944 tcg_gen_shli_i32(rd, t0, 8);
3945 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3946 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3947 tcg_gen_or_i32(rd, rd, tmp);
3949 tcg_gen_shri_i32(t1, t1, 8);
3950 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3951 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3952 tcg_gen_or_i32(t1, t1, tmp);
3953 tcg_gen_mov_i32(t0, rd);
3955 tcg_temp_free_i32(tmp);
3956 tcg_temp_free_i32(rd);
3959 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
3961 TCGv_i32 rd, tmp;
3963 rd = tcg_temp_new_i32();
3964 tmp = tcg_temp_new_i32();
3966 tcg_gen_shli_i32(rd, t0, 16);
3967 tcg_gen_andi_i32(tmp, t1, 0xffff);
3968 tcg_gen_or_i32(rd, rd, tmp);
3969 tcg_gen_shri_i32(t1, t1, 16);
3970 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3971 tcg_gen_or_i32(t1, t1, tmp);
3972 tcg_gen_mov_i32(t0, rd);
3974 tcg_temp_free_i32(tmp);
3975 tcg_temp_free_i32(rd);
3979 static struct {
3980 int nregs;
3981 int interleave;
3982 int spacing;
3983 } neon_ls_element_type[11] = {
3984 {4, 4, 1},
3985 {4, 4, 2},
3986 {4, 1, 1},
3987 {4, 2, 1},
3988 {3, 3, 1},
3989 {3, 3, 2},
3990 {3, 1, 1},
3991 {1, 1, 1},
3992 {2, 2, 1},
3993 {2, 2, 2},
3994 {2, 1, 1}
3997 /* Translate a NEON load/store element instruction. Return nonzero if the
3998 instruction is invalid. */
3999 static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4001 int rd, rn, rm;
4002 int op;
4003 int nregs;
4004 int interleave;
4005 int spacing;
4006 int stride;
4007 int size;
4008 int reg;
4009 int pass;
4010 int load;
4011 int shift;
4012 int n;
4013 TCGv_i32 addr;
4014 TCGv_i32 tmp;
4015 TCGv_i32 tmp2;
4016 TCGv_i64 tmp64;
4018 if (!s->vfp_enabled)
4019 return 1;
4020 VFP_DREG_D(rd, insn);
4021 rn = (insn >> 16) & 0xf;
4022 rm = insn & 0xf;
4023 load = (insn & (1 << 21)) != 0;
4024 if ((insn & (1 << 23)) == 0) {
4025 /* Load store all elements. */
4026 op = (insn >> 8) & 0xf;
4027 size = (insn >> 6) & 3;
4028 if (op > 10)
4029 return 1;
4030 /* Catch UNDEF cases for bad values of align field */
4031 switch (op & 0xc) {
4032 case 4:
4033 if (((insn >> 5) & 1) == 1) {
4034 return 1;
4036 break;
4037 case 8:
4038 if (((insn >> 4) & 3) == 3) {
4039 return 1;
4041 break;
4042 default:
4043 break;
4045 nregs = neon_ls_element_type[op].nregs;
4046 interleave = neon_ls_element_type[op].interleave;
4047 spacing = neon_ls_element_type[op].spacing;
4048 if (size == 3 && (interleave | spacing) != 1)
4049 return 1;
4050 addr = tcg_temp_new_i32();
4051 load_reg_var(s, addr, rn);
4052 stride = (1 << size) * interleave;
4053 for (reg = 0; reg < nregs; reg++) {
4054 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
4055 load_reg_var(s, addr, rn);
4056 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
4057 } else if (interleave == 2 && nregs == 4 && reg == 2) {
4058 load_reg_var(s, addr, rn);
4059 tcg_gen_addi_i32(addr, addr, 1 << size);
4061 if (size == 3) {
4062 tmp64 = tcg_temp_new_i64();
4063 if (load) {
4064 gen_aa32_ld64(tmp64, addr, IS_USER(s));
4065 neon_store_reg64(tmp64, rd);
4066 } else {
4067 neon_load_reg64(tmp64, rd);
4068 gen_aa32_st64(tmp64, addr, IS_USER(s));
4070 tcg_temp_free_i64(tmp64);
4071 tcg_gen_addi_i32(addr, addr, stride);
4072 } else {
4073 for (pass = 0; pass < 2; pass++) {
4074 if (size == 2) {
4075 if (load) {
4076 tmp = tcg_temp_new_i32();
4077 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4078 neon_store_reg(rd, pass, tmp);
4079 } else {
4080 tmp = neon_load_reg(rd, pass);
4081 gen_aa32_st32(tmp, addr, IS_USER(s));
4082 tcg_temp_free_i32(tmp);
4084 tcg_gen_addi_i32(addr, addr, stride);
4085 } else if (size == 1) {
4086 if (load) {
4087 tmp = tcg_temp_new_i32();
4088 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4089 tcg_gen_addi_i32(addr, addr, stride);
4090 tmp2 = tcg_temp_new_i32();
4091 gen_aa32_ld16u(tmp2, addr, IS_USER(s));
4092 tcg_gen_addi_i32(addr, addr, stride);
4093 tcg_gen_shli_i32(tmp2, tmp2, 16);
4094 tcg_gen_or_i32(tmp, tmp, tmp2);
4095 tcg_temp_free_i32(tmp2);
4096 neon_store_reg(rd, pass, tmp);
4097 } else {
4098 tmp = neon_load_reg(rd, pass);
4099 tmp2 = tcg_temp_new_i32();
4100 tcg_gen_shri_i32(tmp2, tmp, 16);
4101 gen_aa32_st16(tmp, addr, IS_USER(s));
4102 tcg_temp_free_i32(tmp);
4103 tcg_gen_addi_i32(addr, addr, stride);
4104 gen_aa32_st16(tmp2, addr, IS_USER(s));
4105 tcg_temp_free_i32(tmp2);
4106 tcg_gen_addi_i32(addr, addr, stride);
4108 } else /* size == 0 */ {
4109 if (load) {
4110 TCGV_UNUSED_I32(tmp2);
4111 for (n = 0; n < 4; n++) {
4112 tmp = tcg_temp_new_i32();
4113 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4114 tcg_gen_addi_i32(addr, addr, stride);
4115 if (n == 0) {
4116 tmp2 = tmp;
4117 } else {
4118 tcg_gen_shli_i32(tmp, tmp, n * 8);
4119 tcg_gen_or_i32(tmp2, tmp2, tmp);
4120 tcg_temp_free_i32(tmp);
4123 neon_store_reg(rd, pass, tmp2);
4124 } else {
4125 tmp2 = neon_load_reg(rd, pass);
4126 for (n = 0; n < 4; n++) {
4127 tmp = tcg_temp_new_i32();
4128 if (n == 0) {
4129 tcg_gen_mov_i32(tmp, tmp2);
4130 } else {
4131 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4133 gen_aa32_st8(tmp, addr, IS_USER(s));
4134 tcg_temp_free_i32(tmp);
4135 tcg_gen_addi_i32(addr, addr, stride);
4137 tcg_temp_free_i32(tmp2);
4142 rd += spacing;
4144 tcg_temp_free_i32(addr);
4145 stride = nregs * 8;
4146 } else {
4147 size = (insn >> 10) & 3;
4148 if (size == 3) {
4149 /* Load single element to all lanes. */
4150 int a = (insn >> 4) & 1;
4151 if (!load) {
4152 return 1;
4154 size = (insn >> 6) & 3;
4155 nregs = ((insn >> 8) & 3) + 1;
4157 if (size == 3) {
4158 if (nregs != 4 || a == 0) {
4159 return 1;
4161 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4162 size = 2;
4164 if (nregs == 1 && a == 1 && size == 0) {
4165 return 1;
4167 if (nregs == 3 && a == 1) {
4168 return 1;
4170 addr = tcg_temp_new_i32();
4171 load_reg_var(s, addr, rn);
4172 if (nregs == 1) {
4173 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4174 tmp = gen_load_and_replicate(s, addr, size);
4175 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4176 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4177 if (insn & (1 << 5)) {
4178 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4179 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4181 tcg_temp_free_i32(tmp);
4182 } else {
4183 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4184 stride = (insn & (1 << 5)) ? 2 : 1;
4185 for (reg = 0; reg < nregs; reg++) {
4186 tmp = gen_load_and_replicate(s, addr, size);
4187 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4188 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4189 tcg_temp_free_i32(tmp);
4190 tcg_gen_addi_i32(addr, addr, 1 << size);
4191 rd += stride;
4194 tcg_temp_free_i32(addr);
4195 stride = (1 << size) * nregs;
4196 } else {
4197 /* Single element. */
4198 int idx = (insn >> 4) & 0xf;
4199 pass = (insn >> 7) & 1;
4200 switch (size) {
4201 case 0:
4202 shift = ((insn >> 5) & 3) * 8;
4203 stride = 1;
4204 break;
4205 case 1:
4206 shift = ((insn >> 6) & 1) * 16;
4207 stride = (insn & (1 << 5)) ? 2 : 1;
4208 break;
4209 case 2:
4210 shift = 0;
4211 stride = (insn & (1 << 6)) ? 2 : 1;
4212 break;
4213 default:
4214 abort();
4216 nregs = ((insn >> 8) & 3) + 1;
4217 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4218 switch (nregs) {
4219 case 1:
4220 if (((idx & (1 << size)) != 0) ||
4221 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4222 return 1;
4224 break;
4225 case 3:
4226 if ((idx & 1) != 0) {
4227 return 1;
4229 /* fall through */
4230 case 2:
4231 if (size == 2 && (idx & 2) != 0) {
4232 return 1;
4234 break;
4235 case 4:
4236 if ((size == 2) && ((idx & 3) == 3)) {
4237 return 1;
4239 break;
4240 default:
4241 abort();
4243 if ((rd + stride * (nregs - 1)) > 31) {
4244 /* Attempts to write off the end of the register file
4245 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4246 * the neon_load_reg() would write off the end of the array.
4248 return 1;
4250 addr = tcg_temp_new_i32();
4251 load_reg_var(s, addr, rn);
4252 for (reg = 0; reg < nregs; reg++) {
4253 if (load) {
4254 tmp = tcg_temp_new_i32();
4255 switch (size) {
4256 case 0:
4257 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4258 break;
4259 case 1:
4260 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4261 break;
4262 case 2:
4263 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4264 break;
4265 default: /* Avoid compiler warnings. */
4266 abort();
4268 if (size != 2) {
4269 tmp2 = neon_load_reg(rd, pass);
4270 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4271 shift, size ? 16 : 8);
4272 tcg_temp_free_i32(tmp2);
4274 neon_store_reg(rd, pass, tmp);
4275 } else { /* Store */
4276 tmp = neon_load_reg(rd, pass);
4277 if (shift)
4278 tcg_gen_shri_i32(tmp, tmp, shift);
4279 switch (size) {
4280 case 0:
4281 gen_aa32_st8(tmp, addr, IS_USER(s));
4282 break;
4283 case 1:
4284 gen_aa32_st16(tmp, addr, IS_USER(s));
4285 break;
4286 case 2:
4287 gen_aa32_st32(tmp, addr, IS_USER(s));
4288 break;
4290 tcg_temp_free_i32(tmp);
4292 rd += stride;
4293 tcg_gen_addi_i32(addr, addr, 1 << size);
4295 tcg_temp_free_i32(addr);
4296 stride = nregs * (1 << size);
4299 if (rm != 15) {
4300 TCGv_i32 base;
4302 base = load_reg(s, rn);
4303 if (rm == 13) {
4304 tcg_gen_addi_i32(base, base, stride);
4305 } else {
4306 TCGv_i32 index;
4307 index = load_reg(s, rm);
4308 tcg_gen_add_i32(base, base, index);
4309 tcg_temp_free_i32(index);
4311 store_reg(s, rn, base);
4313 return 0;
4316 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4317 static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
4319 tcg_gen_and_i32(t, t, c);
4320 tcg_gen_andc_i32(f, f, c);
4321 tcg_gen_or_i32(dest, t, f);
4324 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4326 switch (size) {
4327 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4328 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4329 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4330 default: abort();
4334 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4336 switch (size) {
4337 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4338 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4339 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4340 default: abort();
4344 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
4346 switch (size) {
4347 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4348 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4349 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4350 default: abort();
4354 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4356 switch (size) {
4357 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4358 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4359 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4360 default: abort();
4364 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
4365 int q, int u)
4367 if (q) {
4368 if (u) {
4369 switch (size) {
4370 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4371 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4372 default: abort();
4374 } else {
4375 switch (size) {
4376 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4377 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4378 default: abort();
4381 } else {
4382 if (u) {
4383 switch (size) {
4384 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4385 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4386 default: abort();
4388 } else {
4389 switch (size) {
4390 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4391 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4392 default: abort();
4398 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
4400 if (u) {
4401 switch (size) {
4402 case 0: gen_helper_neon_widen_u8(dest, src); break;
4403 case 1: gen_helper_neon_widen_u16(dest, src); break;
4404 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4405 default: abort();
4407 } else {
4408 switch (size) {
4409 case 0: gen_helper_neon_widen_s8(dest, src); break;
4410 case 1: gen_helper_neon_widen_s16(dest, src); break;
4411 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4412 default: abort();
4415 tcg_temp_free_i32(src);
4418 static inline void gen_neon_addl(int size)
4420 switch (size) {
4421 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4422 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4423 case 2: tcg_gen_add_i64(CPU_V001); break;
4424 default: abort();
4428 static inline void gen_neon_subl(int size)
4430 switch (size) {
4431 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4432 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4433 case 2: tcg_gen_sub_i64(CPU_V001); break;
4434 default: abort();
4438 static inline void gen_neon_negl(TCGv_i64 var, int size)
4440 switch (size) {
4441 case 0: gen_helper_neon_negl_u16(var, var); break;
4442 case 1: gen_helper_neon_negl_u32(var, var); break;
4443 case 2:
4444 tcg_gen_neg_i64(var, var);
4445 break;
4446 default: abort();
4450 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4452 switch (size) {
4453 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4454 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4455 default: abort();
4459 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4460 int size, int u)
4462 TCGv_i64 tmp;
4464 switch ((size << 1) | u) {
4465 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4466 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4467 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4468 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4469 case 4:
4470 tmp = gen_muls_i64_i32(a, b);
4471 tcg_gen_mov_i64(dest, tmp);
4472 tcg_temp_free_i64(tmp);
4473 break;
4474 case 5:
4475 tmp = gen_mulu_i64_i32(a, b);
4476 tcg_gen_mov_i64(dest, tmp);
4477 tcg_temp_free_i64(tmp);
4478 break;
4479 default: abort();
4482 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4483 Don't forget to clean them now. */
4484 if (size < 2) {
4485 tcg_temp_free_i32(a);
4486 tcg_temp_free_i32(b);
4490 static void gen_neon_narrow_op(int op, int u, int size,
4491 TCGv_i32 dest, TCGv_i64 src)
4493 if (op) {
4494 if (u) {
4495 gen_neon_unarrow_sats(size, dest, src);
4496 } else {
4497 gen_neon_narrow(size, dest, src);
4499 } else {
4500 if (u) {
4501 gen_neon_narrow_satu(size, dest, src);
4502 } else {
4503 gen_neon_narrow_sats(size, dest, src);
4508 /* Symbolic constants for op fields for Neon 3-register same-length.
4509 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4510 * table A7-9.
4512 #define NEON_3R_VHADD 0
4513 #define NEON_3R_VQADD 1
4514 #define NEON_3R_VRHADD 2
4515 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4516 #define NEON_3R_VHSUB 4
4517 #define NEON_3R_VQSUB 5
4518 #define NEON_3R_VCGT 6
4519 #define NEON_3R_VCGE 7
4520 #define NEON_3R_VSHL 8
4521 #define NEON_3R_VQSHL 9
4522 #define NEON_3R_VRSHL 10
4523 #define NEON_3R_VQRSHL 11
4524 #define NEON_3R_VMAX 12
4525 #define NEON_3R_VMIN 13
4526 #define NEON_3R_VABD 14
4527 #define NEON_3R_VABA 15
4528 #define NEON_3R_VADD_VSUB 16
4529 #define NEON_3R_VTST_VCEQ 17
4530 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4531 #define NEON_3R_VMUL 19
4532 #define NEON_3R_VPMAX 20
4533 #define NEON_3R_VPMIN 21
4534 #define NEON_3R_VQDMULH_VQRDMULH 22
4535 #define NEON_3R_VPADD 23
4536 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4537 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4538 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4539 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4540 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4541 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4542 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
4544 static const uint8_t neon_3r_sizes[] = {
4545 [NEON_3R_VHADD] = 0x7,
4546 [NEON_3R_VQADD] = 0xf,
4547 [NEON_3R_VRHADD] = 0x7,
4548 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4549 [NEON_3R_VHSUB] = 0x7,
4550 [NEON_3R_VQSUB] = 0xf,
4551 [NEON_3R_VCGT] = 0x7,
4552 [NEON_3R_VCGE] = 0x7,
4553 [NEON_3R_VSHL] = 0xf,
4554 [NEON_3R_VQSHL] = 0xf,
4555 [NEON_3R_VRSHL] = 0xf,
4556 [NEON_3R_VQRSHL] = 0xf,
4557 [NEON_3R_VMAX] = 0x7,
4558 [NEON_3R_VMIN] = 0x7,
4559 [NEON_3R_VABD] = 0x7,
4560 [NEON_3R_VABA] = 0x7,
4561 [NEON_3R_VADD_VSUB] = 0xf,
4562 [NEON_3R_VTST_VCEQ] = 0x7,
4563 [NEON_3R_VML] = 0x7,
4564 [NEON_3R_VMUL] = 0x7,
4565 [NEON_3R_VPMAX] = 0x7,
4566 [NEON_3R_VPMIN] = 0x7,
4567 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4568 [NEON_3R_VPADD] = 0x7,
4569 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
4570 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4571 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4572 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4573 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4574 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4575 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
4578 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4579 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4580 * table A7-13.
4582 #define NEON_2RM_VREV64 0
4583 #define NEON_2RM_VREV32 1
4584 #define NEON_2RM_VREV16 2
4585 #define NEON_2RM_VPADDL 4
4586 #define NEON_2RM_VPADDL_U 5
4587 #define NEON_2RM_AESE 6 /* Includes AESD */
4588 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
4589 #define NEON_2RM_VCLS 8
4590 #define NEON_2RM_VCLZ 9
4591 #define NEON_2RM_VCNT 10
4592 #define NEON_2RM_VMVN 11
4593 #define NEON_2RM_VPADAL 12
4594 #define NEON_2RM_VPADAL_U 13
4595 #define NEON_2RM_VQABS 14
4596 #define NEON_2RM_VQNEG 15
4597 #define NEON_2RM_VCGT0 16
4598 #define NEON_2RM_VCGE0 17
4599 #define NEON_2RM_VCEQ0 18
4600 #define NEON_2RM_VCLE0 19
4601 #define NEON_2RM_VCLT0 20
4602 #define NEON_2RM_VABS 22
4603 #define NEON_2RM_VNEG 23
4604 #define NEON_2RM_VCGT0_F 24
4605 #define NEON_2RM_VCGE0_F 25
4606 #define NEON_2RM_VCEQ0_F 26
4607 #define NEON_2RM_VCLE0_F 27
4608 #define NEON_2RM_VCLT0_F 28
4609 #define NEON_2RM_VABS_F 30
4610 #define NEON_2RM_VNEG_F 31
4611 #define NEON_2RM_VSWP 32
4612 #define NEON_2RM_VTRN 33
4613 #define NEON_2RM_VUZP 34
4614 #define NEON_2RM_VZIP 35
4615 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4616 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4617 #define NEON_2RM_VSHLL 38
4618 #define NEON_2RM_VCVT_F16_F32 44
4619 #define NEON_2RM_VCVT_F32_F16 46
4620 #define NEON_2RM_VRECPE 56
4621 #define NEON_2RM_VRSQRTE 57
4622 #define NEON_2RM_VRECPE_F 58
4623 #define NEON_2RM_VRSQRTE_F 59
4624 #define NEON_2RM_VCVT_FS 60
4625 #define NEON_2RM_VCVT_FU 61
4626 #define NEON_2RM_VCVT_SF 62
4627 #define NEON_2RM_VCVT_UF 63
4629 static int neon_2rm_is_float_op(int op)
4631 /* Return true if this neon 2reg-misc op is float-to-float */
4632 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4633 op >= NEON_2RM_VRECPE_F);
4636 /* Each entry in this array has bit n set if the insn allows
4637 * size value n (otherwise it will UNDEF). Since unallocated
4638 * op values will have no bits set they always UNDEF.
4640 static const uint8_t neon_2rm_sizes[] = {
4641 [NEON_2RM_VREV64] = 0x7,
4642 [NEON_2RM_VREV32] = 0x3,
4643 [NEON_2RM_VREV16] = 0x1,
4644 [NEON_2RM_VPADDL] = 0x7,
4645 [NEON_2RM_VPADDL_U] = 0x7,
4646 [NEON_2RM_AESE] = 0x1,
4647 [NEON_2RM_AESMC] = 0x1,
4648 [NEON_2RM_VCLS] = 0x7,
4649 [NEON_2RM_VCLZ] = 0x7,
4650 [NEON_2RM_VCNT] = 0x1,
4651 [NEON_2RM_VMVN] = 0x1,
4652 [NEON_2RM_VPADAL] = 0x7,
4653 [NEON_2RM_VPADAL_U] = 0x7,
4654 [NEON_2RM_VQABS] = 0x7,
4655 [NEON_2RM_VQNEG] = 0x7,
4656 [NEON_2RM_VCGT0] = 0x7,
4657 [NEON_2RM_VCGE0] = 0x7,
4658 [NEON_2RM_VCEQ0] = 0x7,
4659 [NEON_2RM_VCLE0] = 0x7,
4660 [NEON_2RM_VCLT0] = 0x7,
4661 [NEON_2RM_VABS] = 0x7,
4662 [NEON_2RM_VNEG] = 0x7,
4663 [NEON_2RM_VCGT0_F] = 0x4,
4664 [NEON_2RM_VCGE0_F] = 0x4,
4665 [NEON_2RM_VCEQ0_F] = 0x4,
4666 [NEON_2RM_VCLE0_F] = 0x4,
4667 [NEON_2RM_VCLT0_F] = 0x4,
4668 [NEON_2RM_VABS_F] = 0x4,
4669 [NEON_2RM_VNEG_F] = 0x4,
4670 [NEON_2RM_VSWP] = 0x1,
4671 [NEON_2RM_VTRN] = 0x7,
4672 [NEON_2RM_VUZP] = 0x7,
4673 [NEON_2RM_VZIP] = 0x7,
4674 [NEON_2RM_VMOVN] = 0x7,
4675 [NEON_2RM_VQMOVN] = 0x7,
4676 [NEON_2RM_VSHLL] = 0x7,
4677 [NEON_2RM_VCVT_F16_F32] = 0x2,
4678 [NEON_2RM_VCVT_F32_F16] = 0x2,
4679 [NEON_2RM_VRECPE] = 0x4,
4680 [NEON_2RM_VRSQRTE] = 0x4,
4681 [NEON_2RM_VRECPE_F] = 0x4,
4682 [NEON_2RM_VRSQRTE_F] = 0x4,
4683 [NEON_2RM_VCVT_FS] = 0x4,
4684 [NEON_2RM_VCVT_FU] = 0x4,
4685 [NEON_2RM_VCVT_SF] = 0x4,
4686 [NEON_2RM_VCVT_UF] = 0x4,
4689 /* Translate a NEON data processing instruction. Return nonzero if the
4690 instruction is invalid.
4691 We process data in a mixture of 32-bit and 64-bit chunks.
4692 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4694 static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4696 int op;
4697 int q;
4698 int rd, rn, rm;
4699 int size;
4700 int shift;
4701 int pass;
4702 int count;
4703 int pairwise;
4704 int u;
4705 uint32_t imm, mask;
4706 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
4707 TCGv_i64 tmp64;
4709 if (!s->vfp_enabled)
4710 return 1;
4711 q = (insn & (1 << 6)) != 0;
4712 u = (insn >> 24) & 1;
4713 VFP_DREG_D(rd, insn);
4714 VFP_DREG_N(rn, insn);
4715 VFP_DREG_M(rm, insn);
4716 size = (insn >> 20) & 3;
4717 if ((insn & (1 << 23)) == 0) {
4718 /* Three register same length. */
4719 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4720 /* Catch invalid op and bad size combinations: UNDEF */
4721 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4722 return 1;
4724 /* All insns of this form UNDEF for either this condition or the
4725 * superset of cases "Q==1"; we catch the latter later.
4727 if (q && ((rd | rn | rm) & 1)) {
4728 return 1;
4730 if (size == 3 && op != NEON_3R_LOGIC) {
4731 /* 64-bit element instructions. */
4732 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4733 neon_load_reg64(cpu_V0, rn + pass);
4734 neon_load_reg64(cpu_V1, rm + pass);
4735 switch (op) {
4736 case NEON_3R_VQADD:
4737 if (u) {
4738 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4739 cpu_V0, cpu_V1);
4740 } else {
4741 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4742 cpu_V0, cpu_V1);
4744 break;
4745 case NEON_3R_VQSUB:
4746 if (u) {
4747 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4748 cpu_V0, cpu_V1);
4749 } else {
4750 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4751 cpu_V0, cpu_V1);
4753 break;
4754 case NEON_3R_VSHL:
4755 if (u) {
4756 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4757 } else {
4758 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4760 break;
4761 case NEON_3R_VQSHL:
4762 if (u) {
4763 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4764 cpu_V1, cpu_V0);
4765 } else {
4766 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4767 cpu_V1, cpu_V0);
4769 break;
4770 case NEON_3R_VRSHL:
4771 if (u) {
4772 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4773 } else {
4774 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4776 break;
4777 case NEON_3R_VQRSHL:
4778 if (u) {
4779 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4780 cpu_V1, cpu_V0);
4781 } else {
4782 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4783 cpu_V1, cpu_V0);
4785 break;
4786 case NEON_3R_VADD_VSUB:
4787 if (u) {
4788 tcg_gen_sub_i64(CPU_V001);
4789 } else {
4790 tcg_gen_add_i64(CPU_V001);
4792 break;
4793 default:
4794 abort();
4796 neon_store_reg64(cpu_V0, rd + pass);
4798 return 0;
4800 pairwise = 0;
4801 switch (op) {
4802 case NEON_3R_VSHL:
4803 case NEON_3R_VQSHL:
4804 case NEON_3R_VRSHL:
4805 case NEON_3R_VQRSHL:
4807 int rtmp;
4808 /* Shift instruction operands are reversed. */
4809 rtmp = rn;
4810 rn = rm;
4811 rm = rtmp;
4813 break;
4814 case NEON_3R_VPADD:
4815 if (u) {
4816 return 1;
4818 /* Fall through */
4819 case NEON_3R_VPMAX:
4820 case NEON_3R_VPMIN:
4821 pairwise = 1;
4822 break;
4823 case NEON_3R_FLOAT_ARITH:
4824 pairwise = (u && size < 2); /* if VPADD (float) */
4825 break;
4826 case NEON_3R_FLOAT_MINMAX:
4827 pairwise = u; /* if VPMIN/VPMAX (float) */
4828 break;
4829 case NEON_3R_FLOAT_CMP:
4830 if (!u && size) {
4831 /* no encoding for U=0 C=1x */
4832 return 1;
4834 break;
4835 case NEON_3R_FLOAT_ACMP:
4836 if (!u) {
4837 return 1;
4839 break;
4840 case NEON_3R_FLOAT_MISC:
4841 /* VMAXNM/VMINNM in ARMv8 */
4842 if (u && !arm_feature(env, ARM_FEATURE_V8)) {
4843 return 1;
4845 break;
4846 case NEON_3R_VMUL:
4847 if (u && (size != 0)) {
4848 /* UNDEF on invalid size for polynomial subcase */
4849 return 1;
4851 break;
4852 case NEON_3R_VFM:
4853 if (!arm_feature(env, ARM_FEATURE_VFP4) || u) {
4854 return 1;
4856 break;
4857 default:
4858 break;
4861 if (pairwise && q) {
4862 /* All the pairwise insns UNDEF if Q is set */
4863 return 1;
4866 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4868 if (pairwise) {
4869 /* Pairwise. */
4870 if (pass < 1) {
4871 tmp = neon_load_reg(rn, 0);
4872 tmp2 = neon_load_reg(rn, 1);
4873 } else {
4874 tmp = neon_load_reg(rm, 0);
4875 tmp2 = neon_load_reg(rm, 1);
4877 } else {
4878 /* Elementwise. */
4879 tmp = neon_load_reg(rn, pass);
4880 tmp2 = neon_load_reg(rm, pass);
4882 switch (op) {
4883 case NEON_3R_VHADD:
4884 GEN_NEON_INTEGER_OP(hadd);
4885 break;
4886 case NEON_3R_VQADD:
4887 GEN_NEON_INTEGER_OP_ENV(qadd);
4888 break;
4889 case NEON_3R_VRHADD:
4890 GEN_NEON_INTEGER_OP(rhadd);
4891 break;
4892 case NEON_3R_LOGIC: /* Logic ops. */
4893 switch ((u << 2) | size) {
4894 case 0: /* VAND */
4895 tcg_gen_and_i32(tmp, tmp, tmp2);
4896 break;
4897 case 1: /* BIC */
4898 tcg_gen_andc_i32(tmp, tmp, tmp2);
4899 break;
4900 case 2: /* VORR */
4901 tcg_gen_or_i32(tmp, tmp, tmp2);
4902 break;
4903 case 3: /* VORN */
4904 tcg_gen_orc_i32(tmp, tmp, tmp2);
4905 break;
4906 case 4: /* VEOR */
4907 tcg_gen_xor_i32(tmp, tmp, tmp2);
4908 break;
4909 case 5: /* VBSL */
4910 tmp3 = neon_load_reg(rd, pass);
4911 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4912 tcg_temp_free_i32(tmp3);
4913 break;
4914 case 6: /* VBIT */
4915 tmp3 = neon_load_reg(rd, pass);
4916 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4917 tcg_temp_free_i32(tmp3);
4918 break;
4919 case 7: /* VBIF */
4920 tmp3 = neon_load_reg(rd, pass);
4921 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4922 tcg_temp_free_i32(tmp3);
4923 break;
4925 break;
4926 case NEON_3R_VHSUB:
4927 GEN_NEON_INTEGER_OP(hsub);
4928 break;
4929 case NEON_3R_VQSUB:
4930 GEN_NEON_INTEGER_OP_ENV(qsub);
4931 break;
4932 case NEON_3R_VCGT:
4933 GEN_NEON_INTEGER_OP(cgt);
4934 break;
4935 case NEON_3R_VCGE:
4936 GEN_NEON_INTEGER_OP(cge);
4937 break;
4938 case NEON_3R_VSHL:
4939 GEN_NEON_INTEGER_OP(shl);
4940 break;
4941 case NEON_3R_VQSHL:
4942 GEN_NEON_INTEGER_OP_ENV(qshl);
4943 break;
4944 case NEON_3R_VRSHL:
4945 GEN_NEON_INTEGER_OP(rshl);
4946 break;
4947 case NEON_3R_VQRSHL:
4948 GEN_NEON_INTEGER_OP_ENV(qrshl);
4949 break;
4950 case NEON_3R_VMAX:
4951 GEN_NEON_INTEGER_OP(max);
4952 break;
4953 case NEON_3R_VMIN:
4954 GEN_NEON_INTEGER_OP(min);
4955 break;
4956 case NEON_3R_VABD:
4957 GEN_NEON_INTEGER_OP(abd);
4958 break;
4959 case NEON_3R_VABA:
4960 GEN_NEON_INTEGER_OP(abd);
4961 tcg_temp_free_i32(tmp2);
4962 tmp2 = neon_load_reg(rd, pass);
4963 gen_neon_add(size, tmp, tmp2);
4964 break;
4965 case NEON_3R_VADD_VSUB:
4966 if (!u) { /* VADD */
4967 gen_neon_add(size, tmp, tmp2);
4968 } else { /* VSUB */
4969 switch (size) {
4970 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4971 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4972 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4973 default: abort();
4976 break;
4977 case NEON_3R_VTST_VCEQ:
4978 if (!u) { /* VTST */
4979 switch (size) {
4980 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4981 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4982 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4983 default: abort();
4985 } else { /* VCEQ */
4986 switch (size) {
4987 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4988 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4989 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4990 default: abort();
4993 break;
4994 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
4995 switch (size) {
4996 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
4997 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
4998 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
4999 default: abort();
5001 tcg_temp_free_i32(tmp2);
5002 tmp2 = neon_load_reg(rd, pass);
5003 if (u) { /* VMLS */
5004 gen_neon_rsb(size, tmp, tmp2);
5005 } else { /* VMLA */
5006 gen_neon_add(size, tmp, tmp2);
5008 break;
5009 case NEON_3R_VMUL:
5010 if (u) { /* polynomial */
5011 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
5012 } else { /* Integer */
5013 switch (size) {
5014 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5015 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5016 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5017 default: abort();
5020 break;
5021 case NEON_3R_VPMAX:
5022 GEN_NEON_INTEGER_OP(pmax);
5023 break;
5024 case NEON_3R_VPMIN:
5025 GEN_NEON_INTEGER_OP(pmin);
5026 break;
5027 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
5028 if (!u) { /* VQDMULH */
5029 switch (size) {
5030 case 1:
5031 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5032 break;
5033 case 2:
5034 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5035 break;
5036 default: abort();
5038 } else { /* VQRDMULH */
5039 switch (size) {
5040 case 1:
5041 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5042 break;
5043 case 2:
5044 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5045 break;
5046 default: abort();
5049 break;
5050 case NEON_3R_VPADD:
5051 switch (size) {
5052 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5053 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5054 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5055 default: abort();
5057 break;
5058 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
5060 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5061 switch ((u << 2) | size) {
5062 case 0: /* VADD */
5063 case 4: /* VPADD */
5064 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5065 break;
5066 case 2: /* VSUB */
5067 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
5068 break;
5069 case 6: /* VABD */
5070 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
5071 break;
5072 default:
5073 abort();
5075 tcg_temp_free_ptr(fpstatus);
5076 break;
5078 case NEON_3R_FLOAT_MULTIPLY:
5080 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5081 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5082 if (!u) {
5083 tcg_temp_free_i32(tmp2);
5084 tmp2 = neon_load_reg(rd, pass);
5085 if (size == 0) {
5086 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5087 } else {
5088 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5091 tcg_temp_free_ptr(fpstatus);
5092 break;
5094 case NEON_3R_FLOAT_CMP:
5096 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5097 if (!u) {
5098 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5099 } else {
5100 if (size == 0) {
5101 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5102 } else {
5103 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5106 tcg_temp_free_ptr(fpstatus);
5107 break;
5109 case NEON_3R_FLOAT_ACMP:
5111 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5112 if (size == 0) {
5113 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5114 } else {
5115 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5117 tcg_temp_free_ptr(fpstatus);
5118 break;
5120 case NEON_3R_FLOAT_MINMAX:
5122 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5123 if (size == 0) {
5124 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
5125 } else {
5126 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
5128 tcg_temp_free_ptr(fpstatus);
5129 break;
5131 case NEON_3R_FLOAT_MISC:
5132 if (u) {
5133 /* VMAXNM/VMINNM */
5134 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5135 if (size == 0) {
5136 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
5137 } else {
5138 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
5140 tcg_temp_free_ptr(fpstatus);
5141 } else {
5142 if (size == 0) {
5143 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5144 } else {
5145 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5148 break;
5149 case NEON_3R_VFM:
5151 /* VFMA, VFMS: fused multiply-add */
5152 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5153 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5154 if (size) {
5155 /* VFMS */
5156 gen_helper_vfp_negs(tmp, tmp);
5158 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5159 tcg_temp_free_i32(tmp3);
5160 tcg_temp_free_ptr(fpstatus);
5161 break;
5163 default:
5164 abort();
5166 tcg_temp_free_i32(tmp2);
5168 /* Save the result. For elementwise operations we can put it
5169 straight into the destination register. For pairwise operations
5170 we have to be careful to avoid clobbering the source operands. */
5171 if (pairwise && rd == rm) {
5172 neon_store_scratch(pass, tmp);
5173 } else {
5174 neon_store_reg(rd, pass, tmp);
5177 } /* for pass */
5178 if (pairwise && rd == rm) {
5179 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5180 tmp = neon_load_scratch(pass);
5181 neon_store_reg(rd, pass, tmp);
5184 /* End of 3 register same size operations. */
5185 } else if (insn & (1 << 4)) {
5186 if ((insn & 0x00380080) != 0) {
5187 /* Two registers and shift. */
5188 op = (insn >> 8) & 0xf;
5189 if (insn & (1 << 7)) {
5190 /* 64-bit shift. */
5191 if (op > 7) {
5192 return 1;
5194 size = 3;
5195 } else {
5196 size = 2;
5197 while ((insn & (1 << (size + 19))) == 0)
5198 size--;
5200 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5201 /* To avoid excessive duplication of ops we implement shift
5202 by immediate using the variable shift operations. */
5203 if (op < 8) {
5204 /* Shift by immediate:
5205 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5206 if (q && ((rd | rm) & 1)) {
5207 return 1;
5209 if (!u && (op == 4 || op == 6)) {
5210 return 1;
5212 /* Right shifts are encoded as N - shift, where N is the
5213 element size in bits. */
5214 if (op <= 4)
5215 shift = shift - (1 << (size + 3));
5216 if (size == 3) {
5217 count = q + 1;
5218 } else {
5219 count = q ? 4: 2;
5221 switch (size) {
5222 case 0:
5223 imm = (uint8_t) shift;
5224 imm |= imm << 8;
5225 imm |= imm << 16;
5226 break;
5227 case 1:
5228 imm = (uint16_t) shift;
5229 imm |= imm << 16;
5230 break;
5231 case 2:
5232 case 3:
5233 imm = shift;
5234 break;
5235 default:
5236 abort();
5239 for (pass = 0; pass < count; pass++) {
5240 if (size == 3) {
5241 neon_load_reg64(cpu_V0, rm + pass);
5242 tcg_gen_movi_i64(cpu_V1, imm);
5243 switch (op) {
5244 case 0: /* VSHR */
5245 case 1: /* VSRA */
5246 if (u)
5247 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5248 else
5249 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5250 break;
5251 case 2: /* VRSHR */
5252 case 3: /* VRSRA */
5253 if (u)
5254 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5255 else
5256 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5257 break;
5258 case 4: /* VSRI */
5259 case 5: /* VSHL, VSLI */
5260 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5261 break;
5262 case 6: /* VQSHLU */
5263 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5264 cpu_V0, cpu_V1);
5265 break;
5266 case 7: /* VQSHL */
5267 if (u) {
5268 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5269 cpu_V0, cpu_V1);
5270 } else {
5271 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5272 cpu_V0, cpu_V1);
5274 break;
5276 if (op == 1 || op == 3) {
5277 /* Accumulate. */
5278 neon_load_reg64(cpu_V1, rd + pass);
5279 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5280 } else if (op == 4 || (op == 5 && u)) {
5281 /* Insert */
5282 neon_load_reg64(cpu_V1, rd + pass);
5283 uint64_t mask;
5284 if (shift < -63 || shift > 63) {
5285 mask = 0;
5286 } else {
5287 if (op == 4) {
5288 mask = 0xffffffffffffffffull >> -shift;
5289 } else {
5290 mask = 0xffffffffffffffffull << shift;
5293 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5294 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5296 neon_store_reg64(cpu_V0, rd + pass);
5297 } else { /* size < 3 */
5298 /* Operands in T0 and T1. */
5299 tmp = neon_load_reg(rm, pass);
5300 tmp2 = tcg_temp_new_i32();
5301 tcg_gen_movi_i32(tmp2, imm);
5302 switch (op) {
5303 case 0: /* VSHR */
5304 case 1: /* VSRA */
5305 GEN_NEON_INTEGER_OP(shl);
5306 break;
5307 case 2: /* VRSHR */
5308 case 3: /* VRSRA */
5309 GEN_NEON_INTEGER_OP(rshl);
5310 break;
5311 case 4: /* VSRI */
5312 case 5: /* VSHL, VSLI */
5313 switch (size) {
5314 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5315 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5316 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5317 default: abort();
5319 break;
5320 case 6: /* VQSHLU */
5321 switch (size) {
5322 case 0:
5323 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5324 tmp, tmp2);
5325 break;
5326 case 1:
5327 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5328 tmp, tmp2);
5329 break;
5330 case 2:
5331 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5332 tmp, tmp2);
5333 break;
5334 default:
5335 abort();
5337 break;
5338 case 7: /* VQSHL */
5339 GEN_NEON_INTEGER_OP_ENV(qshl);
5340 break;
5342 tcg_temp_free_i32(tmp2);
5344 if (op == 1 || op == 3) {
5345 /* Accumulate. */
5346 tmp2 = neon_load_reg(rd, pass);
5347 gen_neon_add(size, tmp, tmp2);
5348 tcg_temp_free_i32(tmp2);
5349 } else if (op == 4 || (op == 5 && u)) {
5350 /* Insert */
5351 switch (size) {
5352 case 0:
5353 if (op == 4)
5354 mask = 0xff >> -shift;
5355 else
5356 mask = (uint8_t)(0xff << shift);
5357 mask |= mask << 8;
5358 mask |= mask << 16;
5359 break;
5360 case 1:
5361 if (op == 4)
5362 mask = 0xffff >> -shift;
5363 else
5364 mask = (uint16_t)(0xffff << shift);
5365 mask |= mask << 16;
5366 break;
5367 case 2:
5368 if (shift < -31 || shift > 31) {
5369 mask = 0;
5370 } else {
5371 if (op == 4)
5372 mask = 0xffffffffu >> -shift;
5373 else
5374 mask = 0xffffffffu << shift;
5376 break;
5377 default:
5378 abort();
5380 tmp2 = neon_load_reg(rd, pass);
5381 tcg_gen_andi_i32(tmp, tmp, mask);
5382 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5383 tcg_gen_or_i32(tmp, tmp, tmp2);
5384 tcg_temp_free_i32(tmp2);
5386 neon_store_reg(rd, pass, tmp);
5388 } /* for pass */
5389 } else if (op < 10) {
5390 /* Shift by immediate and narrow:
5391 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5392 int input_unsigned = (op == 8) ? !u : u;
5393 if (rm & 1) {
5394 return 1;
5396 shift = shift - (1 << (size + 3));
5397 size++;
5398 if (size == 3) {
5399 tmp64 = tcg_const_i64(shift);
5400 neon_load_reg64(cpu_V0, rm);
5401 neon_load_reg64(cpu_V1, rm + 1);
5402 for (pass = 0; pass < 2; pass++) {
5403 TCGv_i64 in;
5404 if (pass == 0) {
5405 in = cpu_V0;
5406 } else {
5407 in = cpu_V1;
5409 if (q) {
5410 if (input_unsigned) {
5411 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5412 } else {
5413 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5415 } else {
5416 if (input_unsigned) {
5417 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5418 } else {
5419 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5422 tmp = tcg_temp_new_i32();
5423 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5424 neon_store_reg(rd, pass, tmp);
5425 } /* for pass */
5426 tcg_temp_free_i64(tmp64);
5427 } else {
5428 if (size == 1) {
5429 imm = (uint16_t)shift;
5430 imm |= imm << 16;
5431 } else {
5432 /* size == 2 */
5433 imm = (uint32_t)shift;
5435 tmp2 = tcg_const_i32(imm);
5436 tmp4 = neon_load_reg(rm + 1, 0);
5437 tmp5 = neon_load_reg(rm + 1, 1);
5438 for (pass = 0; pass < 2; pass++) {
5439 if (pass == 0) {
5440 tmp = neon_load_reg(rm, 0);
5441 } else {
5442 tmp = tmp4;
5444 gen_neon_shift_narrow(size, tmp, tmp2, q,
5445 input_unsigned);
5446 if (pass == 0) {
5447 tmp3 = neon_load_reg(rm, 1);
5448 } else {
5449 tmp3 = tmp5;
5451 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5452 input_unsigned);
5453 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5454 tcg_temp_free_i32(tmp);
5455 tcg_temp_free_i32(tmp3);
5456 tmp = tcg_temp_new_i32();
5457 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5458 neon_store_reg(rd, pass, tmp);
5459 } /* for pass */
5460 tcg_temp_free_i32(tmp2);
5462 } else if (op == 10) {
5463 /* VSHLL, VMOVL */
5464 if (q || (rd & 1)) {
5465 return 1;
5467 tmp = neon_load_reg(rm, 0);
5468 tmp2 = neon_load_reg(rm, 1);
5469 for (pass = 0; pass < 2; pass++) {
5470 if (pass == 1)
5471 tmp = tmp2;
5473 gen_neon_widen(cpu_V0, tmp, size, u);
5475 if (shift != 0) {
5476 /* The shift is less than the width of the source
5477 type, so we can just shift the whole register. */
5478 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5479 /* Widen the result of shift: we need to clear
5480 * the potential overflow bits resulting from
5481 * left bits of the narrow input appearing as
5482 * right bits of left the neighbour narrow
5483 * input. */
5484 if (size < 2 || !u) {
5485 uint64_t imm64;
5486 if (size == 0) {
5487 imm = (0xffu >> (8 - shift));
5488 imm |= imm << 16;
5489 } else if (size == 1) {
5490 imm = 0xffff >> (16 - shift);
5491 } else {
5492 /* size == 2 */
5493 imm = 0xffffffff >> (32 - shift);
5495 if (size < 2) {
5496 imm64 = imm | (((uint64_t)imm) << 32);
5497 } else {
5498 imm64 = imm;
5500 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5503 neon_store_reg64(cpu_V0, rd + pass);
5505 } else if (op >= 14) {
5506 /* VCVT fixed-point. */
5507 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5508 return 1;
5510 /* We have already masked out the must-be-1 top bit of imm6,
5511 * hence this 32-shift where the ARM ARM has 64-imm6.
5513 shift = 32 - shift;
5514 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5515 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5516 if (!(op & 1)) {
5517 if (u)
5518 gen_vfp_ulto(0, shift, 1);
5519 else
5520 gen_vfp_slto(0, shift, 1);
5521 } else {
5522 if (u)
5523 gen_vfp_toul(0, shift, 1);
5524 else
5525 gen_vfp_tosl(0, shift, 1);
5527 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5529 } else {
5530 return 1;
5532 } else { /* (insn & 0x00380080) == 0 */
5533 int invert;
5534 if (q && (rd & 1)) {
5535 return 1;
5538 op = (insn >> 8) & 0xf;
5539 /* One register and immediate. */
5540 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5541 invert = (insn & (1 << 5)) != 0;
5542 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5543 * We choose to not special-case this and will behave as if a
5544 * valid constant encoding of 0 had been given.
5546 switch (op) {
5547 case 0: case 1:
5548 /* no-op */
5549 break;
5550 case 2: case 3:
5551 imm <<= 8;
5552 break;
5553 case 4: case 5:
5554 imm <<= 16;
5555 break;
5556 case 6: case 7:
5557 imm <<= 24;
5558 break;
5559 case 8: case 9:
5560 imm |= imm << 16;
5561 break;
5562 case 10: case 11:
5563 imm = (imm << 8) | (imm << 24);
5564 break;
5565 case 12:
5566 imm = (imm << 8) | 0xff;
5567 break;
5568 case 13:
5569 imm = (imm << 16) | 0xffff;
5570 break;
5571 case 14:
5572 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5573 if (invert)
5574 imm = ~imm;
5575 break;
5576 case 15:
5577 if (invert) {
5578 return 1;
5580 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5581 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5582 break;
5584 if (invert)
5585 imm = ~imm;
5587 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5588 if (op & 1 && op < 12) {
5589 tmp = neon_load_reg(rd, pass);
5590 if (invert) {
5591 /* The immediate value has already been inverted, so
5592 BIC becomes AND. */
5593 tcg_gen_andi_i32(tmp, tmp, imm);
5594 } else {
5595 tcg_gen_ori_i32(tmp, tmp, imm);
5597 } else {
5598 /* VMOV, VMVN. */
5599 tmp = tcg_temp_new_i32();
5600 if (op == 14 && invert) {
5601 int n;
5602 uint32_t val;
5603 val = 0;
5604 for (n = 0; n < 4; n++) {
5605 if (imm & (1 << (n + (pass & 1) * 4)))
5606 val |= 0xff << (n * 8);
5608 tcg_gen_movi_i32(tmp, val);
5609 } else {
5610 tcg_gen_movi_i32(tmp, imm);
5613 neon_store_reg(rd, pass, tmp);
5616 } else { /* (insn & 0x00800010 == 0x00800000) */
5617 if (size != 3) {
5618 op = (insn >> 8) & 0xf;
5619 if ((insn & (1 << 6)) == 0) {
5620 /* Three registers of different lengths. */
5621 int src1_wide;
5622 int src2_wide;
5623 int prewiden;
5624 /* undefreq: bit 0 : UNDEF if size != 0
5625 * bit 1 : UNDEF if size == 0
5626 * bit 2 : UNDEF if U == 1
5627 * Note that [1:0] set implies 'always UNDEF'
5629 int undefreq;
5630 /* prewiden, src1_wide, src2_wide, undefreq */
5631 static const int neon_3reg_wide[16][4] = {
5632 {1, 0, 0, 0}, /* VADDL */
5633 {1, 1, 0, 0}, /* VADDW */
5634 {1, 0, 0, 0}, /* VSUBL */
5635 {1, 1, 0, 0}, /* VSUBW */
5636 {0, 1, 1, 0}, /* VADDHN */
5637 {0, 0, 0, 0}, /* VABAL */
5638 {0, 1, 1, 0}, /* VSUBHN */
5639 {0, 0, 0, 0}, /* VABDL */
5640 {0, 0, 0, 0}, /* VMLAL */
5641 {0, 0, 0, 6}, /* VQDMLAL */
5642 {0, 0, 0, 0}, /* VMLSL */
5643 {0, 0, 0, 6}, /* VQDMLSL */
5644 {0, 0, 0, 0}, /* Integer VMULL */
5645 {0, 0, 0, 2}, /* VQDMULL */
5646 {0, 0, 0, 5}, /* Polynomial VMULL */
5647 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5650 prewiden = neon_3reg_wide[op][0];
5651 src1_wide = neon_3reg_wide[op][1];
5652 src2_wide = neon_3reg_wide[op][2];
5653 undefreq = neon_3reg_wide[op][3];
5655 if (((undefreq & 1) && (size != 0)) ||
5656 ((undefreq & 2) && (size == 0)) ||
5657 ((undefreq & 4) && u)) {
5658 return 1;
5660 if ((src1_wide && (rn & 1)) ||
5661 (src2_wide && (rm & 1)) ||
5662 (!src2_wide && (rd & 1))) {
5663 return 1;
5666 /* Avoid overlapping operands. Wide source operands are
5667 always aligned so will never overlap with wide
5668 destinations in problematic ways. */
5669 if (rd == rm && !src2_wide) {
5670 tmp = neon_load_reg(rm, 1);
5671 neon_store_scratch(2, tmp);
5672 } else if (rd == rn && !src1_wide) {
5673 tmp = neon_load_reg(rn, 1);
5674 neon_store_scratch(2, tmp);
5676 TCGV_UNUSED_I32(tmp3);
5677 for (pass = 0; pass < 2; pass++) {
5678 if (src1_wide) {
5679 neon_load_reg64(cpu_V0, rn + pass);
5680 TCGV_UNUSED_I32(tmp);
5681 } else {
5682 if (pass == 1 && rd == rn) {
5683 tmp = neon_load_scratch(2);
5684 } else {
5685 tmp = neon_load_reg(rn, pass);
5687 if (prewiden) {
5688 gen_neon_widen(cpu_V0, tmp, size, u);
5691 if (src2_wide) {
5692 neon_load_reg64(cpu_V1, rm + pass);
5693 TCGV_UNUSED_I32(tmp2);
5694 } else {
5695 if (pass == 1 && rd == rm) {
5696 tmp2 = neon_load_scratch(2);
5697 } else {
5698 tmp2 = neon_load_reg(rm, pass);
5700 if (prewiden) {
5701 gen_neon_widen(cpu_V1, tmp2, size, u);
5704 switch (op) {
5705 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5706 gen_neon_addl(size);
5707 break;
5708 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5709 gen_neon_subl(size);
5710 break;
5711 case 5: case 7: /* VABAL, VABDL */
5712 switch ((size << 1) | u) {
5713 case 0:
5714 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5715 break;
5716 case 1:
5717 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5718 break;
5719 case 2:
5720 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5721 break;
5722 case 3:
5723 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5724 break;
5725 case 4:
5726 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5727 break;
5728 case 5:
5729 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5730 break;
5731 default: abort();
5733 tcg_temp_free_i32(tmp2);
5734 tcg_temp_free_i32(tmp);
5735 break;
5736 case 8: case 9: case 10: case 11: case 12: case 13:
5737 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5738 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5739 break;
5740 case 14: /* Polynomial VMULL */
5741 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5742 tcg_temp_free_i32(tmp2);
5743 tcg_temp_free_i32(tmp);
5744 break;
5745 default: /* 15 is RESERVED: caught earlier */
5746 abort();
5748 if (op == 13) {
5749 /* VQDMULL */
5750 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5751 neon_store_reg64(cpu_V0, rd + pass);
5752 } else if (op == 5 || (op >= 8 && op <= 11)) {
5753 /* Accumulate. */
5754 neon_load_reg64(cpu_V1, rd + pass);
5755 switch (op) {
5756 case 10: /* VMLSL */
5757 gen_neon_negl(cpu_V0, size);
5758 /* Fall through */
5759 case 5: case 8: /* VABAL, VMLAL */
5760 gen_neon_addl(size);
5761 break;
5762 case 9: case 11: /* VQDMLAL, VQDMLSL */
5763 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5764 if (op == 11) {
5765 gen_neon_negl(cpu_V0, size);
5767 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5768 break;
5769 default:
5770 abort();
5772 neon_store_reg64(cpu_V0, rd + pass);
5773 } else if (op == 4 || op == 6) {
5774 /* Narrowing operation. */
5775 tmp = tcg_temp_new_i32();
5776 if (!u) {
5777 switch (size) {
5778 case 0:
5779 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5780 break;
5781 case 1:
5782 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5783 break;
5784 case 2:
5785 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5786 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5787 break;
5788 default: abort();
5790 } else {
5791 switch (size) {
5792 case 0:
5793 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5794 break;
5795 case 1:
5796 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5797 break;
5798 case 2:
5799 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5800 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5801 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5802 break;
5803 default: abort();
5806 if (pass == 0) {
5807 tmp3 = tmp;
5808 } else {
5809 neon_store_reg(rd, 0, tmp3);
5810 neon_store_reg(rd, 1, tmp);
5812 } else {
5813 /* Write back the result. */
5814 neon_store_reg64(cpu_V0, rd + pass);
5817 } else {
5818 /* Two registers and a scalar. NB that for ops of this form
5819 * the ARM ARM labels bit 24 as Q, but it is in our variable
5820 * 'u', not 'q'.
5822 if (size == 0) {
5823 return 1;
5825 switch (op) {
5826 case 1: /* Float VMLA scalar */
5827 case 5: /* Floating point VMLS scalar */
5828 case 9: /* Floating point VMUL scalar */
5829 if (size == 1) {
5830 return 1;
5832 /* fall through */
5833 case 0: /* Integer VMLA scalar */
5834 case 4: /* Integer VMLS scalar */
5835 case 8: /* Integer VMUL scalar */
5836 case 12: /* VQDMULH scalar */
5837 case 13: /* VQRDMULH scalar */
5838 if (u && ((rd | rn) & 1)) {
5839 return 1;
5841 tmp = neon_get_scalar(size, rm);
5842 neon_store_scratch(0, tmp);
5843 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5844 tmp = neon_load_scratch(0);
5845 tmp2 = neon_load_reg(rn, pass);
5846 if (op == 12) {
5847 if (size == 1) {
5848 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5849 } else {
5850 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5852 } else if (op == 13) {
5853 if (size == 1) {
5854 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5855 } else {
5856 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5858 } else if (op & 1) {
5859 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5860 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5861 tcg_temp_free_ptr(fpstatus);
5862 } else {
5863 switch (size) {
5864 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5865 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5866 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5867 default: abort();
5870 tcg_temp_free_i32(tmp2);
5871 if (op < 8) {
5872 /* Accumulate. */
5873 tmp2 = neon_load_reg(rd, pass);
5874 switch (op) {
5875 case 0:
5876 gen_neon_add(size, tmp, tmp2);
5877 break;
5878 case 1:
5880 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5881 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5882 tcg_temp_free_ptr(fpstatus);
5883 break;
5885 case 4:
5886 gen_neon_rsb(size, tmp, tmp2);
5887 break;
5888 case 5:
5890 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5891 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5892 tcg_temp_free_ptr(fpstatus);
5893 break;
5895 default:
5896 abort();
5898 tcg_temp_free_i32(tmp2);
5900 neon_store_reg(rd, pass, tmp);
5902 break;
5903 case 3: /* VQDMLAL scalar */
5904 case 7: /* VQDMLSL scalar */
5905 case 11: /* VQDMULL scalar */
5906 if (u == 1) {
5907 return 1;
5909 /* fall through */
5910 case 2: /* VMLAL sclar */
5911 case 6: /* VMLSL scalar */
5912 case 10: /* VMULL scalar */
5913 if (rd & 1) {
5914 return 1;
5916 tmp2 = neon_get_scalar(size, rm);
5917 /* We need a copy of tmp2 because gen_neon_mull
5918 * deletes it during pass 0. */
5919 tmp4 = tcg_temp_new_i32();
5920 tcg_gen_mov_i32(tmp4, tmp2);
5921 tmp3 = neon_load_reg(rn, 1);
5923 for (pass = 0; pass < 2; pass++) {
5924 if (pass == 0) {
5925 tmp = neon_load_reg(rn, 0);
5926 } else {
5927 tmp = tmp3;
5928 tmp2 = tmp4;
5930 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5931 if (op != 11) {
5932 neon_load_reg64(cpu_V1, rd + pass);
5934 switch (op) {
5935 case 6:
5936 gen_neon_negl(cpu_V0, size);
5937 /* Fall through */
5938 case 2:
5939 gen_neon_addl(size);
5940 break;
5941 case 3: case 7:
5942 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5943 if (op == 7) {
5944 gen_neon_negl(cpu_V0, size);
5946 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5947 break;
5948 case 10:
5949 /* no-op */
5950 break;
5951 case 11:
5952 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5953 break;
5954 default:
5955 abort();
5957 neon_store_reg64(cpu_V0, rd + pass);
5961 break;
5962 default: /* 14 and 15 are RESERVED */
5963 return 1;
5966 } else { /* size == 3 */
5967 if (!u) {
5968 /* Extract. */
5969 imm = (insn >> 8) & 0xf;
5971 if (imm > 7 && !q)
5972 return 1;
5974 if (q && ((rd | rn | rm) & 1)) {
5975 return 1;
5978 if (imm == 0) {
5979 neon_load_reg64(cpu_V0, rn);
5980 if (q) {
5981 neon_load_reg64(cpu_V1, rn + 1);
5983 } else if (imm == 8) {
5984 neon_load_reg64(cpu_V0, rn + 1);
5985 if (q) {
5986 neon_load_reg64(cpu_V1, rm);
5988 } else if (q) {
5989 tmp64 = tcg_temp_new_i64();
5990 if (imm < 8) {
5991 neon_load_reg64(cpu_V0, rn);
5992 neon_load_reg64(tmp64, rn + 1);
5993 } else {
5994 neon_load_reg64(cpu_V0, rn + 1);
5995 neon_load_reg64(tmp64, rm);
5997 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
5998 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
5999 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6000 if (imm < 8) {
6001 neon_load_reg64(cpu_V1, rm);
6002 } else {
6003 neon_load_reg64(cpu_V1, rm + 1);
6004 imm -= 8;
6006 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6007 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6008 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
6009 tcg_temp_free_i64(tmp64);
6010 } else {
6011 /* BUGFIX */
6012 neon_load_reg64(cpu_V0, rn);
6013 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
6014 neon_load_reg64(cpu_V1, rm);
6015 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6016 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6018 neon_store_reg64(cpu_V0, rd);
6019 if (q) {
6020 neon_store_reg64(cpu_V1, rd + 1);
6022 } else if ((insn & (1 << 11)) == 0) {
6023 /* Two register misc. */
6024 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6025 size = (insn >> 18) & 3;
6026 /* UNDEF for unknown op values and bad op-size combinations */
6027 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6028 return 1;
6030 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6031 q && ((rm | rd) & 1)) {
6032 return 1;
6034 switch (op) {
6035 case NEON_2RM_VREV64:
6036 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6037 tmp = neon_load_reg(rm, pass * 2);
6038 tmp2 = neon_load_reg(rm, pass * 2 + 1);
6039 switch (size) {
6040 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6041 case 1: gen_swap_half(tmp); break;
6042 case 2: /* no-op */ break;
6043 default: abort();
6045 neon_store_reg(rd, pass * 2 + 1, tmp);
6046 if (size == 2) {
6047 neon_store_reg(rd, pass * 2, tmp2);
6048 } else {
6049 switch (size) {
6050 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6051 case 1: gen_swap_half(tmp2); break;
6052 default: abort();
6054 neon_store_reg(rd, pass * 2, tmp2);
6057 break;
6058 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6059 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
6060 for (pass = 0; pass < q + 1; pass++) {
6061 tmp = neon_load_reg(rm, pass * 2);
6062 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6063 tmp = neon_load_reg(rm, pass * 2 + 1);
6064 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6065 switch (size) {
6066 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6067 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6068 case 2: tcg_gen_add_i64(CPU_V001); break;
6069 default: abort();
6071 if (op >= NEON_2RM_VPADAL) {
6072 /* Accumulate. */
6073 neon_load_reg64(cpu_V1, rd + pass);
6074 gen_neon_addl(size);
6076 neon_store_reg64(cpu_V0, rd + pass);
6078 break;
6079 case NEON_2RM_VTRN:
6080 if (size == 2) {
6081 int n;
6082 for (n = 0; n < (q ? 4 : 2); n += 2) {
6083 tmp = neon_load_reg(rm, n);
6084 tmp2 = neon_load_reg(rd, n + 1);
6085 neon_store_reg(rm, n, tmp2);
6086 neon_store_reg(rd, n + 1, tmp);
6088 } else {
6089 goto elementwise;
6091 break;
6092 case NEON_2RM_VUZP:
6093 if (gen_neon_unzip(rd, rm, size, q)) {
6094 return 1;
6096 break;
6097 case NEON_2RM_VZIP:
6098 if (gen_neon_zip(rd, rm, size, q)) {
6099 return 1;
6101 break;
6102 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6103 /* also VQMOVUN; op field and mnemonics don't line up */
6104 if (rm & 1) {
6105 return 1;
6107 TCGV_UNUSED_I32(tmp2);
6108 for (pass = 0; pass < 2; pass++) {
6109 neon_load_reg64(cpu_V0, rm + pass);
6110 tmp = tcg_temp_new_i32();
6111 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6112 tmp, cpu_V0);
6113 if (pass == 0) {
6114 tmp2 = tmp;
6115 } else {
6116 neon_store_reg(rd, 0, tmp2);
6117 neon_store_reg(rd, 1, tmp);
6120 break;
6121 case NEON_2RM_VSHLL:
6122 if (q || (rd & 1)) {
6123 return 1;
6125 tmp = neon_load_reg(rm, 0);
6126 tmp2 = neon_load_reg(rm, 1);
6127 for (pass = 0; pass < 2; pass++) {
6128 if (pass == 1)
6129 tmp = tmp2;
6130 gen_neon_widen(cpu_V0, tmp, size, 1);
6131 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
6132 neon_store_reg64(cpu_V0, rd + pass);
6134 break;
6135 case NEON_2RM_VCVT_F16_F32:
6136 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6137 q || (rm & 1)) {
6138 return 1;
6140 tmp = tcg_temp_new_i32();
6141 tmp2 = tcg_temp_new_i32();
6142 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
6143 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6144 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
6145 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6146 tcg_gen_shli_i32(tmp2, tmp2, 16);
6147 tcg_gen_or_i32(tmp2, tmp2, tmp);
6148 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
6149 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6150 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6151 neon_store_reg(rd, 0, tmp2);
6152 tmp2 = tcg_temp_new_i32();
6153 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6154 tcg_gen_shli_i32(tmp2, tmp2, 16);
6155 tcg_gen_or_i32(tmp2, tmp2, tmp);
6156 neon_store_reg(rd, 1, tmp2);
6157 tcg_temp_free_i32(tmp);
6158 break;
6159 case NEON_2RM_VCVT_F32_F16:
6160 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6161 q || (rd & 1)) {
6162 return 1;
6164 tmp3 = tcg_temp_new_i32();
6165 tmp = neon_load_reg(rm, 0);
6166 tmp2 = neon_load_reg(rm, 1);
6167 tcg_gen_ext16u_i32(tmp3, tmp);
6168 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6169 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6170 tcg_gen_shri_i32(tmp3, tmp, 16);
6171 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6172 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6173 tcg_temp_free_i32(tmp);
6174 tcg_gen_ext16u_i32(tmp3, tmp2);
6175 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6176 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6177 tcg_gen_shri_i32(tmp3, tmp2, 16);
6178 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6179 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6180 tcg_temp_free_i32(tmp2);
6181 tcg_temp_free_i32(tmp3);
6182 break;
6183 case NEON_2RM_AESE: case NEON_2RM_AESMC:
6184 if (!arm_feature(env, ARM_FEATURE_V8_AES)
6185 || ((rm | rd) & 1)) {
6186 return 1;
6188 tmp = tcg_const_i32(rd);
6189 tmp2 = tcg_const_i32(rm);
6191 /* Bit 6 is the lowest opcode bit; it distinguishes between
6192 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6194 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6196 if (op == NEON_2RM_AESE) {
6197 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6198 } else {
6199 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6201 tcg_temp_free_i32(tmp);
6202 tcg_temp_free_i32(tmp2);
6203 tcg_temp_free_i32(tmp3);
6204 break;
6205 default:
6206 elementwise:
6207 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6208 if (neon_2rm_is_float_op(op)) {
6209 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6210 neon_reg_offset(rm, pass));
6211 TCGV_UNUSED_I32(tmp);
6212 } else {
6213 tmp = neon_load_reg(rm, pass);
6215 switch (op) {
6216 case NEON_2RM_VREV32:
6217 switch (size) {
6218 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6219 case 1: gen_swap_half(tmp); break;
6220 default: abort();
6222 break;
6223 case NEON_2RM_VREV16:
6224 gen_rev16(tmp);
6225 break;
6226 case NEON_2RM_VCLS:
6227 switch (size) {
6228 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6229 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6230 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6231 default: abort();
6233 break;
6234 case NEON_2RM_VCLZ:
6235 switch (size) {
6236 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6237 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6238 case 2: gen_helper_clz(tmp, tmp); break;
6239 default: abort();
6241 break;
6242 case NEON_2RM_VCNT:
6243 gen_helper_neon_cnt_u8(tmp, tmp);
6244 break;
6245 case NEON_2RM_VMVN:
6246 tcg_gen_not_i32(tmp, tmp);
6247 break;
6248 case NEON_2RM_VQABS:
6249 switch (size) {
6250 case 0:
6251 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6252 break;
6253 case 1:
6254 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6255 break;
6256 case 2:
6257 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6258 break;
6259 default: abort();
6261 break;
6262 case NEON_2RM_VQNEG:
6263 switch (size) {
6264 case 0:
6265 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6266 break;
6267 case 1:
6268 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6269 break;
6270 case 2:
6271 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6272 break;
6273 default: abort();
6275 break;
6276 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6277 tmp2 = tcg_const_i32(0);
6278 switch(size) {
6279 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6280 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6281 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6282 default: abort();
6284 tcg_temp_free_i32(tmp2);
6285 if (op == NEON_2RM_VCLE0) {
6286 tcg_gen_not_i32(tmp, tmp);
6288 break;
6289 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6290 tmp2 = tcg_const_i32(0);
6291 switch(size) {
6292 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6293 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6294 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6295 default: abort();
6297 tcg_temp_free_i32(tmp2);
6298 if (op == NEON_2RM_VCLT0) {
6299 tcg_gen_not_i32(tmp, tmp);
6301 break;
6302 case NEON_2RM_VCEQ0:
6303 tmp2 = tcg_const_i32(0);
6304 switch(size) {
6305 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6306 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6307 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6308 default: abort();
6310 tcg_temp_free_i32(tmp2);
6311 break;
6312 case NEON_2RM_VABS:
6313 switch(size) {
6314 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6315 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6316 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6317 default: abort();
6319 break;
6320 case NEON_2RM_VNEG:
6321 tmp2 = tcg_const_i32(0);
6322 gen_neon_rsb(size, tmp, tmp2);
6323 tcg_temp_free_i32(tmp2);
6324 break;
6325 case NEON_2RM_VCGT0_F:
6327 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6328 tmp2 = tcg_const_i32(0);
6329 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6330 tcg_temp_free_i32(tmp2);
6331 tcg_temp_free_ptr(fpstatus);
6332 break;
6334 case NEON_2RM_VCGE0_F:
6336 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6337 tmp2 = tcg_const_i32(0);
6338 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6339 tcg_temp_free_i32(tmp2);
6340 tcg_temp_free_ptr(fpstatus);
6341 break;
6343 case NEON_2RM_VCEQ0_F:
6345 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6346 tmp2 = tcg_const_i32(0);
6347 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6348 tcg_temp_free_i32(tmp2);
6349 tcg_temp_free_ptr(fpstatus);
6350 break;
6352 case NEON_2RM_VCLE0_F:
6354 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6355 tmp2 = tcg_const_i32(0);
6356 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6357 tcg_temp_free_i32(tmp2);
6358 tcg_temp_free_ptr(fpstatus);
6359 break;
6361 case NEON_2RM_VCLT0_F:
6363 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6364 tmp2 = tcg_const_i32(0);
6365 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6366 tcg_temp_free_i32(tmp2);
6367 tcg_temp_free_ptr(fpstatus);
6368 break;
6370 case NEON_2RM_VABS_F:
6371 gen_vfp_abs(0);
6372 break;
6373 case NEON_2RM_VNEG_F:
6374 gen_vfp_neg(0);
6375 break;
6376 case NEON_2RM_VSWP:
6377 tmp2 = neon_load_reg(rd, pass);
6378 neon_store_reg(rm, pass, tmp2);
6379 break;
6380 case NEON_2RM_VTRN:
6381 tmp2 = neon_load_reg(rd, pass);
6382 switch (size) {
6383 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6384 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6385 default: abort();
6387 neon_store_reg(rm, pass, tmp2);
6388 break;
6389 case NEON_2RM_VRECPE:
6390 gen_helper_recpe_u32(tmp, tmp, cpu_env);
6391 break;
6392 case NEON_2RM_VRSQRTE:
6393 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
6394 break;
6395 case NEON_2RM_VRECPE_F:
6396 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
6397 break;
6398 case NEON_2RM_VRSQRTE_F:
6399 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
6400 break;
6401 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6402 gen_vfp_sito(0, 1);
6403 break;
6404 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6405 gen_vfp_uito(0, 1);
6406 break;
6407 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6408 gen_vfp_tosiz(0, 1);
6409 break;
6410 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6411 gen_vfp_touiz(0, 1);
6412 break;
6413 default:
6414 /* Reserved op values were caught by the
6415 * neon_2rm_sizes[] check earlier.
6417 abort();
6419 if (neon_2rm_is_float_op(op)) {
6420 tcg_gen_st_f32(cpu_F0s, cpu_env,
6421 neon_reg_offset(rd, pass));
6422 } else {
6423 neon_store_reg(rd, pass, tmp);
6426 break;
6428 } else if ((insn & (1 << 10)) == 0) {
6429 /* VTBL, VTBX. */
6430 int n = ((insn >> 8) & 3) + 1;
6431 if ((rn + n) > 32) {
6432 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6433 * helper function running off the end of the register file.
6435 return 1;
6437 n <<= 3;
6438 if (insn & (1 << 6)) {
6439 tmp = neon_load_reg(rd, 0);
6440 } else {
6441 tmp = tcg_temp_new_i32();
6442 tcg_gen_movi_i32(tmp, 0);
6444 tmp2 = neon_load_reg(rm, 0);
6445 tmp4 = tcg_const_i32(rn);
6446 tmp5 = tcg_const_i32(n);
6447 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
6448 tcg_temp_free_i32(tmp);
6449 if (insn & (1 << 6)) {
6450 tmp = neon_load_reg(rd, 1);
6451 } else {
6452 tmp = tcg_temp_new_i32();
6453 tcg_gen_movi_i32(tmp, 0);
6455 tmp3 = neon_load_reg(rm, 1);
6456 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
6457 tcg_temp_free_i32(tmp5);
6458 tcg_temp_free_i32(tmp4);
6459 neon_store_reg(rd, 0, tmp2);
6460 neon_store_reg(rd, 1, tmp3);
6461 tcg_temp_free_i32(tmp);
6462 } else if ((insn & 0x380) == 0) {
6463 /* VDUP */
6464 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6465 return 1;
6467 if (insn & (1 << 19)) {
6468 tmp = neon_load_reg(rm, 1);
6469 } else {
6470 tmp = neon_load_reg(rm, 0);
6472 if (insn & (1 << 16)) {
6473 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6474 } else if (insn & (1 << 17)) {
6475 if ((insn >> 18) & 1)
6476 gen_neon_dup_high16(tmp);
6477 else
6478 gen_neon_dup_low16(tmp);
6480 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6481 tmp2 = tcg_temp_new_i32();
6482 tcg_gen_mov_i32(tmp2, tmp);
6483 neon_store_reg(rd, pass, tmp2);
6485 tcg_temp_free_i32(tmp);
6486 } else {
6487 return 1;
6491 return 0;
6494 static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
6496 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
6497 const ARMCPRegInfo *ri;
6499 cpnum = (insn >> 8) & 0xf;
6500 if (arm_feature(env, ARM_FEATURE_XSCALE)
6501 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6502 return 1;
6504 /* First check for coprocessor space used for actual instructions */
6505 switch (cpnum) {
6506 case 0:
6507 case 1:
6508 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6509 return disas_iwmmxt_insn(env, s, insn);
6510 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6511 return disas_dsp_insn(env, s, insn);
6513 return 1;
6514 default:
6515 break;
6518 /* Otherwise treat as a generic register access */
6519 is64 = (insn & (1 << 25)) == 0;
6520 if (!is64 && ((insn & (1 << 4)) == 0)) {
6521 /* cdp */
6522 return 1;
6525 crm = insn & 0xf;
6526 if (is64) {
6527 crn = 0;
6528 opc1 = (insn >> 4) & 0xf;
6529 opc2 = 0;
6530 rt2 = (insn >> 16) & 0xf;
6531 } else {
6532 crn = (insn >> 16) & 0xf;
6533 opc1 = (insn >> 21) & 7;
6534 opc2 = (insn >> 5) & 7;
6535 rt2 = 0;
6537 isread = (insn >> 20) & 1;
6538 rt = (insn >> 12) & 0xf;
6540 ri = get_arm_cp_reginfo(s->cp_regs,
6541 ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
6542 if (ri) {
6543 /* Check access permissions */
6544 if (!cp_access_ok(s->current_pl, ri, isread)) {
6545 return 1;
6548 /* Handle special cases first */
6549 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
6550 case ARM_CP_NOP:
6551 return 0;
6552 case ARM_CP_WFI:
6553 if (isread) {
6554 return 1;
6556 gen_set_pc_im(s, s->pc);
6557 s->is_jmp = DISAS_WFI;
6558 return 0;
6559 default:
6560 break;
6563 if (use_icount && (ri->type & ARM_CP_IO)) {
6564 gen_io_start();
6567 if (isread) {
6568 /* Read */
6569 if (is64) {
6570 TCGv_i64 tmp64;
6571 TCGv_i32 tmp;
6572 if (ri->type & ARM_CP_CONST) {
6573 tmp64 = tcg_const_i64(ri->resetvalue);
6574 } else if (ri->readfn) {
6575 TCGv_ptr tmpptr;
6576 gen_set_pc_im(s, s->pc);
6577 tmp64 = tcg_temp_new_i64();
6578 tmpptr = tcg_const_ptr(ri);
6579 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
6580 tcg_temp_free_ptr(tmpptr);
6581 } else {
6582 tmp64 = tcg_temp_new_i64();
6583 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
6585 tmp = tcg_temp_new_i32();
6586 tcg_gen_trunc_i64_i32(tmp, tmp64);
6587 store_reg(s, rt, tmp);
6588 tcg_gen_shri_i64(tmp64, tmp64, 32);
6589 tmp = tcg_temp_new_i32();
6590 tcg_gen_trunc_i64_i32(tmp, tmp64);
6591 tcg_temp_free_i64(tmp64);
6592 store_reg(s, rt2, tmp);
6593 } else {
6594 TCGv_i32 tmp;
6595 if (ri->type & ARM_CP_CONST) {
6596 tmp = tcg_const_i32(ri->resetvalue);
6597 } else if (ri->readfn) {
6598 TCGv_ptr tmpptr;
6599 gen_set_pc_im(s, s->pc);
6600 tmp = tcg_temp_new_i32();
6601 tmpptr = tcg_const_ptr(ri);
6602 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
6603 tcg_temp_free_ptr(tmpptr);
6604 } else {
6605 tmp = load_cpu_offset(ri->fieldoffset);
6607 if (rt == 15) {
6608 /* Destination register of r15 for 32 bit loads sets
6609 * the condition codes from the high 4 bits of the value
6611 gen_set_nzcv(tmp);
6612 tcg_temp_free_i32(tmp);
6613 } else {
6614 store_reg(s, rt, tmp);
6617 } else {
6618 /* Write */
6619 if (ri->type & ARM_CP_CONST) {
6620 /* If not forbidden by access permissions, treat as WI */
6621 return 0;
6624 if (is64) {
6625 TCGv_i32 tmplo, tmphi;
6626 TCGv_i64 tmp64 = tcg_temp_new_i64();
6627 tmplo = load_reg(s, rt);
6628 tmphi = load_reg(s, rt2);
6629 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
6630 tcg_temp_free_i32(tmplo);
6631 tcg_temp_free_i32(tmphi);
6632 if (ri->writefn) {
6633 TCGv_ptr tmpptr = tcg_const_ptr(ri);
6634 gen_set_pc_im(s, s->pc);
6635 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
6636 tcg_temp_free_ptr(tmpptr);
6637 } else {
6638 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
6640 tcg_temp_free_i64(tmp64);
6641 } else {
6642 if (ri->writefn) {
6643 TCGv_i32 tmp;
6644 TCGv_ptr tmpptr;
6645 gen_set_pc_im(s, s->pc);
6646 tmp = load_reg(s, rt);
6647 tmpptr = tcg_const_ptr(ri);
6648 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
6649 tcg_temp_free_ptr(tmpptr);
6650 tcg_temp_free_i32(tmp);
6651 } else {
6652 TCGv_i32 tmp = load_reg(s, rt);
6653 store_cpu_offset(tmp, ri->fieldoffset);
6658 if (use_icount && (ri->type & ARM_CP_IO)) {
6659 /* I/O operations must end the TB here (whether read or write) */
6660 gen_io_end();
6661 gen_lookup_tb(s);
6662 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
6663 /* We default to ending the TB on a coprocessor register write,
6664 * but allow this to be suppressed by the register definition
6665 * (usually only necessary to work around guest bugs).
6667 gen_lookup_tb(s);
6670 return 0;
6673 return 1;
6677 /* Store a 64-bit value to a register pair. Clobbers val. */
6678 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6680 TCGv_i32 tmp;
6681 tmp = tcg_temp_new_i32();
6682 tcg_gen_trunc_i64_i32(tmp, val);
6683 store_reg(s, rlow, tmp);
6684 tmp = tcg_temp_new_i32();
6685 tcg_gen_shri_i64(val, val, 32);
6686 tcg_gen_trunc_i64_i32(tmp, val);
6687 store_reg(s, rhigh, tmp);
6690 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6691 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
6693 TCGv_i64 tmp;
6694 TCGv_i32 tmp2;
6696 /* Load value and extend to 64 bits. */
6697 tmp = tcg_temp_new_i64();
6698 tmp2 = load_reg(s, rlow);
6699 tcg_gen_extu_i32_i64(tmp, tmp2);
6700 tcg_temp_free_i32(tmp2);
6701 tcg_gen_add_i64(val, val, tmp);
6702 tcg_temp_free_i64(tmp);
6705 /* load and add a 64-bit value from a register pair. */
6706 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
6708 TCGv_i64 tmp;
6709 TCGv_i32 tmpl;
6710 TCGv_i32 tmph;
6712 /* Load 64-bit value rd:rn. */
6713 tmpl = load_reg(s, rlow);
6714 tmph = load_reg(s, rhigh);
6715 tmp = tcg_temp_new_i64();
6716 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
6717 tcg_temp_free_i32(tmpl);
6718 tcg_temp_free_i32(tmph);
6719 tcg_gen_add_i64(val, val, tmp);
6720 tcg_temp_free_i64(tmp);
6723 /* Set N and Z flags from hi|lo. */
6724 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
6726 tcg_gen_mov_i32(cpu_NF, hi);
6727 tcg_gen_or_i32(cpu_ZF, lo, hi);
6730 /* Load/Store exclusive instructions are implemented by remembering
6731 the value/address loaded, and seeing if these are the same
6732 when the store is performed. This should be sufficient to implement
6733 the architecturally mandated semantics, and avoids having to monitor
6734 regular stores.
6736 In system emulation mode only one CPU will be running at once, so
6737 this sequence is effectively atomic. In user emulation mode we
6738 throw an exception and handle the atomic operation elsewhere. */
6739 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6740 TCGv_i32 addr, int size)
6742 TCGv_i32 tmp = tcg_temp_new_i32();
6744 switch (size) {
6745 case 0:
6746 gen_aa32_ld8u(tmp, addr, IS_USER(s));
6747 break;
6748 case 1:
6749 gen_aa32_ld16u(tmp, addr, IS_USER(s));
6750 break;
6751 case 2:
6752 case 3:
6753 gen_aa32_ld32u(tmp, addr, IS_USER(s));
6754 break;
6755 default:
6756 abort();
6759 if (size == 3) {
6760 TCGv_i32 tmp2 = tcg_temp_new_i32();
6761 TCGv_i32 tmp3 = tcg_temp_new_i32();
6763 tcg_gen_addi_i32(tmp2, addr, 4);
6764 gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
6765 tcg_temp_free_i32(tmp2);
6766 tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
6767 store_reg(s, rt2, tmp3);
6768 } else {
6769 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
6772 store_reg(s, rt, tmp);
6773 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
6776 static void gen_clrex(DisasContext *s)
6778 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
6781 #ifdef CONFIG_USER_ONLY
6782 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6783 TCGv_i32 addr, int size)
6785 tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
6786 tcg_gen_movi_i32(cpu_exclusive_info,
6787 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6788 gen_exception_insn(s, 4, EXCP_STREX);
6790 #else
6791 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6792 TCGv_i32 addr, int size)
6794 TCGv_i32 tmp;
6795 TCGv_i64 val64, extaddr;
6796 int done_label;
6797 int fail_label;
6799 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6800 [addr] = {Rt};
6801 {Rd} = 0;
6802 } else {
6803 {Rd} = 1;
6804 } */
6805 fail_label = gen_new_label();
6806 done_label = gen_new_label();
6807 extaddr = tcg_temp_new_i64();
6808 tcg_gen_extu_i32_i64(extaddr, addr);
6809 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
6810 tcg_temp_free_i64(extaddr);
6812 tmp = tcg_temp_new_i32();
6813 switch (size) {
6814 case 0:
6815 gen_aa32_ld8u(tmp, addr, IS_USER(s));
6816 break;
6817 case 1:
6818 gen_aa32_ld16u(tmp, addr, IS_USER(s));
6819 break;
6820 case 2:
6821 case 3:
6822 gen_aa32_ld32u(tmp, addr, IS_USER(s));
6823 break;
6824 default:
6825 abort();
6828 val64 = tcg_temp_new_i64();
6829 if (size == 3) {
6830 TCGv_i32 tmp2 = tcg_temp_new_i32();
6831 TCGv_i32 tmp3 = tcg_temp_new_i32();
6832 tcg_gen_addi_i32(tmp2, addr, 4);
6833 gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
6834 tcg_temp_free_i32(tmp2);
6835 tcg_gen_concat_i32_i64(val64, tmp, tmp3);
6836 tcg_temp_free_i32(tmp3);
6837 } else {
6838 tcg_gen_extu_i32_i64(val64, tmp);
6840 tcg_temp_free_i32(tmp);
6842 tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
6843 tcg_temp_free_i64(val64);
6845 tmp = load_reg(s, rt);
6846 switch (size) {
6847 case 0:
6848 gen_aa32_st8(tmp, addr, IS_USER(s));
6849 break;
6850 case 1:
6851 gen_aa32_st16(tmp, addr, IS_USER(s));
6852 break;
6853 case 2:
6854 case 3:
6855 gen_aa32_st32(tmp, addr, IS_USER(s));
6856 break;
6857 default:
6858 abort();
6860 tcg_temp_free_i32(tmp);
6861 if (size == 3) {
6862 tcg_gen_addi_i32(addr, addr, 4);
6863 tmp = load_reg(s, rt2);
6864 gen_aa32_st32(tmp, addr, IS_USER(s));
6865 tcg_temp_free_i32(tmp);
6867 tcg_gen_movi_i32(cpu_R[rd], 0);
6868 tcg_gen_br(done_label);
6869 gen_set_label(fail_label);
6870 tcg_gen_movi_i32(cpu_R[rd], 1);
6871 gen_set_label(done_label);
6872 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
6874 #endif
6876 /* gen_srs:
6877 * @env: CPUARMState
6878 * @s: DisasContext
6879 * @mode: mode field from insn (which stack to store to)
6880 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
6881 * @writeback: true if writeback bit set
6883 * Generate code for the SRS (Store Return State) insn.
6885 static void gen_srs(DisasContext *s,
6886 uint32_t mode, uint32_t amode, bool writeback)
6888 int32_t offset;
6889 TCGv_i32 addr = tcg_temp_new_i32();
6890 TCGv_i32 tmp = tcg_const_i32(mode);
6891 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6892 tcg_temp_free_i32(tmp);
6893 switch (amode) {
6894 case 0: /* DA */
6895 offset = -4;
6896 break;
6897 case 1: /* IA */
6898 offset = 0;
6899 break;
6900 case 2: /* DB */
6901 offset = -8;
6902 break;
6903 case 3: /* IB */
6904 offset = 4;
6905 break;
6906 default:
6907 abort();
6909 tcg_gen_addi_i32(addr, addr, offset);
6910 tmp = load_reg(s, 14);
6911 gen_aa32_st32(tmp, addr, 0);
6912 tcg_temp_free_i32(tmp);
6913 tmp = load_cpu_field(spsr);
6914 tcg_gen_addi_i32(addr, addr, 4);
6915 gen_aa32_st32(tmp, addr, 0);
6916 tcg_temp_free_i32(tmp);
6917 if (writeback) {
6918 switch (amode) {
6919 case 0:
6920 offset = -8;
6921 break;
6922 case 1:
6923 offset = 4;
6924 break;
6925 case 2:
6926 offset = -4;
6927 break;
6928 case 3:
6929 offset = 0;
6930 break;
6931 default:
6932 abort();
6934 tcg_gen_addi_i32(addr, addr, offset);
6935 tmp = tcg_const_i32(mode);
6936 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6937 tcg_temp_free_i32(tmp);
6939 tcg_temp_free_i32(addr);
6942 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
6944 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6945 TCGv_i32 tmp;
6946 TCGv_i32 tmp2;
6947 TCGv_i32 tmp3;
6948 TCGv_i32 addr;
6949 TCGv_i64 tmp64;
6951 insn = arm_ldl_code(env, s->pc, s->bswap_code);
6952 s->pc += 4;
6954 /* M variants do not implement ARM mode. */
6955 if (IS_M(env))
6956 goto illegal_op;
6957 cond = insn >> 28;
6958 if (cond == 0xf){
6959 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6960 * choose to UNDEF. In ARMv5 and above the space is used
6961 * for miscellaneous unconditional instructions.
6963 ARCH(5);
6965 /* Unconditional instructions. */
6966 if (((insn >> 25) & 7) == 1) {
6967 /* NEON Data processing. */
6968 if (!arm_feature(env, ARM_FEATURE_NEON))
6969 goto illegal_op;
6971 if (disas_neon_data_insn(env, s, insn))
6972 goto illegal_op;
6973 return;
6975 if ((insn & 0x0f100000) == 0x04000000) {
6976 /* NEON load/store. */
6977 if (!arm_feature(env, ARM_FEATURE_NEON))
6978 goto illegal_op;
6980 if (disas_neon_ls_insn(env, s, insn))
6981 goto illegal_op;
6982 return;
6984 if ((insn & 0x0f000e10) == 0x0e000a00) {
6985 /* VFP. */
6986 if (disas_vfp_insn(env, s, insn)) {
6987 goto illegal_op;
6989 return;
6991 if (((insn & 0x0f30f000) == 0x0510f000) ||
6992 ((insn & 0x0f30f010) == 0x0710f000)) {
6993 if ((insn & (1 << 22)) == 0) {
6994 /* PLDW; v7MP */
6995 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6996 goto illegal_op;
6999 /* Otherwise PLD; v5TE+ */
7000 ARCH(5TE);
7001 return;
7003 if (((insn & 0x0f70f000) == 0x0450f000) ||
7004 ((insn & 0x0f70f010) == 0x0650f000)) {
7005 ARCH(7);
7006 return; /* PLI; V7 */
7008 if (((insn & 0x0f700000) == 0x04100000) ||
7009 ((insn & 0x0f700010) == 0x06100000)) {
7010 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7011 goto illegal_op;
7013 return; /* v7MP: Unallocated memory hint: must NOP */
7016 if ((insn & 0x0ffffdff) == 0x01010000) {
7017 ARCH(6);
7018 /* setend */
7019 if (((insn >> 9) & 1) != s->bswap_code) {
7020 /* Dynamic endianness switching not implemented. */
7021 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
7022 goto illegal_op;
7024 return;
7025 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7026 switch ((insn >> 4) & 0xf) {
7027 case 1: /* clrex */
7028 ARCH(6K);
7029 gen_clrex(s);
7030 return;
7031 case 4: /* dsb */
7032 case 5: /* dmb */
7033 case 6: /* isb */
7034 ARCH(7);
7035 /* We don't emulate caches so these are a no-op. */
7036 return;
7037 default:
7038 goto illegal_op;
7040 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7041 /* srs */
7042 if (IS_USER(s)) {
7043 goto illegal_op;
7045 ARCH(6);
7046 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
7047 return;
7048 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
7049 /* rfe */
7050 int32_t offset;
7051 if (IS_USER(s))
7052 goto illegal_op;
7053 ARCH(6);
7054 rn = (insn >> 16) & 0xf;
7055 addr = load_reg(s, rn);
7056 i = (insn >> 23) & 3;
7057 switch (i) {
7058 case 0: offset = -4; break; /* DA */
7059 case 1: offset = 0; break; /* IA */
7060 case 2: offset = -8; break; /* DB */
7061 case 3: offset = 4; break; /* IB */
7062 default: abort();
7064 if (offset)
7065 tcg_gen_addi_i32(addr, addr, offset);
7066 /* Load PC into tmp and CPSR into tmp2. */
7067 tmp = tcg_temp_new_i32();
7068 gen_aa32_ld32u(tmp, addr, 0);
7069 tcg_gen_addi_i32(addr, addr, 4);
7070 tmp2 = tcg_temp_new_i32();
7071 gen_aa32_ld32u(tmp2, addr, 0);
7072 if (insn & (1 << 21)) {
7073 /* Base writeback. */
7074 switch (i) {
7075 case 0: offset = -8; break;
7076 case 1: offset = 4; break;
7077 case 2: offset = -4; break;
7078 case 3: offset = 0; break;
7079 default: abort();
7081 if (offset)
7082 tcg_gen_addi_i32(addr, addr, offset);
7083 store_reg(s, rn, addr);
7084 } else {
7085 tcg_temp_free_i32(addr);
7087 gen_rfe(s, tmp, tmp2);
7088 return;
7089 } else if ((insn & 0x0e000000) == 0x0a000000) {
7090 /* branch link and change to thumb (blx <offset>) */
7091 int32_t offset;
7093 val = (uint32_t)s->pc;
7094 tmp = tcg_temp_new_i32();
7095 tcg_gen_movi_i32(tmp, val);
7096 store_reg(s, 14, tmp);
7097 /* Sign-extend the 24-bit offset */
7098 offset = (((int32_t)insn) << 8) >> 8;
7099 /* offset * 4 + bit24 * 2 + (thumb bit) */
7100 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7101 /* pipeline offset */
7102 val += 4;
7103 /* protected by ARCH(5); above, near the start of uncond block */
7104 gen_bx_im(s, val);
7105 return;
7106 } else if ((insn & 0x0e000f00) == 0x0c000100) {
7107 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7108 /* iWMMXt register transfer. */
7109 if (env->cp15.c15_cpar & (1 << 1))
7110 if (!disas_iwmmxt_insn(env, s, insn))
7111 return;
7113 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7114 /* Coprocessor double register transfer. */
7115 ARCH(5TE);
7116 } else if ((insn & 0x0f000010) == 0x0e000010) {
7117 /* Additional coprocessor register transfer. */
7118 } else if ((insn & 0x0ff10020) == 0x01000000) {
7119 uint32_t mask;
7120 uint32_t val;
7121 /* cps (privileged) */
7122 if (IS_USER(s))
7123 return;
7124 mask = val = 0;
7125 if (insn & (1 << 19)) {
7126 if (insn & (1 << 8))
7127 mask |= CPSR_A;
7128 if (insn & (1 << 7))
7129 mask |= CPSR_I;
7130 if (insn & (1 << 6))
7131 mask |= CPSR_F;
7132 if (insn & (1 << 18))
7133 val |= mask;
7135 if (insn & (1 << 17)) {
7136 mask |= CPSR_M;
7137 val |= (insn & 0x1f);
7139 if (mask) {
7140 gen_set_psr_im(s, mask, 0, val);
7142 return;
7144 goto illegal_op;
7146 if (cond != 0xe) {
7147 /* if not always execute, we generate a conditional jump to
7148 next instruction */
7149 s->condlabel = gen_new_label();
7150 arm_gen_test_cc(cond ^ 1, s->condlabel);
7151 s->condjmp = 1;
7153 if ((insn & 0x0f900000) == 0x03000000) {
7154 if ((insn & (1 << 21)) == 0) {
7155 ARCH(6T2);
7156 rd = (insn >> 12) & 0xf;
7157 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7158 if ((insn & (1 << 22)) == 0) {
7159 /* MOVW */
7160 tmp = tcg_temp_new_i32();
7161 tcg_gen_movi_i32(tmp, val);
7162 } else {
7163 /* MOVT */
7164 tmp = load_reg(s, rd);
7165 tcg_gen_ext16u_i32(tmp, tmp);
7166 tcg_gen_ori_i32(tmp, tmp, val << 16);
7168 store_reg(s, rd, tmp);
7169 } else {
7170 if (((insn >> 12) & 0xf) != 0xf)
7171 goto illegal_op;
7172 if (((insn >> 16) & 0xf) == 0) {
7173 gen_nop_hint(s, insn & 0xff);
7174 } else {
7175 /* CPSR = immediate */
7176 val = insn & 0xff;
7177 shift = ((insn >> 8) & 0xf) * 2;
7178 if (shift)
7179 val = (val >> shift) | (val << (32 - shift));
7180 i = ((insn & (1 << 22)) != 0);
7181 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
7182 goto illegal_op;
7185 } else if ((insn & 0x0f900000) == 0x01000000
7186 && (insn & 0x00000090) != 0x00000090) {
7187 /* miscellaneous instructions */
7188 op1 = (insn >> 21) & 3;
7189 sh = (insn >> 4) & 0xf;
7190 rm = insn & 0xf;
7191 switch (sh) {
7192 case 0x0: /* move program status register */
7193 if (op1 & 1) {
7194 /* PSR = reg */
7195 tmp = load_reg(s, rm);
7196 i = ((op1 & 2) != 0);
7197 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
7198 goto illegal_op;
7199 } else {
7200 /* reg = PSR */
7201 rd = (insn >> 12) & 0xf;
7202 if (op1 & 2) {
7203 if (IS_USER(s))
7204 goto illegal_op;
7205 tmp = load_cpu_field(spsr);
7206 } else {
7207 tmp = tcg_temp_new_i32();
7208 gen_helper_cpsr_read(tmp, cpu_env);
7210 store_reg(s, rd, tmp);
7212 break;
7213 case 0x1:
7214 if (op1 == 1) {
7215 /* branch/exchange thumb (bx). */
7216 ARCH(4T);
7217 tmp = load_reg(s, rm);
7218 gen_bx(s, tmp);
7219 } else if (op1 == 3) {
7220 /* clz */
7221 ARCH(5);
7222 rd = (insn >> 12) & 0xf;
7223 tmp = load_reg(s, rm);
7224 gen_helper_clz(tmp, tmp);
7225 store_reg(s, rd, tmp);
7226 } else {
7227 goto illegal_op;
7229 break;
7230 case 0x2:
7231 if (op1 == 1) {
7232 ARCH(5J); /* bxj */
7233 /* Trivial implementation equivalent to bx. */
7234 tmp = load_reg(s, rm);
7235 gen_bx(s, tmp);
7236 } else {
7237 goto illegal_op;
7239 break;
7240 case 0x3:
7241 if (op1 != 1)
7242 goto illegal_op;
7244 ARCH(5);
7245 /* branch link/exchange thumb (blx) */
7246 tmp = load_reg(s, rm);
7247 tmp2 = tcg_temp_new_i32();
7248 tcg_gen_movi_i32(tmp2, s->pc);
7249 store_reg(s, 14, tmp2);
7250 gen_bx(s, tmp);
7251 break;
7252 case 0x5: /* saturating add/subtract */
7253 ARCH(5TE);
7254 rd = (insn >> 12) & 0xf;
7255 rn = (insn >> 16) & 0xf;
7256 tmp = load_reg(s, rm);
7257 tmp2 = load_reg(s, rn);
7258 if (op1 & 2)
7259 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
7260 if (op1 & 1)
7261 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
7262 else
7263 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7264 tcg_temp_free_i32(tmp2);
7265 store_reg(s, rd, tmp);
7266 break;
7267 case 7:
7268 /* SMC instruction (op1 == 3)
7269 and undefined instructions (op1 == 0 || op1 == 2)
7270 will trap */
7271 if (op1 != 1) {
7272 goto illegal_op;
7274 /* bkpt */
7275 ARCH(5);
7276 gen_exception_insn(s, 4, EXCP_BKPT);
7277 break;
7278 case 0x8: /* signed multiply */
7279 case 0xa:
7280 case 0xc:
7281 case 0xe:
7282 ARCH(5TE);
7283 rs = (insn >> 8) & 0xf;
7284 rn = (insn >> 12) & 0xf;
7285 rd = (insn >> 16) & 0xf;
7286 if (op1 == 1) {
7287 /* (32 * 16) >> 16 */
7288 tmp = load_reg(s, rm);
7289 tmp2 = load_reg(s, rs);
7290 if (sh & 4)
7291 tcg_gen_sari_i32(tmp2, tmp2, 16);
7292 else
7293 gen_sxth(tmp2);
7294 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7295 tcg_gen_shri_i64(tmp64, tmp64, 16);
7296 tmp = tcg_temp_new_i32();
7297 tcg_gen_trunc_i64_i32(tmp, tmp64);
7298 tcg_temp_free_i64(tmp64);
7299 if ((sh & 2) == 0) {
7300 tmp2 = load_reg(s, rn);
7301 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7302 tcg_temp_free_i32(tmp2);
7304 store_reg(s, rd, tmp);
7305 } else {
7306 /* 16 * 16 */
7307 tmp = load_reg(s, rm);
7308 tmp2 = load_reg(s, rs);
7309 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7310 tcg_temp_free_i32(tmp2);
7311 if (op1 == 2) {
7312 tmp64 = tcg_temp_new_i64();
7313 tcg_gen_ext_i32_i64(tmp64, tmp);
7314 tcg_temp_free_i32(tmp);
7315 gen_addq(s, tmp64, rn, rd);
7316 gen_storeq_reg(s, rn, rd, tmp64);
7317 tcg_temp_free_i64(tmp64);
7318 } else {
7319 if (op1 == 0) {
7320 tmp2 = load_reg(s, rn);
7321 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7322 tcg_temp_free_i32(tmp2);
7324 store_reg(s, rd, tmp);
7327 break;
7328 default:
7329 goto illegal_op;
7331 } else if (((insn & 0x0e000000) == 0 &&
7332 (insn & 0x00000090) != 0x90) ||
7333 ((insn & 0x0e000000) == (1 << 25))) {
7334 int set_cc, logic_cc, shiftop;
7336 op1 = (insn >> 21) & 0xf;
7337 set_cc = (insn >> 20) & 1;
7338 logic_cc = table_logic_cc[op1] & set_cc;
7340 /* data processing instruction */
7341 if (insn & (1 << 25)) {
7342 /* immediate operand */
7343 val = insn & 0xff;
7344 shift = ((insn >> 8) & 0xf) * 2;
7345 if (shift) {
7346 val = (val >> shift) | (val << (32 - shift));
7348 tmp2 = tcg_temp_new_i32();
7349 tcg_gen_movi_i32(tmp2, val);
7350 if (logic_cc && shift) {
7351 gen_set_CF_bit31(tmp2);
7353 } else {
7354 /* register */
7355 rm = (insn) & 0xf;
7356 tmp2 = load_reg(s, rm);
7357 shiftop = (insn >> 5) & 3;
7358 if (!(insn & (1 << 4))) {
7359 shift = (insn >> 7) & 0x1f;
7360 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7361 } else {
7362 rs = (insn >> 8) & 0xf;
7363 tmp = load_reg(s, rs);
7364 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7367 if (op1 != 0x0f && op1 != 0x0d) {
7368 rn = (insn >> 16) & 0xf;
7369 tmp = load_reg(s, rn);
7370 } else {
7371 TCGV_UNUSED_I32(tmp);
7373 rd = (insn >> 12) & 0xf;
7374 switch(op1) {
7375 case 0x00:
7376 tcg_gen_and_i32(tmp, tmp, tmp2);
7377 if (logic_cc) {
7378 gen_logic_CC(tmp);
7380 store_reg_bx(env, s, rd, tmp);
7381 break;
7382 case 0x01:
7383 tcg_gen_xor_i32(tmp, tmp, tmp2);
7384 if (logic_cc) {
7385 gen_logic_CC(tmp);
7387 store_reg_bx(env, s, rd, tmp);
7388 break;
7389 case 0x02:
7390 if (set_cc && rd == 15) {
7391 /* SUBS r15, ... is used for exception return. */
7392 if (IS_USER(s)) {
7393 goto illegal_op;
7395 gen_sub_CC(tmp, tmp, tmp2);
7396 gen_exception_return(s, tmp);
7397 } else {
7398 if (set_cc) {
7399 gen_sub_CC(tmp, tmp, tmp2);
7400 } else {
7401 tcg_gen_sub_i32(tmp, tmp, tmp2);
7403 store_reg_bx(env, s, rd, tmp);
7405 break;
7406 case 0x03:
7407 if (set_cc) {
7408 gen_sub_CC(tmp, tmp2, tmp);
7409 } else {
7410 tcg_gen_sub_i32(tmp, tmp2, tmp);
7412 store_reg_bx(env, s, rd, tmp);
7413 break;
7414 case 0x04:
7415 if (set_cc) {
7416 gen_add_CC(tmp, tmp, tmp2);
7417 } else {
7418 tcg_gen_add_i32(tmp, tmp, tmp2);
7420 store_reg_bx(env, s, rd, tmp);
7421 break;
7422 case 0x05:
7423 if (set_cc) {
7424 gen_adc_CC(tmp, tmp, tmp2);
7425 } else {
7426 gen_add_carry(tmp, tmp, tmp2);
7428 store_reg_bx(env, s, rd, tmp);
7429 break;
7430 case 0x06:
7431 if (set_cc) {
7432 gen_sbc_CC(tmp, tmp, tmp2);
7433 } else {
7434 gen_sub_carry(tmp, tmp, tmp2);
7436 store_reg_bx(env, s, rd, tmp);
7437 break;
7438 case 0x07:
7439 if (set_cc) {
7440 gen_sbc_CC(tmp, tmp2, tmp);
7441 } else {
7442 gen_sub_carry(tmp, tmp2, tmp);
7444 store_reg_bx(env, s, rd, tmp);
7445 break;
7446 case 0x08:
7447 if (set_cc) {
7448 tcg_gen_and_i32(tmp, tmp, tmp2);
7449 gen_logic_CC(tmp);
7451 tcg_temp_free_i32(tmp);
7452 break;
7453 case 0x09:
7454 if (set_cc) {
7455 tcg_gen_xor_i32(tmp, tmp, tmp2);
7456 gen_logic_CC(tmp);
7458 tcg_temp_free_i32(tmp);
7459 break;
7460 case 0x0a:
7461 if (set_cc) {
7462 gen_sub_CC(tmp, tmp, tmp2);
7464 tcg_temp_free_i32(tmp);
7465 break;
7466 case 0x0b:
7467 if (set_cc) {
7468 gen_add_CC(tmp, tmp, tmp2);
7470 tcg_temp_free_i32(tmp);
7471 break;
7472 case 0x0c:
7473 tcg_gen_or_i32(tmp, tmp, tmp2);
7474 if (logic_cc) {
7475 gen_logic_CC(tmp);
7477 store_reg_bx(env, s, rd, tmp);
7478 break;
7479 case 0x0d:
7480 if (logic_cc && rd == 15) {
7481 /* MOVS r15, ... is used for exception return. */
7482 if (IS_USER(s)) {
7483 goto illegal_op;
7485 gen_exception_return(s, tmp2);
7486 } else {
7487 if (logic_cc) {
7488 gen_logic_CC(tmp2);
7490 store_reg_bx(env, s, rd, tmp2);
7492 break;
7493 case 0x0e:
7494 tcg_gen_andc_i32(tmp, tmp, tmp2);
7495 if (logic_cc) {
7496 gen_logic_CC(tmp);
7498 store_reg_bx(env, s, rd, tmp);
7499 break;
7500 default:
7501 case 0x0f:
7502 tcg_gen_not_i32(tmp2, tmp2);
7503 if (logic_cc) {
7504 gen_logic_CC(tmp2);
7506 store_reg_bx(env, s, rd, tmp2);
7507 break;
7509 if (op1 != 0x0f && op1 != 0x0d) {
7510 tcg_temp_free_i32(tmp2);
7512 } else {
7513 /* other instructions */
7514 op1 = (insn >> 24) & 0xf;
7515 switch(op1) {
7516 case 0x0:
7517 case 0x1:
7518 /* multiplies, extra load/stores */
7519 sh = (insn >> 5) & 3;
7520 if (sh == 0) {
7521 if (op1 == 0x0) {
7522 rd = (insn >> 16) & 0xf;
7523 rn = (insn >> 12) & 0xf;
7524 rs = (insn >> 8) & 0xf;
7525 rm = (insn) & 0xf;
7526 op1 = (insn >> 20) & 0xf;
7527 switch (op1) {
7528 case 0: case 1: case 2: case 3: case 6:
7529 /* 32 bit mul */
7530 tmp = load_reg(s, rs);
7531 tmp2 = load_reg(s, rm);
7532 tcg_gen_mul_i32(tmp, tmp, tmp2);
7533 tcg_temp_free_i32(tmp2);
7534 if (insn & (1 << 22)) {
7535 /* Subtract (mls) */
7536 ARCH(6T2);
7537 tmp2 = load_reg(s, rn);
7538 tcg_gen_sub_i32(tmp, tmp2, tmp);
7539 tcg_temp_free_i32(tmp2);
7540 } else if (insn & (1 << 21)) {
7541 /* Add */
7542 tmp2 = load_reg(s, rn);
7543 tcg_gen_add_i32(tmp, tmp, tmp2);
7544 tcg_temp_free_i32(tmp2);
7546 if (insn & (1 << 20))
7547 gen_logic_CC(tmp);
7548 store_reg(s, rd, tmp);
7549 break;
7550 case 4:
7551 /* 64 bit mul double accumulate (UMAAL) */
7552 ARCH(6);
7553 tmp = load_reg(s, rs);
7554 tmp2 = load_reg(s, rm);
7555 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7556 gen_addq_lo(s, tmp64, rn);
7557 gen_addq_lo(s, tmp64, rd);
7558 gen_storeq_reg(s, rn, rd, tmp64);
7559 tcg_temp_free_i64(tmp64);
7560 break;
7561 case 8: case 9: case 10: case 11:
7562 case 12: case 13: case 14: case 15:
7563 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7564 tmp = load_reg(s, rs);
7565 tmp2 = load_reg(s, rm);
7566 if (insn & (1 << 22)) {
7567 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
7568 } else {
7569 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
7571 if (insn & (1 << 21)) { /* mult accumulate */
7572 TCGv_i32 al = load_reg(s, rn);
7573 TCGv_i32 ah = load_reg(s, rd);
7574 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
7575 tcg_temp_free_i32(al);
7576 tcg_temp_free_i32(ah);
7578 if (insn & (1 << 20)) {
7579 gen_logicq_cc(tmp, tmp2);
7581 store_reg(s, rn, tmp);
7582 store_reg(s, rd, tmp2);
7583 break;
7584 default:
7585 goto illegal_op;
7587 } else {
7588 rn = (insn >> 16) & 0xf;
7589 rd = (insn >> 12) & 0xf;
7590 if (insn & (1 << 23)) {
7591 /* load/store exclusive */
7592 int op2 = (insn >> 8) & 3;
7593 op1 = (insn >> 21) & 0x3;
7595 switch (op2) {
7596 case 0: /* lda/stl */
7597 if (op1 == 1) {
7598 goto illegal_op;
7600 ARCH(8);
7601 break;
7602 case 1: /* reserved */
7603 goto illegal_op;
7604 case 2: /* ldaex/stlex */
7605 ARCH(8);
7606 break;
7607 case 3: /* ldrex/strex */
7608 if (op1) {
7609 ARCH(6K);
7610 } else {
7611 ARCH(6);
7613 break;
7616 addr = tcg_temp_local_new_i32();
7617 load_reg_var(s, addr, rn);
7619 /* Since the emulation does not have barriers,
7620 the acquire/release semantics need no special
7621 handling */
7622 if (op2 == 0) {
7623 if (insn & (1 << 20)) {
7624 tmp = tcg_temp_new_i32();
7625 switch (op1) {
7626 case 0: /* lda */
7627 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7628 break;
7629 case 2: /* ldab */
7630 gen_aa32_ld8u(tmp, addr, IS_USER(s));
7631 break;
7632 case 3: /* ldah */
7633 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7634 break;
7635 default:
7636 abort();
7638 store_reg(s, rd, tmp);
7639 } else {
7640 rm = insn & 0xf;
7641 tmp = load_reg(s, rm);
7642 switch (op1) {
7643 case 0: /* stl */
7644 gen_aa32_st32(tmp, addr, IS_USER(s));
7645 break;
7646 case 2: /* stlb */
7647 gen_aa32_st8(tmp, addr, IS_USER(s));
7648 break;
7649 case 3: /* stlh */
7650 gen_aa32_st16(tmp, addr, IS_USER(s));
7651 break;
7652 default:
7653 abort();
7655 tcg_temp_free_i32(tmp);
7657 } else if (insn & (1 << 20)) {
7658 switch (op1) {
7659 case 0: /* ldrex */
7660 gen_load_exclusive(s, rd, 15, addr, 2);
7661 break;
7662 case 1: /* ldrexd */
7663 gen_load_exclusive(s, rd, rd + 1, addr, 3);
7664 break;
7665 case 2: /* ldrexb */
7666 gen_load_exclusive(s, rd, 15, addr, 0);
7667 break;
7668 case 3: /* ldrexh */
7669 gen_load_exclusive(s, rd, 15, addr, 1);
7670 break;
7671 default:
7672 abort();
7674 } else {
7675 rm = insn & 0xf;
7676 switch (op1) {
7677 case 0: /* strex */
7678 gen_store_exclusive(s, rd, rm, 15, addr, 2);
7679 break;
7680 case 1: /* strexd */
7681 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
7682 break;
7683 case 2: /* strexb */
7684 gen_store_exclusive(s, rd, rm, 15, addr, 0);
7685 break;
7686 case 3: /* strexh */
7687 gen_store_exclusive(s, rd, rm, 15, addr, 1);
7688 break;
7689 default:
7690 abort();
7693 tcg_temp_free_i32(addr);
7694 } else {
7695 /* SWP instruction */
7696 rm = (insn) & 0xf;
7698 /* ??? This is not really atomic. However we know
7699 we never have multiple CPUs running in parallel,
7700 so it is good enough. */
7701 addr = load_reg(s, rn);
7702 tmp = load_reg(s, rm);
7703 tmp2 = tcg_temp_new_i32();
7704 if (insn & (1 << 22)) {
7705 gen_aa32_ld8u(tmp2, addr, IS_USER(s));
7706 gen_aa32_st8(tmp, addr, IS_USER(s));
7707 } else {
7708 gen_aa32_ld32u(tmp2, addr, IS_USER(s));
7709 gen_aa32_st32(tmp, addr, IS_USER(s));
7711 tcg_temp_free_i32(tmp);
7712 tcg_temp_free_i32(addr);
7713 store_reg(s, rd, tmp2);
7716 } else {
7717 int address_offset;
7718 int load;
7719 /* Misc load/store */
7720 rn = (insn >> 16) & 0xf;
7721 rd = (insn >> 12) & 0xf;
7722 addr = load_reg(s, rn);
7723 if (insn & (1 << 24))
7724 gen_add_datah_offset(s, insn, 0, addr);
7725 address_offset = 0;
7726 if (insn & (1 << 20)) {
7727 /* load */
7728 tmp = tcg_temp_new_i32();
7729 switch(sh) {
7730 case 1:
7731 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7732 break;
7733 case 2:
7734 gen_aa32_ld8s(tmp, addr, IS_USER(s));
7735 break;
7736 default:
7737 case 3:
7738 gen_aa32_ld16s(tmp, addr, IS_USER(s));
7739 break;
7741 load = 1;
7742 } else if (sh & 2) {
7743 ARCH(5TE);
7744 /* doubleword */
7745 if (sh & 1) {
7746 /* store */
7747 tmp = load_reg(s, rd);
7748 gen_aa32_st32(tmp, addr, IS_USER(s));
7749 tcg_temp_free_i32(tmp);
7750 tcg_gen_addi_i32(addr, addr, 4);
7751 tmp = load_reg(s, rd + 1);
7752 gen_aa32_st32(tmp, addr, IS_USER(s));
7753 tcg_temp_free_i32(tmp);
7754 load = 0;
7755 } else {
7756 /* load */
7757 tmp = tcg_temp_new_i32();
7758 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7759 store_reg(s, rd, tmp);
7760 tcg_gen_addi_i32(addr, addr, 4);
7761 tmp = tcg_temp_new_i32();
7762 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7763 rd++;
7764 load = 1;
7766 address_offset = -4;
7767 } else {
7768 /* store */
7769 tmp = load_reg(s, rd);
7770 gen_aa32_st16(tmp, addr, IS_USER(s));
7771 tcg_temp_free_i32(tmp);
7772 load = 0;
7774 /* Perform base writeback before the loaded value to
7775 ensure correct behavior with overlapping index registers.
7776 ldrd with base writeback is is undefined if the
7777 destination and index registers overlap. */
7778 if (!(insn & (1 << 24))) {
7779 gen_add_datah_offset(s, insn, address_offset, addr);
7780 store_reg(s, rn, addr);
7781 } else if (insn & (1 << 21)) {
7782 if (address_offset)
7783 tcg_gen_addi_i32(addr, addr, address_offset);
7784 store_reg(s, rn, addr);
7785 } else {
7786 tcg_temp_free_i32(addr);
7788 if (load) {
7789 /* Complete the load. */
7790 store_reg(s, rd, tmp);
7793 break;
7794 case 0x4:
7795 case 0x5:
7796 goto do_ldst;
7797 case 0x6:
7798 case 0x7:
7799 if (insn & (1 << 4)) {
7800 ARCH(6);
7801 /* Armv6 Media instructions. */
7802 rm = insn & 0xf;
7803 rn = (insn >> 16) & 0xf;
7804 rd = (insn >> 12) & 0xf;
7805 rs = (insn >> 8) & 0xf;
7806 switch ((insn >> 23) & 3) {
7807 case 0: /* Parallel add/subtract. */
7808 op1 = (insn >> 20) & 7;
7809 tmp = load_reg(s, rn);
7810 tmp2 = load_reg(s, rm);
7811 sh = (insn >> 5) & 7;
7812 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
7813 goto illegal_op;
7814 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7815 tcg_temp_free_i32(tmp2);
7816 store_reg(s, rd, tmp);
7817 break;
7818 case 1:
7819 if ((insn & 0x00700020) == 0) {
7820 /* Halfword pack. */
7821 tmp = load_reg(s, rn);
7822 tmp2 = load_reg(s, rm);
7823 shift = (insn >> 7) & 0x1f;
7824 if (insn & (1 << 6)) {
7825 /* pkhtb */
7826 if (shift == 0)
7827 shift = 31;
7828 tcg_gen_sari_i32(tmp2, tmp2, shift);
7829 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7830 tcg_gen_ext16u_i32(tmp2, tmp2);
7831 } else {
7832 /* pkhbt */
7833 if (shift)
7834 tcg_gen_shli_i32(tmp2, tmp2, shift);
7835 tcg_gen_ext16u_i32(tmp, tmp);
7836 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7838 tcg_gen_or_i32(tmp, tmp, tmp2);
7839 tcg_temp_free_i32(tmp2);
7840 store_reg(s, rd, tmp);
7841 } else if ((insn & 0x00200020) == 0x00200000) {
7842 /* [us]sat */
7843 tmp = load_reg(s, rm);
7844 shift = (insn >> 7) & 0x1f;
7845 if (insn & (1 << 6)) {
7846 if (shift == 0)
7847 shift = 31;
7848 tcg_gen_sari_i32(tmp, tmp, shift);
7849 } else {
7850 tcg_gen_shli_i32(tmp, tmp, shift);
7852 sh = (insn >> 16) & 0x1f;
7853 tmp2 = tcg_const_i32(sh);
7854 if (insn & (1 << 22))
7855 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
7856 else
7857 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
7858 tcg_temp_free_i32(tmp2);
7859 store_reg(s, rd, tmp);
7860 } else if ((insn & 0x00300fe0) == 0x00200f20) {
7861 /* [us]sat16 */
7862 tmp = load_reg(s, rm);
7863 sh = (insn >> 16) & 0x1f;
7864 tmp2 = tcg_const_i32(sh);
7865 if (insn & (1 << 22))
7866 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
7867 else
7868 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
7869 tcg_temp_free_i32(tmp2);
7870 store_reg(s, rd, tmp);
7871 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
7872 /* Select bytes. */
7873 tmp = load_reg(s, rn);
7874 tmp2 = load_reg(s, rm);
7875 tmp3 = tcg_temp_new_i32();
7876 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
7877 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7878 tcg_temp_free_i32(tmp3);
7879 tcg_temp_free_i32(tmp2);
7880 store_reg(s, rd, tmp);
7881 } else if ((insn & 0x000003e0) == 0x00000060) {
7882 tmp = load_reg(s, rm);
7883 shift = (insn >> 10) & 3;
7884 /* ??? In many cases it's not necessary to do a
7885 rotate, a shift is sufficient. */
7886 if (shift != 0)
7887 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7888 op1 = (insn >> 20) & 7;
7889 switch (op1) {
7890 case 0: gen_sxtb16(tmp); break;
7891 case 2: gen_sxtb(tmp); break;
7892 case 3: gen_sxth(tmp); break;
7893 case 4: gen_uxtb16(tmp); break;
7894 case 6: gen_uxtb(tmp); break;
7895 case 7: gen_uxth(tmp); break;
7896 default: goto illegal_op;
7898 if (rn != 15) {
7899 tmp2 = load_reg(s, rn);
7900 if ((op1 & 3) == 0) {
7901 gen_add16(tmp, tmp2);
7902 } else {
7903 tcg_gen_add_i32(tmp, tmp, tmp2);
7904 tcg_temp_free_i32(tmp2);
7907 store_reg(s, rd, tmp);
7908 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7909 /* rev */
7910 tmp = load_reg(s, rm);
7911 if (insn & (1 << 22)) {
7912 if (insn & (1 << 7)) {
7913 gen_revsh(tmp);
7914 } else {
7915 ARCH(6T2);
7916 gen_helper_rbit(tmp, tmp);
7918 } else {
7919 if (insn & (1 << 7))
7920 gen_rev16(tmp);
7921 else
7922 tcg_gen_bswap32_i32(tmp, tmp);
7924 store_reg(s, rd, tmp);
7925 } else {
7926 goto illegal_op;
7928 break;
7929 case 2: /* Multiplies (Type 3). */
7930 switch ((insn >> 20) & 0x7) {
7931 case 5:
7932 if (((insn >> 6) ^ (insn >> 7)) & 1) {
7933 /* op2 not 00x or 11x : UNDEF */
7934 goto illegal_op;
7936 /* Signed multiply most significant [accumulate].
7937 (SMMUL, SMMLA, SMMLS) */
7938 tmp = load_reg(s, rm);
7939 tmp2 = load_reg(s, rs);
7940 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7942 if (rd != 15) {
7943 tmp = load_reg(s, rd);
7944 if (insn & (1 << 6)) {
7945 tmp64 = gen_subq_msw(tmp64, tmp);
7946 } else {
7947 tmp64 = gen_addq_msw(tmp64, tmp);
7950 if (insn & (1 << 5)) {
7951 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7953 tcg_gen_shri_i64(tmp64, tmp64, 32);
7954 tmp = tcg_temp_new_i32();
7955 tcg_gen_trunc_i64_i32(tmp, tmp64);
7956 tcg_temp_free_i64(tmp64);
7957 store_reg(s, rn, tmp);
7958 break;
7959 case 0:
7960 case 4:
7961 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
7962 if (insn & (1 << 7)) {
7963 goto illegal_op;
7965 tmp = load_reg(s, rm);
7966 tmp2 = load_reg(s, rs);
7967 if (insn & (1 << 5))
7968 gen_swap_half(tmp2);
7969 gen_smul_dual(tmp, tmp2);
7970 if (insn & (1 << 6)) {
7971 /* This subtraction cannot overflow. */
7972 tcg_gen_sub_i32(tmp, tmp, tmp2);
7973 } else {
7974 /* This addition cannot overflow 32 bits;
7975 * however it may overflow considered as a signed
7976 * operation, in which case we must set the Q flag.
7978 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7980 tcg_temp_free_i32(tmp2);
7981 if (insn & (1 << 22)) {
7982 /* smlald, smlsld */
7983 tmp64 = tcg_temp_new_i64();
7984 tcg_gen_ext_i32_i64(tmp64, tmp);
7985 tcg_temp_free_i32(tmp);
7986 gen_addq(s, tmp64, rd, rn);
7987 gen_storeq_reg(s, rd, rn, tmp64);
7988 tcg_temp_free_i64(tmp64);
7989 } else {
7990 /* smuad, smusd, smlad, smlsd */
7991 if (rd != 15)
7993 tmp2 = load_reg(s, rd);
7994 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7995 tcg_temp_free_i32(tmp2);
7997 store_reg(s, rn, tmp);
7999 break;
8000 case 1:
8001 case 3:
8002 /* SDIV, UDIV */
8003 if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
8004 goto illegal_op;
8006 if (((insn >> 5) & 7) || (rd != 15)) {
8007 goto illegal_op;
8009 tmp = load_reg(s, rm);
8010 tmp2 = load_reg(s, rs);
8011 if (insn & (1 << 21)) {
8012 gen_helper_udiv(tmp, tmp, tmp2);
8013 } else {
8014 gen_helper_sdiv(tmp, tmp, tmp2);
8016 tcg_temp_free_i32(tmp2);
8017 store_reg(s, rn, tmp);
8018 break;
8019 default:
8020 goto illegal_op;
8022 break;
8023 case 3:
8024 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8025 switch (op1) {
8026 case 0: /* Unsigned sum of absolute differences. */
8027 ARCH(6);
8028 tmp = load_reg(s, rm);
8029 tmp2 = load_reg(s, rs);
8030 gen_helper_usad8(tmp, tmp, tmp2);
8031 tcg_temp_free_i32(tmp2);
8032 if (rd != 15) {
8033 tmp2 = load_reg(s, rd);
8034 tcg_gen_add_i32(tmp, tmp, tmp2);
8035 tcg_temp_free_i32(tmp2);
8037 store_reg(s, rn, tmp);
8038 break;
8039 case 0x20: case 0x24: case 0x28: case 0x2c:
8040 /* Bitfield insert/clear. */
8041 ARCH(6T2);
8042 shift = (insn >> 7) & 0x1f;
8043 i = (insn >> 16) & 0x1f;
8044 i = i + 1 - shift;
8045 if (rm == 15) {
8046 tmp = tcg_temp_new_i32();
8047 tcg_gen_movi_i32(tmp, 0);
8048 } else {
8049 tmp = load_reg(s, rm);
8051 if (i != 32) {
8052 tmp2 = load_reg(s, rd);
8053 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
8054 tcg_temp_free_i32(tmp2);
8056 store_reg(s, rd, tmp);
8057 break;
8058 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8059 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
8060 ARCH(6T2);
8061 tmp = load_reg(s, rm);
8062 shift = (insn >> 7) & 0x1f;
8063 i = ((insn >> 16) & 0x1f) + 1;
8064 if (shift + i > 32)
8065 goto illegal_op;
8066 if (i < 32) {
8067 if (op1 & 0x20) {
8068 gen_ubfx(tmp, shift, (1u << i) - 1);
8069 } else {
8070 gen_sbfx(tmp, shift, i);
8073 store_reg(s, rd, tmp);
8074 break;
8075 default:
8076 goto illegal_op;
8078 break;
8080 break;
8082 do_ldst:
8083 /* Check for undefined extension instructions
8084 * per the ARM Bible IE:
8085 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
8087 sh = (0xf << 20) | (0xf << 4);
8088 if (op1 == 0x7 && ((insn & sh) == sh))
8090 goto illegal_op;
8092 /* load/store byte/word */
8093 rn = (insn >> 16) & 0xf;
8094 rd = (insn >> 12) & 0xf;
8095 tmp2 = load_reg(s, rn);
8096 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
8097 if (insn & (1 << 24))
8098 gen_add_data_offset(s, insn, tmp2);
8099 if (insn & (1 << 20)) {
8100 /* load */
8101 tmp = tcg_temp_new_i32();
8102 if (insn & (1 << 22)) {
8103 gen_aa32_ld8u(tmp, tmp2, i);
8104 } else {
8105 gen_aa32_ld32u(tmp, tmp2, i);
8107 } else {
8108 /* store */
8109 tmp = load_reg(s, rd);
8110 if (insn & (1 << 22)) {
8111 gen_aa32_st8(tmp, tmp2, i);
8112 } else {
8113 gen_aa32_st32(tmp, tmp2, i);
8115 tcg_temp_free_i32(tmp);
8117 if (!(insn & (1 << 24))) {
8118 gen_add_data_offset(s, insn, tmp2);
8119 store_reg(s, rn, tmp2);
8120 } else if (insn & (1 << 21)) {
8121 store_reg(s, rn, tmp2);
8122 } else {
8123 tcg_temp_free_i32(tmp2);
8125 if (insn & (1 << 20)) {
8126 /* Complete the load. */
8127 store_reg_from_load(env, s, rd, tmp);
8129 break;
8130 case 0x08:
8131 case 0x09:
8133 int j, n, user, loaded_base;
8134 TCGv_i32 loaded_var;
8135 /* load/store multiple words */
8136 /* XXX: store correct base if write back */
8137 user = 0;
8138 if (insn & (1 << 22)) {
8139 if (IS_USER(s))
8140 goto illegal_op; /* only usable in supervisor mode */
8142 if ((insn & (1 << 15)) == 0)
8143 user = 1;
8145 rn = (insn >> 16) & 0xf;
8146 addr = load_reg(s, rn);
8148 /* compute total size */
8149 loaded_base = 0;
8150 TCGV_UNUSED_I32(loaded_var);
8151 n = 0;
8152 for(i=0;i<16;i++) {
8153 if (insn & (1 << i))
8154 n++;
8156 /* XXX: test invalid n == 0 case ? */
8157 if (insn & (1 << 23)) {
8158 if (insn & (1 << 24)) {
8159 /* pre increment */
8160 tcg_gen_addi_i32(addr, addr, 4);
8161 } else {
8162 /* post increment */
8164 } else {
8165 if (insn & (1 << 24)) {
8166 /* pre decrement */
8167 tcg_gen_addi_i32(addr, addr, -(n * 4));
8168 } else {
8169 /* post decrement */
8170 if (n != 1)
8171 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8174 j = 0;
8175 for(i=0;i<16;i++) {
8176 if (insn & (1 << i)) {
8177 if (insn & (1 << 20)) {
8178 /* load */
8179 tmp = tcg_temp_new_i32();
8180 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8181 if (user) {
8182 tmp2 = tcg_const_i32(i);
8183 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
8184 tcg_temp_free_i32(tmp2);
8185 tcg_temp_free_i32(tmp);
8186 } else if (i == rn) {
8187 loaded_var = tmp;
8188 loaded_base = 1;
8189 } else {
8190 store_reg_from_load(env, s, i, tmp);
8192 } else {
8193 /* store */
8194 if (i == 15) {
8195 /* special case: r15 = PC + 8 */
8196 val = (long)s->pc + 4;
8197 tmp = tcg_temp_new_i32();
8198 tcg_gen_movi_i32(tmp, val);
8199 } else if (user) {
8200 tmp = tcg_temp_new_i32();
8201 tmp2 = tcg_const_i32(i);
8202 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
8203 tcg_temp_free_i32(tmp2);
8204 } else {
8205 tmp = load_reg(s, i);
8207 gen_aa32_st32(tmp, addr, IS_USER(s));
8208 tcg_temp_free_i32(tmp);
8210 j++;
8211 /* no need to add after the last transfer */
8212 if (j != n)
8213 tcg_gen_addi_i32(addr, addr, 4);
8216 if (insn & (1 << 21)) {
8217 /* write back */
8218 if (insn & (1 << 23)) {
8219 if (insn & (1 << 24)) {
8220 /* pre increment */
8221 } else {
8222 /* post increment */
8223 tcg_gen_addi_i32(addr, addr, 4);
8225 } else {
8226 if (insn & (1 << 24)) {
8227 /* pre decrement */
8228 if (n != 1)
8229 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8230 } else {
8231 /* post decrement */
8232 tcg_gen_addi_i32(addr, addr, -(n * 4));
8235 store_reg(s, rn, addr);
8236 } else {
8237 tcg_temp_free_i32(addr);
8239 if (loaded_base) {
8240 store_reg(s, rn, loaded_var);
8242 if ((insn & (1 << 22)) && !user) {
8243 /* Restore CPSR from SPSR. */
8244 tmp = load_cpu_field(spsr);
8245 gen_set_cpsr(tmp, 0xffffffff);
8246 tcg_temp_free_i32(tmp);
8247 s->is_jmp = DISAS_UPDATE;
8250 break;
8251 case 0xa:
8252 case 0xb:
8254 int32_t offset;
8256 /* branch (and link) */
8257 val = (int32_t)s->pc;
8258 if (insn & (1 << 24)) {
8259 tmp = tcg_temp_new_i32();
8260 tcg_gen_movi_i32(tmp, val);
8261 store_reg(s, 14, tmp);
8263 offset = sextract32(insn << 2, 0, 26);
8264 val += offset + 4;
8265 gen_jmp(s, val);
8267 break;
8268 case 0xc:
8269 case 0xd:
8270 case 0xe:
8271 if (((insn >> 8) & 0xe) == 10) {
8272 /* VFP. */
8273 if (disas_vfp_insn(env, s, insn)) {
8274 goto illegal_op;
8276 } else if (disas_coproc_insn(env, s, insn)) {
8277 /* Coprocessor. */
8278 goto illegal_op;
8280 break;
8281 case 0xf:
8282 /* swi */
8283 gen_set_pc_im(s, s->pc);
8284 s->is_jmp = DISAS_SWI;
8285 break;
8286 default:
8287 illegal_op:
8288 gen_exception_insn(s, 4, EXCP_UDEF);
8289 break;
8294 /* Return true if this is a Thumb-2 logical op. */
8295 static int
8296 thumb2_logic_op(int op)
8298 return (op < 8);
8301 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
8302 then set condition code flags based on the result of the operation.
8303 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
8304 to the high bit of T1.
8305 Returns zero if the opcode is valid. */
8307 static int
8308 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
8309 TCGv_i32 t0, TCGv_i32 t1)
8311 int logic_cc;
8313 logic_cc = 0;
8314 switch (op) {
8315 case 0: /* and */
8316 tcg_gen_and_i32(t0, t0, t1);
8317 logic_cc = conds;
8318 break;
8319 case 1: /* bic */
8320 tcg_gen_andc_i32(t0, t0, t1);
8321 logic_cc = conds;
8322 break;
8323 case 2: /* orr */
8324 tcg_gen_or_i32(t0, t0, t1);
8325 logic_cc = conds;
8326 break;
8327 case 3: /* orn */
8328 tcg_gen_orc_i32(t0, t0, t1);
8329 logic_cc = conds;
8330 break;
8331 case 4: /* eor */
8332 tcg_gen_xor_i32(t0, t0, t1);
8333 logic_cc = conds;
8334 break;
8335 case 8: /* add */
8336 if (conds)
8337 gen_add_CC(t0, t0, t1);
8338 else
8339 tcg_gen_add_i32(t0, t0, t1);
8340 break;
8341 case 10: /* adc */
8342 if (conds)
8343 gen_adc_CC(t0, t0, t1);
8344 else
8345 gen_adc(t0, t1);
8346 break;
8347 case 11: /* sbc */
8348 if (conds) {
8349 gen_sbc_CC(t0, t0, t1);
8350 } else {
8351 gen_sub_carry(t0, t0, t1);
8353 break;
8354 case 13: /* sub */
8355 if (conds)
8356 gen_sub_CC(t0, t0, t1);
8357 else
8358 tcg_gen_sub_i32(t0, t0, t1);
8359 break;
8360 case 14: /* rsb */
8361 if (conds)
8362 gen_sub_CC(t0, t1, t0);
8363 else
8364 tcg_gen_sub_i32(t0, t1, t0);
8365 break;
8366 default: /* 5, 6, 7, 9, 12, 15. */
8367 return 1;
8369 if (logic_cc) {
8370 gen_logic_CC(t0);
8371 if (shifter_out)
8372 gen_set_CF_bit31(t1);
8374 return 0;
8377 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
8378 is not legal. */
8379 static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
8381 uint32_t insn, imm, shift, offset;
8382 uint32_t rd, rn, rm, rs;
8383 TCGv_i32 tmp;
8384 TCGv_i32 tmp2;
8385 TCGv_i32 tmp3;
8386 TCGv_i32 addr;
8387 TCGv_i64 tmp64;
8388 int op;
8389 int shiftop;
8390 int conds;
8391 int logic_cc;
8393 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
8394 || arm_feature (env, ARM_FEATURE_M))) {
8395 /* Thumb-1 cores may need to treat bl and blx as a pair of
8396 16-bit instructions to get correct prefetch abort behavior. */
8397 insn = insn_hw1;
8398 if ((insn & (1 << 12)) == 0) {
8399 ARCH(5);
8400 /* Second half of blx. */
8401 offset = ((insn & 0x7ff) << 1);
8402 tmp = load_reg(s, 14);
8403 tcg_gen_addi_i32(tmp, tmp, offset);
8404 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8406 tmp2 = tcg_temp_new_i32();
8407 tcg_gen_movi_i32(tmp2, s->pc | 1);
8408 store_reg(s, 14, tmp2);
8409 gen_bx(s, tmp);
8410 return 0;
8412 if (insn & (1 << 11)) {
8413 /* Second half of bl. */
8414 offset = ((insn & 0x7ff) << 1) | 1;
8415 tmp = load_reg(s, 14);
8416 tcg_gen_addi_i32(tmp, tmp, offset);
8418 tmp2 = tcg_temp_new_i32();
8419 tcg_gen_movi_i32(tmp2, s->pc | 1);
8420 store_reg(s, 14, tmp2);
8421 gen_bx(s, tmp);
8422 return 0;
8424 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
8425 /* Instruction spans a page boundary. Implement it as two
8426 16-bit instructions in case the second half causes an
8427 prefetch abort. */
8428 offset = ((int32_t)insn << 21) >> 9;
8429 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
8430 return 0;
8432 /* Fall through to 32-bit decode. */
8435 insn = arm_lduw_code(env, s->pc, s->bswap_code);
8436 s->pc += 2;
8437 insn |= (uint32_t)insn_hw1 << 16;
8439 if ((insn & 0xf800e800) != 0xf000e800) {
8440 ARCH(6T2);
8443 rn = (insn >> 16) & 0xf;
8444 rs = (insn >> 12) & 0xf;
8445 rd = (insn >> 8) & 0xf;
8446 rm = insn & 0xf;
8447 switch ((insn >> 25) & 0xf) {
8448 case 0: case 1: case 2: case 3:
8449 /* 16-bit instructions. Should never happen. */
8450 abort();
8451 case 4:
8452 if (insn & (1 << 22)) {
8453 /* Other load/store, table branch. */
8454 if (insn & 0x01200000) {
8455 /* Load/store doubleword. */
8456 if (rn == 15) {
8457 addr = tcg_temp_new_i32();
8458 tcg_gen_movi_i32(addr, s->pc & ~3);
8459 } else {
8460 addr = load_reg(s, rn);
8462 offset = (insn & 0xff) * 4;
8463 if ((insn & (1 << 23)) == 0)
8464 offset = -offset;
8465 if (insn & (1 << 24)) {
8466 tcg_gen_addi_i32(addr, addr, offset);
8467 offset = 0;
8469 if (insn & (1 << 20)) {
8470 /* ldrd */
8471 tmp = tcg_temp_new_i32();
8472 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8473 store_reg(s, rs, tmp);
8474 tcg_gen_addi_i32(addr, addr, 4);
8475 tmp = tcg_temp_new_i32();
8476 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8477 store_reg(s, rd, tmp);
8478 } else {
8479 /* strd */
8480 tmp = load_reg(s, rs);
8481 gen_aa32_st32(tmp, addr, IS_USER(s));
8482 tcg_temp_free_i32(tmp);
8483 tcg_gen_addi_i32(addr, addr, 4);
8484 tmp = load_reg(s, rd);
8485 gen_aa32_st32(tmp, addr, IS_USER(s));
8486 tcg_temp_free_i32(tmp);
8488 if (insn & (1 << 21)) {
8489 /* Base writeback. */
8490 if (rn == 15)
8491 goto illegal_op;
8492 tcg_gen_addi_i32(addr, addr, offset - 4);
8493 store_reg(s, rn, addr);
8494 } else {
8495 tcg_temp_free_i32(addr);
8497 } else if ((insn & (1 << 23)) == 0) {
8498 /* Load/store exclusive word. */
8499 addr = tcg_temp_local_new_i32();
8500 load_reg_var(s, addr, rn);
8501 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
8502 if (insn & (1 << 20)) {
8503 gen_load_exclusive(s, rs, 15, addr, 2);
8504 } else {
8505 gen_store_exclusive(s, rd, rs, 15, addr, 2);
8507 tcg_temp_free_i32(addr);
8508 } else if ((insn & (7 << 5)) == 0) {
8509 /* Table Branch. */
8510 if (rn == 15) {
8511 addr = tcg_temp_new_i32();
8512 tcg_gen_movi_i32(addr, s->pc);
8513 } else {
8514 addr = load_reg(s, rn);
8516 tmp = load_reg(s, rm);
8517 tcg_gen_add_i32(addr, addr, tmp);
8518 if (insn & (1 << 4)) {
8519 /* tbh */
8520 tcg_gen_add_i32(addr, addr, tmp);
8521 tcg_temp_free_i32(tmp);
8522 tmp = tcg_temp_new_i32();
8523 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8524 } else { /* tbb */
8525 tcg_temp_free_i32(tmp);
8526 tmp = tcg_temp_new_i32();
8527 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8529 tcg_temp_free_i32(addr);
8530 tcg_gen_shli_i32(tmp, tmp, 1);
8531 tcg_gen_addi_i32(tmp, tmp, s->pc);
8532 store_reg(s, 15, tmp);
8533 } else {
8534 int op2 = (insn >> 6) & 0x3;
8535 op = (insn >> 4) & 0x3;
8536 switch (op2) {
8537 case 0:
8538 goto illegal_op;
8539 case 1:
8540 /* Load/store exclusive byte/halfword/doubleword */
8541 if (op == 2) {
8542 goto illegal_op;
8544 ARCH(7);
8545 break;
8546 case 2:
8547 /* Load-acquire/store-release */
8548 if (op == 3) {
8549 goto illegal_op;
8551 /* Fall through */
8552 case 3:
8553 /* Load-acquire/store-release exclusive */
8554 ARCH(8);
8555 break;
8557 addr = tcg_temp_local_new_i32();
8558 load_reg_var(s, addr, rn);
8559 if (!(op2 & 1)) {
8560 if (insn & (1 << 20)) {
8561 tmp = tcg_temp_new_i32();
8562 switch (op) {
8563 case 0: /* ldab */
8564 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8565 break;
8566 case 1: /* ldah */
8567 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8568 break;
8569 case 2: /* lda */
8570 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8571 break;
8572 default:
8573 abort();
8575 store_reg(s, rs, tmp);
8576 } else {
8577 tmp = load_reg(s, rs);
8578 switch (op) {
8579 case 0: /* stlb */
8580 gen_aa32_st8(tmp, addr, IS_USER(s));
8581 break;
8582 case 1: /* stlh */
8583 gen_aa32_st16(tmp, addr, IS_USER(s));
8584 break;
8585 case 2: /* stl */
8586 gen_aa32_st32(tmp, addr, IS_USER(s));
8587 break;
8588 default:
8589 abort();
8591 tcg_temp_free_i32(tmp);
8593 } else if (insn & (1 << 20)) {
8594 gen_load_exclusive(s, rs, rd, addr, op);
8595 } else {
8596 gen_store_exclusive(s, rm, rs, rd, addr, op);
8598 tcg_temp_free_i32(addr);
8600 } else {
8601 /* Load/store multiple, RFE, SRS. */
8602 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
8603 /* RFE, SRS: not available in user mode or on M profile */
8604 if (IS_USER(s) || IS_M(env)) {
8605 goto illegal_op;
8607 if (insn & (1 << 20)) {
8608 /* rfe */
8609 addr = load_reg(s, rn);
8610 if ((insn & (1 << 24)) == 0)
8611 tcg_gen_addi_i32(addr, addr, -8);
8612 /* Load PC into tmp and CPSR into tmp2. */
8613 tmp = tcg_temp_new_i32();
8614 gen_aa32_ld32u(tmp, addr, 0);
8615 tcg_gen_addi_i32(addr, addr, 4);
8616 tmp2 = tcg_temp_new_i32();
8617 gen_aa32_ld32u(tmp2, addr, 0);
8618 if (insn & (1 << 21)) {
8619 /* Base writeback. */
8620 if (insn & (1 << 24)) {
8621 tcg_gen_addi_i32(addr, addr, 4);
8622 } else {
8623 tcg_gen_addi_i32(addr, addr, -4);
8625 store_reg(s, rn, addr);
8626 } else {
8627 tcg_temp_free_i32(addr);
8629 gen_rfe(s, tmp, tmp2);
8630 } else {
8631 /* srs */
8632 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
8633 insn & (1 << 21));
8635 } else {
8636 int i, loaded_base = 0;
8637 TCGv_i32 loaded_var;
8638 /* Load/store multiple. */
8639 addr = load_reg(s, rn);
8640 offset = 0;
8641 for (i = 0; i < 16; i++) {
8642 if (insn & (1 << i))
8643 offset += 4;
8645 if (insn & (1 << 24)) {
8646 tcg_gen_addi_i32(addr, addr, -offset);
8649 TCGV_UNUSED_I32(loaded_var);
8650 for (i = 0; i < 16; i++) {
8651 if ((insn & (1 << i)) == 0)
8652 continue;
8653 if (insn & (1 << 20)) {
8654 /* Load. */
8655 tmp = tcg_temp_new_i32();
8656 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8657 if (i == 15) {
8658 gen_bx(s, tmp);
8659 } else if (i == rn) {
8660 loaded_var = tmp;
8661 loaded_base = 1;
8662 } else {
8663 store_reg(s, i, tmp);
8665 } else {
8666 /* Store. */
8667 tmp = load_reg(s, i);
8668 gen_aa32_st32(tmp, addr, IS_USER(s));
8669 tcg_temp_free_i32(tmp);
8671 tcg_gen_addi_i32(addr, addr, 4);
8673 if (loaded_base) {
8674 store_reg(s, rn, loaded_var);
8676 if (insn & (1 << 21)) {
8677 /* Base register writeback. */
8678 if (insn & (1 << 24)) {
8679 tcg_gen_addi_i32(addr, addr, -offset);
8681 /* Fault if writeback register is in register list. */
8682 if (insn & (1 << rn))
8683 goto illegal_op;
8684 store_reg(s, rn, addr);
8685 } else {
8686 tcg_temp_free_i32(addr);
8690 break;
8691 case 5:
8693 op = (insn >> 21) & 0xf;
8694 if (op == 6) {
8695 /* Halfword pack. */
8696 tmp = load_reg(s, rn);
8697 tmp2 = load_reg(s, rm);
8698 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
8699 if (insn & (1 << 5)) {
8700 /* pkhtb */
8701 if (shift == 0)
8702 shift = 31;
8703 tcg_gen_sari_i32(tmp2, tmp2, shift);
8704 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8705 tcg_gen_ext16u_i32(tmp2, tmp2);
8706 } else {
8707 /* pkhbt */
8708 if (shift)
8709 tcg_gen_shli_i32(tmp2, tmp2, shift);
8710 tcg_gen_ext16u_i32(tmp, tmp);
8711 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8713 tcg_gen_or_i32(tmp, tmp, tmp2);
8714 tcg_temp_free_i32(tmp2);
8715 store_reg(s, rd, tmp);
8716 } else {
8717 /* Data processing register constant shift. */
8718 if (rn == 15) {
8719 tmp = tcg_temp_new_i32();
8720 tcg_gen_movi_i32(tmp, 0);
8721 } else {
8722 tmp = load_reg(s, rn);
8724 tmp2 = load_reg(s, rm);
8726 shiftop = (insn >> 4) & 3;
8727 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8728 conds = (insn & (1 << 20)) != 0;
8729 logic_cc = (conds && thumb2_logic_op(op));
8730 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8731 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
8732 goto illegal_op;
8733 tcg_temp_free_i32(tmp2);
8734 if (rd != 15) {
8735 store_reg(s, rd, tmp);
8736 } else {
8737 tcg_temp_free_i32(tmp);
8740 break;
8741 case 13: /* Misc data processing. */
8742 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
8743 if (op < 4 && (insn & 0xf000) != 0xf000)
8744 goto illegal_op;
8745 switch (op) {
8746 case 0: /* Register controlled shift. */
8747 tmp = load_reg(s, rn);
8748 tmp2 = load_reg(s, rm);
8749 if ((insn & 0x70) != 0)
8750 goto illegal_op;
8751 op = (insn >> 21) & 3;
8752 logic_cc = (insn & (1 << 20)) != 0;
8753 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
8754 if (logic_cc)
8755 gen_logic_CC(tmp);
8756 store_reg_bx(env, s, rd, tmp);
8757 break;
8758 case 1: /* Sign/zero extend. */
8759 tmp = load_reg(s, rm);
8760 shift = (insn >> 4) & 3;
8761 /* ??? In many cases it's not necessary to do a
8762 rotate, a shift is sufficient. */
8763 if (shift != 0)
8764 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8765 op = (insn >> 20) & 7;
8766 switch (op) {
8767 case 0: gen_sxth(tmp); break;
8768 case 1: gen_uxth(tmp); break;
8769 case 2: gen_sxtb16(tmp); break;
8770 case 3: gen_uxtb16(tmp); break;
8771 case 4: gen_sxtb(tmp); break;
8772 case 5: gen_uxtb(tmp); break;
8773 default: goto illegal_op;
8775 if (rn != 15) {
8776 tmp2 = load_reg(s, rn);
8777 if ((op >> 1) == 1) {
8778 gen_add16(tmp, tmp2);
8779 } else {
8780 tcg_gen_add_i32(tmp, tmp, tmp2);
8781 tcg_temp_free_i32(tmp2);
8784 store_reg(s, rd, tmp);
8785 break;
8786 case 2: /* SIMD add/subtract. */
8787 op = (insn >> 20) & 7;
8788 shift = (insn >> 4) & 7;
8789 if ((op & 3) == 3 || (shift & 3) == 3)
8790 goto illegal_op;
8791 tmp = load_reg(s, rn);
8792 tmp2 = load_reg(s, rm);
8793 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
8794 tcg_temp_free_i32(tmp2);
8795 store_reg(s, rd, tmp);
8796 break;
8797 case 3: /* Other data processing. */
8798 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
8799 if (op < 4) {
8800 /* Saturating add/subtract. */
8801 tmp = load_reg(s, rn);
8802 tmp2 = load_reg(s, rm);
8803 if (op & 1)
8804 gen_helper_double_saturate(tmp, cpu_env, tmp);
8805 if (op & 2)
8806 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
8807 else
8808 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
8809 tcg_temp_free_i32(tmp2);
8810 } else {
8811 tmp = load_reg(s, rn);
8812 switch (op) {
8813 case 0x0a: /* rbit */
8814 gen_helper_rbit(tmp, tmp);
8815 break;
8816 case 0x08: /* rev */
8817 tcg_gen_bswap32_i32(tmp, tmp);
8818 break;
8819 case 0x09: /* rev16 */
8820 gen_rev16(tmp);
8821 break;
8822 case 0x0b: /* revsh */
8823 gen_revsh(tmp);
8824 break;
8825 case 0x10: /* sel */
8826 tmp2 = load_reg(s, rm);
8827 tmp3 = tcg_temp_new_i32();
8828 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8829 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8830 tcg_temp_free_i32(tmp3);
8831 tcg_temp_free_i32(tmp2);
8832 break;
8833 case 0x18: /* clz */
8834 gen_helper_clz(tmp, tmp);
8835 break;
8836 default:
8837 goto illegal_op;
8840 store_reg(s, rd, tmp);
8841 break;
8842 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
8843 op = (insn >> 4) & 0xf;
8844 tmp = load_reg(s, rn);
8845 tmp2 = load_reg(s, rm);
8846 switch ((insn >> 20) & 7) {
8847 case 0: /* 32 x 32 -> 32 */
8848 tcg_gen_mul_i32(tmp, tmp, tmp2);
8849 tcg_temp_free_i32(tmp2);
8850 if (rs != 15) {
8851 tmp2 = load_reg(s, rs);
8852 if (op)
8853 tcg_gen_sub_i32(tmp, tmp2, tmp);
8854 else
8855 tcg_gen_add_i32(tmp, tmp, tmp2);
8856 tcg_temp_free_i32(tmp2);
8858 break;
8859 case 1: /* 16 x 16 -> 32 */
8860 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8861 tcg_temp_free_i32(tmp2);
8862 if (rs != 15) {
8863 tmp2 = load_reg(s, rs);
8864 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8865 tcg_temp_free_i32(tmp2);
8867 break;
8868 case 2: /* Dual multiply add. */
8869 case 4: /* Dual multiply subtract. */
8870 if (op)
8871 gen_swap_half(tmp2);
8872 gen_smul_dual(tmp, tmp2);
8873 if (insn & (1 << 22)) {
8874 /* This subtraction cannot overflow. */
8875 tcg_gen_sub_i32(tmp, tmp, tmp2);
8876 } else {
8877 /* This addition cannot overflow 32 bits;
8878 * however it may overflow considered as a signed
8879 * operation, in which case we must set the Q flag.
8881 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8883 tcg_temp_free_i32(tmp2);
8884 if (rs != 15)
8886 tmp2 = load_reg(s, rs);
8887 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8888 tcg_temp_free_i32(tmp2);
8890 break;
8891 case 3: /* 32 * 16 -> 32msb */
8892 if (op)
8893 tcg_gen_sari_i32(tmp2, tmp2, 16);
8894 else
8895 gen_sxth(tmp2);
8896 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8897 tcg_gen_shri_i64(tmp64, tmp64, 16);
8898 tmp = tcg_temp_new_i32();
8899 tcg_gen_trunc_i64_i32(tmp, tmp64);
8900 tcg_temp_free_i64(tmp64);
8901 if (rs != 15)
8903 tmp2 = load_reg(s, rs);
8904 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8905 tcg_temp_free_i32(tmp2);
8907 break;
8908 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8909 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8910 if (rs != 15) {
8911 tmp = load_reg(s, rs);
8912 if (insn & (1 << 20)) {
8913 tmp64 = gen_addq_msw(tmp64, tmp);
8914 } else {
8915 tmp64 = gen_subq_msw(tmp64, tmp);
8918 if (insn & (1 << 4)) {
8919 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8921 tcg_gen_shri_i64(tmp64, tmp64, 32);
8922 tmp = tcg_temp_new_i32();
8923 tcg_gen_trunc_i64_i32(tmp, tmp64);
8924 tcg_temp_free_i64(tmp64);
8925 break;
8926 case 7: /* Unsigned sum of absolute differences. */
8927 gen_helper_usad8(tmp, tmp, tmp2);
8928 tcg_temp_free_i32(tmp2);
8929 if (rs != 15) {
8930 tmp2 = load_reg(s, rs);
8931 tcg_gen_add_i32(tmp, tmp, tmp2);
8932 tcg_temp_free_i32(tmp2);
8934 break;
8936 store_reg(s, rd, tmp);
8937 break;
8938 case 6: case 7: /* 64-bit multiply, Divide. */
8939 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
8940 tmp = load_reg(s, rn);
8941 tmp2 = load_reg(s, rm);
8942 if ((op & 0x50) == 0x10) {
8943 /* sdiv, udiv */
8944 if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
8945 goto illegal_op;
8947 if (op & 0x20)
8948 gen_helper_udiv(tmp, tmp, tmp2);
8949 else
8950 gen_helper_sdiv(tmp, tmp, tmp2);
8951 tcg_temp_free_i32(tmp2);
8952 store_reg(s, rd, tmp);
8953 } else if ((op & 0xe) == 0xc) {
8954 /* Dual multiply accumulate long. */
8955 if (op & 1)
8956 gen_swap_half(tmp2);
8957 gen_smul_dual(tmp, tmp2);
8958 if (op & 0x10) {
8959 tcg_gen_sub_i32(tmp, tmp, tmp2);
8960 } else {
8961 tcg_gen_add_i32(tmp, tmp, tmp2);
8963 tcg_temp_free_i32(tmp2);
8964 /* BUGFIX */
8965 tmp64 = tcg_temp_new_i64();
8966 tcg_gen_ext_i32_i64(tmp64, tmp);
8967 tcg_temp_free_i32(tmp);
8968 gen_addq(s, tmp64, rs, rd);
8969 gen_storeq_reg(s, rs, rd, tmp64);
8970 tcg_temp_free_i64(tmp64);
8971 } else {
8972 if (op & 0x20) {
8973 /* Unsigned 64-bit multiply */
8974 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8975 } else {
8976 if (op & 8) {
8977 /* smlalxy */
8978 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8979 tcg_temp_free_i32(tmp2);
8980 tmp64 = tcg_temp_new_i64();
8981 tcg_gen_ext_i32_i64(tmp64, tmp);
8982 tcg_temp_free_i32(tmp);
8983 } else {
8984 /* Signed 64-bit multiply */
8985 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8988 if (op & 4) {
8989 /* umaal */
8990 gen_addq_lo(s, tmp64, rs);
8991 gen_addq_lo(s, tmp64, rd);
8992 } else if (op & 0x40) {
8993 /* 64-bit accumulate. */
8994 gen_addq(s, tmp64, rs, rd);
8996 gen_storeq_reg(s, rs, rd, tmp64);
8997 tcg_temp_free_i64(tmp64);
8999 break;
9001 break;
9002 case 6: case 7: case 14: case 15:
9003 /* Coprocessor. */
9004 if (((insn >> 24) & 3) == 3) {
9005 /* Translate into the equivalent ARM encoding. */
9006 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
9007 if (disas_neon_data_insn(env, s, insn))
9008 goto illegal_op;
9009 } else if (((insn >> 8) & 0xe) == 10) {
9010 if (disas_vfp_insn(env, s, insn)) {
9011 goto illegal_op;
9013 } else {
9014 if (insn & (1 << 28))
9015 goto illegal_op;
9016 if (disas_coproc_insn (env, s, insn))
9017 goto illegal_op;
9019 break;
9020 case 8: case 9: case 10: case 11:
9021 if (insn & (1 << 15)) {
9022 /* Branches, misc control. */
9023 if (insn & 0x5000) {
9024 /* Unconditional branch. */
9025 /* signextend(hw1[10:0]) -> offset[:12]. */
9026 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
9027 /* hw1[10:0] -> offset[11:1]. */
9028 offset |= (insn & 0x7ff) << 1;
9029 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
9030 offset[24:22] already have the same value because of the
9031 sign extension above. */
9032 offset ^= ((~insn) & (1 << 13)) << 10;
9033 offset ^= ((~insn) & (1 << 11)) << 11;
9035 if (insn & (1 << 14)) {
9036 /* Branch and link. */
9037 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
9040 offset += s->pc;
9041 if (insn & (1 << 12)) {
9042 /* b/bl */
9043 gen_jmp(s, offset);
9044 } else {
9045 /* blx */
9046 offset &= ~(uint32_t)2;
9047 /* thumb2 bx, no need to check */
9048 gen_bx_im(s, offset);
9050 } else if (((insn >> 23) & 7) == 7) {
9051 /* Misc control */
9052 if (insn & (1 << 13))
9053 goto illegal_op;
9055 if (insn & (1 << 26)) {
9056 /* Secure monitor call (v6Z) */
9057 qemu_log_mask(LOG_UNIMP,
9058 "arm: unimplemented secure monitor call\n");
9059 goto illegal_op; /* not implemented. */
9060 } else {
9061 op = (insn >> 20) & 7;
9062 switch (op) {
9063 case 0: /* msr cpsr. */
9064 if (IS_M(env)) {
9065 tmp = load_reg(s, rn);
9066 addr = tcg_const_i32(insn & 0xff);
9067 gen_helper_v7m_msr(cpu_env, addr, tmp);
9068 tcg_temp_free_i32(addr);
9069 tcg_temp_free_i32(tmp);
9070 gen_lookup_tb(s);
9071 break;
9073 /* fall through */
9074 case 1: /* msr spsr. */
9075 if (IS_M(env))
9076 goto illegal_op;
9077 tmp = load_reg(s, rn);
9078 if (gen_set_psr(s,
9079 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
9080 op == 1, tmp))
9081 goto illegal_op;
9082 break;
9083 case 2: /* cps, nop-hint. */
9084 if (((insn >> 8) & 7) == 0) {
9085 gen_nop_hint(s, insn & 0xff);
9087 /* Implemented as NOP in user mode. */
9088 if (IS_USER(s))
9089 break;
9090 offset = 0;
9091 imm = 0;
9092 if (insn & (1 << 10)) {
9093 if (insn & (1 << 7))
9094 offset |= CPSR_A;
9095 if (insn & (1 << 6))
9096 offset |= CPSR_I;
9097 if (insn & (1 << 5))
9098 offset |= CPSR_F;
9099 if (insn & (1 << 9))
9100 imm = CPSR_A | CPSR_I | CPSR_F;
9102 if (insn & (1 << 8)) {
9103 offset |= 0x1f;
9104 imm |= (insn & 0x1f);
9106 if (offset) {
9107 gen_set_psr_im(s, offset, 0, imm);
9109 break;
9110 case 3: /* Special control operations. */
9111 ARCH(7);
9112 op = (insn >> 4) & 0xf;
9113 switch (op) {
9114 case 2: /* clrex */
9115 gen_clrex(s);
9116 break;
9117 case 4: /* dsb */
9118 case 5: /* dmb */
9119 case 6: /* isb */
9120 /* These execute as NOPs. */
9121 break;
9122 default:
9123 goto illegal_op;
9125 break;
9126 case 4: /* bxj */
9127 /* Trivial implementation equivalent to bx. */
9128 tmp = load_reg(s, rn);
9129 gen_bx(s, tmp);
9130 break;
9131 case 5: /* Exception return. */
9132 if (IS_USER(s)) {
9133 goto illegal_op;
9135 if (rn != 14 || rd != 15) {
9136 goto illegal_op;
9138 tmp = load_reg(s, rn);
9139 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
9140 gen_exception_return(s, tmp);
9141 break;
9142 case 6: /* mrs cpsr. */
9143 tmp = tcg_temp_new_i32();
9144 if (IS_M(env)) {
9145 addr = tcg_const_i32(insn & 0xff);
9146 gen_helper_v7m_mrs(tmp, cpu_env, addr);
9147 tcg_temp_free_i32(addr);
9148 } else {
9149 gen_helper_cpsr_read(tmp, cpu_env);
9151 store_reg(s, rd, tmp);
9152 break;
9153 case 7: /* mrs spsr. */
9154 /* Not accessible in user mode. */
9155 if (IS_USER(s) || IS_M(env))
9156 goto illegal_op;
9157 tmp = load_cpu_field(spsr);
9158 store_reg(s, rd, tmp);
9159 break;
9162 } else {
9163 /* Conditional branch. */
9164 op = (insn >> 22) & 0xf;
9165 /* Generate a conditional jump to next instruction. */
9166 s->condlabel = gen_new_label();
9167 arm_gen_test_cc(op ^ 1, s->condlabel);
9168 s->condjmp = 1;
9170 /* offset[11:1] = insn[10:0] */
9171 offset = (insn & 0x7ff) << 1;
9172 /* offset[17:12] = insn[21:16]. */
9173 offset |= (insn & 0x003f0000) >> 4;
9174 /* offset[31:20] = insn[26]. */
9175 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
9176 /* offset[18] = insn[13]. */
9177 offset |= (insn & (1 << 13)) << 5;
9178 /* offset[19] = insn[11]. */
9179 offset |= (insn & (1 << 11)) << 8;
9181 /* jump to the offset */
9182 gen_jmp(s, s->pc + offset);
9184 } else {
9185 /* Data processing immediate. */
9186 if (insn & (1 << 25)) {
9187 if (insn & (1 << 24)) {
9188 if (insn & (1 << 20))
9189 goto illegal_op;
9190 /* Bitfield/Saturate. */
9191 op = (insn >> 21) & 7;
9192 imm = insn & 0x1f;
9193 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9194 if (rn == 15) {
9195 tmp = tcg_temp_new_i32();
9196 tcg_gen_movi_i32(tmp, 0);
9197 } else {
9198 tmp = load_reg(s, rn);
9200 switch (op) {
9201 case 2: /* Signed bitfield extract. */
9202 imm++;
9203 if (shift + imm > 32)
9204 goto illegal_op;
9205 if (imm < 32)
9206 gen_sbfx(tmp, shift, imm);
9207 break;
9208 case 6: /* Unsigned bitfield extract. */
9209 imm++;
9210 if (shift + imm > 32)
9211 goto illegal_op;
9212 if (imm < 32)
9213 gen_ubfx(tmp, shift, (1u << imm) - 1);
9214 break;
9215 case 3: /* Bitfield insert/clear. */
9216 if (imm < shift)
9217 goto illegal_op;
9218 imm = imm + 1 - shift;
9219 if (imm != 32) {
9220 tmp2 = load_reg(s, rd);
9221 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
9222 tcg_temp_free_i32(tmp2);
9224 break;
9225 case 7:
9226 goto illegal_op;
9227 default: /* Saturate. */
9228 if (shift) {
9229 if (op & 1)
9230 tcg_gen_sari_i32(tmp, tmp, shift);
9231 else
9232 tcg_gen_shli_i32(tmp, tmp, shift);
9234 tmp2 = tcg_const_i32(imm);
9235 if (op & 4) {
9236 /* Unsigned. */
9237 if ((op & 1) && shift == 0)
9238 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9239 else
9240 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9241 } else {
9242 /* Signed. */
9243 if ((op & 1) && shift == 0)
9244 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9245 else
9246 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9248 tcg_temp_free_i32(tmp2);
9249 break;
9251 store_reg(s, rd, tmp);
9252 } else {
9253 imm = ((insn & 0x04000000) >> 15)
9254 | ((insn & 0x7000) >> 4) | (insn & 0xff);
9255 if (insn & (1 << 22)) {
9256 /* 16-bit immediate. */
9257 imm |= (insn >> 4) & 0xf000;
9258 if (insn & (1 << 23)) {
9259 /* movt */
9260 tmp = load_reg(s, rd);
9261 tcg_gen_ext16u_i32(tmp, tmp);
9262 tcg_gen_ori_i32(tmp, tmp, imm << 16);
9263 } else {
9264 /* movw */
9265 tmp = tcg_temp_new_i32();
9266 tcg_gen_movi_i32(tmp, imm);
9268 } else {
9269 /* Add/sub 12-bit immediate. */
9270 if (rn == 15) {
9271 offset = s->pc & ~(uint32_t)3;
9272 if (insn & (1 << 23))
9273 offset -= imm;
9274 else
9275 offset += imm;
9276 tmp = tcg_temp_new_i32();
9277 tcg_gen_movi_i32(tmp, offset);
9278 } else {
9279 tmp = load_reg(s, rn);
9280 if (insn & (1 << 23))
9281 tcg_gen_subi_i32(tmp, tmp, imm);
9282 else
9283 tcg_gen_addi_i32(tmp, tmp, imm);
9286 store_reg(s, rd, tmp);
9288 } else {
9289 int shifter_out = 0;
9290 /* modified 12-bit immediate. */
9291 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
9292 imm = (insn & 0xff);
9293 switch (shift) {
9294 case 0: /* XY */
9295 /* Nothing to do. */
9296 break;
9297 case 1: /* 00XY00XY */
9298 imm |= imm << 16;
9299 break;
9300 case 2: /* XY00XY00 */
9301 imm |= imm << 16;
9302 imm <<= 8;
9303 break;
9304 case 3: /* XYXYXYXY */
9305 imm |= imm << 16;
9306 imm |= imm << 8;
9307 break;
9308 default: /* Rotated constant. */
9309 shift = (shift << 1) | (imm >> 7);
9310 imm |= 0x80;
9311 imm = imm << (32 - shift);
9312 shifter_out = 1;
9313 break;
9315 tmp2 = tcg_temp_new_i32();
9316 tcg_gen_movi_i32(tmp2, imm);
9317 rn = (insn >> 16) & 0xf;
9318 if (rn == 15) {
9319 tmp = tcg_temp_new_i32();
9320 tcg_gen_movi_i32(tmp, 0);
9321 } else {
9322 tmp = load_reg(s, rn);
9324 op = (insn >> 21) & 0xf;
9325 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
9326 shifter_out, tmp, tmp2))
9327 goto illegal_op;
9328 tcg_temp_free_i32(tmp2);
9329 rd = (insn >> 8) & 0xf;
9330 if (rd != 15) {
9331 store_reg(s, rd, tmp);
9332 } else {
9333 tcg_temp_free_i32(tmp);
9337 break;
9338 case 12: /* Load/store single data item. */
9340 int postinc = 0;
9341 int writeback = 0;
9342 int user;
9343 if ((insn & 0x01100000) == 0x01000000) {
9344 if (disas_neon_ls_insn(env, s, insn))
9345 goto illegal_op;
9346 break;
9348 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
9349 if (rs == 15) {
9350 if (!(insn & (1 << 20))) {
9351 goto illegal_op;
9353 if (op != 2) {
9354 /* Byte or halfword load space with dest == r15 : memory hints.
9355 * Catch them early so we don't emit pointless addressing code.
9356 * This space is a mix of:
9357 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
9358 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
9359 * cores)
9360 * unallocated hints, which must be treated as NOPs
9361 * UNPREDICTABLE space, which we NOP or UNDEF depending on
9362 * which is easiest for the decoding logic
9363 * Some space which must UNDEF
9365 int op1 = (insn >> 23) & 3;
9366 int op2 = (insn >> 6) & 0x3f;
9367 if (op & 2) {
9368 goto illegal_op;
9370 if (rn == 15) {
9371 /* UNPREDICTABLE, unallocated hint or
9372 * PLD/PLDW/PLI (literal)
9374 return 0;
9376 if (op1 & 1) {
9377 return 0; /* PLD/PLDW/PLI or unallocated hint */
9379 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
9380 return 0; /* PLD/PLDW/PLI or unallocated hint */
9382 /* UNDEF space, or an UNPREDICTABLE */
9383 return 1;
9386 user = IS_USER(s);
9387 if (rn == 15) {
9388 addr = tcg_temp_new_i32();
9389 /* PC relative. */
9390 /* s->pc has already been incremented by 4. */
9391 imm = s->pc & 0xfffffffc;
9392 if (insn & (1 << 23))
9393 imm += insn & 0xfff;
9394 else
9395 imm -= insn & 0xfff;
9396 tcg_gen_movi_i32(addr, imm);
9397 } else {
9398 addr = load_reg(s, rn);
9399 if (insn & (1 << 23)) {
9400 /* Positive offset. */
9401 imm = insn & 0xfff;
9402 tcg_gen_addi_i32(addr, addr, imm);
9403 } else {
9404 imm = insn & 0xff;
9405 switch ((insn >> 8) & 0xf) {
9406 case 0x0: /* Shifted Register. */
9407 shift = (insn >> 4) & 0xf;
9408 if (shift > 3) {
9409 tcg_temp_free_i32(addr);
9410 goto illegal_op;
9412 tmp = load_reg(s, rm);
9413 if (shift)
9414 tcg_gen_shli_i32(tmp, tmp, shift);
9415 tcg_gen_add_i32(addr, addr, tmp);
9416 tcg_temp_free_i32(tmp);
9417 break;
9418 case 0xc: /* Negative offset. */
9419 tcg_gen_addi_i32(addr, addr, -imm);
9420 break;
9421 case 0xe: /* User privilege. */
9422 tcg_gen_addi_i32(addr, addr, imm);
9423 user = 1;
9424 break;
9425 case 0x9: /* Post-decrement. */
9426 imm = -imm;
9427 /* Fall through. */
9428 case 0xb: /* Post-increment. */
9429 postinc = 1;
9430 writeback = 1;
9431 break;
9432 case 0xd: /* Pre-decrement. */
9433 imm = -imm;
9434 /* Fall through. */
9435 case 0xf: /* Pre-increment. */
9436 tcg_gen_addi_i32(addr, addr, imm);
9437 writeback = 1;
9438 break;
9439 default:
9440 tcg_temp_free_i32(addr);
9441 goto illegal_op;
9445 if (insn & (1 << 20)) {
9446 /* Load. */
9447 tmp = tcg_temp_new_i32();
9448 switch (op) {
9449 case 0:
9450 gen_aa32_ld8u(tmp, addr, user);
9451 break;
9452 case 4:
9453 gen_aa32_ld8s(tmp, addr, user);
9454 break;
9455 case 1:
9456 gen_aa32_ld16u(tmp, addr, user);
9457 break;
9458 case 5:
9459 gen_aa32_ld16s(tmp, addr, user);
9460 break;
9461 case 2:
9462 gen_aa32_ld32u(tmp, addr, user);
9463 break;
9464 default:
9465 tcg_temp_free_i32(tmp);
9466 tcg_temp_free_i32(addr);
9467 goto illegal_op;
9469 if (rs == 15) {
9470 gen_bx(s, tmp);
9471 } else {
9472 store_reg(s, rs, tmp);
9474 } else {
9475 /* Store. */
9476 tmp = load_reg(s, rs);
9477 switch (op) {
9478 case 0:
9479 gen_aa32_st8(tmp, addr, user);
9480 break;
9481 case 1:
9482 gen_aa32_st16(tmp, addr, user);
9483 break;
9484 case 2:
9485 gen_aa32_st32(tmp, addr, user);
9486 break;
9487 default:
9488 tcg_temp_free_i32(tmp);
9489 tcg_temp_free_i32(addr);
9490 goto illegal_op;
9492 tcg_temp_free_i32(tmp);
9494 if (postinc)
9495 tcg_gen_addi_i32(addr, addr, imm);
9496 if (writeback) {
9497 store_reg(s, rn, addr);
9498 } else {
9499 tcg_temp_free_i32(addr);
9502 break;
9503 default:
9504 goto illegal_op;
9506 return 0;
9507 illegal_op:
9508 return 1;
9511 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
9513 uint32_t val, insn, op, rm, rn, rd, shift, cond;
9514 int32_t offset;
9515 int i;
9516 TCGv_i32 tmp;
9517 TCGv_i32 tmp2;
9518 TCGv_i32 addr;
9520 if (s->condexec_mask) {
9521 cond = s->condexec_cond;
9522 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
9523 s->condlabel = gen_new_label();
9524 arm_gen_test_cc(cond ^ 1, s->condlabel);
9525 s->condjmp = 1;
9529 insn = arm_lduw_code(env, s->pc, s->bswap_code);
9530 s->pc += 2;
9532 switch (insn >> 12) {
9533 case 0: case 1:
9535 rd = insn & 7;
9536 op = (insn >> 11) & 3;
9537 if (op == 3) {
9538 /* add/subtract */
9539 rn = (insn >> 3) & 7;
9540 tmp = load_reg(s, rn);
9541 if (insn & (1 << 10)) {
9542 /* immediate */
9543 tmp2 = tcg_temp_new_i32();
9544 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
9545 } else {
9546 /* reg */
9547 rm = (insn >> 6) & 7;
9548 tmp2 = load_reg(s, rm);
9550 if (insn & (1 << 9)) {
9551 if (s->condexec_mask)
9552 tcg_gen_sub_i32(tmp, tmp, tmp2);
9553 else
9554 gen_sub_CC(tmp, tmp, tmp2);
9555 } else {
9556 if (s->condexec_mask)
9557 tcg_gen_add_i32(tmp, tmp, tmp2);
9558 else
9559 gen_add_CC(tmp, tmp, tmp2);
9561 tcg_temp_free_i32(tmp2);
9562 store_reg(s, rd, tmp);
9563 } else {
9564 /* shift immediate */
9565 rm = (insn >> 3) & 7;
9566 shift = (insn >> 6) & 0x1f;
9567 tmp = load_reg(s, rm);
9568 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
9569 if (!s->condexec_mask)
9570 gen_logic_CC(tmp);
9571 store_reg(s, rd, tmp);
9573 break;
9574 case 2: case 3:
9575 /* arithmetic large immediate */
9576 op = (insn >> 11) & 3;
9577 rd = (insn >> 8) & 0x7;
9578 if (op == 0) { /* mov */
9579 tmp = tcg_temp_new_i32();
9580 tcg_gen_movi_i32(tmp, insn & 0xff);
9581 if (!s->condexec_mask)
9582 gen_logic_CC(tmp);
9583 store_reg(s, rd, tmp);
9584 } else {
9585 tmp = load_reg(s, rd);
9586 tmp2 = tcg_temp_new_i32();
9587 tcg_gen_movi_i32(tmp2, insn & 0xff);
9588 switch (op) {
9589 case 1: /* cmp */
9590 gen_sub_CC(tmp, tmp, tmp2);
9591 tcg_temp_free_i32(tmp);
9592 tcg_temp_free_i32(tmp2);
9593 break;
9594 case 2: /* add */
9595 if (s->condexec_mask)
9596 tcg_gen_add_i32(tmp, tmp, tmp2);
9597 else
9598 gen_add_CC(tmp, tmp, tmp2);
9599 tcg_temp_free_i32(tmp2);
9600 store_reg(s, rd, tmp);
9601 break;
9602 case 3: /* sub */
9603 if (s->condexec_mask)
9604 tcg_gen_sub_i32(tmp, tmp, tmp2);
9605 else
9606 gen_sub_CC(tmp, tmp, tmp2);
9607 tcg_temp_free_i32(tmp2);
9608 store_reg(s, rd, tmp);
9609 break;
9612 break;
9613 case 4:
9614 if (insn & (1 << 11)) {
9615 rd = (insn >> 8) & 7;
9616 /* load pc-relative. Bit 1 of PC is ignored. */
9617 val = s->pc + 2 + ((insn & 0xff) * 4);
9618 val &= ~(uint32_t)2;
9619 addr = tcg_temp_new_i32();
9620 tcg_gen_movi_i32(addr, val);
9621 tmp = tcg_temp_new_i32();
9622 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9623 tcg_temp_free_i32(addr);
9624 store_reg(s, rd, tmp);
9625 break;
9627 if (insn & (1 << 10)) {
9628 /* data processing extended or blx */
9629 rd = (insn & 7) | ((insn >> 4) & 8);
9630 rm = (insn >> 3) & 0xf;
9631 op = (insn >> 8) & 3;
9632 switch (op) {
9633 case 0: /* add */
9634 tmp = load_reg(s, rd);
9635 tmp2 = load_reg(s, rm);
9636 tcg_gen_add_i32(tmp, tmp, tmp2);
9637 tcg_temp_free_i32(tmp2);
9638 store_reg(s, rd, tmp);
9639 break;
9640 case 1: /* cmp */
9641 tmp = load_reg(s, rd);
9642 tmp2 = load_reg(s, rm);
9643 gen_sub_CC(tmp, tmp, tmp2);
9644 tcg_temp_free_i32(tmp2);
9645 tcg_temp_free_i32(tmp);
9646 break;
9647 case 2: /* mov/cpy */
9648 tmp = load_reg(s, rm);
9649 store_reg(s, rd, tmp);
9650 break;
9651 case 3:/* branch [and link] exchange thumb register */
9652 tmp = load_reg(s, rm);
9653 if (insn & (1 << 7)) {
9654 ARCH(5);
9655 val = (uint32_t)s->pc | 1;
9656 tmp2 = tcg_temp_new_i32();
9657 tcg_gen_movi_i32(tmp2, val);
9658 store_reg(s, 14, tmp2);
9660 /* already thumb, no need to check */
9661 gen_bx(s, tmp);
9662 break;
9664 break;
9667 /* data processing register */
9668 rd = insn & 7;
9669 rm = (insn >> 3) & 7;
9670 op = (insn >> 6) & 0xf;
9671 if (op == 2 || op == 3 || op == 4 || op == 7) {
9672 /* the shift/rotate ops want the operands backwards */
9673 val = rm;
9674 rm = rd;
9675 rd = val;
9676 val = 1;
9677 } else {
9678 val = 0;
9681 if (op == 9) { /* neg */
9682 tmp = tcg_temp_new_i32();
9683 tcg_gen_movi_i32(tmp, 0);
9684 } else if (op != 0xf) { /* mvn doesn't read its first operand */
9685 tmp = load_reg(s, rd);
9686 } else {
9687 TCGV_UNUSED_I32(tmp);
9690 tmp2 = load_reg(s, rm);
9691 switch (op) {
9692 case 0x0: /* and */
9693 tcg_gen_and_i32(tmp, tmp, tmp2);
9694 if (!s->condexec_mask)
9695 gen_logic_CC(tmp);
9696 break;
9697 case 0x1: /* eor */
9698 tcg_gen_xor_i32(tmp, tmp, tmp2);
9699 if (!s->condexec_mask)
9700 gen_logic_CC(tmp);
9701 break;
9702 case 0x2: /* lsl */
9703 if (s->condexec_mask) {
9704 gen_shl(tmp2, tmp2, tmp);
9705 } else {
9706 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
9707 gen_logic_CC(tmp2);
9709 break;
9710 case 0x3: /* lsr */
9711 if (s->condexec_mask) {
9712 gen_shr(tmp2, tmp2, tmp);
9713 } else {
9714 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
9715 gen_logic_CC(tmp2);
9717 break;
9718 case 0x4: /* asr */
9719 if (s->condexec_mask) {
9720 gen_sar(tmp2, tmp2, tmp);
9721 } else {
9722 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
9723 gen_logic_CC(tmp2);
9725 break;
9726 case 0x5: /* adc */
9727 if (s->condexec_mask) {
9728 gen_adc(tmp, tmp2);
9729 } else {
9730 gen_adc_CC(tmp, tmp, tmp2);
9732 break;
9733 case 0x6: /* sbc */
9734 if (s->condexec_mask) {
9735 gen_sub_carry(tmp, tmp, tmp2);
9736 } else {
9737 gen_sbc_CC(tmp, tmp, tmp2);
9739 break;
9740 case 0x7: /* ror */
9741 if (s->condexec_mask) {
9742 tcg_gen_andi_i32(tmp, tmp, 0x1f);
9743 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9744 } else {
9745 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
9746 gen_logic_CC(tmp2);
9748 break;
9749 case 0x8: /* tst */
9750 tcg_gen_and_i32(tmp, tmp, tmp2);
9751 gen_logic_CC(tmp);
9752 rd = 16;
9753 break;
9754 case 0x9: /* neg */
9755 if (s->condexec_mask)
9756 tcg_gen_neg_i32(tmp, tmp2);
9757 else
9758 gen_sub_CC(tmp, tmp, tmp2);
9759 break;
9760 case 0xa: /* cmp */
9761 gen_sub_CC(tmp, tmp, tmp2);
9762 rd = 16;
9763 break;
9764 case 0xb: /* cmn */
9765 gen_add_CC(tmp, tmp, tmp2);
9766 rd = 16;
9767 break;
9768 case 0xc: /* orr */
9769 tcg_gen_or_i32(tmp, tmp, tmp2);
9770 if (!s->condexec_mask)
9771 gen_logic_CC(tmp);
9772 break;
9773 case 0xd: /* mul */
9774 tcg_gen_mul_i32(tmp, tmp, tmp2);
9775 if (!s->condexec_mask)
9776 gen_logic_CC(tmp);
9777 break;
9778 case 0xe: /* bic */
9779 tcg_gen_andc_i32(tmp, tmp, tmp2);
9780 if (!s->condexec_mask)
9781 gen_logic_CC(tmp);
9782 break;
9783 case 0xf: /* mvn */
9784 tcg_gen_not_i32(tmp2, tmp2);
9785 if (!s->condexec_mask)
9786 gen_logic_CC(tmp2);
9787 val = 1;
9788 rm = rd;
9789 break;
9791 if (rd != 16) {
9792 if (val) {
9793 store_reg(s, rm, tmp2);
9794 if (op != 0xf)
9795 tcg_temp_free_i32(tmp);
9796 } else {
9797 store_reg(s, rd, tmp);
9798 tcg_temp_free_i32(tmp2);
9800 } else {
9801 tcg_temp_free_i32(tmp);
9802 tcg_temp_free_i32(tmp2);
9804 break;
9806 case 5:
9807 /* load/store register offset. */
9808 rd = insn & 7;
9809 rn = (insn >> 3) & 7;
9810 rm = (insn >> 6) & 7;
9811 op = (insn >> 9) & 7;
9812 addr = load_reg(s, rn);
9813 tmp = load_reg(s, rm);
9814 tcg_gen_add_i32(addr, addr, tmp);
9815 tcg_temp_free_i32(tmp);
9817 if (op < 3) { /* store */
9818 tmp = load_reg(s, rd);
9819 } else {
9820 tmp = tcg_temp_new_i32();
9823 switch (op) {
9824 case 0: /* str */
9825 gen_aa32_st32(tmp, addr, IS_USER(s));
9826 break;
9827 case 1: /* strh */
9828 gen_aa32_st16(tmp, addr, IS_USER(s));
9829 break;
9830 case 2: /* strb */
9831 gen_aa32_st8(tmp, addr, IS_USER(s));
9832 break;
9833 case 3: /* ldrsb */
9834 gen_aa32_ld8s(tmp, addr, IS_USER(s));
9835 break;
9836 case 4: /* ldr */
9837 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9838 break;
9839 case 5: /* ldrh */
9840 gen_aa32_ld16u(tmp, addr, IS_USER(s));
9841 break;
9842 case 6: /* ldrb */
9843 gen_aa32_ld8u(tmp, addr, IS_USER(s));
9844 break;
9845 case 7: /* ldrsh */
9846 gen_aa32_ld16s(tmp, addr, IS_USER(s));
9847 break;
9849 if (op >= 3) { /* load */
9850 store_reg(s, rd, tmp);
9851 } else {
9852 tcg_temp_free_i32(tmp);
9854 tcg_temp_free_i32(addr);
9855 break;
9857 case 6:
9858 /* load/store word immediate offset */
9859 rd = insn & 7;
9860 rn = (insn >> 3) & 7;
9861 addr = load_reg(s, rn);
9862 val = (insn >> 4) & 0x7c;
9863 tcg_gen_addi_i32(addr, addr, val);
9865 if (insn & (1 << 11)) {
9866 /* load */
9867 tmp = tcg_temp_new_i32();
9868 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9869 store_reg(s, rd, tmp);
9870 } else {
9871 /* store */
9872 tmp = load_reg(s, rd);
9873 gen_aa32_st32(tmp, addr, IS_USER(s));
9874 tcg_temp_free_i32(tmp);
9876 tcg_temp_free_i32(addr);
9877 break;
9879 case 7:
9880 /* load/store byte immediate offset */
9881 rd = insn & 7;
9882 rn = (insn >> 3) & 7;
9883 addr = load_reg(s, rn);
9884 val = (insn >> 6) & 0x1f;
9885 tcg_gen_addi_i32(addr, addr, val);
9887 if (insn & (1 << 11)) {
9888 /* load */
9889 tmp = tcg_temp_new_i32();
9890 gen_aa32_ld8u(tmp, addr, IS_USER(s));
9891 store_reg(s, rd, tmp);
9892 } else {
9893 /* store */
9894 tmp = load_reg(s, rd);
9895 gen_aa32_st8(tmp, addr, IS_USER(s));
9896 tcg_temp_free_i32(tmp);
9898 tcg_temp_free_i32(addr);
9899 break;
9901 case 8:
9902 /* load/store halfword immediate offset */
9903 rd = insn & 7;
9904 rn = (insn >> 3) & 7;
9905 addr = load_reg(s, rn);
9906 val = (insn >> 5) & 0x3e;
9907 tcg_gen_addi_i32(addr, addr, val);
9909 if (insn & (1 << 11)) {
9910 /* load */
9911 tmp = tcg_temp_new_i32();
9912 gen_aa32_ld16u(tmp, addr, IS_USER(s));
9913 store_reg(s, rd, tmp);
9914 } else {
9915 /* store */
9916 tmp = load_reg(s, rd);
9917 gen_aa32_st16(tmp, addr, IS_USER(s));
9918 tcg_temp_free_i32(tmp);
9920 tcg_temp_free_i32(addr);
9921 break;
9923 case 9:
9924 /* load/store from stack */
9925 rd = (insn >> 8) & 7;
9926 addr = load_reg(s, 13);
9927 val = (insn & 0xff) * 4;
9928 tcg_gen_addi_i32(addr, addr, val);
9930 if (insn & (1 << 11)) {
9931 /* load */
9932 tmp = tcg_temp_new_i32();
9933 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9934 store_reg(s, rd, tmp);
9935 } else {
9936 /* store */
9937 tmp = load_reg(s, rd);
9938 gen_aa32_st32(tmp, addr, IS_USER(s));
9939 tcg_temp_free_i32(tmp);
9941 tcg_temp_free_i32(addr);
9942 break;
9944 case 10:
9945 /* add to high reg */
9946 rd = (insn >> 8) & 7;
9947 if (insn & (1 << 11)) {
9948 /* SP */
9949 tmp = load_reg(s, 13);
9950 } else {
9951 /* PC. bit 1 is ignored. */
9952 tmp = tcg_temp_new_i32();
9953 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
9955 val = (insn & 0xff) * 4;
9956 tcg_gen_addi_i32(tmp, tmp, val);
9957 store_reg(s, rd, tmp);
9958 break;
9960 case 11:
9961 /* misc */
9962 op = (insn >> 8) & 0xf;
9963 switch (op) {
9964 case 0:
9965 /* adjust stack pointer */
9966 tmp = load_reg(s, 13);
9967 val = (insn & 0x7f) * 4;
9968 if (insn & (1 << 7))
9969 val = -(int32_t)val;
9970 tcg_gen_addi_i32(tmp, tmp, val);
9971 store_reg(s, 13, tmp);
9972 break;
9974 case 2: /* sign/zero extend. */
9975 ARCH(6);
9976 rd = insn & 7;
9977 rm = (insn >> 3) & 7;
9978 tmp = load_reg(s, rm);
9979 switch ((insn >> 6) & 3) {
9980 case 0: gen_sxth(tmp); break;
9981 case 1: gen_sxtb(tmp); break;
9982 case 2: gen_uxth(tmp); break;
9983 case 3: gen_uxtb(tmp); break;
9985 store_reg(s, rd, tmp);
9986 break;
9987 case 4: case 5: case 0xc: case 0xd:
9988 /* push/pop */
9989 addr = load_reg(s, 13);
9990 if (insn & (1 << 8))
9991 offset = 4;
9992 else
9993 offset = 0;
9994 for (i = 0; i < 8; i++) {
9995 if (insn & (1 << i))
9996 offset += 4;
9998 if ((insn & (1 << 11)) == 0) {
9999 tcg_gen_addi_i32(addr, addr, -offset);
10001 for (i = 0; i < 8; i++) {
10002 if (insn & (1 << i)) {
10003 if (insn & (1 << 11)) {
10004 /* pop */
10005 tmp = tcg_temp_new_i32();
10006 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10007 store_reg(s, i, tmp);
10008 } else {
10009 /* push */
10010 tmp = load_reg(s, i);
10011 gen_aa32_st32(tmp, addr, IS_USER(s));
10012 tcg_temp_free_i32(tmp);
10014 /* advance to the next address. */
10015 tcg_gen_addi_i32(addr, addr, 4);
10018 TCGV_UNUSED_I32(tmp);
10019 if (insn & (1 << 8)) {
10020 if (insn & (1 << 11)) {
10021 /* pop pc */
10022 tmp = tcg_temp_new_i32();
10023 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10024 /* don't set the pc until the rest of the instruction
10025 has completed */
10026 } else {
10027 /* push lr */
10028 tmp = load_reg(s, 14);
10029 gen_aa32_st32(tmp, addr, IS_USER(s));
10030 tcg_temp_free_i32(tmp);
10032 tcg_gen_addi_i32(addr, addr, 4);
10034 if ((insn & (1 << 11)) == 0) {
10035 tcg_gen_addi_i32(addr, addr, -offset);
10037 /* write back the new stack pointer */
10038 store_reg(s, 13, addr);
10039 /* set the new PC value */
10040 if ((insn & 0x0900) == 0x0900) {
10041 store_reg_from_load(env, s, 15, tmp);
10043 break;
10045 case 1: case 3: case 9: case 11: /* czb */
10046 rm = insn & 7;
10047 tmp = load_reg(s, rm);
10048 s->condlabel = gen_new_label();
10049 s->condjmp = 1;
10050 if (insn & (1 << 11))
10051 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
10052 else
10053 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
10054 tcg_temp_free_i32(tmp);
10055 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
10056 val = (uint32_t)s->pc + 2;
10057 val += offset;
10058 gen_jmp(s, val);
10059 break;
10061 case 15: /* IT, nop-hint. */
10062 if ((insn & 0xf) == 0) {
10063 gen_nop_hint(s, (insn >> 4) & 0xf);
10064 break;
10066 /* If Then. */
10067 s->condexec_cond = (insn >> 4) & 0xe;
10068 s->condexec_mask = insn & 0x1f;
10069 /* No actual code generated for this insn, just setup state. */
10070 break;
10072 case 0xe: /* bkpt */
10073 ARCH(5);
10074 gen_exception_insn(s, 2, EXCP_BKPT);
10075 break;
10077 case 0xa: /* rev */
10078 ARCH(6);
10079 rn = (insn >> 3) & 0x7;
10080 rd = insn & 0x7;
10081 tmp = load_reg(s, rn);
10082 switch ((insn >> 6) & 3) {
10083 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
10084 case 1: gen_rev16(tmp); break;
10085 case 3: gen_revsh(tmp); break;
10086 default: goto illegal_op;
10088 store_reg(s, rd, tmp);
10089 break;
10091 case 6:
10092 switch ((insn >> 5) & 7) {
10093 case 2:
10094 /* setend */
10095 ARCH(6);
10096 if (((insn >> 3) & 1) != s->bswap_code) {
10097 /* Dynamic endianness switching not implemented. */
10098 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
10099 goto illegal_op;
10101 break;
10102 case 3:
10103 /* cps */
10104 ARCH(6);
10105 if (IS_USER(s)) {
10106 break;
10108 if (IS_M(env)) {
10109 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
10110 /* FAULTMASK */
10111 if (insn & 1) {
10112 addr = tcg_const_i32(19);
10113 gen_helper_v7m_msr(cpu_env, addr, tmp);
10114 tcg_temp_free_i32(addr);
10116 /* PRIMASK */
10117 if (insn & 2) {
10118 addr = tcg_const_i32(16);
10119 gen_helper_v7m_msr(cpu_env, addr, tmp);
10120 tcg_temp_free_i32(addr);
10122 tcg_temp_free_i32(tmp);
10123 gen_lookup_tb(s);
10124 } else {
10125 if (insn & (1 << 4)) {
10126 shift = CPSR_A | CPSR_I | CPSR_F;
10127 } else {
10128 shift = 0;
10130 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
10132 break;
10133 default:
10134 goto undef;
10136 break;
10138 default:
10139 goto undef;
10141 break;
10143 case 12:
10145 /* load/store multiple */
10146 TCGv_i32 loaded_var;
10147 TCGV_UNUSED_I32(loaded_var);
10148 rn = (insn >> 8) & 0x7;
10149 addr = load_reg(s, rn);
10150 for (i = 0; i < 8; i++) {
10151 if (insn & (1 << i)) {
10152 if (insn & (1 << 11)) {
10153 /* load */
10154 tmp = tcg_temp_new_i32();
10155 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10156 if (i == rn) {
10157 loaded_var = tmp;
10158 } else {
10159 store_reg(s, i, tmp);
10161 } else {
10162 /* store */
10163 tmp = load_reg(s, i);
10164 gen_aa32_st32(tmp, addr, IS_USER(s));
10165 tcg_temp_free_i32(tmp);
10167 /* advance to the next address */
10168 tcg_gen_addi_i32(addr, addr, 4);
10171 if ((insn & (1 << rn)) == 0) {
10172 /* base reg not in list: base register writeback */
10173 store_reg(s, rn, addr);
10174 } else {
10175 /* base reg in list: if load, complete it now */
10176 if (insn & (1 << 11)) {
10177 store_reg(s, rn, loaded_var);
10179 tcg_temp_free_i32(addr);
10181 break;
10183 case 13:
10184 /* conditional branch or swi */
10185 cond = (insn >> 8) & 0xf;
10186 if (cond == 0xe)
10187 goto undef;
10189 if (cond == 0xf) {
10190 /* swi */
10191 gen_set_pc_im(s, s->pc);
10192 s->is_jmp = DISAS_SWI;
10193 break;
10195 /* generate a conditional jump to next instruction */
10196 s->condlabel = gen_new_label();
10197 arm_gen_test_cc(cond ^ 1, s->condlabel);
10198 s->condjmp = 1;
10200 /* jump to the offset */
10201 val = (uint32_t)s->pc + 2;
10202 offset = ((int32_t)insn << 24) >> 24;
10203 val += offset << 1;
10204 gen_jmp(s, val);
10205 break;
10207 case 14:
10208 if (insn & (1 << 11)) {
10209 if (disas_thumb2_insn(env, s, insn))
10210 goto undef32;
10211 break;
10213 /* unconditional branch */
10214 val = (uint32_t)s->pc;
10215 offset = ((int32_t)insn << 21) >> 21;
10216 val += (offset << 1) + 2;
10217 gen_jmp(s, val);
10218 break;
10220 case 15:
10221 if (disas_thumb2_insn(env, s, insn))
10222 goto undef32;
10223 break;
10225 return;
10226 undef32:
10227 gen_exception_insn(s, 4, EXCP_UDEF);
10228 return;
10229 illegal_op:
10230 undef:
10231 gen_exception_insn(s, 2, EXCP_UDEF);
10234 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
10235 basic block 'tb'. If search_pc is TRUE, also generate PC
10236 information for each intermediate instruction. */
10237 static inline void gen_intermediate_code_internal(ARMCPU *cpu,
10238 TranslationBlock *tb,
10239 bool search_pc)
10241 CPUState *cs = CPU(cpu);
10242 CPUARMState *env = &cpu->env;
10243 DisasContext dc1, *dc = &dc1;
10244 CPUBreakpoint *bp;
10245 uint16_t *gen_opc_end;
10246 int j, lj;
10247 target_ulong pc_start;
10248 target_ulong next_page_start;
10249 int num_insns;
10250 int max_insns;
10252 /* generate intermediate code */
10254 /* The A64 decoder has its own top level loop, because it doesn't need
10255 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
10257 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
10258 gen_intermediate_code_internal_a64(cpu, tb, search_pc);
10259 return;
10262 pc_start = tb->pc;
10264 dc->tb = tb;
10266 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
10268 dc->is_jmp = DISAS_NEXT;
10269 dc->pc = pc_start;
10270 dc->singlestep_enabled = cs->singlestep_enabled;
10271 dc->condjmp = 0;
10273 dc->aarch64 = 0;
10274 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
10275 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
10276 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
10277 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
10278 #if !defined(CONFIG_USER_ONLY)
10279 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
10280 #endif
10281 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
10282 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
10283 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
10284 dc->cp_regs = cpu->cp_regs;
10285 dc->current_pl = arm_current_pl(env);
10287 cpu_F0s = tcg_temp_new_i32();
10288 cpu_F1s = tcg_temp_new_i32();
10289 cpu_F0d = tcg_temp_new_i64();
10290 cpu_F1d = tcg_temp_new_i64();
10291 cpu_V0 = cpu_F0d;
10292 cpu_V1 = cpu_F1d;
10293 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
10294 cpu_M0 = tcg_temp_new_i64();
10295 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
10296 lj = -1;
10297 num_insns = 0;
10298 max_insns = tb->cflags & CF_COUNT_MASK;
10299 if (max_insns == 0)
10300 max_insns = CF_COUNT_MASK;
10302 gen_tb_start();
10304 tcg_clear_temp_count();
10306 /* A note on handling of the condexec (IT) bits:
10308 * We want to avoid the overhead of having to write the updated condexec
10309 * bits back to the CPUARMState for every instruction in an IT block. So:
10310 * (1) if the condexec bits are not already zero then we write
10311 * zero back into the CPUARMState now. This avoids complications trying
10312 * to do it at the end of the block. (For example if we don't do this
10313 * it's hard to identify whether we can safely skip writing condexec
10314 * at the end of the TB, which we definitely want to do for the case
10315 * where a TB doesn't do anything with the IT state at all.)
10316 * (2) if we are going to leave the TB then we call gen_set_condexec()
10317 * which will write the correct value into CPUARMState if zero is wrong.
10318 * This is done both for leaving the TB at the end, and for leaving
10319 * it because of an exception we know will happen, which is done in
10320 * gen_exception_insn(). The latter is necessary because we need to
10321 * leave the TB with the PC/IT state just prior to execution of the
10322 * instruction which caused the exception.
10323 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
10324 * then the CPUARMState will be wrong and we need to reset it.
10325 * This is handled in the same way as restoration of the
10326 * PC in these situations: we will be called again with search_pc=1
10327 * and generate a mapping of the condexec bits for each PC in
10328 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
10329 * this to restore the condexec bits.
10331 * Note that there are no instructions which can read the condexec
10332 * bits, and none which can write non-static values to them, so
10333 * we don't need to care about whether CPUARMState is correct in the
10334 * middle of a TB.
10337 /* Reset the conditional execution bits immediately. This avoids
10338 complications trying to do it at the end of the block. */
10339 if (dc->condexec_mask || dc->condexec_cond)
10341 TCGv_i32 tmp = tcg_temp_new_i32();
10342 tcg_gen_movi_i32(tmp, 0);
10343 store_cpu_field(tmp, condexec_bits);
10345 do {
10346 #ifdef CONFIG_USER_ONLY
10347 /* Intercept jump to the magic kernel page. */
10348 if (dc->pc >= 0xffff0000) {
10349 /* We always get here via a jump, so know we are not in a
10350 conditional execution block. */
10351 gen_exception(EXCP_KERNEL_TRAP);
10352 dc->is_jmp = DISAS_UPDATE;
10353 break;
10355 #else
10356 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
10357 /* We always get here via a jump, so know we are not in a
10358 conditional execution block. */
10359 gen_exception(EXCP_EXCEPTION_EXIT);
10360 dc->is_jmp = DISAS_UPDATE;
10361 break;
10363 #endif
10365 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
10366 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
10367 if (bp->pc == dc->pc) {
10368 gen_exception_insn(dc, 0, EXCP_DEBUG);
10369 /* Advance PC so that clearing the breakpoint will
10370 invalidate this TB. */
10371 dc->pc += 2;
10372 goto done_generating;
10376 if (search_pc) {
10377 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10378 if (lj < j) {
10379 lj++;
10380 while (lj < j)
10381 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10383 tcg_ctx.gen_opc_pc[lj] = dc->pc;
10384 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
10385 tcg_ctx.gen_opc_instr_start[lj] = 1;
10386 tcg_ctx.gen_opc_icount[lj] = num_insns;
10389 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
10390 gen_io_start();
10392 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
10393 tcg_gen_debug_insn_start(dc->pc);
10396 if (dc->thumb) {
10397 disas_thumb_insn(env, dc);
10398 if (dc->condexec_mask) {
10399 dc->condexec_cond = (dc->condexec_cond & 0xe)
10400 | ((dc->condexec_mask >> 4) & 1);
10401 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
10402 if (dc->condexec_mask == 0) {
10403 dc->condexec_cond = 0;
10406 } else {
10407 disas_arm_insn(env, dc);
10410 if (dc->condjmp && !dc->is_jmp) {
10411 gen_set_label(dc->condlabel);
10412 dc->condjmp = 0;
10415 if (tcg_check_temp_count()) {
10416 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
10417 dc->pc);
10420 /* Translation stops when a conditional branch is encountered.
10421 * Otherwise the subsequent code could get translated several times.
10422 * Also stop translation when a page boundary is reached. This
10423 * ensures prefetch aborts occur at the right place. */
10424 num_insns ++;
10425 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
10426 !cs->singlestep_enabled &&
10427 !singlestep &&
10428 dc->pc < next_page_start &&
10429 num_insns < max_insns);
10431 if (tb->cflags & CF_LAST_IO) {
10432 if (dc->condjmp) {
10433 /* FIXME: This can theoretically happen with self-modifying
10434 code. */
10435 cpu_abort(env, "IO on conditional branch instruction");
10437 gen_io_end();
10440 /* At this stage dc->condjmp will only be set when the skipped
10441 instruction was a conditional branch or trap, and the PC has
10442 already been written. */
10443 if (unlikely(cs->singlestep_enabled)) {
10444 /* Make sure the pc is updated, and raise a debug exception. */
10445 if (dc->condjmp) {
10446 gen_set_condexec(dc);
10447 if (dc->is_jmp == DISAS_SWI) {
10448 gen_exception(EXCP_SWI);
10449 } else {
10450 gen_exception(EXCP_DEBUG);
10452 gen_set_label(dc->condlabel);
10454 if (dc->condjmp || !dc->is_jmp) {
10455 gen_set_pc_im(dc, dc->pc);
10456 dc->condjmp = 0;
10458 gen_set_condexec(dc);
10459 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
10460 gen_exception(EXCP_SWI);
10461 } else {
10462 /* FIXME: Single stepping a WFI insn will not halt
10463 the CPU. */
10464 gen_exception(EXCP_DEBUG);
10466 } else {
10467 /* While branches must always occur at the end of an IT block,
10468 there are a few other things that can cause us to terminate
10469 the TB in the middle of an IT block:
10470 - Exception generating instructions (bkpt, swi, undefined).
10471 - Page boundaries.
10472 - Hardware watchpoints.
10473 Hardware breakpoints have already been handled and skip this code.
10475 gen_set_condexec(dc);
10476 switch(dc->is_jmp) {
10477 case DISAS_NEXT:
10478 gen_goto_tb(dc, 1, dc->pc);
10479 break;
10480 default:
10481 case DISAS_JUMP:
10482 case DISAS_UPDATE:
10483 /* indicate that the hash table must be used to find the next TB */
10484 tcg_gen_exit_tb(0);
10485 break;
10486 case DISAS_TB_JUMP:
10487 /* nothing more to generate */
10488 break;
10489 case DISAS_WFI:
10490 gen_helper_wfi(cpu_env);
10491 break;
10492 case DISAS_SWI:
10493 gen_exception(EXCP_SWI);
10494 break;
10496 if (dc->condjmp) {
10497 gen_set_label(dc->condlabel);
10498 gen_set_condexec(dc);
10499 gen_goto_tb(dc, 1, dc->pc);
10500 dc->condjmp = 0;
10504 done_generating:
10505 gen_tb_end(tb, num_insns);
10506 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
10508 #ifdef DEBUG_DISAS
10509 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
10510 qemu_log("----------------\n");
10511 qemu_log("IN: %s\n", lookup_symbol(pc_start));
10512 log_target_disas(env, pc_start, dc->pc - pc_start,
10513 dc->thumb | (dc->bswap_code << 1));
10514 qemu_log("\n");
10516 #endif
10517 if (search_pc) {
10518 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10519 lj++;
10520 while (lj <= j)
10521 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10522 } else {
10523 tb->size = dc->pc - pc_start;
10524 tb->icount = num_insns;
10528 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
10530 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
10533 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
10535 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
10538 static const char *cpu_mode_names[16] = {
10539 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
10540 "???", "???", "???", "und", "???", "???", "???", "sys"
10543 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
10544 int flags)
10546 ARMCPU *cpu = ARM_CPU(cs);
10547 CPUARMState *env = &cpu->env;
10548 int i;
10549 uint32_t psr;
10551 for(i=0;i<16;i++) {
10552 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
10553 if ((i % 4) == 3)
10554 cpu_fprintf(f, "\n");
10555 else
10556 cpu_fprintf(f, " ");
10558 psr = cpsr_read(env);
10559 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
10560 psr,
10561 psr & (1 << 31) ? 'N' : '-',
10562 psr & (1 << 30) ? 'Z' : '-',
10563 psr & (1 << 29) ? 'C' : '-',
10564 psr & (1 << 28) ? 'V' : '-',
10565 psr & CPSR_T ? 'T' : 'A',
10566 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
10568 if (flags & CPU_DUMP_FPU) {
10569 int numvfpregs = 0;
10570 if (arm_feature(env, ARM_FEATURE_VFP)) {
10571 numvfpregs += 16;
10573 if (arm_feature(env, ARM_FEATURE_VFP3)) {
10574 numvfpregs += 16;
10576 for (i = 0; i < numvfpregs; i++) {
10577 uint64_t v = float64_val(env->vfp.regs[i]);
10578 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
10579 i * 2, (uint32_t)v,
10580 i * 2 + 1, (uint32_t)(v >> 32),
10581 i, v);
10583 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
10587 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
10589 if (is_a64(env)) {
10590 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
10591 env->condexec_bits = 0;
10592 } else {
10593 env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
10594 env->condexec_bits = gen_opc_condexec_bits[pc_pos];