target-arm: Implement ARMv8 MVFR registers
[qemu.git] / target-arm / translate.c
blobf7b5dafcb765238bedd2df3722a705dfb5a0367d
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 "internals.h"
29 #include "disas/disas.h"
30 #include "tcg-op.h"
31 #include "qemu/log.h"
32 #include "qemu/bitops.h"
34 #include "helper.h"
35 #define GEN_HELPER 1
36 #include "helper.h"
38 #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
39 #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
40 /* currently all emulated v5 cores are also v5TE, so don't bother */
41 #define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5)
42 #define ENABLE_ARCH_5J 0
43 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
44 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
45 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
46 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
47 #define ENABLE_ARCH_8 arm_feature(env, ARM_FEATURE_V8)
49 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
51 #include "translate.h"
52 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
54 #if defined(CONFIG_USER_ONLY)
55 #define IS_USER(s) 1
56 #else
57 #define IS_USER(s) (s->user)
58 #endif
60 TCGv_ptr cpu_env;
61 /* We reuse the same 64-bit temporaries for efficiency. */
62 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
63 static TCGv_i32 cpu_R[16];
64 static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
65 static TCGv_i64 cpu_exclusive_addr;
66 static TCGv_i64 cpu_exclusive_val;
67 #ifdef CONFIG_USER_ONLY
68 static TCGv_i64 cpu_exclusive_test;
69 static TCGv_i32 cpu_exclusive_info;
70 #endif
72 /* FIXME: These should be removed. */
73 static TCGv_i32 cpu_F0s, cpu_F1s;
74 static TCGv_i64 cpu_F0d, cpu_F1d;
76 #include "exec/gen-icount.h"
78 static const char *regnames[] =
79 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
80 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
82 /* initialize TCG globals. */
83 void arm_translate_init(void)
85 int i;
87 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
89 for (i = 0; i < 16; i++) {
90 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
91 offsetof(CPUARMState, regs[i]),
92 regnames[i]);
94 cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
95 cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
96 cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
97 cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
99 cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
100 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
101 cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
102 offsetof(CPUARMState, exclusive_val), "exclusive_val");
103 #ifdef CONFIG_USER_ONLY
104 cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
105 offsetof(CPUARMState, exclusive_test), "exclusive_test");
106 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
107 offsetof(CPUARMState, exclusive_info), "exclusive_info");
108 #endif
110 a64_translate_init();
113 static inline TCGv_i32 load_cpu_offset(int offset)
115 TCGv_i32 tmp = tcg_temp_new_i32();
116 tcg_gen_ld_i32(tmp, cpu_env, offset);
117 return tmp;
120 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
122 static inline void store_cpu_offset(TCGv_i32 var, int offset)
124 tcg_gen_st_i32(var, cpu_env, offset);
125 tcg_temp_free_i32(var);
128 #define store_cpu_field(var, name) \
129 store_cpu_offset(var, offsetof(CPUARMState, name))
131 /* Set a variable to the value of a CPU register. */
132 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
134 if (reg == 15) {
135 uint32_t addr;
136 /* normally, since we updated PC, we need only to add one insn */
137 if (s->thumb)
138 addr = (long)s->pc + 2;
139 else
140 addr = (long)s->pc + 4;
141 tcg_gen_movi_i32(var, addr);
142 } else {
143 tcg_gen_mov_i32(var, cpu_R[reg]);
147 /* Create a new temporary and set it to the value of a CPU register. */
148 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
150 TCGv_i32 tmp = tcg_temp_new_i32();
151 load_reg_var(s, tmp, reg);
152 return tmp;
155 /* Set a CPU register. The source must be a temporary and will be
156 marked as dead. */
157 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
159 if (reg == 15) {
160 tcg_gen_andi_i32(var, var, ~1);
161 s->is_jmp = DISAS_JUMP;
163 tcg_gen_mov_i32(cpu_R[reg], var);
164 tcg_temp_free_i32(var);
167 /* Value extensions. */
168 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
169 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
170 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
171 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
173 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
174 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
177 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
179 TCGv_i32 tmp_mask = tcg_const_i32(mask);
180 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
181 tcg_temp_free_i32(tmp_mask);
183 /* Set NZCV flags from the high 4 bits of var. */
184 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
186 static void gen_exception_internal(int excp)
188 TCGv_i32 tcg_excp = tcg_const_i32(excp);
190 assert(excp_is_internal(excp));
191 gen_helper_exception_internal(cpu_env, tcg_excp);
192 tcg_temp_free_i32(tcg_excp);
195 static void gen_exception(int excp, uint32_t syndrome)
197 TCGv_i32 tcg_excp = tcg_const_i32(excp);
198 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
200 gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn);
201 tcg_temp_free_i32(tcg_syn);
202 tcg_temp_free_i32(tcg_excp);
205 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
207 TCGv_i32 tmp1 = tcg_temp_new_i32();
208 TCGv_i32 tmp2 = tcg_temp_new_i32();
209 tcg_gen_ext16s_i32(tmp1, a);
210 tcg_gen_ext16s_i32(tmp2, b);
211 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
212 tcg_temp_free_i32(tmp2);
213 tcg_gen_sari_i32(a, a, 16);
214 tcg_gen_sari_i32(b, b, 16);
215 tcg_gen_mul_i32(b, b, a);
216 tcg_gen_mov_i32(a, tmp1);
217 tcg_temp_free_i32(tmp1);
220 /* Byteswap each halfword. */
221 static void gen_rev16(TCGv_i32 var)
223 TCGv_i32 tmp = tcg_temp_new_i32();
224 tcg_gen_shri_i32(tmp, var, 8);
225 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
226 tcg_gen_shli_i32(var, var, 8);
227 tcg_gen_andi_i32(var, var, 0xff00ff00);
228 tcg_gen_or_i32(var, var, tmp);
229 tcg_temp_free_i32(tmp);
232 /* Byteswap low halfword and sign extend. */
233 static void gen_revsh(TCGv_i32 var)
235 tcg_gen_ext16u_i32(var, var);
236 tcg_gen_bswap16_i32(var, var);
237 tcg_gen_ext16s_i32(var, var);
240 /* Unsigned bitfield extract. */
241 static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask)
243 if (shift)
244 tcg_gen_shri_i32(var, var, shift);
245 tcg_gen_andi_i32(var, var, mask);
248 /* Signed bitfield extract. */
249 static void gen_sbfx(TCGv_i32 var, int shift, int width)
251 uint32_t signbit;
253 if (shift)
254 tcg_gen_sari_i32(var, var, shift);
255 if (shift + width < 32) {
256 signbit = 1u << (width - 1);
257 tcg_gen_andi_i32(var, var, (1u << width) - 1);
258 tcg_gen_xori_i32(var, var, signbit);
259 tcg_gen_subi_i32(var, var, signbit);
263 /* Return (b << 32) + a. Mark inputs as dead */
264 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
266 TCGv_i64 tmp64 = tcg_temp_new_i64();
268 tcg_gen_extu_i32_i64(tmp64, b);
269 tcg_temp_free_i32(b);
270 tcg_gen_shli_i64(tmp64, tmp64, 32);
271 tcg_gen_add_i64(a, tmp64, a);
273 tcg_temp_free_i64(tmp64);
274 return a;
277 /* Return (b << 32) - a. Mark inputs as dead. */
278 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
280 TCGv_i64 tmp64 = tcg_temp_new_i64();
282 tcg_gen_extu_i32_i64(tmp64, b);
283 tcg_temp_free_i32(b);
284 tcg_gen_shli_i64(tmp64, tmp64, 32);
285 tcg_gen_sub_i64(a, tmp64, a);
287 tcg_temp_free_i64(tmp64);
288 return a;
291 /* 32x32->64 multiply. Marks inputs as dead. */
292 static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
294 TCGv_i32 lo = tcg_temp_new_i32();
295 TCGv_i32 hi = tcg_temp_new_i32();
296 TCGv_i64 ret;
298 tcg_gen_mulu2_i32(lo, hi, a, b);
299 tcg_temp_free_i32(a);
300 tcg_temp_free_i32(b);
302 ret = tcg_temp_new_i64();
303 tcg_gen_concat_i32_i64(ret, lo, hi);
304 tcg_temp_free_i32(lo);
305 tcg_temp_free_i32(hi);
307 return ret;
310 static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
312 TCGv_i32 lo = tcg_temp_new_i32();
313 TCGv_i32 hi = tcg_temp_new_i32();
314 TCGv_i64 ret;
316 tcg_gen_muls2_i32(lo, hi, a, b);
317 tcg_temp_free_i32(a);
318 tcg_temp_free_i32(b);
320 ret = tcg_temp_new_i64();
321 tcg_gen_concat_i32_i64(ret, lo, hi);
322 tcg_temp_free_i32(lo);
323 tcg_temp_free_i32(hi);
325 return ret;
328 /* Swap low and high halfwords. */
329 static void gen_swap_half(TCGv_i32 var)
331 TCGv_i32 tmp = tcg_temp_new_i32();
332 tcg_gen_shri_i32(tmp, var, 16);
333 tcg_gen_shli_i32(var, var, 16);
334 tcg_gen_or_i32(var, var, tmp);
335 tcg_temp_free_i32(tmp);
338 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
339 tmp = (t0 ^ t1) & 0x8000;
340 t0 &= ~0x8000;
341 t1 &= ~0x8000;
342 t0 = (t0 + t1) ^ tmp;
345 static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
347 TCGv_i32 tmp = tcg_temp_new_i32();
348 tcg_gen_xor_i32(tmp, t0, t1);
349 tcg_gen_andi_i32(tmp, tmp, 0x8000);
350 tcg_gen_andi_i32(t0, t0, ~0x8000);
351 tcg_gen_andi_i32(t1, t1, ~0x8000);
352 tcg_gen_add_i32(t0, t0, t1);
353 tcg_gen_xor_i32(t0, t0, tmp);
354 tcg_temp_free_i32(tmp);
355 tcg_temp_free_i32(t1);
358 /* Set CF to the top bit of var. */
359 static void gen_set_CF_bit31(TCGv_i32 var)
361 tcg_gen_shri_i32(cpu_CF, var, 31);
364 /* Set N and Z flags from var. */
365 static inline void gen_logic_CC(TCGv_i32 var)
367 tcg_gen_mov_i32(cpu_NF, var);
368 tcg_gen_mov_i32(cpu_ZF, var);
371 /* T0 += T1 + CF. */
372 static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
374 tcg_gen_add_i32(t0, t0, t1);
375 tcg_gen_add_i32(t0, t0, cpu_CF);
378 /* dest = T0 + T1 + CF. */
379 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
381 tcg_gen_add_i32(dest, t0, t1);
382 tcg_gen_add_i32(dest, dest, cpu_CF);
385 /* dest = T0 - T1 + CF - 1. */
386 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
388 tcg_gen_sub_i32(dest, t0, t1);
389 tcg_gen_add_i32(dest, dest, cpu_CF);
390 tcg_gen_subi_i32(dest, dest, 1);
393 /* dest = T0 + T1. Compute C, N, V and Z flags */
394 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
396 TCGv_i32 tmp = tcg_temp_new_i32();
397 tcg_gen_movi_i32(tmp, 0);
398 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
399 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
400 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
401 tcg_gen_xor_i32(tmp, t0, t1);
402 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
403 tcg_temp_free_i32(tmp);
404 tcg_gen_mov_i32(dest, cpu_NF);
407 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
408 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
410 TCGv_i32 tmp = tcg_temp_new_i32();
411 if (TCG_TARGET_HAS_add2_i32) {
412 tcg_gen_movi_i32(tmp, 0);
413 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
414 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
415 } else {
416 TCGv_i64 q0 = tcg_temp_new_i64();
417 TCGv_i64 q1 = tcg_temp_new_i64();
418 tcg_gen_extu_i32_i64(q0, t0);
419 tcg_gen_extu_i32_i64(q1, t1);
420 tcg_gen_add_i64(q0, q0, q1);
421 tcg_gen_extu_i32_i64(q1, cpu_CF);
422 tcg_gen_add_i64(q0, q0, q1);
423 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
424 tcg_temp_free_i64(q0);
425 tcg_temp_free_i64(q1);
427 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
428 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
429 tcg_gen_xor_i32(tmp, t0, t1);
430 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
431 tcg_temp_free_i32(tmp);
432 tcg_gen_mov_i32(dest, cpu_NF);
435 /* dest = T0 - T1. Compute C, N, V and Z flags */
436 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
438 TCGv_i32 tmp;
439 tcg_gen_sub_i32(cpu_NF, t0, t1);
440 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
441 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
442 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
443 tmp = tcg_temp_new_i32();
444 tcg_gen_xor_i32(tmp, t0, t1);
445 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
446 tcg_temp_free_i32(tmp);
447 tcg_gen_mov_i32(dest, cpu_NF);
450 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
451 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
453 TCGv_i32 tmp = tcg_temp_new_i32();
454 tcg_gen_not_i32(tmp, t1);
455 gen_adc_CC(dest, t0, tmp);
456 tcg_temp_free_i32(tmp);
459 #define GEN_SHIFT(name) \
460 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
462 TCGv_i32 tmp1, tmp2, tmp3; \
463 tmp1 = tcg_temp_new_i32(); \
464 tcg_gen_andi_i32(tmp1, t1, 0xff); \
465 tmp2 = tcg_const_i32(0); \
466 tmp3 = tcg_const_i32(0x1f); \
467 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
468 tcg_temp_free_i32(tmp3); \
469 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
470 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
471 tcg_temp_free_i32(tmp2); \
472 tcg_temp_free_i32(tmp1); \
474 GEN_SHIFT(shl)
475 GEN_SHIFT(shr)
476 #undef GEN_SHIFT
478 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
480 TCGv_i32 tmp1, tmp2;
481 tmp1 = tcg_temp_new_i32();
482 tcg_gen_andi_i32(tmp1, t1, 0xff);
483 tmp2 = tcg_const_i32(0x1f);
484 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
485 tcg_temp_free_i32(tmp2);
486 tcg_gen_sar_i32(dest, t0, tmp1);
487 tcg_temp_free_i32(tmp1);
490 static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
492 TCGv_i32 c0 = tcg_const_i32(0);
493 TCGv_i32 tmp = tcg_temp_new_i32();
494 tcg_gen_neg_i32(tmp, src);
495 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
496 tcg_temp_free_i32(c0);
497 tcg_temp_free_i32(tmp);
500 static void shifter_out_im(TCGv_i32 var, int shift)
502 if (shift == 0) {
503 tcg_gen_andi_i32(cpu_CF, var, 1);
504 } else {
505 tcg_gen_shri_i32(cpu_CF, var, shift);
506 if (shift != 31) {
507 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
512 /* Shift by immediate. Includes special handling for shift == 0. */
513 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
514 int shift, int flags)
516 switch (shiftop) {
517 case 0: /* LSL */
518 if (shift != 0) {
519 if (flags)
520 shifter_out_im(var, 32 - shift);
521 tcg_gen_shli_i32(var, var, shift);
523 break;
524 case 1: /* LSR */
525 if (shift == 0) {
526 if (flags) {
527 tcg_gen_shri_i32(cpu_CF, var, 31);
529 tcg_gen_movi_i32(var, 0);
530 } else {
531 if (flags)
532 shifter_out_im(var, shift - 1);
533 tcg_gen_shri_i32(var, var, shift);
535 break;
536 case 2: /* ASR */
537 if (shift == 0)
538 shift = 32;
539 if (flags)
540 shifter_out_im(var, shift - 1);
541 if (shift == 32)
542 shift = 31;
543 tcg_gen_sari_i32(var, var, shift);
544 break;
545 case 3: /* ROR/RRX */
546 if (shift != 0) {
547 if (flags)
548 shifter_out_im(var, shift - 1);
549 tcg_gen_rotri_i32(var, var, shift); break;
550 } else {
551 TCGv_i32 tmp = tcg_temp_new_i32();
552 tcg_gen_shli_i32(tmp, cpu_CF, 31);
553 if (flags)
554 shifter_out_im(var, 0);
555 tcg_gen_shri_i32(var, var, 1);
556 tcg_gen_or_i32(var, var, tmp);
557 tcg_temp_free_i32(tmp);
562 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
563 TCGv_i32 shift, int flags)
565 if (flags) {
566 switch (shiftop) {
567 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
568 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
569 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
570 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
572 } else {
573 switch (shiftop) {
574 case 0:
575 gen_shl(var, var, shift);
576 break;
577 case 1:
578 gen_shr(var, var, shift);
579 break;
580 case 2:
581 gen_sar(var, var, shift);
582 break;
583 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
584 tcg_gen_rotr_i32(var, var, shift); break;
587 tcg_temp_free_i32(shift);
590 #define PAS_OP(pfx) \
591 switch (op2) { \
592 case 0: gen_pas_helper(glue(pfx,add16)); break; \
593 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
594 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
595 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
596 case 4: gen_pas_helper(glue(pfx,add8)); break; \
597 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
599 static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
601 TCGv_ptr tmp;
603 switch (op1) {
604 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
605 case 1:
606 tmp = tcg_temp_new_ptr();
607 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
608 PAS_OP(s)
609 tcg_temp_free_ptr(tmp);
610 break;
611 case 5:
612 tmp = tcg_temp_new_ptr();
613 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
614 PAS_OP(u)
615 tcg_temp_free_ptr(tmp);
616 break;
617 #undef gen_pas_helper
618 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
619 case 2:
620 PAS_OP(q);
621 break;
622 case 3:
623 PAS_OP(sh);
624 break;
625 case 6:
626 PAS_OP(uq);
627 break;
628 case 7:
629 PAS_OP(uh);
630 break;
631 #undef gen_pas_helper
634 #undef PAS_OP
636 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
637 #define PAS_OP(pfx) \
638 switch (op1) { \
639 case 0: gen_pas_helper(glue(pfx,add8)); break; \
640 case 1: gen_pas_helper(glue(pfx,add16)); break; \
641 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
642 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
643 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
644 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
646 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
648 TCGv_ptr tmp;
650 switch (op2) {
651 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
652 case 0:
653 tmp = tcg_temp_new_ptr();
654 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
655 PAS_OP(s)
656 tcg_temp_free_ptr(tmp);
657 break;
658 case 4:
659 tmp = tcg_temp_new_ptr();
660 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
661 PAS_OP(u)
662 tcg_temp_free_ptr(tmp);
663 break;
664 #undef gen_pas_helper
665 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
666 case 1:
667 PAS_OP(q);
668 break;
669 case 2:
670 PAS_OP(sh);
671 break;
672 case 5:
673 PAS_OP(uq);
674 break;
675 case 6:
676 PAS_OP(uh);
677 break;
678 #undef gen_pas_helper
681 #undef PAS_OP
684 * generate a conditional branch based on ARM condition code cc.
685 * This is common between ARM and Aarch64 targets.
687 void arm_gen_test_cc(int cc, int label)
689 TCGv_i32 tmp;
690 int inv;
692 switch (cc) {
693 case 0: /* eq: Z */
694 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
695 break;
696 case 1: /* ne: !Z */
697 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
698 break;
699 case 2: /* cs: C */
700 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label);
701 break;
702 case 3: /* cc: !C */
703 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
704 break;
705 case 4: /* mi: N */
706 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label);
707 break;
708 case 5: /* pl: !N */
709 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label);
710 break;
711 case 6: /* vs: V */
712 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label);
713 break;
714 case 7: /* vc: !V */
715 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label);
716 break;
717 case 8: /* hi: C && !Z */
718 inv = gen_new_label();
719 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv);
720 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
721 gen_set_label(inv);
722 break;
723 case 9: /* ls: !C || Z */
724 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
725 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
726 break;
727 case 10: /* ge: N == V -> N ^ V == 0 */
728 tmp = tcg_temp_new_i32();
729 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
730 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
731 tcg_temp_free_i32(tmp);
732 break;
733 case 11: /* lt: N != V -> N ^ V != 0 */
734 tmp = tcg_temp_new_i32();
735 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
736 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
737 tcg_temp_free_i32(tmp);
738 break;
739 case 12: /* gt: !Z && N == V */
740 inv = gen_new_label();
741 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv);
742 tmp = tcg_temp_new_i32();
743 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
744 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
745 tcg_temp_free_i32(tmp);
746 gen_set_label(inv);
747 break;
748 case 13: /* le: Z || N != V */
749 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
750 tmp = tcg_temp_new_i32();
751 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
752 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
753 tcg_temp_free_i32(tmp);
754 break;
755 default:
756 fprintf(stderr, "Bad condition code 0x%x\n", cc);
757 abort();
761 static const uint8_t table_logic_cc[16] = {
762 1, /* and */
763 1, /* xor */
764 0, /* sub */
765 0, /* rsb */
766 0, /* add */
767 0, /* adc */
768 0, /* sbc */
769 0, /* rsc */
770 1, /* andl */
771 1, /* xorl */
772 0, /* cmp */
773 0, /* cmn */
774 1, /* orr */
775 1, /* mov */
776 1, /* bic */
777 1, /* mvn */
780 /* Set PC and Thumb state from an immediate address. */
781 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
783 TCGv_i32 tmp;
785 s->is_jmp = DISAS_UPDATE;
786 if (s->thumb != (addr & 1)) {
787 tmp = tcg_temp_new_i32();
788 tcg_gen_movi_i32(tmp, addr & 1);
789 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
790 tcg_temp_free_i32(tmp);
792 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
795 /* Set PC and Thumb state from var. var is marked as dead. */
796 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
798 s->is_jmp = DISAS_UPDATE;
799 tcg_gen_andi_i32(cpu_R[15], var, ~1);
800 tcg_gen_andi_i32(var, var, 1);
801 store_cpu_field(var, thumb);
804 /* Variant of store_reg which uses branch&exchange logic when storing
805 to r15 in ARM architecture v7 and above. The source must be a temporary
806 and will be marked as dead. */
807 static inline void store_reg_bx(CPUARMState *env, DisasContext *s,
808 int reg, TCGv_i32 var)
810 if (reg == 15 && ENABLE_ARCH_7) {
811 gen_bx(s, var);
812 } else {
813 store_reg(s, reg, var);
817 /* Variant of store_reg which uses branch&exchange logic when storing
818 * to r15 in ARM architecture v5T and above. This is used for storing
819 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
820 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
821 static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
822 int reg, TCGv_i32 var)
824 if (reg == 15 && ENABLE_ARCH_5) {
825 gen_bx(s, var);
826 } else {
827 store_reg(s, reg, var);
831 /* Abstractions of "generate code to do a guest load/store for
832 * AArch32", where a vaddr is always 32 bits (and is zero
833 * extended if we're a 64 bit core) and data is also
834 * 32 bits unless specifically doing a 64 bit access.
835 * These functions work like tcg_gen_qemu_{ld,st}* except
836 * that the address argument is TCGv_i32 rather than TCGv.
838 #if TARGET_LONG_BITS == 32
840 #define DO_GEN_LD(SUFF, OPC) \
841 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
843 tcg_gen_qemu_ld_i32(val, addr, index, OPC); \
846 #define DO_GEN_ST(SUFF, OPC) \
847 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
849 tcg_gen_qemu_st_i32(val, addr, index, OPC); \
852 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
854 tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
857 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
859 tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
862 #else
864 #define DO_GEN_LD(SUFF, OPC) \
865 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
867 TCGv addr64 = tcg_temp_new(); \
868 tcg_gen_extu_i32_i64(addr64, addr); \
869 tcg_gen_qemu_ld_i32(val, addr64, index, OPC); \
870 tcg_temp_free(addr64); \
873 #define DO_GEN_ST(SUFF, OPC) \
874 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
876 TCGv addr64 = tcg_temp_new(); \
877 tcg_gen_extu_i32_i64(addr64, addr); \
878 tcg_gen_qemu_st_i32(val, addr64, index, OPC); \
879 tcg_temp_free(addr64); \
882 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
884 TCGv addr64 = tcg_temp_new();
885 tcg_gen_extu_i32_i64(addr64, addr);
886 tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
887 tcg_temp_free(addr64);
890 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
892 TCGv addr64 = tcg_temp_new();
893 tcg_gen_extu_i32_i64(addr64, addr);
894 tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
895 tcg_temp_free(addr64);
898 #endif
900 DO_GEN_LD(8s, MO_SB)
901 DO_GEN_LD(8u, MO_UB)
902 DO_GEN_LD(16s, MO_TESW)
903 DO_GEN_LD(16u, MO_TEUW)
904 DO_GEN_LD(32u, MO_TEUL)
905 DO_GEN_ST(8, MO_UB)
906 DO_GEN_ST(16, MO_TEUW)
907 DO_GEN_ST(32, MO_TEUL)
909 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
911 tcg_gen_movi_i32(cpu_R[15], val);
914 static inline void
915 gen_set_condexec (DisasContext *s)
917 if (s->condexec_mask) {
918 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
919 TCGv_i32 tmp = tcg_temp_new_i32();
920 tcg_gen_movi_i32(tmp, val);
921 store_cpu_field(tmp, condexec_bits);
925 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
927 gen_set_condexec(s);
928 gen_set_pc_im(s, s->pc - offset);
929 gen_exception_internal(excp);
930 s->is_jmp = DISAS_JUMP;
933 static void gen_exception_insn(DisasContext *s, int offset, int excp, int syn)
935 gen_set_condexec(s);
936 gen_set_pc_im(s, s->pc - offset);
937 gen_exception(excp, syn);
938 s->is_jmp = DISAS_JUMP;
941 /* Force a TB lookup after an instruction that changes the CPU state. */
942 static inline void gen_lookup_tb(DisasContext *s)
944 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
945 s->is_jmp = DISAS_UPDATE;
948 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
949 TCGv_i32 var)
951 int val, rm, shift, shiftop;
952 TCGv_i32 offset;
954 if (!(insn & (1 << 25))) {
955 /* immediate */
956 val = insn & 0xfff;
957 if (!(insn & (1 << 23)))
958 val = -val;
959 if (val != 0)
960 tcg_gen_addi_i32(var, var, val);
961 } else {
962 /* shift/register */
963 rm = (insn) & 0xf;
964 shift = (insn >> 7) & 0x1f;
965 shiftop = (insn >> 5) & 3;
966 offset = load_reg(s, rm);
967 gen_arm_shift_im(offset, shiftop, shift, 0);
968 if (!(insn & (1 << 23)))
969 tcg_gen_sub_i32(var, var, offset);
970 else
971 tcg_gen_add_i32(var, var, offset);
972 tcg_temp_free_i32(offset);
976 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
977 int extra, TCGv_i32 var)
979 int val, rm;
980 TCGv_i32 offset;
982 if (insn & (1 << 22)) {
983 /* immediate */
984 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
985 if (!(insn & (1 << 23)))
986 val = -val;
987 val += extra;
988 if (val != 0)
989 tcg_gen_addi_i32(var, var, val);
990 } else {
991 /* register */
992 if (extra)
993 tcg_gen_addi_i32(var, var, extra);
994 rm = (insn) & 0xf;
995 offset = load_reg(s, rm);
996 if (!(insn & (1 << 23)))
997 tcg_gen_sub_i32(var, var, offset);
998 else
999 tcg_gen_add_i32(var, var, offset);
1000 tcg_temp_free_i32(offset);
1004 static TCGv_ptr get_fpstatus_ptr(int neon)
1006 TCGv_ptr statusptr = tcg_temp_new_ptr();
1007 int offset;
1008 if (neon) {
1009 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1010 } else {
1011 offset = offsetof(CPUARMState, vfp.fp_status);
1013 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1014 return statusptr;
1017 #define VFP_OP2(name) \
1018 static inline void gen_vfp_##name(int dp) \
1020 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1021 if (dp) { \
1022 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1023 } else { \
1024 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1026 tcg_temp_free_ptr(fpst); \
1029 VFP_OP2(add)
1030 VFP_OP2(sub)
1031 VFP_OP2(mul)
1032 VFP_OP2(div)
1034 #undef VFP_OP2
1036 static inline void gen_vfp_F1_mul(int dp)
1038 /* Like gen_vfp_mul() but put result in F1 */
1039 TCGv_ptr fpst = get_fpstatus_ptr(0);
1040 if (dp) {
1041 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1042 } else {
1043 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1045 tcg_temp_free_ptr(fpst);
1048 static inline void gen_vfp_F1_neg(int dp)
1050 /* Like gen_vfp_neg() but put result in F1 */
1051 if (dp) {
1052 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1053 } else {
1054 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1058 static inline void gen_vfp_abs(int dp)
1060 if (dp)
1061 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1062 else
1063 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1066 static inline void gen_vfp_neg(int dp)
1068 if (dp)
1069 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1070 else
1071 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1074 static inline void gen_vfp_sqrt(int dp)
1076 if (dp)
1077 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1078 else
1079 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1082 static inline void gen_vfp_cmp(int dp)
1084 if (dp)
1085 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1086 else
1087 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1090 static inline void gen_vfp_cmpe(int dp)
1092 if (dp)
1093 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1094 else
1095 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1098 static inline void gen_vfp_F1_ld0(int dp)
1100 if (dp)
1101 tcg_gen_movi_i64(cpu_F1d, 0);
1102 else
1103 tcg_gen_movi_i32(cpu_F1s, 0);
1106 #define VFP_GEN_ITOF(name) \
1107 static inline void gen_vfp_##name(int dp, int neon) \
1109 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1110 if (dp) { \
1111 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1112 } else { \
1113 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1115 tcg_temp_free_ptr(statusptr); \
1118 VFP_GEN_ITOF(uito)
1119 VFP_GEN_ITOF(sito)
1120 #undef VFP_GEN_ITOF
1122 #define VFP_GEN_FTOI(name) \
1123 static inline void gen_vfp_##name(int dp, int neon) \
1125 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1126 if (dp) { \
1127 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1128 } else { \
1129 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1131 tcg_temp_free_ptr(statusptr); \
1134 VFP_GEN_FTOI(toui)
1135 VFP_GEN_FTOI(touiz)
1136 VFP_GEN_FTOI(tosi)
1137 VFP_GEN_FTOI(tosiz)
1138 #undef VFP_GEN_FTOI
1140 #define VFP_GEN_FIX(name, round) \
1141 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1143 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1144 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1145 if (dp) { \
1146 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1147 statusptr); \
1148 } else { \
1149 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1150 statusptr); \
1152 tcg_temp_free_i32(tmp_shift); \
1153 tcg_temp_free_ptr(statusptr); \
1155 VFP_GEN_FIX(tosh, _round_to_zero)
1156 VFP_GEN_FIX(tosl, _round_to_zero)
1157 VFP_GEN_FIX(touh, _round_to_zero)
1158 VFP_GEN_FIX(toul, _round_to_zero)
1159 VFP_GEN_FIX(shto, )
1160 VFP_GEN_FIX(slto, )
1161 VFP_GEN_FIX(uhto, )
1162 VFP_GEN_FIX(ulto, )
1163 #undef VFP_GEN_FIX
1165 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1167 if (dp) {
1168 gen_aa32_ld64(cpu_F0d, addr, IS_USER(s));
1169 } else {
1170 gen_aa32_ld32u(cpu_F0s, addr, IS_USER(s));
1174 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1176 if (dp) {
1177 gen_aa32_st64(cpu_F0d, addr, IS_USER(s));
1178 } else {
1179 gen_aa32_st32(cpu_F0s, addr, IS_USER(s));
1183 static inline long
1184 vfp_reg_offset (int dp, int reg)
1186 if (dp)
1187 return offsetof(CPUARMState, vfp.regs[reg]);
1188 else if (reg & 1) {
1189 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1190 + offsetof(CPU_DoubleU, l.upper);
1191 } else {
1192 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1193 + offsetof(CPU_DoubleU, l.lower);
1197 /* Return the offset of a 32-bit piece of a NEON register.
1198 zero is the least significant end of the register. */
1199 static inline long
1200 neon_reg_offset (int reg, int n)
1202 int sreg;
1203 sreg = reg * 2 + n;
1204 return vfp_reg_offset(0, sreg);
1207 static TCGv_i32 neon_load_reg(int reg, int pass)
1209 TCGv_i32 tmp = tcg_temp_new_i32();
1210 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1211 return tmp;
1214 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1216 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1217 tcg_temp_free_i32(var);
1220 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1222 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1225 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1227 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1230 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1231 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1232 #define tcg_gen_st_f32 tcg_gen_st_i32
1233 #define tcg_gen_st_f64 tcg_gen_st_i64
1235 static inline void gen_mov_F0_vreg(int dp, int reg)
1237 if (dp)
1238 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1239 else
1240 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1243 static inline void gen_mov_F1_vreg(int dp, int reg)
1245 if (dp)
1246 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1247 else
1248 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1251 static inline void gen_mov_vreg_F0(int dp, int reg)
1253 if (dp)
1254 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1255 else
1256 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1259 #define ARM_CP_RW_BIT (1 << 20)
1261 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1263 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1266 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1268 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1271 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1273 TCGv_i32 var = tcg_temp_new_i32();
1274 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1275 return var;
1278 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1280 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1281 tcg_temp_free_i32(var);
1284 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1286 iwmmxt_store_reg(cpu_M0, rn);
1289 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1291 iwmmxt_load_reg(cpu_M0, rn);
1294 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1296 iwmmxt_load_reg(cpu_V1, rn);
1297 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1300 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1302 iwmmxt_load_reg(cpu_V1, rn);
1303 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1306 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1308 iwmmxt_load_reg(cpu_V1, rn);
1309 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1312 #define IWMMXT_OP(name) \
1313 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1315 iwmmxt_load_reg(cpu_V1, rn); \
1316 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1319 #define IWMMXT_OP_ENV(name) \
1320 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1322 iwmmxt_load_reg(cpu_V1, rn); \
1323 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1326 #define IWMMXT_OP_ENV_SIZE(name) \
1327 IWMMXT_OP_ENV(name##b) \
1328 IWMMXT_OP_ENV(name##w) \
1329 IWMMXT_OP_ENV(name##l)
1331 #define IWMMXT_OP_ENV1(name) \
1332 static inline void gen_op_iwmmxt_##name##_M0(void) \
1334 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1337 IWMMXT_OP(maddsq)
1338 IWMMXT_OP(madduq)
1339 IWMMXT_OP(sadb)
1340 IWMMXT_OP(sadw)
1341 IWMMXT_OP(mulslw)
1342 IWMMXT_OP(mulshw)
1343 IWMMXT_OP(mululw)
1344 IWMMXT_OP(muluhw)
1345 IWMMXT_OP(macsw)
1346 IWMMXT_OP(macuw)
1348 IWMMXT_OP_ENV_SIZE(unpackl)
1349 IWMMXT_OP_ENV_SIZE(unpackh)
1351 IWMMXT_OP_ENV1(unpacklub)
1352 IWMMXT_OP_ENV1(unpackluw)
1353 IWMMXT_OP_ENV1(unpacklul)
1354 IWMMXT_OP_ENV1(unpackhub)
1355 IWMMXT_OP_ENV1(unpackhuw)
1356 IWMMXT_OP_ENV1(unpackhul)
1357 IWMMXT_OP_ENV1(unpacklsb)
1358 IWMMXT_OP_ENV1(unpacklsw)
1359 IWMMXT_OP_ENV1(unpacklsl)
1360 IWMMXT_OP_ENV1(unpackhsb)
1361 IWMMXT_OP_ENV1(unpackhsw)
1362 IWMMXT_OP_ENV1(unpackhsl)
1364 IWMMXT_OP_ENV_SIZE(cmpeq)
1365 IWMMXT_OP_ENV_SIZE(cmpgtu)
1366 IWMMXT_OP_ENV_SIZE(cmpgts)
1368 IWMMXT_OP_ENV_SIZE(mins)
1369 IWMMXT_OP_ENV_SIZE(minu)
1370 IWMMXT_OP_ENV_SIZE(maxs)
1371 IWMMXT_OP_ENV_SIZE(maxu)
1373 IWMMXT_OP_ENV_SIZE(subn)
1374 IWMMXT_OP_ENV_SIZE(addn)
1375 IWMMXT_OP_ENV_SIZE(subu)
1376 IWMMXT_OP_ENV_SIZE(addu)
1377 IWMMXT_OP_ENV_SIZE(subs)
1378 IWMMXT_OP_ENV_SIZE(adds)
1380 IWMMXT_OP_ENV(avgb0)
1381 IWMMXT_OP_ENV(avgb1)
1382 IWMMXT_OP_ENV(avgw0)
1383 IWMMXT_OP_ENV(avgw1)
1385 IWMMXT_OP(msadb)
1387 IWMMXT_OP_ENV(packuw)
1388 IWMMXT_OP_ENV(packul)
1389 IWMMXT_OP_ENV(packuq)
1390 IWMMXT_OP_ENV(packsw)
1391 IWMMXT_OP_ENV(packsl)
1392 IWMMXT_OP_ENV(packsq)
1394 static void gen_op_iwmmxt_set_mup(void)
1396 TCGv_i32 tmp;
1397 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1398 tcg_gen_ori_i32(tmp, tmp, 2);
1399 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1402 static void gen_op_iwmmxt_set_cup(void)
1404 TCGv_i32 tmp;
1405 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1406 tcg_gen_ori_i32(tmp, tmp, 1);
1407 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1410 static void gen_op_iwmmxt_setpsr_nz(void)
1412 TCGv_i32 tmp = tcg_temp_new_i32();
1413 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1414 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1417 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1419 iwmmxt_load_reg(cpu_V1, rn);
1420 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1421 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1424 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1425 TCGv_i32 dest)
1427 int rd;
1428 uint32_t offset;
1429 TCGv_i32 tmp;
1431 rd = (insn >> 16) & 0xf;
1432 tmp = load_reg(s, rd);
1434 offset = (insn & 0xff) << ((insn >> 7) & 2);
1435 if (insn & (1 << 24)) {
1436 /* Pre indexed */
1437 if (insn & (1 << 23))
1438 tcg_gen_addi_i32(tmp, tmp, offset);
1439 else
1440 tcg_gen_addi_i32(tmp, tmp, -offset);
1441 tcg_gen_mov_i32(dest, tmp);
1442 if (insn & (1 << 21))
1443 store_reg(s, rd, tmp);
1444 else
1445 tcg_temp_free_i32(tmp);
1446 } else if (insn & (1 << 21)) {
1447 /* Post indexed */
1448 tcg_gen_mov_i32(dest, tmp);
1449 if (insn & (1 << 23))
1450 tcg_gen_addi_i32(tmp, tmp, offset);
1451 else
1452 tcg_gen_addi_i32(tmp, tmp, -offset);
1453 store_reg(s, rd, tmp);
1454 } else if (!(insn & (1 << 23)))
1455 return 1;
1456 return 0;
1459 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1461 int rd = (insn >> 0) & 0xf;
1462 TCGv_i32 tmp;
1464 if (insn & (1 << 8)) {
1465 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1466 return 1;
1467 } else {
1468 tmp = iwmmxt_load_creg(rd);
1470 } else {
1471 tmp = tcg_temp_new_i32();
1472 iwmmxt_load_reg(cpu_V0, rd);
1473 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1475 tcg_gen_andi_i32(tmp, tmp, mask);
1476 tcg_gen_mov_i32(dest, tmp);
1477 tcg_temp_free_i32(tmp);
1478 return 0;
1481 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1482 (ie. an undefined instruction). */
1483 static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
1485 int rd, wrd;
1486 int rdhi, rdlo, rd0, rd1, i;
1487 TCGv_i32 addr;
1488 TCGv_i32 tmp, tmp2, tmp3;
1490 if ((insn & 0x0e000e00) == 0x0c000000) {
1491 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1492 wrd = insn & 0xf;
1493 rdlo = (insn >> 12) & 0xf;
1494 rdhi = (insn >> 16) & 0xf;
1495 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1496 iwmmxt_load_reg(cpu_V0, wrd);
1497 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1498 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1499 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1500 } else { /* TMCRR */
1501 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1502 iwmmxt_store_reg(cpu_V0, wrd);
1503 gen_op_iwmmxt_set_mup();
1505 return 0;
1508 wrd = (insn >> 12) & 0xf;
1509 addr = tcg_temp_new_i32();
1510 if (gen_iwmmxt_address(s, insn, addr)) {
1511 tcg_temp_free_i32(addr);
1512 return 1;
1514 if (insn & ARM_CP_RW_BIT) {
1515 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1516 tmp = tcg_temp_new_i32();
1517 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1518 iwmmxt_store_creg(wrd, tmp);
1519 } else {
1520 i = 1;
1521 if (insn & (1 << 8)) {
1522 if (insn & (1 << 22)) { /* WLDRD */
1523 gen_aa32_ld64(cpu_M0, addr, IS_USER(s));
1524 i = 0;
1525 } else { /* WLDRW wRd */
1526 tmp = tcg_temp_new_i32();
1527 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1529 } else {
1530 tmp = tcg_temp_new_i32();
1531 if (insn & (1 << 22)) { /* WLDRH */
1532 gen_aa32_ld16u(tmp, addr, IS_USER(s));
1533 } else { /* WLDRB */
1534 gen_aa32_ld8u(tmp, addr, IS_USER(s));
1537 if (i) {
1538 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1539 tcg_temp_free_i32(tmp);
1541 gen_op_iwmmxt_movq_wRn_M0(wrd);
1543 } else {
1544 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1545 tmp = iwmmxt_load_creg(wrd);
1546 gen_aa32_st32(tmp, addr, IS_USER(s));
1547 } else {
1548 gen_op_iwmmxt_movq_M0_wRn(wrd);
1549 tmp = tcg_temp_new_i32();
1550 if (insn & (1 << 8)) {
1551 if (insn & (1 << 22)) { /* WSTRD */
1552 gen_aa32_st64(cpu_M0, addr, IS_USER(s));
1553 } else { /* WSTRW wRd */
1554 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1555 gen_aa32_st32(tmp, addr, IS_USER(s));
1557 } else {
1558 if (insn & (1 << 22)) { /* WSTRH */
1559 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1560 gen_aa32_st16(tmp, addr, IS_USER(s));
1561 } else { /* WSTRB */
1562 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1563 gen_aa32_st8(tmp, addr, IS_USER(s));
1567 tcg_temp_free_i32(tmp);
1569 tcg_temp_free_i32(addr);
1570 return 0;
1573 if ((insn & 0x0f000000) != 0x0e000000)
1574 return 1;
1576 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1577 case 0x000: /* WOR */
1578 wrd = (insn >> 12) & 0xf;
1579 rd0 = (insn >> 0) & 0xf;
1580 rd1 = (insn >> 16) & 0xf;
1581 gen_op_iwmmxt_movq_M0_wRn(rd0);
1582 gen_op_iwmmxt_orq_M0_wRn(rd1);
1583 gen_op_iwmmxt_setpsr_nz();
1584 gen_op_iwmmxt_movq_wRn_M0(wrd);
1585 gen_op_iwmmxt_set_mup();
1586 gen_op_iwmmxt_set_cup();
1587 break;
1588 case 0x011: /* TMCR */
1589 if (insn & 0xf)
1590 return 1;
1591 rd = (insn >> 12) & 0xf;
1592 wrd = (insn >> 16) & 0xf;
1593 switch (wrd) {
1594 case ARM_IWMMXT_wCID:
1595 case ARM_IWMMXT_wCASF:
1596 break;
1597 case ARM_IWMMXT_wCon:
1598 gen_op_iwmmxt_set_cup();
1599 /* Fall through. */
1600 case ARM_IWMMXT_wCSSF:
1601 tmp = iwmmxt_load_creg(wrd);
1602 tmp2 = load_reg(s, rd);
1603 tcg_gen_andc_i32(tmp, tmp, tmp2);
1604 tcg_temp_free_i32(tmp2);
1605 iwmmxt_store_creg(wrd, tmp);
1606 break;
1607 case ARM_IWMMXT_wCGR0:
1608 case ARM_IWMMXT_wCGR1:
1609 case ARM_IWMMXT_wCGR2:
1610 case ARM_IWMMXT_wCGR3:
1611 gen_op_iwmmxt_set_cup();
1612 tmp = load_reg(s, rd);
1613 iwmmxt_store_creg(wrd, tmp);
1614 break;
1615 default:
1616 return 1;
1618 break;
1619 case 0x100: /* WXOR */
1620 wrd = (insn >> 12) & 0xf;
1621 rd0 = (insn >> 0) & 0xf;
1622 rd1 = (insn >> 16) & 0xf;
1623 gen_op_iwmmxt_movq_M0_wRn(rd0);
1624 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1625 gen_op_iwmmxt_setpsr_nz();
1626 gen_op_iwmmxt_movq_wRn_M0(wrd);
1627 gen_op_iwmmxt_set_mup();
1628 gen_op_iwmmxt_set_cup();
1629 break;
1630 case 0x111: /* TMRC */
1631 if (insn & 0xf)
1632 return 1;
1633 rd = (insn >> 12) & 0xf;
1634 wrd = (insn >> 16) & 0xf;
1635 tmp = iwmmxt_load_creg(wrd);
1636 store_reg(s, rd, tmp);
1637 break;
1638 case 0x300: /* WANDN */
1639 wrd = (insn >> 12) & 0xf;
1640 rd0 = (insn >> 0) & 0xf;
1641 rd1 = (insn >> 16) & 0xf;
1642 gen_op_iwmmxt_movq_M0_wRn(rd0);
1643 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1644 gen_op_iwmmxt_andq_M0_wRn(rd1);
1645 gen_op_iwmmxt_setpsr_nz();
1646 gen_op_iwmmxt_movq_wRn_M0(wrd);
1647 gen_op_iwmmxt_set_mup();
1648 gen_op_iwmmxt_set_cup();
1649 break;
1650 case 0x200: /* WAND */
1651 wrd = (insn >> 12) & 0xf;
1652 rd0 = (insn >> 0) & 0xf;
1653 rd1 = (insn >> 16) & 0xf;
1654 gen_op_iwmmxt_movq_M0_wRn(rd0);
1655 gen_op_iwmmxt_andq_M0_wRn(rd1);
1656 gen_op_iwmmxt_setpsr_nz();
1657 gen_op_iwmmxt_movq_wRn_M0(wrd);
1658 gen_op_iwmmxt_set_mup();
1659 gen_op_iwmmxt_set_cup();
1660 break;
1661 case 0x810: case 0xa10: /* WMADD */
1662 wrd = (insn >> 12) & 0xf;
1663 rd0 = (insn >> 0) & 0xf;
1664 rd1 = (insn >> 16) & 0xf;
1665 gen_op_iwmmxt_movq_M0_wRn(rd0);
1666 if (insn & (1 << 21))
1667 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1668 else
1669 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1670 gen_op_iwmmxt_movq_wRn_M0(wrd);
1671 gen_op_iwmmxt_set_mup();
1672 break;
1673 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1674 wrd = (insn >> 12) & 0xf;
1675 rd0 = (insn >> 16) & 0xf;
1676 rd1 = (insn >> 0) & 0xf;
1677 gen_op_iwmmxt_movq_M0_wRn(rd0);
1678 switch ((insn >> 22) & 3) {
1679 case 0:
1680 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1681 break;
1682 case 1:
1683 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1684 break;
1685 case 2:
1686 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1687 break;
1688 case 3:
1689 return 1;
1691 gen_op_iwmmxt_movq_wRn_M0(wrd);
1692 gen_op_iwmmxt_set_mup();
1693 gen_op_iwmmxt_set_cup();
1694 break;
1695 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1696 wrd = (insn >> 12) & 0xf;
1697 rd0 = (insn >> 16) & 0xf;
1698 rd1 = (insn >> 0) & 0xf;
1699 gen_op_iwmmxt_movq_M0_wRn(rd0);
1700 switch ((insn >> 22) & 3) {
1701 case 0:
1702 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1703 break;
1704 case 1:
1705 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1706 break;
1707 case 2:
1708 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1709 break;
1710 case 3:
1711 return 1;
1713 gen_op_iwmmxt_movq_wRn_M0(wrd);
1714 gen_op_iwmmxt_set_mup();
1715 gen_op_iwmmxt_set_cup();
1716 break;
1717 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1718 wrd = (insn >> 12) & 0xf;
1719 rd0 = (insn >> 16) & 0xf;
1720 rd1 = (insn >> 0) & 0xf;
1721 gen_op_iwmmxt_movq_M0_wRn(rd0);
1722 if (insn & (1 << 22))
1723 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1724 else
1725 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1726 if (!(insn & (1 << 20)))
1727 gen_op_iwmmxt_addl_M0_wRn(wrd);
1728 gen_op_iwmmxt_movq_wRn_M0(wrd);
1729 gen_op_iwmmxt_set_mup();
1730 break;
1731 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1732 wrd = (insn >> 12) & 0xf;
1733 rd0 = (insn >> 16) & 0xf;
1734 rd1 = (insn >> 0) & 0xf;
1735 gen_op_iwmmxt_movq_M0_wRn(rd0);
1736 if (insn & (1 << 21)) {
1737 if (insn & (1 << 20))
1738 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1739 else
1740 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1741 } else {
1742 if (insn & (1 << 20))
1743 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1744 else
1745 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1747 gen_op_iwmmxt_movq_wRn_M0(wrd);
1748 gen_op_iwmmxt_set_mup();
1749 break;
1750 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1751 wrd = (insn >> 12) & 0xf;
1752 rd0 = (insn >> 16) & 0xf;
1753 rd1 = (insn >> 0) & 0xf;
1754 gen_op_iwmmxt_movq_M0_wRn(rd0);
1755 if (insn & (1 << 21))
1756 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1757 else
1758 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1759 if (!(insn & (1 << 20))) {
1760 iwmmxt_load_reg(cpu_V1, wrd);
1761 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1763 gen_op_iwmmxt_movq_wRn_M0(wrd);
1764 gen_op_iwmmxt_set_mup();
1765 break;
1766 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1767 wrd = (insn >> 12) & 0xf;
1768 rd0 = (insn >> 16) & 0xf;
1769 rd1 = (insn >> 0) & 0xf;
1770 gen_op_iwmmxt_movq_M0_wRn(rd0);
1771 switch ((insn >> 22) & 3) {
1772 case 0:
1773 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1774 break;
1775 case 1:
1776 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1777 break;
1778 case 2:
1779 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1780 break;
1781 case 3:
1782 return 1;
1784 gen_op_iwmmxt_movq_wRn_M0(wrd);
1785 gen_op_iwmmxt_set_mup();
1786 gen_op_iwmmxt_set_cup();
1787 break;
1788 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1789 wrd = (insn >> 12) & 0xf;
1790 rd0 = (insn >> 16) & 0xf;
1791 rd1 = (insn >> 0) & 0xf;
1792 gen_op_iwmmxt_movq_M0_wRn(rd0);
1793 if (insn & (1 << 22)) {
1794 if (insn & (1 << 20))
1795 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1796 else
1797 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1798 } else {
1799 if (insn & (1 << 20))
1800 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1801 else
1802 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1804 gen_op_iwmmxt_movq_wRn_M0(wrd);
1805 gen_op_iwmmxt_set_mup();
1806 gen_op_iwmmxt_set_cup();
1807 break;
1808 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1809 wrd = (insn >> 12) & 0xf;
1810 rd0 = (insn >> 16) & 0xf;
1811 rd1 = (insn >> 0) & 0xf;
1812 gen_op_iwmmxt_movq_M0_wRn(rd0);
1813 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1814 tcg_gen_andi_i32(tmp, tmp, 7);
1815 iwmmxt_load_reg(cpu_V1, rd1);
1816 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1817 tcg_temp_free_i32(tmp);
1818 gen_op_iwmmxt_movq_wRn_M0(wrd);
1819 gen_op_iwmmxt_set_mup();
1820 break;
1821 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1822 if (((insn >> 6) & 3) == 3)
1823 return 1;
1824 rd = (insn >> 12) & 0xf;
1825 wrd = (insn >> 16) & 0xf;
1826 tmp = load_reg(s, rd);
1827 gen_op_iwmmxt_movq_M0_wRn(wrd);
1828 switch ((insn >> 6) & 3) {
1829 case 0:
1830 tmp2 = tcg_const_i32(0xff);
1831 tmp3 = tcg_const_i32((insn & 7) << 3);
1832 break;
1833 case 1:
1834 tmp2 = tcg_const_i32(0xffff);
1835 tmp3 = tcg_const_i32((insn & 3) << 4);
1836 break;
1837 case 2:
1838 tmp2 = tcg_const_i32(0xffffffff);
1839 tmp3 = tcg_const_i32((insn & 1) << 5);
1840 break;
1841 default:
1842 TCGV_UNUSED_I32(tmp2);
1843 TCGV_UNUSED_I32(tmp3);
1845 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1846 tcg_temp_free_i32(tmp3);
1847 tcg_temp_free_i32(tmp2);
1848 tcg_temp_free_i32(tmp);
1849 gen_op_iwmmxt_movq_wRn_M0(wrd);
1850 gen_op_iwmmxt_set_mup();
1851 break;
1852 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1853 rd = (insn >> 12) & 0xf;
1854 wrd = (insn >> 16) & 0xf;
1855 if (rd == 15 || ((insn >> 22) & 3) == 3)
1856 return 1;
1857 gen_op_iwmmxt_movq_M0_wRn(wrd);
1858 tmp = tcg_temp_new_i32();
1859 switch ((insn >> 22) & 3) {
1860 case 0:
1861 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1862 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1863 if (insn & 8) {
1864 tcg_gen_ext8s_i32(tmp, tmp);
1865 } else {
1866 tcg_gen_andi_i32(tmp, tmp, 0xff);
1868 break;
1869 case 1:
1870 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1871 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1872 if (insn & 8) {
1873 tcg_gen_ext16s_i32(tmp, tmp);
1874 } else {
1875 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1877 break;
1878 case 2:
1879 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1880 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1881 break;
1883 store_reg(s, rd, tmp);
1884 break;
1885 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1886 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1887 return 1;
1888 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1889 switch ((insn >> 22) & 3) {
1890 case 0:
1891 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1892 break;
1893 case 1:
1894 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1895 break;
1896 case 2:
1897 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1898 break;
1900 tcg_gen_shli_i32(tmp, tmp, 28);
1901 gen_set_nzcv(tmp);
1902 tcg_temp_free_i32(tmp);
1903 break;
1904 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1905 if (((insn >> 6) & 3) == 3)
1906 return 1;
1907 rd = (insn >> 12) & 0xf;
1908 wrd = (insn >> 16) & 0xf;
1909 tmp = load_reg(s, rd);
1910 switch ((insn >> 6) & 3) {
1911 case 0:
1912 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1913 break;
1914 case 1:
1915 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1916 break;
1917 case 2:
1918 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1919 break;
1921 tcg_temp_free_i32(tmp);
1922 gen_op_iwmmxt_movq_wRn_M0(wrd);
1923 gen_op_iwmmxt_set_mup();
1924 break;
1925 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1926 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1927 return 1;
1928 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1929 tmp2 = tcg_temp_new_i32();
1930 tcg_gen_mov_i32(tmp2, tmp);
1931 switch ((insn >> 22) & 3) {
1932 case 0:
1933 for (i = 0; i < 7; i ++) {
1934 tcg_gen_shli_i32(tmp2, tmp2, 4);
1935 tcg_gen_and_i32(tmp, tmp, tmp2);
1937 break;
1938 case 1:
1939 for (i = 0; i < 3; i ++) {
1940 tcg_gen_shli_i32(tmp2, tmp2, 8);
1941 tcg_gen_and_i32(tmp, tmp, tmp2);
1943 break;
1944 case 2:
1945 tcg_gen_shli_i32(tmp2, tmp2, 16);
1946 tcg_gen_and_i32(tmp, tmp, tmp2);
1947 break;
1949 gen_set_nzcv(tmp);
1950 tcg_temp_free_i32(tmp2);
1951 tcg_temp_free_i32(tmp);
1952 break;
1953 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1954 wrd = (insn >> 12) & 0xf;
1955 rd0 = (insn >> 16) & 0xf;
1956 gen_op_iwmmxt_movq_M0_wRn(rd0);
1957 switch ((insn >> 22) & 3) {
1958 case 0:
1959 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1960 break;
1961 case 1:
1962 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1963 break;
1964 case 2:
1965 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1966 break;
1967 case 3:
1968 return 1;
1970 gen_op_iwmmxt_movq_wRn_M0(wrd);
1971 gen_op_iwmmxt_set_mup();
1972 break;
1973 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1974 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1975 return 1;
1976 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1977 tmp2 = tcg_temp_new_i32();
1978 tcg_gen_mov_i32(tmp2, tmp);
1979 switch ((insn >> 22) & 3) {
1980 case 0:
1981 for (i = 0; i < 7; i ++) {
1982 tcg_gen_shli_i32(tmp2, tmp2, 4);
1983 tcg_gen_or_i32(tmp, tmp, tmp2);
1985 break;
1986 case 1:
1987 for (i = 0; i < 3; i ++) {
1988 tcg_gen_shli_i32(tmp2, tmp2, 8);
1989 tcg_gen_or_i32(tmp, tmp, tmp2);
1991 break;
1992 case 2:
1993 tcg_gen_shli_i32(tmp2, tmp2, 16);
1994 tcg_gen_or_i32(tmp, tmp, tmp2);
1995 break;
1997 gen_set_nzcv(tmp);
1998 tcg_temp_free_i32(tmp2);
1999 tcg_temp_free_i32(tmp);
2000 break;
2001 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2002 rd = (insn >> 12) & 0xf;
2003 rd0 = (insn >> 16) & 0xf;
2004 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2005 return 1;
2006 gen_op_iwmmxt_movq_M0_wRn(rd0);
2007 tmp = tcg_temp_new_i32();
2008 switch ((insn >> 22) & 3) {
2009 case 0:
2010 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2011 break;
2012 case 1:
2013 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2014 break;
2015 case 2:
2016 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2017 break;
2019 store_reg(s, rd, tmp);
2020 break;
2021 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2022 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2023 wrd = (insn >> 12) & 0xf;
2024 rd0 = (insn >> 16) & 0xf;
2025 rd1 = (insn >> 0) & 0xf;
2026 gen_op_iwmmxt_movq_M0_wRn(rd0);
2027 switch ((insn >> 22) & 3) {
2028 case 0:
2029 if (insn & (1 << 21))
2030 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2031 else
2032 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2033 break;
2034 case 1:
2035 if (insn & (1 << 21))
2036 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2037 else
2038 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2039 break;
2040 case 2:
2041 if (insn & (1 << 21))
2042 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2043 else
2044 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2045 break;
2046 case 3:
2047 return 1;
2049 gen_op_iwmmxt_movq_wRn_M0(wrd);
2050 gen_op_iwmmxt_set_mup();
2051 gen_op_iwmmxt_set_cup();
2052 break;
2053 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2054 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2055 wrd = (insn >> 12) & 0xf;
2056 rd0 = (insn >> 16) & 0xf;
2057 gen_op_iwmmxt_movq_M0_wRn(rd0);
2058 switch ((insn >> 22) & 3) {
2059 case 0:
2060 if (insn & (1 << 21))
2061 gen_op_iwmmxt_unpacklsb_M0();
2062 else
2063 gen_op_iwmmxt_unpacklub_M0();
2064 break;
2065 case 1:
2066 if (insn & (1 << 21))
2067 gen_op_iwmmxt_unpacklsw_M0();
2068 else
2069 gen_op_iwmmxt_unpackluw_M0();
2070 break;
2071 case 2:
2072 if (insn & (1 << 21))
2073 gen_op_iwmmxt_unpacklsl_M0();
2074 else
2075 gen_op_iwmmxt_unpacklul_M0();
2076 break;
2077 case 3:
2078 return 1;
2080 gen_op_iwmmxt_movq_wRn_M0(wrd);
2081 gen_op_iwmmxt_set_mup();
2082 gen_op_iwmmxt_set_cup();
2083 break;
2084 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2085 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2086 wrd = (insn >> 12) & 0xf;
2087 rd0 = (insn >> 16) & 0xf;
2088 gen_op_iwmmxt_movq_M0_wRn(rd0);
2089 switch ((insn >> 22) & 3) {
2090 case 0:
2091 if (insn & (1 << 21))
2092 gen_op_iwmmxt_unpackhsb_M0();
2093 else
2094 gen_op_iwmmxt_unpackhub_M0();
2095 break;
2096 case 1:
2097 if (insn & (1 << 21))
2098 gen_op_iwmmxt_unpackhsw_M0();
2099 else
2100 gen_op_iwmmxt_unpackhuw_M0();
2101 break;
2102 case 2:
2103 if (insn & (1 << 21))
2104 gen_op_iwmmxt_unpackhsl_M0();
2105 else
2106 gen_op_iwmmxt_unpackhul_M0();
2107 break;
2108 case 3:
2109 return 1;
2111 gen_op_iwmmxt_movq_wRn_M0(wrd);
2112 gen_op_iwmmxt_set_mup();
2113 gen_op_iwmmxt_set_cup();
2114 break;
2115 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2116 case 0x214: case 0x614: case 0xa14: case 0xe14:
2117 if (((insn >> 22) & 3) == 0)
2118 return 1;
2119 wrd = (insn >> 12) & 0xf;
2120 rd0 = (insn >> 16) & 0xf;
2121 gen_op_iwmmxt_movq_M0_wRn(rd0);
2122 tmp = tcg_temp_new_i32();
2123 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2124 tcg_temp_free_i32(tmp);
2125 return 1;
2127 switch ((insn >> 22) & 3) {
2128 case 1:
2129 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2130 break;
2131 case 2:
2132 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2133 break;
2134 case 3:
2135 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2136 break;
2138 tcg_temp_free_i32(tmp);
2139 gen_op_iwmmxt_movq_wRn_M0(wrd);
2140 gen_op_iwmmxt_set_mup();
2141 gen_op_iwmmxt_set_cup();
2142 break;
2143 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2144 case 0x014: case 0x414: case 0x814: case 0xc14:
2145 if (((insn >> 22) & 3) == 0)
2146 return 1;
2147 wrd = (insn >> 12) & 0xf;
2148 rd0 = (insn >> 16) & 0xf;
2149 gen_op_iwmmxt_movq_M0_wRn(rd0);
2150 tmp = tcg_temp_new_i32();
2151 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2152 tcg_temp_free_i32(tmp);
2153 return 1;
2155 switch ((insn >> 22) & 3) {
2156 case 1:
2157 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2158 break;
2159 case 2:
2160 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2161 break;
2162 case 3:
2163 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2164 break;
2166 tcg_temp_free_i32(tmp);
2167 gen_op_iwmmxt_movq_wRn_M0(wrd);
2168 gen_op_iwmmxt_set_mup();
2169 gen_op_iwmmxt_set_cup();
2170 break;
2171 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2172 case 0x114: case 0x514: case 0x914: case 0xd14:
2173 if (((insn >> 22) & 3) == 0)
2174 return 1;
2175 wrd = (insn >> 12) & 0xf;
2176 rd0 = (insn >> 16) & 0xf;
2177 gen_op_iwmmxt_movq_M0_wRn(rd0);
2178 tmp = tcg_temp_new_i32();
2179 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2180 tcg_temp_free_i32(tmp);
2181 return 1;
2183 switch ((insn >> 22) & 3) {
2184 case 1:
2185 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2186 break;
2187 case 2:
2188 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2189 break;
2190 case 3:
2191 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2192 break;
2194 tcg_temp_free_i32(tmp);
2195 gen_op_iwmmxt_movq_wRn_M0(wrd);
2196 gen_op_iwmmxt_set_mup();
2197 gen_op_iwmmxt_set_cup();
2198 break;
2199 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2200 case 0x314: case 0x714: case 0xb14: case 0xf14:
2201 if (((insn >> 22) & 3) == 0)
2202 return 1;
2203 wrd = (insn >> 12) & 0xf;
2204 rd0 = (insn >> 16) & 0xf;
2205 gen_op_iwmmxt_movq_M0_wRn(rd0);
2206 tmp = tcg_temp_new_i32();
2207 switch ((insn >> 22) & 3) {
2208 case 1:
2209 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2210 tcg_temp_free_i32(tmp);
2211 return 1;
2213 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2214 break;
2215 case 2:
2216 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2217 tcg_temp_free_i32(tmp);
2218 return 1;
2220 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2221 break;
2222 case 3:
2223 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2224 tcg_temp_free_i32(tmp);
2225 return 1;
2227 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2228 break;
2230 tcg_temp_free_i32(tmp);
2231 gen_op_iwmmxt_movq_wRn_M0(wrd);
2232 gen_op_iwmmxt_set_mup();
2233 gen_op_iwmmxt_set_cup();
2234 break;
2235 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2236 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2237 wrd = (insn >> 12) & 0xf;
2238 rd0 = (insn >> 16) & 0xf;
2239 rd1 = (insn >> 0) & 0xf;
2240 gen_op_iwmmxt_movq_M0_wRn(rd0);
2241 switch ((insn >> 22) & 3) {
2242 case 0:
2243 if (insn & (1 << 21))
2244 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2245 else
2246 gen_op_iwmmxt_minub_M0_wRn(rd1);
2247 break;
2248 case 1:
2249 if (insn & (1 << 21))
2250 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2251 else
2252 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2253 break;
2254 case 2:
2255 if (insn & (1 << 21))
2256 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2257 else
2258 gen_op_iwmmxt_minul_M0_wRn(rd1);
2259 break;
2260 case 3:
2261 return 1;
2263 gen_op_iwmmxt_movq_wRn_M0(wrd);
2264 gen_op_iwmmxt_set_mup();
2265 break;
2266 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2267 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2268 wrd = (insn >> 12) & 0xf;
2269 rd0 = (insn >> 16) & 0xf;
2270 rd1 = (insn >> 0) & 0xf;
2271 gen_op_iwmmxt_movq_M0_wRn(rd0);
2272 switch ((insn >> 22) & 3) {
2273 case 0:
2274 if (insn & (1 << 21))
2275 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2276 else
2277 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2278 break;
2279 case 1:
2280 if (insn & (1 << 21))
2281 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2282 else
2283 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2284 break;
2285 case 2:
2286 if (insn & (1 << 21))
2287 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2288 else
2289 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2290 break;
2291 case 3:
2292 return 1;
2294 gen_op_iwmmxt_movq_wRn_M0(wrd);
2295 gen_op_iwmmxt_set_mup();
2296 break;
2297 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2298 case 0x402: case 0x502: case 0x602: case 0x702:
2299 wrd = (insn >> 12) & 0xf;
2300 rd0 = (insn >> 16) & 0xf;
2301 rd1 = (insn >> 0) & 0xf;
2302 gen_op_iwmmxt_movq_M0_wRn(rd0);
2303 tmp = tcg_const_i32((insn >> 20) & 3);
2304 iwmmxt_load_reg(cpu_V1, rd1);
2305 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2306 tcg_temp_free_i32(tmp);
2307 gen_op_iwmmxt_movq_wRn_M0(wrd);
2308 gen_op_iwmmxt_set_mup();
2309 break;
2310 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2311 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2312 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2313 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2314 wrd = (insn >> 12) & 0xf;
2315 rd0 = (insn >> 16) & 0xf;
2316 rd1 = (insn >> 0) & 0xf;
2317 gen_op_iwmmxt_movq_M0_wRn(rd0);
2318 switch ((insn >> 20) & 0xf) {
2319 case 0x0:
2320 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2321 break;
2322 case 0x1:
2323 gen_op_iwmmxt_subub_M0_wRn(rd1);
2324 break;
2325 case 0x3:
2326 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2327 break;
2328 case 0x4:
2329 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2330 break;
2331 case 0x5:
2332 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2333 break;
2334 case 0x7:
2335 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2336 break;
2337 case 0x8:
2338 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2339 break;
2340 case 0x9:
2341 gen_op_iwmmxt_subul_M0_wRn(rd1);
2342 break;
2343 case 0xb:
2344 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2345 break;
2346 default:
2347 return 1;
2349 gen_op_iwmmxt_movq_wRn_M0(wrd);
2350 gen_op_iwmmxt_set_mup();
2351 gen_op_iwmmxt_set_cup();
2352 break;
2353 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2354 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2355 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2356 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2357 wrd = (insn >> 12) & 0xf;
2358 rd0 = (insn >> 16) & 0xf;
2359 gen_op_iwmmxt_movq_M0_wRn(rd0);
2360 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2361 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2362 tcg_temp_free_i32(tmp);
2363 gen_op_iwmmxt_movq_wRn_M0(wrd);
2364 gen_op_iwmmxt_set_mup();
2365 gen_op_iwmmxt_set_cup();
2366 break;
2367 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2368 case 0x418: case 0x518: case 0x618: case 0x718:
2369 case 0x818: case 0x918: case 0xa18: case 0xb18:
2370 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2371 wrd = (insn >> 12) & 0xf;
2372 rd0 = (insn >> 16) & 0xf;
2373 rd1 = (insn >> 0) & 0xf;
2374 gen_op_iwmmxt_movq_M0_wRn(rd0);
2375 switch ((insn >> 20) & 0xf) {
2376 case 0x0:
2377 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2378 break;
2379 case 0x1:
2380 gen_op_iwmmxt_addub_M0_wRn(rd1);
2381 break;
2382 case 0x3:
2383 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2384 break;
2385 case 0x4:
2386 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2387 break;
2388 case 0x5:
2389 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2390 break;
2391 case 0x7:
2392 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2393 break;
2394 case 0x8:
2395 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2396 break;
2397 case 0x9:
2398 gen_op_iwmmxt_addul_M0_wRn(rd1);
2399 break;
2400 case 0xb:
2401 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2402 break;
2403 default:
2404 return 1;
2406 gen_op_iwmmxt_movq_wRn_M0(wrd);
2407 gen_op_iwmmxt_set_mup();
2408 gen_op_iwmmxt_set_cup();
2409 break;
2410 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2411 case 0x408: case 0x508: case 0x608: case 0x708:
2412 case 0x808: case 0x908: case 0xa08: case 0xb08:
2413 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2414 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2415 return 1;
2416 wrd = (insn >> 12) & 0xf;
2417 rd0 = (insn >> 16) & 0xf;
2418 rd1 = (insn >> 0) & 0xf;
2419 gen_op_iwmmxt_movq_M0_wRn(rd0);
2420 switch ((insn >> 22) & 3) {
2421 case 1:
2422 if (insn & (1 << 21))
2423 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2424 else
2425 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2426 break;
2427 case 2:
2428 if (insn & (1 << 21))
2429 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2430 else
2431 gen_op_iwmmxt_packul_M0_wRn(rd1);
2432 break;
2433 case 3:
2434 if (insn & (1 << 21))
2435 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2436 else
2437 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2438 break;
2440 gen_op_iwmmxt_movq_wRn_M0(wrd);
2441 gen_op_iwmmxt_set_mup();
2442 gen_op_iwmmxt_set_cup();
2443 break;
2444 case 0x201: case 0x203: case 0x205: case 0x207:
2445 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2446 case 0x211: case 0x213: case 0x215: case 0x217:
2447 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2448 wrd = (insn >> 5) & 0xf;
2449 rd0 = (insn >> 12) & 0xf;
2450 rd1 = (insn >> 0) & 0xf;
2451 if (rd0 == 0xf || rd1 == 0xf)
2452 return 1;
2453 gen_op_iwmmxt_movq_M0_wRn(wrd);
2454 tmp = load_reg(s, rd0);
2455 tmp2 = load_reg(s, rd1);
2456 switch ((insn >> 16) & 0xf) {
2457 case 0x0: /* TMIA */
2458 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2459 break;
2460 case 0x8: /* TMIAPH */
2461 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2462 break;
2463 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2464 if (insn & (1 << 16))
2465 tcg_gen_shri_i32(tmp, tmp, 16);
2466 if (insn & (1 << 17))
2467 tcg_gen_shri_i32(tmp2, tmp2, 16);
2468 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2469 break;
2470 default:
2471 tcg_temp_free_i32(tmp2);
2472 tcg_temp_free_i32(tmp);
2473 return 1;
2475 tcg_temp_free_i32(tmp2);
2476 tcg_temp_free_i32(tmp);
2477 gen_op_iwmmxt_movq_wRn_M0(wrd);
2478 gen_op_iwmmxt_set_mup();
2479 break;
2480 default:
2481 return 1;
2484 return 0;
2487 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2488 (ie. an undefined instruction). */
2489 static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2491 int acc, rd0, rd1, rdhi, rdlo;
2492 TCGv_i32 tmp, tmp2;
2494 if ((insn & 0x0ff00f10) == 0x0e200010) {
2495 /* Multiply with Internal Accumulate Format */
2496 rd0 = (insn >> 12) & 0xf;
2497 rd1 = insn & 0xf;
2498 acc = (insn >> 5) & 7;
2500 if (acc != 0)
2501 return 1;
2503 tmp = load_reg(s, rd0);
2504 tmp2 = load_reg(s, rd1);
2505 switch ((insn >> 16) & 0xf) {
2506 case 0x0: /* MIA */
2507 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2508 break;
2509 case 0x8: /* MIAPH */
2510 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2511 break;
2512 case 0xc: /* MIABB */
2513 case 0xd: /* MIABT */
2514 case 0xe: /* MIATB */
2515 case 0xf: /* MIATT */
2516 if (insn & (1 << 16))
2517 tcg_gen_shri_i32(tmp, tmp, 16);
2518 if (insn & (1 << 17))
2519 tcg_gen_shri_i32(tmp2, tmp2, 16);
2520 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2521 break;
2522 default:
2523 return 1;
2525 tcg_temp_free_i32(tmp2);
2526 tcg_temp_free_i32(tmp);
2528 gen_op_iwmmxt_movq_wRn_M0(acc);
2529 return 0;
2532 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2533 /* Internal Accumulator Access Format */
2534 rdhi = (insn >> 16) & 0xf;
2535 rdlo = (insn >> 12) & 0xf;
2536 acc = insn & 7;
2538 if (acc != 0)
2539 return 1;
2541 if (insn & ARM_CP_RW_BIT) { /* MRA */
2542 iwmmxt_load_reg(cpu_V0, acc);
2543 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2544 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2545 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2546 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2547 } else { /* MAR */
2548 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2549 iwmmxt_store_reg(cpu_V0, acc);
2551 return 0;
2554 return 1;
2557 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2558 #define VFP_SREG(insn, bigbit, smallbit) \
2559 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2560 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2561 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2562 reg = (((insn) >> (bigbit)) & 0x0f) \
2563 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2564 } else { \
2565 if (insn & (1 << (smallbit))) \
2566 return 1; \
2567 reg = ((insn) >> (bigbit)) & 0x0f; \
2568 }} while (0)
2570 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2571 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2572 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2573 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2574 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2575 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2577 /* Move between integer and VFP cores. */
2578 static TCGv_i32 gen_vfp_mrs(void)
2580 TCGv_i32 tmp = tcg_temp_new_i32();
2581 tcg_gen_mov_i32(tmp, cpu_F0s);
2582 return tmp;
2585 static void gen_vfp_msr(TCGv_i32 tmp)
2587 tcg_gen_mov_i32(cpu_F0s, tmp);
2588 tcg_temp_free_i32(tmp);
2591 static void gen_neon_dup_u8(TCGv_i32 var, int shift)
2593 TCGv_i32 tmp = tcg_temp_new_i32();
2594 if (shift)
2595 tcg_gen_shri_i32(var, var, shift);
2596 tcg_gen_ext8u_i32(var, var);
2597 tcg_gen_shli_i32(tmp, var, 8);
2598 tcg_gen_or_i32(var, var, tmp);
2599 tcg_gen_shli_i32(tmp, var, 16);
2600 tcg_gen_or_i32(var, var, tmp);
2601 tcg_temp_free_i32(tmp);
2604 static void gen_neon_dup_low16(TCGv_i32 var)
2606 TCGv_i32 tmp = tcg_temp_new_i32();
2607 tcg_gen_ext16u_i32(var, var);
2608 tcg_gen_shli_i32(tmp, var, 16);
2609 tcg_gen_or_i32(var, var, tmp);
2610 tcg_temp_free_i32(tmp);
2613 static void gen_neon_dup_high16(TCGv_i32 var)
2615 TCGv_i32 tmp = tcg_temp_new_i32();
2616 tcg_gen_andi_i32(var, var, 0xffff0000);
2617 tcg_gen_shri_i32(tmp, var, 16);
2618 tcg_gen_or_i32(var, var, tmp);
2619 tcg_temp_free_i32(tmp);
2622 static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
2624 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2625 TCGv_i32 tmp = tcg_temp_new_i32();
2626 switch (size) {
2627 case 0:
2628 gen_aa32_ld8u(tmp, addr, IS_USER(s));
2629 gen_neon_dup_u8(tmp, 0);
2630 break;
2631 case 1:
2632 gen_aa32_ld16u(tmp, addr, IS_USER(s));
2633 gen_neon_dup_low16(tmp);
2634 break;
2635 case 2:
2636 gen_aa32_ld32u(tmp, addr, IS_USER(s));
2637 break;
2638 default: /* Avoid compiler warnings. */
2639 abort();
2641 return tmp;
2644 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2645 uint32_t dp)
2647 uint32_t cc = extract32(insn, 20, 2);
2649 if (dp) {
2650 TCGv_i64 frn, frm, dest;
2651 TCGv_i64 tmp, zero, zf, nf, vf;
2653 zero = tcg_const_i64(0);
2655 frn = tcg_temp_new_i64();
2656 frm = tcg_temp_new_i64();
2657 dest = tcg_temp_new_i64();
2659 zf = tcg_temp_new_i64();
2660 nf = tcg_temp_new_i64();
2661 vf = tcg_temp_new_i64();
2663 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2664 tcg_gen_ext_i32_i64(nf, cpu_NF);
2665 tcg_gen_ext_i32_i64(vf, cpu_VF);
2667 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2668 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2669 switch (cc) {
2670 case 0: /* eq: Z */
2671 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2672 frn, frm);
2673 break;
2674 case 1: /* vs: V */
2675 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2676 frn, frm);
2677 break;
2678 case 2: /* ge: N == V -> N ^ V == 0 */
2679 tmp = tcg_temp_new_i64();
2680 tcg_gen_xor_i64(tmp, vf, nf);
2681 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2682 frn, frm);
2683 tcg_temp_free_i64(tmp);
2684 break;
2685 case 3: /* gt: !Z && N == V */
2686 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2687 frn, frm);
2688 tmp = tcg_temp_new_i64();
2689 tcg_gen_xor_i64(tmp, vf, nf);
2690 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2691 dest, frm);
2692 tcg_temp_free_i64(tmp);
2693 break;
2695 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2696 tcg_temp_free_i64(frn);
2697 tcg_temp_free_i64(frm);
2698 tcg_temp_free_i64(dest);
2700 tcg_temp_free_i64(zf);
2701 tcg_temp_free_i64(nf);
2702 tcg_temp_free_i64(vf);
2704 tcg_temp_free_i64(zero);
2705 } else {
2706 TCGv_i32 frn, frm, dest;
2707 TCGv_i32 tmp, zero;
2709 zero = tcg_const_i32(0);
2711 frn = tcg_temp_new_i32();
2712 frm = tcg_temp_new_i32();
2713 dest = tcg_temp_new_i32();
2714 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2715 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2716 switch (cc) {
2717 case 0: /* eq: Z */
2718 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2719 frn, frm);
2720 break;
2721 case 1: /* vs: V */
2722 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2723 frn, frm);
2724 break;
2725 case 2: /* ge: N == V -> N ^ V == 0 */
2726 tmp = tcg_temp_new_i32();
2727 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2728 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2729 frn, frm);
2730 tcg_temp_free_i32(tmp);
2731 break;
2732 case 3: /* gt: !Z && N == V */
2733 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2734 frn, frm);
2735 tmp = tcg_temp_new_i32();
2736 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2737 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2738 dest, frm);
2739 tcg_temp_free_i32(tmp);
2740 break;
2742 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2743 tcg_temp_free_i32(frn);
2744 tcg_temp_free_i32(frm);
2745 tcg_temp_free_i32(dest);
2747 tcg_temp_free_i32(zero);
2750 return 0;
2753 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2754 uint32_t rm, uint32_t dp)
2756 uint32_t vmin = extract32(insn, 6, 1);
2757 TCGv_ptr fpst = get_fpstatus_ptr(0);
2759 if (dp) {
2760 TCGv_i64 frn, frm, dest;
2762 frn = tcg_temp_new_i64();
2763 frm = tcg_temp_new_i64();
2764 dest = tcg_temp_new_i64();
2766 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2767 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2768 if (vmin) {
2769 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
2770 } else {
2771 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
2773 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2774 tcg_temp_free_i64(frn);
2775 tcg_temp_free_i64(frm);
2776 tcg_temp_free_i64(dest);
2777 } else {
2778 TCGv_i32 frn, frm, dest;
2780 frn = tcg_temp_new_i32();
2781 frm = tcg_temp_new_i32();
2782 dest = tcg_temp_new_i32();
2784 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2785 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2786 if (vmin) {
2787 gen_helper_vfp_minnums(dest, frn, frm, fpst);
2788 } else {
2789 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
2791 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2792 tcg_temp_free_i32(frn);
2793 tcg_temp_free_i32(frm);
2794 tcg_temp_free_i32(dest);
2797 tcg_temp_free_ptr(fpst);
2798 return 0;
2801 static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2802 int rounding)
2804 TCGv_ptr fpst = get_fpstatus_ptr(0);
2805 TCGv_i32 tcg_rmode;
2807 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2808 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2810 if (dp) {
2811 TCGv_i64 tcg_op;
2812 TCGv_i64 tcg_res;
2813 tcg_op = tcg_temp_new_i64();
2814 tcg_res = tcg_temp_new_i64();
2815 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2816 gen_helper_rintd(tcg_res, tcg_op, fpst);
2817 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2818 tcg_temp_free_i64(tcg_op);
2819 tcg_temp_free_i64(tcg_res);
2820 } else {
2821 TCGv_i32 tcg_op;
2822 TCGv_i32 tcg_res;
2823 tcg_op = tcg_temp_new_i32();
2824 tcg_res = tcg_temp_new_i32();
2825 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2826 gen_helper_rints(tcg_res, tcg_op, fpst);
2827 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2828 tcg_temp_free_i32(tcg_op);
2829 tcg_temp_free_i32(tcg_res);
2832 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2833 tcg_temp_free_i32(tcg_rmode);
2835 tcg_temp_free_ptr(fpst);
2836 return 0;
2839 static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2840 int rounding)
2842 bool is_signed = extract32(insn, 7, 1);
2843 TCGv_ptr fpst = get_fpstatus_ptr(0);
2844 TCGv_i32 tcg_rmode, tcg_shift;
2846 tcg_shift = tcg_const_i32(0);
2848 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2849 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2851 if (dp) {
2852 TCGv_i64 tcg_double, tcg_res;
2853 TCGv_i32 tcg_tmp;
2854 /* Rd is encoded as a single precision register even when the source
2855 * is double precision.
2857 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
2858 tcg_double = tcg_temp_new_i64();
2859 tcg_res = tcg_temp_new_i64();
2860 tcg_tmp = tcg_temp_new_i32();
2861 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
2862 if (is_signed) {
2863 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
2864 } else {
2865 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
2867 tcg_gen_trunc_i64_i32(tcg_tmp, tcg_res);
2868 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
2869 tcg_temp_free_i32(tcg_tmp);
2870 tcg_temp_free_i64(tcg_res);
2871 tcg_temp_free_i64(tcg_double);
2872 } else {
2873 TCGv_i32 tcg_single, tcg_res;
2874 tcg_single = tcg_temp_new_i32();
2875 tcg_res = tcg_temp_new_i32();
2876 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
2877 if (is_signed) {
2878 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
2879 } else {
2880 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
2882 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
2883 tcg_temp_free_i32(tcg_res);
2884 tcg_temp_free_i32(tcg_single);
2887 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2888 tcg_temp_free_i32(tcg_rmode);
2890 tcg_temp_free_i32(tcg_shift);
2892 tcg_temp_free_ptr(fpst);
2894 return 0;
2897 /* Table for converting the most common AArch32 encoding of
2898 * rounding mode to arm_fprounding order (which matches the
2899 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
2901 static const uint8_t fp_decode_rm[] = {
2902 FPROUNDING_TIEAWAY,
2903 FPROUNDING_TIEEVEN,
2904 FPROUNDING_POSINF,
2905 FPROUNDING_NEGINF,
2908 static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2910 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
2912 if (!arm_feature(env, ARM_FEATURE_V8)) {
2913 return 1;
2916 if (dp) {
2917 VFP_DREG_D(rd, insn);
2918 VFP_DREG_N(rn, insn);
2919 VFP_DREG_M(rm, insn);
2920 } else {
2921 rd = VFP_SREG_D(insn);
2922 rn = VFP_SREG_N(insn);
2923 rm = VFP_SREG_M(insn);
2926 if ((insn & 0x0f800e50) == 0x0e000a00) {
2927 return handle_vsel(insn, rd, rn, rm, dp);
2928 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
2929 return handle_vminmaxnm(insn, rd, rn, rm, dp);
2930 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
2931 /* VRINTA, VRINTN, VRINTP, VRINTM */
2932 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2933 return handle_vrint(insn, rd, rm, dp, rounding);
2934 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
2935 /* VCVTA, VCVTN, VCVTP, VCVTM */
2936 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2937 return handle_vcvt(insn, rd, rm, dp, rounding);
2939 return 1;
2942 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2943 (ie. an undefined instruction). */
2944 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
2946 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2947 int dp, veclen;
2948 TCGv_i32 addr;
2949 TCGv_i32 tmp;
2950 TCGv_i32 tmp2;
2952 if (!arm_feature(env, ARM_FEATURE_VFP))
2953 return 1;
2955 /* FIXME: this access check should not take precedence over UNDEF
2956 * for invalid encodings; we will generate incorrect syndrome information
2957 * for attempts to execute invalid vfp/neon encodings with FP disabled.
2959 if (!s->cpacr_fpen) {
2960 gen_exception_insn(s, 4, EXCP_UDEF,
2961 syn_fp_access_trap(1, 0xe, s->thumb));
2962 return 0;
2965 if (!s->vfp_enabled) {
2966 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2967 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2968 return 1;
2969 rn = (insn >> 16) & 0xf;
2970 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
2971 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
2972 return 1;
2976 if (extract32(insn, 28, 4) == 0xf) {
2977 /* Encodings with T=1 (Thumb) or unconditional (ARM):
2978 * only used in v8 and above.
2980 return disas_vfp_v8_insn(env, s, insn);
2983 dp = ((insn & 0xf00) == 0xb00);
2984 switch ((insn >> 24) & 0xf) {
2985 case 0xe:
2986 if (insn & (1 << 4)) {
2987 /* single register transfer */
2988 rd = (insn >> 12) & 0xf;
2989 if (dp) {
2990 int size;
2991 int pass;
2993 VFP_DREG_N(rn, insn);
2994 if (insn & 0xf)
2995 return 1;
2996 if (insn & 0x00c00060
2997 && !arm_feature(env, ARM_FEATURE_NEON))
2998 return 1;
3000 pass = (insn >> 21) & 1;
3001 if (insn & (1 << 22)) {
3002 size = 0;
3003 offset = ((insn >> 5) & 3) * 8;
3004 } else if (insn & (1 << 5)) {
3005 size = 1;
3006 offset = (insn & (1 << 6)) ? 16 : 0;
3007 } else {
3008 size = 2;
3009 offset = 0;
3011 if (insn & ARM_CP_RW_BIT) {
3012 /* vfp->arm */
3013 tmp = neon_load_reg(rn, pass);
3014 switch (size) {
3015 case 0:
3016 if (offset)
3017 tcg_gen_shri_i32(tmp, tmp, offset);
3018 if (insn & (1 << 23))
3019 gen_uxtb(tmp);
3020 else
3021 gen_sxtb(tmp);
3022 break;
3023 case 1:
3024 if (insn & (1 << 23)) {
3025 if (offset) {
3026 tcg_gen_shri_i32(tmp, tmp, 16);
3027 } else {
3028 gen_uxth(tmp);
3030 } else {
3031 if (offset) {
3032 tcg_gen_sari_i32(tmp, tmp, 16);
3033 } else {
3034 gen_sxth(tmp);
3037 break;
3038 case 2:
3039 break;
3041 store_reg(s, rd, tmp);
3042 } else {
3043 /* arm->vfp */
3044 tmp = load_reg(s, rd);
3045 if (insn & (1 << 23)) {
3046 /* VDUP */
3047 if (size == 0) {
3048 gen_neon_dup_u8(tmp, 0);
3049 } else if (size == 1) {
3050 gen_neon_dup_low16(tmp);
3052 for (n = 0; n <= pass * 2; n++) {
3053 tmp2 = tcg_temp_new_i32();
3054 tcg_gen_mov_i32(tmp2, tmp);
3055 neon_store_reg(rn, n, tmp2);
3057 neon_store_reg(rn, n, tmp);
3058 } else {
3059 /* VMOV */
3060 switch (size) {
3061 case 0:
3062 tmp2 = neon_load_reg(rn, pass);
3063 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
3064 tcg_temp_free_i32(tmp2);
3065 break;
3066 case 1:
3067 tmp2 = neon_load_reg(rn, pass);
3068 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
3069 tcg_temp_free_i32(tmp2);
3070 break;
3071 case 2:
3072 break;
3074 neon_store_reg(rn, pass, tmp);
3077 } else { /* !dp */
3078 if ((insn & 0x6f) != 0x00)
3079 return 1;
3080 rn = VFP_SREG_N(insn);
3081 if (insn & ARM_CP_RW_BIT) {
3082 /* vfp->arm */
3083 if (insn & (1 << 21)) {
3084 /* system register */
3085 rn >>= 1;
3087 switch (rn) {
3088 case ARM_VFP_FPSID:
3089 /* VFP2 allows access to FSID from userspace.
3090 VFP3 restricts all id registers to privileged
3091 accesses. */
3092 if (IS_USER(s)
3093 && arm_feature(env, ARM_FEATURE_VFP3))
3094 return 1;
3095 tmp = load_cpu_field(vfp.xregs[rn]);
3096 break;
3097 case ARM_VFP_FPEXC:
3098 if (IS_USER(s))
3099 return 1;
3100 tmp = load_cpu_field(vfp.xregs[rn]);
3101 break;
3102 case ARM_VFP_FPINST:
3103 case ARM_VFP_FPINST2:
3104 /* Not present in VFP3. */
3105 if (IS_USER(s)
3106 || arm_feature(env, ARM_FEATURE_VFP3))
3107 return 1;
3108 tmp = load_cpu_field(vfp.xregs[rn]);
3109 break;
3110 case ARM_VFP_FPSCR:
3111 if (rd == 15) {
3112 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3113 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3114 } else {
3115 tmp = tcg_temp_new_i32();
3116 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3118 break;
3119 case ARM_VFP_MVFR2:
3120 if (!arm_feature(env, ARM_FEATURE_V8)) {
3121 return 1;
3123 /* fall through */
3124 case ARM_VFP_MVFR0:
3125 case ARM_VFP_MVFR1:
3126 if (IS_USER(s)
3127 || !arm_feature(env, ARM_FEATURE_MVFR))
3128 return 1;
3129 tmp = load_cpu_field(vfp.xregs[rn]);
3130 break;
3131 default:
3132 return 1;
3134 } else {
3135 gen_mov_F0_vreg(0, rn);
3136 tmp = gen_vfp_mrs();
3138 if (rd == 15) {
3139 /* Set the 4 flag bits in the CPSR. */
3140 gen_set_nzcv(tmp);
3141 tcg_temp_free_i32(tmp);
3142 } else {
3143 store_reg(s, rd, tmp);
3145 } else {
3146 /* arm->vfp */
3147 if (insn & (1 << 21)) {
3148 rn >>= 1;
3149 /* system register */
3150 switch (rn) {
3151 case ARM_VFP_FPSID:
3152 case ARM_VFP_MVFR0:
3153 case ARM_VFP_MVFR1:
3154 /* Writes are ignored. */
3155 break;
3156 case ARM_VFP_FPSCR:
3157 tmp = load_reg(s, rd);
3158 gen_helper_vfp_set_fpscr(cpu_env, tmp);
3159 tcg_temp_free_i32(tmp);
3160 gen_lookup_tb(s);
3161 break;
3162 case ARM_VFP_FPEXC:
3163 if (IS_USER(s))
3164 return 1;
3165 /* TODO: VFP subarchitecture support.
3166 * For now, keep the EN bit only */
3167 tmp = load_reg(s, rd);
3168 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3169 store_cpu_field(tmp, vfp.xregs[rn]);
3170 gen_lookup_tb(s);
3171 break;
3172 case ARM_VFP_FPINST:
3173 case ARM_VFP_FPINST2:
3174 tmp = load_reg(s, rd);
3175 store_cpu_field(tmp, vfp.xregs[rn]);
3176 break;
3177 default:
3178 return 1;
3180 } else {
3181 tmp = load_reg(s, rd);
3182 gen_vfp_msr(tmp);
3183 gen_mov_vreg_F0(0, rn);
3187 } else {
3188 /* data processing */
3189 /* The opcode is in bits 23, 21, 20 and 6. */
3190 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3191 if (dp) {
3192 if (op == 15) {
3193 /* rn is opcode */
3194 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3195 } else {
3196 /* rn is register number */
3197 VFP_DREG_N(rn, insn);
3200 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
3201 ((rn & 0x1e) == 0x6))) {
3202 /* Integer or single/half precision destination. */
3203 rd = VFP_SREG_D(insn);
3204 } else {
3205 VFP_DREG_D(rd, insn);
3207 if (op == 15 &&
3208 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
3209 ((rn & 0x1e) == 0x4))) {
3210 /* VCVT from int or half precision is always from S reg
3211 * regardless of dp bit. VCVT with immediate frac_bits
3212 * has same format as SREG_M.
3214 rm = VFP_SREG_M(insn);
3215 } else {
3216 VFP_DREG_M(rm, insn);
3218 } else {
3219 rn = VFP_SREG_N(insn);
3220 if (op == 15 && rn == 15) {
3221 /* Double precision destination. */
3222 VFP_DREG_D(rd, insn);
3223 } else {
3224 rd = VFP_SREG_D(insn);
3226 /* NB that we implicitly rely on the encoding for the frac_bits
3227 * in VCVT of fixed to float being the same as that of an SREG_M
3229 rm = VFP_SREG_M(insn);
3232 veclen = s->vec_len;
3233 if (op == 15 && rn > 3)
3234 veclen = 0;
3236 /* Shut up compiler warnings. */
3237 delta_m = 0;
3238 delta_d = 0;
3239 bank_mask = 0;
3241 if (veclen > 0) {
3242 if (dp)
3243 bank_mask = 0xc;
3244 else
3245 bank_mask = 0x18;
3247 /* Figure out what type of vector operation this is. */
3248 if ((rd & bank_mask) == 0) {
3249 /* scalar */
3250 veclen = 0;
3251 } else {
3252 if (dp)
3253 delta_d = (s->vec_stride >> 1) + 1;
3254 else
3255 delta_d = s->vec_stride + 1;
3257 if ((rm & bank_mask) == 0) {
3258 /* mixed scalar/vector */
3259 delta_m = 0;
3260 } else {
3261 /* vector */
3262 delta_m = delta_d;
3267 /* Load the initial operands. */
3268 if (op == 15) {
3269 switch (rn) {
3270 case 16:
3271 case 17:
3272 /* Integer source */
3273 gen_mov_F0_vreg(0, rm);
3274 break;
3275 case 8:
3276 case 9:
3277 /* Compare */
3278 gen_mov_F0_vreg(dp, rd);
3279 gen_mov_F1_vreg(dp, rm);
3280 break;
3281 case 10:
3282 case 11:
3283 /* Compare with zero */
3284 gen_mov_F0_vreg(dp, rd);
3285 gen_vfp_F1_ld0(dp);
3286 break;
3287 case 20:
3288 case 21:
3289 case 22:
3290 case 23:
3291 case 28:
3292 case 29:
3293 case 30:
3294 case 31:
3295 /* Source and destination the same. */
3296 gen_mov_F0_vreg(dp, rd);
3297 break;
3298 case 4:
3299 case 5:
3300 case 6:
3301 case 7:
3302 /* VCVTB, VCVTT: only present with the halfprec extension
3303 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3304 * (we choose to UNDEF)
3306 if ((dp && !arm_feature(env, ARM_FEATURE_V8)) ||
3307 !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3308 return 1;
3310 if (!extract32(rn, 1, 1)) {
3311 /* Half precision source. */
3312 gen_mov_F0_vreg(0, rm);
3313 break;
3315 /* Otherwise fall through */
3316 default:
3317 /* One source operand. */
3318 gen_mov_F0_vreg(dp, rm);
3319 break;
3321 } else {
3322 /* Two source operands. */
3323 gen_mov_F0_vreg(dp, rn);
3324 gen_mov_F1_vreg(dp, rm);
3327 for (;;) {
3328 /* Perform the calculation. */
3329 switch (op) {
3330 case 0: /* VMLA: fd + (fn * fm) */
3331 /* Note that order of inputs to the add matters for NaNs */
3332 gen_vfp_F1_mul(dp);
3333 gen_mov_F0_vreg(dp, rd);
3334 gen_vfp_add(dp);
3335 break;
3336 case 1: /* VMLS: fd + -(fn * fm) */
3337 gen_vfp_mul(dp);
3338 gen_vfp_F1_neg(dp);
3339 gen_mov_F0_vreg(dp, rd);
3340 gen_vfp_add(dp);
3341 break;
3342 case 2: /* VNMLS: -fd + (fn * fm) */
3343 /* Note that it isn't valid to replace (-A + B) with (B - A)
3344 * or similar plausible looking simplifications
3345 * because this will give wrong results for NaNs.
3347 gen_vfp_F1_mul(dp);
3348 gen_mov_F0_vreg(dp, rd);
3349 gen_vfp_neg(dp);
3350 gen_vfp_add(dp);
3351 break;
3352 case 3: /* VNMLA: -fd + -(fn * fm) */
3353 gen_vfp_mul(dp);
3354 gen_vfp_F1_neg(dp);
3355 gen_mov_F0_vreg(dp, rd);
3356 gen_vfp_neg(dp);
3357 gen_vfp_add(dp);
3358 break;
3359 case 4: /* mul: fn * fm */
3360 gen_vfp_mul(dp);
3361 break;
3362 case 5: /* nmul: -(fn * fm) */
3363 gen_vfp_mul(dp);
3364 gen_vfp_neg(dp);
3365 break;
3366 case 6: /* add: fn + fm */
3367 gen_vfp_add(dp);
3368 break;
3369 case 7: /* sub: fn - fm */
3370 gen_vfp_sub(dp);
3371 break;
3372 case 8: /* div: fn / fm */
3373 gen_vfp_div(dp);
3374 break;
3375 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3376 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3377 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3378 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3379 /* These are fused multiply-add, and must be done as one
3380 * floating point operation with no rounding between the
3381 * multiplication and addition steps.
3382 * NB that doing the negations here as separate steps is
3383 * correct : an input NaN should come out with its sign bit
3384 * flipped if it is a negated-input.
3386 if (!arm_feature(env, ARM_FEATURE_VFP4)) {
3387 return 1;
3389 if (dp) {
3390 TCGv_ptr fpst;
3391 TCGv_i64 frd;
3392 if (op & 1) {
3393 /* VFNMS, VFMS */
3394 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3396 frd = tcg_temp_new_i64();
3397 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3398 if (op & 2) {
3399 /* VFNMA, VFNMS */
3400 gen_helper_vfp_negd(frd, frd);
3402 fpst = get_fpstatus_ptr(0);
3403 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3404 cpu_F1d, frd, fpst);
3405 tcg_temp_free_ptr(fpst);
3406 tcg_temp_free_i64(frd);
3407 } else {
3408 TCGv_ptr fpst;
3409 TCGv_i32 frd;
3410 if (op & 1) {
3411 /* VFNMS, VFMS */
3412 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3414 frd = tcg_temp_new_i32();
3415 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3416 if (op & 2) {
3417 gen_helper_vfp_negs(frd, frd);
3419 fpst = get_fpstatus_ptr(0);
3420 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3421 cpu_F1s, frd, fpst);
3422 tcg_temp_free_ptr(fpst);
3423 tcg_temp_free_i32(frd);
3425 break;
3426 case 14: /* fconst */
3427 if (!arm_feature(env, ARM_FEATURE_VFP3))
3428 return 1;
3430 n = (insn << 12) & 0x80000000;
3431 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3432 if (dp) {
3433 if (i & 0x40)
3434 i |= 0x3f80;
3435 else
3436 i |= 0x4000;
3437 n |= i << 16;
3438 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3439 } else {
3440 if (i & 0x40)
3441 i |= 0x780;
3442 else
3443 i |= 0x800;
3444 n |= i << 19;
3445 tcg_gen_movi_i32(cpu_F0s, n);
3447 break;
3448 case 15: /* extension space */
3449 switch (rn) {
3450 case 0: /* cpy */
3451 /* no-op */
3452 break;
3453 case 1: /* abs */
3454 gen_vfp_abs(dp);
3455 break;
3456 case 2: /* neg */
3457 gen_vfp_neg(dp);
3458 break;
3459 case 3: /* sqrt */
3460 gen_vfp_sqrt(dp);
3461 break;
3462 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
3463 tmp = gen_vfp_mrs();
3464 tcg_gen_ext16u_i32(tmp, tmp);
3465 if (dp) {
3466 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3467 cpu_env);
3468 } else {
3469 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3470 cpu_env);
3472 tcg_temp_free_i32(tmp);
3473 break;
3474 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
3475 tmp = gen_vfp_mrs();
3476 tcg_gen_shri_i32(tmp, tmp, 16);
3477 if (dp) {
3478 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3479 cpu_env);
3480 } else {
3481 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3482 cpu_env);
3484 tcg_temp_free_i32(tmp);
3485 break;
3486 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3487 tmp = tcg_temp_new_i32();
3488 if (dp) {
3489 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3490 cpu_env);
3491 } else {
3492 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3493 cpu_env);
3495 gen_mov_F0_vreg(0, rd);
3496 tmp2 = gen_vfp_mrs();
3497 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3498 tcg_gen_or_i32(tmp, tmp, tmp2);
3499 tcg_temp_free_i32(tmp2);
3500 gen_vfp_msr(tmp);
3501 break;
3502 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3503 tmp = tcg_temp_new_i32();
3504 if (dp) {
3505 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3506 cpu_env);
3507 } else {
3508 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3509 cpu_env);
3511 tcg_gen_shli_i32(tmp, tmp, 16);
3512 gen_mov_F0_vreg(0, rd);
3513 tmp2 = gen_vfp_mrs();
3514 tcg_gen_ext16u_i32(tmp2, tmp2);
3515 tcg_gen_or_i32(tmp, tmp, tmp2);
3516 tcg_temp_free_i32(tmp2);
3517 gen_vfp_msr(tmp);
3518 break;
3519 case 8: /* cmp */
3520 gen_vfp_cmp(dp);
3521 break;
3522 case 9: /* cmpe */
3523 gen_vfp_cmpe(dp);
3524 break;
3525 case 10: /* cmpz */
3526 gen_vfp_cmp(dp);
3527 break;
3528 case 11: /* cmpez */
3529 gen_vfp_F1_ld0(dp);
3530 gen_vfp_cmpe(dp);
3531 break;
3532 case 12: /* vrintr */
3534 TCGv_ptr fpst = get_fpstatus_ptr(0);
3535 if (dp) {
3536 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3537 } else {
3538 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3540 tcg_temp_free_ptr(fpst);
3541 break;
3543 case 13: /* vrintz */
3545 TCGv_ptr fpst = get_fpstatus_ptr(0);
3546 TCGv_i32 tcg_rmode;
3547 tcg_rmode = tcg_const_i32(float_round_to_zero);
3548 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3549 if (dp) {
3550 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3551 } else {
3552 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3554 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3555 tcg_temp_free_i32(tcg_rmode);
3556 tcg_temp_free_ptr(fpst);
3557 break;
3559 case 14: /* vrintx */
3561 TCGv_ptr fpst = get_fpstatus_ptr(0);
3562 if (dp) {
3563 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3564 } else {
3565 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3567 tcg_temp_free_ptr(fpst);
3568 break;
3570 case 15: /* single<->double conversion */
3571 if (dp)
3572 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3573 else
3574 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3575 break;
3576 case 16: /* fuito */
3577 gen_vfp_uito(dp, 0);
3578 break;
3579 case 17: /* fsito */
3580 gen_vfp_sito(dp, 0);
3581 break;
3582 case 20: /* fshto */
3583 if (!arm_feature(env, ARM_FEATURE_VFP3))
3584 return 1;
3585 gen_vfp_shto(dp, 16 - rm, 0);
3586 break;
3587 case 21: /* fslto */
3588 if (!arm_feature(env, ARM_FEATURE_VFP3))
3589 return 1;
3590 gen_vfp_slto(dp, 32 - rm, 0);
3591 break;
3592 case 22: /* fuhto */
3593 if (!arm_feature(env, ARM_FEATURE_VFP3))
3594 return 1;
3595 gen_vfp_uhto(dp, 16 - rm, 0);
3596 break;
3597 case 23: /* fulto */
3598 if (!arm_feature(env, ARM_FEATURE_VFP3))
3599 return 1;
3600 gen_vfp_ulto(dp, 32 - rm, 0);
3601 break;
3602 case 24: /* ftoui */
3603 gen_vfp_toui(dp, 0);
3604 break;
3605 case 25: /* ftouiz */
3606 gen_vfp_touiz(dp, 0);
3607 break;
3608 case 26: /* ftosi */
3609 gen_vfp_tosi(dp, 0);
3610 break;
3611 case 27: /* ftosiz */
3612 gen_vfp_tosiz(dp, 0);
3613 break;
3614 case 28: /* ftosh */
3615 if (!arm_feature(env, ARM_FEATURE_VFP3))
3616 return 1;
3617 gen_vfp_tosh(dp, 16 - rm, 0);
3618 break;
3619 case 29: /* ftosl */
3620 if (!arm_feature(env, ARM_FEATURE_VFP3))
3621 return 1;
3622 gen_vfp_tosl(dp, 32 - rm, 0);
3623 break;
3624 case 30: /* ftouh */
3625 if (!arm_feature(env, ARM_FEATURE_VFP3))
3626 return 1;
3627 gen_vfp_touh(dp, 16 - rm, 0);
3628 break;
3629 case 31: /* ftoul */
3630 if (!arm_feature(env, ARM_FEATURE_VFP3))
3631 return 1;
3632 gen_vfp_toul(dp, 32 - rm, 0);
3633 break;
3634 default: /* undefined */
3635 return 1;
3637 break;
3638 default: /* undefined */
3639 return 1;
3642 /* Write back the result. */
3643 if (op == 15 && (rn >= 8 && rn <= 11)) {
3644 /* Comparison, do nothing. */
3645 } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
3646 (rn & 0x1e) == 0x6)) {
3647 /* VCVT double to int: always integer result.
3648 * VCVT double to half precision is always a single
3649 * precision result.
3651 gen_mov_vreg_F0(0, rd);
3652 } else if (op == 15 && rn == 15) {
3653 /* conversion */
3654 gen_mov_vreg_F0(!dp, rd);
3655 } else {
3656 gen_mov_vreg_F0(dp, rd);
3659 /* break out of the loop if we have finished */
3660 if (veclen == 0)
3661 break;
3663 if (op == 15 && delta_m == 0) {
3664 /* single source one-many */
3665 while (veclen--) {
3666 rd = ((rd + delta_d) & (bank_mask - 1))
3667 | (rd & bank_mask);
3668 gen_mov_vreg_F0(dp, rd);
3670 break;
3672 /* Setup the next operands. */
3673 veclen--;
3674 rd = ((rd + delta_d) & (bank_mask - 1))
3675 | (rd & bank_mask);
3677 if (op == 15) {
3678 /* One source operand. */
3679 rm = ((rm + delta_m) & (bank_mask - 1))
3680 | (rm & bank_mask);
3681 gen_mov_F0_vreg(dp, rm);
3682 } else {
3683 /* Two source operands. */
3684 rn = ((rn + delta_d) & (bank_mask - 1))
3685 | (rn & bank_mask);
3686 gen_mov_F0_vreg(dp, rn);
3687 if (delta_m) {
3688 rm = ((rm + delta_m) & (bank_mask - 1))
3689 | (rm & bank_mask);
3690 gen_mov_F1_vreg(dp, rm);
3695 break;
3696 case 0xc:
3697 case 0xd:
3698 if ((insn & 0x03e00000) == 0x00400000) {
3699 /* two-register transfer */
3700 rn = (insn >> 16) & 0xf;
3701 rd = (insn >> 12) & 0xf;
3702 if (dp) {
3703 VFP_DREG_M(rm, insn);
3704 } else {
3705 rm = VFP_SREG_M(insn);
3708 if (insn & ARM_CP_RW_BIT) {
3709 /* vfp->arm */
3710 if (dp) {
3711 gen_mov_F0_vreg(0, rm * 2);
3712 tmp = gen_vfp_mrs();
3713 store_reg(s, rd, tmp);
3714 gen_mov_F0_vreg(0, rm * 2 + 1);
3715 tmp = gen_vfp_mrs();
3716 store_reg(s, rn, tmp);
3717 } else {
3718 gen_mov_F0_vreg(0, rm);
3719 tmp = gen_vfp_mrs();
3720 store_reg(s, rd, tmp);
3721 gen_mov_F0_vreg(0, rm + 1);
3722 tmp = gen_vfp_mrs();
3723 store_reg(s, rn, tmp);
3725 } else {
3726 /* arm->vfp */
3727 if (dp) {
3728 tmp = load_reg(s, rd);
3729 gen_vfp_msr(tmp);
3730 gen_mov_vreg_F0(0, rm * 2);
3731 tmp = load_reg(s, rn);
3732 gen_vfp_msr(tmp);
3733 gen_mov_vreg_F0(0, rm * 2 + 1);
3734 } else {
3735 tmp = load_reg(s, rd);
3736 gen_vfp_msr(tmp);
3737 gen_mov_vreg_F0(0, rm);
3738 tmp = load_reg(s, rn);
3739 gen_vfp_msr(tmp);
3740 gen_mov_vreg_F0(0, rm + 1);
3743 } else {
3744 /* Load/store */
3745 rn = (insn >> 16) & 0xf;
3746 if (dp)
3747 VFP_DREG_D(rd, insn);
3748 else
3749 rd = VFP_SREG_D(insn);
3750 if ((insn & 0x01200000) == 0x01000000) {
3751 /* Single load/store */
3752 offset = (insn & 0xff) << 2;
3753 if ((insn & (1 << 23)) == 0)
3754 offset = -offset;
3755 if (s->thumb && rn == 15) {
3756 /* This is actually UNPREDICTABLE */
3757 addr = tcg_temp_new_i32();
3758 tcg_gen_movi_i32(addr, s->pc & ~2);
3759 } else {
3760 addr = load_reg(s, rn);
3762 tcg_gen_addi_i32(addr, addr, offset);
3763 if (insn & (1 << 20)) {
3764 gen_vfp_ld(s, dp, addr);
3765 gen_mov_vreg_F0(dp, rd);
3766 } else {
3767 gen_mov_F0_vreg(dp, rd);
3768 gen_vfp_st(s, dp, addr);
3770 tcg_temp_free_i32(addr);
3771 } else {
3772 /* load/store multiple */
3773 int w = insn & (1 << 21);
3774 if (dp)
3775 n = (insn >> 1) & 0x7f;
3776 else
3777 n = insn & 0xff;
3779 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3780 /* P == U , W == 1 => UNDEF */
3781 return 1;
3783 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3784 /* UNPREDICTABLE cases for bad immediates: we choose to
3785 * UNDEF to avoid generating huge numbers of TCG ops
3787 return 1;
3789 if (rn == 15 && w) {
3790 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3791 return 1;
3794 if (s->thumb && rn == 15) {
3795 /* This is actually UNPREDICTABLE */
3796 addr = tcg_temp_new_i32();
3797 tcg_gen_movi_i32(addr, s->pc & ~2);
3798 } else {
3799 addr = load_reg(s, rn);
3801 if (insn & (1 << 24)) /* pre-decrement */
3802 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3804 if (dp)
3805 offset = 8;
3806 else
3807 offset = 4;
3808 for (i = 0; i < n; i++) {
3809 if (insn & ARM_CP_RW_BIT) {
3810 /* load */
3811 gen_vfp_ld(s, dp, addr);
3812 gen_mov_vreg_F0(dp, rd + i);
3813 } else {
3814 /* store */
3815 gen_mov_F0_vreg(dp, rd + i);
3816 gen_vfp_st(s, dp, addr);
3818 tcg_gen_addi_i32(addr, addr, offset);
3820 if (w) {
3821 /* writeback */
3822 if (insn & (1 << 24))
3823 offset = -offset * n;
3824 else if (dp && (insn & 1))
3825 offset = 4;
3826 else
3827 offset = 0;
3829 if (offset != 0)
3830 tcg_gen_addi_i32(addr, addr, offset);
3831 store_reg(s, rn, addr);
3832 } else {
3833 tcg_temp_free_i32(addr);
3837 break;
3838 default:
3839 /* Should never happen. */
3840 return 1;
3842 return 0;
3845 static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
3847 TranslationBlock *tb;
3849 tb = s->tb;
3850 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3851 tcg_gen_goto_tb(n);
3852 gen_set_pc_im(s, dest);
3853 tcg_gen_exit_tb((uintptr_t)tb + n);
3854 } else {
3855 gen_set_pc_im(s, dest);
3856 tcg_gen_exit_tb(0);
3860 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3862 if (unlikely(s->singlestep_enabled)) {
3863 /* An indirect jump so that we still trigger the debug exception. */
3864 if (s->thumb)
3865 dest |= 1;
3866 gen_bx_im(s, dest);
3867 } else {
3868 gen_goto_tb(s, 0, dest);
3869 s->is_jmp = DISAS_TB_JUMP;
3873 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
3875 if (x)
3876 tcg_gen_sari_i32(t0, t0, 16);
3877 else
3878 gen_sxth(t0);
3879 if (y)
3880 tcg_gen_sari_i32(t1, t1, 16);
3881 else
3882 gen_sxth(t1);
3883 tcg_gen_mul_i32(t0, t0, t1);
3886 /* Return the mask of PSR bits set by a MSR instruction. */
3887 static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
3888 uint32_t mask;
3890 mask = 0;
3891 if (flags & (1 << 0))
3892 mask |= 0xff;
3893 if (flags & (1 << 1))
3894 mask |= 0xff00;
3895 if (flags & (1 << 2))
3896 mask |= 0xff0000;
3897 if (flags & (1 << 3))
3898 mask |= 0xff000000;
3900 /* Mask out undefined bits. */
3901 mask &= ~CPSR_RESERVED;
3902 if (!arm_feature(env, ARM_FEATURE_V4T))
3903 mask &= ~CPSR_T;
3904 if (!arm_feature(env, ARM_FEATURE_V5))
3905 mask &= ~CPSR_Q; /* V5TE in reality*/
3906 if (!arm_feature(env, ARM_FEATURE_V6))
3907 mask &= ~(CPSR_E | CPSR_GE);
3908 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3909 mask &= ~CPSR_IT;
3910 /* Mask out execution state bits. */
3911 if (!spsr)
3912 mask &= ~CPSR_EXEC;
3913 /* Mask out privileged bits. */
3914 if (IS_USER(s))
3915 mask &= CPSR_USER;
3916 return mask;
3919 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3920 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
3922 TCGv_i32 tmp;
3923 if (spsr) {
3924 /* ??? This is also undefined in system mode. */
3925 if (IS_USER(s))
3926 return 1;
3928 tmp = load_cpu_field(spsr);
3929 tcg_gen_andi_i32(tmp, tmp, ~mask);
3930 tcg_gen_andi_i32(t0, t0, mask);
3931 tcg_gen_or_i32(tmp, tmp, t0);
3932 store_cpu_field(tmp, spsr);
3933 } else {
3934 gen_set_cpsr(t0, mask);
3936 tcg_temp_free_i32(t0);
3937 gen_lookup_tb(s);
3938 return 0;
3941 /* Returns nonzero if access to the PSR is not permitted. */
3942 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3944 TCGv_i32 tmp;
3945 tmp = tcg_temp_new_i32();
3946 tcg_gen_movi_i32(tmp, val);
3947 return gen_set_psr(s, mask, spsr, tmp);
3950 /* Generate an old-style exception return. Marks pc as dead. */
3951 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3953 TCGv_i32 tmp;
3954 store_reg(s, 15, pc);
3955 tmp = load_cpu_field(spsr);
3956 gen_set_cpsr(tmp, 0xffffffff);
3957 tcg_temp_free_i32(tmp);
3958 s->is_jmp = DISAS_UPDATE;
3961 /* Generate a v6 exception return. Marks both values as dead. */
3962 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
3964 gen_set_cpsr(cpsr, 0xffffffff);
3965 tcg_temp_free_i32(cpsr);
3966 store_reg(s, 15, pc);
3967 s->is_jmp = DISAS_UPDATE;
3970 static void gen_nop_hint(DisasContext *s, int val)
3972 switch (val) {
3973 case 3: /* wfi */
3974 gen_set_pc_im(s, s->pc);
3975 s->is_jmp = DISAS_WFI;
3976 break;
3977 case 2: /* wfe */
3978 gen_set_pc_im(s, s->pc);
3979 s->is_jmp = DISAS_WFE;
3980 break;
3981 case 4: /* sev */
3982 case 5: /* sevl */
3983 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
3984 default: /* nop */
3985 break;
3989 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3991 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
3993 switch (size) {
3994 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3995 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3996 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3997 default: abort();
4001 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
4003 switch (size) {
4004 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4005 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4006 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
4007 default: return;
4011 /* 32-bit pairwise ops end up the same as the elementwise versions. */
4012 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
4013 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
4014 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
4015 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
4017 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
4018 switch ((size << 1) | u) { \
4019 case 0: \
4020 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
4021 break; \
4022 case 1: \
4023 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
4024 break; \
4025 case 2: \
4026 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
4027 break; \
4028 case 3: \
4029 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
4030 break; \
4031 case 4: \
4032 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
4033 break; \
4034 case 5: \
4035 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
4036 break; \
4037 default: return 1; \
4038 }} while (0)
4040 #define GEN_NEON_INTEGER_OP(name) do { \
4041 switch ((size << 1) | u) { \
4042 case 0: \
4043 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4044 break; \
4045 case 1: \
4046 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4047 break; \
4048 case 2: \
4049 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4050 break; \
4051 case 3: \
4052 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4053 break; \
4054 case 4: \
4055 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4056 break; \
4057 case 5: \
4058 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4059 break; \
4060 default: return 1; \
4061 }} while (0)
4063 static TCGv_i32 neon_load_scratch(int scratch)
4065 TCGv_i32 tmp = tcg_temp_new_i32();
4066 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4067 return tmp;
4070 static void neon_store_scratch(int scratch, TCGv_i32 var)
4072 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4073 tcg_temp_free_i32(var);
4076 static inline TCGv_i32 neon_get_scalar(int size, int reg)
4078 TCGv_i32 tmp;
4079 if (size == 1) {
4080 tmp = neon_load_reg(reg & 7, reg >> 4);
4081 if (reg & 8) {
4082 gen_neon_dup_high16(tmp);
4083 } else {
4084 gen_neon_dup_low16(tmp);
4086 } else {
4087 tmp = neon_load_reg(reg & 15, reg >> 4);
4089 return tmp;
4092 static int gen_neon_unzip(int rd, int rm, int size, int q)
4094 TCGv_i32 tmp, tmp2;
4095 if (!q && size == 2) {
4096 return 1;
4098 tmp = tcg_const_i32(rd);
4099 tmp2 = tcg_const_i32(rm);
4100 if (q) {
4101 switch (size) {
4102 case 0:
4103 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
4104 break;
4105 case 1:
4106 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
4107 break;
4108 case 2:
4109 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
4110 break;
4111 default:
4112 abort();
4114 } else {
4115 switch (size) {
4116 case 0:
4117 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
4118 break;
4119 case 1:
4120 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
4121 break;
4122 default:
4123 abort();
4126 tcg_temp_free_i32(tmp);
4127 tcg_temp_free_i32(tmp2);
4128 return 0;
4131 static int gen_neon_zip(int rd, int rm, int size, int q)
4133 TCGv_i32 tmp, tmp2;
4134 if (!q && size == 2) {
4135 return 1;
4137 tmp = tcg_const_i32(rd);
4138 tmp2 = tcg_const_i32(rm);
4139 if (q) {
4140 switch (size) {
4141 case 0:
4142 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
4143 break;
4144 case 1:
4145 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
4146 break;
4147 case 2:
4148 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
4149 break;
4150 default:
4151 abort();
4153 } else {
4154 switch (size) {
4155 case 0:
4156 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
4157 break;
4158 case 1:
4159 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
4160 break;
4161 default:
4162 abort();
4165 tcg_temp_free_i32(tmp);
4166 tcg_temp_free_i32(tmp2);
4167 return 0;
4170 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
4172 TCGv_i32 rd, tmp;
4174 rd = tcg_temp_new_i32();
4175 tmp = tcg_temp_new_i32();
4177 tcg_gen_shli_i32(rd, t0, 8);
4178 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4179 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4180 tcg_gen_or_i32(rd, rd, tmp);
4182 tcg_gen_shri_i32(t1, t1, 8);
4183 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4184 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4185 tcg_gen_or_i32(t1, t1, tmp);
4186 tcg_gen_mov_i32(t0, rd);
4188 tcg_temp_free_i32(tmp);
4189 tcg_temp_free_i32(rd);
4192 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
4194 TCGv_i32 rd, tmp;
4196 rd = tcg_temp_new_i32();
4197 tmp = tcg_temp_new_i32();
4199 tcg_gen_shli_i32(rd, t0, 16);
4200 tcg_gen_andi_i32(tmp, t1, 0xffff);
4201 tcg_gen_or_i32(rd, rd, tmp);
4202 tcg_gen_shri_i32(t1, t1, 16);
4203 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4204 tcg_gen_or_i32(t1, t1, tmp);
4205 tcg_gen_mov_i32(t0, rd);
4207 tcg_temp_free_i32(tmp);
4208 tcg_temp_free_i32(rd);
4212 static struct {
4213 int nregs;
4214 int interleave;
4215 int spacing;
4216 } neon_ls_element_type[11] = {
4217 {4, 4, 1},
4218 {4, 4, 2},
4219 {4, 1, 1},
4220 {4, 2, 1},
4221 {3, 3, 1},
4222 {3, 3, 2},
4223 {3, 1, 1},
4224 {1, 1, 1},
4225 {2, 2, 1},
4226 {2, 2, 2},
4227 {2, 1, 1}
4230 /* Translate a NEON load/store element instruction. Return nonzero if the
4231 instruction is invalid. */
4232 static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4234 int rd, rn, rm;
4235 int op;
4236 int nregs;
4237 int interleave;
4238 int spacing;
4239 int stride;
4240 int size;
4241 int reg;
4242 int pass;
4243 int load;
4244 int shift;
4245 int n;
4246 TCGv_i32 addr;
4247 TCGv_i32 tmp;
4248 TCGv_i32 tmp2;
4249 TCGv_i64 tmp64;
4251 /* FIXME: this access check should not take precedence over UNDEF
4252 * for invalid encodings; we will generate incorrect syndrome information
4253 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4255 if (!s->cpacr_fpen) {
4256 gen_exception_insn(s, 4, EXCP_UDEF,
4257 syn_fp_access_trap(1, 0xe, s->thumb));
4258 return 0;
4261 if (!s->vfp_enabled)
4262 return 1;
4263 VFP_DREG_D(rd, insn);
4264 rn = (insn >> 16) & 0xf;
4265 rm = insn & 0xf;
4266 load = (insn & (1 << 21)) != 0;
4267 if ((insn & (1 << 23)) == 0) {
4268 /* Load store all elements. */
4269 op = (insn >> 8) & 0xf;
4270 size = (insn >> 6) & 3;
4271 if (op > 10)
4272 return 1;
4273 /* Catch UNDEF cases for bad values of align field */
4274 switch (op & 0xc) {
4275 case 4:
4276 if (((insn >> 5) & 1) == 1) {
4277 return 1;
4279 break;
4280 case 8:
4281 if (((insn >> 4) & 3) == 3) {
4282 return 1;
4284 break;
4285 default:
4286 break;
4288 nregs = neon_ls_element_type[op].nregs;
4289 interleave = neon_ls_element_type[op].interleave;
4290 spacing = neon_ls_element_type[op].spacing;
4291 if (size == 3 && (interleave | spacing) != 1)
4292 return 1;
4293 addr = tcg_temp_new_i32();
4294 load_reg_var(s, addr, rn);
4295 stride = (1 << size) * interleave;
4296 for (reg = 0; reg < nregs; reg++) {
4297 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
4298 load_reg_var(s, addr, rn);
4299 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
4300 } else if (interleave == 2 && nregs == 4 && reg == 2) {
4301 load_reg_var(s, addr, rn);
4302 tcg_gen_addi_i32(addr, addr, 1 << size);
4304 if (size == 3) {
4305 tmp64 = tcg_temp_new_i64();
4306 if (load) {
4307 gen_aa32_ld64(tmp64, addr, IS_USER(s));
4308 neon_store_reg64(tmp64, rd);
4309 } else {
4310 neon_load_reg64(tmp64, rd);
4311 gen_aa32_st64(tmp64, addr, IS_USER(s));
4313 tcg_temp_free_i64(tmp64);
4314 tcg_gen_addi_i32(addr, addr, stride);
4315 } else {
4316 for (pass = 0; pass < 2; pass++) {
4317 if (size == 2) {
4318 if (load) {
4319 tmp = tcg_temp_new_i32();
4320 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4321 neon_store_reg(rd, pass, tmp);
4322 } else {
4323 tmp = neon_load_reg(rd, pass);
4324 gen_aa32_st32(tmp, addr, IS_USER(s));
4325 tcg_temp_free_i32(tmp);
4327 tcg_gen_addi_i32(addr, addr, stride);
4328 } else if (size == 1) {
4329 if (load) {
4330 tmp = tcg_temp_new_i32();
4331 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4332 tcg_gen_addi_i32(addr, addr, stride);
4333 tmp2 = tcg_temp_new_i32();
4334 gen_aa32_ld16u(tmp2, addr, IS_USER(s));
4335 tcg_gen_addi_i32(addr, addr, stride);
4336 tcg_gen_shli_i32(tmp2, tmp2, 16);
4337 tcg_gen_or_i32(tmp, tmp, tmp2);
4338 tcg_temp_free_i32(tmp2);
4339 neon_store_reg(rd, pass, tmp);
4340 } else {
4341 tmp = neon_load_reg(rd, pass);
4342 tmp2 = tcg_temp_new_i32();
4343 tcg_gen_shri_i32(tmp2, tmp, 16);
4344 gen_aa32_st16(tmp, addr, IS_USER(s));
4345 tcg_temp_free_i32(tmp);
4346 tcg_gen_addi_i32(addr, addr, stride);
4347 gen_aa32_st16(tmp2, addr, IS_USER(s));
4348 tcg_temp_free_i32(tmp2);
4349 tcg_gen_addi_i32(addr, addr, stride);
4351 } else /* size == 0 */ {
4352 if (load) {
4353 TCGV_UNUSED_I32(tmp2);
4354 for (n = 0; n < 4; n++) {
4355 tmp = tcg_temp_new_i32();
4356 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4357 tcg_gen_addi_i32(addr, addr, stride);
4358 if (n == 0) {
4359 tmp2 = tmp;
4360 } else {
4361 tcg_gen_shli_i32(tmp, tmp, n * 8);
4362 tcg_gen_or_i32(tmp2, tmp2, tmp);
4363 tcg_temp_free_i32(tmp);
4366 neon_store_reg(rd, pass, tmp2);
4367 } else {
4368 tmp2 = neon_load_reg(rd, pass);
4369 for (n = 0; n < 4; n++) {
4370 tmp = tcg_temp_new_i32();
4371 if (n == 0) {
4372 tcg_gen_mov_i32(tmp, tmp2);
4373 } else {
4374 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4376 gen_aa32_st8(tmp, addr, IS_USER(s));
4377 tcg_temp_free_i32(tmp);
4378 tcg_gen_addi_i32(addr, addr, stride);
4380 tcg_temp_free_i32(tmp2);
4385 rd += spacing;
4387 tcg_temp_free_i32(addr);
4388 stride = nregs * 8;
4389 } else {
4390 size = (insn >> 10) & 3;
4391 if (size == 3) {
4392 /* Load single element to all lanes. */
4393 int a = (insn >> 4) & 1;
4394 if (!load) {
4395 return 1;
4397 size = (insn >> 6) & 3;
4398 nregs = ((insn >> 8) & 3) + 1;
4400 if (size == 3) {
4401 if (nregs != 4 || a == 0) {
4402 return 1;
4404 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4405 size = 2;
4407 if (nregs == 1 && a == 1 && size == 0) {
4408 return 1;
4410 if (nregs == 3 && a == 1) {
4411 return 1;
4413 addr = tcg_temp_new_i32();
4414 load_reg_var(s, addr, rn);
4415 if (nregs == 1) {
4416 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4417 tmp = gen_load_and_replicate(s, addr, size);
4418 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4419 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4420 if (insn & (1 << 5)) {
4421 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4422 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4424 tcg_temp_free_i32(tmp);
4425 } else {
4426 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4427 stride = (insn & (1 << 5)) ? 2 : 1;
4428 for (reg = 0; reg < nregs; reg++) {
4429 tmp = gen_load_and_replicate(s, addr, size);
4430 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4431 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4432 tcg_temp_free_i32(tmp);
4433 tcg_gen_addi_i32(addr, addr, 1 << size);
4434 rd += stride;
4437 tcg_temp_free_i32(addr);
4438 stride = (1 << size) * nregs;
4439 } else {
4440 /* Single element. */
4441 int idx = (insn >> 4) & 0xf;
4442 pass = (insn >> 7) & 1;
4443 switch (size) {
4444 case 0:
4445 shift = ((insn >> 5) & 3) * 8;
4446 stride = 1;
4447 break;
4448 case 1:
4449 shift = ((insn >> 6) & 1) * 16;
4450 stride = (insn & (1 << 5)) ? 2 : 1;
4451 break;
4452 case 2:
4453 shift = 0;
4454 stride = (insn & (1 << 6)) ? 2 : 1;
4455 break;
4456 default:
4457 abort();
4459 nregs = ((insn >> 8) & 3) + 1;
4460 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4461 switch (nregs) {
4462 case 1:
4463 if (((idx & (1 << size)) != 0) ||
4464 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4465 return 1;
4467 break;
4468 case 3:
4469 if ((idx & 1) != 0) {
4470 return 1;
4472 /* fall through */
4473 case 2:
4474 if (size == 2 && (idx & 2) != 0) {
4475 return 1;
4477 break;
4478 case 4:
4479 if ((size == 2) && ((idx & 3) == 3)) {
4480 return 1;
4482 break;
4483 default:
4484 abort();
4486 if ((rd + stride * (nregs - 1)) > 31) {
4487 /* Attempts to write off the end of the register file
4488 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4489 * the neon_load_reg() would write off the end of the array.
4491 return 1;
4493 addr = tcg_temp_new_i32();
4494 load_reg_var(s, addr, rn);
4495 for (reg = 0; reg < nregs; reg++) {
4496 if (load) {
4497 tmp = tcg_temp_new_i32();
4498 switch (size) {
4499 case 0:
4500 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4501 break;
4502 case 1:
4503 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4504 break;
4505 case 2:
4506 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4507 break;
4508 default: /* Avoid compiler warnings. */
4509 abort();
4511 if (size != 2) {
4512 tmp2 = neon_load_reg(rd, pass);
4513 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4514 shift, size ? 16 : 8);
4515 tcg_temp_free_i32(tmp2);
4517 neon_store_reg(rd, pass, tmp);
4518 } else { /* Store */
4519 tmp = neon_load_reg(rd, pass);
4520 if (shift)
4521 tcg_gen_shri_i32(tmp, tmp, shift);
4522 switch (size) {
4523 case 0:
4524 gen_aa32_st8(tmp, addr, IS_USER(s));
4525 break;
4526 case 1:
4527 gen_aa32_st16(tmp, addr, IS_USER(s));
4528 break;
4529 case 2:
4530 gen_aa32_st32(tmp, addr, IS_USER(s));
4531 break;
4533 tcg_temp_free_i32(tmp);
4535 rd += stride;
4536 tcg_gen_addi_i32(addr, addr, 1 << size);
4538 tcg_temp_free_i32(addr);
4539 stride = nregs * (1 << size);
4542 if (rm != 15) {
4543 TCGv_i32 base;
4545 base = load_reg(s, rn);
4546 if (rm == 13) {
4547 tcg_gen_addi_i32(base, base, stride);
4548 } else {
4549 TCGv_i32 index;
4550 index = load_reg(s, rm);
4551 tcg_gen_add_i32(base, base, index);
4552 tcg_temp_free_i32(index);
4554 store_reg(s, rn, base);
4556 return 0;
4559 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4560 static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
4562 tcg_gen_and_i32(t, t, c);
4563 tcg_gen_andc_i32(f, f, c);
4564 tcg_gen_or_i32(dest, t, f);
4567 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4569 switch (size) {
4570 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4571 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4572 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4573 default: abort();
4577 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4579 switch (size) {
4580 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4581 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4582 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4583 default: abort();
4587 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
4589 switch (size) {
4590 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4591 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4592 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4593 default: abort();
4597 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4599 switch (size) {
4600 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4601 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4602 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4603 default: abort();
4607 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
4608 int q, int u)
4610 if (q) {
4611 if (u) {
4612 switch (size) {
4613 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4614 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4615 default: abort();
4617 } else {
4618 switch (size) {
4619 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4620 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4621 default: abort();
4624 } else {
4625 if (u) {
4626 switch (size) {
4627 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4628 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4629 default: abort();
4631 } else {
4632 switch (size) {
4633 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4634 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4635 default: abort();
4641 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
4643 if (u) {
4644 switch (size) {
4645 case 0: gen_helper_neon_widen_u8(dest, src); break;
4646 case 1: gen_helper_neon_widen_u16(dest, src); break;
4647 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4648 default: abort();
4650 } else {
4651 switch (size) {
4652 case 0: gen_helper_neon_widen_s8(dest, src); break;
4653 case 1: gen_helper_neon_widen_s16(dest, src); break;
4654 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4655 default: abort();
4658 tcg_temp_free_i32(src);
4661 static inline void gen_neon_addl(int size)
4663 switch (size) {
4664 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4665 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4666 case 2: tcg_gen_add_i64(CPU_V001); break;
4667 default: abort();
4671 static inline void gen_neon_subl(int size)
4673 switch (size) {
4674 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4675 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4676 case 2: tcg_gen_sub_i64(CPU_V001); break;
4677 default: abort();
4681 static inline void gen_neon_negl(TCGv_i64 var, int size)
4683 switch (size) {
4684 case 0: gen_helper_neon_negl_u16(var, var); break;
4685 case 1: gen_helper_neon_negl_u32(var, var); break;
4686 case 2:
4687 tcg_gen_neg_i64(var, var);
4688 break;
4689 default: abort();
4693 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4695 switch (size) {
4696 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4697 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4698 default: abort();
4702 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4703 int size, int u)
4705 TCGv_i64 tmp;
4707 switch ((size << 1) | u) {
4708 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4709 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4710 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4711 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4712 case 4:
4713 tmp = gen_muls_i64_i32(a, b);
4714 tcg_gen_mov_i64(dest, tmp);
4715 tcg_temp_free_i64(tmp);
4716 break;
4717 case 5:
4718 tmp = gen_mulu_i64_i32(a, b);
4719 tcg_gen_mov_i64(dest, tmp);
4720 tcg_temp_free_i64(tmp);
4721 break;
4722 default: abort();
4725 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4726 Don't forget to clean them now. */
4727 if (size < 2) {
4728 tcg_temp_free_i32(a);
4729 tcg_temp_free_i32(b);
4733 static void gen_neon_narrow_op(int op, int u, int size,
4734 TCGv_i32 dest, TCGv_i64 src)
4736 if (op) {
4737 if (u) {
4738 gen_neon_unarrow_sats(size, dest, src);
4739 } else {
4740 gen_neon_narrow(size, dest, src);
4742 } else {
4743 if (u) {
4744 gen_neon_narrow_satu(size, dest, src);
4745 } else {
4746 gen_neon_narrow_sats(size, dest, src);
4751 /* Symbolic constants for op fields for Neon 3-register same-length.
4752 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4753 * table A7-9.
4755 #define NEON_3R_VHADD 0
4756 #define NEON_3R_VQADD 1
4757 #define NEON_3R_VRHADD 2
4758 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4759 #define NEON_3R_VHSUB 4
4760 #define NEON_3R_VQSUB 5
4761 #define NEON_3R_VCGT 6
4762 #define NEON_3R_VCGE 7
4763 #define NEON_3R_VSHL 8
4764 #define NEON_3R_VQSHL 9
4765 #define NEON_3R_VRSHL 10
4766 #define NEON_3R_VQRSHL 11
4767 #define NEON_3R_VMAX 12
4768 #define NEON_3R_VMIN 13
4769 #define NEON_3R_VABD 14
4770 #define NEON_3R_VABA 15
4771 #define NEON_3R_VADD_VSUB 16
4772 #define NEON_3R_VTST_VCEQ 17
4773 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4774 #define NEON_3R_VMUL 19
4775 #define NEON_3R_VPMAX 20
4776 #define NEON_3R_VPMIN 21
4777 #define NEON_3R_VQDMULH_VQRDMULH 22
4778 #define NEON_3R_VPADD 23
4779 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4780 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4781 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4782 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4783 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4784 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4785 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
4787 static const uint8_t neon_3r_sizes[] = {
4788 [NEON_3R_VHADD] = 0x7,
4789 [NEON_3R_VQADD] = 0xf,
4790 [NEON_3R_VRHADD] = 0x7,
4791 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4792 [NEON_3R_VHSUB] = 0x7,
4793 [NEON_3R_VQSUB] = 0xf,
4794 [NEON_3R_VCGT] = 0x7,
4795 [NEON_3R_VCGE] = 0x7,
4796 [NEON_3R_VSHL] = 0xf,
4797 [NEON_3R_VQSHL] = 0xf,
4798 [NEON_3R_VRSHL] = 0xf,
4799 [NEON_3R_VQRSHL] = 0xf,
4800 [NEON_3R_VMAX] = 0x7,
4801 [NEON_3R_VMIN] = 0x7,
4802 [NEON_3R_VABD] = 0x7,
4803 [NEON_3R_VABA] = 0x7,
4804 [NEON_3R_VADD_VSUB] = 0xf,
4805 [NEON_3R_VTST_VCEQ] = 0x7,
4806 [NEON_3R_VML] = 0x7,
4807 [NEON_3R_VMUL] = 0x7,
4808 [NEON_3R_VPMAX] = 0x7,
4809 [NEON_3R_VPMIN] = 0x7,
4810 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4811 [NEON_3R_VPADD] = 0x7,
4812 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
4813 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4814 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4815 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4816 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4817 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4818 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
4821 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4822 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4823 * table A7-13.
4825 #define NEON_2RM_VREV64 0
4826 #define NEON_2RM_VREV32 1
4827 #define NEON_2RM_VREV16 2
4828 #define NEON_2RM_VPADDL 4
4829 #define NEON_2RM_VPADDL_U 5
4830 #define NEON_2RM_AESE 6 /* Includes AESD */
4831 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
4832 #define NEON_2RM_VCLS 8
4833 #define NEON_2RM_VCLZ 9
4834 #define NEON_2RM_VCNT 10
4835 #define NEON_2RM_VMVN 11
4836 #define NEON_2RM_VPADAL 12
4837 #define NEON_2RM_VPADAL_U 13
4838 #define NEON_2RM_VQABS 14
4839 #define NEON_2RM_VQNEG 15
4840 #define NEON_2RM_VCGT0 16
4841 #define NEON_2RM_VCGE0 17
4842 #define NEON_2RM_VCEQ0 18
4843 #define NEON_2RM_VCLE0 19
4844 #define NEON_2RM_VCLT0 20
4845 #define NEON_2RM_VABS 22
4846 #define NEON_2RM_VNEG 23
4847 #define NEON_2RM_VCGT0_F 24
4848 #define NEON_2RM_VCGE0_F 25
4849 #define NEON_2RM_VCEQ0_F 26
4850 #define NEON_2RM_VCLE0_F 27
4851 #define NEON_2RM_VCLT0_F 28
4852 #define NEON_2RM_VABS_F 30
4853 #define NEON_2RM_VNEG_F 31
4854 #define NEON_2RM_VSWP 32
4855 #define NEON_2RM_VTRN 33
4856 #define NEON_2RM_VUZP 34
4857 #define NEON_2RM_VZIP 35
4858 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4859 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4860 #define NEON_2RM_VSHLL 38
4861 #define NEON_2RM_VRINTN 40
4862 #define NEON_2RM_VRINTX 41
4863 #define NEON_2RM_VRINTA 42
4864 #define NEON_2RM_VRINTZ 43
4865 #define NEON_2RM_VCVT_F16_F32 44
4866 #define NEON_2RM_VRINTM 45
4867 #define NEON_2RM_VCVT_F32_F16 46
4868 #define NEON_2RM_VRINTP 47
4869 #define NEON_2RM_VCVTAU 48
4870 #define NEON_2RM_VCVTAS 49
4871 #define NEON_2RM_VCVTNU 50
4872 #define NEON_2RM_VCVTNS 51
4873 #define NEON_2RM_VCVTPU 52
4874 #define NEON_2RM_VCVTPS 53
4875 #define NEON_2RM_VCVTMU 54
4876 #define NEON_2RM_VCVTMS 55
4877 #define NEON_2RM_VRECPE 56
4878 #define NEON_2RM_VRSQRTE 57
4879 #define NEON_2RM_VRECPE_F 58
4880 #define NEON_2RM_VRSQRTE_F 59
4881 #define NEON_2RM_VCVT_FS 60
4882 #define NEON_2RM_VCVT_FU 61
4883 #define NEON_2RM_VCVT_SF 62
4884 #define NEON_2RM_VCVT_UF 63
4886 static int neon_2rm_is_float_op(int op)
4888 /* Return true if this neon 2reg-misc op is float-to-float */
4889 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4890 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
4891 op == NEON_2RM_VRINTM ||
4892 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
4893 op >= NEON_2RM_VRECPE_F);
4896 /* Each entry in this array has bit n set if the insn allows
4897 * size value n (otherwise it will UNDEF). Since unallocated
4898 * op values will have no bits set they always UNDEF.
4900 static const uint8_t neon_2rm_sizes[] = {
4901 [NEON_2RM_VREV64] = 0x7,
4902 [NEON_2RM_VREV32] = 0x3,
4903 [NEON_2RM_VREV16] = 0x1,
4904 [NEON_2RM_VPADDL] = 0x7,
4905 [NEON_2RM_VPADDL_U] = 0x7,
4906 [NEON_2RM_AESE] = 0x1,
4907 [NEON_2RM_AESMC] = 0x1,
4908 [NEON_2RM_VCLS] = 0x7,
4909 [NEON_2RM_VCLZ] = 0x7,
4910 [NEON_2RM_VCNT] = 0x1,
4911 [NEON_2RM_VMVN] = 0x1,
4912 [NEON_2RM_VPADAL] = 0x7,
4913 [NEON_2RM_VPADAL_U] = 0x7,
4914 [NEON_2RM_VQABS] = 0x7,
4915 [NEON_2RM_VQNEG] = 0x7,
4916 [NEON_2RM_VCGT0] = 0x7,
4917 [NEON_2RM_VCGE0] = 0x7,
4918 [NEON_2RM_VCEQ0] = 0x7,
4919 [NEON_2RM_VCLE0] = 0x7,
4920 [NEON_2RM_VCLT0] = 0x7,
4921 [NEON_2RM_VABS] = 0x7,
4922 [NEON_2RM_VNEG] = 0x7,
4923 [NEON_2RM_VCGT0_F] = 0x4,
4924 [NEON_2RM_VCGE0_F] = 0x4,
4925 [NEON_2RM_VCEQ0_F] = 0x4,
4926 [NEON_2RM_VCLE0_F] = 0x4,
4927 [NEON_2RM_VCLT0_F] = 0x4,
4928 [NEON_2RM_VABS_F] = 0x4,
4929 [NEON_2RM_VNEG_F] = 0x4,
4930 [NEON_2RM_VSWP] = 0x1,
4931 [NEON_2RM_VTRN] = 0x7,
4932 [NEON_2RM_VUZP] = 0x7,
4933 [NEON_2RM_VZIP] = 0x7,
4934 [NEON_2RM_VMOVN] = 0x7,
4935 [NEON_2RM_VQMOVN] = 0x7,
4936 [NEON_2RM_VSHLL] = 0x7,
4937 [NEON_2RM_VRINTN] = 0x4,
4938 [NEON_2RM_VRINTX] = 0x4,
4939 [NEON_2RM_VRINTA] = 0x4,
4940 [NEON_2RM_VRINTZ] = 0x4,
4941 [NEON_2RM_VCVT_F16_F32] = 0x2,
4942 [NEON_2RM_VRINTM] = 0x4,
4943 [NEON_2RM_VCVT_F32_F16] = 0x2,
4944 [NEON_2RM_VRINTP] = 0x4,
4945 [NEON_2RM_VCVTAU] = 0x4,
4946 [NEON_2RM_VCVTAS] = 0x4,
4947 [NEON_2RM_VCVTNU] = 0x4,
4948 [NEON_2RM_VCVTNS] = 0x4,
4949 [NEON_2RM_VCVTPU] = 0x4,
4950 [NEON_2RM_VCVTPS] = 0x4,
4951 [NEON_2RM_VCVTMU] = 0x4,
4952 [NEON_2RM_VCVTMS] = 0x4,
4953 [NEON_2RM_VRECPE] = 0x4,
4954 [NEON_2RM_VRSQRTE] = 0x4,
4955 [NEON_2RM_VRECPE_F] = 0x4,
4956 [NEON_2RM_VRSQRTE_F] = 0x4,
4957 [NEON_2RM_VCVT_FS] = 0x4,
4958 [NEON_2RM_VCVT_FU] = 0x4,
4959 [NEON_2RM_VCVT_SF] = 0x4,
4960 [NEON_2RM_VCVT_UF] = 0x4,
4963 /* Translate a NEON data processing instruction. Return nonzero if the
4964 instruction is invalid.
4965 We process data in a mixture of 32-bit and 64-bit chunks.
4966 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4968 static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4970 int op;
4971 int q;
4972 int rd, rn, rm;
4973 int size;
4974 int shift;
4975 int pass;
4976 int count;
4977 int pairwise;
4978 int u;
4979 uint32_t imm, mask;
4980 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
4981 TCGv_i64 tmp64;
4983 /* FIXME: this access check should not take precedence over UNDEF
4984 * for invalid encodings; we will generate incorrect syndrome information
4985 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4987 if (!s->cpacr_fpen) {
4988 gen_exception_insn(s, 4, EXCP_UDEF,
4989 syn_fp_access_trap(1, 0xe, s->thumb));
4990 return 0;
4993 if (!s->vfp_enabled)
4994 return 1;
4995 q = (insn & (1 << 6)) != 0;
4996 u = (insn >> 24) & 1;
4997 VFP_DREG_D(rd, insn);
4998 VFP_DREG_N(rn, insn);
4999 VFP_DREG_M(rm, insn);
5000 size = (insn >> 20) & 3;
5001 if ((insn & (1 << 23)) == 0) {
5002 /* Three register same length. */
5003 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
5004 /* Catch invalid op and bad size combinations: UNDEF */
5005 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
5006 return 1;
5008 /* All insns of this form UNDEF for either this condition or the
5009 * superset of cases "Q==1"; we catch the latter later.
5011 if (q && ((rd | rn | rm) & 1)) {
5012 return 1;
5014 if (size == 3 && op != NEON_3R_LOGIC) {
5015 /* 64-bit element instructions. */
5016 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5017 neon_load_reg64(cpu_V0, rn + pass);
5018 neon_load_reg64(cpu_V1, rm + pass);
5019 switch (op) {
5020 case NEON_3R_VQADD:
5021 if (u) {
5022 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
5023 cpu_V0, cpu_V1);
5024 } else {
5025 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
5026 cpu_V0, cpu_V1);
5028 break;
5029 case NEON_3R_VQSUB:
5030 if (u) {
5031 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
5032 cpu_V0, cpu_V1);
5033 } else {
5034 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
5035 cpu_V0, cpu_V1);
5037 break;
5038 case NEON_3R_VSHL:
5039 if (u) {
5040 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5041 } else {
5042 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5044 break;
5045 case NEON_3R_VQSHL:
5046 if (u) {
5047 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5048 cpu_V1, cpu_V0);
5049 } else {
5050 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5051 cpu_V1, cpu_V0);
5053 break;
5054 case NEON_3R_VRSHL:
5055 if (u) {
5056 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
5057 } else {
5058 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5060 break;
5061 case NEON_3R_VQRSHL:
5062 if (u) {
5063 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5064 cpu_V1, cpu_V0);
5065 } else {
5066 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5067 cpu_V1, cpu_V0);
5069 break;
5070 case NEON_3R_VADD_VSUB:
5071 if (u) {
5072 tcg_gen_sub_i64(CPU_V001);
5073 } else {
5074 tcg_gen_add_i64(CPU_V001);
5076 break;
5077 default:
5078 abort();
5080 neon_store_reg64(cpu_V0, rd + pass);
5082 return 0;
5084 pairwise = 0;
5085 switch (op) {
5086 case NEON_3R_VSHL:
5087 case NEON_3R_VQSHL:
5088 case NEON_3R_VRSHL:
5089 case NEON_3R_VQRSHL:
5091 int rtmp;
5092 /* Shift instruction operands are reversed. */
5093 rtmp = rn;
5094 rn = rm;
5095 rm = rtmp;
5097 break;
5098 case NEON_3R_VPADD:
5099 if (u) {
5100 return 1;
5102 /* Fall through */
5103 case NEON_3R_VPMAX:
5104 case NEON_3R_VPMIN:
5105 pairwise = 1;
5106 break;
5107 case NEON_3R_FLOAT_ARITH:
5108 pairwise = (u && size < 2); /* if VPADD (float) */
5109 break;
5110 case NEON_3R_FLOAT_MINMAX:
5111 pairwise = u; /* if VPMIN/VPMAX (float) */
5112 break;
5113 case NEON_3R_FLOAT_CMP:
5114 if (!u && size) {
5115 /* no encoding for U=0 C=1x */
5116 return 1;
5118 break;
5119 case NEON_3R_FLOAT_ACMP:
5120 if (!u) {
5121 return 1;
5123 break;
5124 case NEON_3R_FLOAT_MISC:
5125 /* VMAXNM/VMINNM in ARMv8 */
5126 if (u && !arm_feature(env, ARM_FEATURE_V8)) {
5127 return 1;
5129 break;
5130 case NEON_3R_VMUL:
5131 if (u && (size != 0)) {
5132 /* UNDEF on invalid size for polynomial subcase */
5133 return 1;
5135 break;
5136 case NEON_3R_VFM:
5137 if (!arm_feature(env, ARM_FEATURE_VFP4) || u) {
5138 return 1;
5140 break;
5141 default:
5142 break;
5145 if (pairwise && q) {
5146 /* All the pairwise insns UNDEF if Q is set */
5147 return 1;
5150 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5152 if (pairwise) {
5153 /* Pairwise. */
5154 if (pass < 1) {
5155 tmp = neon_load_reg(rn, 0);
5156 tmp2 = neon_load_reg(rn, 1);
5157 } else {
5158 tmp = neon_load_reg(rm, 0);
5159 tmp2 = neon_load_reg(rm, 1);
5161 } else {
5162 /* Elementwise. */
5163 tmp = neon_load_reg(rn, pass);
5164 tmp2 = neon_load_reg(rm, pass);
5166 switch (op) {
5167 case NEON_3R_VHADD:
5168 GEN_NEON_INTEGER_OP(hadd);
5169 break;
5170 case NEON_3R_VQADD:
5171 GEN_NEON_INTEGER_OP_ENV(qadd);
5172 break;
5173 case NEON_3R_VRHADD:
5174 GEN_NEON_INTEGER_OP(rhadd);
5175 break;
5176 case NEON_3R_LOGIC: /* Logic ops. */
5177 switch ((u << 2) | size) {
5178 case 0: /* VAND */
5179 tcg_gen_and_i32(tmp, tmp, tmp2);
5180 break;
5181 case 1: /* BIC */
5182 tcg_gen_andc_i32(tmp, tmp, tmp2);
5183 break;
5184 case 2: /* VORR */
5185 tcg_gen_or_i32(tmp, tmp, tmp2);
5186 break;
5187 case 3: /* VORN */
5188 tcg_gen_orc_i32(tmp, tmp, tmp2);
5189 break;
5190 case 4: /* VEOR */
5191 tcg_gen_xor_i32(tmp, tmp, tmp2);
5192 break;
5193 case 5: /* VBSL */
5194 tmp3 = neon_load_reg(rd, pass);
5195 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
5196 tcg_temp_free_i32(tmp3);
5197 break;
5198 case 6: /* VBIT */
5199 tmp3 = neon_load_reg(rd, pass);
5200 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
5201 tcg_temp_free_i32(tmp3);
5202 break;
5203 case 7: /* VBIF */
5204 tmp3 = neon_load_reg(rd, pass);
5205 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
5206 tcg_temp_free_i32(tmp3);
5207 break;
5209 break;
5210 case NEON_3R_VHSUB:
5211 GEN_NEON_INTEGER_OP(hsub);
5212 break;
5213 case NEON_3R_VQSUB:
5214 GEN_NEON_INTEGER_OP_ENV(qsub);
5215 break;
5216 case NEON_3R_VCGT:
5217 GEN_NEON_INTEGER_OP(cgt);
5218 break;
5219 case NEON_3R_VCGE:
5220 GEN_NEON_INTEGER_OP(cge);
5221 break;
5222 case NEON_3R_VSHL:
5223 GEN_NEON_INTEGER_OP(shl);
5224 break;
5225 case NEON_3R_VQSHL:
5226 GEN_NEON_INTEGER_OP_ENV(qshl);
5227 break;
5228 case NEON_3R_VRSHL:
5229 GEN_NEON_INTEGER_OP(rshl);
5230 break;
5231 case NEON_3R_VQRSHL:
5232 GEN_NEON_INTEGER_OP_ENV(qrshl);
5233 break;
5234 case NEON_3R_VMAX:
5235 GEN_NEON_INTEGER_OP(max);
5236 break;
5237 case NEON_3R_VMIN:
5238 GEN_NEON_INTEGER_OP(min);
5239 break;
5240 case NEON_3R_VABD:
5241 GEN_NEON_INTEGER_OP(abd);
5242 break;
5243 case NEON_3R_VABA:
5244 GEN_NEON_INTEGER_OP(abd);
5245 tcg_temp_free_i32(tmp2);
5246 tmp2 = neon_load_reg(rd, pass);
5247 gen_neon_add(size, tmp, tmp2);
5248 break;
5249 case NEON_3R_VADD_VSUB:
5250 if (!u) { /* VADD */
5251 gen_neon_add(size, tmp, tmp2);
5252 } else { /* VSUB */
5253 switch (size) {
5254 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
5255 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
5256 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
5257 default: abort();
5260 break;
5261 case NEON_3R_VTST_VCEQ:
5262 if (!u) { /* VTST */
5263 switch (size) {
5264 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
5265 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
5266 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
5267 default: abort();
5269 } else { /* VCEQ */
5270 switch (size) {
5271 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5272 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5273 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5274 default: abort();
5277 break;
5278 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
5279 switch (size) {
5280 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5281 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5282 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5283 default: abort();
5285 tcg_temp_free_i32(tmp2);
5286 tmp2 = neon_load_reg(rd, pass);
5287 if (u) { /* VMLS */
5288 gen_neon_rsb(size, tmp, tmp2);
5289 } else { /* VMLA */
5290 gen_neon_add(size, tmp, tmp2);
5292 break;
5293 case NEON_3R_VMUL:
5294 if (u) { /* polynomial */
5295 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
5296 } else { /* Integer */
5297 switch (size) {
5298 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5299 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5300 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5301 default: abort();
5304 break;
5305 case NEON_3R_VPMAX:
5306 GEN_NEON_INTEGER_OP(pmax);
5307 break;
5308 case NEON_3R_VPMIN:
5309 GEN_NEON_INTEGER_OP(pmin);
5310 break;
5311 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
5312 if (!u) { /* VQDMULH */
5313 switch (size) {
5314 case 1:
5315 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5316 break;
5317 case 2:
5318 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5319 break;
5320 default: abort();
5322 } else { /* VQRDMULH */
5323 switch (size) {
5324 case 1:
5325 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5326 break;
5327 case 2:
5328 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5329 break;
5330 default: abort();
5333 break;
5334 case NEON_3R_VPADD:
5335 switch (size) {
5336 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5337 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5338 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5339 default: abort();
5341 break;
5342 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
5344 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5345 switch ((u << 2) | size) {
5346 case 0: /* VADD */
5347 case 4: /* VPADD */
5348 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5349 break;
5350 case 2: /* VSUB */
5351 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
5352 break;
5353 case 6: /* VABD */
5354 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
5355 break;
5356 default:
5357 abort();
5359 tcg_temp_free_ptr(fpstatus);
5360 break;
5362 case NEON_3R_FLOAT_MULTIPLY:
5364 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5365 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5366 if (!u) {
5367 tcg_temp_free_i32(tmp2);
5368 tmp2 = neon_load_reg(rd, pass);
5369 if (size == 0) {
5370 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5371 } else {
5372 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5375 tcg_temp_free_ptr(fpstatus);
5376 break;
5378 case NEON_3R_FLOAT_CMP:
5380 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5381 if (!u) {
5382 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5383 } else {
5384 if (size == 0) {
5385 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5386 } else {
5387 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5390 tcg_temp_free_ptr(fpstatus);
5391 break;
5393 case NEON_3R_FLOAT_ACMP:
5395 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5396 if (size == 0) {
5397 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5398 } else {
5399 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5401 tcg_temp_free_ptr(fpstatus);
5402 break;
5404 case NEON_3R_FLOAT_MINMAX:
5406 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5407 if (size == 0) {
5408 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
5409 } else {
5410 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
5412 tcg_temp_free_ptr(fpstatus);
5413 break;
5415 case NEON_3R_FLOAT_MISC:
5416 if (u) {
5417 /* VMAXNM/VMINNM */
5418 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5419 if (size == 0) {
5420 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
5421 } else {
5422 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
5424 tcg_temp_free_ptr(fpstatus);
5425 } else {
5426 if (size == 0) {
5427 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5428 } else {
5429 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5432 break;
5433 case NEON_3R_VFM:
5435 /* VFMA, VFMS: fused multiply-add */
5436 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5437 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5438 if (size) {
5439 /* VFMS */
5440 gen_helper_vfp_negs(tmp, tmp);
5442 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5443 tcg_temp_free_i32(tmp3);
5444 tcg_temp_free_ptr(fpstatus);
5445 break;
5447 default:
5448 abort();
5450 tcg_temp_free_i32(tmp2);
5452 /* Save the result. For elementwise operations we can put it
5453 straight into the destination register. For pairwise operations
5454 we have to be careful to avoid clobbering the source operands. */
5455 if (pairwise && rd == rm) {
5456 neon_store_scratch(pass, tmp);
5457 } else {
5458 neon_store_reg(rd, pass, tmp);
5461 } /* for pass */
5462 if (pairwise && rd == rm) {
5463 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5464 tmp = neon_load_scratch(pass);
5465 neon_store_reg(rd, pass, tmp);
5468 /* End of 3 register same size operations. */
5469 } else if (insn & (1 << 4)) {
5470 if ((insn & 0x00380080) != 0) {
5471 /* Two registers and shift. */
5472 op = (insn >> 8) & 0xf;
5473 if (insn & (1 << 7)) {
5474 /* 64-bit shift. */
5475 if (op > 7) {
5476 return 1;
5478 size = 3;
5479 } else {
5480 size = 2;
5481 while ((insn & (1 << (size + 19))) == 0)
5482 size--;
5484 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5485 /* To avoid excessive duplication of ops we implement shift
5486 by immediate using the variable shift operations. */
5487 if (op < 8) {
5488 /* Shift by immediate:
5489 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5490 if (q && ((rd | rm) & 1)) {
5491 return 1;
5493 if (!u && (op == 4 || op == 6)) {
5494 return 1;
5496 /* Right shifts are encoded as N - shift, where N is the
5497 element size in bits. */
5498 if (op <= 4)
5499 shift = shift - (1 << (size + 3));
5500 if (size == 3) {
5501 count = q + 1;
5502 } else {
5503 count = q ? 4: 2;
5505 switch (size) {
5506 case 0:
5507 imm = (uint8_t) shift;
5508 imm |= imm << 8;
5509 imm |= imm << 16;
5510 break;
5511 case 1:
5512 imm = (uint16_t) shift;
5513 imm |= imm << 16;
5514 break;
5515 case 2:
5516 case 3:
5517 imm = shift;
5518 break;
5519 default:
5520 abort();
5523 for (pass = 0; pass < count; pass++) {
5524 if (size == 3) {
5525 neon_load_reg64(cpu_V0, rm + pass);
5526 tcg_gen_movi_i64(cpu_V1, imm);
5527 switch (op) {
5528 case 0: /* VSHR */
5529 case 1: /* VSRA */
5530 if (u)
5531 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5532 else
5533 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5534 break;
5535 case 2: /* VRSHR */
5536 case 3: /* VRSRA */
5537 if (u)
5538 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5539 else
5540 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5541 break;
5542 case 4: /* VSRI */
5543 case 5: /* VSHL, VSLI */
5544 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5545 break;
5546 case 6: /* VQSHLU */
5547 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5548 cpu_V0, cpu_V1);
5549 break;
5550 case 7: /* VQSHL */
5551 if (u) {
5552 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5553 cpu_V0, cpu_V1);
5554 } else {
5555 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5556 cpu_V0, cpu_V1);
5558 break;
5560 if (op == 1 || op == 3) {
5561 /* Accumulate. */
5562 neon_load_reg64(cpu_V1, rd + pass);
5563 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5564 } else if (op == 4 || (op == 5 && u)) {
5565 /* Insert */
5566 neon_load_reg64(cpu_V1, rd + pass);
5567 uint64_t mask;
5568 if (shift < -63 || shift > 63) {
5569 mask = 0;
5570 } else {
5571 if (op == 4) {
5572 mask = 0xffffffffffffffffull >> -shift;
5573 } else {
5574 mask = 0xffffffffffffffffull << shift;
5577 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5578 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5580 neon_store_reg64(cpu_V0, rd + pass);
5581 } else { /* size < 3 */
5582 /* Operands in T0 and T1. */
5583 tmp = neon_load_reg(rm, pass);
5584 tmp2 = tcg_temp_new_i32();
5585 tcg_gen_movi_i32(tmp2, imm);
5586 switch (op) {
5587 case 0: /* VSHR */
5588 case 1: /* VSRA */
5589 GEN_NEON_INTEGER_OP(shl);
5590 break;
5591 case 2: /* VRSHR */
5592 case 3: /* VRSRA */
5593 GEN_NEON_INTEGER_OP(rshl);
5594 break;
5595 case 4: /* VSRI */
5596 case 5: /* VSHL, VSLI */
5597 switch (size) {
5598 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5599 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5600 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5601 default: abort();
5603 break;
5604 case 6: /* VQSHLU */
5605 switch (size) {
5606 case 0:
5607 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5608 tmp, tmp2);
5609 break;
5610 case 1:
5611 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5612 tmp, tmp2);
5613 break;
5614 case 2:
5615 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5616 tmp, tmp2);
5617 break;
5618 default:
5619 abort();
5621 break;
5622 case 7: /* VQSHL */
5623 GEN_NEON_INTEGER_OP_ENV(qshl);
5624 break;
5626 tcg_temp_free_i32(tmp2);
5628 if (op == 1 || op == 3) {
5629 /* Accumulate. */
5630 tmp2 = neon_load_reg(rd, pass);
5631 gen_neon_add(size, tmp, tmp2);
5632 tcg_temp_free_i32(tmp2);
5633 } else if (op == 4 || (op == 5 && u)) {
5634 /* Insert */
5635 switch (size) {
5636 case 0:
5637 if (op == 4)
5638 mask = 0xff >> -shift;
5639 else
5640 mask = (uint8_t)(0xff << shift);
5641 mask |= mask << 8;
5642 mask |= mask << 16;
5643 break;
5644 case 1:
5645 if (op == 4)
5646 mask = 0xffff >> -shift;
5647 else
5648 mask = (uint16_t)(0xffff << shift);
5649 mask |= mask << 16;
5650 break;
5651 case 2:
5652 if (shift < -31 || shift > 31) {
5653 mask = 0;
5654 } else {
5655 if (op == 4)
5656 mask = 0xffffffffu >> -shift;
5657 else
5658 mask = 0xffffffffu << shift;
5660 break;
5661 default:
5662 abort();
5664 tmp2 = neon_load_reg(rd, pass);
5665 tcg_gen_andi_i32(tmp, tmp, mask);
5666 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5667 tcg_gen_or_i32(tmp, tmp, tmp2);
5668 tcg_temp_free_i32(tmp2);
5670 neon_store_reg(rd, pass, tmp);
5672 } /* for pass */
5673 } else if (op < 10) {
5674 /* Shift by immediate and narrow:
5675 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5676 int input_unsigned = (op == 8) ? !u : u;
5677 if (rm & 1) {
5678 return 1;
5680 shift = shift - (1 << (size + 3));
5681 size++;
5682 if (size == 3) {
5683 tmp64 = tcg_const_i64(shift);
5684 neon_load_reg64(cpu_V0, rm);
5685 neon_load_reg64(cpu_V1, rm + 1);
5686 for (pass = 0; pass < 2; pass++) {
5687 TCGv_i64 in;
5688 if (pass == 0) {
5689 in = cpu_V0;
5690 } else {
5691 in = cpu_V1;
5693 if (q) {
5694 if (input_unsigned) {
5695 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5696 } else {
5697 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5699 } else {
5700 if (input_unsigned) {
5701 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5702 } else {
5703 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5706 tmp = tcg_temp_new_i32();
5707 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5708 neon_store_reg(rd, pass, tmp);
5709 } /* for pass */
5710 tcg_temp_free_i64(tmp64);
5711 } else {
5712 if (size == 1) {
5713 imm = (uint16_t)shift;
5714 imm |= imm << 16;
5715 } else {
5716 /* size == 2 */
5717 imm = (uint32_t)shift;
5719 tmp2 = tcg_const_i32(imm);
5720 tmp4 = neon_load_reg(rm + 1, 0);
5721 tmp5 = neon_load_reg(rm + 1, 1);
5722 for (pass = 0; pass < 2; pass++) {
5723 if (pass == 0) {
5724 tmp = neon_load_reg(rm, 0);
5725 } else {
5726 tmp = tmp4;
5728 gen_neon_shift_narrow(size, tmp, tmp2, q,
5729 input_unsigned);
5730 if (pass == 0) {
5731 tmp3 = neon_load_reg(rm, 1);
5732 } else {
5733 tmp3 = tmp5;
5735 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5736 input_unsigned);
5737 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5738 tcg_temp_free_i32(tmp);
5739 tcg_temp_free_i32(tmp3);
5740 tmp = tcg_temp_new_i32();
5741 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5742 neon_store_reg(rd, pass, tmp);
5743 } /* for pass */
5744 tcg_temp_free_i32(tmp2);
5746 } else if (op == 10) {
5747 /* VSHLL, VMOVL */
5748 if (q || (rd & 1)) {
5749 return 1;
5751 tmp = neon_load_reg(rm, 0);
5752 tmp2 = neon_load_reg(rm, 1);
5753 for (pass = 0; pass < 2; pass++) {
5754 if (pass == 1)
5755 tmp = tmp2;
5757 gen_neon_widen(cpu_V0, tmp, size, u);
5759 if (shift != 0) {
5760 /* The shift is less than the width of the source
5761 type, so we can just shift the whole register. */
5762 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5763 /* Widen the result of shift: we need to clear
5764 * the potential overflow bits resulting from
5765 * left bits of the narrow input appearing as
5766 * right bits of left the neighbour narrow
5767 * input. */
5768 if (size < 2 || !u) {
5769 uint64_t imm64;
5770 if (size == 0) {
5771 imm = (0xffu >> (8 - shift));
5772 imm |= imm << 16;
5773 } else if (size == 1) {
5774 imm = 0xffff >> (16 - shift);
5775 } else {
5776 /* size == 2 */
5777 imm = 0xffffffff >> (32 - shift);
5779 if (size < 2) {
5780 imm64 = imm | (((uint64_t)imm) << 32);
5781 } else {
5782 imm64 = imm;
5784 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5787 neon_store_reg64(cpu_V0, rd + pass);
5789 } else if (op >= 14) {
5790 /* VCVT fixed-point. */
5791 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5792 return 1;
5794 /* We have already masked out the must-be-1 top bit of imm6,
5795 * hence this 32-shift where the ARM ARM has 64-imm6.
5797 shift = 32 - shift;
5798 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5799 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5800 if (!(op & 1)) {
5801 if (u)
5802 gen_vfp_ulto(0, shift, 1);
5803 else
5804 gen_vfp_slto(0, shift, 1);
5805 } else {
5806 if (u)
5807 gen_vfp_toul(0, shift, 1);
5808 else
5809 gen_vfp_tosl(0, shift, 1);
5811 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5813 } else {
5814 return 1;
5816 } else { /* (insn & 0x00380080) == 0 */
5817 int invert;
5818 if (q && (rd & 1)) {
5819 return 1;
5822 op = (insn >> 8) & 0xf;
5823 /* One register and immediate. */
5824 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5825 invert = (insn & (1 << 5)) != 0;
5826 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5827 * We choose to not special-case this and will behave as if a
5828 * valid constant encoding of 0 had been given.
5830 switch (op) {
5831 case 0: case 1:
5832 /* no-op */
5833 break;
5834 case 2: case 3:
5835 imm <<= 8;
5836 break;
5837 case 4: case 5:
5838 imm <<= 16;
5839 break;
5840 case 6: case 7:
5841 imm <<= 24;
5842 break;
5843 case 8: case 9:
5844 imm |= imm << 16;
5845 break;
5846 case 10: case 11:
5847 imm = (imm << 8) | (imm << 24);
5848 break;
5849 case 12:
5850 imm = (imm << 8) | 0xff;
5851 break;
5852 case 13:
5853 imm = (imm << 16) | 0xffff;
5854 break;
5855 case 14:
5856 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5857 if (invert)
5858 imm = ~imm;
5859 break;
5860 case 15:
5861 if (invert) {
5862 return 1;
5864 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5865 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5866 break;
5868 if (invert)
5869 imm = ~imm;
5871 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5872 if (op & 1 && op < 12) {
5873 tmp = neon_load_reg(rd, pass);
5874 if (invert) {
5875 /* The immediate value has already been inverted, so
5876 BIC becomes AND. */
5877 tcg_gen_andi_i32(tmp, tmp, imm);
5878 } else {
5879 tcg_gen_ori_i32(tmp, tmp, imm);
5881 } else {
5882 /* VMOV, VMVN. */
5883 tmp = tcg_temp_new_i32();
5884 if (op == 14 && invert) {
5885 int n;
5886 uint32_t val;
5887 val = 0;
5888 for (n = 0; n < 4; n++) {
5889 if (imm & (1 << (n + (pass & 1) * 4)))
5890 val |= 0xff << (n * 8);
5892 tcg_gen_movi_i32(tmp, val);
5893 } else {
5894 tcg_gen_movi_i32(tmp, imm);
5897 neon_store_reg(rd, pass, tmp);
5900 } else { /* (insn & 0x00800010 == 0x00800000) */
5901 if (size != 3) {
5902 op = (insn >> 8) & 0xf;
5903 if ((insn & (1 << 6)) == 0) {
5904 /* Three registers of different lengths. */
5905 int src1_wide;
5906 int src2_wide;
5907 int prewiden;
5908 /* undefreq: bit 0 : UNDEF if size != 0
5909 * bit 1 : UNDEF if size == 0
5910 * bit 2 : UNDEF if U == 1
5911 * Note that [1:0] set implies 'always UNDEF'
5913 int undefreq;
5914 /* prewiden, src1_wide, src2_wide, undefreq */
5915 static const int neon_3reg_wide[16][4] = {
5916 {1, 0, 0, 0}, /* VADDL */
5917 {1, 1, 0, 0}, /* VADDW */
5918 {1, 0, 0, 0}, /* VSUBL */
5919 {1, 1, 0, 0}, /* VSUBW */
5920 {0, 1, 1, 0}, /* VADDHN */
5921 {0, 0, 0, 0}, /* VABAL */
5922 {0, 1, 1, 0}, /* VSUBHN */
5923 {0, 0, 0, 0}, /* VABDL */
5924 {0, 0, 0, 0}, /* VMLAL */
5925 {0, 0, 0, 6}, /* VQDMLAL */
5926 {0, 0, 0, 0}, /* VMLSL */
5927 {0, 0, 0, 6}, /* VQDMLSL */
5928 {0, 0, 0, 0}, /* Integer VMULL */
5929 {0, 0, 0, 2}, /* VQDMULL */
5930 {0, 0, 0, 5}, /* Polynomial VMULL */
5931 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5934 prewiden = neon_3reg_wide[op][0];
5935 src1_wide = neon_3reg_wide[op][1];
5936 src2_wide = neon_3reg_wide[op][2];
5937 undefreq = neon_3reg_wide[op][3];
5939 if (((undefreq & 1) && (size != 0)) ||
5940 ((undefreq & 2) && (size == 0)) ||
5941 ((undefreq & 4) && u)) {
5942 return 1;
5944 if ((src1_wide && (rn & 1)) ||
5945 (src2_wide && (rm & 1)) ||
5946 (!src2_wide && (rd & 1))) {
5947 return 1;
5950 /* Avoid overlapping operands. Wide source operands are
5951 always aligned so will never overlap with wide
5952 destinations in problematic ways. */
5953 if (rd == rm && !src2_wide) {
5954 tmp = neon_load_reg(rm, 1);
5955 neon_store_scratch(2, tmp);
5956 } else if (rd == rn && !src1_wide) {
5957 tmp = neon_load_reg(rn, 1);
5958 neon_store_scratch(2, tmp);
5960 TCGV_UNUSED_I32(tmp3);
5961 for (pass = 0; pass < 2; pass++) {
5962 if (src1_wide) {
5963 neon_load_reg64(cpu_V0, rn + pass);
5964 TCGV_UNUSED_I32(tmp);
5965 } else {
5966 if (pass == 1 && rd == rn) {
5967 tmp = neon_load_scratch(2);
5968 } else {
5969 tmp = neon_load_reg(rn, pass);
5971 if (prewiden) {
5972 gen_neon_widen(cpu_V0, tmp, size, u);
5975 if (src2_wide) {
5976 neon_load_reg64(cpu_V1, rm + pass);
5977 TCGV_UNUSED_I32(tmp2);
5978 } else {
5979 if (pass == 1 && rd == rm) {
5980 tmp2 = neon_load_scratch(2);
5981 } else {
5982 tmp2 = neon_load_reg(rm, pass);
5984 if (prewiden) {
5985 gen_neon_widen(cpu_V1, tmp2, size, u);
5988 switch (op) {
5989 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5990 gen_neon_addl(size);
5991 break;
5992 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5993 gen_neon_subl(size);
5994 break;
5995 case 5: case 7: /* VABAL, VABDL */
5996 switch ((size << 1) | u) {
5997 case 0:
5998 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5999 break;
6000 case 1:
6001 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
6002 break;
6003 case 2:
6004 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
6005 break;
6006 case 3:
6007 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
6008 break;
6009 case 4:
6010 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
6011 break;
6012 case 5:
6013 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
6014 break;
6015 default: abort();
6017 tcg_temp_free_i32(tmp2);
6018 tcg_temp_free_i32(tmp);
6019 break;
6020 case 8: case 9: case 10: case 11: case 12: case 13:
6021 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
6022 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6023 break;
6024 case 14: /* Polynomial VMULL */
6025 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
6026 tcg_temp_free_i32(tmp2);
6027 tcg_temp_free_i32(tmp);
6028 break;
6029 default: /* 15 is RESERVED: caught earlier */
6030 abort();
6032 if (op == 13) {
6033 /* VQDMULL */
6034 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6035 neon_store_reg64(cpu_V0, rd + pass);
6036 } else if (op == 5 || (op >= 8 && op <= 11)) {
6037 /* Accumulate. */
6038 neon_load_reg64(cpu_V1, rd + pass);
6039 switch (op) {
6040 case 10: /* VMLSL */
6041 gen_neon_negl(cpu_V0, size);
6042 /* Fall through */
6043 case 5: case 8: /* VABAL, VMLAL */
6044 gen_neon_addl(size);
6045 break;
6046 case 9: case 11: /* VQDMLAL, VQDMLSL */
6047 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6048 if (op == 11) {
6049 gen_neon_negl(cpu_V0, size);
6051 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6052 break;
6053 default:
6054 abort();
6056 neon_store_reg64(cpu_V0, rd + pass);
6057 } else if (op == 4 || op == 6) {
6058 /* Narrowing operation. */
6059 tmp = tcg_temp_new_i32();
6060 if (!u) {
6061 switch (size) {
6062 case 0:
6063 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6064 break;
6065 case 1:
6066 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6067 break;
6068 case 2:
6069 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6070 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
6071 break;
6072 default: abort();
6074 } else {
6075 switch (size) {
6076 case 0:
6077 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6078 break;
6079 case 1:
6080 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6081 break;
6082 case 2:
6083 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6084 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6085 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
6086 break;
6087 default: abort();
6090 if (pass == 0) {
6091 tmp3 = tmp;
6092 } else {
6093 neon_store_reg(rd, 0, tmp3);
6094 neon_store_reg(rd, 1, tmp);
6096 } else {
6097 /* Write back the result. */
6098 neon_store_reg64(cpu_V0, rd + pass);
6101 } else {
6102 /* Two registers and a scalar. NB that for ops of this form
6103 * the ARM ARM labels bit 24 as Q, but it is in our variable
6104 * 'u', not 'q'.
6106 if (size == 0) {
6107 return 1;
6109 switch (op) {
6110 case 1: /* Float VMLA scalar */
6111 case 5: /* Floating point VMLS scalar */
6112 case 9: /* Floating point VMUL scalar */
6113 if (size == 1) {
6114 return 1;
6116 /* fall through */
6117 case 0: /* Integer VMLA scalar */
6118 case 4: /* Integer VMLS scalar */
6119 case 8: /* Integer VMUL scalar */
6120 case 12: /* VQDMULH scalar */
6121 case 13: /* VQRDMULH scalar */
6122 if (u && ((rd | rn) & 1)) {
6123 return 1;
6125 tmp = neon_get_scalar(size, rm);
6126 neon_store_scratch(0, tmp);
6127 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6128 tmp = neon_load_scratch(0);
6129 tmp2 = neon_load_reg(rn, pass);
6130 if (op == 12) {
6131 if (size == 1) {
6132 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6133 } else {
6134 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6136 } else if (op == 13) {
6137 if (size == 1) {
6138 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6139 } else {
6140 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6142 } else if (op & 1) {
6143 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6144 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6145 tcg_temp_free_ptr(fpstatus);
6146 } else {
6147 switch (size) {
6148 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6149 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6150 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
6151 default: abort();
6154 tcg_temp_free_i32(tmp2);
6155 if (op < 8) {
6156 /* Accumulate. */
6157 tmp2 = neon_load_reg(rd, pass);
6158 switch (op) {
6159 case 0:
6160 gen_neon_add(size, tmp, tmp2);
6161 break;
6162 case 1:
6164 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6165 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6166 tcg_temp_free_ptr(fpstatus);
6167 break;
6169 case 4:
6170 gen_neon_rsb(size, tmp, tmp2);
6171 break;
6172 case 5:
6174 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6175 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6176 tcg_temp_free_ptr(fpstatus);
6177 break;
6179 default:
6180 abort();
6182 tcg_temp_free_i32(tmp2);
6184 neon_store_reg(rd, pass, tmp);
6186 break;
6187 case 3: /* VQDMLAL scalar */
6188 case 7: /* VQDMLSL scalar */
6189 case 11: /* VQDMULL scalar */
6190 if (u == 1) {
6191 return 1;
6193 /* fall through */
6194 case 2: /* VMLAL sclar */
6195 case 6: /* VMLSL scalar */
6196 case 10: /* VMULL scalar */
6197 if (rd & 1) {
6198 return 1;
6200 tmp2 = neon_get_scalar(size, rm);
6201 /* We need a copy of tmp2 because gen_neon_mull
6202 * deletes it during pass 0. */
6203 tmp4 = tcg_temp_new_i32();
6204 tcg_gen_mov_i32(tmp4, tmp2);
6205 tmp3 = neon_load_reg(rn, 1);
6207 for (pass = 0; pass < 2; pass++) {
6208 if (pass == 0) {
6209 tmp = neon_load_reg(rn, 0);
6210 } else {
6211 tmp = tmp3;
6212 tmp2 = tmp4;
6214 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6215 if (op != 11) {
6216 neon_load_reg64(cpu_V1, rd + pass);
6218 switch (op) {
6219 case 6:
6220 gen_neon_negl(cpu_V0, size);
6221 /* Fall through */
6222 case 2:
6223 gen_neon_addl(size);
6224 break;
6225 case 3: case 7:
6226 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6227 if (op == 7) {
6228 gen_neon_negl(cpu_V0, size);
6230 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6231 break;
6232 case 10:
6233 /* no-op */
6234 break;
6235 case 11:
6236 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6237 break;
6238 default:
6239 abort();
6241 neon_store_reg64(cpu_V0, rd + pass);
6245 break;
6246 default: /* 14 and 15 are RESERVED */
6247 return 1;
6250 } else { /* size == 3 */
6251 if (!u) {
6252 /* Extract. */
6253 imm = (insn >> 8) & 0xf;
6255 if (imm > 7 && !q)
6256 return 1;
6258 if (q && ((rd | rn | rm) & 1)) {
6259 return 1;
6262 if (imm == 0) {
6263 neon_load_reg64(cpu_V0, rn);
6264 if (q) {
6265 neon_load_reg64(cpu_V1, rn + 1);
6267 } else if (imm == 8) {
6268 neon_load_reg64(cpu_V0, rn + 1);
6269 if (q) {
6270 neon_load_reg64(cpu_V1, rm);
6272 } else if (q) {
6273 tmp64 = tcg_temp_new_i64();
6274 if (imm < 8) {
6275 neon_load_reg64(cpu_V0, rn);
6276 neon_load_reg64(tmp64, rn + 1);
6277 } else {
6278 neon_load_reg64(cpu_V0, rn + 1);
6279 neon_load_reg64(tmp64, rm);
6281 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
6282 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
6283 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6284 if (imm < 8) {
6285 neon_load_reg64(cpu_V1, rm);
6286 } else {
6287 neon_load_reg64(cpu_V1, rm + 1);
6288 imm -= 8;
6290 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6291 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6292 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
6293 tcg_temp_free_i64(tmp64);
6294 } else {
6295 /* BUGFIX */
6296 neon_load_reg64(cpu_V0, rn);
6297 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
6298 neon_load_reg64(cpu_V1, rm);
6299 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6300 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6302 neon_store_reg64(cpu_V0, rd);
6303 if (q) {
6304 neon_store_reg64(cpu_V1, rd + 1);
6306 } else if ((insn & (1 << 11)) == 0) {
6307 /* Two register misc. */
6308 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6309 size = (insn >> 18) & 3;
6310 /* UNDEF for unknown op values and bad op-size combinations */
6311 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6312 return 1;
6314 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6315 q && ((rm | rd) & 1)) {
6316 return 1;
6318 switch (op) {
6319 case NEON_2RM_VREV64:
6320 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6321 tmp = neon_load_reg(rm, pass * 2);
6322 tmp2 = neon_load_reg(rm, pass * 2 + 1);
6323 switch (size) {
6324 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6325 case 1: gen_swap_half(tmp); break;
6326 case 2: /* no-op */ break;
6327 default: abort();
6329 neon_store_reg(rd, pass * 2 + 1, tmp);
6330 if (size == 2) {
6331 neon_store_reg(rd, pass * 2, tmp2);
6332 } else {
6333 switch (size) {
6334 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6335 case 1: gen_swap_half(tmp2); break;
6336 default: abort();
6338 neon_store_reg(rd, pass * 2, tmp2);
6341 break;
6342 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6343 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
6344 for (pass = 0; pass < q + 1; pass++) {
6345 tmp = neon_load_reg(rm, pass * 2);
6346 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6347 tmp = neon_load_reg(rm, pass * 2 + 1);
6348 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6349 switch (size) {
6350 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6351 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6352 case 2: tcg_gen_add_i64(CPU_V001); break;
6353 default: abort();
6355 if (op >= NEON_2RM_VPADAL) {
6356 /* Accumulate. */
6357 neon_load_reg64(cpu_V1, rd + pass);
6358 gen_neon_addl(size);
6360 neon_store_reg64(cpu_V0, rd + pass);
6362 break;
6363 case NEON_2RM_VTRN:
6364 if (size == 2) {
6365 int n;
6366 for (n = 0; n < (q ? 4 : 2); n += 2) {
6367 tmp = neon_load_reg(rm, n);
6368 tmp2 = neon_load_reg(rd, n + 1);
6369 neon_store_reg(rm, n, tmp2);
6370 neon_store_reg(rd, n + 1, tmp);
6372 } else {
6373 goto elementwise;
6375 break;
6376 case NEON_2RM_VUZP:
6377 if (gen_neon_unzip(rd, rm, size, q)) {
6378 return 1;
6380 break;
6381 case NEON_2RM_VZIP:
6382 if (gen_neon_zip(rd, rm, size, q)) {
6383 return 1;
6385 break;
6386 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6387 /* also VQMOVUN; op field and mnemonics don't line up */
6388 if (rm & 1) {
6389 return 1;
6391 TCGV_UNUSED_I32(tmp2);
6392 for (pass = 0; pass < 2; pass++) {
6393 neon_load_reg64(cpu_V0, rm + pass);
6394 tmp = tcg_temp_new_i32();
6395 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6396 tmp, cpu_V0);
6397 if (pass == 0) {
6398 tmp2 = tmp;
6399 } else {
6400 neon_store_reg(rd, 0, tmp2);
6401 neon_store_reg(rd, 1, tmp);
6404 break;
6405 case NEON_2RM_VSHLL:
6406 if (q || (rd & 1)) {
6407 return 1;
6409 tmp = neon_load_reg(rm, 0);
6410 tmp2 = neon_load_reg(rm, 1);
6411 for (pass = 0; pass < 2; pass++) {
6412 if (pass == 1)
6413 tmp = tmp2;
6414 gen_neon_widen(cpu_V0, tmp, size, 1);
6415 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
6416 neon_store_reg64(cpu_V0, rd + pass);
6418 break;
6419 case NEON_2RM_VCVT_F16_F32:
6420 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6421 q || (rm & 1)) {
6422 return 1;
6424 tmp = tcg_temp_new_i32();
6425 tmp2 = tcg_temp_new_i32();
6426 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
6427 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6428 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
6429 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6430 tcg_gen_shli_i32(tmp2, tmp2, 16);
6431 tcg_gen_or_i32(tmp2, tmp2, tmp);
6432 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
6433 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6434 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6435 neon_store_reg(rd, 0, tmp2);
6436 tmp2 = tcg_temp_new_i32();
6437 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6438 tcg_gen_shli_i32(tmp2, tmp2, 16);
6439 tcg_gen_or_i32(tmp2, tmp2, tmp);
6440 neon_store_reg(rd, 1, tmp2);
6441 tcg_temp_free_i32(tmp);
6442 break;
6443 case NEON_2RM_VCVT_F32_F16:
6444 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6445 q || (rd & 1)) {
6446 return 1;
6448 tmp3 = tcg_temp_new_i32();
6449 tmp = neon_load_reg(rm, 0);
6450 tmp2 = neon_load_reg(rm, 1);
6451 tcg_gen_ext16u_i32(tmp3, tmp);
6452 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6453 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6454 tcg_gen_shri_i32(tmp3, tmp, 16);
6455 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6456 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6457 tcg_temp_free_i32(tmp);
6458 tcg_gen_ext16u_i32(tmp3, tmp2);
6459 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6460 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6461 tcg_gen_shri_i32(tmp3, tmp2, 16);
6462 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6463 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6464 tcg_temp_free_i32(tmp2);
6465 tcg_temp_free_i32(tmp3);
6466 break;
6467 case NEON_2RM_AESE: case NEON_2RM_AESMC:
6468 if (!arm_feature(env, ARM_FEATURE_V8_AES)
6469 || ((rm | rd) & 1)) {
6470 return 1;
6472 tmp = tcg_const_i32(rd);
6473 tmp2 = tcg_const_i32(rm);
6475 /* Bit 6 is the lowest opcode bit; it distinguishes between
6476 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6478 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6480 if (op == NEON_2RM_AESE) {
6481 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6482 } else {
6483 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6485 tcg_temp_free_i32(tmp);
6486 tcg_temp_free_i32(tmp2);
6487 tcg_temp_free_i32(tmp3);
6488 break;
6489 default:
6490 elementwise:
6491 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6492 if (neon_2rm_is_float_op(op)) {
6493 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6494 neon_reg_offset(rm, pass));
6495 TCGV_UNUSED_I32(tmp);
6496 } else {
6497 tmp = neon_load_reg(rm, pass);
6499 switch (op) {
6500 case NEON_2RM_VREV32:
6501 switch (size) {
6502 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6503 case 1: gen_swap_half(tmp); break;
6504 default: abort();
6506 break;
6507 case NEON_2RM_VREV16:
6508 gen_rev16(tmp);
6509 break;
6510 case NEON_2RM_VCLS:
6511 switch (size) {
6512 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6513 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6514 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6515 default: abort();
6517 break;
6518 case NEON_2RM_VCLZ:
6519 switch (size) {
6520 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6521 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6522 case 2: gen_helper_clz(tmp, tmp); break;
6523 default: abort();
6525 break;
6526 case NEON_2RM_VCNT:
6527 gen_helper_neon_cnt_u8(tmp, tmp);
6528 break;
6529 case NEON_2RM_VMVN:
6530 tcg_gen_not_i32(tmp, tmp);
6531 break;
6532 case NEON_2RM_VQABS:
6533 switch (size) {
6534 case 0:
6535 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6536 break;
6537 case 1:
6538 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6539 break;
6540 case 2:
6541 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6542 break;
6543 default: abort();
6545 break;
6546 case NEON_2RM_VQNEG:
6547 switch (size) {
6548 case 0:
6549 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6550 break;
6551 case 1:
6552 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6553 break;
6554 case 2:
6555 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6556 break;
6557 default: abort();
6559 break;
6560 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6561 tmp2 = tcg_const_i32(0);
6562 switch(size) {
6563 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6564 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6565 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6566 default: abort();
6568 tcg_temp_free_i32(tmp2);
6569 if (op == NEON_2RM_VCLE0) {
6570 tcg_gen_not_i32(tmp, tmp);
6572 break;
6573 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6574 tmp2 = tcg_const_i32(0);
6575 switch(size) {
6576 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6577 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6578 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6579 default: abort();
6581 tcg_temp_free_i32(tmp2);
6582 if (op == NEON_2RM_VCLT0) {
6583 tcg_gen_not_i32(tmp, tmp);
6585 break;
6586 case NEON_2RM_VCEQ0:
6587 tmp2 = tcg_const_i32(0);
6588 switch(size) {
6589 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6590 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6591 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6592 default: abort();
6594 tcg_temp_free_i32(tmp2);
6595 break;
6596 case NEON_2RM_VABS:
6597 switch(size) {
6598 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6599 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6600 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6601 default: abort();
6603 break;
6604 case NEON_2RM_VNEG:
6605 tmp2 = tcg_const_i32(0);
6606 gen_neon_rsb(size, tmp, tmp2);
6607 tcg_temp_free_i32(tmp2);
6608 break;
6609 case NEON_2RM_VCGT0_F:
6611 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6612 tmp2 = tcg_const_i32(0);
6613 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6614 tcg_temp_free_i32(tmp2);
6615 tcg_temp_free_ptr(fpstatus);
6616 break;
6618 case NEON_2RM_VCGE0_F:
6620 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6621 tmp2 = tcg_const_i32(0);
6622 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6623 tcg_temp_free_i32(tmp2);
6624 tcg_temp_free_ptr(fpstatus);
6625 break;
6627 case NEON_2RM_VCEQ0_F:
6629 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6630 tmp2 = tcg_const_i32(0);
6631 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6632 tcg_temp_free_i32(tmp2);
6633 tcg_temp_free_ptr(fpstatus);
6634 break;
6636 case NEON_2RM_VCLE0_F:
6638 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6639 tmp2 = tcg_const_i32(0);
6640 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6641 tcg_temp_free_i32(tmp2);
6642 tcg_temp_free_ptr(fpstatus);
6643 break;
6645 case NEON_2RM_VCLT0_F:
6647 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6648 tmp2 = tcg_const_i32(0);
6649 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6650 tcg_temp_free_i32(tmp2);
6651 tcg_temp_free_ptr(fpstatus);
6652 break;
6654 case NEON_2RM_VABS_F:
6655 gen_vfp_abs(0);
6656 break;
6657 case NEON_2RM_VNEG_F:
6658 gen_vfp_neg(0);
6659 break;
6660 case NEON_2RM_VSWP:
6661 tmp2 = neon_load_reg(rd, pass);
6662 neon_store_reg(rm, pass, tmp2);
6663 break;
6664 case NEON_2RM_VTRN:
6665 tmp2 = neon_load_reg(rd, pass);
6666 switch (size) {
6667 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6668 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6669 default: abort();
6671 neon_store_reg(rm, pass, tmp2);
6672 break;
6673 case NEON_2RM_VRINTN:
6674 case NEON_2RM_VRINTA:
6675 case NEON_2RM_VRINTM:
6676 case NEON_2RM_VRINTP:
6677 case NEON_2RM_VRINTZ:
6679 TCGv_i32 tcg_rmode;
6680 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6681 int rmode;
6683 if (op == NEON_2RM_VRINTZ) {
6684 rmode = FPROUNDING_ZERO;
6685 } else {
6686 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6689 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6690 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6691 cpu_env);
6692 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
6693 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6694 cpu_env);
6695 tcg_temp_free_ptr(fpstatus);
6696 tcg_temp_free_i32(tcg_rmode);
6697 break;
6699 case NEON_2RM_VRINTX:
6701 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6702 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
6703 tcg_temp_free_ptr(fpstatus);
6704 break;
6706 case NEON_2RM_VCVTAU:
6707 case NEON_2RM_VCVTAS:
6708 case NEON_2RM_VCVTNU:
6709 case NEON_2RM_VCVTNS:
6710 case NEON_2RM_VCVTPU:
6711 case NEON_2RM_VCVTPS:
6712 case NEON_2RM_VCVTMU:
6713 case NEON_2RM_VCVTMS:
6715 bool is_signed = !extract32(insn, 7, 1);
6716 TCGv_ptr fpst = get_fpstatus_ptr(1);
6717 TCGv_i32 tcg_rmode, tcg_shift;
6718 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6720 tcg_shift = tcg_const_i32(0);
6721 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6722 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6723 cpu_env);
6725 if (is_signed) {
6726 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
6727 tcg_shift, fpst);
6728 } else {
6729 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
6730 tcg_shift, fpst);
6733 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6734 cpu_env);
6735 tcg_temp_free_i32(tcg_rmode);
6736 tcg_temp_free_i32(tcg_shift);
6737 tcg_temp_free_ptr(fpst);
6738 break;
6740 case NEON_2RM_VRECPE:
6742 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6743 gen_helper_recpe_u32(tmp, tmp, fpstatus);
6744 tcg_temp_free_ptr(fpstatus);
6745 break;
6747 case NEON_2RM_VRSQRTE:
6749 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6750 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
6751 tcg_temp_free_ptr(fpstatus);
6752 break;
6754 case NEON_2RM_VRECPE_F:
6756 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6757 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
6758 tcg_temp_free_ptr(fpstatus);
6759 break;
6761 case NEON_2RM_VRSQRTE_F:
6763 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6764 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
6765 tcg_temp_free_ptr(fpstatus);
6766 break;
6768 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6769 gen_vfp_sito(0, 1);
6770 break;
6771 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6772 gen_vfp_uito(0, 1);
6773 break;
6774 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6775 gen_vfp_tosiz(0, 1);
6776 break;
6777 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6778 gen_vfp_touiz(0, 1);
6779 break;
6780 default:
6781 /* Reserved op values were caught by the
6782 * neon_2rm_sizes[] check earlier.
6784 abort();
6786 if (neon_2rm_is_float_op(op)) {
6787 tcg_gen_st_f32(cpu_F0s, cpu_env,
6788 neon_reg_offset(rd, pass));
6789 } else {
6790 neon_store_reg(rd, pass, tmp);
6793 break;
6795 } else if ((insn & (1 << 10)) == 0) {
6796 /* VTBL, VTBX. */
6797 int n = ((insn >> 8) & 3) + 1;
6798 if ((rn + n) > 32) {
6799 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6800 * helper function running off the end of the register file.
6802 return 1;
6804 n <<= 3;
6805 if (insn & (1 << 6)) {
6806 tmp = neon_load_reg(rd, 0);
6807 } else {
6808 tmp = tcg_temp_new_i32();
6809 tcg_gen_movi_i32(tmp, 0);
6811 tmp2 = neon_load_reg(rm, 0);
6812 tmp4 = tcg_const_i32(rn);
6813 tmp5 = tcg_const_i32(n);
6814 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
6815 tcg_temp_free_i32(tmp);
6816 if (insn & (1 << 6)) {
6817 tmp = neon_load_reg(rd, 1);
6818 } else {
6819 tmp = tcg_temp_new_i32();
6820 tcg_gen_movi_i32(tmp, 0);
6822 tmp3 = neon_load_reg(rm, 1);
6823 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
6824 tcg_temp_free_i32(tmp5);
6825 tcg_temp_free_i32(tmp4);
6826 neon_store_reg(rd, 0, tmp2);
6827 neon_store_reg(rd, 1, tmp3);
6828 tcg_temp_free_i32(tmp);
6829 } else if ((insn & 0x380) == 0) {
6830 /* VDUP */
6831 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6832 return 1;
6834 if (insn & (1 << 19)) {
6835 tmp = neon_load_reg(rm, 1);
6836 } else {
6837 tmp = neon_load_reg(rm, 0);
6839 if (insn & (1 << 16)) {
6840 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6841 } else if (insn & (1 << 17)) {
6842 if ((insn >> 18) & 1)
6843 gen_neon_dup_high16(tmp);
6844 else
6845 gen_neon_dup_low16(tmp);
6847 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6848 tmp2 = tcg_temp_new_i32();
6849 tcg_gen_mov_i32(tmp2, tmp);
6850 neon_store_reg(rd, pass, tmp2);
6852 tcg_temp_free_i32(tmp);
6853 } else {
6854 return 1;
6858 return 0;
6861 static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
6863 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
6864 const ARMCPRegInfo *ri;
6866 cpnum = (insn >> 8) & 0xf;
6867 if (arm_feature(env, ARM_FEATURE_XSCALE)
6868 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6869 return 1;
6871 /* First check for coprocessor space used for actual instructions */
6872 switch (cpnum) {
6873 case 0:
6874 case 1:
6875 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6876 return disas_iwmmxt_insn(env, s, insn);
6877 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6878 return disas_dsp_insn(env, s, insn);
6880 return 1;
6881 default:
6882 break;
6885 /* Otherwise treat as a generic register access */
6886 is64 = (insn & (1 << 25)) == 0;
6887 if (!is64 && ((insn & (1 << 4)) == 0)) {
6888 /* cdp */
6889 return 1;
6892 crm = insn & 0xf;
6893 if (is64) {
6894 crn = 0;
6895 opc1 = (insn >> 4) & 0xf;
6896 opc2 = 0;
6897 rt2 = (insn >> 16) & 0xf;
6898 } else {
6899 crn = (insn >> 16) & 0xf;
6900 opc1 = (insn >> 21) & 7;
6901 opc2 = (insn >> 5) & 7;
6902 rt2 = 0;
6904 isread = (insn >> 20) & 1;
6905 rt = (insn >> 12) & 0xf;
6907 ri = get_arm_cp_reginfo(s->cp_regs,
6908 ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
6909 if (ri) {
6910 /* Check access permissions */
6911 if (!cp_access_ok(s->current_pl, ri, isread)) {
6912 return 1;
6915 if (ri->accessfn) {
6916 /* Emit code to perform further access permissions checks at
6917 * runtime; this may result in an exception.
6919 TCGv_ptr tmpptr;
6920 TCGv_i32 tcg_syn;
6921 uint32_t syndrome;
6923 /* Note that since we are an implementation which takes an
6924 * exception on a trapped conditional instruction only if the
6925 * instruction passes its condition code check, we can take
6926 * advantage of the clause in the ARM ARM that allows us to set
6927 * the COND field in the instruction to 0xE in all cases.
6928 * We could fish the actual condition out of the insn (ARM)
6929 * or the condexec bits (Thumb) but it isn't necessary.
6931 switch (cpnum) {
6932 case 14:
6933 if (is64) {
6934 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
6935 isread, s->thumb);
6936 } else {
6937 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
6938 rt, isread, s->thumb);
6940 break;
6941 case 15:
6942 if (is64) {
6943 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
6944 isread, s->thumb);
6945 } else {
6946 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
6947 rt, isread, s->thumb);
6949 break;
6950 default:
6951 /* ARMv8 defines that only coprocessors 14 and 15 exist,
6952 * so this can only happen if this is an ARMv7 or earlier CPU,
6953 * in which case the syndrome information won't actually be
6954 * guest visible.
6956 assert(!arm_feature(env, ARM_FEATURE_V8));
6957 syndrome = syn_uncategorized();
6958 break;
6961 gen_set_pc_im(s, s->pc);
6962 tmpptr = tcg_const_ptr(ri);
6963 tcg_syn = tcg_const_i32(syndrome);
6964 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
6965 tcg_temp_free_ptr(tmpptr);
6966 tcg_temp_free_i32(tcg_syn);
6969 /* Handle special cases first */
6970 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
6971 case ARM_CP_NOP:
6972 return 0;
6973 case ARM_CP_WFI:
6974 if (isread) {
6975 return 1;
6977 gen_set_pc_im(s, s->pc);
6978 s->is_jmp = DISAS_WFI;
6979 return 0;
6980 default:
6981 break;
6984 if (use_icount && (ri->type & ARM_CP_IO)) {
6985 gen_io_start();
6988 if (isread) {
6989 /* Read */
6990 if (is64) {
6991 TCGv_i64 tmp64;
6992 TCGv_i32 tmp;
6993 if (ri->type & ARM_CP_CONST) {
6994 tmp64 = tcg_const_i64(ri->resetvalue);
6995 } else if (ri->readfn) {
6996 TCGv_ptr tmpptr;
6997 tmp64 = tcg_temp_new_i64();
6998 tmpptr = tcg_const_ptr(ri);
6999 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7000 tcg_temp_free_ptr(tmpptr);
7001 } else {
7002 tmp64 = tcg_temp_new_i64();
7003 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7005 tmp = tcg_temp_new_i32();
7006 tcg_gen_trunc_i64_i32(tmp, tmp64);
7007 store_reg(s, rt, tmp);
7008 tcg_gen_shri_i64(tmp64, tmp64, 32);
7009 tmp = tcg_temp_new_i32();
7010 tcg_gen_trunc_i64_i32(tmp, tmp64);
7011 tcg_temp_free_i64(tmp64);
7012 store_reg(s, rt2, tmp);
7013 } else {
7014 TCGv_i32 tmp;
7015 if (ri->type & ARM_CP_CONST) {
7016 tmp = tcg_const_i32(ri->resetvalue);
7017 } else if (ri->readfn) {
7018 TCGv_ptr tmpptr;
7019 tmp = tcg_temp_new_i32();
7020 tmpptr = tcg_const_ptr(ri);
7021 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7022 tcg_temp_free_ptr(tmpptr);
7023 } else {
7024 tmp = load_cpu_offset(ri->fieldoffset);
7026 if (rt == 15) {
7027 /* Destination register of r15 for 32 bit loads sets
7028 * the condition codes from the high 4 bits of the value
7030 gen_set_nzcv(tmp);
7031 tcg_temp_free_i32(tmp);
7032 } else {
7033 store_reg(s, rt, tmp);
7036 } else {
7037 /* Write */
7038 if (ri->type & ARM_CP_CONST) {
7039 /* If not forbidden by access permissions, treat as WI */
7040 return 0;
7043 if (is64) {
7044 TCGv_i32 tmplo, tmphi;
7045 TCGv_i64 tmp64 = tcg_temp_new_i64();
7046 tmplo = load_reg(s, rt);
7047 tmphi = load_reg(s, rt2);
7048 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7049 tcg_temp_free_i32(tmplo);
7050 tcg_temp_free_i32(tmphi);
7051 if (ri->writefn) {
7052 TCGv_ptr tmpptr = tcg_const_ptr(ri);
7053 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7054 tcg_temp_free_ptr(tmpptr);
7055 } else {
7056 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7058 tcg_temp_free_i64(tmp64);
7059 } else {
7060 if (ri->writefn) {
7061 TCGv_i32 tmp;
7062 TCGv_ptr tmpptr;
7063 tmp = load_reg(s, rt);
7064 tmpptr = tcg_const_ptr(ri);
7065 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7066 tcg_temp_free_ptr(tmpptr);
7067 tcg_temp_free_i32(tmp);
7068 } else {
7069 TCGv_i32 tmp = load_reg(s, rt);
7070 store_cpu_offset(tmp, ri->fieldoffset);
7075 if (use_icount && (ri->type & ARM_CP_IO)) {
7076 /* I/O operations must end the TB here (whether read or write) */
7077 gen_io_end();
7078 gen_lookup_tb(s);
7079 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
7080 /* We default to ending the TB on a coprocessor register write,
7081 * but allow this to be suppressed by the register definition
7082 * (usually only necessary to work around guest bugs).
7084 gen_lookup_tb(s);
7087 return 0;
7090 /* Unknown register; this might be a guest error or a QEMU
7091 * unimplemented feature.
7093 if (is64) {
7094 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7095 "64 bit system register cp:%d opc1: %d crm:%d\n",
7096 isread ? "read" : "write", cpnum, opc1, crm);
7097 } else {
7098 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7099 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d\n",
7100 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2);
7103 return 1;
7107 /* Store a 64-bit value to a register pair. Clobbers val. */
7108 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
7110 TCGv_i32 tmp;
7111 tmp = tcg_temp_new_i32();
7112 tcg_gen_trunc_i64_i32(tmp, val);
7113 store_reg(s, rlow, tmp);
7114 tmp = tcg_temp_new_i32();
7115 tcg_gen_shri_i64(val, val, 32);
7116 tcg_gen_trunc_i64_i32(tmp, val);
7117 store_reg(s, rhigh, tmp);
7120 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
7121 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
7123 TCGv_i64 tmp;
7124 TCGv_i32 tmp2;
7126 /* Load value and extend to 64 bits. */
7127 tmp = tcg_temp_new_i64();
7128 tmp2 = load_reg(s, rlow);
7129 tcg_gen_extu_i32_i64(tmp, tmp2);
7130 tcg_temp_free_i32(tmp2);
7131 tcg_gen_add_i64(val, val, tmp);
7132 tcg_temp_free_i64(tmp);
7135 /* load and add a 64-bit value from a register pair. */
7136 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
7138 TCGv_i64 tmp;
7139 TCGv_i32 tmpl;
7140 TCGv_i32 tmph;
7142 /* Load 64-bit value rd:rn. */
7143 tmpl = load_reg(s, rlow);
7144 tmph = load_reg(s, rhigh);
7145 tmp = tcg_temp_new_i64();
7146 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7147 tcg_temp_free_i32(tmpl);
7148 tcg_temp_free_i32(tmph);
7149 tcg_gen_add_i64(val, val, tmp);
7150 tcg_temp_free_i64(tmp);
7153 /* Set N and Z flags from hi|lo. */
7154 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
7156 tcg_gen_mov_i32(cpu_NF, hi);
7157 tcg_gen_or_i32(cpu_ZF, lo, hi);
7160 /* Load/Store exclusive instructions are implemented by remembering
7161 the value/address loaded, and seeing if these are the same
7162 when the store is performed. This should be sufficient to implement
7163 the architecturally mandated semantics, and avoids having to monitor
7164 regular stores.
7166 In system emulation mode only one CPU will be running at once, so
7167 this sequence is effectively atomic. In user emulation mode we
7168 throw an exception and handle the atomic operation elsewhere. */
7169 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
7170 TCGv_i32 addr, int size)
7172 TCGv_i32 tmp = tcg_temp_new_i32();
7174 switch (size) {
7175 case 0:
7176 gen_aa32_ld8u(tmp, addr, IS_USER(s));
7177 break;
7178 case 1:
7179 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7180 break;
7181 case 2:
7182 case 3:
7183 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7184 break;
7185 default:
7186 abort();
7189 if (size == 3) {
7190 TCGv_i32 tmp2 = tcg_temp_new_i32();
7191 TCGv_i32 tmp3 = tcg_temp_new_i32();
7193 tcg_gen_addi_i32(tmp2, addr, 4);
7194 gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
7195 tcg_temp_free_i32(tmp2);
7196 tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
7197 store_reg(s, rt2, tmp3);
7198 } else {
7199 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
7202 store_reg(s, rt, tmp);
7203 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
7206 static void gen_clrex(DisasContext *s)
7208 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7211 #ifdef CONFIG_USER_ONLY
7212 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7213 TCGv_i32 addr, int size)
7215 tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
7216 tcg_gen_movi_i32(cpu_exclusive_info,
7217 size | (rd << 4) | (rt << 8) | (rt2 << 12));
7218 gen_exception_internal_insn(s, 4, EXCP_STREX);
7220 #else
7221 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7222 TCGv_i32 addr, int size)
7224 TCGv_i32 tmp;
7225 TCGv_i64 val64, extaddr;
7226 int done_label;
7227 int fail_label;
7229 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7230 [addr] = {Rt};
7231 {Rd} = 0;
7232 } else {
7233 {Rd} = 1;
7234 } */
7235 fail_label = gen_new_label();
7236 done_label = gen_new_label();
7237 extaddr = tcg_temp_new_i64();
7238 tcg_gen_extu_i32_i64(extaddr, addr);
7239 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7240 tcg_temp_free_i64(extaddr);
7242 tmp = tcg_temp_new_i32();
7243 switch (size) {
7244 case 0:
7245 gen_aa32_ld8u(tmp, addr, IS_USER(s));
7246 break;
7247 case 1:
7248 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7249 break;
7250 case 2:
7251 case 3:
7252 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7253 break;
7254 default:
7255 abort();
7258 val64 = tcg_temp_new_i64();
7259 if (size == 3) {
7260 TCGv_i32 tmp2 = tcg_temp_new_i32();
7261 TCGv_i32 tmp3 = tcg_temp_new_i32();
7262 tcg_gen_addi_i32(tmp2, addr, 4);
7263 gen_aa32_ld32u(tmp3, tmp2, IS_USER(s));
7264 tcg_temp_free_i32(tmp2);
7265 tcg_gen_concat_i32_i64(val64, tmp, tmp3);
7266 tcg_temp_free_i32(tmp3);
7267 } else {
7268 tcg_gen_extu_i32_i64(val64, tmp);
7270 tcg_temp_free_i32(tmp);
7272 tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
7273 tcg_temp_free_i64(val64);
7275 tmp = load_reg(s, rt);
7276 switch (size) {
7277 case 0:
7278 gen_aa32_st8(tmp, addr, IS_USER(s));
7279 break;
7280 case 1:
7281 gen_aa32_st16(tmp, addr, IS_USER(s));
7282 break;
7283 case 2:
7284 case 3:
7285 gen_aa32_st32(tmp, addr, IS_USER(s));
7286 break;
7287 default:
7288 abort();
7290 tcg_temp_free_i32(tmp);
7291 if (size == 3) {
7292 tcg_gen_addi_i32(addr, addr, 4);
7293 tmp = load_reg(s, rt2);
7294 gen_aa32_st32(tmp, addr, IS_USER(s));
7295 tcg_temp_free_i32(tmp);
7297 tcg_gen_movi_i32(cpu_R[rd], 0);
7298 tcg_gen_br(done_label);
7299 gen_set_label(fail_label);
7300 tcg_gen_movi_i32(cpu_R[rd], 1);
7301 gen_set_label(done_label);
7302 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7304 #endif
7306 /* gen_srs:
7307 * @env: CPUARMState
7308 * @s: DisasContext
7309 * @mode: mode field from insn (which stack to store to)
7310 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7311 * @writeback: true if writeback bit set
7313 * Generate code for the SRS (Store Return State) insn.
7315 static void gen_srs(DisasContext *s,
7316 uint32_t mode, uint32_t amode, bool writeback)
7318 int32_t offset;
7319 TCGv_i32 addr = tcg_temp_new_i32();
7320 TCGv_i32 tmp = tcg_const_i32(mode);
7321 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7322 tcg_temp_free_i32(tmp);
7323 switch (amode) {
7324 case 0: /* DA */
7325 offset = -4;
7326 break;
7327 case 1: /* IA */
7328 offset = 0;
7329 break;
7330 case 2: /* DB */
7331 offset = -8;
7332 break;
7333 case 3: /* IB */
7334 offset = 4;
7335 break;
7336 default:
7337 abort();
7339 tcg_gen_addi_i32(addr, addr, offset);
7340 tmp = load_reg(s, 14);
7341 gen_aa32_st32(tmp, addr, 0);
7342 tcg_temp_free_i32(tmp);
7343 tmp = load_cpu_field(spsr);
7344 tcg_gen_addi_i32(addr, addr, 4);
7345 gen_aa32_st32(tmp, addr, 0);
7346 tcg_temp_free_i32(tmp);
7347 if (writeback) {
7348 switch (amode) {
7349 case 0:
7350 offset = -8;
7351 break;
7352 case 1:
7353 offset = 4;
7354 break;
7355 case 2:
7356 offset = -4;
7357 break;
7358 case 3:
7359 offset = 0;
7360 break;
7361 default:
7362 abort();
7364 tcg_gen_addi_i32(addr, addr, offset);
7365 tmp = tcg_const_i32(mode);
7366 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7367 tcg_temp_free_i32(tmp);
7369 tcg_temp_free_i32(addr);
7372 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
7374 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
7375 TCGv_i32 tmp;
7376 TCGv_i32 tmp2;
7377 TCGv_i32 tmp3;
7378 TCGv_i32 addr;
7379 TCGv_i64 tmp64;
7381 insn = arm_ldl_code(env, s->pc, s->bswap_code);
7382 s->pc += 4;
7384 /* M variants do not implement ARM mode. */
7385 if (IS_M(env))
7386 goto illegal_op;
7387 cond = insn >> 28;
7388 if (cond == 0xf){
7389 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
7390 * choose to UNDEF. In ARMv5 and above the space is used
7391 * for miscellaneous unconditional instructions.
7393 ARCH(5);
7395 /* Unconditional instructions. */
7396 if (((insn >> 25) & 7) == 1) {
7397 /* NEON Data processing. */
7398 if (!arm_feature(env, ARM_FEATURE_NEON))
7399 goto illegal_op;
7401 if (disas_neon_data_insn(env, s, insn))
7402 goto illegal_op;
7403 return;
7405 if ((insn & 0x0f100000) == 0x04000000) {
7406 /* NEON load/store. */
7407 if (!arm_feature(env, ARM_FEATURE_NEON))
7408 goto illegal_op;
7410 if (disas_neon_ls_insn(env, s, insn))
7411 goto illegal_op;
7412 return;
7414 if ((insn & 0x0f000e10) == 0x0e000a00) {
7415 /* VFP. */
7416 if (disas_vfp_insn(env, s, insn)) {
7417 goto illegal_op;
7419 return;
7421 if (((insn & 0x0f30f000) == 0x0510f000) ||
7422 ((insn & 0x0f30f010) == 0x0710f000)) {
7423 if ((insn & (1 << 22)) == 0) {
7424 /* PLDW; v7MP */
7425 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7426 goto illegal_op;
7429 /* Otherwise PLD; v5TE+ */
7430 ARCH(5TE);
7431 return;
7433 if (((insn & 0x0f70f000) == 0x0450f000) ||
7434 ((insn & 0x0f70f010) == 0x0650f000)) {
7435 ARCH(7);
7436 return; /* PLI; V7 */
7438 if (((insn & 0x0f700000) == 0x04100000) ||
7439 ((insn & 0x0f700010) == 0x06100000)) {
7440 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7441 goto illegal_op;
7443 return; /* v7MP: Unallocated memory hint: must NOP */
7446 if ((insn & 0x0ffffdff) == 0x01010000) {
7447 ARCH(6);
7448 /* setend */
7449 if (((insn >> 9) & 1) != s->bswap_code) {
7450 /* Dynamic endianness switching not implemented. */
7451 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
7452 goto illegal_op;
7454 return;
7455 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7456 switch ((insn >> 4) & 0xf) {
7457 case 1: /* clrex */
7458 ARCH(6K);
7459 gen_clrex(s);
7460 return;
7461 case 4: /* dsb */
7462 case 5: /* dmb */
7463 case 6: /* isb */
7464 ARCH(7);
7465 /* We don't emulate caches so these are a no-op. */
7466 return;
7467 default:
7468 goto illegal_op;
7470 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7471 /* srs */
7472 if (IS_USER(s)) {
7473 goto illegal_op;
7475 ARCH(6);
7476 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
7477 return;
7478 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
7479 /* rfe */
7480 int32_t offset;
7481 if (IS_USER(s))
7482 goto illegal_op;
7483 ARCH(6);
7484 rn = (insn >> 16) & 0xf;
7485 addr = load_reg(s, rn);
7486 i = (insn >> 23) & 3;
7487 switch (i) {
7488 case 0: offset = -4; break; /* DA */
7489 case 1: offset = 0; break; /* IA */
7490 case 2: offset = -8; break; /* DB */
7491 case 3: offset = 4; break; /* IB */
7492 default: abort();
7494 if (offset)
7495 tcg_gen_addi_i32(addr, addr, offset);
7496 /* Load PC into tmp and CPSR into tmp2. */
7497 tmp = tcg_temp_new_i32();
7498 gen_aa32_ld32u(tmp, addr, 0);
7499 tcg_gen_addi_i32(addr, addr, 4);
7500 tmp2 = tcg_temp_new_i32();
7501 gen_aa32_ld32u(tmp2, addr, 0);
7502 if (insn & (1 << 21)) {
7503 /* Base writeback. */
7504 switch (i) {
7505 case 0: offset = -8; break;
7506 case 1: offset = 4; break;
7507 case 2: offset = -4; break;
7508 case 3: offset = 0; break;
7509 default: abort();
7511 if (offset)
7512 tcg_gen_addi_i32(addr, addr, offset);
7513 store_reg(s, rn, addr);
7514 } else {
7515 tcg_temp_free_i32(addr);
7517 gen_rfe(s, tmp, tmp2);
7518 return;
7519 } else if ((insn & 0x0e000000) == 0x0a000000) {
7520 /* branch link and change to thumb (blx <offset>) */
7521 int32_t offset;
7523 val = (uint32_t)s->pc;
7524 tmp = tcg_temp_new_i32();
7525 tcg_gen_movi_i32(tmp, val);
7526 store_reg(s, 14, tmp);
7527 /* Sign-extend the 24-bit offset */
7528 offset = (((int32_t)insn) << 8) >> 8;
7529 /* offset * 4 + bit24 * 2 + (thumb bit) */
7530 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7531 /* pipeline offset */
7532 val += 4;
7533 /* protected by ARCH(5); above, near the start of uncond block */
7534 gen_bx_im(s, val);
7535 return;
7536 } else if ((insn & 0x0e000f00) == 0x0c000100) {
7537 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7538 /* iWMMXt register transfer. */
7539 if (env->cp15.c15_cpar & (1 << 1))
7540 if (!disas_iwmmxt_insn(env, s, insn))
7541 return;
7543 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7544 /* Coprocessor double register transfer. */
7545 ARCH(5TE);
7546 } else if ((insn & 0x0f000010) == 0x0e000010) {
7547 /* Additional coprocessor register transfer. */
7548 } else if ((insn & 0x0ff10020) == 0x01000000) {
7549 uint32_t mask;
7550 uint32_t val;
7551 /* cps (privileged) */
7552 if (IS_USER(s))
7553 return;
7554 mask = val = 0;
7555 if (insn & (1 << 19)) {
7556 if (insn & (1 << 8))
7557 mask |= CPSR_A;
7558 if (insn & (1 << 7))
7559 mask |= CPSR_I;
7560 if (insn & (1 << 6))
7561 mask |= CPSR_F;
7562 if (insn & (1 << 18))
7563 val |= mask;
7565 if (insn & (1 << 17)) {
7566 mask |= CPSR_M;
7567 val |= (insn & 0x1f);
7569 if (mask) {
7570 gen_set_psr_im(s, mask, 0, val);
7572 return;
7574 goto illegal_op;
7576 if (cond != 0xe) {
7577 /* if not always execute, we generate a conditional jump to
7578 next instruction */
7579 s->condlabel = gen_new_label();
7580 arm_gen_test_cc(cond ^ 1, s->condlabel);
7581 s->condjmp = 1;
7583 if ((insn & 0x0f900000) == 0x03000000) {
7584 if ((insn & (1 << 21)) == 0) {
7585 ARCH(6T2);
7586 rd = (insn >> 12) & 0xf;
7587 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7588 if ((insn & (1 << 22)) == 0) {
7589 /* MOVW */
7590 tmp = tcg_temp_new_i32();
7591 tcg_gen_movi_i32(tmp, val);
7592 } else {
7593 /* MOVT */
7594 tmp = load_reg(s, rd);
7595 tcg_gen_ext16u_i32(tmp, tmp);
7596 tcg_gen_ori_i32(tmp, tmp, val << 16);
7598 store_reg(s, rd, tmp);
7599 } else {
7600 if (((insn >> 12) & 0xf) != 0xf)
7601 goto illegal_op;
7602 if (((insn >> 16) & 0xf) == 0) {
7603 gen_nop_hint(s, insn & 0xff);
7604 } else {
7605 /* CPSR = immediate */
7606 val = insn & 0xff;
7607 shift = ((insn >> 8) & 0xf) * 2;
7608 if (shift)
7609 val = (val >> shift) | (val << (32 - shift));
7610 i = ((insn & (1 << 22)) != 0);
7611 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
7612 goto illegal_op;
7615 } else if ((insn & 0x0f900000) == 0x01000000
7616 && (insn & 0x00000090) != 0x00000090) {
7617 /* miscellaneous instructions */
7618 op1 = (insn >> 21) & 3;
7619 sh = (insn >> 4) & 0xf;
7620 rm = insn & 0xf;
7621 switch (sh) {
7622 case 0x0: /* move program status register */
7623 if (op1 & 1) {
7624 /* PSR = reg */
7625 tmp = load_reg(s, rm);
7626 i = ((op1 & 2) != 0);
7627 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
7628 goto illegal_op;
7629 } else {
7630 /* reg = PSR */
7631 rd = (insn >> 12) & 0xf;
7632 if (op1 & 2) {
7633 if (IS_USER(s))
7634 goto illegal_op;
7635 tmp = load_cpu_field(spsr);
7636 } else {
7637 tmp = tcg_temp_new_i32();
7638 gen_helper_cpsr_read(tmp, cpu_env);
7640 store_reg(s, rd, tmp);
7642 break;
7643 case 0x1:
7644 if (op1 == 1) {
7645 /* branch/exchange thumb (bx). */
7646 ARCH(4T);
7647 tmp = load_reg(s, rm);
7648 gen_bx(s, tmp);
7649 } else if (op1 == 3) {
7650 /* clz */
7651 ARCH(5);
7652 rd = (insn >> 12) & 0xf;
7653 tmp = load_reg(s, rm);
7654 gen_helper_clz(tmp, tmp);
7655 store_reg(s, rd, tmp);
7656 } else {
7657 goto illegal_op;
7659 break;
7660 case 0x2:
7661 if (op1 == 1) {
7662 ARCH(5J); /* bxj */
7663 /* Trivial implementation equivalent to bx. */
7664 tmp = load_reg(s, rm);
7665 gen_bx(s, tmp);
7666 } else {
7667 goto illegal_op;
7669 break;
7670 case 0x3:
7671 if (op1 != 1)
7672 goto illegal_op;
7674 ARCH(5);
7675 /* branch link/exchange thumb (blx) */
7676 tmp = load_reg(s, rm);
7677 tmp2 = tcg_temp_new_i32();
7678 tcg_gen_movi_i32(tmp2, s->pc);
7679 store_reg(s, 14, tmp2);
7680 gen_bx(s, tmp);
7681 break;
7682 case 0x4:
7684 /* crc32/crc32c */
7685 uint32_t c = extract32(insn, 8, 4);
7687 /* Check this CPU supports ARMv8 CRC instructions.
7688 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
7689 * Bits 8, 10 and 11 should be zero.
7691 if (!arm_feature(env, ARM_FEATURE_CRC) || op1 == 0x3 ||
7692 (c & 0xd) != 0) {
7693 goto illegal_op;
7696 rn = extract32(insn, 16, 4);
7697 rd = extract32(insn, 12, 4);
7699 tmp = load_reg(s, rn);
7700 tmp2 = load_reg(s, rm);
7701 tmp3 = tcg_const_i32(1 << op1);
7702 if (c & 0x2) {
7703 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
7704 } else {
7705 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
7707 tcg_temp_free_i32(tmp2);
7708 tcg_temp_free_i32(tmp3);
7709 store_reg(s, rd, tmp);
7710 break;
7712 case 0x5: /* saturating add/subtract */
7713 ARCH(5TE);
7714 rd = (insn >> 12) & 0xf;
7715 rn = (insn >> 16) & 0xf;
7716 tmp = load_reg(s, rm);
7717 tmp2 = load_reg(s, rn);
7718 if (op1 & 2)
7719 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
7720 if (op1 & 1)
7721 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
7722 else
7723 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7724 tcg_temp_free_i32(tmp2);
7725 store_reg(s, rd, tmp);
7726 break;
7727 case 7:
7729 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
7730 /* SMC instruction (op1 == 3)
7731 and undefined instructions (op1 == 0 || op1 == 2)
7732 will trap */
7733 if (op1 != 1) {
7734 goto illegal_op;
7736 /* bkpt */
7737 ARCH(5);
7738 gen_exception_insn(s, 4, EXCP_BKPT, syn_aa32_bkpt(imm16, false));
7739 break;
7741 case 0x8: /* signed multiply */
7742 case 0xa:
7743 case 0xc:
7744 case 0xe:
7745 ARCH(5TE);
7746 rs = (insn >> 8) & 0xf;
7747 rn = (insn >> 12) & 0xf;
7748 rd = (insn >> 16) & 0xf;
7749 if (op1 == 1) {
7750 /* (32 * 16) >> 16 */
7751 tmp = load_reg(s, rm);
7752 tmp2 = load_reg(s, rs);
7753 if (sh & 4)
7754 tcg_gen_sari_i32(tmp2, tmp2, 16);
7755 else
7756 gen_sxth(tmp2);
7757 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7758 tcg_gen_shri_i64(tmp64, tmp64, 16);
7759 tmp = tcg_temp_new_i32();
7760 tcg_gen_trunc_i64_i32(tmp, tmp64);
7761 tcg_temp_free_i64(tmp64);
7762 if ((sh & 2) == 0) {
7763 tmp2 = load_reg(s, rn);
7764 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7765 tcg_temp_free_i32(tmp2);
7767 store_reg(s, rd, tmp);
7768 } else {
7769 /* 16 * 16 */
7770 tmp = load_reg(s, rm);
7771 tmp2 = load_reg(s, rs);
7772 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7773 tcg_temp_free_i32(tmp2);
7774 if (op1 == 2) {
7775 tmp64 = tcg_temp_new_i64();
7776 tcg_gen_ext_i32_i64(tmp64, tmp);
7777 tcg_temp_free_i32(tmp);
7778 gen_addq(s, tmp64, rn, rd);
7779 gen_storeq_reg(s, rn, rd, tmp64);
7780 tcg_temp_free_i64(tmp64);
7781 } else {
7782 if (op1 == 0) {
7783 tmp2 = load_reg(s, rn);
7784 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7785 tcg_temp_free_i32(tmp2);
7787 store_reg(s, rd, tmp);
7790 break;
7791 default:
7792 goto illegal_op;
7794 } else if (((insn & 0x0e000000) == 0 &&
7795 (insn & 0x00000090) != 0x90) ||
7796 ((insn & 0x0e000000) == (1 << 25))) {
7797 int set_cc, logic_cc, shiftop;
7799 op1 = (insn >> 21) & 0xf;
7800 set_cc = (insn >> 20) & 1;
7801 logic_cc = table_logic_cc[op1] & set_cc;
7803 /* data processing instruction */
7804 if (insn & (1 << 25)) {
7805 /* immediate operand */
7806 val = insn & 0xff;
7807 shift = ((insn >> 8) & 0xf) * 2;
7808 if (shift) {
7809 val = (val >> shift) | (val << (32 - shift));
7811 tmp2 = tcg_temp_new_i32();
7812 tcg_gen_movi_i32(tmp2, val);
7813 if (logic_cc && shift) {
7814 gen_set_CF_bit31(tmp2);
7816 } else {
7817 /* register */
7818 rm = (insn) & 0xf;
7819 tmp2 = load_reg(s, rm);
7820 shiftop = (insn >> 5) & 3;
7821 if (!(insn & (1 << 4))) {
7822 shift = (insn >> 7) & 0x1f;
7823 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7824 } else {
7825 rs = (insn >> 8) & 0xf;
7826 tmp = load_reg(s, rs);
7827 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7830 if (op1 != 0x0f && op1 != 0x0d) {
7831 rn = (insn >> 16) & 0xf;
7832 tmp = load_reg(s, rn);
7833 } else {
7834 TCGV_UNUSED_I32(tmp);
7836 rd = (insn >> 12) & 0xf;
7837 switch(op1) {
7838 case 0x00:
7839 tcg_gen_and_i32(tmp, tmp, tmp2);
7840 if (logic_cc) {
7841 gen_logic_CC(tmp);
7843 store_reg_bx(env, s, rd, tmp);
7844 break;
7845 case 0x01:
7846 tcg_gen_xor_i32(tmp, tmp, tmp2);
7847 if (logic_cc) {
7848 gen_logic_CC(tmp);
7850 store_reg_bx(env, s, rd, tmp);
7851 break;
7852 case 0x02:
7853 if (set_cc && rd == 15) {
7854 /* SUBS r15, ... is used for exception return. */
7855 if (IS_USER(s)) {
7856 goto illegal_op;
7858 gen_sub_CC(tmp, tmp, tmp2);
7859 gen_exception_return(s, tmp);
7860 } else {
7861 if (set_cc) {
7862 gen_sub_CC(tmp, tmp, tmp2);
7863 } else {
7864 tcg_gen_sub_i32(tmp, tmp, tmp2);
7866 store_reg_bx(env, s, rd, tmp);
7868 break;
7869 case 0x03:
7870 if (set_cc) {
7871 gen_sub_CC(tmp, tmp2, tmp);
7872 } else {
7873 tcg_gen_sub_i32(tmp, tmp2, tmp);
7875 store_reg_bx(env, s, rd, tmp);
7876 break;
7877 case 0x04:
7878 if (set_cc) {
7879 gen_add_CC(tmp, tmp, tmp2);
7880 } else {
7881 tcg_gen_add_i32(tmp, tmp, tmp2);
7883 store_reg_bx(env, s, rd, tmp);
7884 break;
7885 case 0x05:
7886 if (set_cc) {
7887 gen_adc_CC(tmp, tmp, tmp2);
7888 } else {
7889 gen_add_carry(tmp, tmp, tmp2);
7891 store_reg_bx(env, s, rd, tmp);
7892 break;
7893 case 0x06:
7894 if (set_cc) {
7895 gen_sbc_CC(tmp, tmp, tmp2);
7896 } else {
7897 gen_sub_carry(tmp, tmp, tmp2);
7899 store_reg_bx(env, s, rd, tmp);
7900 break;
7901 case 0x07:
7902 if (set_cc) {
7903 gen_sbc_CC(tmp, tmp2, tmp);
7904 } else {
7905 gen_sub_carry(tmp, tmp2, tmp);
7907 store_reg_bx(env, s, rd, tmp);
7908 break;
7909 case 0x08:
7910 if (set_cc) {
7911 tcg_gen_and_i32(tmp, tmp, tmp2);
7912 gen_logic_CC(tmp);
7914 tcg_temp_free_i32(tmp);
7915 break;
7916 case 0x09:
7917 if (set_cc) {
7918 tcg_gen_xor_i32(tmp, tmp, tmp2);
7919 gen_logic_CC(tmp);
7921 tcg_temp_free_i32(tmp);
7922 break;
7923 case 0x0a:
7924 if (set_cc) {
7925 gen_sub_CC(tmp, tmp, tmp2);
7927 tcg_temp_free_i32(tmp);
7928 break;
7929 case 0x0b:
7930 if (set_cc) {
7931 gen_add_CC(tmp, tmp, tmp2);
7933 tcg_temp_free_i32(tmp);
7934 break;
7935 case 0x0c:
7936 tcg_gen_or_i32(tmp, tmp, tmp2);
7937 if (logic_cc) {
7938 gen_logic_CC(tmp);
7940 store_reg_bx(env, s, rd, tmp);
7941 break;
7942 case 0x0d:
7943 if (logic_cc && rd == 15) {
7944 /* MOVS r15, ... is used for exception return. */
7945 if (IS_USER(s)) {
7946 goto illegal_op;
7948 gen_exception_return(s, tmp2);
7949 } else {
7950 if (logic_cc) {
7951 gen_logic_CC(tmp2);
7953 store_reg_bx(env, s, rd, tmp2);
7955 break;
7956 case 0x0e:
7957 tcg_gen_andc_i32(tmp, tmp, tmp2);
7958 if (logic_cc) {
7959 gen_logic_CC(tmp);
7961 store_reg_bx(env, s, rd, tmp);
7962 break;
7963 default:
7964 case 0x0f:
7965 tcg_gen_not_i32(tmp2, tmp2);
7966 if (logic_cc) {
7967 gen_logic_CC(tmp2);
7969 store_reg_bx(env, s, rd, tmp2);
7970 break;
7972 if (op1 != 0x0f && op1 != 0x0d) {
7973 tcg_temp_free_i32(tmp2);
7975 } else {
7976 /* other instructions */
7977 op1 = (insn >> 24) & 0xf;
7978 switch(op1) {
7979 case 0x0:
7980 case 0x1:
7981 /* multiplies, extra load/stores */
7982 sh = (insn >> 5) & 3;
7983 if (sh == 0) {
7984 if (op1 == 0x0) {
7985 rd = (insn >> 16) & 0xf;
7986 rn = (insn >> 12) & 0xf;
7987 rs = (insn >> 8) & 0xf;
7988 rm = (insn) & 0xf;
7989 op1 = (insn >> 20) & 0xf;
7990 switch (op1) {
7991 case 0: case 1: case 2: case 3: case 6:
7992 /* 32 bit mul */
7993 tmp = load_reg(s, rs);
7994 tmp2 = load_reg(s, rm);
7995 tcg_gen_mul_i32(tmp, tmp, tmp2);
7996 tcg_temp_free_i32(tmp2);
7997 if (insn & (1 << 22)) {
7998 /* Subtract (mls) */
7999 ARCH(6T2);
8000 tmp2 = load_reg(s, rn);
8001 tcg_gen_sub_i32(tmp, tmp2, tmp);
8002 tcg_temp_free_i32(tmp2);
8003 } else if (insn & (1 << 21)) {
8004 /* Add */
8005 tmp2 = load_reg(s, rn);
8006 tcg_gen_add_i32(tmp, tmp, tmp2);
8007 tcg_temp_free_i32(tmp2);
8009 if (insn & (1 << 20))
8010 gen_logic_CC(tmp);
8011 store_reg(s, rd, tmp);
8012 break;
8013 case 4:
8014 /* 64 bit mul double accumulate (UMAAL) */
8015 ARCH(6);
8016 tmp = load_reg(s, rs);
8017 tmp2 = load_reg(s, rm);
8018 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8019 gen_addq_lo(s, tmp64, rn);
8020 gen_addq_lo(s, tmp64, rd);
8021 gen_storeq_reg(s, rn, rd, tmp64);
8022 tcg_temp_free_i64(tmp64);
8023 break;
8024 case 8: case 9: case 10: case 11:
8025 case 12: case 13: case 14: case 15:
8026 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
8027 tmp = load_reg(s, rs);
8028 tmp2 = load_reg(s, rm);
8029 if (insn & (1 << 22)) {
8030 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8031 } else {
8032 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8034 if (insn & (1 << 21)) { /* mult accumulate */
8035 TCGv_i32 al = load_reg(s, rn);
8036 TCGv_i32 ah = load_reg(s, rd);
8037 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
8038 tcg_temp_free_i32(al);
8039 tcg_temp_free_i32(ah);
8041 if (insn & (1 << 20)) {
8042 gen_logicq_cc(tmp, tmp2);
8044 store_reg(s, rn, tmp);
8045 store_reg(s, rd, tmp2);
8046 break;
8047 default:
8048 goto illegal_op;
8050 } else {
8051 rn = (insn >> 16) & 0xf;
8052 rd = (insn >> 12) & 0xf;
8053 if (insn & (1 << 23)) {
8054 /* load/store exclusive */
8055 int op2 = (insn >> 8) & 3;
8056 op1 = (insn >> 21) & 0x3;
8058 switch (op2) {
8059 case 0: /* lda/stl */
8060 if (op1 == 1) {
8061 goto illegal_op;
8063 ARCH(8);
8064 break;
8065 case 1: /* reserved */
8066 goto illegal_op;
8067 case 2: /* ldaex/stlex */
8068 ARCH(8);
8069 break;
8070 case 3: /* ldrex/strex */
8071 if (op1) {
8072 ARCH(6K);
8073 } else {
8074 ARCH(6);
8076 break;
8079 addr = tcg_temp_local_new_i32();
8080 load_reg_var(s, addr, rn);
8082 /* Since the emulation does not have barriers,
8083 the acquire/release semantics need no special
8084 handling */
8085 if (op2 == 0) {
8086 if (insn & (1 << 20)) {
8087 tmp = tcg_temp_new_i32();
8088 switch (op1) {
8089 case 0: /* lda */
8090 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8091 break;
8092 case 2: /* ldab */
8093 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8094 break;
8095 case 3: /* ldah */
8096 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8097 break;
8098 default:
8099 abort();
8101 store_reg(s, rd, tmp);
8102 } else {
8103 rm = insn & 0xf;
8104 tmp = load_reg(s, rm);
8105 switch (op1) {
8106 case 0: /* stl */
8107 gen_aa32_st32(tmp, addr, IS_USER(s));
8108 break;
8109 case 2: /* stlb */
8110 gen_aa32_st8(tmp, addr, IS_USER(s));
8111 break;
8112 case 3: /* stlh */
8113 gen_aa32_st16(tmp, addr, IS_USER(s));
8114 break;
8115 default:
8116 abort();
8118 tcg_temp_free_i32(tmp);
8120 } else if (insn & (1 << 20)) {
8121 switch (op1) {
8122 case 0: /* ldrex */
8123 gen_load_exclusive(s, rd, 15, addr, 2);
8124 break;
8125 case 1: /* ldrexd */
8126 gen_load_exclusive(s, rd, rd + 1, addr, 3);
8127 break;
8128 case 2: /* ldrexb */
8129 gen_load_exclusive(s, rd, 15, addr, 0);
8130 break;
8131 case 3: /* ldrexh */
8132 gen_load_exclusive(s, rd, 15, addr, 1);
8133 break;
8134 default:
8135 abort();
8137 } else {
8138 rm = insn & 0xf;
8139 switch (op1) {
8140 case 0: /* strex */
8141 gen_store_exclusive(s, rd, rm, 15, addr, 2);
8142 break;
8143 case 1: /* strexd */
8144 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
8145 break;
8146 case 2: /* strexb */
8147 gen_store_exclusive(s, rd, rm, 15, addr, 0);
8148 break;
8149 case 3: /* strexh */
8150 gen_store_exclusive(s, rd, rm, 15, addr, 1);
8151 break;
8152 default:
8153 abort();
8156 tcg_temp_free_i32(addr);
8157 } else {
8158 /* SWP instruction */
8159 rm = (insn) & 0xf;
8161 /* ??? This is not really atomic. However we know
8162 we never have multiple CPUs running in parallel,
8163 so it is good enough. */
8164 addr = load_reg(s, rn);
8165 tmp = load_reg(s, rm);
8166 tmp2 = tcg_temp_new_i32();
8167 if (insn & (1 << 22)) {
8168 gen_aa32_ld8u(tmp2, addr, IS_USER(s));
8169 gen_aa32_st8(tmp, addr, IS_USER(s));
8170 } else {
8171 gen_aa32_ld32u(tmp2, addr, IS_USER(s));
8172 gen_aa32_st32(tmp, addr, IS_USER(s));
8174 tcg_temp_free_i32(tmp);
8175 tcg_temp_free_i32(addr);
8176 store_reg(s, rd, tmp2);
8179 } else {
8180 int address_offset;
8181 int load;
8182 /* Misc load/store */
8183 rn = (insn >> 16) & 0xf;
8184 rd = (insn >> 12) & 0xf;
8185 addr = load_reg(s, rn);
8186 if (insn & (1 << 24))
8187 gen_add_datah_offset(s, insn, 0, addr);
8188 address_offset = 0;
8189 if (insn & (1 << 20)) {
8190 /* load */
8191 tmp = tcg_temp_new_i32();
8192 switch(sh) {
8193 case 1:
8194 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8195 break;
8196 case 2:
8197 gen_aa32_ld8s(tmp, addr, IS_USER(s));
8198 break;
8199 default:
8200 case 3:
8201 gen_aa32_ld16s(tmp, addr, IS_USER(s));
8202 break;
8204 load = 1;
8205 } else if (sh & 2) {
8206 ARCH(5TE);
8207 /* doubleword */
8208 if (sh & 1) {
8209 /* store */
8210 tmp = load_reg(s, rd);
8211 gen_aa32_st32(tmp, addr, IS_USER(s));
8212 tcg_temp_free_i32(tmp);
8213 tcg_gen_addi_i32(addr, addr, 4);
8214 tmp = load_reg(s, rd + 1);
8215 gen_aa32_st32(tmp, addr, IS_USER(s));
8216 tcg_temp_free_i32(tmp);
8217 load = 0;
8218 } else {
8219 /* load */
8220 tmp = tcg_temp_new_i32();
8221 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8222 store_reg(s, rd, tmp);
8223 tcg_gen_addi_i32(addr, addr, 4);
8224 tmp = tcg_temp_new_i32();
8225 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8226 rd++;
8227 load = 1;
8229 address_offset = -4;
8230 } else {
8231 /* store */
8232 tmp = load_reg(s, rd);
8233 gen_aa32_st16(tmp, addr, IS_USER(s));
8234 tcg_temp_free_i32(tmp);
8235 load = 0;
8237 /* Perform base writeback before the loaded value to
8238 ensure correct behavior with overlapping index registers.
8239 ldrd with base writeback is is undefined if the
8240 destination and index registers overlap. */
8241 if (!(insn & (1 << 24))) {
8242 gen_add_datah_offset(s, insn, address_offset, addr);
8243 store_reg(s, rn, addr);
8244 } else if (insn & (1 << 21)) {
8245 if (address_offset)
8246 tcg_gen_addi_i32(addr, addr, address_offset);
8247 store_reg(s, rn, addr);
8248 } else {
8249 tcg_temp_free_i32(addr);
8251 if (load) {
8252 /* Complete the load. */
8253 store_reg(s, rd, tmp);
8256 break;
8257 case 0x4:
8258 case 0x5:
8259 goto do_ldst;
8260 case 0x6:
8261 case 0x7:
8262 if (insn & (1 << 4)) {
8263 ARCH(6);
8264 /* Armv6 Media instructions. */
8265 rm = insn & 0xf;
8266 rn = (insn >> 16) & 0xf;
8267 rd = (insn >> 12) & 0xf;
8268 rs = (insn >> 8) & 0xf;
8269 switch ((insn >> 23) & 3) {
8270 case 0: /* Parallel add/subtract. */
8271 op1 = (insn >> 20) & 7;
8272 tmp = load_reg(s, rn);
8273 tmp2 = load_reg(s, rm);
8274 sh = (insn >> 5) & 7;
8275 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8276 goto illegal_op;
8277 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
8278 tcg_temp_free_i32(tmp2);
8279 store_reg(s, rd, tmp);
8280 break;
8281 case 1:
8282 if ((insn & 0x00700020) == 0) {
8283 /* Halfword pack. */
8284 tmp = load_reg(s, rn);
8285 tmp2 = load_reg(s, rm);
8286 shift = (insn >> 7) & 0x1f;
8287 if (insn & (1 << 6)) {
8288 /* pkhtb */
8289 if (shift == 0)
8290 shift = 31;
8291 tcg_gen_sari_i32(tmp2, tmp2, shift);
8292 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8293 tcg_gen_ext16u_i32(tmp2, tmp2);
8294 } else {
8295 /* pkhbt */
8296 if (shift)
8297 tcg_gen_shli_i32(tmp2, tmp2, shift);
8298 tcg_gen_ext16u_i32(tmp, tmp);
8299 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8301 tcg_gen_or_i32(tmp, tmp, tmp2);
8302 tcg_temp_free_i32(tmp2);
8303 store_reg(s, rd, tmp);
8304 } else if ((insn & 0x00200020) == 0x00200000) {
8305 /* [us]sat */
8306 tmp = load_reg(s, rm);
8307 shift = (insn >> 7) & 0x1f;
8308 if (insn & (1 << 6)) {
8309 if (shift == 0)
8310 shift = 31;
8311 tcg_gen_sari_i32(tmp, tmp, shift);
8312 } else {
8313 tcg_gen_shli_i32(tmp, tmp, shift);
8315 sh = (insn >> 16) & 0x1f;
8316 tmp2 = tcg_const_i32(sh);
8317 if (insn & (1 << 22))
8318 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
8319 else
8320 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
8321 tcg_temp_free_i32(tmp2);
8322 store_reg(s, rd, tmp);
8323 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8324 /* [us]sat16 */
8325 tmp = load_reg(s, rm);
8326 sh = (insn >> 16) & 0x1f;
8327 tmp2 = tcg_const_i32(sh);
8328 if (insn & (1 << 22))
8329 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
8330 else
8331 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
8332 tcg_temp_free_i32(tmp2);
8333 store_reg(s, rd, tmp);
8334 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8335 /* Select bytes. */
8336 tmp = load_reg(s, rn);
8337 tmp2 = load_reg(s, rm);
8338 tmp3 = tcg_temp_new_i32();
8339 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8340 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8341 tcg_temp_free_i32(tmp3);
8342 tcg_temp_free_i32(tmp2);
8343 store_reg(s, rd, tmp);
8344 } else if ((insn & 0x000003e0) == 0x00000060) {
8345 tmp = load_reg(s, rm);
8346 shift = (insn >> 10) & 3;
8347 /* ??? In many cases it's not necessary to do a
8348 rotate, a shift is sufficient. */
8349 if (shift != 0)
8350 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8351 op1 = (insn >> 20) & 7;
8352 switch (op1) {
8353 case 0: gen_sxtb16(tmp); break;
8354 case 2: gen_sxtb(tmp); break;
8355 case 3: gen_sxth(tmp); break;
8356 case 4: gen_uxtb16(tmp); break;
8357 case 6: gen_uxtb(tmp); break;
8358 case 7: gen_uxth(tmp); break;
8359 default: goto illegal_op;
8361 if (rn != 15) {
8362 tmp2 = load_reg(s, rn);
8363 if ((op1 & 3) == 0) {
8364 gen_add16(tmp, tmp2);
8365 } else {
8366 tcg_gen_add_i32(tmp, tmp, tmp2);
8367 tcg_temp_free_i32(tmp2);
8370 store_reg(s, rd, tmp);
8371 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
8372 /* rev */
8373 tmp = load_reg(s, rm);
8374 if (insn & (1 << 22)) {
8375 if (insn & (1 << 7)) {
8376 gen_revsh(tmp);
8377 } else {
8378 ARCH(6T2);
8379 gen_helper_rbit(tmp, tmp);
8381 } else {
8382 if (insn & (1 << 7))
8383 gen_rev16(tmp);
8384 else
8385 tcg_gen_bswap32_i32(tmp, tmp);
8387 store_reg(s, rd, tmp);
8388 } else {
8389 goto illegal_op;
8391 break;
8392 case 2: /* Multiplies (Type 3). */
8393 switch ((insn >> 20) & 0x7) {
8394 case 5:
8395 if (((insn >> 6) ^ (insn >> 7)) & 1) {
8396 /* op2 not 00x or 11x : UNDEF */
8397 goto illegal_op;
8399 /* Signed multiply most significant [accumulate].
8400 (SMMUL, SMMLA, SMMLS) */
8401 tmp = load_reg(s, rm);
8402 tmp2 = load_reg(s, rs);
8403 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8405 if (rd != 15) {
8406 tmp = load_reg(s, rd);
8407 if (insn & (1 << 6)) {
8408 tmp64 = gen_subq_msw(tmp64, tmp);
8409 } else {
8410 tmp64 = gen_addq_msw(tmp64, tmp);
8413 if (insn & (1 << 5)) {
8414 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8416 tcg_gen_shri_i64(tmp64, tmp64, 32);
8417 tmp = tcg_temp_new_i32();
8418 tcg_gen_trunc_i64_i32(tmp, tmp64);
8419 tcg_temp_free_i64(tmp64);
8420 store_reg(s, rn, tmp);
8421 break;
8422 case 0:
8423 case 4:
8424 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
8425 if (insn & (1 << 7)) {
8426 goto illegal_op;
8428 tmp = load_reg(s, rm);
8429 tmp2 = load_reg(s, rs);
8430 if (insn & (1 << 5))
8431 gen_swap_half(tmp2);
8432 gen_smul_dual(tmp, tmp2);
8433 if (insn & (1 << 6)) {
8434 /* This subtraction cannot overflow. */
8435 tcg_gen_sub_i32(tmp, tmp, tmp2);
8436 } else {
8437 /* This addition cannot overflow 32 bits;
8438 * however it may overflow considered as a signed
8439 * operation, in which case we must set the Q flag.
8441 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8443 tcg_temp_free_i32(tmp2);
8444 if (insn & (1 << 22)) {
8445 /* smlald, smlsld */
8446 tmp64 = tcg_temp_new_i64();
8447 tcg_gen_ext_i32_i64(tmp64, tmp);
8448 tcg_temp_free_i32(tmp);
8449 gen_addq(s, tmp64, rd, rn);
8450 gen_storeq_reg(s, rd, rn, tmp64);
8451 tcg_temp_free_i64(tmp64);
8452 } else {
8453 /* smuad, smusd, smlad, smlsd */
8454 if (rd != 15)
8456 tmp2 = load_reg(s, rd);
8457 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8458 tcg_temp_free_i32(tmp2);
8460 store_reg(s, rn, tmp);
8462 break;
8463 case 1:
8464 case 3:
8465 /* SDIV, UDIV */
8466 if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
8467 goto illegal_op;
8469 if (((insn >> 5) & 7) || (rd != 15)) {
8470 goto illegal_op;
8472 tmp = load_reg(s, rm);
8473 tmp2 = load_reg(s, rs);
8474 if (insn & (1 << 21)) {
8475 gen_helper_udiv(tmp, tmp, tmp2);
8476 } else {
8477 gen_helper_sdiv(tmp, tmp, tmp2);
8479 tcg_temp_free_i32(tmp2);
8480 store_reg(s, rn, tmp);
8481 break;
8482 default:
8483 goto illegal_op;
8485 break;
8486 case 3:
8487 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8488 switch (op1) {
8489 case 0: /* Unsigned sum of absolute differences. */
8490 ARCH(6);
8491 tmp = load_reg(s, rm);
8492 tmp2 = load_reg(s, rs);
8493 gen_helper_usad8(tmp, tmp, tmp2);
8494 tcg_temp_free_i32(tmp2);
8495 if (rd != 15) {
8496 tmp2 = load_reg(s, rd);
8497 tcg_gen_add_i32(tmp, tmp, tmp2);
8498 tcg_temp_free_i32(tmp2);
8500 store_reg(s, rn, tmp);
8501 break;
8502 case 0x20: case 0x24: case 0x28: case 0x2c:
8503 /* Bitfield insert/clear. */
8504 ARCH(6T2);
8505 shift = (insn >> 7) & 0x1f;
8506 i = (insn >> 16) & 0x1f;
8507 i = i + 1 - shift;
8508 if (rm == 15) {
8509 tmp = tcg_temp_new_i32();
8510 tcg_gen_movi_i32(tmp, 0);
8511 } else {
8512 tmp = load_reg(s, rm);
8514 if (i != 32) {
8515 tmp2 = load_reg(s, rd);
8516 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
8517 tcg_temp_free_i32(tmp2);
8519 store_reg(s, rd, tmp);
8520 break;
8521 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8522 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
8523 ARCH(6T2);
8524 tmp = load_reg(s, rm);
8525 shift = (insn >> 7) & 0x1f;
8526 i = ((insn >> 16) & 0x1f) + 1;
8527 if (shift + i > 32)
8528 goto illegal_op;
8529 if (i < 32) {
8530 if (op1 & 0x20) {
8531 gen_ubfx(tmp, shift, (1u << i) - 1);
8532 } else {
8533 gen_sbfx(tmp, shift, i);
8536 store_reg(s, rd, tmp);
8537 break;
8538 default:
8539 goto illegal_op;
8541 break;
8543 break;
8545 do_ldst:
8546 /* Check for undefined extension instructions
8547 * per the ARM Bible IE:
8548 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
8550 sh = (0xf << 20) | (0xf << 4);
8551 if (op1 == 0x7 && ((insn & sh) == sh))
8553 goto illegal_op;
8555 /* load/store byte/word */
8556 rn = (insn >> 16) & 0xf;
8557 rd = (insn >> 12) & 0xf;
8558 tmp2 = load_reg(s, rn);
8559 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
8560 if (insn & (1 << 24))
8561 gen_add_data_offset(s, insn, tmp2);
8562 if (insn & (1 << 20)) {
8563 /* load */
8564 tmp = tcg_temp_new_i32();
8565 if (insn & (1 << 22)) {
8566 gen_aa32_ld8u(tmp, tmp2, i);
8567 } else {
8568 gen_aa32_ld32u(tmp, tmp2, i);
8570 } else {
8571 /* store */
8572 tmp = load_reg(s, rd);
8573 if (insn & (1 << 22)) {
8574 gen_aa32_st8(tmp, tmp2, i);
8575 } else {
8576 gen_aa32_st32(tmp, tmp2, i);
8578 tcg_temp_free_i32(tmp);
8580 if (!(insn & (1 << 24))) {
8581 gen_add_data_offset(s, insn, tmp2);
8582 store_reg(s, rn, tmp2);
8583 } else if (insn & (1 << 21)) {
8584 store_reg(s, rn, tmp2);
8585 } else {
8586 tcg_temp_free_i32(tmp2);
8588 if (insn & (1 << 20)) {
8589 /* Complete the load. */
8590 store_reg_from_load(env, s, rd, tmp);
8592 break;
8593 case 0x08:
8594 case 0x09:
8596 int j, n, user, loaded_base;
8597 TCGv_i32 loaded_var;
8598 /* load/store multiple words */
8599 /* XXX: store correct base if write back */
8600 user = 0;
8601 if (insn & (1 << 22)) {
8602 if (IS_USER(s))
8603 goto illegal_op; /* only usable in supervisor mode */
8605 if ((insn & (1 << 15)) == 0)
8606 user = 1;
8608 rn = (insn >> 16) & 0xf;
8609 addr = load_reg(s, rn);
8611 /* compute total size */
8612 loaded_base = 0;
8613 TCGV_UNUSED_I32(loaded_var);
8614 n = 0;
8615 for(i=0;i<16;i++) {
8616 if (insn & (1 << i))
8617 n++;
8619 /* XXX: test invalid n == 0 case ? */
8620 if (insn & (1 << 23)) {
8621 if (insn & (1 << 24)) {
8622 /* pre increment */
8623 tcg_gen_addi_i32(addr, addr, 4);
8624 } else {
8625 /* post increment */
8627 } else {
8628 if (insn & (1 << 24)) {
8629 /* pre decrement */
8630 tcg_gen_addi_i32(addr, addr, -(n * 4));
8631 } else {
8632 /* post decrement */
8633 if (n != 1)
8634 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8637 j = 0;
8638 for(i=0;i<16;i++) {
8639 if (insn & (1 << i)) {
8640 if (insn & (1 << 20)) {
8641 /* load */
8642 tmp = tcg_temp_new_i32();
8643 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8644 if (user) {
8645 tmp2 = tcg_const_i32(i);
8646 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
8647 tcg_temp_free_i32(tmp2);
8648 tcg_temp_free_i32(tmp);
8649 } else if (i == rn) {
8650 loaded_var = tmp;
8651 loaded_base = 1;
8652 } else {
8653 store_reg_from_load(env, s, i, tmp);
8655 } else {
8656 /* store */
8657 if (i == 15) {
8658 /* special case: r15 = PC + 8 */
8659 val = (long)s->pc + 4;
8660 tmp = tcg_temp_new_i32();
8661 tcg_gen_movi_i32(tmp, val);
8662 } else if (user) {
8663 tmp = tcg_temp_new_i32();
8664 tmp2 = tcg_const_i32(i);
8665 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
8666 tcg_temp_free_i32(tmp2);
8667 } else {
8668 tmp = load_reg(s, i);
8670 gen_aa32_st32(tmp, addr, IS_USER(s));
8671 tcg_temp_free_i32(tmp);
8673 j++;
8674 /* no need to add after the last transfer */
8675 if (j != n)
8676 tcg_gen_addi_i32(addr, addr, 4);
8679 if (insn & (1 << 21)) {
8680 /* write back */
8681 if (insn & (1 << 23)) {
8682 if (insn & (1 << 24)) {
8683 /* pre increment */
8684 } else {
8685 /* post increment */
8686 tcg_gen_addi_i32(addr, addr, 4);
8688 } else {
8689 if (insn & (1 << 24)) {
8690 /* pre decrement */
8691 if (n != 1)
8692 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8693 } else {
8694 /* post decrement */
8695 tcg_gen_addi_i32(addr, addr, -(n * 4));
8698 store_reg(s, rn, addr);
8699 } else {
8700 tcg_temp_free_i32(addr);
8702 if (loaded_base) {
8703 store_reg(s, rn, loaded_var);
8705 if ((insn & (1 << 22)) && !user) {
8706 /* Restore CPSR from SPSR. */
8707 tmp = load_cpu_field(spsr);
8708 gen_set_cpsr(tmp, 0xffffffff);
8709 tcg_temp_free_i32(tmp);
8710 s->is_jmp = DISAS_UPDATE;
8713 break;
8714 case 0xa:
8715 case 0xb:
8717 int32_t offset;
8719 /* branch (and link) */
8720 val = (int32_t)s->pc;
8721 if (insn & (1 << 24)) {
8722 tmp = tcg_temp_new_i32();
8723 tcg_gen_movi_i32(tmp, val);
8724 store_reg(s, 14, tmp);
8726 offset = sextract32(insn << 2, 0, 26);
8727 val += offset + 4;
8728 gen_jmp(s, val);
8730 break;
8731 case 0xc:
8732 case 0xd:
8733 case 0xe:
8734 if (((insn >> 8) & 0xe) == 10) {
8735 /* VFP. */
8736 if (disas_vfp_insn(env, s, insn)) {
8737 goto illegal_op;
8739 } else if (disas_coproc_insn(env, s, insn)) {
8740 /* Coprocessor. */
8741 goto illegal_op;
8743 break;
8744 case 0xf:
8745 /* swi */
8746 gen_set_pc_im(s, s->pc);
8747 s->svc_imm = extract32(insn, 0, 24);
8748 s->is_jmp = DISAS_SWI;
8749 break;
8750 default:
8751 illegal_op:
8752 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
8753 break;
8758 /* Return true if this is a Thumb-2 logical op. */
8759 static int
8760 thumb2_logic_op(int op)
8762 return (op < 8);
8765 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
8766 then set condition code flags based on the result of the operation.
8767 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
8768 to the high bit of T1.
8769 Returns zero if the opcode is valid. */
8771 static int
8772 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
8773 TCGv_i32 t0, TCGv_i32 t1)
8775 int logic_cc;
8777 logic_cc = 0;
8778 switch (op) {
8779 case 0: /* and */
8780 tcg_gen_and_i32(t0, t0, t1);
8781 logic_cc = conds;
8782 break;
8783 case 1: /* bic */
8784 tcg_gen_andc_i32(t0, t0, t1);
8785 logic_cc = conds;
8786 break;
8787 case 2: /* orr */
8788 tcg_gen_or_i32(t0, t0, t1);
8789 logic_cc = conds;
8790 break;
8791 case 3: /* orn */
8792 tcg_gen_orc_i32(t0, t0, t1);
8793 logic_cc = conds;
8794 break;
8795 case 4: /* eor */
8796 tcg_gen_xor_i32(t0, t0, t1);
8797 logic_cc = conds;
8798 break;
8799 case 8: /* add */
8800 if (conds)
8801 gen_add_CC(t0, t0, t1);
8802 else
8803 tcg_gen_add_i32(t0, t0, t1);
8804 break;
8805 case 10: /* adc */
8806 if (conds)
8807 gen_adc_CC(t0, t0, t1);
8808 else
8809 gen_adc(t0, t1);
8810 break;
8811 case 11: /* sbc */
8812 if (conds) {
8813 gen_sbc_CC(t0, t0, t1);
8814 } else {
8815 gen_sub_carry(t0, t0, t1);
8817 break;
8818 case 13: /* sub */
8819 if (conds)
8820 gen_sub_CC(t0, t0, t1);
8821 else
8822 tcg_gen_sub_i32(t0, t0, t1);
8823 break;
8824 case 14: /* rsb */
8825 if (conds)
8826 gen_sub_CC(t0, t1, t0);
8827 else
8828 tcg_gen_sub_i32(t0, t1, t0);
8829 break;
8830 default: /* 5, 6, 7, 9, 12, 15. */
8831 return 1;
8833 if (logic_cc) {
8834 gen_logic_CC(t0);
8835 if (shifter_out)
8836 gen_set_CF_bit31(t1);
8838 return 0;
8841 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
8842 is not legal. */
8843 static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
8845 uint32_t insn, imm, shift, offset;
8846 uint32_t rd, rn, rm, rs;
8847 TCGv_i32 tmp;
8848 TCGv_i32 tmp2;
8849 TCGv_i32 tmp3;
8850 TCGv_i32 addr;
8851 TCGv_i64 tmp64;
8852 int op;
8853 int shiftop;
8854 int conds;
8855 int logic_cc;
8857 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
8858 || arm_feature (env, ARM_FEATURE_M))) {
8859 /* Thumb-1 cores may need to treat bl and blx as a pair of
8860 16-bit instructions to get correct prefetch abort behavior. */
8861 insn = insn_hw1;
8862 if ((insn & (1 << 12)) == 0) {
8863 ARCH(5);
8864 /* Second half of blx. */
8865 offset = ((insn & 0x7ff) << 1);
8866 tmp = load_reg(s, 14);
8867 tcg_gen_addi_i32(tmp, tmp, offset);
8868 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8870 tmp2 = tcg_temp_new_i32();
8871 tcg_gen_movi_i32(tmp2, s->pc | 1);
8872 store_reg(s, 14, tmp2);
8873 gen_bx(s, tmp);
8874 return 0;
8876 if (insn & (1 << 11)) {
8877 /* Second half of bl. */
8878 offset = ((insn & 0x7ff) << 1) | 1;
8879 tmp = load_reg(s, 14);
8880 tcg_gen_addi_i32(tmp, tmp, offset);
8882 tmp2 = tcg_temp_new_i32();
8883 tcg_gen_movi_i32(tmp2, s->pc | 1);
8884 store_reg(s, 14, tmp2);
8885 gen_bx(s, tmp);
8886 return 0;
8888 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
8889 /* Instruction spans a page boundary. Implement it as two
8890 16-bit instructions in case the second half causes an
8891 prefetch abort. */
8892 offset = ((int32_t)insn << 21) >> 9;
8893 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
8894 return 0;
8896 /* Fall through to 32-bit decode. */
8899 insn = arm_lduw_code(env, s->pc, s->bswap_code);
8900 s->pc += 2;
8901 insn |= (uint32_t)insn_hw1 << 16;
8903 if ((insn & 0xf800e800) != 0xf000e800) {
8904 ARCH(6T2);
8907 rn = (insn >> 16) & 0xf;
8908 rs = (insn >> 12) & 0xf;
8909 rd = (insn >> 8) & 0xf;
8910 rm = insn & 0xf;
8911 switch ((insn >> 25) & 0xf) {
8912 case 0: case 1: case 2: case 3:
8913 /* 16-bit instructions. Should never happen. */
8914 abort();
8915 case 4:
8916 if (insn & (1 << 22)) {
8917 /* Other load/store, table branch. */
8918 if (insn & 0x01200000) {
8919 /* Load/store doubleword. */
8920 if (rn == 15) {
8921 addr = tcg_temp_new_i32();
8922 tcg_gen_movi_i32(addr, s->pc & ~3);
8923 } else {
8924 addr = load_reg(s, rn);
8926 offset = (insn & 0xff) * 4;
8927 if ((insn & (1 << 23)) == 0)
8928 offset = -offset;
8929 if (insn & (1 << 24)) {
8930 tcg_gen_addi_i32(addr, addr, offset);
8931 offset = 0;
8933 if (insn & (1 << 20)) {
8934 /* ldrd */
8935 tmp = tcg_temp_new_i32();
8936 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8937 store_reg(s, rs, tmp);
8938 tcg_gen_addi_i32(addr, addr, 4);
8939 tmp = tcg_temp_new_i32();
8940 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8941 store_reg(s, rd, tmp);
8942 } else {
8943 /* strd */
8944 tmp = load_reg(s, rs);
8945 gen_aa32_st32(tmp, addr, IS_USER(s));
8946 tcg_temp_free_i32(tmp);
8947 tcg_gen_addi_i32(addr, addr, 4);
8948 tmp = load_reg(s, rd);
8949 gen_aa32_st32(tmp, addr, IS_USER(s));
8950 tcg_temp_free_i32(tmp);
8952 if (insn & (1 << 21)) {
8953 /* Base writeback. */
8954 if (rn == 15)
8955 goto illegal_op;
8956 tcg_gen_addi_i32(addr, addr, offset - 4);
8957 store_reg(s, rn, addr);
8958 } else {
8959 tcg_temp_free_i32(addr);
8961 } else if ((insn & (1 << 23)) == 0) {
8962 /* Load/store exclusive word. */
8963 addr = tcg_temp_local_new_i32();
8964 load_reg_var(s, addr, rn);
8965 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
8966 if (insn & (1 << 20)) {
8967 gen_load_exclusive(s, rs, 15, addr, 2);
8968 } else {
8969 gen_store_exclusive(s, rd, rs, 15, addr, 2);
8971 tcg_temp_free_i32(addr);
8972 } else if ((insn & (7 << 5)) == 0) {
8973 /* Table Branch. */
8974 if (rn == 15) {
8975 addr = tcg_temp_new_i32();
8976 tcg_gen_movi_i32(addr, s->pc);
8977 } else {
8978 addr = load_reg(s, rn);
8980 tmp = load_reg(s, rm);
8981 tcg_gen_add_i32(addr, addr, tmp);
8982 if (insn & (1 << 4)) {
8983 /* tbh */
8984 tcg_gen_add_i32(addr, addr, tmp);
8985 tcg_temp_free_i32(tmp);
8986 tmp = tcg_temp_new_i32();
8987 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8988 } else { /* tbb */
8989 tcg_temp_free_i32(tmp);
8990 tmp = tcg_temp_new_i32();
8991 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8993 tcg_temp_free_i32(addr);
8994 tcg_gen_shli_i32(tmp, tmp, 1);
8995 tcg_gen_addi_i32(tmp, tmp, s->pc);
8996 store_reg(s, 15, tmp);
8997 } else {
8998 int op2 = (insn >> 6) & 0x3;
8999 op = (insn >> 4) & 0x3;
9000 switch (op2) {
9001 case 0:
9002 goto illegal_op;
9003 case 1:
9004 /* Load/store exclusive byte/halfword/doubleword */
9005 if (op == 2) {
9006 goto illegal_op;
9008 ARCH(7);
9009 break;
9010 case 2:
9011 /* Load-acquire/store-release */
9012 if (op == 3) {
9013 goto illegal_op;
9015 /* Fall through */
9016 case 3:
9017 /* Load-acquire/store-release exclusive */
9018 ARCH(8);
9019 break;
9021 addr = tcg_temp_local_new_i32();
9022 load_reg_var(s, addr, rn);
9023 if (!(op2 & 1)) {
9024 if (insn & (1 << 20)) {
9025 tmp = tcg_temp_new_i32();
9026 switch (op) {
9027 case 0: /* ldab */
9028 gen_aa32_ld8u(tmp, addr, IS_USER(s));
9029 break;
9030 case 1: /* ldah */
9031 gen_aa32_ld16u(tmp, addr, IS_USER(s));
9032 break;
9033 case 2: /* lda */
9034 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9035 break;
9036 default:
9037 abort();
9039 store_reg(s, rs, tmp);
9040 } else {
9041 tmp = load_reg(s, rs);
9042 switch (op) {
9043 case 0: /* stlb */
9044 gen_aa32_st8(tmp, addr, IS_USER(s));
9045 break;
9046 case 1: /* stlh */
9047 gen_aa32_st16(tmp, addr, IS_USER(s));
9048 break;
9049 case 2: /* stl */
9050 gen_aa32_st32(tmp, addr, IS_USER(s));
9051 break;
9052 default:
9053 abort();
9055 tcg_temp_free_i32(tmp);
9057 } else if (insn & (1 << 20)) {
9058 gen_load_exclusive(s, rs, rd, addr, op);
9059 } else {
9060 gen_store_exclusive(s, rm, rs, rd, addr, op);
9062 tcg_temp_free_i32(addr);
9064 } else {
9065 /* Load/store multiple, RFE, SRS. */
9066 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
9067 /* RFE, SRS: not available in user mode or on M profile */
9068 if (IS_USER(s) || IS_M(env)) {
9069 goto illegal_op;
9071 if (insn & (1 << 20)) {
9072 /* rfe */
9073 addr = load_reg(s, rn);
9074 if ((insn & (1 << 24)) == 0)
9075 tcg_gen_addi_i32(addr, addr, -8);
9076 /* Load PC into tmp and CPSR into tmp2. */
9077 tmp = tcg_temp_new_i32();
9078 gen_aa32_ld32u(tmp, addr, 0);
9079 tcg_gen_addi_i32(addr, addr, 4);
9080 tmp2 = tcg_temp_new_i32();
9081 gen_aa32_ld32u(tmp2, addr, 0);
9082 if (insn & (1 << 21)) {
9083 /* Base writeback. */
9084 if (insn & (1 << 24)) {
9085 tcg_gen_addi_i32(addr, addr, 4);
9086 } else {
9087 tcg_gen_addi_i32(addr, addr, -4);
9089 store_reg(s, rn, addr);
9090 } else {
9091 tcg_temp_free_i32(addr);
9093 gen_rfe(s, tmp, tmp2);
9094 } else {
9095 /* srs */
9096 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
9097 insn & (1 << 21));
9099 } else {
9100 int i, loaded_base = 0;
9101 TCGv_i32 loaded_var;
9102 /* Load/store multiple. */
9103 addr = load_reg(s, rn);
9104 offset = 0;
9105 for (i = 0; i < 16; i++) {
9106 if (insn & (1 << i))
9107 offset += 4;
9109 if (insn & (1 << 24)) {
9110 tcg_gen_addi_i32(addr, addr, -offset);
9113 TCGV_UNUSED_I32(loaded_var);
9114 for (i = 0; i < 16; i++) {
9115 if ((insn & (1 << i)) == 0)
9116 continue;
9117 if (insn & (1 << 20)) {
9118 /* Load. */
9119 tmp = tcg_temp_new_i32();
9120 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9121 if (i == 15) {
9122 gen_bx(s, tmp);
9123 } else if (i == rn) {
9124 loaded_var = tmp;
9125 loaded_base = 1;
9126 } else {
9127 store_reg(s, i, tmp);
9129 } else {
9130 /* Store. */
9131 tmp = load_reg(s, i);
9132 gen_aa32_st32(tmp, addr, IS_USER(s));
9133 tcg_temp_free_i32(tmp);
9135 tcg_gen_addi_i32(addr, addr, 4);
9137 if (loaded_base) {
9138 store_reg(s, rn, loaded_var);
9140 if (insn & (1 << 21)) {
9141 /* Base register writeback. */
9142 if (insn & (1 << 24)) {
9143 tcg_gen_addi_i32(addr, addr, -offset);
9145 /* Fault if writeback register is in register list. */
9146 if (insn & (1 << rn))
9147 goto illegal_op;
9148 store_reg(s, rn, addr);
9149 } else {
9150 tcg_temp_free_i32(addr);
9154 break;
9155 case 5:
9157 op = (insn >> 21) & 0xf;
9158 if (op == 6) {
9159 /* Halfword pack. */
9160 tmp = load_reg(s, rn);
9161 tmp2 = load_reg(s, rm);
9162 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
9163 if (insn & (1 << 5)) {
9164 /* pkhtb */
9165 if (shift == 0)
9166 shift = 31;
9167 tcg_gen_sari_i32(tmp2, tmp2, shift);
9168 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9169 tcg_gen_ext16u_i32(tmp2, tmp2);
9170 } else {
9171 /* pkhbt */
9172 if (shift)
9173 tcg_gen_shli_i32(tmp2, tmp2, shift);
9174 tcg_gen_ext16u_i32(tmp, tmp);
9175 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9177 tcg_gen_or_i32(tmp, tmp, tmp2);
9178 tcg_temp_free_i32(tmp2);
9179 store_reg(s, rd, tmp);
9180 } else {
9181 /* Data processing register constant shift. */
9182 if (rn == 15) {
9183 tmp = tcg_temp_new_i32();
9184 tcg_gen_movi_i32(tmp, 0);
9185 } else {
9186 tmp = load_reg(s, rn);
9188 tmp2 = load_reg(s, rm);
9190 shiftop = (insn >> 4) & 3;
9191 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9192 conds = (insn & (1 << 20)) != 0;
9193 logic_cc = (conds && thumb2_logic_op(op));
9194 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9195 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9196 goto illegal_op;
9197 tcg_temp_free_i32(tmp2);
9198 if (rd != 15) {
9199 store_reg(s, rd, tmp);
9200 } else {
9201 tcg_temp_free_i32(tmp);
9204 break;
9205 case 13: /* Misc data processing. */
9206 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9207 if (op < 4 && (insn & 0xf000) != 0xf000)
9208 goto illegal_op;
9209 switch (op) {
9210 case 0: /* Register controlled shift. */
9211 tmp = load_reg(s, rn);
9212 tmp2 = load_reg(s, rm);
9213 if ((insn & 0x70) != 0)
9214 goto illegal_op;
9215 op = (insn >> 21) & 3;
9216 logic_cc = (insn & (1 << 20)) != 0;
9217 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9218 if (logic_cc)
9219 gen_logic_CC(tmp);
9220 store_reg_bx(env, s, rd, tmp);
9221 break;
9222 case 1: /* Sign/zero extend. */
9223 tmp = load_reg(s, rm);
9224 shift = (insn >> 4) & 3;
9225 /* ??? In many cases it's not necessary to do a
9226 rotate, a shift is sufficient. */
9227 if (shift != 0)
9228 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9229 op = (insn >> 20) & 7;
9230 switch (op) {
9231 case 0: gen_sxth(tmp); break;
9232 case 1: gen_uxth(tmp); break;
9233 case 2: gen_sxtb16(tmp); break;
9234 case 3: gen_uxtb16(tmp); break;
9235 case 4: gen_sxtb(tmp); break;
9236 case 5: gen_uxtb(tmp); break;
9237 default: goto illegal_op;
9239 if (rn != 15) {
9240 tmp2 = load_reg(s, rn);
9241 if ((op >> 1) == 1) {
9242 gen_add16(tmp, tmp2);
9243 } else {
9244 tcg_gen_add_i32(tmp, tmp, tmp2);
9245 tcg_temp_free_i32(tmp2);
9248 store_reg(s, rd, tmp);
9249 break;
9250 case 2: /* SIMD add/subtract. */
9251 op = (insn >> 20) & 7;
9252 shift = (insn >> 4) & 7;
9253 if ((op & 3) == 3 || (shift & 3) == 3)
9254 goto illegal_op;
9255 tmp = load_reg(s, rn);
9256 tmp2 = load_reg(s, rm);
9257 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
9258 tcg_temp_free_i32(tmp2);
9259 store_reg(s, rd, tmp);
9260 break;
9261 case 3: /* Other data processing. */
9262 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9263 if (op < 4) {
9264 /* Saturating add/subtract. */
9265 tmp = load_reg(s, rn);
9266 tmp2 = load_reg(s, rm);
9267 if (op & 1)
9268 gen_helper_double_saturate(tmp, cpu_env, tmp);
9269 if (op & 2)
9270 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9271 else
9272 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
9273 tcg_temp_free_i32(tmp2);
9274 } else {
9275 tmp = load_reg(s, rn);
9276 switch (op) {
9277 case 0x0a: /* rbit */
9278 gen_helper_rbit(tmp, tmp);
9279 break;
9280 case 0x08: /* rev */
9281 tcg_gen_bswap32_i32(tmp, tmp);
9282 break;
9283 case 0x09: /* rev16 */
9284 gen_rev16(tmp);
9285 break;
9286 case 0x0b: /* revsh */
9287 gen_revsh(tmp);
9288 break;
9289 case 0x10: /* sel */
9290 tmp2 = load_reg(s, rm);
9291 tmp3 = tcg_temp_new_i32();
9292 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
9293 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
9294 tcg_temp_free_i32(tmp3);
9295 tcg_temp_free_i32(tmp2);
9296 break;
9297 case 0x18: /* clz */
9298 gen_helper_clz(tmp, tmp);
9299 break;
9300 case 0x20:
9301 case 0x21:
9302 case 0x22:
9303 case 0x28:
9304 case 0x29:
9305 case 0x2a:
9307 /* crc32/crc32c */
9308 uint32_t sz = op & 0x3;
9309 uint32_t c = op & 0x8;
9311 if (!arm_feature(env, ARM_FEATURE_CRC)) {
9312 goto illegal_op;
9315 tmp2 = load_reg(s, rm);
9316 tmp3 = tcg_const_i32(1 << sz);
9317 if (c) {
9318 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
9319 } else {
9320 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
9322 tcg_temp_free_i32(tmp2);
9323 tcg_temp_free_i32(tmp3);
9324 break;
9326 default:
9327 goto illegal_op;
9330 store_reg(s, rd, tmp);
9331 break;
9332 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
9333 op = (insn >> 4) & 0xf;
9334 tmp = load_reg(s, rn);
9335 tmp2 = load_reg(s, rm);
9336 switch ((insn >> 20) & 7) {
9337 case 0: /* 32 x 32 -> 32 */
9338 tcg_gen_mul_i32(tmp, tmp, tmp2);
9339 tcg_temp_free_i32(tmp2);
9340 if (rs != 15) {
9341 tmp2 = load_reg(s, rs);
9342 if (op)
9343 tcg_gen_sub_i32(tmp, tmp2, tmp);
9344 else
9345 tcg_gen_add_i32(tmp, tmp, tmp2);
9346 tcg_temp_free_i32(tmp2);
9348 break;
9349 case 1: /* 16 x 16 -> 32 */
9350 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9351 tcg_temp_free_i32(tmp2);
9352 if (rs != 15) {
9353 tmp2 = load_reg(s, rs);
9354 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9355 tcg_temp_free_i32(tmp2);
9357 break;
9358 case 2: /* Dual multiply add. */
9359 case 4: /* Dual multiply subtract. */
9360 if (op)
9361 gen_swap_half(tmp2);
9362 gen_smul_dual(tmp, tmp2);
9363 if (insn & (1 << 22)) {
9364 /* This subtraction cannot overflow. */
9365 tcg_gen_sub_i32(tmp, tmp, tmp2);
9366 } else {
9367 /* This addition cannot overflow 32 bits;
9368 * however it may overflow considered as a signed
9369 * operation, in which case we must set the Q flag.
9371 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9373 tcg_temp_free_i32(tmp2);
9374 if (rs != 15)
9376 tmp2 = load_reg(s, rs);
9377 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9378 tcg_temp_free_i32(tmp2);
9380 break;
9381 case 3: /* 32 * 16 -> 32msb */
9382 if (op)
9383 tcg_gen_sari_i32(tmp2, tmp2, 16);
9384 else
9385 gen_sxth(tmp2);
9386 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9387 tcg_gen_shri_i64(tmp64, tmp64, 16);
9388 tmp = tcg_temp_new_i32();
9389 tcg_gen_trunc_i64_i32(tmp, tmp64);
9390 tcg_temp_free_i64(tmp64);
9391 if (rs != 15)
9393 tmp2 = load_reg(s, rs);
9394 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9395 tcg_temp_free_i32(tmp2);
9397 break;
9398 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
9399 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9400 if (rs != 15) {
9401 tmp = load_reg(s, rs);
9402 if (insn & (1 << 20)) {
9403 tmp64 = gen_addq_msw(tmp64, tmp);
9404 } else {
9405 tmp64 = gen_subq_msw(tmp64, tmp);
9408 if (insn & (1 << 4)) {
9409 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9411 tcg_gen_shri_i64(tmp64, tmp64, 32);
9412 tmp = tcg_temp_new_i32();
9413 tcg_gen_trunc_i64_i32(tmp, tmp64);
9414 tcg_temp_free_i64(tmp64);
9415 break;
9416 case 7: /* Unsigned sum of absolute differences. */
9417 gen_helper_usad8(tmp, tmp, tmp2);
9418 tcg_temp_free_i32(tmp2);
9419 if (rs != 15) {
9420 tmp2 = load_reg(s, rs);
9421 tcg_gen_add_i32(tmp, tmp, tmp2);
9422 tcg_temp_free_i32(tmp2);
9424 break;
9426 store_reg(s, rd, tmp);
9427 break;
9428 case 6: case 7: /* 64-bit multiply, Divide. */
9429 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
9430 tmp = load_reg(s, rn);
9431 tmp2 = load_reg(s, rm);
9432 if ((op & 0x50) == 0x10) {
9433 /* sdiv, udiv */
9434 if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
9435 goto illegal_op;
9437 if (op & 0x20)
9438 gen_helper_udiv(tmp, tmp, tmp2);
9439 else
9440 gen_helper_sdiv(tmp, tmp, tmp2);
9441 tcg_temp_free_i32(tmp2);
9442 store_reg(s, rd, tmp);
9443 } else if ((op & 0xe) == 0xc) {
9444 /* Dual multiply accumulate long. */
9445 if (op & 1)
9446 gen_swap_half(tmp2);
9447 gen_smul_dual(tmp, tmp2);
9448 if (op & 0x10) {
9449 tcg_gen_sub_i32(tmp, tmp, tmp2);
9450 } else {
9451 tcg_gen_add_i32(tmp, tmp, tmp2);
9453 tcg_temp_free_i32(tmp2);
9454 /* BUGFIX */
9455 tmp64 = tcg_temp_new_i64();
9456 tcg_gen_ext_i32_i64(tmp64, tmp);
9457 tcg_temp_free_i32(tmp);
9458 gen_addq(s, tmp64, rs, rd);
9459 gen_storeq_reg(s, rs, rd, tmp64);
9460 tcg_temp_free_i64(tmp64);
9461 } else {
9462 if (op & 0x20) {
9463 /* Unsigned 64-bit multiply */
9464 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9465 } else {
9466 if (op & 8) {
9467 /* smlalxy */
9468 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9469 tcg_temp_free_i32(tmp2);
9470 tmp64 = tcg_temp_new_i64();
9471 tcg_gen_ext_i32_i64(tmp64, tmp);
9472 tcg_temp_free_i32(tmp);
9473 } else {
9474 /* Signed 64-bit multiply */
9475 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9478 if (op & 4) {
9479 /* umaal */
9480 gen_addq_lo(s, tmp64, rs);
9481 gen_addq_lo(s, tmp64, rd);
9482 } else if (op & 0x40) {
9483 /* 64-bit accumulate. */
9484 gen_addq(s, tmp64, rs, rd);
9486 gen_storeq_reg(s, rs, rd, tmp64);
9487 tcg_temp_free_i64(tmp64);
9489 break;
9491 break;
9492 case 6: case 7: case 14: case 15:
9493 /* Coprocessor. */
9494 if (((insn >> 24) & 3) == 3) {
9495 /* Translate into the equivalent ARM encoding. */
9496 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
9497 if (disas_neon_data_insn(env, s, insn))
9498 goto illegal_op;
9499 } else if (((insn >> 8) & 0xe) == 10) {
9500 if (disas_vfp_insn(env, s, insn)) {
9501 goto illegal_op;
9503 } else {
9504 if (insn & (1 << 28))
9505 goto illegal_op;
9506 if (disas_coproc_insn (env, s, insn))
9507 goto illegal_op;
9509 break;
9510 case 8: case 9: case 10: case 11:
9511 if (insn & (1 << 15)) {
9512 /* Branches, misc control. */
9513 if (insn & 0x5000) {
9514 /* Unconditional branch. */
9515 /* signextend(hw1[10:0]) -> offset[:12]. */
9516 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
9517 /* hw1[10:0] -> offset[11:1]. */
9518 offset |= (insn & 0x7ff) << 1;
9519 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
9520 offset[24:22] already have the same value because of the
9521 sign extension above. */
9522 offset ^= ((~insn) & (1 << 13)) << 10;
9523 offset ^= ((~insn) & (1 << 11)) << 11;
9525 if (insn & (1 << 14)) {
9526 /* Branch and link. */
9527 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
9530 offset += s->pc;
9531 if (insn & (1 << 12)) {
9532 /* b/bl */
9533 gen_jmp(s, offset);
9534 } else {
9535 /* blx */
9536 offset &= ~(uint32_t)2;
9537 /* thumb2 bx, no need to check */
9538 gen_bx_im(s, offset);
9540 } else if (((insn >> 23) & 7) == 7) {
9541 /* Misc control */
9542 if (insn & (1 << 13))
9543 goto illegal_op;
9545 if (insn & (1 << 26)) {
9546 /* Secure monitor call (v6Z) */
9547 qemu_log_mask(LOG_UNIMP,
9548 "arm: unimplemented secure monitor call\n");
9549 goto illegal_op; /* not implemented. */
9550 } else {
9551 op = (insn >> 20) & 7;
9552 switch (op) {
9553 case 0: /* msr cpsr. */
9554 if (IS_M(env)) {
9555 tmp = load_reg(s, rn);
9556 addr = tcg_const_i32(insn & 0xff);
9557 gen_helper_v7m_msr(cpu_env, addr, tmp);
9558 tcg_temp_free_i32(addr);
9559 tcg_temp_free_i32(tmp);
9560 gen_lookup_tb(s);
9561 break;
9563 /* fall through */
9564 case 1: /* msr spsr. */
9565 if (IS_M(env))
9566 goto illegal_op;
9567 tmp = load_reg(s, rn);
9568 if (gen_set_psr(s,
9569 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
9570 op == 1, tmp))
9571 goto illegal_op;
9572 break;
9573 case 2: /* cps, nop-hint. */
9574 if (((insn >> 8) & 7) == 0) {
9575 gen_nop_hint(s, insn & 0xff);
9577 /* Implemented as NOP in user mode. */
9578 if (IS_USER(s))
9579 break;
9580 offset = 0;
9581 imm = 0;
9582 if (insn & (1 << 10)) {
9583 if (insn & (1 << 7))
9584 offset |= CPSR_A;
9585 if (insn & (1 << 6))
9586 offset |= CPSR_I;
9587 if (insn & (1 << 5))
9588 offset |= CPSR_F;
9589 if (insn & (1 << 9))
9590 imm = CPSR_A | CPSR_I | CPSR_F;
9592 if (insn & (1 << 8)) {
9593 offset |= 0x1f;
9594 imm |= (insn & 0x1f);
9596 if (offset) {
9597 gen_set_psr_im(s, offset, 0, imm);
9599 break;
9600 case 3: /* Special control operations. */
9601 ARCH(7);
9602 op = (insn >> 4) & 0xf;
9603 switch (op) {
9604 case 2: /* clrex */
9605 gen_clrex(s);
9606 break;
9607 case 4: /* dsb */
9608 case 5: /* dmb */
9609 case 6: /* isb */
9610 /* These execute as NOPs. */
9611 break;
9612 default:
9613 goto illegal_op;
9615 break;
9616 case 4: /* bxj */
9617 /* Trivial implementation equivalent to bx. */
9618 tmp = load_reg(s, rn);
9619 gen_bx(s, tmp);
9620 break;
9621 case 5: /* Exception return. */
9622 if (IS_USER(s)) {
9623 goto illegal_op;
9625 if (rn != 14 || rd != 15) {
9626 goto illegal_op;
9628 tmp = load_reg(s, rn);
9629 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
9630 gen_exception_return(s, tmp);
9631 break;
9632 case 6: /* mrs cpsr. */
9633 tmp = tcg_temp_new_i32();
9634 if (IS_M(env)) {
9635 addr = tcg_const_i32(insn & 0xff);
9636 gen_helper_v7m_mrs(tmp, cpu_env, addr);
9637 tcg_temp_free_i32(addr);
9638 } else {
9639 gen_helper_cpsr_read(tmp, cpu_env);
9641 store_reg(s, rd, tmp);
9642 break;
9643 case 7: /* mrs spsr. */
9644 /* Not accessible in user mode. */
9645 if (IS_USER(s) || IS_M(env))
9646 goto illegal_op;
9647 tmp = load_cpu_field(spsr);
9648 store_reg(s, rd, tmp);
9649 break;
9652 } else {
9653 /* Conditional branch. */
9654 op = (insn >> 22) & 0xf;
9655 /* Generate a conditional jump to next instruction. */
9656 s->condlabel = gen_new_label();
9657 arm_gen_test_cc(op ^ 1, s->condlabel);
9658 s->condjmp = 1;
9660 /* offset[11:1] = insn[10:0] */
9661 offset = (insn & 0x7ff) << 1;
9662 /* offset[17:12] = insn[21:16]. */
9663 offset |= (insn & 0x003f0000) >> 4;
9664 /* offset[31:20] = insn[26]. */
9665 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
9666 /* offset[18] = insn[13]. */
9667 offset |= (insn & (1 << 13)) << 5;
9668 /* offset[19] = insn[11]. */
9669 offset |= (insn & (1 << 11)) << 8;
9671 /* jump to the offset */
9672 gen_jmp(s, s->pc + offset);
9674 } else {
9675 /* Data processing immediate. */
9676 if (insn & (1 << 25)) {
9677 if (insn & (1 << 24)) {
9678 if (insn & (1 << 20))
9679 goto illegal_op;
9680 /* Bitfield/Saturate. */
9681 op = (insn >> 21) & 7;
9682 imm = insn & 0x1f;
9683 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9684 if (rn == 15) {
9685 tmp = tcg_temp_new_i32();
9686 tcg_gen_movi_i32(tmp, 0);
9687 } else {
9688 tmp = load_reg(s, rn);
9690 switch (op) {
9691 case 2: /* Signed bitfield extract. */
9692 imm++;
9693 if (shift + imm > 32)
9694 goto illegal_op;
9695 if (imm < 32)
9696 gen_sbfx(tmp, shift, imm);
9697 break;
9698 case 6: /* Unsigned bitfield extract. */
9699 imm++;
9700 if (shift + imm > 32)
9701 goto illegal_op;
9702 if (imm < 32)
9703 gen_ubfx(tmp, shift, (1u << imm) - 1);
9704 break;
9705 case 3: /* Bitfield insert/clear. */
9706 if (imm < shift)
9707 goto illegal_op;
9708 imm = imm + 1 - shift;
9709 if (imm != 32) {
9710 tmp2 = load_reg(s, rd);
9711 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
9712 tcg_temp_free_i32(tmp2);
9714 break;
9715 case 7:
9716 goto illegal_op;
9717 default: /* Saturate. */
9718 if (shift) {
9719 if (op & 1)
9720 tcg_gen_sari_i32(tmp, tmp, shift);
9721 else
9722 tcg_gen_shli_i32(tmp, tmp, shift);
9724 tmp2 = tcg_const_i32(imm);
9725 if (op & 4) {
9726 /* Unsigned. */
9727 if ((op & 1) && shift == 0)
9728 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9729 else
9730 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9731 } else {
9732 /* Signed. */
9733 if ((op & 1) && shift == 0)
9734 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9735 else
9736 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9738 tcg_temp_free_i32(tmp2);
9739 break;
9741 store_reg(s, rd, tmp);
9742 } else {
9743 imm = ((insn & 0x04000000) >> 15)
9744 | ((insn & 0x7000) >> 4) | (insn & 0xff);
9745 if (insn & (1 << 22)) {
9746 /* 16-bit immediate. */
9747 imm |= (insn >> 4) & 0xf000;
9748 if (insn & (1 << 23)) {
9749 /* movt */
9750 tmp = load_reg(s, rd);
9751 tcg_gen_ext16u_i32(tmp, tmp);
9752 tcg_gen_ori_i32(tmp, tmp, imm << 16);
9753 } else {
9754 /* movw */
9755 tmp = tcg_temp_new_i32();
9756 tcg_gen_movi_i32(tmp, imm);
9758 } else {
9759 /* Add/sub 12-bit immediate. */
9760 if (rn == 15) {
9761 offset = s->pc & ~(uint32_t)3;
9762 if (insn & (1 << 23))
9763 offset -= imm;
9764 else
9765 offset += imm;
9766 tmp = tcg_temp_new_i32();
9767 tcg_gen_movi_i32(tmp, offset);
9768 } else {
9769 tmp = load_reg(s, rn);
9770 if (insn & (1 << 23))
9771 tcg_gen_subi_i32(tmp, tmp, imm);
9772 else
9773 tcg_gen_addi_i32(tmp, tmp, imm);
9776 store_reg(s, rd, tmp);
9778 } else {
9779 int shifter_out = 0;
9780 /* modified 12-bit immediate. */
9781 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
9782 imm = (insn & 0xff);
9783 switch (shift) {
9784 case 0: /* XY */
9785 /* Nothing to do. */
9786 break;
9787 case 1: /* 00XY00XY */
9788 imm |= imm << 16;
9789 break;
9790 case 2: /* XY00XY00 */
9791 imm |= imm << 16;
9792 imm <<= 8;
9793 break;
9794 case 3: /* XYXYXYXY */
9795 imm |= imm << 16;
9796 imm |= imm << 8;
9797 break;
9798 default: /* Rotated constant. */
9799 shift = (shift << 1) | (imm >> 7);
9800 imm |= 0x80;
9801 imm = imm << (32 - shift);
9802 shifter_out = 1;
9803 break;
9805 tmp2 = tcg_temp_new_i32();
9806 tcg_gen_movi_i32(tmp2, imm);
9807 rn = (insn >> 16) & 0xf;
9808 if (rn == 15) {
9809 tmp = tcg_temp_new_i32();
9810 tcg_gen_movi_i32(tmp, 0);
9811 } else {
9812 tmp = load_reg(s, rn);
9814 op = (insn >> 21) & 0xf;
9815 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
9816 shifter_out, tmp, tmp2))
9817 goto illegal_op;
9818 tcg_temp_free_i32(tmp2);
9819 rd = (insn >> 8) & 0xf;
9820 if (rd != 15) {
9821 store_reg(s, rd, tmp);
9822 } else {
9823 tcg_temp_free_i32(tmp);
9827 break;
9828 case 12: /* Load/store single data item. */
9830 int postinc = 0;
9831 int writeback = 0;
9832 int user;
9833 if ((insn & 0x01100000) == 0x01000000) {
9834 if (disas_neon_ls_insn(env, s, insn))
9835 goto illegal_op;
9836 break;
9838 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
9839 if (rs == 15) {
9840 if (!(insn & (1 << 20))) {
9841 goto illegal_op;
9843 if (op != 2) {
9844 /* Byte or halfword load space with dest == r15 : memory hints.
9845 * Catch them early so we don't emit pointless addressing code.
9846 * This space is a mix of:
9847 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
9848 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
9849 * cores)
9850 * unallocated hints, which must be treated as NOPs
9851 * UNPREDICTABLE space, which we NOP or UNDEF depending on
9852 * which is easiest for the decoding logic
9853 * Some space which must UNDEF
9855 int op1 = (insn >> 23) & 3;
9856 int op2 = (insn >> 6) & 0x3f;
9857 if (op & 2) {
9858 goto illegal_op;
9860 if (rn == 15) {
9861 /* UNPREDICTABLE, unallocated hint or
9862 * PLD/PLDW/PLI (literal)
9864 return 0;
9866 if (op1 & 1) {
9867 return 0; /* PLD/PLDW/PLI or unallocated hint */
9869 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
9870 return 0; /* PLD/PLDW/PLI or unallocated hint */
9872 /* UNDEF space, or an UNPREDICTABLE */
9873 return 1;
9876 user = IS_USER(s);
9877 if (rn == 15) {
9878 addr = tcg_temp_new_i32();
9879 /* PC relative. */
9880 /* s->pc has already been incremented by 4. */
9881 imm = s->pc & 0xfffffffc;
9882 if (insn & (1 << 23))
9883 imm += insn & 0xfff;
9884 else
9885 imm -= insn & 0xfff;
9886 tcg_gen_movi_i32(addr, imm);
9887 } else {
9888 addr = load_reg(s, rn);
9889 if (insn & (1 << 23)) {
9890 /* Positive offset. */
9891 imm = insn & 0xfff;
9892 tcg_gen_addi_i32(addr, addr, imm);
9893 } else {
9894 imm = insn & 0xff;
9895 switch ((insn >> 8) & 0xf) {
9896 case 0x0: /* Shifted Register. */
9897 shift = (insn >> 4) & 0xf;
9898 if (shift > 3) {
9899 tcg_temp_free_i32(addr);
9900 goto illegal_op;
9902 tmp = load_reg(s, rm);
9903 if (shift)
9904 tcg_gen_shli_i32(tmp, tmp, shift);
9905 tcg_gen_add_i32(addr, addr, tmp);
9906 tcg_temp_free_i32(tmp);
9907 break;
9908 case 0xc: /* Negative offset. */
9909 tcg_gen_addi_i32(addr, addr, -imm);
9910 break;
9911 case 0xe: /* User privilege. */
9912 tcg_gen_addi_i32(addr, addr, imm);
9913 user = 1;
9914 break;
9915 case 0x9: /* Post-decrement. */
9916 imm = -imm;
9917 /* Fall through. */
9918 case 0xb: /* Post-increment. */
9919 postinc = 1;
9920 writeback = 1;
9921 break;
9922 case 0xd: /* Pre-decrement. */
9923 imm = -imm;
9924 /* Fall through. */
9925 case 0xf: /* Pre-increment. */
9926 tcg_gen_addi_i32(addr, addr, imm);
9927 writeback = 1;
9928 break;
9929 default:
9930 tcg_temp_free_i32(addr);
9931 goto illegal_op;
9935 if (insn & (1 << 20)) {
9936 /* Load. */
9937 tmp = tcg_temp_new_i32();
9938 switch (op) {
9939 case 0:
9940 gen_aa32_ld8u(tmp, addr, user);
9941 break;
9942 case 4:
9943 gen_aa32_ld8s(tmp, addr, user);
9944 break;
9945 case 1:
9946 gen_aa32_ld16u(tmp, addr, user);
9947 break;
9948 case 5:
9949 gen_aa32_ld16s(tmp, addr, user);
9950 break;
9951 case 2:
9952 gen_aa32_ld32u(tmp, addr, user);
9953 break;
9954 default:
9955 tcg_temp_free_i32(tmp);
9956 tcg_temp_free_i32(addr);
9957 goto illegal_op;
9959 if (rs == 15) {
9960 gen_bx(s, tmp);
9961 } else {
9962 store_reg(s, rs, tmp);
9964 } else {
9965 /* Store. */
9966 tmp = load_reg(s, rs);
9967 switch (op) {
9968 case 0:
9969 gen_aa32_st8(tmp, addr, user);
9970 break;
9971 case 1:
9972 gen_aa32_st16(tmp, addr, user);
9973 break;
9974 case 2:
9975 gen_aa32_st32(tmp, addr, user);
9976 break;
9977 default:
9978 tcg_temp_free_i32(tmp);
9979 tcg_temp_free_i32(addr);
9980 goto illegal_op;
9982 tcg_temp_free_i32(tmp);
9984 if (postinc)
9985 tcg_gen_addi_i32(addr, addr, imm);
9986 if (writeback) {
9987 store_reg(s, rn, addr);
9988 } else {
9989 tcg_temp_free_i32(addr);
9992 break;
9993 default:
9994 goto illegal_op;
9996 return 0;
9997 illegal_op:
9998 return 1;
10001 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
10003 uint32_t val, insn, op, rm, rn, rd, shift, cond;
10004 int32_t offset;
10005 int i;
10006 TCGv_i32 tmp;
10007 TCGv_i32 tmp2;
10008 TCGv_i32 addr;
10010 if (s->condexec_mask) {
10011 cond = s->condexec_cond;
10012 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
10013 s->condlabel = gen_new_label();
10014 arm_gen_test_cc(cond ^ 1, s->condlabel);
10015 s->condjmp = 1;
10019 insn = arm_lduw_code(env, s->pc, s->bswap_code);
10020 s->pc += 2;
10022 switch (insn >> 12) {
10023 case 0: case 1:
10025 rd = insn & 7;
10026 op = (insn >> 11) & 3;
10027 if (op == 3) {
10028 /* add/subtract */
10029 rn = (insn >> 3) & 7;
10030 tmp = load_reg(s, rn);
10031 if (insn & (1 << 10)) {
10032 /* immediate */
10033 tmp2 = tcg_temp_new_i32();
10034 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
10035 } else {
10036 /* reg */
10037 rm = (insn >> 6) & 7;
10038 tmp2 = load_reg(s, rm);
10040 if (insn & (1 << 9)) {
10041 if (s->condexec_mask)
10042 tcg_gen_sub_i32(tmp, tmp, tmp2);
10043 else
10044 gen_sub_CC(tmp, tmp, tmp2);
10045 } else {
10046 if (s->condexec_mask)
10047 tcg_gen_add_i32(tmp, tmp, tmp2);
10048 else
10049 gen_add_CC(tmp, tmp, tmp2);
10051 tcg_temp_free_i32(tmp2);
10052 store_reg(s, rd, tmp);
10053 } else {
10054 /* shift immediate */
10055 rm = (insn >> 3) & 7;
10056 shift = (insn >> 6) & 0x1f;
10057 tmp = load_reg(s, rm);
10058 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
10059 if (!s->condexec_mask)
10060 gen_logic_CC(tmp);
10061 store_reg(s, rd, tmp);
10063 break;
10064 case 2: case 3:
10065 /* arithmetic large immediate */
10066 op = (insn >> 11) & 3;
10067 rd = (insn >> 8) & 0x7;
10068 if (op == 0) { /* mov */
10069 tmp = tcg_temp_new_i32();
10070 tcg_gen_movi_i32(tmp, insn & 0xff);
10071 if (!s->condexec_mask)
10072 gen_logic_CC(tmp);
10073 store_reg(s, rd, tmp);
10074 } else {
10075 tmp = load_reg(s, rd);
10076 tmp2 = tcg_temp_new_i32();
10077 tcg_gen_movi_i32(tmp2, insn & 0xff);
10078 switch (op) {
10079 case 1: /* cmp */
10080 gen_sub_CC(tmp, tmp, tmp2);
10081 tcg_temp_free_i32(tmp);
10082 tcg_temp_free_i32(tmp2);
10083 break;
10084 case 2: /* add */
10085 if (s->condexec_mask)
10086 tcg_gen_add_i32(tmp, tmp, tmp2);
10087 else
10088 gen_add_CC(tmp, tmp, tmp2);
10089 tcg_temp_free_i32(tmp2);
10090 store_reg(s, rd, tmp);
10091 break;
10092 case 3: /* sub */
10093 if (s->condexec_mask)
10094 tcg_gen_sub_i32(tmp, tmp, tmp2);
10095 else
10096 gen_sub_CC(tmp, tmp, tmp2);
10097 tcg_temp_free_i32(tmp2);
10098 store_reg(s, rd, tmp);
10099 break;
10102 break;
10103 case 4:
10104 if (insn & (1 << 11)) {
10105 rd = (insn >> 8) & 7;
10106 /* load pc-relative. Bit 1 of PC is ignored. */
10107 val = s->pc + 2 + ((insn & 0xff) * 4);
10108 val &= ~(uint32_t)2;
10109 addr = tcg_temp_new_i32();
10110 tcg_gen_movi_i32(addr, val);
10111 tmp = tcg_temp_new_i32();
10112 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10113 tcg_temp_free_i32(addr);
10114 store_reg(s, rd, tmp);
10115 break;
10117 if (insn & (1 << 10)) {
10118 /* data processing extended or blx */
10119 rd = (insn & 7) | ((insn >> 4) & 8);
10120 rm = (insn >> 3) & 0xf;
10121 op = (insn >> 8) & 3;
10122 switch (op) {
10123 case 0: /* add */
10124 tmp = load_reg(s, rd);
10125 tmp2 = load_reg(s, rm);
10126 tcg_gen_add_i32(tmp, tmp, tmp2);
10127 tcg_temp_free_i32(tmp2);
10128 store_reg(s, rd, tmp);
10129 break;
10130 case 1: /* cmp */
10131 tmp = load_reg(s, rd);
10132 tmp2 = load_reg(s, rm);
10133 gen_sub_CC(tmp, tmp, tmp2);
10134 tcg_temp_free_i32(tmp2);
10135 tcg_temp_free_i32(tmp);
10136 break;
10137 case 2: /* mov/cpy */
10138 tmp = load_reg(s, rm);
10139 store_reg(s, rd, tmp);
10140 break;
10141 case 3:/* branch [and link] exchange thumb register */
10142 tmp = load_reg(s, rm);
10143 if (insn & (1 << 7)) {
10144 ARCH(5);
10145 val = (uint32_t)s->pc | 1;
10146 tmp2 = tcg_temp_new_i32();
10147 tcg_gen_movi_i32(tmp2, val);
10148 store_reg(s, 14, tmp2);
10150 /* already thumb, no need to check */
10151 gen_bx(s, tmp);
10152 break;
10154 break;
10157 /* data processing register */
10158 rd = insn & 7;
10159 rm = (insn >> 3) & 7;
10160 op = (insn >> 6) & 0xf;
10161 if (op == 2 || op == 3 || op == 4 || op == 7) {
10162 /* the shift/rotate ops want the operands backwards */
10163 val = rm;
10164 rm = rd;
10165 rd = val;
10166 val = 1;
10167 } else {
10168 val = 0;
10171 if (op == 9) { /* neg */
10172 tmp = tcg_temp_new_i32();
10173 tcg_gen_movi_i32(tmp, 0);
10174 } else if (op != 0xf) { /* mvn doesn't read its first operand */
10175 tmp = load_reg(s, rd);
10176 } else {
10177 TCGV_UNUSED_I32(tmp);
10180 tmp2 = load_reg(s, rm);
10181 switch (op) {
10182 case 0x0: /* and */
10183 tcg_gen_and_i32(tmp, tmp, tmp2);
10184 if (!s->condexec_mask)
10185 gen_logic_CC(tmp);
10186 break;
10187 case 0x1: /* eor */
10188 tcg_gen_xor_i32(tmp, tmp, tmp2);
10189 if (!s->condexec_mask)
10190 gen_logic_CC(tmp);
10191 break;
10192 case 0x2: /* lsl */
10193 if (s->condexec_mask) {
10194 gen_shl(tmp2, tmp2, tmp);
10195 } else {
10196 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
10197 gen_logic_CC(tmp2);
10199 break;
10200 case 0x3: /* lsr */
10201 if (s->condexec_mask) {
10202 gen_shr(tmp2, tmp2, tmp);
10203 } else {
10204 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
10205 gen_logic_CC(tmp2);
10207 break;
10208 case 0x4: /* asr */
10209 if (s->condexec_mask) {
10210 gen_sar(tmp2, tmp2, tmp);
10211 } else {
10212 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
10213 gen_logic_CC(tmp2);
10215 break;
10216 case 0x5: /* adc */
10217 if (s->condexec_mask) {
10218 gen_adc(tmp, tmp2);
10219 } else {
10220 gen_adc_CC(tmp, tmp, tmp2);
10222 break;
10223 case 0x6: /* sbc */
10224 if (s->condexec_mask) {
10225 gen_sub_carry(tmp, tmp, tmp2);
10226 } else {
10227 gen_sbc_CC(tmp, tmp, tmp2);
10229 break;
10230 case 0x7: /* ror */
10231 if (s->condexec_mask) {
10232 tcg_gen_andi_i32(tmp, tmp, 0x1f);
10233 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
10234 } else {
10235 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
10236 gen_logic_CC(tmp2);
10238 break;
10239 case 0x8: /* tst */
10240 tcg_gen_and_i32(tmp, tmp, tmp2);
10241 gen_logic_CC(tmp);
10242 rd = 16;
10243 break;
10244 case 0x9: /* neg */
10245 if (s->condexec_mask)
10246 tcg_gen_neg_i32(tmp, tmp2);
10247 else
10248 gen_sub_CC(tmp, tmp, tmp2);
10249 break;
10250 case 0xa: /* cmp */
10251 gen_sub_CC(tmp, tmp, tmp2);
10252 rd = 16;
10253 break;
10254 case 0xb: /* cmn */
10255 gen_add_CC(tmp, tmp, tmp2);
10256 rd = 16;
10257 break;
10258 case 0xc: /* orr */
10259 tcg_gen_or_i32(tmp, tmp, tmp2);
10260 if (!s->condexec_mask)
10261 gen_logic_CC(tmp);
10262 break;
10263 case 0xd: /* mul */
10264 tcg_gen_mul_i32(tmp, tmp, tmp2);
10265 if (!s->condexec_mask)
10266 gen_logic_CC(tmp);
10267 break;
10268 case 0xe: /* bic */
10269 tcg_gen_andc_i32(tmp, tmp, tmp2);
10270 if (!s->condexec_mask)
10271 gen_logic_CC(tmp);
10272 break;
10273 case 0xf: /* mvn */
10274 tcg_gen_not_i32(tmp2, tmp2);
10275 if (!s->condexec_mask)
10276 gen_logic_CC(tmp2);
10277 val = 1;
10278 rm = rd;
10279 break;
10281 if (rd != 16) {
10282 if (val) {
10283 store_reg(s, rm, tmp2);
10284 if (op != 0xf)
10285 tcg_temp_free_i32(tmp);
10286 } else {
10287 store_reg(s, rd, tmp);
10288 tcg_temp_free_i32(tmp2);
10290 } else {
10291 tcg_temp_free_i32(tmp);
10292 tcg_temp_free_i32(tmp2);
10294 break;
10296 case 5:
10297 /* load/store register offset. */
10298 rd = insn & 7;
10299 rn = (insn >> 3) & 7;
10300 rm = (insn >> 6) & 7;
10301 op = (insn >> 9) & 7;
10302 addr = load_reg(s, rn);
10303 tmp = load_reg(s, rm);
10304 tcg_gen_add_i32(addr, addr, tmp);
10305 tcg_temp_free_i32(tmp);
10307 if (op < 3) { /* store */
10308 tmp = load_reg(s, rd);
10309 } else {
10310 tmp = tcg_temp_new_i32();
10313 switch (op) {
10314 case 0: /* str */
10315 gen_aa32_st32(tmp, addr, IS_USER(s));
10316 break;
10317 case 1: /* strh */
10318 gen_aa32_st16(tmp, addr, IS_USER(s));
10319 break;
10320 case 2: /* strb */
10321 gen_aa32_st8(tmp, addr, IS_USER(s));
10322 break;
10323 case 3: /* ldrsb */
10324 gen_aa32_ld8s(tmp, addr, IS_USER(s));
10325 break;
10326 case 4: /* ldr */
10327 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10328 break;
10329 case 5: /* ldrh */
10330 gen_aa32_ld16u(tmp, addr, IS_USER(s));
10331 break;
10332 case 6: /* ldrb */
10333 gen_aa32_ld8u(tmp, addr, IS_USER(s));
10334 break;
10335 case 7: /* ldrsh */
10336 gen_aa32_ld16s(tmp, addr, IS_USER(s));
10337 break;
10339 if (op >= 3) { /* load */
10340 store_reg(s, rd, tmp);
10341 } else {
10342 tcg_temp_free_i32(tmp);
10344 tcg_temp_free_i32(addr);
10345 break;
10347 case 6:
10348 /* load/store word immediate offset */
10349 rd = insn & 7;
10350 rn = (insn >> 3) & 7;
10351 addr = load_reg(s, rn);
10352 val = (insn >> 4) & 0x7c;
10353 tcg_gen_addi_i32(addr, addr, val);
10355 if (insn & (1 << 11)) {
10356 /* load */
10357 tmp = tcg_temp_new_i32();
10358 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10359 store_reg(s, rd, tmp);
10360 } else {
10361 /* store */
10362 tmp = load_reg(s, rd);
10363 gen_aa32_st32(tmp, addr, IS_USER(s));
10364 tcg_temp_free_i32(tmp);
10366 tcg_temp_free_i32(addr);
10367 break;
10369 case 7:
10370 /* load/store byte immediate offset */
10371 rd = insn & 7;
10372 rn = (insn >> 3) & 7;
10373 addr = load_reg(s, rn);
10374 val = (insn >> 6) & 0x1f;
10375 tcg_gen_addi_i32(addr, addr, val);
10377 if (insn & (1 << 11)) {
10378 /* load */
10379 tmp = tcg_temp_new_i32();
10380 gen_aa32_ld8u(tmp, addr, IS_USER(s));
10381 store_reg(s, rd, tmp);
10382 } else {
10383 /* store */
10384 tmp = load_reg(s, rd);
10385 gen_aa32_st8(tmp, addr, IS_USER(s));
10386 tcg_temp_free_i32(tmp);
10388 tcg_temp_free_i32(addr);
10389 break;
10391 case 8:
10392 /* load/store halfword immediate offset */
10393 rd = insn & 7;
10394 rn = (insn >> 3) & 7;
10395 addr = load_reg(s, rn);
10396 val = (insn >> 5) & 0x3e;
10397 tcg_gen_addi_i32(addr, addr, val);
10399 if (insn & (1 << 11)) {
10400 /* load */
10401 tmp = tcg_temp_new_i32();
10402 gen_aa32_ld16u(tmp, addr, IS_USER(s));
10403 store_reg(s, rd, tmp);
10404 } else {
10405 /* store */
10406 tmp = load_reg(s, rd);
10407 gen_aa32_st16(tmp, addr, IS_USER(s));
10408 tcg_temp_free_i32(tmp);
10410 tcg_temp_free_i32(addr);
10411 break;
10413 case 9:
10414 /* load/store from stack */
10415 rd = (insn >> 8) & 7;
10416 addr = load_reg(s, 13);
10417 val = (insn & 0xff) * 4;
10418 tcg_gen_addi_i32(addr, addr, val);
10420 if (insn & (1 << 11)) {
10421 /* load */
10422 tmp = tcg_temp_new_i32();
10423 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10424 store_reg(s, rd, tmp);
10425 } else {
10426 /* store */
10427 tmp = load_reg(s, rd);
10428 gen_aa32_st32(tmp, addr, IS_USER(s));
10429 tcg_temp_free_i32(tmp);
10431 tcg_temp_free_i32(addr);
10432 break;
10434 case 10:
10435 /* add to high reg */
10436 rd = (insn >> 8) & 7;
10437 if (insn & (1 << 11)) {
10438 /* SP */
10439 tmp = load_reg(s, 13);
10440 } else {
10441 /* PC. bit 1 is ignored. */
10442 tmp = tcg_temp_new_i32();
10443 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
10445 val = (insn & 0xff) * 4;
10446 tcg_gen_addi_i32(tmp, tmp, val);
10447 store_reg(s, rd, tmp);
10448 break;
10450 case 11:
10451 /* misc */
10452 op = (insn >> 8) & 0xf;
10453 switch (op) {
10454 case 0:
10455 /* adjust stack pointer */
10456 tmp = load_reg(s, 13);
10457 val = (insn & 0x7f) * 4;
10458 if (insn & (1 << 7))
10459 val = -(int32_t)val;
10460 tcg_gen_addi_i32(tmp, tmp, val);
10461 store_reg(s, 13, tmp);
10462 break;
10464 case 2: /* sign/zero extend. */
10465 ARCH(6);
10466 rd = insn & 7;
10467 rm = (insn >> 3) & 7;
10468 tmp = load_reg(s, rm);
10469 switch ((insn >> 6) & 3) {
10470 case 0: gen_sxth(tmp); break;
10471 case 1: gen_sxtb(tmp); break;
10472 case 2: gen_uxth(tmp); break;
10473 case 3: gen_uxtb(tmp); break;
10475 store_reg(s, rd, tmp);
10476 break;
10477 case 4: case 5: case 0xc: case 0xd:
10478 /* push/pop */
10479 addr = load_reg(s, 13);
10480 if (insn & (1 << 8))
10481 offset = 4;
10482 else
10483 offset = 0;
10484 for (i = 0; i < 8; i++) {
10485 if (insn & (1 << i))
10486 offset += 4;
10488 if ((insn & (1 << 11)) == 0) {
10489 tcg_gen_addi_i32(addr, addr, -offset);
10491 for (i = 0; i < 8; i++) {
10492 if (insn & (1 << i)) {
10493 if (insn & (1 << 11)) {
10494 /* pop */
10495 tmp = tcg_temp_new_i32();
10496 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10497 store_reg(s, i, tmp);
10498 } else {
10499 /* push */
10500 tmp = load_reg(s, i);
10501 gen_aa32_st32(tmp, addr, IS_USER(s));
10502 tcg_temp_free_i32(tmp);
10504 /* advance to the next address. */
10505 tcg_gen_addi_i32(addr, addr, 4);
10508 TCGV_UNUSED_I32(tmp);
10509 if (insn & (1 << 8)) {
10510 if (insn & (1 << 11)) {
10511 /* pop pc */
10512 tmp = tcg_temp_new_i32();
10513 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10514 /* don't set the pc until the rest of the instruction
10515 has completed */
10516 } else {
10517 /* push lr */
10518 tmp = load_reg(s, 14);
10519 gen_aa32_st32(tmp, addr, IS_USER(s));
10520 tcg_temp_free_i32(tmp);
10522 tcg_gen_addi_i32(addr, addr, 4);
10524 if ((insn & (1 << 11)) == 0) {
10525 tcg_gen_addi_i32(addr, addr, -offset);
10527 /* write back the new stack pointer */
10528 store_reg(s, 13, addr);
10529 /* set the new PC value */
10530 if ((insn & 0x0900) == 0x0900) {
10531 store_reg_from_load(env, s, 15, tmp);
10533 break;
10535 case 1: case 3: case 9: case 11: /* czb */
10536 rm = insn & 7;
10537 tmp = load_reg(s, rm);
10538 s->condlabel = gen_new_label();
10539 s->condjmp = 1;
10540 if (insn & (1 << 11))
10541 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
10542 else
10543 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
10544 tcg_temp_free_i32(tmp);
10545 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
10546 val = (uint32_t)s->pc + 2;
10547 val += offset;
10548 gen_jmp(s, val);
10549 break;
10551 case 15: /* IT, nop-hint. */
10552 if ((insn & 0xf) == 0) {
10553 gen_nop_hint(s, (insn >> 4) & 0xf);
10554 break;
10556 /* If Then. */
10557 s->condexec_cond = (insn >> 4) & 0xe;
10558 s->condexec_mask = insn & 0x1f;
10559 /* No actual code generated for this insn, just setup state. */
10560 break;
10562 case 0xe: /* bkpt */
10564 int imm8 = extract32(insn, 0, 8);
10565 ARCH(5);
10566 gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true));
10567 break;
10570 case 0xa: /* rev */
10571 ARCH(6);
10572 rn = (insn >> 3) & 0x7;
10573 rd = insn & 0x7;
10574 tmp = load_reg(s, rn);
10575 switch ((insn >> 6) & 3) {
10576 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
10577 case 1: gen_rev16(tmp); break;
10578 case 3: gen_revsh(tmp); break;
10579 default: goto illegal_op;
10581 store_reg(s, rd, tmp);
10582 break;
10584 case 6:
10585 switch ((insn >> 5) & 7) {
10586 case 2:
10587 /* setend */
10588 ARCH(6);
10589 if (((insn >> 3) & 1) != s->bswap_code) {
10590 /* Dynamic endianness switching not implemented. */
10591 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
10592 goto illegal_op;
10594 break;
10595 case 3:
10596 /* cps */
10597 ARCH(6);
10598 if (IS_USER(s)) {
10599 break;
10601 if (IS_M(env)) {
10602 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
10603 /* FAULTMASK */
10604 if (insn & 1) {
10605 addr = tcg_const_i32(19);
10606 gen_helper_v7m_msr(cpu_env, addr, tmp);
10607 tcg_temp_free_i32(addr);
10609 /* PRIMASK */
10610 if (insn & 2) {
10611 addr = tcg_const_i32(16);
10612 gen_helper_v7m_msr(cpu_env, addr, tmp);
10613 tcg_temp_free_i32(addr);
10615 tcg_temp_free_i32(tmp);
10616 gen_lookup_tb(s);
10617 } else {
10618 if (insn & (1 << 4)) {
10619 shift = CPSR_A | CPSR_I | CPSR_F;
10620 } else {
10621 shift = 0;
10623 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
10625 break;
10626 default:
10627 goto undef;
10629 break;
10631 default:
10632 goto undef;
10634 break;
10636 case 12:
10638 /* load/store multiple */
10639 TCGv_i32 loaded_var;
10640 TCGV_UNUSED_I32(loaded_var);
10641 rn = (insn >> 8) & 0x7;
10642 addr = load_reg(s, rn);
10643 for (i = 0; i < 8; i++) {
10644 if (insn & (1 << i)) {
10645 if (insn & (1 << 11)) {
10646 /* load */
10647 tmp = tcg_temp_new_i32();
10648 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10649 if (i == rn) {
10650 loaded_var = tmp;
10651 } else {
10652 store_reg(s, i, tmp);
10654 } else {
10655 /* store */
10656 tmp = load_reg(s, i);
10657 gen_aa32_st32(tmp, addr, IS_USER(s));
10658 tcg_temp_free_i32(tmp);
10660 /* advance to the next address */
10661 tcg_gen_addi_i32(addr, addr, 4);
10664 if ((insn & (1 << rn)) == 0) {
10665 /* base reg not in list: base register writeback */
10666 store_reg(s, rn, addr);
10667 } else {
10668 /* base reg in list: if load, complete it now */
10669 if (insn & (1 << 11)) {
10670 store_reg(s, rn, loaded_var);
10672 tcg_temp_free_i32(addr);
10674 break;
10676 case 13:
10677 /* conditional branch or swi */
10678 cond = (insn >> 8) & 0xf;
10679 if (cond == 0xe)
10680 goto undef;
10682 if (cond == 0xf) {
10683 /* swi */
10684 gen_set_pc_im(s, s->pc);
10685 s->svc_imm = extract32(insn, 0, 8);
10686 s->is_jmp = DISAS_SWI;
10687 break;
10689 /* generate a conditional jump to next instruction */
10690 s->condlabel = gen_new_label();
10691 arm_gen_test_cc(cond ^ 1, s->condlabel);
10692 s->condjmp = 1;
10694 /* jump to the offset */
10695 val = (uint32_t)s->pc + 2;
10696 offset = ((int32_t)insn << 24) >> 24;
10697 val += offset << 1;
10698 gen_jmp(s, val);
10699 break;
10701 case 14:
10702 if (insn & (1 << 11)) {
10703 if (disas_thumb2_insn(env, s, insn))
10704 goto undef32;
10705 break;
10707 /* unconditional branch */
10708 val = (uint32_t)s->pc;
10709 offset = ((int32_t)insn << 21) >> 21;
10710 val += (offset << 1) + 2;
10711 gen_jmp(s, val);
10712 break;
10714 case 15:
10715 if (disas_thumb2_insn(env, s, insn))
10716 goto undef32;
10717 break;
10719 return;
10720 undef32:
10721 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
10722 return;
10723 illegal_op:
10724 undef:
10725 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized());
10728 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
10729 basic block 'tb'. If search_pc is TRUE, also generate PC
10730 information for each intermediate instruction. */
10731 static inline void gen_intermediate_code_internal(ARMCPU *cpu,
10732 TranslationBlock *tb,
10733 bool search_pc)
10735 CPUState *cs = CPU(cpu);
10736 CPUARMState *env = &cpu->env;
10737 DisasContext dc1, *dc = &dc1;
10738 CPUBreakpoint *bp;
10739 uint16_t *gen_opc_end;
10740 int j, lj;
10741 target_ulong pc_start;
10742 target_ulong next_page_start;
10743 int num_insns;
10744 int max_insns;
10746 /* generate intermediate code */
10748 /* The A64 decoder has its own top level loop, because it doesn't need
10749 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
10751 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
10752 gen_intermediate_code_internal_a64(cpu, tb, search_pc);
10753 return;
10756 pc_start = tb->pc;
10758 dc->tb = tb;
10760 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
10762 dc->is_jmp = DISAS_NEXT;
10763 dc->pc = pc_start;
10764 dc->singlestep_enabled = cs->singlestep_enabled;
10765 dc->condjmp = 0;
10767 dc->aarch64 = 0;
10768 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
10769 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
10770 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
10771 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
10772 #if !defined(CONFIG_USER_ONLY)
10773 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
10774 #endif
10775 dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
10776 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
10777 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
10778 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
10779 dc->cp_regs = cpu->cp_regs;
10780 dc->current_pl = arm_current_pl(env);
10781 dc->features = env->features;
10783 cpu_F0s = tcg_temp_new_i32();
10784 cpu_F1s = tcg_temp_new_i32();
10785 cpu_F0d = tcg_temp_new_i64();
10786 cpu_F1d = tcg_temp_new_i64();
10787 cpu_V0 = cpu_F0d;
10788 cpu_V1 = cpu_F1d;
10789 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
10790 cpu_M0 = tcg_temp_new_i64();
10791 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
10792 lj = -1;
10793 num_insns = 0;
10794 max_insns = tb->cflags & CF_COUNT_MASK;
10795 if (max_insns == 0)
10796 max_insns = CF_COUNT_MASK;
10798 gen_tb_start();
10800 tcg_clear_temp_count();
10802 /* A note on handling of the condexec (IT) bits:
10804 * We want to avoid the overhead of having to write the updated condexec
10805 * bits back to the CPUARMState for every instruction in an IT block. So:
10806 * (1) if the condexec bits are not already zero then we write
10807 * zero back into the CPUARMState now. This avoids complications trying
10808 * to do it at the end of the block. (For example if we don't do this
10809 * it's hard to identify whether we can safely skip writing condexec
10810 * at the end of the TB, which we definitely want to do for the case
10811 * where a TB doesn't do anything with the IT state at all.)
10812 * (2) if we are going to leave the TB then we call gen_set_condexec()
10813 * which will write the correct value into CPUARMState if zero is wrong.
10814 * This is done both for leaving the TB at the end, and for leaving
10815 * it because of an exception we know will happen, which is done in
10816 * gen_exception_insn(). The latter is necessary because we need to
10817 * leave the TB with the PC/IT state just prior to execution of the
10818 * instruction which caused the exception.
10819 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
10820 * then the CPUARMState will be wrong and we need to reset it.
10821 * This is handled in the same way as restoration of the
10822 * PC in these situations: we will be called again with search_pc=1
10823 * and generate a mapping of the condexec bits for each PC in
10824 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
10825 * this to restore the condexec bits.
10827 * Note that there are no instructions which can read the condexec
10828 * bits, and none which can write non-static values to them, so
10829 * we don't need to care about whether CPUARMState is correct in the
10830 * middle of a TB.
10833 /* Reset the conditional execution bits immediately. This avoids
10834 complications trying to do it at the end of the block. */
10835 if (dc->condexec_mask || dc->condexec_cond)
10837 TCGv_i32 tmp = tcg_temp_new_i32();
10838 tcg_gen_movi_i32(tmp, 0);
10839 store_cpu_field(tmp, condexec_bits);
10841 do {
10842 #ifdef CONFIG_USER_ONLY
10843 /* Intercept jump to the magic kernel page. */
10844 if (dc->pc >= 0xffff0000) {
10845 /* We always get here via a jump, so know we are not in a
10846 conditional execution block. */
10847 gen_exception_internal(EXCP_KERNEL_TRAP);
10848 dc->is_jmp = DISAS_UPDATE;
10849 break;
10851 #else
10852 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
10853 /* We always get here via a jump, so know we are not in a
10854 conditional execution block. */
10855 gen_exception_internal(EXCP_EXCEPTION_EXIT);
10856 dc->is_jmp = DISAS_UPDATE;
10857 break;
10859 #endif
10861 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
10862 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
10863 if (bp->pc == dc->pc) {
10864 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
10865 /* Advance PC so that clearing the breakpoint will
10866 invalidate this TB. */
10867 dc->pc += 2;
10868 goto done_generating;
10872 if (search_pc) {
10873 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10874 if (lj < j) {
10875 lj++;
10876 while (lj < j)
10877 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10879 tcg_ctx.gen_opc_pc[lj] = dc->pc;
10880 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
10881 tcg_ctx.gen_opc_instr_start[lj] = 1;
10882 tcg_ctx.gen_opc_icount[lj] = num_insns;
10885 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
10886 gen_io_start();
10888 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
10889 tcg_gen_debug_insn_start(dc->pc);
10892 if (dc->thumb) {
10893 disas_thumb_insn(env, dc);
10894 if (dc->condexec_mask) {
10895 dc->condexec_cond = (dc->condexec_cond & 0xe)
10896 | ((dc->condexec_mask >> 4) & 1);
10897 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
10898 if (dc->condexec_mask == 0) {
10899 dc->condexec_cond = 0;
10902 } else {
10903 disas_arm_insn(env, dc);
10906 if (dc->condjmp && !dc->is_jmp) {
10907 gen_set_label(dc->condlabel);
10908 dc->condjmp = 0;
10911 if (tcg_check_temp_count()) {
10912 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
10913 dc->pc);
10916 /* Translation stops when a conditional branch is encountered.
10917 * Otherwise the subsequent code could get translated several times.
10918 * Also stop translation when a page boundary is reached. This
10919 * ensures prefetch aborts occur at the right place. */
10920 num_insns ++;
10921 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
10922 !cs->singlestep_enabled &&
10923 !singlestep &&
10924 dc->pc < next_page_start &&
10925 num_insns < max_insns);
10927 if (tb->cflags & CF_LAST_IO) {
10928 if (dc->condjmp) {
10929 /* FIXME: This can theoretically happen with self-modifying
10930 code. */
10931 cpu_abort(cs, "IO on conditional branch instruction");
10933 gen_io_end();
10936 /* At this stage dc->condjmp will only be set when the skipped
10937 instruction was a conditional branch or trap, and the PC has
10938 already been written. */
10939 if (unlikely(cs->singlestep_enabled)) {
10940 /* Make sure the pc is updated, and raise a debug exception. */
10941 if (dc->condjmp) {
10942 gen_set_condexec(dc);
10943 if (dc->is_jmp == DISAS_SWI) {
10944 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
10945 } else {
10946 gen_exception_internal(EXCP_DEBUG);
10948 gen_set_label(dc->condlabel);
10950 if (dc->condjmp || !dc->is_jmp) {
10951 gen_set_pc_im(dc, dc->pc);
10952 dc->condjmp = 0;
10954 gen_set_condexec(dc);
10955 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
10956 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
10957 } else {
10958 /* FIXME: Single stepping a WFI insn will not halt
10959 the CPU. */
10960 gen_exception_internal(EXCP_DEBUG);
10962 } else {
10963 /* While branches must always occur at the end of an IT block,
10964 there are a few other things that can cause us to terminate
10965 the TB in the middle of an IT block:
10966 - Exception generating instructions (bkpt, swi, undefined).
10967 - Page boundaries.
10968 - Hardware watchpoints.
10969 Hardware breakpoints have already been handled and skip this code.
10971 gen_set_condexec(dc);
10972 switch(dc->is_jmp) {
10973 case DISAS_NEXT:
10974 gen_goto_tb(dc, 1, dc->pc);
10975 break;
10976 default:
10977 case DISAS_JUMP:
10978 case DISAS_UPDATE:
10979 /* indicate that the hash table must be used to find the next TB */
10980 tcg_gen_exit_tb(0);
10981 break;
10982 case DISAS_TB_JUMP:
10983 /* nothing more to generate */
10984 break;
10985 case DISAS_WFI:
10986 gen_helper_wfi(cpu_env);
10987 break;
10988 case DISAS_WFE:
10989 gen_helper_wfe(cpu_env);
10990 break;
10991 case DISAS_SWI:
10992 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
10993 break;
10995 if (dc->condjmp) {
10996 gen_set_label(dc->condlabel);
10997 gen_set_condexec(dc);
10998 gen_goto_tb(dc, 1, dc->pc);
10999 dc->condjmp = 0;
11003 done_generating:
11004 gen_tb_end(tb, num_insns);
11005 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
11007 #ifdef DEBUG_DISAS
11008 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
11009 qemu_log("----------------\n");
11010 qemu_log("IN: %s\n", lookup_symbol(pc_start));
11011 log_target_disas(env, pc_start, dc->pc - pc_start,
11012 dc->thumb | (dc->bswap_code << 1));
11013 qemu_log("\n");
11015 #endif
11016 if (search_pc) {
11017 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
11018 lj++;
11019 while (lj <= j)
11020 tcg_ctx.gen_opc_instr_start[lj++] = 0;
11021 } else {
11022 tb->size = dc->pc - pc_start;
11023 tb->icount = num_insns;
11027 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
11029 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
11032 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
11034 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
11037 static const char *cpu_mode_names[16] = {
11038 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
11039 "???", "???", "???", "und", "???", "???", "???", "sys"
11042 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11043 int flags)
11045 ARMCPU *cpu = ARM_CPU(cs);
11046 CPUARMState *env = &cpu->env;
11047 int i;
11048 uint32_t psr;
11050 for(i=0;i<16;i++) {
11051 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
11052 if ((i % 4) == 3)
11053 cpu_fprintf(f, "\n");
11054 else
11055 cpu_fprintf(f, " ");
11057 psr = cpsr_read(env);
11058 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
11059 psr,
11060 psr & (1 << 31) ? 'N' : '-',
11061 psr & (1 << 30) ? 'Z' : '-',
11062 psr & (1 << 29) ? 'C' : '-',
11063 psr & (1 << 28) ? 'V' : '-',
11064 psr & CPSR_T ? 'T' : 'A',
11065 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
11067 if (flags & CPU_DUMP_FPU) {
11068 int numvfpregs = 0;
11069 if (arm_feature(env, ARM_FEATURE_VFP)) {
11070 numvfpregs += 16;
11072 if (arm_feature(env, ARM_FEATURE_VFP3)) {
11073 numvfpregs += 16;
11075 for (i = 0; i < numvfpregs; i++) {
11076 uint64_t v = float64_val(env->vfp.regs[i]);
11077 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
11078 i * 2, (uint32_t)v,
11079 i * 2 + 1, (uint32_t)(v >> 32),
11080 i, v);
11082 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
11086 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
11088 if (is_a64(env)) {
11089 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
11090 env->condexec_bits = 0;
11091 } else {
11092 env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
11093 env->condexec_bits = gen_opc_condexec_bits[pc_pos];