qom: Split out object and class caches
[qemu.git] / target-arm / translate.c
blob1403ecf216259dabe7f977b4af4642de693f2f94
1 /*
2 * ARM translation
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
27 #include "cpu.h"
28 #include "disas/disas.h"
29 #include "tcg-op.h"
30 #include "qemu/log.h"
31 #include "qemu/bitops.h"
33 #include "helper.h"
34 #define GEN_HELPER 1
35 #include "helper.h"
37 #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
38 #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
39 /* currently all emulated v5 cores are also v5TE, so don't bother */
40 #define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5)
41 #define ENABLE_ARCH_5J 0
42 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
43 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
44 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
45 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
46 #define ENABLE_ARCH_8 arm_feature(env, ARM_FEATURE_V8)
48 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
50 #include "translate.h"
51 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
53 #if defined(CONFIG_USER_ONLY)
54 #define IS_USER(s) 1
55 #else
56 #define IS_USER(s) (s->user)
57 #endif
59 TCGv_ptr cpu_env;
60 /* We reuse the same 64-bit temporaries for efficiency. */
61 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
62 static TCGv_i32 cpu_R[16];
63 static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
64 static TCGv_i32 cpu_exclusive_addr;
65 static TCGv_i32 cpu_exclusive_val;
66 static TCGv_i32 cpu_exclusive_high;
67 #ifdef CONFIG_USER_ONLY
68 static TCGv_i32 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_i32(TCG_AREG0,
100 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
101 cpu_exclusive_val = tcg_global_mem_new_i32(TCG_AREG0,
102 offsetof(CPUARMState, exclusive_val), "exclusive_val");
103 cpu_exclusive_high = tcg_global_mem_new_i32(TCG_AREG0,
104 offsetof(CPUARMState, exclusive_high), "exclusive_high");
105 #ifdef CONFIG_USER_ONLY
106 cpu_exclusive_test = tcg_global_mem_new_i32(TCG_AREG0,
107 offsetof(CPUARMState, exclusive_test), "exclusive_test");
108 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
109 offsetof(CPUARMState, exclusive_info), "exclusive_info");
110 #endif
112 a64_translate_init();
115 static inline TCGv_i32 load_cpu_offset(int offset)
117 TCGv_i32 tmp = tcg_temp_new_i32();
118 tcg_gen_ld_i32(tmp, cpu_env, offset);
119 return tmp;
122 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
124 static inline void store_cpu_offset(TCGv_i32 var, int offset)
126 tcg_gen_st_i32(var, cpu_env, offset);
127 tcg_temp_free_i32(var);
130 #define store_cpu_field(var, name) \
131 store_cpu_offset(var, offsetof(CPUARMState, name))
133 /* Set a variable to the value of a CPU register. */
134 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
136 if (reg == 15) {
137 uint32_t addr;
138 /* normally, since we updated PC, we need only to add one insn */
139 if (s->thumb)
140 addr = (long)s->pc + 2;
141 else
142 addr = (long)s->pc + 4;
143 tcg_gen_movi_i32(var, addr);
144 } else {
145 tcg_gen_mov_i32(var, cpu_R[reg]);
149 /* Create a new temporary and set it to the value of a CPU register. */
150 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
152 TCGv_i32 tmp = tcg_temp_new_i32();
153 load_reg_var(s, tmp, reg);
154 return tmp;
157 /* Set a CPU register. The source must be a temporary and will be
158 marked as dead. */
159 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
161 if (reg == 15) {
162 tcg_gen_andi_i32(var, var, ~1);
163 s->is_jmp = DISAS_JUMP;
165 tcg_gen_mov_i32(cpu_R[reg], var);
166 tcg_temp_free_i32(var);
169 /* Value extensions. */
170 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
171 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
172 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
173 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
175 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
176 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
179 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
181 TCGv_i32 tmp_mask = tcg_const_i32(mask);
182 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
183 tcg_temp_free_i32(tmp_mask);
185 /* Set NZCV flags from the high 4 bits of var. */
186 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
188 static void gen_exception(int excp)
190 TCGv_i32 tmp = tcg_temp_new_i32();
191 tcg_gen_movi_i32(tmp, excp);
192 gen_helper_exception(cpu_env, tmp);
193 tcg_temp_free_i32(tmp);
196 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
198 TCGv_i32 tmp1 = tcg_temp_new_i32();
199 TCGv_i32 tmp2 = tcg_temp_new_i32();
200 tcg_gen_ext16s_i32(tmp1, a);
201 tcg_gen_ext16s_i32(tmp2, b);
202 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
203 tcg_temp_free_i32(tmp2);
204 tcg_gen_sari_i32(a, a, 16);
205 tcg_gen_sari_i32(b, b, 16);
206 tcg_gen_mul_i32(b, b, a);
207 tcg_gen_mov_i32(a, tmp1);
208 tcg_temp_free_i32(tmp1);
211 /* Byteswap each halfword. */
212 static void gen_rev16(TCGv_i32 var)
214 TCGv_i32 tmp = tcg_temp_new_i32();
215 tcg_gen_shri_i32(tmp, var, 8);
216 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
217 tcg_gen_shli_i32(var, var, 8);
218 tcg_gen_andi_i32(var, var, 0xff00ff00);
219 tcg_gen_or_i32(var, var, tmp);
220 tcg_temp_free_i32(tmp);
223 /* Byteswap low halfword and sign extend. */
224 static void gen_revsh(TCGv_i32 var)
226 tcg_gen_ext16u_i32(var, var);
227 tcg_gen_bswap16_i32(var, var);
228 tcg_gen_ext16s_i32(var, var);
231 /* Unsigned bitfield extract. */
232 static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask)
234 if (shift)
235 tcg_gen_shri_i32(var, var, shift);
236 tcg_gen_andi_i32(var, var, mask);
239 /* Signed bitfield extract. */
240 static void gen_sbfx(TCGv_i32 var, int shift, int width)
242 uint32_t signbit;
244 if (shift)
245 tcg_gen_sari_i32(var, var, shift);
246 if (shift + width < 32) {
247 signbit = 1u << (width - 1);
248 tcg_gen_andi_i32(var, var, (1u << width) - 1);
249 tcg_gen_xori_i32(var, var, signbit);
250 tcg_gen_subi_i32(var, var, signbit);
254 /* Return (b << 32) + a. Mark inputs as dead */
255 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
257 TCGv_i64 tmp64 = tcg_temp_new_i64();
259 tcg_gen_extu_i32_i64(tmp64, b);
260 tcg_temp_free_i32(b);
261 tcg_gen_shli_i64(tmp64, tmp64, 32);
262 tcg_gen_add_i64(a, tmp64, a);
264 tcg_temp_free_i64(tmp64);
265 return a;
268 /* Return (b << 32) - a. Mark inputs as dead. */
269 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
271 TCGv_i64 tmp64 = tcg_temp_new_i64();
273 tcg_gen_extu_i32_i64(tmp64, b);
274 tcg_temp_free_i32(b);
275 tcg_gen_shli_i64(tmp64, tmp64, 32);
276 tcg_gen_sub_i64(a, tmp64, a);
278 tcg_temp_free_i64(tmp64);
279 return a;
282 /* 32x32->64 multiply. Marks inputs as dead. */
283 static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
285 TCGv_i32 lo = tcg_temp_new_i32();
286 TCGv_i32 hi = tcg_temp_new_i32();
287 TCGv_i64 ret;
289 tcg_gen_mulu2_i32(lo, hi, a, b);
290 tcg_temp_free_i32(a);
291 tcg_temp_free_i32(b);
293 ret = tcg_temp_new_i64();
294 tcg_gen_concat_i32_i64(ret, lo, hi);
295 tcg_temp_free_i32(lo);
296 tcg_temp_free_i32(hi);
298 return ret;
301 static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
303 TCGv_i32 lo = tcg_temp_new_i32();
304 TCGv_i32 hi = tcg_temp_new_i32();
305 TCGv_i64 ret;
307 tcg_gen_muls2_i32(lo, hi, a, b);
308 tcg_temp_free_i32(a);
309 tcg_temp_free_i32(b);
311 ret = tcg_temp_new_i64();
312 tcg_gen_concat_i32_i64(ret, lo, hi);
313 tcg_temp_free_i32(lo);
314 tcg_temp_free_i32(hi);
316 return ret;
319 /* Swap low and high halfwords. */
320 static void gen_swap_half(TCGv_i32 var)
322 TCGv_i32 tmp = tcg_temp_new_i32();
323 tcg_gen_shri_i32(tmp, var, 16);
324 tcg_gen_shli_i32(var, var, 16);
325 tcg_gen_or_i32(var, var, tmp);
326 tcg_temp_free_i32(tmp);
329 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
330 tmp = (t0 ^ t1) & 0x8000;
331 t0 &= ~0x8000;
332 t1 &= ~0x8000;
333 t0 = (t0 + t1) ^ tmp;
336 static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
338 TCGv_i32 tmp = tcg_temp_new_i32();
339 tcg_gen_xor_i32(tmp, t0, t1);
340 tcg_gen_andi_i32(tmp, tmp, 0x8000);
341 tcg_gen_andi_i32(t0, t0, ~0x8000);
342 tcg_gen_andi_i32(t1, t1, ~0x8000);
343 tcg_gen_add_i32(t0, t0, t1);
344 tcg_gen_xor_i32(t0, t0, tmp);
345 tcg_temp_free_i32(tmp);
346 tcg_temp_free_i32(t1);
349 /* Set CF to the top bit of var. */
350 static void gen_set_CF_bit31(TCGv_i32 var)
352 tcg_gen_shri_i32(cpu_CF, var, 31);
355 /* Set N and Z flags from var. */
356 static inline void gen_logic_CC(TCGv_i32 var)
358 tcg_gen_mov_i32(cpu_NF, var);
359 tcg_gen_mov_i32(cpu_ZF, var);
362 /* T0 += T1 + CF. */
363 static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
365 tcg_gen_add_i32(t0, t0, t1);
366 tcg_gen_add_i32(t0, t0, cpu_CF);
369 /* dest = T0 + T1 + CF. */
370 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
372 tcg_gen_add_i32(dest, t0, t1);
373 tcg_gen_add_i32(dest, dest, cpu_CF);
376 /* dest = T0 - T1 + CF - 1. */
377 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
379 tcg_gen_sub_i32(dest, t0, t1);
380 tcg_gen_add_i32(dest, dest, cpu_CF);
381 tcg_gen_subi_i32(dest, dest, 1);
384 /* dest = T0 + T1. Compute C, N, V and Z flags */
385 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
387 TCGv_i32 tmp = tcg_temp_new_i32();
388 tcg_gen_movi_i32(tmp, 0);
389 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
390 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
391 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
392 tcg_gen_xor_i32(tmp, t0, t1);
393 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
394 tcg_temp_free_i32(tmp);
395 tcg_gen_mov_i32(dest, cpu_NF);
398 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
399 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
401 TCGv_i32 tmp = tcg_temp_new_i32();
402 if (TCG_TARGET_HAS_add2_i32) {
403 tcg_gen_movi_i32(tmp, 0);
404 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
405 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
406 } else {
407 TCGv_i64 q0 = tcg_temp_new_i64();
408 TCGv_i64 q1 = tcg_temp_new_i64();
409 tcg_gen_extu_i32_i64(q0, t0);
410 tcg_gen_extu_i32_i64(q1, t1);
411 tcg_gen_add_i64(q0, q0, q1);
412 tcg_gen_extu_i32_i64(q1, cpu_CF);
413 tcg_gen_add_i64(q0, q0, q1);
414 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
415 tcg_temp_free_i64(q0);
416 tcg_temp_free_i64(q1);
418 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
419 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
420 tcg_gen_xor_i32(tmp, t0, t1);
421 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
422 tcg_temp_free_i32(tmp);
423 tcg_gen_mov_i32(dest, cpu_NF);
426 /* dest = T0 - T1. Compute C, N, V and Z flags */
427 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
429 TCGv_i32 tmp;
430 tcg_gen_sub_i32(cpu_NF, t0, t1);
431 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
432 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
433 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
434 tmp = tcg_temp_new_i32();
435 tcg_gen_xor_i32(tmp, t0, t1);
436 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
437 tcg_temp_free_i32(tmp);
438 tcg_gen_mov_i32(dest, cpu_NF);
441 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
442 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
444 TCGv_i32 tmp = tcg_temp_new_i32();
445 tcg_gen_not_i32(tmp, t1);
446 gen_adc_CC(dest, t0, tmp);
447 tcg_temp_free_i32(tmp);
450 #define GEN_SHIFT(name) \
451 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
453 TCGv_i32 tmp1, tmp2, tmp3; \
454 tmp1 = tcg_temp_new_i32(); \
455 tcg_gen_andi_i32(tmp1, t1, 0xff); \
456 tmp2 = tcg_const_i32(0); \
457 tmp3 = tcg_const_i32(0x1f); \
458 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
459 tcg_temp_free_i32(tmp3); \
460 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
461 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
462 tcg_temp_free_i32(tmp2); \
463 tcg_temp_free_i32(tmp1); \
465 GEN_SHIFT(shl)
466 GEN_SHIFT(shr)
467 #undef GEN_SHIFT
469 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
471 TCGv_i32 tmp1, tmp2;
472 tmp1 = tcg_temp_new_i32();
473 tcg_gen_andi_i32(tmp1, t1, 0xff);
474 tmp2 = tcg_const_i32(0x1f);
475 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
476 tcg_temp_free_i32(tmp2);
477 tcg_gen_sar_i32(dest, t0, tmp1);
478 tcg_temp_free_i32(tmp1);
481 static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
483 TCGv_i32 c0 = tcg_const_i32(0);
484 TCGv_i32 tmp = tcg_temp_new_i32();
485 tcg_gen_neg_i32(tmp, src);
486 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
487 tcg_temp_free_i32(c0);
488 tcg_temp_free_i32(tmp);
491 static void shifter_out_im(TCGv_i32 var, int shift)
493 if (shift == 0) {
494 tcg_gen_andi_i32(cpu_CF, var, 1);
495 } else {
496 tcg_gen_shri_i32(cpu_CF, var, shift);
497 if (shift != 31) {
498 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
503 /* Shift by immediate. Includes special handling for shift == 0. */
504 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
505 int shift, int flags)
507 switch (shiftop) {
508 case 0: /* LSL */
509 if (shift != 0) {
510 if (flags)
511 shifter_out_im(var, 32 - shift);
512 tcg_gen_shli_i32(var, var, shift);
514 break;
515 case 1: /* LSR */
516 if (shift == 0) {
517 if (flags) {
518 tcg_gen_shri_i32(cpu_CF, var, 31);
520 tcg_gen_movi_i32(var, 0);
521 } else {
522 if (flags)
523 shifter_out_im(var, shift - 1);
524 tcg_gen_shri_i32(var, var, shift);
526 break;
527 case 2: /* ASR */
528 if (shift == 0)
529 shift = 32;
530 if (flags)
531 shifter_out_im(var, shift - 1);
532 if (shift == 32)
533 shift = 31;
534 tcg_gen_sari_i32(var, var, shift);
535 break;
536 case 3: /* ROR/RRX */
537 if (shift != 0) {
538 if (flags)
539 shifter_out_im(var, shift - 1);
540 tcg_gen_rotri_i32(var, var, shift); break;
541 } else {
542 TCGv_i32 tmp = tcg_temp_new_i32();
543 tcg_gen_shli_i32(tmp, cpu_CF, 31);
544 if (flags)
545 shifter_out_im(var, 0);
546 tcg_gen_shri_i32(var, var, 1);
547 tcg_gen_or_i32(var, var, tmp);
548 tcg_temp_free_i32(tmp);
553 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
554 TCGv_i32 shift, int flags)
556 if (flags) {
557 switch (shiftop) {
558 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
559 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
560 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
561 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
563 } else {
564 switch (shiftop) {
565 case 0:
566 gen_shl(var, var, shift);
567 break;
568 case 1:
569 gen_shr(var, var, shift);
570 break;
571 case 2:
572 gen_sar(var, var, shift);
573 break;
574 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
575 tcg_gen_rotr_i32(var, var, shift); break;
578 tcg_temp_free_i32(shift);
581 #define PAS_OP(pfx) \
582 switch (op2) { \
583 case 0: gen_pas_helper(glue(pfx,add16)); break; \
584 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
585 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
586 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
587 case 4: gen_pas_helper(glue(pfx,add8)); break; \
588 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
590 static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
592 TCGv_ptr tmp;
594 switch (op1) {
595 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
596 case 1:
597 tmp = tcg_temp_new_ptr();
598 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
599 PAS_OP(s)
600 tcg_temp_free_ptr(tmp);
601 break;
602 case 5:
603 tmp = tcg_temp_new_ptr();
604 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
605 PAS_OP(u)
606 tcg_temp_free_ptr(tmp);
607 break;
608 #undef gen_pas_helper
609 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
610 case 2:
611 PAS_OP(q);
612 break;
613 case 3:
614 PAS_OP(sh);
615 break;
616 case 6:
617 PAS_OP(uq);
618 break;
619 case 7:
620 PAS_OP(uh);
621 break;
622 #undef gen_pas_helper
625 #undef PAS_OP
627 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
628 #define PAS_OP(pfx) \
629 switch (op1) { \
630 case 0: gen_pas_helper(glue(pfx,add8)); break; \
631 case 1: gen_pas_helper(glue(pfx,add16)); break; \
632 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
633 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
634 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
635 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
637 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
639 TCGv_ptr tmp;
641 switch (op2) {
642 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
643 case 0:
644 tmp = tcg_temp_new_ptr();
645 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
646 PAS_OP(s)
647 tcg_temp_free_ptr(tmp);
648 break;
649 case 4:
650 tmp = tcg_temp_new_ptr();
651 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
652 PAS_OP(u)
653 tcg_temp_free_ptr(tmp);
654 break;
655 #undef gen_pas_helper
656 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
657 case 1:
658 PAS_OP(q);
659 break;
660 case 2:
661 PAS_OP(sh);
662 break;
663 case 5:
664 PAS_OP(uq);
665 break;
666 case 6:
667 PAS_OP(uh);
668 break;
669 #undef gen_pas_helper
672 #undef PAS_OP
675 * generate a conditional branch based on ARM condition code cc.
676 * This is common between ARM and Aarch64 targets.
678 void arm_gen_test_cc(int cc, int label)
680 TCGv_i32 tmp;
681 int inv;
683 switch (cc) {
684 case 0: /* eq: Z */
685 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
686 break;
687 case 1: /* ne: !Z */
688 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
689 break;
690 case 2: /* cs: C */
691 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label);
692 break;
693 case 3: /* cc: !C */
694 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
695 break;
696 case 4: /* mi: N */
697 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label);
698 break;
699 case 5: /* pl: !N */
700 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label);
701 break;
702 case 6: /* vs: V */
703 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label);
704 break;
705 case 7: /* vc: !V */
706 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label);
707 break;
708 case 8: /* hi: C && !Z */
709 inv = gen_new_label();
710 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv);
711 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
712 gen_set_label(inv);
713 break;
714 case 9: /* ls: !C || Z */
715 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
716 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
717 break;
718 case 10: /* ge: N == V -> N ^ V == 0 */
719 tmp = tcg_temp_new_i32();
720 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
721 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
722 tcg_temp_free_i32(tmp);
723 break;
724 case 11: /* lt: N != V -> N ^ V != 0 */
725 tmp = tcg_temp_new_i32();
726 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
727 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
728 tcg_temp_free_i32(tmp);
729 break;
730 case 12: /* gt: !Z && N == V */
731 inv = gen_new_label();
732 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv);
733 tmp = tcg_temp_new_i32();
734 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
735 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
736 tcg_temp_free_i32(tmp);
737 gen_set_label(inv);
738 break;
739 case 13: /* le: Z || N != V */
740 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
741 tmp = tcg_temp_new_i32();
742 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
743 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
744 tcg_temp_free_i32(tmp);
745 break;
746 default:
747 fprintf(stderr, "Bad condition code 0x%x\n", cc);
748 abort();
752 static const uint8_t table_logic_cc[16] = {
753 1, /* and */
754 1, /* xor */
755 0, /* sub */
756 0, /* rsb */
757 0, /* add */
758 0, /* adc */
759 0, /* sbc */
760 0, /* rsc */
761 1, /* andl */
762 1, /* xorl */
763 0, /* cmp */
764 0, /* cmn */
765 1, /* orr */
766 1, /* mov */
767 1, /* bic */
768 1, /* mvn */
771 /* Set PC and Thumb state from an immediate address. */
772 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
774 TCGv_i32 tmp;
776 s->is_jmp = DISAS_UPDATE;
777 if (s->thumb != (addr & 1)) {
778 tmp = tcg_temp_new_i32();
779 tcg_gen_movi_i32(tmp, addr & 1);
780 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
781 tcg_temp_free_i32(tmp);
783 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
786 /* Set PC and Thumb state from var. var is marked as dead. */
787 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
789 s->is_jmp = DISAS_UPDATE;
790 tcg_gen_andi_i32(cpu_R[15], var, ~1);
791 tcg_gen_andi_i32(var, var, 1);
792 store_cpu_field(var, thumb);
795 /* Variant of store_reg which uses branch&exchange logic when storing
796 to r15 in ARM architecture v7 and above. The source must be a temporary
797 and will be marked as dead. */
798 static inline void store_reg_bx(CPUARMState *env, DisasContext *s,
799 int reg, TCGv_i32 var)
801 if (reg == 15 && ENABLE_ARCH_7) {
802 gen_bx(s, var);
803 } else {
804 store_reg(s, reg, var);
808 /* Variant of store_reg which uses branch&exchange logic when storing
809 * to r15 in ARM architecture v5T and above. This is used for storing
810 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
811 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
812 static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
813 int reg, TCGv_i32 var)
815 if (reg == 15 && ENABLE_ARCH_5) {
816 gen_bx(s, var);
817 } else {
818 store_reg(s, reg, var);
822 /* Abstractions of "generate code to do a guest load/store for
823 * AArch32", where a vaddr is always 32 bits (and is zero
824 * extended if we're a 64 bit core) and data is also
825 * 32 bits unless specifically doing a 64 bit access.
826 * These functions work like tcg_gen_qemu_{ld,st}* except
827 * that the address argument is TCGv_i32 rather than TCGv.
829 #if TARGET_LONG_BITS == 32
831 #define DO_GEN_LD(SUFF, OPC) \
832 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
834 tcg_gen_qemu_ld_i32(val, addr, index, OPC); \
837 #define DO_GEN_ST(SUFF, OPC) \
838 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
840 tcg_gen_qemu_st_i32(val, addr, index, OPC); \
843 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
845 tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
848 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
850 tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
853 #else
855 #define DO_GEN_LD(SUFF, OPC) \
856 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
858 TCGv addr64 = tcg_temp_new(); \
859 tcg_gen_extu_i32_i64(addr64, addr); \
860 tcg_gen_qemu_ld_i32(val, addr64, index, OPC); \
861 tcg_temp_free(addr64); \
864 #define DO_GEN_ST(SUFF, OPC) \
865 static inline void gen_aa32_st##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_st_i32(val, addr64, index, OPC); \
870 tcg_temp_free(addr64); \
873 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
875 TCGv addr64 = tcg_temp_new();
876 tcg_gen_extu_i32_i64(addr64, addr);
877 tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
878 tcg_temp_free(addr64);
881 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
883 TCGv addr64 = tcg_temp_new();
884 tcg_gen_extu_i32_i64(addr64, addr);
885 tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
886 tcg_temp_free(addr64);
889 #endif
891 DO_GEN_LD(8s, MO_SB)
892 DO_GEN_LD(8u, MO_UB)
893 DO_GEN_LD(16s, MO_TESW)
894 DO_GEN_LD(16u, MO_TEUW)
895 DO_GEN_LD(32u, MO_TEUL)
896 DO_GEN_ST(8, MO_UB)
897 DO_GEN_ST(16, MO_TEUW)
898 DO_GEN_ST(32, MO_TEUL)
900 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
902 tcg_gen_movi_i32(cpu_R[15], val);
905 /* Force a TB lookup after an instruction that changes the CPU state. */
906 static inline void gen_lookup_tb(DisasContext *s)
908 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
909 s->is_jmp = DISAS_UPDATE;
912 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
913 TCGv_i32 var)
915 int val, rm, shift, shiftop;
916 TCGv_i32 offset;
918 if (!(insn & (1 << 25))) {
919 /* immediate */
920 val = insn & 0xfff;
921 if (!(insn & (1 << 23)))
922 val = -val;
923 if (val != 0)
924 tcg_gen_addi_i32(var, var, val);
925 } else {
926 /* shift/register */
927 rm = (insn) & 0xf;
928 shift = (insn >> 7) & 0x1f;
929 shiftop = (insn >> 5) & 3;
930 offset = load_reg(s, rm);
931 gen_arm_shift_im(offset, shiftop, shift, 0);
932 if (!(insn & (1 << 23)))
933 tcg_gen_sub_i32(var, var, offset);
934 else
935 tcg_gen_add_i32(var, var, offset);
936 tcg_temp_free_i32(offset);
940 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
941 int extra, TCGv_i32 var)
943 int val, rm;
944 TCGv_i32 offset;
946 if (insn & (1 << 22)) {
947 /* immediate */
948 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
949 if (!(insn & (1 << 23)))
950 val = -val;
951 val += extra;
952 if (val != 0)
953 tcg_gen_addi_i32(var, var, val);
954 } else {
955 /* register */
956 if (extra)
957 tcg_gen_addi_i32(var, var, extra);
958 rm = (insn) & 0xf;
959 offset = load_reg(s, rm);
960 if (!(insn & (1 << 23)))
961 tcg_gen_sub_i32(var, var, offset);
962 else
963 tcg_gen_add_i32(var, var, offset);
964 tcg_temp_free_i32(offset);
968 static TCGv_ptr get_fpstatus_ptr(int neon)
970 TCGv_ptr statusptr = tcg_temp_new_ptr();
971 int offset;
972 if (neon) {
973 offset = offsetof(CPUARMState, vfp.standard_fp_status);
974 } else {
975 offset = offsetof(CPUARMState, vfp.fp_status);
977 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
978 return statusptr;
981 #define VFP_OP2(name) \
982 static inline void gen_vfp_##name(int dp) \
984 TCGv_ptr fpst = get_fpstatus_ptr(0); \
985 if (dp) { \
986 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
987 } else { \
988 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
990 tcg_temp_free_ptr(fpst); \
993 VFP_OP2(add)
994 VFP_OP2(sub)
995 VFP_OP2(mul)
996 VFP_OP2(div)
998 #undef VFP_OP2
1000 static inline void gen_vfp_F1_mul(int dp)
1002 /* Like gen_vfp_mul() but put result in F1 */
1003 TCGv_ptr fpst = get_fpstatus_ptr(0);
1004 if (dp) {
1005 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1006 } else {
1007 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1009 tcg_temp_free_ptr(fpst);
1012 static inline void gen_vfp_F1_neg(int dp)
1014 /* Like gen_vfp_neg() but put result in F1 */
1015 if (dp) {
1016 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1017 } else {
1018 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1022 static inline void gen_vfp_abs(int dp)
1024 if (dp)
1025 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1026 else
1027 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1030 static inline void gen_vfp_neg(int dp)
1032 if (dp)
1033 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1034 else
1035 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1038 static inline void gen_vfp_sqrt(int dp)
1040 if (dp)
1041 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1042 else
1043 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1046 static inline void gen_vfp_cmp(int dp)
1048 if (dp)
1049 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1050 else
1051 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1054 static inline void gen_vfp_cmpe(int dp)
1056 if (dp)
1057 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1058 else
1059 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1062 static inline void gen_vfp_F1_ld0(int dp)
1064 if (dp)
1065 tcg_gen_movi_i64(cpu_F1d, 0);
1066 else
1067 tcg_gen_movi_i32(cpu_F1s, 0);
1070 #define VFP_GEN_ITOF(name) \
1071 static inline void gen_vfp_##name(int dp, int neon) \
1073 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1074 if (dp) { \
1075 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1076 } else { \
1077 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1079 tcg_temp_free_ptr(statusptr); \
1082 VFP_GEN_ITOF(uito)
1083 VFP_GEN_ITOF(sito)
1084 #undef VFP_GEN_ITOF
1086 #define VFP_GEN_FTOI(name) \
1087 static inline void gen_vfp_##name(int dp, int neon) \
1089 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1090 if (dp) { \
1091 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1092 } else { \
1093 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1095 tcg_temp_free_ptr(statusptr); \
1098 VFP_GEN_FTOI(toui)
1099 VFP_GEN_FTOI(touiz)
1100 VFP_GEN_FTOI(tosi)
1101 VFP_GEN_FTOI(tosiz)
1102 #undef VFP_GEN_FTOI
1104 #define VFP_GEN_FIX(name) \
1105 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1107 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1108 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1109 if (dp) { \
1110 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, tmp_shift, statusptr); \
1111 } else { \
1112 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, tmp_shift, statusptr); \
1114 tcg_temp_free_i32(tmp_shift); \
1115 tcg_temp_free_ptr(statusptr); \
1117 VFP_GEN_FIX(tosh)
1118 VFP_GEN_FIX(tosl)
1119 VFP_GEN_FIX(touh)
1120 VFP_GEN_FIX(toul)
1121 VFP_GEN_FIX(shto)
1122 VFP_GEN_FIX(slto)
1123 VFP_GEN_FIX(uhto)
1124 VFP_GEN_FIX(ulto)
1125 #undef VFP_GEN_FIX
1127 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1129 if (dp) {
1130 gen_aa32_ld64(cpu_F0d, addr, IS_USER(s));
1131 } else {
1132 gen_aa32_ld32u(cpu_F0s, addr, IS_USER(s));
1136 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1138 if (dp) {
1139 gen_aa32_st64(cpu_F0d, addr, IS_USER(s));
1140 } else {
1141 gen_aa32_st32(cpu_F0s, addr, IS_USER(s));
1145 static inline long
1146 vfp_reg_offset (int dp, int reg)
1148 if (dp)
1149 return offsetof(CPUARMState, vfp.regs[reg]);
1150 else if (reg & 1) {
1151 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1152 + offsetof(CPU_DoubleU, l.upper);
1153 } else {
1154 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1155 + offsetof(CPU_DoubleU, l.lower);
1159 /* Return the offset of a 32-bit piece of a NEON register.
1160 zero is the least significant end of the register. */
1161 static inline long
1162 neon_reg_offset (int reg, int n)
1164 int sreg;
1165 sreg = reg * 2 + n;
1166 return vfp_reg_offset(0, sreg);
1169 static TCGv_i32 neon_load_reg(int reg, int pass)
1171 TCGv_i32 tmp = tcg_temp_new_i32();
1172 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1173 return tmp;
1176 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1178 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1179 tcg_temp_free_i32(var);
1182 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1184 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1187 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1189 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1192 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1193 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1194 #define tcg_gen_st_f32 tcg_gen_st_i32
1195 #define tcg_gen_st_f64 tcg_gen_st_i64
1197 static inline void gen_mov_F0_vreg(int dp, int reg)
1199 if (dp)
1200 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1201 else
1202 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1205 static inline void gen_mov_F1_vreg(int dp, int reg)
1207 if (dp)
1208 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1209 else
1210 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1213 static inline void gen_mov_vreg_F0(int dp, int reg)
1215 if (dp)
1216 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1217 else
1218 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1221 #define ARM_CP_RW_BIT (1 << 20)
1223 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1225 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1228 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1230 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1233 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1235 TCGv_i32 var = tcg_temp_new_i32();
1236 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1237 return var;
1240 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1242 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1243 tcg_temp_free_i32(var);
1246 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1248 iwmmxt_store_reg(cpu_M0, rn);
1251 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1253 iwmmxt_load_reg(cpu_M0, rn);
1256 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1258 iwmmxt_load_reg(cpu_V1, rn);
1259 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1262 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1264 iwmmxt_load_reg(cpu_V1, rn);
1265 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1268 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1270 iwmmxt_load_reg(cpu_V1, rn);
1271 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1274 #define IWMMXT_OP(name) \
1275 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1277 iwmmxt_load_reg(cpu_V1, rn); \
1278 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1281 #define IWMMXT_OP_ENV(name) \
1282 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1284 iwmmxt_load_reg(cpu_V1, rn); \
1285 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1288 #define IWMMXT_OP_ENV_SIZE(name) \
1289 IWMMXT_OP_ENV(name##b) \
1290 IWMMXT_OP_ENV(name##w) \
1291 IWMMXT_OP_ENV(name##l)
1293 #define IWMMXT_OP_ENV1(name) \
1294 static inline void gen_op_iwmmxt_##name##_M0(void) \
1296 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1299 IWMMXT_OP(maddsq)
1300 IWMMXT_OP(madduq)
1301 IWMMXT_OP(sadb)
1302 IWMMXT_OP(sadw)
1303 IWMMXT_OP(mulslw)
1304 IWMMXT_OP(mulshw)
1305 IWMMXT_OP(mululw)
1306 IWMMXT_OP(muluhw)
1307 IWMMXT_OP(macsw)
1308 IWMMXT_OP(macuw)
1310 IWMMXT_OP_ENV_SIZE(unpackl)
1311 IWMMXT_OP_ENV_SIZE(unpackh)
1313 IWMMXT_OP_ENV1(unpacklub)
1314 IWMMXT_OP_ENV1(unpackluw)
1315 IWMMXT_OP_ENV1(unpacklul)
1316 IWMMXT_OP_ENV1(unpackhub)
1317 IWMMXT_OP_ENV1(unpackhuw)
1318 IWMMXT_OP_ENV1(unpackhul)
1319 IWMMXT_OP_ENV1(unpacklsb)
1320 IWMMXT_OP_ENV1(unpacklsw)
1321 IWMMXT_OP_ENV1(unpacklsl)
1322 IWMMXT_OP_ENV1(unpackhsb)
1323 IWMMXT_OP_ENV1(unpackhsw)
1324 IWMMXT_OP_ENV1(unpackhsl)
1326 IWMMXT_OP_ENV_SIZE(cmpeq)
1327 IWMMXT_OP_ENV_SIZE(cmpgtu)
1328 IWMMXT_OP_ENV_SIZE(cmpgts)
1330 IWMMXT_OP_ENV_SIZE(mins)
1331 IWMMXT_OP_ENV_SIZE(minu)
1332 IWMMXT_OP_ENV_SIZE(maxs)
1333 IWMMXT_OP_ENV_SIZE(maxu)
1335 IWMMXT_OP_ENV_SIZE(subn)
1336 IWMMXT_OP_ENV_SIZE(addn)
1337 IWMMXT_OP_ENV_SIZE(subu)
1338 IWMMXT_OP_ENV_SIZE(addu)
1339 IWMMXT_OP_ENV_SIZE(subs)
1340 IWMMXT_OP_ENV_SIZE(adds)
1342 IWMMXT_OP_ENV(avgb0)
1343 IWMMXT_OP_ENV(avgb1)
1344 IWMMXT_OP_ENV(avgw0)
1345 IWMMXT_OP_ENV(avgw1)
1347 IWMMXT_OP(msadb)
1349 IWMMXT_OP_ENV(packuw)
1350 IWMMXT_OP_ENV(packul)
1351 IWMMXT_OP_ENV(packuq)
1352 IWMMXT_OP_ENV(packsw)
1353 IWMMXT_OP_ENV(packsl)
1354 IWMMXT_OP_ENV(packsq)
1356 static void gen_op_iwmmxt_set_mup(void)
1358 TCGv_i32 tmp;
1359 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1360 tcg_gen_ori_i32(tmp, tmp, 2);
1361 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1364 static void gen_op_iwmmxt_set_cup(void)
1366 TCGv_i32 tmp;
1367 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1368 tcg_gen_ori_i32(tmp, tmp, 1);
1369 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1372 static void gen_op_iwmmxt_setpsr_nz(void)
1374 TCGv_i32 tmp = tcg_temp_new_i32();
1375 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1376 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1379 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1381 iwmmxt_load_reg(cpu_V1, rn);
1382 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1383 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1386 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1387 TCGv_i32 dest)
1389 int rd;
1390 uint32_t offset;
1391 TCGv_i32 tmp;
1393 rd = (insn >> 16) & 0xf;
1394 tmp = load_reg(s, rd);
1396 offset = (insn & 0xff) << ((insn >> 7) & 2);
1397 if (insn & (1 << 24)) {
1398 /* Pre indexed */
1399 if (insn & (1 << 23))
1400 tcg_gen_addi_i32(tmp, tmp, offset);
1401 else
1402 tcg_gen_addi_i32(tmp, tmp, -offset);
1403 tcg_gen_mov_i32(dest, tmp);
1404 if (insn & (1 << 21))
1405 store_reg(s, rd, tmp);
1406 else
1407 tcg_temp_free_i32(tmp);
1408 } else if (insn & (1 << 21)) {
1409 /* Post indexed */
1410 tcg_gen_mov_i32(dest, tmp);
1411 if (insn & (1 << 23))
1412 tcg_gen_addi_i32(tmp, tmp, offset);
1413 else
1414 tcg_gen_addi_i32(tmp, tmp, -offset);
1415 store_reg(s, rd, tmp);
1416 } else if (!(insn & (1 << 23)))
1417 return 1;
1418 return 0;
1421 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1423 int rd = (insn >> 0) & 0xf;
1424 TCGv_i32 tmp;
1426 if (insn & (1 << 8)) {
1427 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1428 return 1;
1429 } else {
1430 tmp = iwmmxt_load_creg(rd);
1432 } else {
1433 tmp = tcg_temp_new_i32();
1434 iwmmxt_load_reg(cpu_V0, rd);
1435 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1437 tcg_gen_andi_i32(tmp, tmp, mask);
1438 tcg_gen_mov_i32(dest, tmp);
1439 tcg_temp_free_i32(tmp);
1440 return 0;
1443 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1444 (ie. an undefined instruction). */
1445 static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
1447 int rd, wrd;
1448 int rdhi, rdlo, rd0, rd1, i;
1449 TCGv_i32 addr;
1450 TCGv_i32 tmp, tmp2, tmp3;
1452 if ((insn & 0x0e000e00) == 0x0c000000) {
1453 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1454 wrd = insn & 0xf;
1455 rdlo = (insn >> 12) & 0xf;
1456 rdhi = (insn >> 16) & 0xf;
1457 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1458 iwmmxt_load_reg(cpu_V0, wrd);
1459 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1460 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1461 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1462 } else { /* TMCRR */
1463 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1464 iwmmxt_store_reg(cpu_V0, wrd);
1465 gen_op_iwmmxt_set_mup();
1467 return 0;
1470 wrd = (insn >> 12) & 0xf;
1471 addr = tcg_temp_new_i32();
1472 if (gen_iwmmxt_address(s, insn, addr)) {
1473 tcg_temp_free_i32(addr);
1474 return 1;
1476 if (insn & ARM_CP_RW_BIT) {
1477 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1478 tmp = tcg_temp_new_i32();
1479 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1480 iwmmxt_store_creg(wrd, tmp);
1481 } else {
1482 i = 1;
1483 if (insn & (1 << 8)) {
1484 if (insn & (1 << 22)) { /* WLDRD */
1485 gen_aa32_ld64(cpu_M0, addr, IS_USER(s));
1486 i = 0;
1487 } else { /* WLDRW wRd */
1488 tmp = tcg_temp_new_i32();
1489 gen_aa32_ld32u(tmp, addr, IS_USER(s));
1491 } else {
1492 tmp = tcg_temp_new_i32();
1493 if (insn & (1 << 22)) { /* WLDRH */
1494 gen_aa32_ld16u(tmp, addr, IS_USER(s));
1495 } else { /* WLDRB */
1496 gen_aa32_ld8u(tmp, addr, IS_USER(s));
1499 if (i) {
1500 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1501 tcg_temp_free_i32(tmp);
1503 gen_op_iwmmxt_movq_wRn_M0(wrd);
1505 } else {
1506 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1507 tmp = iwmmxt_load_creg(wrd);
1508 gen_aa32_st32(tmp, addr, IS_USER(s));
1509 } else {
1510 gen_op_iwmmxt_movq_M0_wRn(wrd);
1511 tmp = tcg_temp_new_i32();
1512 if (insn & (1 << 8)) {
1513 if (insn & (1 << 22)) { /* WSTRD */
1514 gen_aa32_st64(cpu_M0, addr, IS_USER(s));
1515 } else { /* WSTRW wRd */
1516 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1517 gen_aa32_st32(tmp, addr, IS_USER(s));
1519 } else {
1520 if (insn & (1 << 22)) { /* WSTRH */
1521 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1522 gen_aa32_st16(tmp, addr, IS_USER(s));
1523 } else { /* WSTRB */
1524 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1525 gen_aa32_st8(tmp, addr, IS_USER(s));
1529 tcg_temp_free_i32(tmp);
1531 tcg_temp_free_i32(addr);
1532 return 0;
1535 if ((insn & 0x0f000000) != 0x0e000000)
1536 return 1;
1538 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1539 case 0x000: /* WOR */
1540 wrd = (insn >> 12) & 0xf;
1541 rd0 = (insn >> 0) & 0xf;
1542 rd1 = (insn >> 16) & 0xf;
1543 gen_op_iwmmxt_movq_M0_wRn(rd0);
1544 gen_op_iwmmxt_orq_M0_wRn(rd1);
1545 gen_op_iwmmxt_setpsr_nz();
1546 gen_op_iwmmxt_movq_wRn_M0(wrd);
1547 gen_op_iwmmxt_set_mup();
1548 gen_op_iwmmxt_set_cup();
1549 break;
1550 case 0x011: /* TMCR */
1551 if (insn & 0xf)
1552 return 1;
1553 rd = (insn >> 12) & 0xf;
1554 wrd = (insn >> 16) & 0xf;
1555 switch (wrd) {
1556 case ARM_IWMMXT_wCID:
1557 case ARM_IWMMXT_wCASF:
1558 break;
1559 case ARM_IWMMXT_wCon:
1560 gen_op_iwmmxt_set_cup();
1561 /* Fall through. */
1562 case ARM_IWMMXT_wCSSF:
1563 tmp = iwmmxt_load_creg(wrd);
1564 tmp2 = load_reg(s, rd);
1565 tcg_gen_andc_i32(tmp, tmp, tmp2);
1566 tcg_temp_free_i32(tmp2);
1567 iwmmxt_store_creg(wrd, tmp);
1568 break;
1569 case ARM_IWMMXT_wCGR0:
1570 case ARM_IWMMXT_wCGR1:
1571 case ARM_IWMMXT_wCGR2:
1572 case ARM_IWMMXT_wCGR3:
1573 gen_op_iwmmxt_set_cup();
1574 tmp = load_reg(s, rd);
1575 iwmmxt_store_creg(wrd, tmp);
1576 break;
1577 default:
1578 return 1;
1580 break;
1581 case 0x100: /* WXOR */
1582 wrd = (insn >> 12) & 0xf;
1583 rd0 = (insn >> 0) & 0xf;
1584 rd1 = (insn >> 16) & 0xf;
1585 gen_op_iwmmxt_movq_M0_wRn(rd0);
1586 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1587 gen_op_iwmmxt_setpsr_nz();
1588 gen_op_iwmmxt_movq_wRn_M0(wrd);
1589 gen_op_iwmmxt_set_mup();
1590 gen_op_iwmmxt_set_cup();
1591 break;
1592 case 0x111: /* TMRC */
1593 if (insn & 0xf)
1594 return 1;
1595 rd = (insn >> 12) & 0xf;
1596 wrd = (insn >> 16) & 0xf;
1597 tmp = iwmmxt_load_creg(wrd);
1598 store_reg(s, rd, tmp);
1599 break;
1600 case 0x300: /* WANDN */
1601 wrd = (insn >> 12) & 0xf;
1602 rd0 = (insn >> 0) & 0xf;
1603 rd1 = (insn >> 16) & 0xf;
1604 gen_op_iwmmxt_movq_M0_wRn(rd0);
1605 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1606 gen_op_iwmmxt_andq_M0_wRn(rd1);
1607 gen_op_iwmmxt_setpsr_nz();
1608 gen_op_iwmmxt_movq_wRn_M0(wrd);
1609 gen_op_iwmmxt_set_mup();
1610 gen_op_iwmmxt_set_cup();
1611 break;
1612 case 0x200: /* WAND */
1613 wrd = (insn >> 12) & 0xf;
1614 rd0 = (insn >> 0) & 0xf;
1615 rd1 = (insn >> 16) & 0xf;
1616 gen_op_iwmmxt_movq_M0_wRn(rd0);
1617 gen_op_iwmmxt_andq_M0_wRn(rd1);
1618 gen_op_iwmmxt_setpsr_nz();
1619 gen_op_iwmmxt_movq_wRn_M0(wrd);
1620 gen_op_iwmmxt_set_mup();
1621 gen_op_iwmmxt_set_cup();
1622 break;
1623 case 0x810: case 0xa10: /* WMADD */
1624 wrd = (insn >> 12) & 0xf;
1625 rd0 = (insn >> 0) & 0xf;
1626 rd1 = (insn >> 16) & 0xf;
1627 gen_op_iwmmxt_movq_M0_wRn(rd0);
1628 if (insn & (1 << 21))
1629 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1630 else
1631 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1632 gen_op_iwmmxt_movq_wRn_M0(wrd);
1633 gen_op_iwmmxt_set_mup();
1634 break;
1635 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1636 wrd = (insn >> 12) & 0xf;
1637 rd0 = (insn >> 16) & 0xf;
1638 rd1 = (insn >> 0) & 0xf;
1639 gen_op_iwmmxt_movq_M0_wRn(rd0);
1640 switch ((insn >> 22) & 3) {
1641 case 0:
1642 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1643 break;
1644 case 1:
1645 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1646 break;
1647 case 2:
1648 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1649 break;
1650 case 3:
1651 return 1;
1653 gen_op_iwmmxt_movq_wRn_M0(wrd);
1654 gen_op_iwmmxt_set_mup();
1655 gen_op_iwmmxt_set_cup();
1656 break;
1657 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1658 wrd = (insn >> 12) & 0xf;
1659 rd0 = (insn >> 16) & 0xf;
1660 rd1 = (insn >> 0) & 0xf;
1661 gen_op_iwmmxt_movq_M0_wRn(rd0);
1662 switch ((insn >> 22) & 3) {
1663 case 0:
1664 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1665 break;
1666 case 1:
1667 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1668 break;
1669 case 2:
1670 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1671 break;
1672 case 3:
1673 return 1;
1675 gen_op_iwmmxt_movq_wRn_M0(wrd);
1676 gen_op_iwmmxt_set_mup();
1677 gen_op_iwmmxt_set_cup();
1678 break;
1679 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1680 wrd = (insn >> 12) & 0xf;
1681 rd0 = (insn >> 16) & 0xf;
1682 rd1 = (insn >> 0) & 0xf;
1683 gen_op_iwmmxt_movq_M0_wRn(rd0);
1684 if (insn & (1 << 22))
1685 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1686 else
1687 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1688 if (!(insn & (1 << 20)))
1689 gen_op_iwmmxt_addl_M0_wRn(wrd);
1690 gen_op_iwmmxt_movq_wRn_M0(wrd);
1691 gen_op_iwmmxt_set_mup();
1692 break;
1693 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1694 wrd = (insn >> 12) & 0xf;
1695 rd0 = (insn >> 16) & 0xf;
1696 rd1 = (insn >> 0) & 0xf;
1697 gen_op_iwmmxt_movq_M0_wRn(rd0);
1698 if (insn & (1 << 21)) {
1699 if (insn & (1 << 20))
1700 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1701 else
1702 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1703 } else {
1704 if (insn & (1 << 20))
1705 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1706 else
1707 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1709 gen_op_iwmmxt_movq_wRn_M0(wrd);
1710 gen_op_iwmmxt_set_mup();
1711 break;
1712 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1713 wrd = (insn >> 12) & 0xf;
1714 rd0 = (insn >> 16) & 0xf;
1715 rd1 = (insn >> 0) & 0xf;
1716 gen_op_iwmmxt_movq_M0_wRn(rd0);
1717 if (insn & (1 << 21))
1718 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1719 else
1720 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1721 if (!(insn & (1 << 20))) {
1722 iwmmxt_load_reg(cpu_V1, wrd);
1723 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1725 gen_op_iwmmxt_movq_wRn_M0(wrd);
1726 gen_op_iwmmxt_set_mup();
1727 break;
1728 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1729 wrd = (insn >> 12) & 0xf;
1730 rd0 = (insn >> 16) & 0xf;
1731 rd1 = (insn >> 0) & 0xf;
1732 gen_op_iwmmxt_movq_M0_wRn(rd0);
1733 switch ((insn >> 22) & 3) {
1734 case 0:
1735 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1736 break;
1737 case 1:
1738 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1739 break;
1740 case 2:
1741 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1742 break;
1743 case 3:
1744 return 1;
1746 gen_op_iwmmxt_movq_wRn_M0(wrd);
1747 gen_op_iwmmxt_set_mup();
1748 gen_op_iwmmxt_set_cup();
1749 break;
1750 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
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 << 22)) {
1756 if (insn & (1 << 20))
1757 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1758 else
1759 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1760 } else {
1761 if (insn & (1 << 20))
1762 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1763 else
1764 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1766 gen_op_iwmmxt_movq_wRn_M0(wrd);
1767 gen_op_iwmmxt_set_mup();
1768 gen_op_iwmmxt_set_cup();
1769 break;
1770 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1771 wrd = (insn >> 12) & 0xf;
1772 rd0 = (insn >> 16) & 0xf;
1773 rd1 = (insn >> 0) & 0xf;
1774 gen_op_iwmmxt_movq_M0_wRn(rd0);
1775 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1776 tcg_gen_andi_i32(tmp, tmp, 7);
1777 iwmmxt_load_reg(cpu_V1, rd1);
1778 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1779 tcg_temp_free_i32(tmp);
1780 gen_op_iwmmxt_movq_wRn_M0(wrd);
1781 gen_op_iwmmxt_set_mup();
1782 break;
1783 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1784 if (((insn >> 6) & 3) == 3)
1785 return 1;
1786 rd = (insn >> 12) & 0xf;
1787 wrd = (insn >> 16) & 0xf;
1788 tmp = load_reg(s, rd);
1789 gen_op_iwmmxt_movq_M0_wRn(wrd);
1790 switch ((insn >> 6) & 3) {
1791 case 0:
1792 tmp2 = tcg_const_i32(0xff);
1793 tmp3 = tcg_const_i32((insn & 7) << 3);
1794 break;
1795 case 1:
1796 tmp2 = tcg_const_i32(0xffff);
1797 tmp3 = tcg_const_i32((insn & 3) << 4);
1798 break;
1799 case 2:
1800 tmp2 = tcg_const_i32(0xffffffff);
1801 tmp3 = tcg_const_i32((insn & 1) << 5);
1802 break;
1803 default:
1804 TCGV_UNUSED_I32(tmp2);
1805 TCGV_UNUSED_I32(tmp3);
1807 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1808 tcg_temp_free_i32(tmp3);
1809 tcg_temp_free_i32(tmp2);
1810 tcg_temp_free_i32(tmp);
1811 gen_op_iwmmxt_movq_wRn_M0(wrd);
1812 gen_op_iwmmxt_set_mup();
1813 break;
1814 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1815 rd = (insn >> 12) & 0xf;
1816 wrd = (insn >> 16) & 0xf;
1817 if (rd == 15 || ((insn >> 22) & 3) == 3)
1818 return 1;
1819 gen_op_iwmmxt_movq_M0_wRn(wrd);
1820 tmp = tcg_temp_new_i32();
1821 switch ((insn >> 22) & 3) {
1822 case 0:
1823 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1824 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1825 if (insn & 8) {
1826 tcg_gen_ext8s_i32(tmp, tmp);
1827 } else {
1828 tcg_gen_andi_i32(tmp, tmp, 0xff);
1830 break;
1831 case 1:
1832 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1833 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1834 if (insn & 8) {
1835 tcg_gen_ext16s_i32(tmp, tmp);
1836 } else {
1837 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1839 break;
1840 case 2:
1841 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1842 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1843 break;
1845 store_reg(s, rd, tmp);
1846 break;
1847 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1848 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1849 return 1;
1850 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1851 switch ((insn >> 22) & 3) {
1852 case 0:
1853 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1854 break;
1855 case 1:
1856 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1857 break;
1858 case 2:
1859 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1860 break;
1862 tcg_gen_shli_i32(tmp, tmp, 28);
1863 gen_set_nzcv(tmp);
1864 tcg_temp_free_i32(tmp);
1865 break;
1866 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1867 if (((insn >> 6) & 3) == 3)
1868 return 1;
1869 rd = (insn >> 12) & 0xf;
1870 wrd = (insn >> 16) & 0xf;
1871 tmp = load_reg(s, rd);
1872 switch ((insn >> 6) & 3) {
1873 case 0:
1874 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1875 break;
1876 case 1:
1877 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1878 break;
1879 case 2:
1880 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1881 break;
1883 tcg_temp_free_i32(tmp);
1884 gen_op_iwmmxt_movq_wRn_M0(wrd);
1885 gen_op_iwmmxt_set_mup();
1886 break;
1887 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1888 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1889 return 1;
1890 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1891 tmp2 = tcg_temp_new_i32();
1892 tcg_gen_mov_i32(tmp2, tmp);
1893 switch ((insn >> 22) & 3) {
1894 case 0:
1895 for (i = 0; i < 7; i ++) {
1896 tcg_gen_shli_i32(tmp2, tmp2, 4);
1897 tcg_gen_and_i32(tmp, tmp, tmp2);
1899 break;
1900 case 1:
1901 for (i = 0; i < 3; i ++) {
1902 tcg_gen_shli_i32(tmp2, tmp2, 8);
1903 tcg_gen_and_i32(tmp, tmp, tmp2);
1905 break;
1906 case 2:
1907 tcg_gen_shli_i32(tmp2, tmp2, 16);
1908 tcg_gen_and_i32(tmp, tmp, tmp2);
1909 break;
1911 gen_set_nzcv(tmp);
1912 tcg_temp_free_i32(tmp2);
1913 tcg_temp_free_i32(tmp);
1914 break;
1915 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1916 wrd = (insn >> 12) & 0xf;
1917 rd0 = (insn >> 16) & 0xf;
1918 gen_op_iwmmxt_movq_M0_wRn(rd0);
1919 switch ((insn >> 22) & 3) {
1920 case 0:
1921 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1922 break;
1923 case 1:
1924 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1925 break;
1926 case 2:
1927 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1928 break;
1929 case 3:
1930 return 1;
1932 gen_op_iwmmxt_movq_wRn_M0(wrd);
1933 gen_op_iwmmxt_set_mup();
1934 break;
1935 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
1936 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1937 return 1;
1938 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1939 tmp2 = tcg_temp_new_i32();
1940 tcg_gen_mov_i32(tmp2, tmp);
1941 switch ((insn >> 22) & 3) {
1942 case 0:
1943 for (i = 0; i < 7; i ++) {
1944 tcg_gen_shli_i32(tmp2, tmp2, 4);
1945 tcg_gen_or_i32(tmp, tmp, tmp2);
1947 break;
1948 case 1:
1949 for (i = 0; i < 3; i ++) {
1950 tcg_gen_shli_i32(tmp2, tmp2, 8);
1951 tcg_gen_or_i32(tmp, tmp, tmp2);
1953 break;
1954 case 2:
1955 tcg_gen_shli_i32(tmp2, tmp2, 16);
1956 tcg_gen_or_i32(tmp, tmp, tmp2);
1957 break;
1959 gen_set_nzcv(tmp);
1960 tcg_temp_free_i32(tmp2);
1961 tcg_temp_free_i32(tmp);
1962 break;
1963 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
1964 rd = (insn >> 12) & 0xf;
1965 rd0 = (insn >> 16) & 0xf;
1966 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
1967 return 1;
1968 gen_op_iwmmxt_movq_M0_wRn(rd0);
1969 tmp = tcg_temp_new_i32();
1970 switch ((insn >> 22) & 3) {
1971 case 0:
1972 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
1973 break;
1974 case 1:
1975 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
1976 break;
1977 case 2:
1978 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
1979 break;
1981 store_reg(s, rd, tmp);
1982 break;
1983 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
1984 case 0x906: case 0xb06: case 0xd06: case 0xf06:
1985 wrd = (insn >> 12) & 0xf;
1986 rd0 = (insn >> 16) & 0xf;
1987 rd1 = (insn >> 0) & 0xf;
1988 gen_op_iwmmxt_movq_M0_wRn(rd0);
1989 switch ((insn >> 22) & 3) {
1990 case 0:
1991 if (insn & (1 << 21))
1992 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
1993 else
1994 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
1995 break;
1996 case 1:
1997 if (insn & (1 << 21))
1998 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
1999 else
2000 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2001 break;
2002 case 2:
2003 if (insn & (1 << 21))
2004 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2005 else
2006 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2007 break;
2008 case 3:
2009 return 1;
2011 gen_op_iwmmxt_movq_wRn_M0(wrd);
2012 gen_op_iwmmxt_set_mup();
2013 gen_op_iwmmxt_set_cup();
2014 break;
2015 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2016 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2017 wrd = (insn >> 12) & 0xf;
2018 rd0 = (insn >> 16) & 0xf;
2019 gen_op_iwmmxt_movq_M0_wRn(rd0);
2020 switch ((insn >> 22) & 3) {
2021 case 0:
2022 if (insn & (1 << 21))
2023 gen_op_iwmmxt_unpacklsb_M0();
2024 else
2025 gen_op_iwmmxt_unpacklub_M0();
2026 break;
2027 case 1:
2028 if (insn & (1 << 21))
2029 gen_op_iwmmxt_unpacklsw_M0();
2030 else
2031 gen_op_iwmmxt_unpackluw_M0();
2032 break;
2033 case 2:
2034 if (insn & (1 << 21))
2035 gen_op_iwmmxt_unpacklsl_M0();
2036 else
2037 gen_op_iwmmxt_unpacklul_M0();
2038 break;
2039 case 3:
2040 return 1;
2042 gen_op_iwmmxt_movq_wRn_M0(wrd);
2043 gen_op_iwmmxt_set_mup();
2044 gen_op_iwmmxt_set_cup();
2045 break;
2046 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2047 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2048 wrd = (insn >> 12) & 0xf;
2049 rd0 = (insn >> 16) & 0xf;
2050 gen_op_iwmmxt_movq_M0_wRn(rd0);
2051 switch ((insn >> 22) & 3) {
2052 case 0:
2053 if (insn & (1 << 21))
2054 gen_op_iwmmxt_unpackhsb_M0();
2055 else
2056 gen_op_iwmmxt_unpackhub_M0();
2057 break;
2058 case 1:
2059 if (insn & (1 << 21))
2060 gen_op_iwmmxt_unpackhsw_M0();
2061 else
2062 gen_op_iwmmxt_unpackhuw_M0();
2063 break;
2064 case 2:
2065 if (insn & (1 << 21))
2066 gen_op_iwmmxt_unpackhsl_M0();
2067 else
2068 gen_op_iwmmxt_unpackhul_M0();
2069 break;
2070 case 3:
2071 return 1;
2073 gen_op_iwmmxt_movq_wRn_M0(wrd);
2074 gen_op_iwmmxt_set_mup();
2075 gen_op_iwmmxt_set_cup();
2076 break;
2077 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2078 case 0x214: case 0x614: case 0xa14: case 0xe14:
2079 if (((insn >> 22) & 3) == 0)
2080 return 1;
2081 wrd = (insn >> 12) & 0xf;
2082 rd0 = (insn >> 16) & 0xf;
2083 gen_op_iwmmxt_movq_M0_wRn(rd0);
2084 tmp = tcg_temp_new_i32();
2085 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2086 tcg_temp_free_i32(tmp);
2087 return 1;
2089 switch ((insn >> 22) & 3) {
2090 case 1:
2091 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2092 break;
2093 case 2:
2094 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2095 break;
2096 case 3:
2097 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2098 break;
2100 tcg_temp_free_i32(tmp);
2101 gen_op_iwmmxt_movq_wRn_M0(wrd);
2102 gen_op_iwmmxt_set_mup();
2103 gen_op_iwmmxt_set_cup();
2104 break;
2105 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2106 case 0x014: case 0x414: case 0x814: case 0xc14:
2107 if (((insn >> 22) & 3) == 0)
2108 return 1;
2109 wrd = (insn >> 12) & 0xf;
2110 rd0 = (insn >> 16) & 0xf;
2111 gen_op_iwmmxt_movq_M0_wRn(rd0);
2112 tmp = tcg_temp_new_i32();
2113 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2114 tcg_temp_free_i32(tmp);
2115 return 1;
2117 switch ((insn >> 22) & 3) {
2118 case 1:
2119 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2120 break;
2121 case 2:
2122 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2123 break;
2124 case 3:
2125 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2126 break;
2128 tcg_temp_free_i32(tmp);
2129 gen_op_iwmmxt_movq_wRn_M0(wrd);
2130 gen_op_iwmmxt_set_mup();
2131 gen_op_iwmmxt_set_cup();
2132 break;
2133 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2134 case 0x114: case 0x514: case 0x914: case 0xd14:
2135 if (((insn >> 22) & 3) == 0)
2136 return 1;
2137 wrd = (insn >> 12) & 0xf;
2138 rd0 = (insn >> 16) & 0xf;
2139 gen_op_iwmmxt_movq_M0_wRn(rd0);
2140 tmp = tcg_temp_new_i32();
2141 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2142 tcg_temp_free_i32(tmp);
2143 return 1;
2145 switch ((insn >> 22) & 3) {
2146 case 1:
2147 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2148 break;
2149 case 2:
2150 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2151 break;
2152 case 3:
2153 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2154 break;
2156 tcg_temp_free_i32(tmp);
2157 gen_op_iwmmxt_movq_wRn_M0(wrd);
2158 gen_op_iwmmxt_set_mup();
2159 gen_op_iwmmxt_set_cup();
2160 break;
2161 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2162 case 0x314: case 0x714: case 0xb14: case 0xf14:
2163 if (((insn >> 22) & 3) == 0)
2164 return 1;
2165 wrd = (insn >> 12) & 0xf;
2166 rd0 = (insn >> 16) & 0xf;
2167 gen_op_iwmmxt_movq_M0_wRn(rd0);
2168 tmp = tcg_temp_new_i32();
2169 switch ((insn >> 22) & 3) {
2170 case 1:
2171 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2172 tcg_temp_free_i32(tmp);
2173 return 1;
2175 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2176 break;
2177 case 2:
2178 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2179 tcg_temp_free_i32(tmp);
2180 return 1;
2182 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2183 break;
2184 case 3:
2185 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2186 tcg_temp_free_i32(tmp);
2187 return 1;
2189 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2190 break;
2192 tcg_temp_free_i32(tmp);
2193 gen_op_iwmmxt_movq_wRn_M0(wrd);
2194 gen_op_iwmmxt_set_mup();
2195 gen_op_iwmmxt_set_cup();
2196 break;
2197 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2198 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2199 wrd = (insn >> 12) & 0xf;
2200 rd0 = (insn >> 16) & 0xf;
2201 rd1 = (insn >> 0) & 0xf;
2202 gen_op_iwmmxt_movq_M0_wRn(rd0);
2203 switch ((insn >> 22) & 3) {
2204 case 0:
2205 if (insn & (1 << 21))
2206 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2207 else
2208 gen_op_iwmmxt_minub_M0_wRn(rd1);
2209 break;
2210 case 1:
2211 if (insn & (1 << 21))
2212 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2213 else
2214 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2215 break;
2216 case 2:
2217 if (insn & (1 << 21))
2218 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2219 else
2220 gen_op_iwmmxt_minul_M0_wRn(rd1);
2221 break;
2222 case 3:
2223 return 1;
2225 gen_op_iwmmxt_movq_wRn_M0(wrd);
2226 gen_op_iwmmxt_set_mup();
2227 break;
2228 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2229 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2230 wrd = (insn >> 12) & 0xf;
2231 rd0 = (insn >> 16) & 0xf;
2232 rd1 = (insn >> 0) & 0xf;
2233 gen_op_iwmmxt_movq_M0_wRn(rd0);
2234 switch ((insn >> 22) & 3) {
2235 case 0:
2236 if (insn & (1 << 21))
2237 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2238 else
2239 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2240 break;
2241 case 1:
2242 if (insn & (1 << 21))
2243 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2244 else
2245 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2246 break;
2247 case 2:
2248 if (insn & (1 << 21))
2249 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2250 else
2251 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2252 break;
2253 case 3:
2254 return 1;
2256 gen_op_iwmmxt_movq_wRn_M0(wrd);
2257 gen_op_iwmmxt_set_mup();
2258 break;
2259 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2260 case 0x402: case 0x502: case 0x602: case 0x702:
2261 wrd = (insn >> 12) & 0xf;
2262 rd0 = (insn >> 16) & 0xf;
2263 rd1 = (insn >> 0) & 0xf;
2264 gen_op_iwmmxt_movq_M0_wRn(rd0);
2265 tmp = tcg_const_i32((insn >> 20) & 3);
2266 iwmmxt_load_reg(cpu_V1, rd1);
2267 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2268 tcg_temp_free_i32(tmp);
2269 gen_op_iwmmxt_movq_wRn_M0(wrd);
2270 gen_op_iwmmxt_set_mup();
2271 break;
2272 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2273 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2274 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2275 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2276 wrd = (insn >> 12) & 0xf;
2277 rd0 = (insn >> 16) & 0xf;
2278 rd1 = (insn >> 0) & 0xf;
2279 gen_op_iwmmxt_movq_M0_wRn(rd0);
2280 switch ((insn >> 20) & 0xf) {
2281 case 0x0:
2282 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2283 break;
2284 case 0x1:
2285 gen_op_iwmmxt_subub_M0_wRn(rd1);
2286 break;
2287 case 0x3:
2288 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2289 break;
2290 case 0x4:
2291 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2292 break;
2293 case 0x5:
2294 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2295 break;
2296 case 0x7:
2297 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2298 break;
2299 case 0x8:
2300 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2301 break;
2302 case 0x9:
2303 gen_op_iwmmxt_subul_M0_wRn(rd1);
2304 break;
2305 case 0xb:
2306 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2307 break;
2308 default:
2309 return 1;
2311 gen_op_iwmmxt_movq_wRn_M0(wrd);
2312 gen_op_iwmmxt_set_mup();
2313 gen_op_iwmmxt_set_cup();
2314 break;
2315 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2316 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2317 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2318 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2319 wrd = (insn >> 12) & 0xf;
2320 rd0 = (insn >> 16) & 0xf;
2321 gen_op_iwmmxt_movq_M0_wRn(rd0);
2322 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2323 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2324 tcg_temp_free_i32(tmp);
2325 gen_op_iwmmxt_movq_wRn_M0(wrd);
2326 gen_op_iwmmxt_set_mup();
2327 gen_op_iwmmxt_set_cup();
2328 break;
2329 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2330 case 0x418: case 0x518: case 0x618: case 0x718:
2331 case 0x818: case 0x918: case 0xa18: case 0xb18:
2332 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2333 wrd = (insn >> 12) & 0xf;
2334 rd0 = (insn >> 16) & 0xf;
2335 rd1 = (insn >> 0) & 0xf;
2336 gen_op_iwmmxt_movq_M0_wRn(rd0);
2337 switch ((insn >> 20) & 0xf) {
2338 case 0x0:
2339 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2340 break;
2341 case 0x1:
2342 gen_op_iwmmxt_addub_M0_wRn(rd1);
2343 break;
2344 case 0x3:
2345 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2346 break;
2347 case 0x4:
2348 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2349 break;
2350 case 0x5:
2351 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2352 break;
2353 case 0x7:
2354 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2355 break;
2356 case 0x8:
2357 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2358 break;
2359 case 0x9:
2360 gen_op_iwmmxt_addul_M0_wRn(rd1);
2361 break;
2362 case 0xb:
2363 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2364 break;
2365 default:
2366 return 1;
2368 gen_op_iwmmxt_movq_wRn_M0(wrd);
2369 gen_op_iwmmxt_set_mup();
2370 gen_op_iwmmxt_set_cup();
2371 break;
2372 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2373 case 0x408: case 0x508: case 0x608: case 0x708:
2374 case 0x808: case 0x908: case 0xa08: case 0xb08:
2375 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2376 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2377 return 1;
2378 wrd = (insn >> 12) & 0xf;
2379 rd0 = (insn >> 16) & 0xf;
2380 rd1 = (insn >> 0) & 0xf;
2381 gen_op_iwmmxt_movq_M0_wRn(rd0);
2382 switch ((insn >> 22) & 3) {
2383 case 1:
2384 if (insn & (1 << 21))
2385 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2386 else
2387 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2388 break;
2389 case 2:
2390 if (insn & (1 << 21))
2391 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2392 else
2393 gen_op_iwmmxt_packul_M0_wRn(rd1);
2394 break;
2395 case 3:
2396 if (insn & (1 << 21))
2397 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2398 else
2399 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2400 break;
2402 gen_op_iwmmxt_movq_wRn_M0(wrd);
2403 gen_op_iwmmxt_set_mup();
2404 gen_op_iwmmxt_set_cup();
2405 break;
2406 case 0x201: case 0x203: case 0x205: case 0x207:
2407 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2408 case 0x211: case 0x213: case 0x215: case 0x217:
2409 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2410 wrd = (insn >> 5) & 0xf;
2411 rd0 = (insn >> 12) & 0xf;
2412 rd1 = (insn >> 0) & 0xf;
2413 if (rd0 == 0xf || rd1 == 0xf)
2414 return 1;
2415 gen_op_iwmmxt_movq_M0_wRn(wrd);
2416 tmp = load_reg(s, rd0);
2417 tmp2 = load_reg(s, rd1);
2418 switch ((insn >> 16) & 0xf) {
2419 case 0x0: /* TMIA */
2420 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2421 break;
2422 case 0x8: /* TMIAPH */
2423 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2424 break;
2425 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2426 if (insn & (1 << 16))
2427 tcg_gen_shri_i32(tmp, tmp, 16);
2428 if (insn & (1 << 17))
2429 tcg_gen_shri_i32(tmp2, tmp2, 16);
2430 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2431 break;
2432 default:
2433 tcg_temp_free_i32(tmp2);
2434 tcg_temp_free_i32(tmp);
2435 return 1;
2437 tcg_temp_free_i32(tmp2);
2438 tcg_temp_free_i32(tmp);
2439 gen_op_iwmmxt_movq_wRn_M0(wrd);
2440 gen_op_iwmmxt_set_mup();
2441 break;
2442 default:
2443 return 1;
2446 return 0;
2449 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2450 (ie. an undefined instruction). */
2451 static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2453 int acc, rd0, rd1, rdhi, rdlo;
2454 TCGv_i32 tmp, tmp2;
2456 if ((insn & 0x0ff00f10) == 0x0e200010) {
2457 /* Multiply with Internal Accumulate Format */
2458 rd0 = (insn >> 12) & 0xf;
2459 rd1 = insn & 0xf;
2460 acc = (insn >> 5) & 7;
2462 if (acc != 0)
2463 return 1;
2465 tmp = load_reg(s, rd0);
2466 tmp2 = load_reg(s, rd1);
2467 switch ((insn >> 16) & 0xf) {
2468 case 0x0: /* MIA */
2469 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2470 break;
2471 case 0x8: /* MIAPH */
2472 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2473 break;
2474 case 0xc: /* MIABB */
2475 case 0xd: /* MIABT */
2476 case 0xe: /* MIATB */
2477 case 0xf: /* MIATT */
2478 if (insn & (1 << 16))
2479 tcg_gen_shri_i32(tmp, tmp, 16);
2480 if (insn & (1 << 17))
2481 tcg_gen_shri_i32(tmp2, tmp2, 16);
2482 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2483 break;
2484 default:
2485 return 1;
2487 tcg_temp_free_i32(tmp2);
2488 tcg_temp_free_i32(tmp);
2490 gen_op_iwmmxt_movq_wRn_M0(acc);
2491 return 0;
2494 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2495 /* Internal Accumulator Access Format */
2496 rdhi = (insn >> 16) & 0xf;
2497 rdlo = (insn >> 12) & 0xf;
2498 acc = insn & 7;
2500 if (acc != 0)
2501 return 1;
2503 if (insn & ARM_CP_RW_BIT) { /* MRA */
2504 iwmmxt_load_reg(cpu_V0, acc);
2505 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2506 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2507 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2508 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2509 } else { /* MAR */
2510 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2511 iwmmxt_store_reg(cpu_V0, acc);
2513 return 0;
2516 return 1;
2519 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2520 #define VFP_SREG(insn, bigbit, smallbit) \
2521 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2522 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2523 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2524 reg = (((insn) >> (bigbit)) & 0x0f) \
2525 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2526 } else { \
2527 if (insn & (1 << (smallbit))) \
2528 return 1; \
2529 reg = ((insn) >> (bigbit)) & 0x0f; \
2530 }} while (0)
2532 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2533 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2534 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2535 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2536 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2537 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2539 /* Move between integer and VFP cores. */
2540 static TCGv_i32 gen_vfp_mrs(void)
2542 TCGv_i32 tmp = tcg_temp_new_i32();
2543 tcg_gen_mov_i32(tmp, cpu_F0s);
2544 return tmp;
2547 static void gen_vfp_msr(TCGv_i32 tmp)
2549 tcg_gen_mov_i32(cpu_F0s, tmp);
2550 tcg_temp_free_i32(tmp);
2553 static void gen_neon_dup_u8(TCGv_i32 var, int shift)
2555 TCGv_i32 tmp = tcg_temp_new_i32();
2556 if (shift)
2557 tcg_gen_shri_i32(var, var, shift);
2558 tcg_gen_ext8u_i32(var, var);
2559 tcg_gen_shli_i32(tmp, var, 8);
2560 tcg_gen_or_i32(var, var, tmp);
2561 tcg_gen_shli_i32(tmp, var, 16);
2562 tcg_gen_or_i32(var, var, tmp);
2563 tcg_temp_free_i32(tmp);
2566 static void gen_neon_dup_low16(TCGv_i32 var)
2568 TCGv_i32 tmp = tcg_temp_new_i32();
2569 tcg_gen_ext16u_i32(var, var);
2570 tcg_gen_shli_i32(tmp, var, 16);
2571 tcg_gen_or_i32(var, var, tmp);
2572 tcg_temp_free_i32(tmp);
2575 static void gen_neon_dup_high16(TCGv_i32 var)
2577 TCGv_i32 tmp = tcg_temp_new_i32();
2578 tcg_gen_andi_i32(var, var, 0xffff0000);
2579 tcg_gen_shri_i32(tmp, var, 16);
2580 tcg_gen_or_i32(var, var, tmp);
2581 tcg_temp_free_i32(tmp);
2584 static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
2586 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2587 TCGv_i32 tmp = tcg_temp_new_i32();
2588 switch (size) {
2589 case 0:
2590 gen_aa32_ld8u(tmp, addr, IS_USER(s));
2591 gen_neon_dup_u8(tmp, 0);
2592 break;
2593 case 1:
2594 gen_aa32_ld16u(tmp, addr, IS_USER(s));
2595 gen_neon_dup_low16(tmp);
2596 break;
2597 case 2:
2598 gen_aa32_ld32u(tmp, addr, IS_USER(s));
2599 break;
2600 default: /* Avoid compiler warnings. */
2601 abort();
2603 return tmp;
2606 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2607 uint32_t dp)
2609 uint32_t cc = extract32(insn, 20, 2);
2611 if (dp) {
2612 TCGv_i64 frn, frm, dest;
2613 TCGv_i64 tmp, zero, zf, nf, vf;
2615 zero = tcg_const_i64(0);
2617 frn = tcg_temp_new_i64();
2618 frm = tcg_temp_new_i64();
2619 dest = tcg_temp_new_i64();
2621 zf = tcg_temp_new_i64();
2622 nf = tcg_temp_new_i64();
2623 vf = tcg_temp_new_i64();
2625 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2626 tcg_gen_ext_i32_i64(nf, cpu_NF);
2627 tcg_gen_ext_i32_i64(vf, cpu_VF);
2629 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2630 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2631 switch (cc) {
2632 case 0: /* eq: Z */
2633 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2634 frn, frm);
2635 break;
2636 case 1: /* vs: V */
2637 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2638 frn, frm);
2639 break;
2640 case 2: /* ge: N == V -> N ^ V == 0 */
2641 tmp = tcg_temp_new_i64();
2642 tcg_gen_xor_i64(tmp, vf, nf);
2643 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2644 frn, frm);
2645 tcg_temp_free_i64(tmp);
2646 break;
2647 case 3: /* gt: !Z && N == V */
2648 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2649 frn, frm);
2650 tmp = tcg_temp_new_i64();
2651 tcg_gen_xor_i64(tmp, vf, nf);
2652 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2653 dest, frm);
2654 tcg_temp_free_i64(tmp);
2655 break;
2657 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2658 tcg_temp_free_i64(frn);
2659 tcg_temp_free_i64(frm);
2660 tcg_temp_free_i64(dest);
2662 tcg_temp_free_i64(zf);
2663 tcg_temp_free_i64(nf);
2664 tcg_temp_free_i64(vf);
2666 tcg_temp_free_i64(zero);
2667 } else {
2668 TCGv_i32 frn, frm, dest;
2669 TCGv_i32 tmp, zero;
2671 zero = tcg_const_i32(0);
2673 frn = tcg_temp_new_i32();
2674 frm = tcg_temp_new_i32();
2675 dest = tcg_temp_new_i32();
2676 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2677 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2678 switch (cc) {
2679 case 0: /* eq: Z */
2680 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2681 frn, frm);
2682 break;
2683 case 1: /* vs: V */
2684 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2685 frn, frm);
2686 break;
2687 case 2: /* ge: N == V -> N ^ V == 0 */
2688 tmp = tcg_temp_new_i32();
2689 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2690 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2691 frn, frm);
2692 tcg_temp_free_i32(tmp);
2693 break;
2694 case 3: /* gt: !Z && N == V */
2695 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2696 frn, frm);
2697 tmp = tcg_temp_new_i32();
2698 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2699 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2700 dest, frm);
2701 tcg_temp_free_i32(tmp);
2702 break;
2704 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2705 tcg_temp_free_i32(frn);
2706 tcg_temp_free_i32(frm);
2707 tcg_temp_free_i32(dest);
2709 tcg_temp_free_i32(zero);
2712 return 0;
2715 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2716 uint32_t rm, uint32_t dp)
2718 uint32_t vmin = extract32(insn, 6, 1);
2719 TCGv_ptr fpst = get_fpstatus_ptr(0);
2721 if (dp) {
2722 TCGv_i64 frn, frm, dest;
2724 frn = tcg_temp_new_i64();
2725 frm = tcg_temp_new_i64();
2726 dest = tcg_temp_new_i64();
2728 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2729 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2730 if (vmin) {
2731 gen_helper_vfp_minnmd(dest, frn, frm, fpst);
2732 } else {
2733 gen_helper_vfp_maxnmd(dest, frn, frm, fpst);
2735 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2736 tcg_temp_free_i64(frn);
2737 tcg_temp_free_i64(frm);
2738 tcg_temp_free_i64(dest);
2739 } else {
2740 TCGv_i32 frn, frm, dest;
2742 frn = tcg_temp_new_i32();
2743 frm = tcg_temp_new_i32();
2744 dest = tcg_temp_new_i32();
2746 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2747 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2748 if (vmin) {
2749 gen_helper_vfp_minnms(dest, frn, frm, fpst);
2750 } else {
2751 gen_helper_vfp_maxnms(dest, frn, frm, fpst);
2753 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2754 tcg_temp_free_i32(frn);
2755 tcg_temp_free_i32(frm);
2756 tcg_temp_free_i32(dest);
2759 tcg_temp_free_ptr(fpst);
2760 return 0;
2763 static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2765 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
2767 if (!arm_feature(env, ARM_FEATURE_V8)) {
2768 return 1;
2771 if (dp) {
2772 VFP_DREG_D(rd, insn);
2773 VFP_DREG_N(rn, insn);
2774 VFP_DREG_M(rm, insn);
2775 } else {
2776 rd = VFP_SREG_D(insn);
2777 rn = VFP_SREG_N(insn);
2778 rm = VFP_SREG_M(insn);
2781 if ((insn & 0x0f800e50) == 0x0e000a00) {
2782 return handle_vsel(insn, rd, rn, rm, dp);
2783 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
2784 return handle_vminmaxnm(insn, rd, rn, rm, dp);
2786 return 1;
2789 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2790 (ie. an undefined instruction). */
2791 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
2793 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2794 int dp, veclen;
2795 TCGv_i32 addr;
2796 TCGv_i32 tmp;
2797 TCGv_i32 tmp2;
2799 if (!arm_feature(env, ARM_FEATURE_VFP))
2800 return 1;
2802 if (!s->vfp_enabled) {
2803 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2804 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2805 return 1;
2806 rn = (insn >> 16) & 0xf;
2807 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC
2808 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0)
2809 return 1;
2812 if (extract32(insn, 28, 4) == 0xf) {
2813 /* Encodings with T=1 (Thumb) or unconditional (ARM):
2814 * only used in v8 and above.
2816 return disas_vfp_v8_insn(env, s, insn);
2819 dp = ((insn & 0xf00) == 0xb00);
2820 switch ((insn >> 24) & 0xf) {
2821 case 0xe:
2822 if (insn & (1 << 4)) {
2823 /* single register transfer */
2824 rd = (insn >> 12) & 0xf;
2825 if (dp) {
2826 int size;
2827 int pass;
2829 VFP_DREG_N(rn, insn);
2830 if (insn & 0xf)
2831 return 1;
2832 if (insn & 0x00c00060
2833 && !arm_feature(env, ARM_FEATURE_NEON))
2834 return 1;
2836 pass = (insn >> 21) & 1;
2837 if (insn & (1 << 22)) {
2838 size = 0;
2839 offset = ((insn >> 5) & 3) * 8;
2840 } else if (insn & (1 << 5)) {
2841 size = 1;
2842 offset = (insn & (1 << 6)) ? 16 : 0;
2843 } else {
2844 size = 2;
2845 offset = 0;
2847 if (insn & ARM_CP_RW_BIT) {
2848 /* vfp->arm */
2849 tmp = neon_load_reg(rn, pass);
2850 switch (size) {
2851 case 0:
2852 if (offset)
2853 tcg_gen_shri_i32(tmp, tmp, offset);
2854 if (insn & (1 << 23))
2855 gen_uxtb(tmp);
2856 else
2857 gen_sxtb(tmp);
2858 break;
2859 case 1:
2860 if (insn & (1 << 23)) {
2861 if (offset) {
2862 tcg_gen_shri_i32(tmp, tmp, 16);
2863 } else {
2864 gen_uxth(tmp);
2866 } else {
2867 if (offset) {
2868 tcg_gen_sari_i32(tmp, tmp, 16);
2869 } else {
2870 gen_sxth(tmp);
2873 break;
2874 case 2:
2875 break;
2877 store_reg(s, rd, tmp);
2878 } else {
2879 /* arm->vfp */
2880 tmp = load_reg(s, rd);
2881 if (insn & (1 << 23)) {
2882 /* VDUP */
2883 if (size == 0) {
2884 gen_neon_dup_u8(tmp, 0);
2885 } else if (size == 1) {
2886 gen_neon_dup_low16(tmp);
2888 for (n = 0; n <= pass * 2; n++) {
2889 tmp2 = tcg_temp_new_i32();
2890 tcg_gen_mov_i32(tmp2, tmp);
2891 neon_store_reg(rn, n, tmp2);
2893 neon_store_reg(rn, n, tmp);
2894 } else {
2895 /* VMOV */
2896 switch (size) {
2897 case 0:
2898 tmp2 = neon_load_reg(rn, pass);
2899 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
2900 tcg_temp_free_i32(tmp2);
2901 break;
2902 case 1:
2903 tmp2 = neon_load_reg(rn, pass);
2904 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
2905 tcg_temp_free_i32(tmp2);
2906 break;
2907 case 2:
2908 break;
2910 neon_store_reg(rn, pass, tmp);
2913 } else { /* !dp */
2914 if ((insn & 0x6f) != 0x00)
2915 return 1;
2916 rn = VFP_SREG_N(insn);
2917 if (insn & ARM_CP_RW_BIT) {
2918 /* vfp->arm */
2919 if (insn & (1 << 21)) {
2920 /* system register */
2921 rn >>= 1;
2923 switch (rn) {
2924 case ARM_VFP_FPSID:
2925 /* VFP2 allows access to FSID from userspace.
2926 VFP3 restricts all id registers to privileged
2927 accesses. */
2928 if (IS_USER(s)
2929 && arm_feature(env, ARM_FEATURE_VFP3))
2930 return 1;
2931 tmp = load_cpu_field(vfp.xregs[rn]);
2932 break;
2933 case ARM_VFP_FPEXC:
2934 if (IS_USER(s))
2935 return 1;
2936 tmp = load_cpu_field(vfp.xregs[rn]);
2937 break;
2938 case ARM_VFP_FPINST:
2939 case ARM_VFP_FPINST2:
2940 /* Not present in VFP3. */
2941 if (IS_USER(s)
2942 || arm_feature(env, ARM_FEATURE_VFP3))
2943 return 1;
2944 tmp = load_cpu_field(vfp.xregs[rn]);
2945 break;
2946 case ARM_VFP_FPSCR:
2947 if (rd == 15) {
2948 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
2949 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
2950 } else {
2951 tmp = tcg_temp_new_i32();
2952 gen_helper_vfp_get_fpscr(tmp, cpu_env);
2954 break;
2955 case ARM_VFP_MVFR0:
2956 case ARM_VFP_MVFR1:
2957 if (IS_USER(s)
2958 || !arm_feature(env, ARM_FEATURE_MVFR))
2959 return 1;
2960 tmp = load_cpu_field(vfp.xregs[rn]);
2961 break;
2962 default:
2963 return 1;
2965 } else {
2966 gen_mov_F0_vreg(0, rn);
2967 tmp = gen_vfp_mrs();
2969 if (rd == 15) {
2970 /* Set the 4 flag bits in the CPSR. */
2971 gen_set_nzcv(tmp);
2972 tcg_temp_free_i32(tmp);
2973 } else {
2974 store_reg(s, rd, tmp);
2976 } else {
2977 /* arm->vfp */
2978 if (insn & (1 << 21)) {
2979 rn >>= 1;
2980 /* system register */
2981 switch (rn) {
2982 case ARM_VFP_FPSID:
2983 case ARM_VFP_MVFR0:
2984 case ARM_VFP_MVFR1:
2985 /* Writes are ignored. */
2986 break;
2987 case ARM_VFP_FPSCR:
2988 tmp = load_reg(s, rd);
2989 gen_helper_vfp_set_fpscr(cpu_env, tmp);
2990 tcg_temp_free_i32(tmp);
2991 gen_lookup_tb(s);
2992 break;
2993 case ARM_VFP_FPEXC:
2994 if (IS_USER(s))
2995 return 1;
2996 /* TODO: VFP subarchitecture support.
2997 * For now, keep the EN bit only */
2998 tmp = load_reg(s, rd);
2999 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3000 store_cpu_field(tmp, vfp.xregs[rn]);
3001 gen_lookup_tb(s);
3002 break;
3003 case ARM_VFP_FPINST:
3004 case ARM_VFP_FPINST2:
3005 tmp = load_reg(s, rd);
3006 store_cpu_field(tmp, vfp.xregs[rn]);
3007 break;
3008 default:
3009 return 1;
3011 } else {
3012 tmp = load_reg(s, rd);
3013 gen_vfp_msr(tmp);
3014 gen_mov_vreg_F0(0, rn);
3018 } else {
3019 /* data processing */
3020 /* The opcode is in bits 23, 21, 20 and 6. */
3021 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3022 if (dp) {
3023 if (op == 15) {
3024 /* rn is opcode */
3025 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3026 } else {
3027 /* rn is register number */
3028 VFP_DREG_N(rn, insn);
3031 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18))) {
3032 /* Integer or single precision destination. */
3033 rd = VFP_SREG_D(insn);
3034 } else {
3035 VFP_DREG_D(rd, insn);
3037 if (op == 15 &&
3038 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14))) {
3039 /* VCVT from int is always from S reg regardless of dp bit.
3040 * VCVT with immediate frac_bits has same format as SREG_M
3042 rm = VFP_SREG_M(insn);
3043 } else {
3044 VFP_DREG_M(rm, insn);
3046 } else {
3047 rn = VFP_SREG_N(insn);
3048 if (op == 15 && rn == 15) {
3049 /* Double precision destination. */
3050 VFP_DREG_D(rd, insn);
3051 } else {
3052 rd = VFP_SREG_D(insn);
3054 /* NB that we implicitly rely on the encoding for the frac_bits
3055 * in VCVT of fixed to float being the same as that of an SREG_M
3057 rm = VFP_SREG_M(insn);
3060 veclen = s->vec_len;
3061 if (op == 15 && rn > 3)
3062 veclen = 0;
3064 /* Shut up compiler warnings. */
3065 delta_m = 0;
3066 delta_d = 0;
3067 bank_mask = 0;
3069 if (veclen > 0) {
3070 if (dp)
3071 bank_mask = 0xc;
3072 else
3073 bank_mask = 0x18;
3075 /* Figure out what type of vector operation this is. */
3076 if ((rd & bank_mask) == 0) {
3077 /* scalar */
3078 veclen = 0;
3079 } else {
3080 if (dp)
3081 delta_d = (s->vec_stride >> 1) + 1;
3082 else
3083 delta_d = s->vec_stride + 1;
3085 if ((rm & bank_mask) == 0) {
3086 /* mixed scalar/vector */
3087 delta_m = 0;
3088 } else {
3089 /* vector */
3090 delta_m = delta_d;
3095 /* Load the initial operands. */
3096 if (op == 15) {
3097 switch (rn) {
3098 case 16:
3099 case 17:
3100 /* Integer source */
3101 gen_mov_F0_vreg(0, rm);
3102 break;
3103 case 8:
3104 case 9:
3105 /* Compare */
3106 gen_mov_F0_vreg(dp, rd);
3107 gen_mov_F1_vreg(dp, rm);
3108 break;
3109 case 10:
3110 case 11:
3111 /* Compare with zero */
3112 gen_mov_F0_vreg(dp, rd);
3113 gen_vfp_F1_ld0(dp);
3114 break;
3115 case 20:
3116 case 21:
3117 case 22:
3118 case 23:
3119 case 28:
3120 case 29:
3121 case 30:
3122 case 31:
3123 /* Source and destination the same. */
3124 gen_mov_F0_vreg(dp, rd);
3125 break;
3126 case 4:
3127 case 5:
3128 case 6:
3129 case 7:
3130 /* VCVTB, VCVTT: only present with the halfprec extension,
3131 * UNPREDICTABLE if bit 8 is set (we choose to UNDEF)
3133 if (dp || !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3134 return 1;
3136 /* Otherwise fall through */
3137 default:
3138 /* One source operand. */
3139 gen_mov_F0_vreg(dp, rm);
3140 break;
3142 } else {
3143 /* Two source operands. */
3144 gen_mov_F0_vreg(dp, rn);
3145 gen_mov_F1_vreg(dp, rm);
3148 for (;;) {
3149 /* Perform the calculation. */
3150 switch (op) {
3151 case 0: /* VMLA: fd + (fn * fm) */
3152 /* Note that order of inputs to the add matters for NaNs */
3153 gen_vfp_F1_mul(dp);
3154 gen_mov_F0_vreg(dp, rd);
3155 gen_vfp_add(dp);
3156 break;
3157 case 1: /* VMLS: fd + -(fn * fm) */
3158 gen_vfp_mul(dp);
3159 gen_vfp_F1_neg(dp);
3160 gen_mov_F0_vreg(dp, rd);
3161 gen_vfp_add(dp);
3162 break;
3163 case 2: /* VNMLS: -fd + (fn * fm) */
3164 /* Note that it isn't valid to replace (-A + B) with (B - A)
3165 * or similar plausible looking simplifications
3166 * because this will give wrong results for NaNs.
3168 gen_vfp_F1_mul(dp);
3169 gen_mov_F0_vreg(dp, rd);
3170 gen_vfp_neg(dp);
3171 gen_vfp_add(dp);
3172 break;
3173 case 3: /* VNMLA: -fd + -(fn * fm) */
3174 gen_vfp_mul(dp);
3175 gen_vfp_F1_neg(dp);
3176 gen_mov_F0_vreg(dp, rd);
3177 gen_vfp_neg(dp);
3178 gen_vfp_add(dp);
3179 break;
3180 case 4: /* mul: fn * fm */
3181 gen_vfp_mul(dp);
3182 break;
3183 case 5: /* nmul: -(fn * fm) */
3184 gen_vfp_mul(dp);
3185 gen_vfp_neg(dp);
3186 break;
3187 case 6: /* add: fn + fm */
3188 gen_vfp_add(dp);
3189 break;
3190 case 7: /* sub: fn - fm */
3191 gen_vfp_sub(dp);
3192 break;
3193 case 8: /* div: fn / fm */
3194 gen_vfp_div(dp);
3195 break;
3196 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3197 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3198 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3199 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3200 /* These are fused multiply-add, and must be done as one
3201 * floating point operation with no rounding between the
3202 * multiplication and addition steps.
3203 * NB that doing the negations here as separate steps is
3204 * correct : an input NaN should come out with its sign bit
3205 * flipped if it is a negated-input.
3207 if (!arm_feature(env, ARM_FEATURE_VFP4)) {
3208 return 1;
3210 if (dp) {
3211 TCGv_ptr fpst;
3212 TCGv_i64 frd;
3213 if (op & 1) {
3214 /* VFNMS, VFMS */
3215 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3217 frd = tcg_temp_new_i64();
3218 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3219 if (op & 2) {
3220 /* VFNMA, VFNMS */
3221 gen_helper_vfp_negd(frd, frd);
3223 fpst = get_fpstatus_ptr(0);
3224 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3225 cpu_F1d, frd, fpst);
3226 tcg_temp_free_ptr(fpst);
3227 tcg_temp_free_i64(frd);
3228 } else {
3229 TCGv_ptr fpst;
3230 TCGv_i32 frd;
3231 if (op & 1) {
3232 /* VFNMS, VFMS */
3233 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3235 frd = tcg_temp_new_i32();
3236 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3237 if (op & 2) {
3238 gen_helper_vfp_negs(frd, frd);
3240 fpst = get_fpstatus_ptr(0);
3241 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3242 cpu_F1s, frd, fpst);
3243 tcg_temp_free_ptr(fpst);
3244 tcg_temp_free_i32(frd);
3246 break;
3247 case 14: /* fconst */
3248 if (!arm_feature(env, ARM_FEATURE_VFP3))
3249 return 1;
3251 n = (insn << 12) & 0x80000000;
3252 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3253 if (dp) {
3254 if (i & 0x40)
3255 i |= 0x3f80;
3256 else
3257 i |= 0x4000;
3258 n |= i << 16;
3259 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3260 } else {
3261 if (i & 0x40)
3262 i |= 0x780;
3263 else
3264 i |= 0x800;
3265 n |= i << 19;
3266 tcg_gen_movi_i32(cpu_F0s, n);
3268 break;
3269 case 15: /* extension space */
3270 switch (rn) {
3271 case 0: /* cpy */
3272 /* no-op */
3273 break;
3274 case 1: /* abs */
3275 gen_vfp_abs(dp);
3276 break;
3277 case 2: /* neg */
3278 gen_vfp_neg(dp);
3279 break;
3280 case 3: /* sqrt */
3281 gen_vfp_sqrt(dp);
3282 break;
3283 case 4: /* vcvtb.f32.f16 */
3284 tmp = gen_vfp_mrs();
3285 tcg_gen_ext16u_i32(tmp, tmp);
3286 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3287 tcg_temp_free_i32(tmp);
3288 break;
3289 case 5: /* vcvtt.f32.f16 */
3290 tmp = gen_vfp_mrs();
3291 tcg_gen_shri_i32(tmp, tmp, 16);
3292 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp, cpu_env);
3293 tcg_temp_free_i32(tmp);
3294 break;
3295 case 6: /* vcvtb.f16.f32 */
3296 tmp = tcg_temp_new_i32();
3297 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3298 gen_mov_F0_vreg(0, rd);
3299 tmp2 = gen_vfp_mrs();
3300 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3301 tcg_gen_or_i32(tmp, tmp, tmp2);
3302 tcg_temp_free_i32(tmp2);
3303 gen_vfp_msr(tmp);
3304 break;
3305 case 7: /* vcvtt.f16.f32 */
3306 tmp = tcg_temp_new_i32();
3307 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
3308 tcg_gen_shli_i32(tmp, tmp, 16);
3309 gen_mov_F0_vreg(0, rd);
3310 tmp2 = gen_vfp_mrs();
3311 tcg_gen_ext16u_i32(tmp2, tmp2);
3312 tcg_gen_or_i32(tmp, tmp, tmp2);
3313 tcg_temp_free_i32(tmp2);
3314 gen_vfp_msr(tmp);
3315 break;
3316 case 8: /* cmp */
3317 gen_vfp_cmp(dp);
3318 break;
3319 case 9: /* cmpe */
3320 gen_vfp_cmpe(dp);
3321 break;
3322 case 10: /* cmpz */
3323 gen_vfp_cmp(dp);
3324 break;
3325 case 11: /* cmpez */
3326 gen_vfp_F1_ld0(dp);
3327 gen_vfp_cmpe(dp);
3328 break;
3329 case 15: /* single<->double conversion */
3330 if (dp)
3331 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3332 else
3333 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3334 break;
3335 case 16: /* fuito */
3336 gen_vfp_uito(dp, 0);
3337 break;
3338 case 17: /* fsito */
3339 gen_vfp_sito(dp, 0);
3340 break;
3341 case 20: /* fshto */
3342 if (!arm_feature(env, ARM_FEATURE_VFP3))
3343 return 1;
3344 gen_vfp_shto(dp, 16 - rm, 0);
3345 break;
3346 case 21: /* fslto */
3347 if (!arm_feature(env, ARM_FEATURE_VFP3))
3348 return 1;
3349 gen_vfp_slto(dp, 32 - rm, 0);
3350 break;
3351 case 22: /* fuhto */
3352 if (!arm_feature(env, ARM_FEATURE_VFP3))
3353 return 1;
3354 gen_vfp_uhto(dp, 16 - rm, 0);
3355 break;
3356 case 23: /* fulto */
3357 if (!arm_feature(env, ARM_FEATURE_VFP3))
3358 return 1;
3359 gen_vfp_ulto(dp, 32 - rm, 0);
3360 break;
3361 case 24: /* ftoui */
3362 gen_vfp_toui(dp, 0);
3363 break;
3364 case 25: /* ftouiz */
3365 gen_vfp_touiz(dp, 0);
3366 break;
3367 case 26: /* ftosi */
3368 gen_vfp_tosi(dp, 0);
3369 break;
3370 case 27: /* ftosiz */
3371 gen_vfp_tosiz(dp, 0);
3372 break;
3373 case 28: /* ftosh */
3374 if (!arm_feature(env, ARM_FEATURE_VFP3))
3375 return 1;
3376 gen_vfp_tosh(dp, 16 - rm, 0);
3377 break;
3378 case 29: /* ftosl */
3379 if (!arm_feature(env, ARM_FEATURE_VFP3))
3380 return 1;
3381 gen_vfp_tosl(dp, 32 - rm, 0);
3382 break;
3383 case 30: /* ftouh */
3384 if (!arm_feature(env, ARM_FEATURE_VFP3))
3385 return 1;
3386 gen_vfp_touh(dp, 16 - rm, 0);
3387 break;
3388 case 31: /* ftoul */
3389 if (!arm_feature(env, ARM_FEATURE_VFP3))
3390 return 1;
3391 gen_vfp_toul(dp, 32 - rm, 0);
3392 break;
3393 default: /* undefined */
3394 return 1;
3396 break;
3397 default: /* undefined */
3398 return 1;
3401 /* Write back the result. */
3402 if (op == 15 && (rn >= 8 && rn <= 11))
3403 ; /* Comparison, do nothing. */
3404 else if (op == 15 && dp && ((rn & 0x1c) == 0x18))
3405 /* VCVT double to int: always integer result. */
3406 gen_mov_vreg_F0(0, rd);
3407 else if (op == 15 && rn == 15)
3408 /* conversion */
3409 gen_mov_vreg_F0(!dp, rd);
3410 else
3411 gen_mov_vreg_F0(dp, rd);
3413 /* break out of the loop if we have finished */
3414 if (veclen == 0)
3415 break;
3417 if (op == 15 && delta_m == 0) {
3418 /* single source one-many */
3419 while (veclen--) {
3420 rd = ((rd + delta_d) & (bank_mask - 1))
3421 | (rd & bank_mask);
3422 gen_mov_vreg_F0(dp, rd);
3424 break;
3426 /* Setup the next operands. */
3427 veclen--;
3428 rd = ((rd + delta_d) & (bank_mask - 1))
3429 | (rd & bank_mask);
3431 if (op == 15) {
3432 /* One source operand. */
3433 rm = ((rm + delta_m) & (bank_mask - 1))
3434 | (rm & bank_mask);
3435 gen_mov_F0_vreg(dp, rm);
3436 } else {
3437 /* Two source operands. */
3438 rn = ((rn + delta_d) & (bank_mask - 1))
3439 | (rn & bank_mask);
3440 gen_mov_F0_vreg(dp, rn);
3441 if (delta_m) {
3442 rm = ((rm + delta_m) & (bank_mask - 1))
3443 | (rm & bank_mask);
3444 gen_mov_F1_vreg(dp, rm);
3449 break;
3450 case 0xc:
3451 case 0xd:
3452 if ((insn & 0x03e00000) == 0x00400000) {
3453 /* two-register transfer */
3454 rn = (insn >> 16) & 0xf;
3455 rd = (insn >> 12) & 0xf;
3456 if (dp) {
3457 VFP_DREG_M(rm, insn);
3458 } else {
3459 rm = VFP_SREG_M(insn);
3462 if (insn & ARM_CP_RW_BIT) {
3463 /* vfp->arm */
3464 if (dp) {
3465 gen_mov_F0_vreg(0, rm * 2);
3466 tmp = gen_vfp_mrs();
3467 store_reg(s, rd, tmp);
3468 gen_mov_F0_vreg(0, rm * 2 + 1);
3469 tmp = gen_vfp_mrs();
3470 store_reg(s, rn, tmp);
3471 } else {
3472 gen_mov_F0_vreg(0, rm);
3473 tmp = gen_vfp_mrs();
3474 store_reg(s, rd, tmp);
3475 gen_mov_F0_vreg(0, rm + 1);
3476 tmp = gen_vfp_mrs();
3477 store_reg(s, rn, tmp);
3479 } else {
3480 /* arm->vfp */
3481 if (dp) {
3482 tmp = load_reg(s, rd);
3483 gen_vfp_msr(tmp);
3484 gen_mov_vreg_F0(0, rm * 2);
3485 tmp = load_reg(s, rn);
3486 gen_vfp_msr(tmp);
3487 gen_mov_vreg_F0(0, rm * 2 + 1);
3488 } else {
3489 tmp = load_reg(s, rd);
3490 gen_vfp_msr(tmp);
3491 gen_mov_vreg_F0(0, rm);
3492 tmp = load_reg(s, rn);
3493 gen_vfp_msr(tmp);
3494 gen_mov_vreg_F0(0, rm + 1);
3497 } else {
3498 /* Load/store */
3499 rn = (insn >> 16) & 0xf;
3500 if (dp)
3501 VFP_DREG_D(rd, insn);
3502 else
3503 rd = VFP_SREG_D(insn);
3504 if ((insn & 0x01200000) == 0x01000000) {
3505 /* Single load/store */
3506 offset = (insn & 0xff) << 2;
3507 if ((insn & (1 << 23)) == 0)
3508 offset = -offset;
3509 if (s->thumb && rn == 15) {
3510 /* This is actually UNPREDICTABLE */
3511 addr = tcg_temp_new_i32();
3512 tcg_gen_movi_i32(addr, s->pc & ~2);
3513 } else {
3514 addr = load_reg(s, rn);
3516 tcg_gen_addi_i32(addr, addr, offset);
3517 if (insn & (1 << 20)) {
3518 gen_vfp_ld(s, dp, addr);
3519 gen_mov_vreg_F0(dp, rd);
3520 } else {
3521 gen_mov_F0_vreg(dp, rd);
3522 gen_vfp_st(s, dp, addr);
3524 tcg_temp_free_i32(addr);
3525 } else {
3526 /* load/store multiple */
3527 int w = insn & (1 << 21);
3528 if (dp)
3529 n = (insn >> 1) & 0x7f;
3530 else
3531 n = insn & 0xff;
3533 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3534 /* P == U , W == 1 => UNDEF */
3535 return 1;
3537 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3538 /* UNPREDICTABLE cases for bad immediates: we choose to
3539 * UNDEF to avoid generating huge numbers of TCG ops
3541 return 1;
3543 if (rn == 15 && w) {
3544 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3545 return 1;
3548 if (s->thumb && rn == 15) {
3549 /* This is actually UNPREDICTABLE */
3550 addr = tcg_temp_new_i32();
3551 tcg_gen_movi_i32(addr, s->pc & ~2);
3552 } else {
3553 addr = load_reg(s, rn);
3555 if (insn & (1 << 24)) /* pre-decrement */
3556 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3558 if (dp)
3559 offset = 8;
3560 else
3561 offset = 4;
3562 for (i = 0; i < n; i++) {
3563 if (insn & ARM_CP_RW_BIT) {
3564 /* load */
3565 gen_vfp_ld(s, dp, addr);
3566 gen_mov_vreg_F0(dp, rd + i);
3567 } else {
3568 /* store */
3569 gen_mov_F0_vreg(dp, rd + i);
3570 gen_vfp_st(s, dp, addr);
3572 tcg_gen_addi_i32(addr, addr, offset);
3574 if (w) {
3575 /* writeback */
3576 if (insn & (1 << 24))
3577 offset = -offset * n;
3578 else if (dp && (insn & 1))
3579 offset = 4;
3580 else
3581 offset = 0;
3583 if (offset != 0)
3584 tcg_gen_addi_i32(addr, addr, offset);
3585 store_reg(s, rn, addr);
3586 } else {
3587 tcg_temp_free_i32(addr);
3591 break;
3592 default:
3593 /* Should never happen. */
3594 return 1;
3596 return 0;
3599 static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
3601 TranslationBlock *tb;
3603 tb = s->tb;
3604 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3605 tcg_gen_goto_tb(n);
3606 gen_set_pc_im(s, dest);
3607 tcg_gen_exit_tb((uintptr_t)tb + n);
3608 } else {
3609 gen_set_pc_im(s, dest);
3610 tcg_gen_exit_tb(0);
3614 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3616 if (unlikely(s->singlestep_enabled)) {
3617 /* An indirect jump so that we still trigger the debug exception. */
3618 if (s->thumb)
3619 dest |= 1;
3620 gen_bx_im(s, dest);
3621 } else {
3622 gen_goto_tb(s, 0, dest);
3623 s->is_jmp = DISAS_TB_JUMP;
3627 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
3629 if (x)
3630 tcg_gen_sari_i32(t0, t0, 16);
3631 else
3632 gen_sxth(t0);
3633 if (y)
3634 tcg_gen_sari_i32(t1, t1, 16);
3635 else
3636 gen_sxth(t1);
3637 tcg_gen_mul_i32(t0, t0, t1);
3640 /* Return the mask of PSR bits set by a MSR instruction. */
3641 static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
3642 uint32_t mask;
3644 mask = 0;
3645 if (flags & (1 << 0))
3646 mask |= 0xff;
3647 if (flags & (1 << 1))
3648 mask |= 0xff00;
3649 if (flags & (1 << 2))
3650 mask |= 0xff0000;
3651 if (flags & (1 << 3))
3652 mask |= 0xff000000;
3654 /* Mask out undefined bits. */
3655 mask &= ~CPSR_RESERVED;
3656 if (!arm_feature(env, ARM_FEATURE_V4T))
3657 mask &= ~CPSR_T;
3658 if (!arm_feature(env, ARM_FEATURE_V5))
3659 mask &= ~CPSR_Q; /* V5TE in reality*/
3660 if (!arm_feature(env, ARM_FEATURE_V6))
3661 mask &= ~(CPSR_E | CPSR_GE);
3662 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3663 mask &= ~CPSR_IT;
3664 /* Mask out execution state bits. */
3665 if (!spsr)
3666 mask &= ~CPSR_EXEC;
3667 /* Mask out privileged bits. */
3668 if (IS_USER(s))
3669 mask &= CPSR_USER;
3670 return mask;
3673 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3674 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
3676 TCGv_i32 tmp;
3677 if (spsr) {
3678 /* ??? This is also undefined in system mode. */
3679 if (IS_USER(s))
3680 return 1;
3682 tmp = load_cpu_field(spsr);
3683 tcg_gen_andi_i32(tmp, tmp, ~mask);
3684 tcg_gen_andi_i32(t0, t0, mask);
3685 tcg_gen_or_i32(tmp, tmp, t0);
3686 store_cpu_field(tmp, spsr);
3687 } else {
3688 gen_set_cpsr(t0, mask);
3690 tcg_temp_free_i32(t0);
3691 gen_lookup_tb(s);
3692 return 0;
3695 /* Returns nonzero if access to the PSR is not permitted. */
3696 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3698 TCGv_i32 tmp;
3699 tmp = tcg_temp_new_i32();
3700 tcg_gen_movi_i32(tmp, val);
3701 return gen_set_psr(s, mask, spsr, tmp);
3704 /* Generate an old-style exception return. Marks pc as dead. */
3705 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3707 TCGv_i32 tmp;
3708 store_reg(s, 15, pc);
3709 tmp = load_cpu_field(spsr);
3710 gen_set_cpsr(tmp, 0xffffffff);
3711 tcg_temp_free_i32(tmp);
3712 s->is_jmp = DISAS_UPDATE;
3715 /* Generate a v6 exception return. Marks both values as dead. */
3716 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
3718 gen_set_cpsr(cpsr, 0xffffffff);
3719 tcg_temp_free_i32(cpsr);
3720 store_reg(s, 15, pc);
3721 s->is_jmp = DISAS_UPDATE;
3724 static inline void
3725 gen_set_condexec (DisasContext *s)
3727 if (s->condexec_mask) {
3728 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
3729 TCGv_i32 tmp = tcg_temp_new_i32();
3730 tcg_gen_movi_i32(tmp, val);
3731 store_cpu_field(tmp, condexec_bits);
3735 static void gen_exception_insn(DisasContext *s, int offset, int excp)
3737 gen_set_condexec(s);
3738 gen_set_pc_im(s, s->pc - offset);
3739 gen_exception(excp);
3740 s->is_jmp = DISAS_JUMP;
3743 static void gen_nop_hint(DisasContext *s, int val)
3745 switch (val) {
3746 case 3: /* wfi */
3747 gen_set_pc_im(s, s->pc);
3748 s->is_jmp = DISAS_WFI;
3749 break;
3750 case 2: /* wfe */
3751 case 4: /* sev */
3752 case 5: /* sevl */
3753 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
3754 default: /* nop */
3755 break;
3759 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
3761 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
3763 switch (size) {
3764 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
3765 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
3766 case 2: tcg_gen_add_i32(t0, t0, t1); break;
3767 default: abort();
3771 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
3773 switch (size) {
3774 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
3775 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
3776 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
3777 default: return;
3781 /* 32-bit pairwise ops end up the same as the elementwise versions. */
3782 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
3783 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
3784 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
3785 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
3787 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
3788 switch ((size << 1) | u) { \
3789 case 0: \
3790 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
3791 break; \
3792 case 1: \
3793 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
3794 break; \
3795 case 2: \
3796 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
3797 break; \
3798 case 3: \
3799 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
3800 break; \
3801 case 4: \
3802 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
3803 break; \
3804 case 5: \
3805 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
3806 break; \
3807 default: return 1; \
3808 }} while (0)
3810 #define GEN_NEON_INTEGER_OP(name) do { \
3811 switch ((size << 1) | u) { \
3812 case 0: \
3813 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
3814 break; \
3815 case 1: \
3816 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
3817 break; \
3818 case 2: \
3819 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
3820 break; \
3821 case 3: \
3822 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
3823 break; \
3824 case 4: \
3825 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
3826 break; \
3827 case 5: \
3828 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
3829 break; \
3830 default: return 1; \
3831 }} while (0)
3833 static TCGv_i32 neon_load_scratch(int scratch)
3835 TCGv_i32 tmp = tcg_temp_new_i32();
3836 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3837 return tmp;
3840 static void neon_store_scratch(int scratch, TCGv_i32 var)
3842 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
3843 tcg_temp_free_i32(var);
3846 static inline TCGv_i32 neon_get_scalar(int size, int reg)
3848 TCGv_i32 tmp;
3849 if (size == 1) {
3850 tmp = neon_load_reg(reg & 7, reg >> 4);
3851 if (reg & 8) {
3852 gen_neon_dup_high16(tmp);
3853 } else {
3854 gen_neon_dup_low16(tmp);
3856 } else {
3857 tmp = neon_load_reg(reg & 15, reg >> 4);
3859 return tmp;
3862 static int gen_neon_unzip(int rd, int rm, int size, int q)
3864 TCGv_i32 tmp, tmp2;
3865 if (!q && size == 2) {
3866 return 1;
3868 tmp = tcg_const_i32(rd);
3869 tmp2 = tcg_const_i32(rm);
3870 if (q) {
3871 switch (size) {
3872 case 0:
3873 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
3874 break;
3875 case 1:
3876 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
3877 break;
3878 case 2:
3879 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
3880 break;
3881 default:
3882 abort();
3884 } else {
3885 switch (size) {
3886 case 0:
3887 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
3888 break;
3889 case 1:
3890 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
3891 break;
3892 default:
3893 abort();
3896 tcg_temp_free_i32(tmp);
3897 tcg_temp_free_i32(tmp2);
3898 return 0;
3901 static int gen_neon_zip(int rd, int rm, int size, int q)
3903 TCGv_i32 tmp, tmp2;
3904 if (!q && size == 2) {
3905 return 1;
3907 tmp = tcg_const_i32(rd);
3908 tmp2 = tcg_const_i32(rm);
3909 if (q) {
3910 switch (size) {
3911 case 0:
3912 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
3913 break;
3914 case 1:
3915 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
3916 break;
3917 case 2:
3918 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
3919 break;
3920 default:
3921 abort();
3923 } else {
3924 switch (size) {
3925 case 0:
3926 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
3927 break;
3928 case 1:
3929 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
3930 break;
3931 default:
3932 abort();
3935 tcg_temp_free_i32(tmp);
3936 tcg_temp_free_i32(tmp2);
3937 return 0;
3940 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
3942 TCGv_i32 rd, tmp;
3944 rd = tcg_temp_new_i32();
3945 tmp = tcg_temp_new_i32();
3947 tcg_gen_shli_i32(rd, t0, 8);
3948 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
3949 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
3950 tcg_gen_or_i32(rd, rd, tmp);
3952 tcg_gen_shri_i32(t1, t1, 8);
3953 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
3954 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
3955 tcg_gen_or_i32(t1, t1, tmp);
3956 tcg_gen_mov_i32(t0, rd);
3958 tcg_temp_free_i32(tmp);
3959 tcg_temp_free_i32(rd);
3962 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
3964 TCGv_i32 rd, tmp;
3966 rd = tcg_temp_new_i32();
3967 tmp = tcg_temp_new_i32();
3969 tcg_gen_shli_i32(rd, t0, 16);
3970 tcg_gen_andi_i32(tmp, t1, 0xffff);
3971 tcg_gen_or_i32(rd, rd, tmp);
3972 tcg_gen_shri_i32(t1, t1, 16);
3973 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
3974 tcg_gen_or_i32(t1, t1, tmp);
3975 tcg_gen_mov_i32(t0, rd);
3977 tcg_temp_free_i32(tmp);
3978 tcg_temp_free_i32(rd);
3982 static struct {
3983 int nregs;
3984 int interleave;
3985 int spacing;
3986 } neon_ls_element_type[11] = {
3987 {4, 4, 1},
3988 {4, 4, 2},
3989 {4, 1, 1},
3990 {4, 2, 1},
3991 {3, 3, 1},
3992 {3, 3, 2},
3993 {3, 1, 1},
3994 {1, 1, 1},
3995 {2, 2, 1},
3996 {2, 2, 2},
3997 {2, 1, 1}
4000 /* Translate a NEON load/store element instruction. Return nonzero if the
4001 instruction is invalid. */
4002 static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4004 int rd, rn, rm;
4005 int op;
4006 int nregs;
4007 int interleave;
4008 int spacing;
4009 int stride;
4010 int size;
4011 int reg;
4012 int pass;
4013 int load;
4014 int shift;
4015 int n;
4016 TCGv_i32 addr;
4017 TCGv_i32 tmp;
4018 TCGv_i32 tmp2;
4019 TCGv_i64 tmp64;
4021 if (!s->vfp_enabled)
4022 return 1;
4023 VFP_DREG_D(rd, insn);
4024 rn = (insn >> 16) & 0xf;
4025 rm = insn & 0xf;
4026 load = (insn & (1 << 21)) != 0;
4027 if ((insn & (1 << 23)) == 0) {
4028 /* Load store all elements. */
4029 op = (insn >> 8) & 0xf;
4030 size = (insn >> 6) & 3;
4031 if (op > 10)
4032 return 1;
4033 /* Catch UNDEF cases for bad values of align field */
4034 switch (op & 0xc) {
4035 case 4:
4036 if (((insn >> 5) & 1) == 1) {
4037 return 1;
4039 break;
4040 case 8:
4041 if (((insn >> 4) & 3) == 3) {
4042 return 1;
4044 break;
4045 default:
4046 break;
4048 nregs = neon_ls_element_type[op].nregs;
4049 interleave = neon_ls_element_type[op].interleave;
4050 spacing = neon_ls_element_type[op].spacing;
4051 if (size == 3 && (interleave | spacing) != 1)
4052 return 1;
4053 addr = tcg_temp_new_i32();
4054 load_reg_var(s, addr, rn);
4055 stride = (1 << size) * interleave;
4056 for (reg = 0; reg < nregs; reg++) {
4057 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
4058 load_reg_var(s, addr, rn);
4059 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
4060 } else if (interleave == 2 && nregs == 4 && reg == 2) {
4061 load_reg_var(s, addr, rn);
4062 tcg_gen_addi_i32(addr, addr, 1 << size);
4064 if (size == 3) {
4065 tmp64 = tcg_temp_new_i64();
4066 if (load) {
4067 gen_aa32_ld64(tmp64, addr, IS_USER(s));
4068 neon_store_reg64(tmp64, rd);
4069 } else {
4070 neon_load_reg64(tmp64, rd);
4071 gen_aa32_st64(tmp64, addr, IS_USER(s));
4073 tcg_temp_free_i64(tmp64);
4074 tcg_gen_addi_i32(addr, addr, stride);
4075 } else {
4076 for (pass = 0; pass < 2; pass++) {
4077 if (size == 2) {
4078 if (load) {
4079 tmp = tcg_temp_new_i32();
4080 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4081 neon_store_reg(rd, pass, tmp);
4082 } else {
4083 tmp = neon_load_reg(rd, pass);
4084 gen_aa32_st32(tmp, addr, IS_USER(s));
4085 tcg_temp_free_i32(tmp);
4087 tcg_gen_addi_i32(addr, addr, stride);
4088 } else if (size == 1) {
4089 if (load) {
4090 tmp = tcg_temp_new_i32();
4091 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4092 tcg_gen_addi_i32(addr, addr, stride);
4093 tmp2 = tcg_temp_new_i32();
4094 gen_aa32_ld16u(tmp2, addr, IS_USER(s));
4095 tcg_gen_addi_i32(addr, addr, stride);
4096 tcg_gen_shli_i32(tmp2, tmp2, 16);
4097 tcg_gen_or_i32(tmp, tmp, tmp2);
4098 tcg_temp_free_i32(tmp2);
4099 neon_store_reg(rd, pass, tmp);
4100 } else {
4101 tmp = neon_load_reg(rd, pass);
4102 tmp2 = tcg_temp_new_i32();
4103 tcg_gen_shri_i32(tmp2, tmp, 16);
4104 gen_aa32_st16(tmp, addr, IS_USER(s));
4105 tcg_temp_free_i32(tmp);
4106 tcg_gen_addi_i32(addr, addr, stride);
4107 gen_aa32_st16(tmp2, addr, IS_USER(s));
4108 tcg_temp_free_i32(tmp2);
4109 tcg_gen_addi_i32(addr, addr, stride);
4111 } else /* size == 0 */ {
4112 if (load) {
4113 TCGV_UNUSED_I32(tmp2);
4114 for (n = 0; n < 4; n++) {
4115 tmp = tcg_temp_new_i32();
4116 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4117 tcg_gen_addi_i32(addr, addr, stride);
4118 if (n == 0) {
4119 tmp2 = tmp;
4120 } else {
4121 tcg_gen_shli_i32(tmp, tmp, n * 8);
4122 tcg_gen_or_i32(tmp2, tmp2, tmp);
4123 tcg_temp_free_i32(tmp);
4126 neon_store_reg(rd, pass, tmp2);
4127 } else {
4128 tmp2 = neon_load_reg(rd, pass);
4129 for (n = 0; n < 4; n++) {
4130 tmp = tcg_temp_new_i32();
4131 if (n == 0) {
4132 tcg_gen_mov_i32(tmp, tmp2);
4133 } else {
4134 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4136 gen_aa32_st8(tmp, addr, IS_USER(s));
4137 tcg_temp_free_i32(tmp);
4138 tcg_gen_addi_i32(addr, addr, stride);
4140 tcg_temp_free_i32(tmp2);
4145 rd += spacing;
4147 tcg_temp_free_i32(addr);
4148 stride = nregs * 8;
4149 } else {
4150 size = (insn >> 10) & 3;
4151 if (size == 3) {
4152 /* Load single element to all lanes. */
4153 int a = (insn >> 4) & 1;
4154 if (!load) {
4155 return 1;
4157 size = (insn >> 6) & 3;
4158 nregs = ((insn >> 8) & 3) + 1;
4160 if (size == 3) {
4161 if (nregs != 4 || a == 0) {
4162 return 1;
4164 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4165 size = 2;
4167 if (nregs == 1 && a == 1 && size == 0) {
4168 return 1;
4170 if (nregs == 3 && a == 1) {
4171 return 1;
4173 addr = tcg_temp_new_i32();
4174 load_reg_var(s, addr, rn);
4175 if (nregs == 1) {
4176 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4177 tmp = gen_load_and_replicate(s, addr, size);
4178 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4179 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4180 if (insn & (1 << 5)) {
4181 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4182 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4184 tcg_temp_free_i32(tmp);
4185 } else {
4186 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4187 stride = (insn & (1 << 5)) ? 2 : 1;
4188 for (reg = 0; reg < nregs; reg++) {
4189 tmp = gen_load_and_replicate(s, addr, size);
4190 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4191 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4192 tcg_temp_free_i32(tmp);
4193 tcg_gen_addi_i32(addr, addr, 1 << size);
4194 rd += stride;
4197 tcg_temp_free_i32(addr);
4198 stride = (1 << size) * nregs;
4199 } else {
4200 /* Single element. */
4201 int idx = (insn >> 4) & 0xf;
4202 pass = (insn >> 7) & 1;
4203 switch (size) {
4204 case 0:
4205 shift = ((insn >> 5) & 3) * 8;
4206 stride = 1;
4207 break;
4208 case 1:
4209 shift = ((insn >> 6) & 1) * 16;
4210 stride = (insn & (1 << 5)) ? 2 : 1;
4211 break;
4212 case 2:
4213 shift = 0;
4214 stride = (insn & (1 << 6)) ? 2 : 1;
4215 break;
4216 default:
4217 abort();
4219 nregs = ((insn >> 8) & 3) + 1;
4220 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4221 switch (nregs) {
4222 case 1:
4223 if (((idx & (1 << size)) != 0) ||
4224 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4225 return 1;
4227 break;
4228 case 3:
4229 if ((idx & 1) != 0) {
4230 return 1;
4232 /* fall through */
4233 case 2:
4234 if (size == 2 && (idx & 2) != 0) {
4235 return 1;
4237 break;
4238 case 4:
4239 if ((size == 2) && ((idx & 3) == 3)) {
4240 return 1;
4242 break;
4243 default:
4244 abort();
4246 if ((rd + stride * (nregs - 1)) > 31) {
4247 /* Attempts to write off the end of the register file
4248 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4249 * the neon_load_reg() would write off the end of the array.
4251 return 1;
4253 addr = tcg_temp_new_i32();
4254 load_reg_var(s, addr, rn);
4255 for (reg = 0; reg < nregs; reg++) {
4256 if (load) {
4257 tmp = tcg_temp_new_i32();
4258 switch (size) {
4259 case 0:
4260 gen_aa32_ld8u(tmp, addr, IS_USER(s));
4261 break;
4262 case 1:
4263 gen_aa32_ld16u(tmp, addr, IS_USER(s));
4264 break;
4265 case 2:
4266 gen_aa32_ld32u(tmp, addr, IS_USER(s));
4267 break;
4268 default: /* Avoid compiler warnings. */
4269 abort();
4271 if (size != 2) {
4272 tmp2 = neon_load_reg(rd, pass);
4273 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4274 shift, size ? 16 : 8);
4275 tcg_temp_free_i32(tmp2);
4277 neon_store_reg(rd, pass, tmp);
4278 } else { /* Store */
4279 tmp = neon_load_reg(rd, pass);
4280 if (shift)
4281 tcg_gen_shri_i32(tmp, tmp, shift);
4282 switch (size) {
4283 case 0:
4284 gen_aa32_st8(tmp, addr, IS_USER(s));
4285 break;
4286 case 1:
4287 gen_aa32_st16(tmp, addr, IS_USER(s));
4288 break;
4289 case 2:
4290 gen_aa32_st32(tmp, addr, IS_USER(s));
4291 break;
4293 tcg_temp_free_i32(tmp);
4295 rd += stride;
4296 tcg_gen_addi_i32(addr, addr, 1 << size);
4298 tcg_temp_free_i32(addr);
4299 stride = nregs * (1 << size);
4302 if (rm != 15) {
4303 TCGv_i32 base;
4305 base = load_reg(s, rn);
4306 if (rm == 13) {
4307 tcg_gen_addi_i32(base, base, stride);
4308 } else {
4309 TCGv_i32 index;
4310 index = load_reg(s, rm);
4311 tcg_gen_add_i32(base, base, index);
4312 tcg_temp_free_i32(index);
4314 store_reg(s, rn, base);
4316 return 0;
4319 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4320 static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
4322 tcg_gen_and_i32(t, t, c);
4323 tcg_gen_andc_i32(f, f, c);
4324 tcg_gen_or_i32(dest, t, f);
4327 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4329 switch (size) {
4330 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4331 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4332 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4333 default: abort();
4337 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4339 switch (size) {
4340 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4341 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4342 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4343 default: abort();
4347 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
4349 switch (size) {
4350 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4351 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4352 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4353 default: abort();
4357 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4359 switch (size) {
4360 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4361 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4362 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4363 default: abort();
4367 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
4368 int q, int u)
4370 if (q) {
4371 if (u) {
4372 switch (size) {
4373 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4374 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4375 default: abort();
4377 } else {
4378 switch (size) {
4379 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4380 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4381 default: abort();
4384 } else {
4385 if (u) {
4386 switch (size) {
4387 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4388 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4389 default: abort();
4391 } else {
4392 switch (size) {
4393 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4394 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4395 default: abort();
4401 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
4403 if (u) {
4404 switch (size) {
4405 case 0: gen_helper_neon_widen_u8(dest, src); break;
4406 case 1: gen_helper_neon_widen_u16(dest, src); break;
4407 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4408 default: abort();
4410 } else {
4411 switch (size) {
4412 case 0: gen_helper_neon_widen_s8(dest, src); break;
4413 case 1: gen_helper_neon_widen_s16(dest, src); break;
4414 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4415 default: abort();
4418 tcg_temp_free_i32(src);
4421 static inline void gen_neon_addl(int size)
4423 switch (size) {
4424 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4425 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4426 case 2: tcg_gen_add_i64(CPU_V001); break;
4427 default: abort();
4431 static inline void gen_neon_subl(int size)
4433 switch (size) {
4434 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4435 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4436 case 2: tcg_gen_sub_i64(CPU_V001); break;
4437 default: abort();
4441 static inline void gen_neon_negl(TCGv_i64 var, int size)
4443 switch (size) {
4444 case 0: gen_helper_neon_negl_u16(var, var); break;
4445 case 1: gen_helper_neon_negl_u32(var, var); break;
4446 case 2:
4447 tcg_gen_neg_i64(var, var);
4448 break;
4449 default: abort();
4453 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4455 switch (size) {
4456 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4457 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4458 default: abort();
4462 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4463 int size, int u)
4465 TCGv_i64 tmp;
4467 switch ((size << 1) | u) {
4468 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4469 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4470 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4471 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4472 case 4:
4473 tmp = gen_muls_i64_i32(a, b);
4474 tcg_gen_mov_i64(dest, tmp);
4475 tcg_temp_free_i64(tmp);
4476 break;
4477 case 5:
4478 tmp = gen_mulu_i64_i32(a, b);
4479 tcg_gen_mov_i64(dest, tmp);
4480 tcg_temp_free_i64(tmp);
4481 break;
4482 default: abort();
4485 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4486 Don't forget to clean them now. */
4487 if (size < 2) {
4488 tcg_temp_free_i32(a);
4489 tcg_temp_free_i32(b);
4493 static void gen_neon_narrow_op(int op, int u, int size,
4494 TCGv_i32 dest, TCGv_i64 src)
4496 if (op) {
4497 if (u) {
4498 gen_neon_unarrow_sats(size, dest, src);
4499 } else {
4500 gen_neon_narrow(size, dest, src);
4502 } else {
4503 if (u) {
4504 gen_neon_narrow_satu(size, dest, src);
4505 } else {
4506 gen_neon_narrow_sats(size, dest, src);
4511 /* Symbolic constants for op fields for Neon 3-register same-length.
4512 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4513 * table A7-9.
4515 #define NEON_3R_VHADD 0
4516 #define NEON_3R_VQADD 1
4517 #define NEON_3R_VRHADD 2
4518 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4519 #define NEON_3R_VHSUB 4
4520 #define NEON_3R_VQSUB 5
4521 #define NEON_3R_VCGT 6
4522 #define NEON_3R_VCGE 7
4523 #define NEON_3R_VSHL 8
4524 #define NEON_3R_VQSHL 9
4525 #define NEON_3R_VRSHL 10
4526 #define NEON_3R_VQRSHL 11
4527 #define NEON_3R_VMAX 12
4528 #define NEON_3R_VMIN 13
4529 #define NEON_3R_VABD 14
4530 #define NEON_3R_VABA 15
4531 #define NEON_3R_VADD_VSUB 16
4532 #define NEON_3R_VTST_VCEQ 17
4533 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4534 #define NEON_3R_VMUL 19
4535 #define NEON_3R_VPMAX 20
4536 #define NEON_3R_VPMIN 21
4537 #define NEON_3R_VQDMULH_VQRDMULH 22
4538 #define NEON_3R_VPADD 23
4539 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4540 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4541 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4542 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4543 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4544 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4545 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
4547 static const uint8_t neon_3r_sizes[] = {
4548 [NEON_3R_VHADD] = 0x7,
4549 [NEON_3R_VQADD] = 0xf,
4550 [NEON_3R_VRHADD] = 0x7,
4551 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4552 [NEON_3R_VHSUB] = 0x7,
4553 [NEON_3R_VQSUB] = 0xf,
4554 [NEON_3R_VCGT] = 0x7,
4555 [NEON_3R_VCGE] = 0x7,
4556 [NEON_3R_VSHL] = 0xf,
4557 [NEON_3R_VQSHL] = 0xf,
4558 [NEON_3R_VRSHL] = 0xf,
4559 [NEON_3R_VQRSHL] = 0xf,
4560 [NEON_3R_VMAX] = 0x7,
4561 [NEON_3R_VMIN] = 0x7,
4562 [NEON_3R_VABD] = 0x7,
4563 [NEON_3R_VABA] = 0x7,
4564 [NEON_3R_VADD_VSUB] = 0xf,
4565 [NEON_3R_VTST_VCEQ] = 0x7,
4566 [NEON_3R_VML] = 0x7,
4567 [NEON_3R_VMUL] = 0x7,
4568 [NEON_3R_VPMAX] = 0x7,
4569 [NEON_3R_VPMIN] = 0x7,
4570 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4571 [NEON_3R_VPADD] = 0x7,
4572 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
4573 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4574 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4575 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4576 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4577 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4578 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
4581 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4582 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4583 * table A7-13.
4585 #define NEON_2RM_VREV64 0
4586 #define NEON_2RM_VREV32 1
4587 #define NEON_2RM_VREV16 2
4588 #define NEON_2RM_VPADDL 4
4589 #define NEON_2RM_VPADDL_U 5
4590 #define NEON_2RM_AESE 6 /* Includes AESD */
4591 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
4592 #define NEON_2RM_VCLS 8
4593 #define NEON_2RM_VCLZ 9
4594 #define NEON_2RM_VCNT 10
4595 #define NEON_2RM_VMVN 11
4596 #define NEON_2RM_VPADAL 12
4597 #define NEON_2RM_VPADAL_U 13
4598 #define NEON_2RM_VQABS 14
4599 #define NEON_2RM_VQNEG 15
4600 #define NEON_2RM_VCGT0 16
4601 #define NEON_2RM_VCGE0 17
4602 #define NEON_2RM_VCEQ0 18
4603 #define NEON_2RM_VCLE0 19
4604 #define NEON_2RM_VCLT0 20
4605 #define NEON_2RM_VABS 22
4606 #define NEON_2RM_VNEG 23
4607 #define NEON_2RM_VCGT0_F 24
4608 #define NEON_2RM_VCGE0_F 25
4609 #define NEON_2RM_VCEQ0_F 26
4610 #define NEON_2RM_VCLE0_F 27
4611 #define NEON_2RM_VCLT0_F 28
4612 #define NEON_2RM_VABS_F 30
4613 #define NEON_2RM_VNEG_F 31
4614 #define NEON_2RM_VSWP 32
4615 #define NEON_2RM_VTRN 33
4616 #define NEON_2RM_VUZP 34
4617 #define NEON_2RM_VZIP 35
4618 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4619 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4620 #define NEON_2RM_VSHLL 38
4621 #define NEON_2RM_VCVT_F16_F32 44
4622 #define NEON_2RM_VCVT_F32_F16 46
4623 #define NEON_2RM_VRECPE 56
4624 #define NEON_2RM_VRSQRTE 57
4625 #define NEON_2RM_VRECPE_F 58
4626 #define NEON_2RM_VRSQRTE_F 59
4627 #define NEON_2RM_VCVT_FS 60
4628 #define NEON_2RM_VCVT_FU 61
4629 #define NEON_2RM_VCVT_SF 62
4630 #define NEON_2RM_VCVT_UF 63
4632 static int neon_2rm_is_float_op(int op)
4634 /* Return true if this neon 2reg-misc op is float-to-float */
4635 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4636 op >= NEON_2RM_VRECPE_F);
4639 /* Each entry in this array has bit n set if the insn allows
4640 * size value n (otherwise it will UNDEF). Since unallocated
4641 * op values will have no bits set they always UNDEF.
4643 static const uint8_t neon_2rm_sizes[] = {
4644 [NEON_2RM_VREV64] = 0x7,
4645 [NEON_2RM_VREV32] = 0x3,
4646 [NEON_2RM_VREV16] = 0x1,
4647 [NEON_2RM_VPADDL] = 0x7,
4648 [NEON_2RM_VPADDL_U] = 0x7,
4649 [NEON_2RM_AESE] = 0x1,
4650 [NEON_2RM_AESMC] = 0x1,
4651 [NEON_2RM_VCLS] = 0x7,
4652 [NEON_2RM_VCLZ] = 0x7,
4653 [NEON_2RM_VCNT] = 0x1,
4654 [NEON_2RM_VMVN] = 0x1,
4655 [NEON_2RM_VPADAL] = 0x7,
4656 [NEON_2RM_VPADAL_U] = 0x7,
4657 [NEON_2RM_VQABS] = 0x7,
4658 [NEON_2RM_VQNEG] = 0x7,
4659 [NEON_2RM_VCGT0] = 0x7,
4660 [NEON_2RM_VCGE0] = 0x7,
4661 [NEON_2RM_VCEQ0] = 0x7,
4662 [NEON_2RM_VCLE0] = 0x7,
4663 [NEON_2RM_VCLT0] = 0x7,
4664 [NEON_2RM_VABS] = 0x7,
4665 [NEON_2RM_VNEG] = 0x7,
4666 [NEON_2RM_VCGT0_F] = 0x4,
4667 [NEON_2RM_VCGE0_F] = 0x4,
4668 [NEON_2RM_VCEQ0_F] = 0x4,
4669 [NEON_2RM_VCLE0_F] = 0x4,
4670 [NEON_2RM_VCLT0_F] = 0x4,
4671 [NEON_2RM_VABS_F] = 0x4,
4672 [NEON_2RM_VNEG_F] = 0x4,
4673 [NEON_2RM_VSWP] = 0x1,
4674 [NEON_2RM_VTRN] = 0x7,
4675 [NEON_2RM_VUZP] = 0x7,
4676 [NEON_2RM_VZIP] = 0x7,
4677 [NEON_2RM_VMOVN] = 0x7,
4678 [NEON_2RM_VQMOVN] = 0x7,
4679 [NEON_2RM_VSHLL] = 0x7,
4680 [NEON_2RM_VCVT_F16_F32] = 0x2,
4681 [NEON_2RM_VCVT_F32_F16] = 0x2,
4682 [NEON_2RM_VRECPE] = 0x4,
4683 [NEON_2RM_VRSQRTE] = 0x4,
4684 [NEON_2RM_VRECPE_F] = 0x4,
4685 [NEON_2RM_VRSQRTE_F] = 0x4,
4686 [NEON_2RM_VCVT_FS] = 0x4,
4687 [NEON_2RM_VCVT_FU] = 0x4,
4688 [NEON_2RM_VCVT_SF] = 0x4,
4689 [NEON_2RM_VCVT_UF] = 0x4,
4692 /* Translate a NEON data processing instruction. Return nonzero if the
4693 instruction is invalid.
4694 We process data in a mixture of 32-bit and 64-bit chunks.
4695 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
4697 static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4699 int op;
4700 int q;
4701 int rd, rn, rm;
4702 int size;
4703 int shift;
4704 int pass;
4705 int count;
4706 int pairwise;
4707 int u;
4708 uint32_t imm, mask;
4709 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
4710 TCGv_i64 tmp64;
4712 if (!s->vfp_enabled)
4713 return 1;
4714 q = (insn & (1 << 6)) != 0;
4715 u = (insn >> 24) & 1;
4716 VFP_DREG_D(rd, insn);
4717 VFP_DREG_N(rn, insn);
4718 VFP_DREG_M(rm, insn);
4719 size = (insn >> 20) & 3;
4720 if ((insn & (1 << 23)) == 0) {
4721 /* Three register same length. */
4722 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
4723 /* Catch invalid op and bad size combinations: UNDEF */
4724 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
4725 return 1;
4727 /* All insns of this form UNDEF for either this condition or the
4728 * superset of cases "Q==1"; we catch the latter later.
4730 if (q && ((rd | rn | rm) & 1)) {
4731 return 1;
4733 if (size == 3 && op != NEON_3R_LOGIC) {
4734 /* 64-bit element instructions. */
4735 for (pass = 0; pass < (q ? 2 : 1); pass++) {
4736 neon_load_reg64(cpu_V0, rn + pass);
4737 neon_load_reg64(cpu_V1, rm + pass);
4738 switch (op) {
4739 case NEON_3R_VQADD:
4740 if (u) {
4741 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
4742 cpu_V0, cpu_V1);
4743 } else {
4744 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
4745 cpu_V0, cpu_V1);
4747 break;
4748 case NEON_3R_VQSUB:
4749 if (u) {
4750 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
4751 cpu_V0, cpu_V1);
4752 } else {
4753 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
4754 cpu_V0, cpu_V1);
4756 break;
4757 case NEON_3R_VSHL:
4758 if (u) {
4759 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
4760 } else {
4761 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
4763 break;
4764 case NEON_3R_VQSHL:
4765 if (u) {
4766 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
4767 cpu_V1, cpu_V0);
4768 } else {
4769 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
4770 cpu_V1, cpu_V0);
4772 break;
4773 case NEON_3R_VRSHL:
4774 if (u) {
4775 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
4776 } else {
4777 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
4779 break;
4780 case NEON_3R_VQRSHL:
4781 if (u) {
4782 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
4783 cpu_V1, cpu_V0);
4784 } else {
4785 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
4786 cpu_V1, cpu_V0);
4788 break;
4789 case NEON_3R_VADD_VSUB:
4790 if (u) {
4791 tcg_gen_sub_i64(CPU_V001);
4792 } else {
4793 tcg_gen_add_i64(CPU_V001);
4795 break;
4796 default:
4797 abort();
4799 neon_store_reg64(cpu_V0, rd + pass);
4801 return 0;
4803 pairwise = 0;
4804 switch (op) {
4805 case NEON_3R_VSHL:
4806 case NEON_3R_VQSHL:
4807 case NEON_3R_VRSHL:
4808 case NEON_3R_VQRSHL:
4810 int rtmp;
4811 /* Shift instruction operands are reversed. */
4812 rtmp = rn;
4813 rn = rm;
4814 rm = rtmp;
4816 break;
4817 case NEON_3R_VPADD:
4818 if (u) {
4819 return 1;
4821 /* Fall through */
4822 case NEON_3R_VPMAX:
4823 case NEON_3R_VPMIN:
4824 pairwise = 1;
4825 break;
4826 case NEON_3R_FLOAT_ARITH:
4827 pairwise = (u && size < 2); /* if VPADD (float) */
4828 break;
4829 case NEON_3R_FLOAT_MINMAX:
4830 pairwise = u; /* if VPMIN/VPMAX (float) */
4831 break;
4832 case NEON_3R_FLOAT_CMP:
4833 if (!u && size) {
4834 /* no encoding for U=0 C=1x */
4835 return 1;
4837 break;
4838 case NEON_3R_FLOAT_ACMP:
4839 if (!u) {
4840 return 1;
4842 break;
4843 case NEON_3R_FLOAT_MISC:
4844 /* VMAXNM/VMINNM in ARMv8 */
4845 if (u && !arm_feature(env, ARM_FEATURE_V8)) {
4846 return 1;
4848 break;
4849 case NEON_3R_VMUL:
4850 if (u && (size != 0)) {
4851 /* UNDEF on invalid size for polynomial subcase */
4852 return 1;
4854 break;
4855 case NEON_3R_VFM:
4856 if (!arm_feature(env, ARM_FEATURE_VFP4) || u) {
4857 return 1;
4859 break;
4860 default:
4861 break;
4864 if (pairwise && q) {
4865 /* All the pairwise insns UNDEF if Q is set */
4866 return 1;
4869 for (pass = 0; pass < (q ? 4 : 2); pass++) {
4871 if (pairwise) {
4872 /* Pairwise. */
4873 if (pass < 1) {
4874 tmp = neon_load_reg(rn, 0);
4875 tmp2 = neon_load_reg(rn, 1);
4876 } else {
4877 tmp = neon_load_reg(rm, 0);
4878 tmp2 = neon_load_reg(rm, 1);
4880 } else {
4881 /* Elementwise. */
4882 tmp = neon_load_reg(rn, pass);
4883 tmp2 = neon_load_reg(rm, pass);
4885 switch (op) {
4886 case NEON_3R_VHADD:
4887 GEN_NEON_INTEGER_OP(hadd);
4888 break;
4889 case NEON_3R_VQADD:
4890 GEN_NEON_INTEGER_OP_ENV(qadd);
4891 break;
4892 case NEON_3R_VRHADD:
4893 GEN_NEON_INTEGER_OP(rhadd);
4894 break;
4895 case NEON_3R_LOGIC: /* Logic ops. */
4896 switch ((u << 2) | size) {
4897 case 0: /* VAND */
4898 tcg_gen_and_i32(tmp, tmp, tmp2);
4899 break;
4900 case 1: /* BIC */
4901 tcg_gen_andc_i32(tmp, tmp, tmp2);
4902 break;
4903 case 2: /* VORR */
4904 tcg_gen_or_i32(tmp, tmp, tmp2);
4905 break;
4906 case 3: /* VORN */
4907 tcg_gen_orc_i32(tmp, tmp, tmp2);
4908 break;
4909 case 4: /* VEOR */
4910 tcg_gen_xor_i32(tmp, tmp, tmp2);
4911 break;
4912 case 5: /* VBSL */
4913 tmp3 = neon_load_reg(rd, pass);
4914 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
4915 tcg_temp_free_i32(tmp3);
4916 break;
4917 case 6: /* VBIT */
4918 tmp3 = neon_load_reg(rd, pass);
4919 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
4920 tcg_temp_free_i32(tmp3);
4921 break;
4922 case 7: /* VBIF */
4923 tmp3 = neon_load_reg(rd, pass);
4924 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
4925 tcg_temp_free_i32(tmp3);
4926 break;
4928 break;
4929 case NEON_3R_VHSUB:
4930 GEN_NEON_INTEGER_OP(hsub);
4931 break;
4932 case NEON_3R_VQSUB:
4933 GEN_NEON_INTEGER_OP_ENV(qsub);
4934 break;
4935 case NEON_3R_VCGT:
4936 GEN_NEON_INTEGER_OP(cgt);
4937 break;
4938 case NEON_3R_VCGE:
4939 GEN_NEON_INTEGER_OP(cge);
4940 break;
4941 case NEON_3R_VSHL:
4942 GEN_NEON_INTEGER_OP(shl);
4943 break;
4944 case NEON_3R_VQSHL:
4945 GEN_NEON_INTEGER_OP_ENV(qshl);
4946 break;
4947 case NEON_3R_VRSHL:
4948 GEN_NEON_INTEGER_OP(rshl);
4949 break;
4950 case NEON_3R_VQRSHL:
4951 GEN_NEON_INTEGER_OP_ENV(qrshl);
4952 break;
4953 case NEON_3R_VMAX:
4954 GEN_NEON_INTEGER_OP(max);
4955 break;
4956 case NEON_3R_VMIN:
4957 GEN_NEON_INTEGER_OP(min);
4958 break;
4959 case NEON_3R_VABD:
4960 GEN_NEON_INTEGER_OP(abd);
4961 break;
4962 case NEON_3R_VABA:
4963 GEN_NEON_INTEGER_OP(abd);
4964 tcg_temp_free_i32(tmp2);
4965 tmp2 = neon_load_reg(rd, pass);
4966 gen_neon_add(size, tmp, tmp2);
4967 break;
4968 case NEON_3R_VADD_VSUB:
4969 if (!u) { /* VADD */
4970 gen_neon_add(size, tmp, tmp2);
4971 } else { /* VSUB */
4972 switch (size) {
4973 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
4974 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
4975 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
4976 default: abort();
4979 break;
4980 case NEON_3R_VTST_VCEQ:
4981 if (!u) { /* VTST */
4982 switch (size) {
4983 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
4984 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
4985 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
4986 default: abort();
4988 } else { /* VCEQ */
4989 switch (size) {
4990 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
4991 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
4992 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
4993 default: abort();
4996 break;
4997 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
4998 switch (size) {
4999 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5000 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5001 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5002 default: abort();
5004 tcg_temp_free_i32(tmp2);
5005 tmp2 = neon_load_reg(rd, pass);
5006 if (u) { /* VMLS */
5007 gen_neon_rsb(size, tmp, tmp2);
5008 } else { /* VMLA */
5009 gen_neon_add(size, tmp, tmp2);
5011 break;
5012 case NEON_3R_VMUL:
5013 if (u) { /* polynomial */
5014 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
5015 } else { /* Integer */
5016 switch (size) {
5017 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5018 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5019 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5020 default: abort();
5023 break;
5024 case NEON_3R_VPMAX:
5025 GEN_NEON_INTEGER_OP(pmax);
5026 break;
5027 case NEON_3R_VPMIN:
5028 GEN_NEON_INTEGER_OP(pmin);
5029 break;
5030 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
5031 if (!u) { /* VQDMULH */
5032 switch (size) {
5033 case 1:
5034 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5035 break;
5036 case 2:
5037 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5038 break;
5039 default: abort();
5041 } else { /* VQRDMULH */
5042 switch (size) {
5043 case 1:
5044 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5045 break;
5046 case 2:
5047 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5048 break;
5049 default: abort();
5052 break;
5053 case NEON_3R_VPADD:
5054 switch (size) {
5055 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5056 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5057 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5058 default: abort();
5060 break;
5061 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
5063 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5064 switch ((u << 2) | size) {
5065 case 0: /* VADD */
5066 case 4: /* VPADD */
5067 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5068 break;
5069 case 2: /* VSUB */
5070 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
5071 break;
5072 case 6: /* VABD */
5073 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
5074 break;
5075 default:
5076 abort();
5078 tcg_temp_free_ptr(fpstatus);
5079 break;
5081 case NEON_3R_FLOAT_MULTIPLY:
5083 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5084 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5085 if (!u) {
5086 tcg_temp_free_i32(tmp2);
5087 tmp2 = neon_load_reg(rd, pass);
5088 if (size == 0) {
5089 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5090 } else {
5091 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5094 tcg_temp_free_ptr(fpstatus);
5095 break;
5097 case NEON_3R_FLOAT_CMP:
5099 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5100 if (!u) {
5101 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5102 } else {
5103 if (size == 0) {
5104 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5105 } else {
5106 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5109 tcg_temp_free_ptr(fpstatus);
5110 break;
5112 case NEON_3R_FLOAT_ACMP:
5114 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5115 if (size == 0) {
5116 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5117 } else {
5118 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5120 tcg_temp_free_ptr(fpstatus);
5121 break;
5123 case NEON_3R_FLOAT_MINMAX:
5125 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5126 if (size == 0) {
5127 gen_helper_neon_max_f32(tmp, tmp, tmp2, fpstatus);
5128 } else {
5129 gen_helper_neon_min_f32(tmp, tmp, tmp2, fpstatus);
5131 tcg_temp_free_ptr(fpstatus);
5132 break;
5134 case NEON_3R_FLOAT_MISC:
5135 if (u) {
5136 /* VMAXNM/VMINNM */
5137 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5138 if (size == 0) {
5139 gen_helper_vfp_maxnms(tmp, tmp, tmp2, fpstatus);
5140 } else {
5141 gen_helper_vfp_minnms(tmp, tmp, tmp2, fpstatus);
5143 tcg_temp_free_ptr(fpstatus);
5144 } else {
5145 if (size == 0) {
5146 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5147 } else {
5148 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5151 break;
5152 case NEON_3R_VFM:
5154 /* VFMA, VFMS: fused multiply-add */
5155 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5156 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5157 if (size) {
5158 /* VFMS */
5159 gen_helper_vfp_negs(tmp, tmp);
5161 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5162 tcg_temp_free_i32(tmp3);
5163 tcg_temp_free_ptr(fpstatus);
5164 break;
5166 default:
5167 abort();
5169 tcg_temp_free_i32(tmp2);
5171 /* Save the result. For elementwise operations we can put it
5172 straight into the destination register. For pairwise operations
5173 we have to be careful to avoid clobbering the source operands. */
5174 if (pairwise && rd == rm) {
5175 neon_store_scratch(pass, tmp);
5176 } else {
5177 neon_store_reg(rd, pass, tmp);
5180 } /* for pass */
5181 if (pairwise && rd == rm) {
5182 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5183 tmp = neon_load_scratch(pass);
5184 neon_store_reg(rd, pass, tmp);
5187 /* End of 3 register same size operations. */
5188 } else if (insn & (1 << 4)) {
5189 if ((insn & 0x00380080) != 0) {
5190 /* Two registers and shift. */
5191 op = (insn >> 8) & 0xf;
5192 if (insn & (1 << 7)) {
5193 /* 64-bit shift. */
5194 if (op > 7) {
5195 return 1;
5197 size = 3;
5198 } else {
5199 size = 2;
5200 while ((insn & (1 << (size + 19))) == 0)
5201 size--;
5203 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5204 /* To avoid excessive duplication of ops we implement shift
5205 by immediate using the variable shift operations. */
5206 if (op < 8) {
5207 /* Shift by immediate:
5208 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5209 if (q && ((rd | rm) & 1)) {
5210 return 1;
5212 if (!u && (op == 4 || op == 6)) {
5213 return 1;
5215 /* Right shifts are encoded as N - shift, where N is the
5216 element size in bits. */
5217 if (op <= 4)
5218 shift = shift - (1 << (size + 3));
5219 if (size == 3) {
5220 count = q + 1;
5221 } else {
5222 count = q ? 4: 2;
5224 switch (size) {
5225 case 0:
5226 imm = (uint8_t) shift;
5227 imm |= imm << 8;
5228 imm |= imm << 16;
5229 break;
5230 case 1:
5231 imm = (uint16_t) shift;
5232 imm |= imm << 16;
5233 break;
5234 case 2:
5235 case 3:
5236 imm = shift;
5237 break;
5238 default:
5239 abort();
5242 for (pass = 0; pass < count; pass++) {
5243 if (size == 3) {
5244 neon_load_reg64(cpu_V0, rm + pass);
5245 tcg_gen_movi_i64(cpu_V1, imm);
5246 switch (op) {
5247 case 0: /* VSHR */
5248 case 1: /* VSRA */
5249 if (u)
5250 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5251 else
5252 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5253 break;
5254 case 2: /* VRSHR */
5255 case 3: /* VRSRA */
5256 if (u)
5257 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5258 else
5259 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5260 break;
5261 case 4: /* VSRI */
5262 case 5: /* VSHL, VSLI */
5263 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5264 break;
5265 case 6: /* VQSHLU */
5266 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5267 cpu_V0, cpu_V1);
5268 break;
5269 case 7: /* VQSHL */
5270 if (u) {
5271 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5272 cpu_V0, cpu_V1);
5273 } else {
5274 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5275 cpu_V0, cpu_V1);
5277 break;
5279 if (op == 1 || op == 3) {
5280 /* Accumulate. */
5281 neon_load_reg64(cpu_V1, rd + pass);
5282 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5283 } else if (op == 4 || (op == 5 && u)) {
5284 /* Insert */
5285 neon_load_reg64(cpu_V1, rd + pass);
5286 uint64_t mask;
5287 if (shift < -63 || shift > 63) {
5288 mask = 0;
5289 } else {
5290 if (op == 4) {
5291 mask = 0xffffffffffffffffull >> -shift;
5292 } else {
5293 mask = 0xffffffffffffffffull << shift;
5296 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5297 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5299 neon_store_reg64(cpu_V0, rd + pass);
5300 } else { /* size < 3 */
5301 /* Operands in T0 and T1. */
5302 tmp = neon_load_reg(rm, pass);
5303 tmp2 = tcg_temp_new_i32();
5304 tcg_gen_movi_i32(tmp2, imm);
5305 switch (op) {
5306 case 0: /* VSHR */
5307 case 1: /* VSRA */
5308 GEN_NEON_INTEGER_OP(shl);
5309 break;
5310 case 2: /* VRSHR */
5311 case 3: /* VRSRA */
5312 GEN_NEON_INTEGER_OP(rshl);
5313 break;
5314 case 4: /* VSRI */
5315 case 5: /* VSHL, VSLI */
5316 switch (size) {
5317 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5318 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5319 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5320 default: abort();
5322 break;
5323 case 6: /* VQSHLU */
5324 switch (size) {
5325 case 0:
5326 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5327 tmp, tmp2);
5328 break;
5329 case 1:
5330 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5331 tmp, tmp2);
5332 break;
5333 case 2:
5334 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5335 tmp, tmp2);
5336 break;
5337 default:
5338 abort();
5340 break;
5341 case 7: /* VQSHL */
5342 GEN_NEON_INTEGER_OP_ENV(qshl);
5343 break;
5345 tcg_temp_free_i32(tmp2);
5347 if (op == 1 || op == 3) {
5348 /* Accumulate. */
5349 tmp2 = neon_load_reg(rd, pass);
5350 gen_neon_add(size, tmp, tmp2);
5351 tcg_temp_free_i32(tmp2);
5352 } else if (op == 4 || (op == 5 && u)) {
5353 /* Insert */
5354 switch (size) {
5355 case 0:
5356 if (op == 4)
5357 mask = 0xff >> -shift;
5358 else
5359 mask = (uint8_t)(0xff << shift);
5360 mask |= mask << 8;
5361 mask |= mask << 16;
5362 break;
5363 case 1:
5364 if (op == 4)
5365 mask = 0xffff >> -shift;
5366 else
5367 mask = (uint16_t)(0xffff << shift);
5368 mask |= mask << 16;
5369 break;
5370 case 2:
5371 if (shift < -31 || shift > 31) {
5372 mask = 0;
5373 } else {
5374 if (op == 4)
5375 mask = 0xffffffffu >> -shift;
5376 else
5377 mask = 0xffffffffu << shift;
5379 break;
5380 default:
5381 abort();
5383 tmp2 = neon_load_reg(rd, pass);
5384 tcg_gen_andi_i32(tmp, tmp, mask);
5385 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5386 tcg_gen_or_i32(tmp, tmp, tmp2);
5387 tcg_temp_free_i32(tmp2);
5389 neon_store_reg(rd, pass, tmp);
5391 } /* for pass */
5392 } else if (op < 10) {
5393 /* Shift by immediate and narrow:
5394 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5395 int input_unsigned = (op == 8) ? !u : u;
5396 if (rm & 1) {
5397 return 1;
5399 shift = shift - (1 << (size + 3));
5400 size++;
5401 if (size == 3) {
5402 tmp64 = tcg_const_i64(shift);
5403 neon_load_reg64(cpu_V0, rm);
5404 neon_load_reg64(cpu_V1, rm + 1);
5405 for (pass = 0; pass < 2; pass++) {
5406 TCGv_i64 in;
5407 if (pass == 0) {
5408 in = cpu_V0;
5409 } else {
5410 in = cpu_V1;
5412 if (q) {
5413 if (input_unsigned) {
5414 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5415 } else {
5416 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5418 } else {
5419 if (input_unsigned) {
5420 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5421 } else {
5422 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5425 tmp = tcg_temp_new_i32();
5426 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5427 neon_store_reg(rd, pass, tmp);
5428 } /* for pass */
5429 tcg_temp_free_i64(tmp64);
5430 } else {
5431 if (size == 1) {
5432 imm = (uint16_t)shift;
5433 imm |= imm << 16;
5434 } else {
5435 /* size == 2 */
5436 imm = (uint32_t)shift;
5438 tmp2 = tcg_const_i32(imm);
5439 tmp4 = neon_load_reg(rm + 1, 0);
5440 tmp5 = neon_load_reg(rm + 1, 1);
5441 for (pass = 0; pass < 2; pass++) {
5442 if (pass == 0) {
5443 tmp = neon_load_reg(rm, 0);
5444 } else {
5445 tmp = tmp4;
5447 gen_neon_shift_narrow(size, tmp, tmp2, q,
5448 input_unsigned);
5449 if (pass == 0) {
5450 tmp3 = neon_load_reg(rm, 1);
5451 } else {
5452 tmp3 = tmp5;
5454 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5455 input_unsigned);
5456 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5457 tcg_temp_free_i32(tmp);
5458 tcg_temp_free_i32(tmp3);
5459 tmp = tcg_temp_new_i32();
5460 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5461 neon_store_reg(rd, pass, tmp);
5462 } /* for pass */
5463 tcg_temp_free_i32(tmp2);
5465 } else if (op == 10) {
5466 /* VSHLL, VMOVL */
5467 if (q || (rd & 1)) {
5468 return 1;
5470 tmp = neon_load_reg(rm, 0);
5471 tmp2 = neon_load_reg(rm, 1);
5472 for (pass = 0; pass < 2; pass++) {
5473 if (pass == 1)
5474 tmp = tmp2;
5476 gen_neon_widen(cpu_V0, tmp, size, u);
5478 if (shift != 0) {
5479 /* The shift is less than the width of the source
5480 type, so we can just shift the whole register. */
5481 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5482 /* Widen the result of shift: we need to clear
5483 * the potential overflow bits resulting from
5484 * left bits of the narrow input appearing as
5485 * right bits of left the neighbour narrow
5486 * input. */
5487 if (size < 2 || !u) {
5488 uint64_t imm64;
5489 if (size == 0) {
5490 imm = (0xffu >> (8 - shift));
5491 imm |= imm << 16;
5492 } else if (size == 1) {
5493 imm = 0xffff >> (16 - shift);
5494 } else {
5495 /* size == 2 */
5496 imm = 0xffffffff >> (32 - shift);
5498 if (size < 2) {
5499 imm64 = imm | (((uint64_t)imm) << 32);
5500 } else {
5501 imm64 = imm;
5503 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5506 neon_store_reg64(cpu_V0, rd + pass);
5508 } else if (op >= 14) {
5509 /* VCVT fixed-point. */
5510 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5511 return 1;
5513 /* We have already masked out the must-be-1 top bit of imm6,
5514 * hence this 32-shift where the ARM ARM has 64-imm6.
5516 shift = 32 - shift;
5517 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5518 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5519 if (!(op & 1)) {
5520 if (u)
5521 gen_vfp_ulto(0, shift, 1);
5522 else
5523 gen_vfp_slto(0, shift, 1);
5524 } else {
5525 if (u)
5526 gen_vfp_toul(0, shift, 1);
5527 else
5528 gen_vfp_tosl(0, shift, 1);
5530 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5532 } else {
5533 return 1;
5535 } else { /* (insn & 0x00380080) == 0 */
5536 int invert;
5537 if (q && (rd & 1)) {
5538 return 1;
5541 op = (insn >> 8) & 0xf;
5542 /* One register and immediate. */
5543 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5544 invert = (insn & (1 << 5)) != 0;
5545 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5546 * We choose to not special-case this and will behave as if a
5547 * valid constant encoding of 0 had been given.
5549 switch (op) {
5550 case 0: case 1:
5551 /* no-op */
5552 break;
5553 case 2: case 3:
5554 imm <<= 8;
5555 break;
5556 case 4: case 5:
5557 imm <<= 16;
5558 break;
5559 case 6: case 7:
5560 imm <<= 24;
5561 break;
5562 case 8: case 9:
5563 imm |= imm << 16;
5564 break;
5565 case 10: case 11:
5566 imm = (imm << 8) | (imm << 24);
5567 break;
5568 case 12:
5569 imm = (imm << 8) | 0xff;
5570 break;
5571 case 13:
5572 imm = (imm << 16) | 0xffff;
5573 break;
5574 case 14:
5575 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5576 if (invert)
5577 imm = ~imm;
5578 break;
5579 case 15:
5580 if (invert) {
5581 return 1;
5583 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5584 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5585 break;
5587 if (invert)
5588 imm = ~imm;
5590 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5591 if (op & 1 && op < 12) {
5592 tmp = neon_load_reg(rd, pass);
5593 if (invert) {
5594 /* The immediate value has already been inverted, so
5595 BIC becomes AND. */
5596 tcg_gen_andi_i32(tmp, tmp, imm);
5597 } else {
5598 tcg_gen_ori_i32(tmp, tmp, imm);
5600 } else {
5601 /* VMOV, VMVN. */
5602 tmp = tcg_temp_new_i32();
5603 if (op == 14 && invert) {
5604 int n;
5605 uint32_t val;
5606 val = 0;
5607 for (n = 0; n < 4; n++) {
5608 if (imm & (1 << (n + (pass & 1) * 4)))
5609 val |= 0xff << (n * 8);
5611 tcg_gen_movi_i32(tmp, val);
5612 } else {
5613 tcg_gen_movi_i32(tmp, imm);
5616 neon_store_reg(rd, pass, tmp);
5619 } else { /* (insn & 0x00800010 == 0x00800000) */
5620 if (size != 3) {
5621 op = (insn >> 8) & 0xf;
5622 if ((insn & (1 << 6)) == 0) {
5623 /* Three registers of different lengths. */
5624 int src1_wide;
5625 int src2_wide;
5626 int prewiden;
5627 /* undefreq: bit 0 : UNDEF if size != 0
5628 * bit 1 : UNDEF if size == 0
5629 * bit 2 : UNDEF if U == 1
5630 * Note that [1:0] set implies 'always UNDEF'
5632 int undefreq;
5633 /* prewiden, src1_wide, src2_wide, undefreq */
5634 static const int neon_3reg_wide[16][4] = {
5635 {1, 0, 0, 0}, /* VADDL */
5636 {1, 1, 0, 0}, /* VADDW */
5637 {1, 0, 0, 0}, /* VSUBL */
5638 {1, 1, 0, 0}, /* VSUBW */
5639 {0, 1, 1, 0}, /* VADDHN */
5640 {0, 0, 0, 0}, /* VABAL */
5641 {0, 1, 1, 0}, /* VSUBHN */
5642 {0, 0, 0, 0}, /* VABDL */
5643 {0, 0, 0, 0}, /* VMLAL */
5644 {0, 0, 0, 6}, /* VQDMLAL */
5645 {0, 0, 0, 0}, /* VMLSL */
5646 {0, 0, 0, 6}, /* VQDMLSL */
5647 {0, 0, 0, 0}, /* Integer VMULL */
5648 {0, 0, 0, 2}, /* VQDMULL */
5649 {0, 0, 0, 5}, /* Polynomial VMULL */
5650 {0, 0, 0, 3}, /* Reserved: always UNDEF */
5653 prewiden = neon_3reg_wide[op][0];
5654 src1_wide = neon_3reg_wide[op][1];
5655 src2_wide = neon_3reg_wide[op][2];
5656 undefreq = neon_3reg_wide[op][3];
5658 if (((undefreq & 1) && (size != 0)) ||
5659 ((undefreq & 2) && (size == 0)) ||
5660 ((undefreq & 4) && u)) {
5661 return 1;
5663 if ((src1_wide && (rn & 1)) ||
5664 (src2_wide && (rm & 1)) ||
5665 (!src2_wide && (rd & 1))) {
5666 return 1;
5669 /* Avoid overlapping operands. Wide source operands are
5670 always aligned so will never overlap with wide
5671 destinations in problematic ways. */
5672 if (rd == rm && !src2_wide) {
5673 tmp = neon_load_reg(rm, 1);
5674 neon_store_scratch(2, tmp);
5675 } else if (rd == rn && !src1_wide) {
5676 tmp = neon_load_reg(rn, 1);
5677 neon_store_scratch(2, tmp);
5679 TCGV_UNUSED_I32(tmp3);
5680 for (pass = 0; pass < 2; pass++) {
5681 if (src1_wide) {
5682 neon_load_reg64(cpu_V0, rn + pass);
5683 TCGV_UNUSED_I32(tmp);
5684 } else {
5685 if (pass == 1 && rd == rn) {
5686 tmp = neon_load_scratch(2);
5687 } else {
5688 tmp = neon_load_reg(rn, pass);
5690 if (prewiden) {
5691 gen_neon_widen(cpu_V0, tmp, size, u);
5694 if (src2_wide) {
5695 neon_load_reg64(cpu_V1, rm + pass);
5696 TCGV_UNUSED_I32(tmp2);
5697 } else {
5698 if (pass == 1 && rd == rm) {
5699 tmp2 = neon_load_scratch(2);
5700 } else {
5701 tmp2 = neon_load_reg(rm, pass);
5703 if (prewiden) {
5704 gen_neon_widen(cpu_V1, tmp2, size, u);
5707 switch (op) {
5708 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
5709 gen_neon_addl(size);
5710 break;
5711 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
5712 gen_neon_subl(size);
5713 break;
5714 case 5: case 7: /* VABAL, VABDL */
5715 switch ((size << 1) | u) {
5716 case 0:
5717 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
5718 break;
5719 case 1:
5720 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
5721 break;
5722 case 2:
5723 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
5724 break;
5725 case 3:
5726 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
5727 break;
5728 case 4:
5729 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
5730 break;
5731 case 5:
5732 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
5733 break;
5734 default: abort();
5736 tcg_temp_free_i32(tmp2);
5737 tcg_temp_free_i32(tmp);
5738 break;
5739 case 8: case 9: case 10: case 11: case 12: case 13:
5740 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
5741 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5742 break;
5743 case 14: /* Polynomial VMULL */
5744 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
5745 tcg_temp_free_i32(tmp2);
5746 tcg_temp_free_i32(tmp);
5747 break;
5748 default: /* 15 is RESERVED: caught earlier */
5749 abort();
5751 if (op == 13) {
5752 /* VQDMULL */
5753 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5754 neon_store_reg64(cpu_V0, rd + pass);
5755 } else if (op == 5 || (op >= 8 && op <= 11)) {
5756 /* Accumulate. */
5757 neon_load_reg64(cpu_V1, rd + pass);
5758 switch (op) {
5759 case 10: /* VMLSL */
5760 gen_neon_negl(cpu_V0, size);
5761 /* Fall through */
5762 case 5: case 8: /* VABAL, VMLAL */
5763 gen_neon_addl(size);
5764 break;
5765 case 9: case 11: /* VQDMLAL, VQDMLSL */
5766 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5767 if (op == 11) {
5768 gen_neon_negl(cpu_V0, size);
5770 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5771 break;
5772 default:
5773 abort();
5775 neon_store_reg64(cpu_V0, rd + pass);
5776 } else if (op == 4 || op == 6) {
5777 /* Narrowing operation. */
5778 tmp = tcg_temp_new_i32();
5779 if (!u) {
5780 switch (size) {
5781 case 0:
5782 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
5783 break;
5784 case 1:
5785 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
5786 break;
5787 case 2:
5788 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5789 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5790 break;
5791 default: abort();
5793 } else {
5794 switch (size) {
5795 case 0:
5796 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
5797 break;
5798 case 1:
5799 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
5800 break;
5801 case 2:
5802 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
5803 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
5804 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
5805 break;
5806 default: abort();
5809 if (pass == 0) {
5810 tmp3 = tmp;
5811 } else {
5812 neon_store_reg(rd, 0, tmp3);
5813 neon_store_reg(rd, 1, tmp);
5815 } else {
5816 /* Write back the result. */
5817 neon_store_reg64(cpu_V0, rd + pass);
5820 } else {
5821 /* Two registers and a scalar. NB that for ops of this form
5822 * the ARM ARM labels bit 24 as Q, but it is in our variable
5823 * 'u', not 'q'.
5825 if (size == 0) {
5826 return 1;
5828 switch (op) {
5829 case 1: /* Float VMLA scalar */
5830 case 5: /* Floating point VMLS scalar */
5831 case 9: /* Floating point VMUL scalar */
5832 if (size == 1) {
5833 return 1;
5835 /* fall through */
5836 case 0: /* Integer VMLA scalar */
5837 case 4: /* Integer VMLS scalar */
5838 case 8: /* Integer VMUL scalar */
5839 case 12: /* VQDMULH scalar */
5840 case 13: /* VQRDMULH scalar */
5841 if (u && ((rd | rn) & 1)) {
5842 return 1;
5844 tmp = neon_get_scalar(size, rm);
5845 neon_store_scratch(0, tmp);
5846 for (pass = 0; pass < (u ? 4 : 2); pass++) {
5847 tmp = neon_load_scratch(0);
5848 tmp2 = neon_load_reg(rn, pass);
5849 if (op == 12) {
5850 if (size == 1) {
5851 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5852 } else {
5853 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5855 } else if (op == 13) {
5856 if (size == 1) {
5857 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5858 } else {
5859 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5861 } else if (op & 1) {
5862 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5863 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5864 tcg_temp_free_ptr(fpstatus);
5865 } else {
5866 switch (size) {
5867 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5868 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5869 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5870 default: abort();
5873 tcg_temp_free_i32(tmp2);
5874 if (op < 8) {
5875 /* Accumulate. */
5876 tmp2 = neon_load_reg(rd, pass);
5877 switch (op) {
5878 case 0:
5879 gen_neon_add(size, tmp, tmp2);
5880 break;
5881 case 1:
5883 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5884 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5885 tcg_temp_free_ptr(fpstatus);
5886 break;
5888 case 4:
5889 gen_neon_rsb(size, tmp, tmp2);
5890 break;
5891 case 5:
5893 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5894 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5895 tcg_temp_free_ptr(fpstatus);
5896 break;
5898 default:
5899 abort();
5901 tcg_temp_free_i32(tmp2);
5903 neon_store_reg(rd, pass, tmp);
5905 break;
5906 case 3: /* VQDMLAL scalar */
5907 case 7: /* VQDMLSL scalar */
5908 case 11: /* VQDMULL scalar */
5909 if (u == 1) {
5910 return 1;
5912 /* fall through */
5913 case 2: /* VMLAL sclar */
5914 case 6: /* VMLSL scalar */
5915 case 10: /* VMULL scalar */
5916 if (rd & 1) {
5917 return 1;
5919 tmp2 = neon_get_scalar(size, rm);
5920 /* We need a copy of tmp2 because gen_neon_mull
5921 * deletes it during pass 0. */
5922 tmp4 = tcg_temp_new_i32();
5923 tcg_gen_mov_i32(tmp4, tmp2);
5924 tmp3 = neon_load_reg(rn, 1);
5926 for (pass = 0; pass < 2; pass++) {
5927 if (pass == 0) {
5928 tmp = neon_load_reg(rn, 0);
5929 } else {
5930 tmp = tmp3;
5931 tmp2 = tmp4;
5933 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
5934 if (op != 11) {
5935 neon_load_reg64(cpu_V1, rd + pass);
5937 switch (op) {
5938 case 6:
5939 gen_neon_negl(cpu_V0, size);
5940 /* Fall through */
5941 case 2:
5942 gen_neon_addl(size);
5943 break;
5944 case 3: case 7:
5945 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5946 if (op == 7) {
5947 gen_neon_negl(cpu_V0, size);
5949 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
5950 break;
5951 case 10:
5952 /* no-op */
5953 break;
5954 case 11:
5955 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
5956 break;
5957 default:
5958 abort();
5960 neon_store_reg64(cpu_V0, rd + pass);
5964 break;
5965 default: /* 14 and 15 are RESERVED */
5966 return 1;
5969 } else { /* size == 3 */
5970 if (!u) {
5971 /* Extract. */
5972 imm = (insn >> 8) & 0xf;
5974 if (imm > 7 && !q)
5975 return 1;
5977 if (q && ((rd | rn | rm) & 1)) {
5978 return 1;
5981 if (imm == 0) {
5982 neon_load_reg64(cpu_V0, rn);
5983 if (q) {
5984 neon_load_reg64(cpu_V1, rn + 1);
5986 } else if (imm == 8) {
5987 neon_load_reg64(cpu_V0, rn + 1);
5988 if (q) {
5989 neon_load_reg64(cpu_V1, rm);
5991 } else if (q) {
5992 tmp64 = tcg_temp_new_i64();
5993 if (imm < 8) {
5994 neon_load_reg64(cpu_V0, rn);
5995 neon_load_reg64(tmp64, rn + 1);
5996 } else {
5997 neon_load_reg64(cpu_V0, rn + 1);
5998 neon_load_reg64(tmp64, rm);
6000 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
6001 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
6002 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6003 if (imm < 8) {
6004 neon_load_reg64(cpu_V1, rm);
6005 } else {
6006 neon_load_reg64(cpu_V1, rm + 1);
6007 imm -= 8;
6009 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6010 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6011 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
6012 tcg_temp_free_i64(tmp64);
6013 } else {
6014 /* BUGFIX */
6015 neon_load_reg64(cpu_V0, rn);
6016 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
6017 neon_load_reg64(cpu_V1, rm);
6018 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6019 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6021 neon_store_reg64(cpu_V0, rd);
6022 if (q) {
6023 neon_store_reg64(cpu_V1, rd + 1);
6025 } else if ((insn & (1 << 11)) == 0) {
6026 /* Two register misc. */
6027 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6028 size = (insn >> 18) & 3;
6029 /* UNDEF for unknown op values and bad op-size combinations */
6030 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6031 return 1;
6033 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6034 q && ((rm | rd) & 1)) {
6035 return 1;
6037 switch (op) {
6038 case NEON_2RM_VREV64:
6039 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6040 tmp = neon_load_reg(rm, pass * 2);
6041 tmp2 = neon_load_reg(rm, pass * 2 + 1);
6042 switch (size) {
6043 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6044 case 1: gen_swap_half(tmp); break;
6045 case 2: /* no-op */ break;
6046 default: abort();
6048 neon_store_reg(rd, pass * 2 + 1, tmp);
6049 if (size == 2) {
6050 neon_store_reg(rd, pass * 2, tmp2);
6051 } else {
6052 switch (size) {
6053 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6054 case 1: gen_swap_half(tmp2); break;
6055 default: abort();
6057 neon_store_reg(rd, pass * 2, tmp2);
6060 break;
6061 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6062 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
6063 for (pass = 0; pass < q + 1; pass++) {
6064 tmp = neon_load_reg(rm, pass * 2);
6065 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6066 tmp = neon_load_reg(rm, pass * 2 + 1);
6067 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6068 switch (size) {
6069 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6070 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6071 case 2: tcg_gen_add_i64(CPU_V001); break;
6072 default: abort();
6074 if (op >= NEON_2RM_VPADAL) {
6075 /* Accumulate. */
6076 neon_load_reg64(cpu_V1, rd + pass);
6077 gen_neon_addl(size);
6079 neon_store_reg64(cpu_V0, rd + pass);
6081 break;
6082 case NEON_2RM_VTRN:
6083 if (size == 2) {
6084 int n;
6085 for (n = 0; n < (q ? 4 : 2); n += 2) {
6086 tmp = neon_load_reg(rm, n);
6087 tmp2 = neon_load_reg(rd, n + 1);
6088 neon_store_reg(rm, n, tmp2);
6089 neon_store_reg(rd, n + 1, tmp);
6091 } else {
6092 goto elementwise;
6094 break;
6095 case NEON_2RM_VUZP:
6096 if (gen_neon_unzip(rd, rm, size, q)) {
6097 return 1;
6099 break;
6100 case NEON_2RM_VZIP:
6101 if (gen_neon_zip(rd, rm, size, q)) {
6102 return 1;
6104 break;
6105 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6106 /* also VQMOVUN; op field and mnemonics don't line up */
6107 if (rm & 1) {
6108 return 1;
6110 TCGV_UNUSED_I32(tmp2);
6111 for (pass = 0; pass < 2; pass++) {
6112 neon_load_reg64(cpu_V0, rm + pass);
6113 tmp = tcg_temp_new_i32();
6114 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6115 tmp, cpu_V0);
6116 if (pass == 0) {
6117 tmp2 = tmp;
6118 } else {
6119 neon_store_reg(rd, 0, tmp2);
6120 neon_store_reg(rd, 1, tmp);
6123 break;
6124 case NEON_2RM_VSHLL:
6125 if (q || (rd & 1)) {
6126 return 1;
6128 tmp = neon_load_reg(rm, 0);
6129 tmp2 = neon_load_reg(rm, 1);
6130 for (pass = 0; pass < 2; pass++) {
6131 if (pass == 1)
6132 tmp = tmp2;
6133 gen_neon_widen(cpu_V0, tmp, size, 1);
6134 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
6135 neon_store_reg64(cpu_V0, rd + pass);
6137 break;
6138 case NEON_2RM_VCVT_F16_F32:
6139 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6140 q || (rm & 1)) {
6141 return 1;
6143 tmp = tcg_temp_new_i32();
6144 tmp2 = tcg_temp_new_i32();
6145 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
6146 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6147 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
6148 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6149 tcg_gen_shli_i32(tmp2, tmp2, 16);
6150 tcg_gen_or_i32(tmp2, tmp2, tmp);
6151 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
6152 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6153 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6154 neon_store_reg(rd, 0, tmp2);
6155 tmp2 = tcg_temp_new_i32();
6156 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6157 tcg_gen_shli_i32(tmp2, tmp2, 16);
6158 tcg_gen_or_i32(tmp2, tmp2, tmp);
6159 neon_store_reg(rd, 1, tmp2);
6160 tcg_temp_free_i32(tmp);
6161 break;
6162 case NEON_2RM_VCVT_F32_F16:
6163 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6164 q || (rd & 1)) {
6165 return 1;
6167 tmp3 = tcg_temp_new_i32();
6168 tmp = neon_load_reg(rm, 0);
6169 tmp2 = neon_load_reg(rm, 1);
6170 tcg_gen_ext16u_i32(tmp3, tmp);
6171 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6172 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6173 tcg_gen_shri_i32(tmp3, tmp, 16);
6174 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6175 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6176 tcg_temp_free_i32(tmp);
6177 tcg_gen_ext16u_i32(tmp3, tmp2);
6178 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6179 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6180 tcg_gen_shri_i32(tmp3, tmp2, 16);
6181 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6182 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6183 tcg_temp_free_i32(tmp2);
6184 tcg_temp_free_i32(tmp3);
6185 break;
6186 case NEON_2RM_AESE: case NEON_2RM_AESMC:
6187 if (!arm_feature(env, ARM_FEATURE_V8_AES)
6188 || ((rm | rd) & 1)) {
6189 return 1;
6191 tmp = tcg_const_i32(rd);
6192 tmp2 = tcg_const_i32(rm);
6194 /* Bit 6 is the lowest opcode bit; it distinguishes between
6195 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6197 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6199 if (op == NEON_2RM_AESE) {
6200 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6201 } else {
6202 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6204 tcg_temp_free_i32(tmp);
6205 tcg_temp_free_i32(tmp2);
6206 tcg_temp_free_i32(tmp3);
6207 break;
6208 default:
6209 elementwise:
6210 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6211 if (neon_2rm_is_float_op(op)) {
6212 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6213 neon_reg_offset(rm, pass));
6214 TCGV_UNUSED_I32(tmp);
6215 } else {
6216 tmp = neon_load_reg(rm, pass);
6218 switch (op) {
6219 case NEON_2RM_VREV32:
6220 switch (size) {
6221 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6222 case 1: gen_swap_half(tmp); break;
6223 default: abort();
6225 break;
6226 case NEON_2RM_VREV16:
6227 gen_rev16(tmp);
6228 break;
6229 case NEON_2RM_VCLS:
6230 switch (size) {
6231 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6232 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6233 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6234 default: abort();
6236 break;
6237 case NEON_2RM_VCLZ:
6238 switch (size) {
6239 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6240 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6241 case 2: gen_helper_clz(tmp, tmp); break;
6242 default: abort();
6244 break;
6245 case NEON_2RM_VCNT:
6246 gen_helper_neon_cnt_u8(tmp, tmp);
6247 break;
6248 case NEON_2RM_VMVN:
6249 tcg_gen_not_i32(tmp, tmp);
6250 break;
6251 case NEON_2RM_VQABS:
6252 switch (size) {
6253 case 0:
6254 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6255 break;
6256 case 1:
6257 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6258 break;
6259 case 2:
6260 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6261 break;
6262 default: abort();
6264 break;
6265 case NEON_2RM_VQNEG:
6266 switch (size) {
6267 case 0:
6268 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6269 break;
6270 case 1:
6271 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6272 break;
6273 case 2:
6274 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6275 break;
6276 default: abort();
6278 break;
6279 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6280 tmp2 = tcg_const_i32(0);
6281 switch(size) {
6282 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6283 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6284 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6285 default: abort();
6287 tcg_temp_free_i32(tmp2);
6288 if (op == NEON_2RM_VCLE0) {
6289 tcg_gen_not_i32(tmp, tmp);
6291 break;
6292 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6293 tmp2 = tcg_const_i32(0);
6294 switch(size) {
6295 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6296 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6297 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6298 default: abort();
6300 tcg_temp_free_i32(tmp2);
6301 if (op == NEON_2RM_VCLT0) {
6302 tcg_gen_not_i32(tmp, tmp);
6304 break;
6305 case NEON_2RM_VCEQ0:
6306 tmp2 = tcg_const_i32(0);
6307 switch(size) {
6308 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6309 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6310 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6311 default: abort();
6313 tcg_temp_free_i32(tmp2);
6314 break;
6315 case NEON_2RM_VABS:
6316 switch(size) {
6317 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6318 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6319 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6320 default: abort();
6322 break;
6323 case NEON_2RM_VNEG:
6324 tmp2 = tcg_const_i32(0);
6325 gen_neon_rsb(size, tmp, tmp2);
6326 tcg_temp_free_i32(tmp2);
6327 break;
6328 case NEON_2RM_VCGT0_F:
6330 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6331 tmp2 = tcg_const_i32(0);
6332 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6333 tcg_temp_free_i32(tmp2);
6334 tcg_temp_free_ptr(fpstatus);
6335 break;
6337 case NEON_2RM_VCGE0_F:
6339 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6340 tmp2 = tcg_const_i32(0);
6341 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6342 tcg_temp_free_i32(tmp2);
6343 tcg_temp_free_ptr(fpstatus);
6344 break;
6346 case NEON_2RM_VCEQ0_F:
6348 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6349 tmp2 = tcg_const_i32(0);
6350 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6351 tcg_temp_free_i32(tmp2);
6352 tcg_temp_free_ptr(fpstatus);
6353 break;
6355 case NEON_2RM_VCLE0_F:
6357 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6358 tmp2 = tcg_const_i32(0);
6359 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6360 tcg_temp_free_i32(tmp2);
6361 tcg_temp_free_ptr(fpstatus);
6362 break;
6364 case NEON_2RM_VCLT0_F:
6366 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6367 tmp2 = tcg_const_i32(0);
6368 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6369 tcg_temp_free_i32(tmp2);
6370 tcg_temp_free_ptr(fpstatus);
6371 break;
6373 case NEON_2RM_VABS_F:
6374 gen_vfp_abs(0);
6375 break;
6376 case NEON_2RM_VNEG_F:
6377 gen_vfp_neg(0);
6378 break;
6379 case NEON_2RM_VSWP:
6380 tmp2 = neon_load_reg(rd, pass);
6381 neon_store_reg(rm, pass, tmp2);
6382 break;
6383 case NEON_2RM_VTRN:
6384 tmp2 = neon_load_reg(rd, pass);
6385 switch (size) {
6386 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6387 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6388 default: abort();
6390 neon_store_reg(rm, pass, tmp2);
6391 break;
6392 case NEON_2RM_VRECPE:
6393 gen_helper_recpe_u32(tmp, tmp, cpu_env);
6394 break;
6395 case NEON_2RM_VRSQRTE:
6396 gen_helper_rsqrte_u32(tmp, tmp, cpu_env);
6397 break;
6398 case NEON_2RM_VRECPE_F:
6399 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, cpu_env);
6400 break;
6401 case NEON_2RM_VRSQRTE_F:
6402 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, cpu_env);
6403 break;
6404 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6405 gen_vfp_sito(0, 1);
6406 break;
6407 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6408 gen_vfp_uito(0, 1);
6409 break;
6410 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6411 gen_vfp_tosiz(0, 1);
6412 break;
6413 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6414 gen_vfp_touiz(0, 1);
6415 break;
6416 default:
6417 /* Reserved op values were caught by the
6418 * neon_2rm_sizes[] check earlier.
6420 abort();
6422 if (neon_2rm_is_float_op(op)) {
6423 tcg_gen_st_f32(cpu_F0s, cpu_env,
6424 neon_reg_offset(rd, pass));
6425 } else {
6426 neon_store_reg(rd, pass, tmp);
6429 break;
6431 } else if ((insn & (1 << 10)) == 0) {
6432 /* VTBL, VTBX. */
6433 int n = ((insn >> 8) & 3) + 1;
6434 if ((rn + n) > 32) {
6435 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6436 * helper function running off the end of the register file.
6438 return 1;
6440 n <<= 3;
6441 if (insn & (1 << 6)) {
6442 tmp = neon_load_reg(rd, 0);
6443 } else {
6444 tmp = tcg_temp_new_i32();
6445 tcg_gen_movi_i32(tmp, 0);
6447 tmp2 = neon_load_reg(rm, 0);
6448 tmp4 = tcg_const_i32(rn);
6449 tmp5 = tcg_const_i32(n);
6450 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
6451 tcg_temp_free_i32(tmp);
6452 if (insn & (1 << 6)) {
6453 tmp = neon_load_reg(rd, 1);
6454 } else {
6455 tmp = tcg_temp_new_i32();
6456 tcg_gen_movi_i32(tmp, 0);
6458 tmp3 = neon_load_reg(rm, 1);
6459 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
6460 tcg_temp_free_i32(tmp5);
6461 tcg_temp_free_i32(tmp4);
6462 neon_store_reg(rd, 0, tmp2);
6463 neon_store_reg(rd, 1, tmp3);
6464 tcg_temp_free_i32(tmp);
6465 } else if ((insn & 0x380) == 0) {
6466 /* VDUP */
6467 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6468 return 1;
6470 if (insn & (1 << 19)) {
6471 tmp = neon_load_reg(rm, 1);
6472 } else {
6473 tmp = neon_load_reg(rm, 0);
6475 if (insn & (1 << 16)) {
6476 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6477 } else if (insn & (1 << 17)) {
6478 if ((insn >> 18) & 1)
6479 gen_neon_dup_high16(tmp);
6480 else
6481 gen_neon_dup_low16(tmp);
6483 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6484 tmp2 = tcg_temp_new_i32();
6485 tcg_gen_mov_i32(tmp2, tmp);
6486 neon_store_reg(rd, pass, tmp2);
6488 tcg_temp_free_i32(tmp);
6489 } else {
6490 return 1;
6494 return 0;
6497 static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
6499 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
6500 const ARMCPRegInfo *ri;
6501 ARMCPU *cpu = arm_env_get_cpu(env);
6503 cpnum = (insn >> 8) & 0xf;
6504 if (arm_feature(env, ARM_FEATURE_XSCALE)
6505 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
6506 return 1;
6508 /* First check for coprocessor space used for actual instructions */
6509 switch (cpnum) {
6510 case 0:
6511 case 1:
6512 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
6513 return disas_iwmmxt_insn(env, s, insn);
6514 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
6515 return disas_dsp_insn(env, s, insn);
6517 return 1;
6518 default:
6519 break;
6522 /* Otherwise treat as a generic register access */
6523 is64 = (insn & (1 << 25)) == 0;
6524 if (!is64 && ((insn & (1 << 4)) == 0)) {
6525 /* cdp */
6526 return 1;
6529 crm = insn & 0xf;
6530 if (is64) {
6531 crn = 0;
6532 opc1 = (insn >> 4) & 0xf;
6533 opc2 = 0;
6534 rt2 = (insn >> 16) & 0xf;
6535 } else {
6536 crn = (insn >> 16) & 0xf;
6537 opc1 = (insn >> 21) & 7;
6538 opc2 = (insn >> 5) & 7;
6539 rt2 = 0;
6541 isread = (insn >> 20) & 1;
6542 rt = (insn >> 12) & 0xf;
6544 ri = get_arm_cp_reginfo(cpu,
6545 ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
6546 if (ri) {
6547 /* Check access permissions */
6548 if (!cp_access_ok(env, ri, isread)) {
6549 return 1;
6552 /* Handle special cases first */
6553 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
6554 case ARM_CP_NOP:
6555 return 0;
6556 case ARM_CP_WFI:
6557 if (isread) {
6558 return 1;
6560 gen_set_pc_im(s, s->pc);
6561 s->is_jmp = DISAS_WFI;
6562 return 0;
6563 default:
6564 break;
6567 if (use_icount && (ri->type & ARM_CP_IO)) {
6568 gen_io_start();
6571 if (isread) {
6572 /* Read */
6573 if (is64) {
6574 TCGv_i64 tmp64;
6575 TCGv_i32 tmp;
6576 if (ri->type & ARM_CP_CONST) {
6577 tmp64 = tcg_const_i64(ri->resetvalue);
6578 } else if (ri->readfn) {
6579 TCGv_ptr tmpptr;
6580 gen_set_pc_im(s, s->pc);
6581 tmp64 = tcg_temp_new_i64();
6582 tmpptr = tcg_const_ptr(ri);
6583 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
6584 tcg_temp_free_ptr(tmpptr);
6585 } else {
6586 tmp64 = tcg_temp_new_i64();
6587 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
6589 tmp = tcg_temp_new_i32();
6590 tcg_gen_trunc_i64_i32(tmp, tmp64);
6591 store_reg(s, rt, tmp);
6592 tcg_gen_shri_i64(tmp64, tmp64, 32);
6593 tmp = tcg_temp_new_i32();
6594 tcg_gen_trunc_i64_i32(tmp, tmp64);
6595 tcg_temp_free_i64(tmp64);
6596 store_reg(s, rt2, tmp);
6597 } else {
6598 TCGv_i32 tmp;
6599 if (ri->type & ARM_CP_CONST) {
6600 tmp = tcg_const_i32(ri->resetvalue);
6601 } else if (ri->readfn) {
6602 TCGv_ptr tmpptr;
6603 gen_set_pc_im(s, s->pc);
6604 tmp = tcg_temp_new_i32();
6605 tmpptr = tcg_const_ptr(ri);
6606 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
6607 tcg_temp_free_ptr(tmpptr);
6608 } else {
6609 tmp = load_cpu_offset(ri->fieldoffset);
6611 if (rt == 15) {
6612 /* Destination register of r15 for 32 bit loads sets
6613 * the condition codes from the high 4 bits of the value
6615 gen_set_nzcv(tmp);
6616 tcg_temp_free_i32(tmp);
6617 } else {
6618 store_reg(s, rt, tmp);
6621 } else {
6622 /* Write */
6623 if (ri->type & ARM_CP_CONST) {
6624 /* If not forbidden by access permissions, treat as WI */
6625 return 0;
6628 if (is64) {
6629 TCGv_i32 tmplo, tmphi;
6630 TCGv_i64 tmp64 = tcg_temp_new_i64();
6631 tmplo = load_reg(s, rt);
6632 tmphi = load_reg(s, rt2);
6633 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
6634 tcg_temp_free_i32(tmplo);
6635 tcg_temp_free_i32(tmphi);
6636 if (ri->writefn) {
6637 TCGv_ptr tmpptr = tcg_const_ptr(ri);
6638 gen_set_pc_im(s, s->pc);
6639 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
6640 tcg_temp_free_ptr(tmpptr);
6641 } else {
6642 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
6644 tcg_temp_free_i64(tmp64);
6645 } else {
6646 if (ri->writefn) {
6647 TCGv_i32 tmp;
6648 TCGv_ptr tmpptr;
6649 gen_set_pc_im(s, s->pc);
6650 tmp = load_reg(s, rt);
6651 tmpptr = tcg_const_ptr(ri);
6652 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
6653 tcg_temp_free_ptr(tmpptr);
6654 tcg_temp_free_i32(tmp);
6655 } else {
6656 TCGv_i32 tmp = load_reg(s, rt);
6657 store_cpu_offset(tmp, ri->fieldoffset);
6662 if (use_icount && (ri->type & ARM_CP_IO)) {
6663 /* I/O operations must end the TB here (whether read or write) */
6664 gen_io_end();
6665 gen_lookup_tb(s);
6666 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
6667 /* We default to ending the TB on a coprocessor register write,
6668 * but allow this to be suppressed by the register definition
6669 * (usually only necessary to work around guest bugs).
6671 gen_lookup_tb(s);
6674 return 0;
6677 return 1;
6681 /* Store a 64-bit value to a register pair. Clobbers val. */
6682 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
6684 TCGv_i32 tmp;
6685 tmp = tcg_temp_new_i32();
6686 tcg_gen_trunc_i64_i32(tmp, val);
6687 store_reg(s, rlow, tmp);
6688 tmp = tcg_temp_new_i32();
6689 tcg_gen_shri_i64(val, val, 32);
6690 tcg_gen_trunc_i64_i32(tmp, val);
6691 store_reg(s, rhigh, tmp);
6694 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
6695 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
6697 TCGv_i64 tmp;
6698 TCGv_i32 tmp2;
6700 /* Load value and extend to 64 bits. */
6701 tmp = tcg_temp_new_i64();
6702 tmp2 = load_reg(s, rlow);
6703 tcg_gen_extu_i32_i64(tmp, tmp2);
6704 tcg_temp_free_i32(tmp2);
6705 tcg_gen_add_i64(val, val, tmp);
6706 tcg_temp_free_i64(tmp);
6709 /* load and add a 64-bit value from a register pair. */
6710 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
6712 TCGv_i64 tmp;
6713 TCGv_i32 tmpl;
6714 TCGv_i32 tmph;
6716 /* Load 64-bit value rd:rn. */
6717 tmpl = load_reg(s, rlow);
6718 tmph = load_reg(s, rhigh);
6719 tmp = tcg_temp_new_i64();
6720 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
6721 tcg_temp_free_i32(tmpl);
6722 tcg_temp_free_i32(tmph);
6723 tcg_gen_add_i64(val, val, tmp);
6724 tcg_temp_free_i64(tmp);
6727 /* Set N and Z flags from hi|lo. */
6728 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
6730 tcg_gen_mov_i32(cpu_NF, hi);
6731 tcg_gen_or_i32(cpu_ZF, lo, hi);
6734 /* Load/Store exclusive instructions are implemented by remembering
6735 the value/address loaded, and seeing if these are the same
6736 when the store is performed. This should be sufficient to implement
6737 the architecturally mandated semantics, and avoids having to monitor
6738 regular stores.
6740 In system emulation mode only one CPU will be running at once, so
6741 this sequence is effectively atomic. In user emulation mode we
6742 throw an exception and handle the atomic operation elsewhere. */
6743 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
6744 TCGv_i32 addr, int size)
6746 TCGv_i32 tmp = tcg_temp_new_i32();
6748 switch (size) {
6749 case 0:
6750 gen_aa32_ld8u(tmp, addr, IS_USER(s));
6751 break;
6752 case 1:
6753 gen_aa32_ld16u(tmp, addr, IS_USER(s));
6754 break;
6755 case 2:
6756 case 3:
6757 gen_aa32_ld32u(tmp, addr, IS_USER(s));
6758 break;
6759 default:
6760 abort();
6762 tcg_gen_mov_i32(cpu_exclusive_val, tmp);
6763 store_reg(s, rt, tmp);
6764 if (size == 3) {
6765 TCGv_i32 tmp2 = tcg_temp_new_i32();
6766 tcg_gen_addi_i32(tmp2, addr, 4);
6767 tmp = tcg_temp_new_i32();
6768 gen_aa32_ld32u(tmp, tmp2, IS_USER(s));
6769 tcg_temp_free_i32(tmp2);
6770 tcg_gen_mov_i32(cpu_exclusive_high, tmp);
6771 store_reg(s, rt2, tmp);
6773 tcg_gen_mov_i32(cpu_exclusive_addr, addr);
6776 static void gen_clrex(DisasContext *s)
6778 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6781 #ifdef CONFIG_USER_ONLY
6782 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6783 TCGv_i32 addr, int size)
6785 tcg_gen_mov_i32(cpu_exclusive_test, addr);
6786 tcg_gen_movi_i32(cpu_exclusive_info,
6787 size | (rd << 4) | (rt << 8) | (rt2 << 12));
6788 gen_exception_insn(s, 4, EXCP_STREX);
6790 #else
6791 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
6792 TCGv_i32 addr, int size)
6794 TCGv_i32 tmp;
6795 int done_label;
6796 int fail_label;
6798 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
6799 [addr] = {Rt};
6800 {Rd} = 0;
6801 } else {
6802 {Rd} = 1;
6803 } */
6804 fail_label = gen_new_label();
6805 done_label = gen_new_label();
6806 tcg_gen_brcond_i32(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
6807 tmp = tcg_temp_new_i32();
6808 switch (size) {
6809 case 0:
6810 gen_aa32_ld8u(tmp, addr, IS_USER(s));
6811 break;
6812 case 1:
6813 gen_aa32_ld16u(tmp, addr, IS_USER(s));
6814 break;
6815 case 2:
6816 case 3:
6817 gen_aa32_ld32u(tmp, addr, IS_USER(s));
6818 break;
6819 default:
6820 abort();
6822 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
6823 tcg_temp_free_i32(tmp);
6824 if (size == 3) {
6825 TCGv_i32 tmp2 = tcg_temp_new_i32();
6826 tcg_gen_addi_i32(tmp2, addr, 4);
6827 tmp = tcg_temp_new_i32();
6828 gen_aa32_ld32u(tmp, tmp2, IS_USER(s));
6829 tcg_temp_free_i32(tmp2);
6830 tcg_gen_brcond_i32(TCG_COND_NE, tmp, cpu_exclusive_high, fail_label);
6831 tcg_temp_free_i32(tmp);
6833 tmp = load_reg(s, rt);
6834 switch (size) {
6835 case 0:
6836 gen_aa32_st8(tmp, addr, IS_USER(s));
6837 break;
6838 case 1:
6839 gen_aa32_st16(tmp, addr, IS_USER(s));
6840 break;
6841 case 2:
6842 case 3:
6843 gen_aa32_st32(tmp, addr, IS_USER(s));
6844 break;
6845 default:
6846 abort();
6848 tcg_temp_free_i32(tmp);
6849 if (size == 3) {
6850 tcg_gen_addi_i32(addr, addr, 4);
6851 tmp = load_reg(s, rt2);
6852 gen_aa32_st32(tmp, addr, IS_USER(s));
6853 tcg_temp_free_i32(tmp);
6855 tcg_gen_movi_i32(cpu_R[rd], 0);
6856 tcg_gen_br(done_label);
6857 gen_set_label(fail_label);
6858 tcg_gen_movi_i32(cpu_R[rd], 1);
6859 gen_set_label(done_label);
6860 tcg_gen_movi_i32(cpu_exclusive_addr, -1);
6862 #endif
6864 /* gen_srs:
6865 * @env: CPUARMState
6866 * @s: DisasContext
6867 * @mode: mode field from insn (which stack to store to)
6868 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
6869 * @writeback: true if writeback bit set
6871 * Generate code for the SRS (Store Return State) insn.
6873 static void gen_srs(DisasContext *s,
6874 uint32_t mode, uint32_t amode, bool writeback)
6876 int32_t offset;
6877 TCGv_i32 addr = tcg_temp_new_i32();
6878 TCGv_i32 tmp = tcg_const_i32(mode);
6879 gen_helper_get_r13_banked(addr, cpu_env, tmp);
6880 tcg_temp_free_i32(tmp);
6881 switch (amode) {
6882 case 0: /* DA */
6883 offset = -4;
6884 break;
6885 case 1: /* IA */
6886 offset = 0;
6887 break;
6888 case 2: /* DB */
6889 offset = -8;
6890 break;
6891 case 3: /* IB */
6892 offset = 4;
6893 break;
6894 default:
6895 abort();
6897 tcg_gen_addi_i32(addr, addr, offset);
6898 tmp = load_reg(s, 14);
6899 gen_aa32_st32(tmp, addr, 0);
6900 tcg_temp_free_i32(tmp);
6901 tmp = load_cpu_field(spsr);
6902 tcg_gen_addi_i32(addr, addr, 4);
6903 gen_aa32_st32(tmp, addr, 0);
6904 tcg_temp_free_i32(tmp);
6905 if (writeback) {
6906 switch (amode) {
6907 case 0:
6908 offset = -8;
6909 break;
6910 case 1:
6911 offset = 4;
6912 break;
6913 case 2:
6914 offset = -4;
6915 break;
6916 case 3:
6917 offset = 0;
6918 break;
6919 default:
6920 abort();
6922 tcg_gen_addi_i32(addr, addr, offset);
6923 tmp = tcg_const_i32(mode);
6924 gen_helper_set_r13_banked(cpu_env, tmp, addr);
6925 tcg_temp_free_i32(tmp);
6927 tcg_temp_free_i32(addr);
6930 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
6932 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
6933 TCGv_i32 tmp;
6934 TCGv_i32 tmp2;
6935 TCGv_i32 tmp3;
6936 TCGv_i32 addr;
6937 TCGv_i64 tmp64;
6939 insn = arm_ldl_code(env, s->pc, s->bswap_code);
6940 s->pc += 4;
6942 /* M variants do not implement ARM mode. */
6943 if (IS_M(env))
6944 goto illegal_op;
6945 cond = insn >> 28;
6946 if (cond == 0xf){
6947 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
6948 * choose to UNDEF. In ARMv5 and above the space is used
6949 * for miscellaneous unconditional instructions.
6951 ARCH(5);
6953 /* Unconditional instructions. */
6954 if (((insn >> 25) & 7) == 1) {
6955 /* NEON Data processing. */
6956 if (!arm_feature(env, ARM_FEATURE_NEON))
6957 goto illegal_op;
6959 if (disas_neon_data_insn(env, s, insn))
6960 goto illegal_op;
6961 return;
6963 if ((insn & 0x0f100000) == 0x04000000) {
6964 /* NEON load/store. */
6965 if (!arm_feature(env, ARM_FEATURE_NEON))
6966 goto illegal_op;
6968 if (disas_neon_ls_insn(env, s, insn))
6969 goto illegal_op;
6970 return;
6972 if ((insn & 0x0f000e10) == 0x0e000a00) {
6973 /* VFP. */
6974 if (disas_vfp_insn(env, s, insn)) {
6975 goto illegal_op;
6977 return;
6979 if (((insn & 0x0f30f000) == 0x0510f000) ||
6980 ((insn & 0x0f30f010) == 0x0710f000)) {
6981 if ((insn & (1 << 22)) == 0) {
6982 /* PLDW; v7MP */
6983 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6984 goto illegal_op;
6987 /* Otherwise PLD; v5TE+ */
6988 ARCH(5TE);
6989 return;
6991 if (((insn & 0x0f70f000) == 0x0450f000) ||
6992 ((insn & 0x0f70f010) == 0x0650f000)) {
6993 ARCH(7);
6994 return; /* PLI; V7 */
6996 if (((insn & 0x0f700000) == 0x04100000) ||
6997 ((insn & 0x0f700010) == 0x06100000)) {
6998 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
6999 goto illegal_op;
7001 return; /* v7MP: Unallocated memory hint: must NOP */
7004 if ((insn & 0x0ffffdff) == 0x01010000) {
7005 ARCH(6);
7006 /* setend */
7007 if (((insn >> 9) & 1) != s->bswap_code) {
7008 /* Dynamic endianness switching not implemented. */
7009 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
7010 goto illegal_op;
7012 return;
7013 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7014 switch ((insn >> 4) & 0xf) {
7015 case 1: /* clrex */
7016 ARCH(6K);
7017 gen_clrex(s);
7018 return;
7019 case 4: /* dsb */
7020 case 5: /* dmb */
7021 case 6: /* isb */
7022 ARCH(7);
7023 /* We don't emulate caches so these are a no-op. */
7024 return;
7025 default:
7026 goto illegal_op;
7028 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7029 /* srs */
7030 if (IS_USER(s)) {
7031 goto illegal_op;
7033 ARCH(6);
7034 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
7035 return;
7036 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
7037 /* rfe */
7038 int32_t offset;
7039 if (IS_USER(s))
7040 goto illegal_op;
7041 ARCH(6);
7042 rn = (insn >> 16) & 0xf;
7043 addr = load_reg(s, rn);
7044 i = (insn >> 23) & 3;
7045 switch (i) {
7046 case 0: offset = -4; break; /* DA */
7047 case 1: offset = 0; break; /* IA */
7048 case 2: offset = -8; break; /* DB */
7049 case 3: offset = 4; break; /* IB */
7050 default: abort();
7052 if (offset)
7053 tcg_gen_addi_i32(addr, addr, offset);
7054 /* Load PC into tmp and CPSR into tmp2. */
7055 tmp = tcg_temp_new_i32();
7056 gen_aa32_ld32u(tmp, addr, 0);
7057 tcg_gen_addi_i32(addr, addr, 4);
7058 tmp2 = tcg_temp_new_i32();
7059 gen_aa32_ld32u(tmp2, addr, 0);
7060 if (insn & (1 << 21)) {
7061 /* Base writeback. */
7062 switch (i) {
7063 case 0: offset = -8; break;
7064 case 1: offset = 4; break;
7065 case 2: offset = -4; break;
7066 case 3: offset = 0; break;
7067 default: abort();
7069 if (offset)
7070 tcg_gen_addi_i32(addr, addr, offset);
7071 store_reg(s, rn, addr);
7072 } else {
7073 tcg_temp_free_i32(addr);
7075 gen_rfe(s, tmp, tmp2);
7076 return;
7077 } else if ((insn & 0x0e000000) == 0x0a000000) {
7078 /* branch link and change to thumb (blx <offset>) */
7079 int32_t offset;
7081 val = (uint32_t)s->pc;
7082 tmp = tcg_temp_new_i32();
7083 tcg_gen_movi_i32(tmp, val);
7084 store_reg(s, 14, tmp);
7085 /* Sign-extend the 24-bit offset */
7086 offset = (((int32_t)insn) << 8) >> 8;
7087 /* offset * 4 + bit24 * 2 + (thumb bit) */
7088 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7089 /* pipeline offset */
7090 val += 4;
7091 /* protected by ARCH(5); above, near the start of uncond block */
7092 gen_bx_im(s, val);
7093 return;
7094 } else if ((insn & 0x0e000f00) == 0x0c000100) {
7095 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7096 /* iWMMXt register transfer. */
7097 if (env->cp15.c15_cpar & (1 << 1))
7098 if (!disas_iwmmxt_insn(env, s, insn))
7099 return;
7101 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7102 /* Coprocessor double register transfer. */
7103 ARCH(5TE);
7104 } else if ((insn & 0x0f000010) == 0x0e000010) {
7105 /* Additional coprocessor register transfer. */
7106 } else if ((insn & 0x0ff10020) == 0x01000000) {
7107 uint32_t mask;
7108 uint32_t val;
7109 /* cps (privileged) */
7110 if (IS_USER(s))
7111 return;
7112 mask = val = 0;
7113 if (insn & (1 << 19)) {
7114 if (insn & (1 << 8))
7115 mask |= CPSR_A;
7116 if (insn & (1 << 7))
7117 mask |= CPSR_I;
7118 if (insn & (1 << 6))
7119 mask |= CPSR_F;
7120 if (insn & (1 << 18))
7121 val |= mask;
7123 if (insn & (1 << 17)) {
7124 mask |= CPSR_M;
7125 val |= (insn & 0x1f);
7127 if (mask) {
7128 gen_set_psr_im(s, mask, 0, val);
7130 return;
7132 goto illegal_op;
7134 if (cond != 0xe) {
7135 /* if not always execute, we generate a conditional jump to
7136 next instruction */
7137 s->condlabel = gen_new_label();
7138 arm_gen_test_cc(cond ^ 1, s->condlabel);
7139 s->condjmp = 1;
7141 if ((insn & 0x0f900000) == 0x03000000) {
7142 if ((insn & (1 << 21)) == 0) {
7143 ARCH(6T2);
7144 rd = (insn >> 12) & 0xf;
7145 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7146 if ((insn & (1 << 22)) == 0) {
7147 /* MOVW */
7148 tmp = tcg_temp_new_i32();
7149 tcg_gen_movi_i32(tmp, val);
7150 } else {
7151 /* MOVT */
7152 tmp = load_reg(s, rd);
7153 tcg_gen_ext16u_i32(tmp, tmp);
7154 tcg_gen_ori_i32(tmp, tmp, val << 16);
7156 store_reg(s, rd, tmp);
7157 } else {
7158 if (((insn >> 12) & 0xf) != 0xf)
7159 goto illegal_op;
7160 if (((insn >> 16) & 0xf) == 0) {
7161 gen_nop_hint(s, insn & 0xff);
7162 } else {
7163 /* CPSR = immediate */
7164 val = insn & 0xff;
7165 shift = ((insn >> 8) & 0xf) * 2;
7166 if (shift)
7167 val = (val >> shift) | (val << (32 - shift));
7168 i = ((insn & (1 << 22)) != 0);
7169 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
7170 goto illegal_op;
7173 } else if ((insn & 0x0f900000) == 0x01000000
7174 && (insn & 0x00000090) != 0x00000090) {
7175 /* miscellaneous instructions */
7176 op1 = (insn >> 21) & 3;
7177 sh = (insn >> 4) & 0xf;
7178 rm = insn & 0xf;
7179 switch (sh) {
7180 case 0x0: /* move program status register */
7181 if (op1 & 1) {
7182 /* PSR = reg */
7183 tmp = load_reg(s, rm);
7184 i = ((op1 & 2) != 0);
7185 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
7186 goto illegal_op;
7187 } else {
7188 /* reg = PSR */
7189 rd = (insn >> 12) & 0xf;
7190 if (op1 & 2) {
7191 if (IS_USER(s))
7192 goto illegal_op;
7193 tmp = load_cpu_field(spsr);
7194 } else {
7195 tmp = tcg_temp_new_i32();
7196 gen_helper_cpsr_read(tmp, cpu_env);
7198 store_reg(s, rd, tmp);
7200 break;
7201 case 0x1:
7202 if (op1 == 1) {
7203 /* branch/exchange thumb (bx). */
7204 ARCH(4T);
7205 tmp = load_reg(s, rm);
7206 gen_bx(s, tmp);
7207 } else if (op1 == 3) {
7208 /* clz */
7209 ARCH(5);
7210 rd = (insn >> 12) & 0xf;
7211 tmp = load_reg(s, rm);
7212 gen_helper_clz(tmp, tmp);
7213 store_reg(s, rd, tmp);
7214 } else {
7215 goto illegal_op;
7217 break;
7218 case 0x2:
7219 if (op1 == 1) {
7220 ARCH(5J); /* bxj */
7221 /* Trivial implementation equivalent to bx. */
7222 tmp = load_reg(s, rm);
7223 gen_bx(s, tmp);
7224 } else {
7225 goto illegal_op;
7227 break;
7228 case 0x3:
7229 if (op1 != 1)
7230 goto illegal_op;
7232 ARCH(5);
7233 /* branch link/exchange thumb (blx) */
7234 tmp = load_reg(s, rm);
7235 tmp2 = tcg_temp_new_i32();
7236 tcg_gen_movi_i32(tmp2, s->pc);
7237 store_reg(s, 14, tmp2);
7238 gen_bx(s, tmp);
7239 break;
7240 case 0x5: /* saturating add/subtract */
7241 ARCH(5TE);
7242 rd = (insn >> 12) & 0xf;
7243 rn = (insn >> 16) & 0xf;
7244 tmp = load_reg(s, rm);
7245 tmp2 = load_reg(s, rn);
7246 if (op1 & 2)
7247 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
7248 if (op1 & 1)
7249 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
7250 else
7251 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7252 tcg_temp_free_i32(tmp2);
7253 store_reg(s, rd, tmp);
7254 break;
7255 case 7:
7256 /* SMC instruction (op1 == 3)
7257 and undefined instructions (op1 == 0 || op1 == 2)
7258 will trap */
7259 if (op1 != 1) {
7260 goto illegal_op;
7262 /* bkpt */
7263 ARCH(5);
7264 gen_exception_insn(s, 4, EXCP_BKPT);
7265 break;
7266 case 0x8: /* signed multiply */
7267 case 0xa:
7268 case 0xc:
7269 case 0xe:
7270 ARCH(5TE);
7271 rs = (insn >> 8) & 0xf;
7272 rn = (insn >> 12) & 0xf;
7273 rd = (insn >> 16) & 0xf;
7274 if (op1 == 1) {
7275 /* (32 * 16) >> 16 */
7276 tmp = load_reg(s, rm);
7277 tmp2 = load_reg(s, rs);
7278 if (sh & 4)
7279 tcg_gen_sari_i32(tmp2, tmp2, 16);
7280 else
7281 gen_sxth(tmp2);
7282 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7283 tcg_gen_shri_i64(tmp64, tmp64, 16);
7284 tmp = tcg_temp_new_i32();
7285 tcg_gen_trunc_i64_i32(tmp, tmp64);
7286 tcg_temp_free_i64(tmp64);
7287 if ((sh & 2) == 0) {
7288 tmp2 = load_reg(s, rn);
7289 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7290 tcg_temp_free_i32(tmp2);
7292 store_reg(s, rd, tmp);
7293 } else {
7294 /* 16 * 16 */
7295 tmp = load_reg(s, rm);
7296 tmp2 = load_reg(s, rs);
7297 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7298 tcg_temp_free_i32(tmp2);
7299 if (op1 == 2) {
7300 tmp64 = tcg_temp_new_i64();
7301 tcg_gen_ext_i32_i64(tmp64, tmp);
7302 tcg_temp_free_i32(tmp);
7303 gen_addq(s, tmp64, rn, rd);
7304 gen_storeq_reg(s, rn, rd, tmp64);
7305 tcg_temp_free_i64(tmp64);
7306 } else {
7307 if (op1 == 0) {
7308 tmp2 = load_reg(s, rn);
7309 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7310 tcg_temp_free_i32(tmp2);
7312 store_reg(s, rd, tmp);
7315 break;
7316 default:
7317 goto illegal_op;
7319 } else if (((insn & 0x0e000000) == 0 &&
7320 (insn & 0x00000090) != 0x90) ||
7321 ((insn & 0x0e000000) == (1 << 25))) {
7322 int set_cc, logic_cc, shiftop;
7324 op1 = (insn >> 21) & 0xf;
7325 set_cc = (insn >> 20) & 1;
7326 logic_cc = table_logic_cc[op1] & set_cc;
7328 /* data processing instruction */
7329 if (insn & (1 << 25)) {
7330 /* immediate operand */
7331 val = insn & 0xff;
7332 shift = ((insn >> 8) & 0xf) * 2;
7333 if (shift) {
7334 val = (val >> shift) | (val << (32 - shift));
7336 tmp2 = tcg_temp_new_i32();
7337 tcg_gen_movi_i32(tmp2, val);
7338 if (logic_cc && shift) {
7339 gen_set_CF_bit31(tmp2);
7341 } else {
7342 /* register */
7343 rm = (insn) & 0xf;
7344 tmp2 = load_reg(s, rm);
7345 shiftop = (insn >> 5) & 3;
7346 if (!(insn & (1 << 4))) {
7347 shift = (insn >> 7) & 0x1f;
7348 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7349 } else {
7350 rs = (insn >> 8) & 0xf;
7351 tmp = load_reg(s, rs);
7352 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7355 if (op1 != 0x0f && op1 != 0x0d) {
7356 rn = (insn >> 16) & 0xf;
7357 tmp = load_reg(s, rn);
7358 } else {
7359 TCGV_UNUSED_I32(tmp);
7361 rd = (insn >> 12) & 0xf;
7362 switch(op1) {
7363 case 0x00:
7364 tcg_gen_and_i32(tmp, tmp, tmp2);
7365 if (logic_cc) {
7366 gen_logic_CC(tmp);
7368 store_reg_bx(env, s, rd, tmp);
7369 break;
7370 case 0x01:
7371 tcg_gen_xor_i32(tmp, tmp, tmp2);
7372 if (logic_cc) {
7373 gen_logic_CC(tmp);
7375 store_reg_bx(env, s, rd, tmp);
7376 break;
7377 case 0x02:
7378 if (set_cc && rd == 15) {
7379 /* SUBS r15, ... is used for exception return. */
7380 if (IS_USER(s)) {
7381 goto illegal_op;
7383 gen_sub_CC(tmp, tmp, tmp2);
7384 gen_exception_return(s, tmp);
7385 } else {
7386 if (set_cc) {
7387 gen_sub_CC(tmp, tmp, tmp2);
7388 } else {
7389 tcg_gen_sub_i32(tmp, tmp, tmp2);
7391 store_reg_bx(env, s, rd, tmp);
7393 break;
7394 case 0x03:
7395 if (set_cc) {
7396 gen_sub_CC(tmp, tmp2, tmp);
7397 } else {
7398 tcg_gen_sub_i32(tmp, tmp2, tmp);
7400 store_reg_bx(env, s, rd, tmp);
7401 break;
7402 case 0x04:
7403 if (set_cc) {
7404 gen_add_CC(tmp, tmp, tmp2);
7405 } else {
7406 tcg_gen_add_i32(tmp, tmp, tmp2);
7408 store_reg_bx(env, s, rd, tmp);
7409 break;
7410 case 0x05:
7411 if (set_cc) {
7412 gen_adc_CC(tmp, tmp, tmp2);
7413 } else {
7414 gen_add_carry(tmp, tmp, tmp2);
7416 store_reg_bx(env, s, rd, tmp);
7417 break;
7418 case 0x06:
7419 if (set_cc) {
7420 gen_sbc_CC(tmp, tmp, tmp2);
7421 } else {
7422 gen_sub_carry(tmp, tmp, tmp2);
7424 store_reg_bx(env, s, rd, tmp);
7425 break;
7426 case 0x07:
7427 if (set_cc) {
7428 gen_sbc_CC(tmp, tmp2, tmp);
7429 } else {
7430 gen_sub_carry(tmp, tmp2, tmp);
7432 store_reg_bx(env, s, rd, tmp);
7433 break;
7434 case 0x08:
7435 if (set_cc) {
7436 tcg_gen_and_i32(tmp, tmp, tmp2);
7437 gen_logic_CC(tmp);
7439 tcg_temp_free_i32(tmp);
7440 break;
7441 case 0x09:
7442 if (set_cc) {
7443 tcg_gen_xor_i32(tmp, tmp, tmp2);
7444 gen_logic_CC(tmp);
7446 tcg_temp_free_i32(tmp);
7447 break;
7448 case 0x0a:
7449 if (set_cc) {
7450 gen_sub_CC(tmp, tmp, tmp2);
7452 tcg_temp_free_i32(tmp);
7453 break;
7454 case 0x0b:
7455 if (set_cc) {
7456 gen_add_CC(tmp, tmp, tmp2);
7458 tcg_temp_free_i32(tmp);
7459 break;
7460 case 0x0c:
7461 tcg_gen_or_i32(tmp, tmp, tmp2);
7462 if (logic_cc) {
7463 gen_logic_CC(tmp);
7465 store_reg_bx(env, s, rd, tmp);
7466 break;
7467 case 0x0d:
7468 if (logic_cc && rd == 15) {
7469 /* MOVS r15, ... is used for exception return. */
7470 if (IS_USER(s)) {
7471 goto illegal_op;
7473 gen_exception_return(s, tmp2);
7474 } else {
7475 if (logic_cc) {
7476 gen_logic_CC(tmp2);
7478 store_reg_bx(env, s, rd, tmp2);
7480 break;
7481 case 0x0e:
7482 tcg_gen_andc_i32(tmp, tmp, tmp2);
7483 if (logic_cc) {
7484 gen_logic_CC(tmp);
7486 store_reg_bx(env, s, rd, tmp);
7487 break;
7488 default:
7489 case 0x0f:
7490 tcg_gen_not_i32(tmp2, tmp2);
7491 if (logic_cc) {
7492 gen_logic_CC(tmp2);
7494 store_reg_bx(env, s, rd, tmp2);
7495 break;
7497 if (op1 != 0x0f && op1 != 0x0d) {
7498 tcg_temp_free_i32(tmp2);
7500 } else {
7501 /* other instructions */
7502 op1 = (insn >> 24) & 0xf;
7503 switch(op1) {
7504 case 0x0:
7505 case 0x1:
7506 /* multiplies, extra load/stores */
7507 sh = (insn >> 5) & 3;
7508 if (sh == 0) {
7509 if (op1 == 0x0) {
7510 rd = (insn >> 16) & 0xf;
7511 rn = (insn >> 12) & 0xf;
7512 rs = (insn >> 8) & 0xf;
7513 rm = (insn) & 0xf;
7514 op1 = (insn >> 20) & 0xf;
7515 switch (op1) {
7516 case 0: case 1: case 2: case 3: case 6:
7517 /* 32 bit mul */
7518 tmp = load_reg(s, rs);
7519 tmp2 = load_reg(s, rm);
7520 tcg_gen_mul_i32(tmp, tmp, tmp2);
7521 tcg_temp_free_i32(tmp2);
7522 if (insn & (1 << 22)) {
7523 /* Subtract (mls) */
7524 ARCH(6T2);
7525 tmp2 = load_reg(s, rn);
7526 tcg_gen_sub_i32(tmp, tmp2, tmp);
7527 tcg_temp_free_i32(tmp2);
7528 } else if (insn & (1 << 21)) {
7529 /* Add */
7530 tmp2 = load_reg(s, rn);
7531 tcg_gen_add_i32(tmp, tmp, tmp2);
7532 tcg_temp_free_i32(tmp2);
7534 if (insn & (1 << 20))
7535 gen_logic_CC(tmp);
7536 store_reg(s, rd, tmp);
7537 break;
7538 case 4:
7539 /* 64 bit mul double accumulate (UMAAL) */
7540 ARCH(6);
7541 tmp = load_reg(s, rs);
7542 tmp2 = load_reg(s, rm);
7543 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
7544 gen_addq_lo(s, tmp64, rn);
7545 gen_addq_lo(s, tmp64, rd);
7546 gen_storeq_reg(s, rn, rd, tmp64);
7547 tcg_temp_free_i64(tmp64);
7548 break;
7549 case 8: case 9: case 10: case 11:
7550 case 12: case 13: case 14: case 15:
7551 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
7552 tmp = load_reg(s, rs);
7553 tmp2 = load_reg(s, rm);
7554 if (insn & (1 << 22)) {
7555 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
7556 } else {
7557 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
7559 if (insn & (1 << 21)) { /* mult accumulate */
7560 TCGv_i32 al = load_reg(s, rn);
7561 TCGv_i32 ah = load_reg(s, rd);
7562 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
7563 tcg_temp_free_i32(al);
7564 tcg_temp_free_i32(ah);
7566 if (insn & (1 << 20)) {
7567 gen_logicq_cc(tmp, tmp2);
7569 store_reg(s, rn, tmp);
7570 store_reg(s, rd, tmp2);
7571 break;
7572 default:
7573 goto illegal_op;
7575 } else {
7576 rn = (insn >> 16) & 0xf;
7577 rd = (insn >> 12) & 0xf;
7578 if (insn & (1 << 23)) {
7579 /* load/store exclusive */
7580 int op2 = (insn >> 8) & 3;
7581 op1 = (insn >> 21) & 0x3;
7583 switch (op2) {
7584 case 0: /* lda/stl */
7585 if (op1 == 1) {
7586 goto illegal_op;
7588 ARCH(8);
7589 break;
7590 case 1: /* reserved */
7591 goto illegal_op;
7592 case 2: /* ldaex/stlex */
7593 ARCH(8);
7594 break;
7595 case 3: /* ldrex/strex */
7596 if (op1) {
7597 ARCH(6K);
7598 } else {
7599 ARCH(6);
7601 break;
7604 addr = tcg_temp_local_new_i32();
7605 load_reg_var(s, addr, rn);
7607 /* Since the emulation does not have barriers,
7608 the acquire/release semantics need no special
7609 handling */
7610 if (op2 == 0) {
7611 if (insn & (1 << 20)) {
7612 tmp = tcg_temp_new_i32();
7613 switch (op1) {
7614 case 0: /* lda */
7615 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7616 break;
7617 case 2: /* ldab */
7618 gen_aa32_ld8u(tmp, addr, IS_USER(s));
7619 break;
7620 case 3: /* ldah */
7621 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7622 break;
7623 default:
7624 abort();
7626 store_reg(s, rd, tmp);
7627 } else {
7628 rm = insn & 0xf;
7629 tmp = load_reg(s, rm);
7630 switch (op1) {
7631 case 0: /* stl */
7632 gen_aa32_st32(tmp, addr, IS_USER(s));
7633 break;
7634 case 2: /* stlb */
7635 gen_aa32_st8(tmp, addr, IS_USER(s));
7636 break;
7637 case 3: /* stlh */
7638 gen_aa32_st16(tmp, addr, IS_USER(s));
7639 break;
7640 default:
7641 abort();
7643 tcg_temp_free_i32(tmp);
7645 } else if (insn & (1 << 20)) {
7646 switch (op1) {
7647 case 0: /* ldrex */
7648 gen_load_exclusive(s, rd, 15, addr, 2);
7649 break;
7650 case 1: /* ldrexd */
7651 gen_load_exclusive(s, rd, rd + 1, addr, 3);
7652 break;
7653 case 2: /* ldrexb */
7654 gen_load_exclusive(s, rd, 15, addr, 0);
7655 break;
7656 case 3: /* ldrexh */
7657 gen_load_exclusive(s, rd, 15, addr, 1);
7658 break;
7659 default:
7660 abort();
7662 } else {
7663 rm = insn & 0xf;
7664 switch (op1) {
7665 case 0: /* strex */
7666 gen_store_exclusive(s, rd, rm, 15, addr, 2);
7667 break;
7668 case 1: /* strexd */
7669 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
7670 break;
7671 case 2: /* strexb */
7672 gen_store_exclusive(s, rd, rm, 15, addr, 0);
7673 break;
7674 case 3: /* strexh */
7675 gen_store_exclusive(s, rd, rm, 15, addr, 1);
7676 break;
7677 default:
7678 abort();
7681 tcg_temp_free_i32(addr);
7682 } else {
7683 /* SWP instruction */
7684 rm = (insn) & 0xf;
7686 /* ??? This is not really atomic. However we know
7687 we never have multiple CPUs running in parallel,
7688 so it is good enough. */
7689 addr = load_reg(s, rn);
7690 tmp = load_reg(s, rm);
7691 tmp2 = tcg_temp_new_i32();
7692 if (insn & (1 << 22)) {
7693 gen_aa32_ld8u(tmp2, addr, IS_USER(s));
7694 gen_aa32_st8(tmp, addr, IS_USER(s));
7695 } else {
7696 gen_aa32_ld32u(tmp2, addr, IS_USER(s));
7697 gen_aa32_st32(tmp, addr, IS_USER(s));
7699 tcg_temp_free_i32(tmp);
7700 tcg_temp_free_i32(addr);
7701 store_reg(s, rd, tmp2);
7704 } else {
7705 int address_offset;
7706 int load;
7707 /* Misc load/store */
7708 rn = (insn >> 16) & 0xf;
7709 rd = (insn >> 12) & 0xf;
7710 addr = load_reg(s, rn);
7711 if (insn & (1 << 24))
7712 gen_add_datah_offset(s, insn, 0, addr);
7713 address_offset = 0;
7714 if (insn & (1 << 20)) {
7715 /* load */
7716 tmp = tcg_temp_new_i32();
7717 switch(sh) {
7718 case 1:
7719 gen_aa32_ld16u(tmp, addr, IS_USER(s));
7720 break;
7721 case 2:
7722 gen_aa32_ld8s(tmp, addr, IS_USER(s));
7723 break;
7724 default:
7725 case 3:
7726 gen_aa32_ld16s(tmp, addr, IS_USER(s));
7727 break;
7729 load = 1;
7730 } else if (sh & 2) {
7731 ARCH(5TE);
7732 /* doubleword */
7733 if (sh & 1) {
7734 /* store */
7735 tmp = load_reg(s, rd);
7736 gen_aa32_st32(tmp, addr, IS_USER(s));
7737 tcg_temp_free_i32(tmp);
7738 tcg_gen_addi_i32(addr, addr, 4);
7739 tmp = load_reg(s, rd + 1);
7740 gen_aa32_st32(tmp, addr, IS_USER(s));
7741 tcg_temp_free_i32(tmp);
7742 load = 0;
7743 } else {
7744 /* load */
7745 tmp = tcg_temp_new_i32();
7746 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7747 store_reg(s, rd, tmp);
7748 tcg_gen_addi_i32(addr, addr, 4);
7749 tmp = tcg_temp_new_i32();
7750 gen_aa32_ld32u(tmp, addr, IS_USER(s));
7751 rd++;
7752 load = 1;
7754 address_offset = -4;
7755 } else {
7756 /* store */
7757 tmp = load_reg(s, rd);
7758 gen_aa32_st16(tmp, addr, IS_USER(s));
7759 tcg_temp_free_i32(tmp);
7760 load = 0;
7762 /* Perform base writeback before the loaded value to
7763 ensure correct behavior with overlapping index registers.
7764 ldrd with base writeback is is undefined if the
7765 destination and index registers overlap. */
7766 if (!(insn & (1 << 24))) {
7767 gen_add_datah_offset(s, insn, address_offset, addr);
7768 store_reg(s, rn, addr);
7769 } else if (insn & (1 << 21)) {
7770 if (address_offset)
7771 tcg_gen_addi_i32(addr, addr, address_offset);
7772 store_reg(s, rn, addr);
7773 } else {
7774 tcg_temp_free_i32(addr);
7776 if (load) {
7777 /* Complete the load. */
7778 store_reg(s, rd, tmp);
7781 break;
7782 case 0x4:
7783 case 0x5:
7784 goto do_ldst;
7785 case 0x6:
7786 case 0x7:
7787 if (insn & (1 << 4)) {
7788 ARCH(6);
7789 /* Armv6 Media instructions. */
7790 rm = insn & 0xf;
7791 rn = (insn >> 16) & 0xf;
7792 rd = (insn >> 12) & 0xf;
7793 rs = (insn >> 8) & 0xf;
7794 switch ((insn >> 23) & 3) {
7795 case 0: /* Parallel add/subtract. */
7796 op1 = (insn >> 20) & 7;
7797 tmp = load_reg(s, rn);
7798 tmp2 = load_reg(s, rm);
7799 sh = (insn >> 5) & 7;
7800 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
7801 goto illegal_op;
7802 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
7803 tcg_temp_free_i32(tmp2);
7804 store_reg(s, rd, tmp);
7805 break;
7806 case 1:
7807 if ((insn & 0x00700020) == 0) {
7808 /* Halfword pack. */
7809 tmp = load_reg(s, rn);
7810 tmp2 = load_reg(s, rm);
7811 shift = (insn >> 7) & 0x1f;
7812 if (insn & (1 << 6)) {
7813 /* pkhtb */
7814 if (shift == 0)
7815 shift = 31;
7816 tcg_gen_sari_i32(tmp2, tmp2, shift);
7817 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
7818 tcg_gen_ext16u_i32(tmp2, tmp2);
7819 } else {
7820 /* pkhbt */
7821 if (shift)
7822 tcg_gen_shli_i32(tmp2, tmp2, shift);
7823 tcg_gen_ext16u_i32(tmp, tmp);
7824 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
7826 tcg_gen_or_i32(tmp, tmp, tmp2);
7827 tcg_temp_free_i32(tmp2);
7828 store_reg(s, rd, tmp);
7829 } else if ((insn & 0x00200020) == 0x00200000) {
7830 /* [us]sat */
7831 tmp = load_reg(s, rm);
7832 shift = (insn >> 7) & 0x1f;
7833 if (insn & (1 << 6)) {
7834 if (shift == 0)
7835 shift = 31;
7836 tcg_gen_sari_i32(tmp, tmp, shift);
7837 } else {
7838 tcg_gen_shli_i32(tmp, tmp, shift);
7840 sh = (insn >> 16) & 0x1f;
7841 tmp2 = tcg_const_i32(sh);
7842 if (insn & (1 << 22))
7843 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
7844 else
7845 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
7846 tcg_temp_free_i32(tmp2);
7847 store_reg(s, rd, tmp);
7848 } else if ((insn & 0x00300fe0) == 0x00200f20) {
7849 /* [us]sat16 */
7850 tmp = load_reg(s, rm);
7851 sh = (insn >> 16) & 0x1f;
7852 tmp2 = tcg_const_i32(sh);
7853 if (insn & (1 << 22))
7854 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
7855 else
7856 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
7857 tcg_temp_free_i32(tmp2);
7858 store_reg(s, rd, tmp);
7859 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
7860 /* Select bytes. */
7861 tmp = load_reg(s, rn);
7862 tmp2 = load_reg(s, rm);
7863 tmp3 = tcg_temp_new_i32();
7864 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
7865 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
7866 tcg_temp_free_i32(tmp3);
7867 tcg_temp_free_i32(tmp2);
7868 store_reg(s, rd, tmp);
7869 } else if ((insn & 0x000003e0) == 0x00000060) {
7870 tmp = load_reg(s, rm);
7871 shift = (insn >> 10) & 3;
7872 /* ??? In many cases it's not necessary to do a
7873 rotate, a shift is sufficient. */
7874 if (shift != 0)
7875 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
7876 op1 = (insn >> 20) & 7;
7877 switch (op1) {
7878 case 0: gen_sxtb16(tmp); break;
7879 case 2: gen_sxtb(tmp); break;
7880 case 3: gen_sxth(tmp); break;
7881 case 4: gen_uxtb16(tmp); break;
7882 case 6: gen_uxtb(tmp); break;
7883 case 7: gen_uxth(tmp); break;
7884 default: goto illegal_op;
7886 if (rn != 15) {
7887 tmp2 = load_reg(s, rn);
7888 if ((op1 & 3) == 0) {
7889 gen_add16(tmp, tmp2);
7890 } else {
7891 tcg_gen_add_i32(tmp, tmp, tmp2);
7892 tcg_temp_free_i32(tmp2);
7895 store_reg(s, rd, tmp);
7896 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
7897 /* rev */
7898 tmp = load_reg(s, rm);
7899 if (insn & (1 << 22)) {
7900 if (insn & (1 << 7)) {
7901 gen_revsh(tmp);
7902 } else {
7903 ARCH(6T2);
7904 gen_helper_rbit(tmp, tmp);
7906 } else {
7907 if (insn & (1 << 7))
7908 gen_rev16(tmp);
7909 else
7910 tcg_gen_bswap32_i32(tmp, tmp);
7912 store_reg(s, rd, tmp);
7913 } else {
7914 goto illegal_op;
7916 break;
7917 case 2: /* Multiplies (Type 3). */
7918 switch ((insn >> 20) & 0x7) {
7919 case 5:
7920 if (((insn >> 6) ^ (insn >> 7)) & 1) {
7921 /* op2 not 00x or 11x : UNDEF */
7922 goto illegal_op;
7924 /* Signed multiply most significant [accumulate].
7925 (SMMUL, SMMLA, SMMLS) */
7926 tmp = load_reg(s, rm);
7927 tmp2 = load_reg(s, rs);
7928 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7930 if (rd != 15) {
7931 tmp = load_reg(s, rd);
7932 if (insn & (1 << 6)) {
7933 tmp64 = gen_subq_msw(tmp64, tmp);
7934 } else {
7935 tmp64 = gen_addq_msw(tmp64, tmp);
7938 if (insn & (1 << 5)) {
7939 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
7941 tcg_gen_shri_i64(tmp64, tmp64, 32);
7942 tmp = tcg_temp_new_i32();
7943 tcg_gen_trunc_i64_i32(tmp, tmp64);
7944 tcg_temp_free_i64(tmp64);
7945 store_reg(s, rn, tmp);
7946 break;
7947 case 0:
7948 case 4:
7949 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
7950 if (insn & (1 << 7)) {
7951 goto illegal_op;
7953 tmp = load_reg(s, rm);
7954 tmp2 = load_reg(s, rs);
7955 if (insn & (1 << 5))
7956 gen_swap_half(tmp2);
7957 gen_smul_dual(tmp, tmp2);
7958 if (insn & (1 << 6)) {
7959 /* This subtraction cannot overflow. */
7960 tcg_gen_sub_i32(tmp, tmp, tmp2);
7961 } else {
7962 /* This addition cannot overflow 32 bits;
7963 * however it may overflow considered as a signed
7964 * operation, in which case we must set the Q flag.
7966 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7968 tcg_temp_free_i32(tmp2);
7969 if (insn & (1 << 22)) {
7970 /* smlald, smlsld */
7971 tmp64 = tcg_temp_new_i64();
7972 tcg_gen_ext_i32_i64(tmp64, tmp);
7973 tcg_temp_free_i32(tmp);
7974 gen_addq(s, tmp64, rd, rn);
7975 gen_storeq_reg(s, rd, rn, tmp64);
7976 tcg_temp_free_i64(tmp64);
7977 } else {
7978 /* smuad, smusd, smlad, smlsd */
7979 if (rd != 15)
7981 tmp2 = load_reg(s, rd);
7982 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7983 tcg_temp_free_i32(tmp2);
7985 store_reg(s, rn, tmp);
7987 break;
7988 case 1:
7989 case 3:
7990 /* SDIV, UDIV */
7991 if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
7992 goto illegal_op;
7994 if (((insn >> 5) & 7) || (rd != 15)) {
7995 goto illegal_op;
7997 tmp = load_reg(s, rm);
7998 tmp2 = load_reg(s, rs);
7999 if (insn & (1 << 21)) {
8000 gen_helper_udiv(tmp, tmp, tmp2);
8001 } else {
8002 gen_helper_sdiv(tmp, tmp, tmp2);
8004 tcg_temp_free_i32(tmp2);
8005 store_reg(s, rn, tmp);
8006 break;
8007 default:
8008 goto illegal_op;
8010 break;
8011 case 3:
8012 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8013 switch (op1) {
8014 case 0: /* Unsigned sum of absolute differences. */
8015 ARCH(6);
8016 tmp = load_reg(s, rm);
8017 tmp2 = load_reg(s, rs);
8018 gen_helper_usad8(tmp, tmp, tmp2);
8019 tcg_temp_free_i32(tmp2);
8020 if (rd != 15) {
8021 tmp2 = load_reg(s, rd);
8022 tcg_gen_add_i32(tmp, tmp, tmp2);
8023 tcg_temp_free_i32(tmp2);
8025 store_reg(s, rn, tmp);
8026 break;
8027 case 0x20: case 0x24: case 0x28: case 0x2c:
8028 /* Bitfield insert/clear. */
8029 ARCH(6T2);
8030 shift = (insn >> 7) & 0x1f;
8031 i = (insn >> 16) & 0x1f;
8032 i = i + 1 - shift;
8033 if (rm == 15) {
8034 tmp = tcg_temp_new_i32();
8035 tcg_gen_movi_i32(tmp, 0);
8036 } else {
8037 tmp = load_reg(s, rm);
8039 if (i != 32) {
8040 tmp2 = load_reg(s, rd);
8041 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
8042 tcg_temp_free_i32(tmp2);
8044 store_reg(s, rd, tmp);
8045 break;
8046 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8047 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
8048 ARCH(6T2);
8049 tmp = load_reg(s, rm);
8050 shift = (insn >> 7) & 0x1f;
8051 i = ((insn >> 16) & 0x1f) + 1;
8052 if (shift + i > 32)
8053 goto illegal_op;
8054 if (i < 32) {
8055 if (op1 & 0x20) {
8056 gen_ubfx(tmp, shift, (1u << i) - 1);
8057 } else {
8058 gen_sbfx(tmp, shift, i);
8061 store_reg(s, rd, tmp);
8062 break;
8063 default:
8064 goto illegal_op;
8066 break;
8068 break;
8070 do_ldst:
8071 /* Check for undefined extension instructions
8072 * per the ARM Bible IE:
8073 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
8075 sh = (0xf << 20) | (0xf << 4);
8076 if (op1 == 0x7 && ((insn & sh) == sh))
8078 goto illegal_op;
8080 /* load/store byte/word */
8081 rn = (insn >> 16) & 0xf;
8082 rd = (insn >> 12) & 0xf;
8083 tmp2 = load_reg(s, rn);
8084 i = (IS_USER(s) || (insn & 0x01200000) == 0x00200000);
8085 if (insn & (1 << 24))
8086 gen_add_data_offset(s, insn, tmp2);
8087 if (insn & (1 << 20)) {
8088 /* load */
8089 tmp = tcg_temp_new_i32();
8090 if (insn & (1 << 22)) {
8091 gen_aa32_ld8u(tmp, tmp2, i);
8092 } else {
8093 gen_aa32_ld32u(tmp, tmp2, i);
8095 } else {
8096 /* store */
8097 tmp = load_reg(s, rd);
8098 if (insn & (1 << 22)) {
8099 gen_aa32_st8(tmp, tmp2, i);
8100 } else {
8101 gen_aa32_st32(tmp, tmp2, i);
8103 tcg_temp_free_i32(tmp);
8105 if (!(insn & (1 << 24))) {
8106 gen_add_data_offset(s, insn, tmp2);
8107 store_reg(s, rn, tmp2);
8108 } else if (insn & (1 << 21)) {
8109 store_reg(s, rn, tmp2);
8110 } else {
8111 tcg_temp_free_i32(tmp2);
8113 if (insn & (1 << 20)) {
8114 /* Complete the load. */
8115 store_reg_from_load(env, s, rd, tmp);
8117 break;
8118 case 0x08:
8119 case 0x09:
8121 int j, n, user, loaded_base;
8122 TCGv_i32 loaded_var;
8123 /* load/store multiple words */
8124 /* XXX: store correct base if write back */
8125 user = 0;
8126 if (insn & (1 << 22)) {
8127 if (IS_USER(s))
8128 goto illegal_op; /* only usable in supervisor mode */
8130 if ((insn & (1 << 15)) == 0)
8131 user = 1;
8133 rn = (insn >> 16) & 0xf;
8134 addr = load_reg(s, rn);
8136 /* compute total size */
8137 loaded_base = 0;
8138 TCGV_UNUSED_I32(loaded_var);
8139 n = 0;
8140 for(i=0;i<16;i++) {
8141 if (insn & (1 << i))
8142 n++;
8144 /* XXX: test invalid n == 0 case ? */
8145 if (insn & (1 << 23)) {
8146 if (insn & (1 << 24)) {
8147 /* pre increment */
8148 tcg_gen_addi_i32(addr, addr, 4);
8149 } else {
8150 /* post increment */
8152 } else {
8153 if (insn & (1 << 24)) {
8154 /* pre decrement */
8155 tcg_gen_addi_i32(addr, addr, -(n * 4));
8156 } else {
8157 /* post decrement */
8158 if (n != 1)
8159 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8162 j = 0;
8163 for(i=0;i<16;i++) {
8164 if (insn & (1 << i)) {
8165 if (insn & (1 << 20)) {
8166 /* load */
8167 tmp = tcg_temp_new_i32();
8168 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8169 if (user) {
8170 tmp2 = tcg_const_i32(i);
8171 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
8172 tcg_temp_free_i32(tmp2);
8173 tcg_temp_free_i32(tmp);
8174 } else if (i == rn) {
8175 loaded_var = tmp;
8176 loaded_base = 1;
8177 } else {
8178 store_reg_from_load(env, s, i, tmp);
8180 } else {
8181 /* store */
8182 if (i == 15) {
8183 /* special case: r15 = PC + 8 */
8184 val = (long)s->pc + 4;
8185 tmp = tcg_temp_new_i32();
8186 tcg_gen_movi_i32(tmp, val);
8187 } else if (user) {
8188 tmp = tcg_temp_new_i32();
8189 tmp2 = tcg_const_i32(i);
8190 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
8191 tcg_temp_free_i32(tmp2);
8192 } else {
8193 tmp = load_reg(s, i);
8195 gen_aa32_st32(tmp, addr, IS_USER(s));
8196 tcg_temp_free_i32(tmp);
8198 j++;
8199 /* no need to add after the last transfer */
8200 if (j != n)
8201 tcg_gen_addi_i32(addr, addr, 4);
8204 if (insn & (1 << 21)) {
8205 /* write back */
8206 if (insn & (1 << 23)) {
8207 if (insn & (1 << 24)) {
8208 /* pre increment */
8209 } else {
8210 /* post increment */
8211 tcg_gen_addi_i32(addr, addr, 4);
8213 } else {
8214 if (insn & (1 << 24)) {
8215 /* pre decrement */
8216 if (n != 1)
8217 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8218 } else {
8219 /* post decrement */
8220 tcg_gen_addi_i32(addr, addr, -(n * 4));
8223 store_reg(s, rn, addr);
8224 } else {
8225 tcg_temp_free_i32(addr);
8227 if (loaded_base) {
8228 store_reg(s, rn, loaded_var);
8230 if ((insn & (1 << 22)) && !user) {
8231 /* Restore CPSR from SPSR. */
8232 tmp = load_cpu_field(spsr);
8233 gen_set_cpsr(tmp, 0xffffffff);
8234 tcg_temp_free_i32(tmp);
8235 s->is_jmp = DISAS_UPDATE;
8238 break;
8239 case 0xa:
8240 case 0xb:
8242 int32_t offset;
8244 /* branch (and link) */
8245 val = (int32_t)s->pc;
8246 if (insn & (1 << 24)) {
8247 tmp = tcg_temp_new_i32();
8248 tcg_gen_movi_i32(tmp, val);
8249 store_reg(s, 14, tmp);
8251 offset = sextract32(insn << 2, 0, 26);
8252 val += offset + 4;
8253 gen_jmp(s, val);
8255 break;
8256 case 0xc:
8257 case 0xd:
8258 case 0xe:
8259 if (((insn >> 8) & 0xe) == 10) {
8260 /* VFP. */
8261 if (disas_vfp_insn(env, s, insn)) {
8262 goto illegal_op;
8264 } else if (disas_coproc_insn(env, s, insn)) {
8265 /* Coprocessor. */
8266 goto illegal_op;
8268 break;
8269 case 0xf:
8270 /* swi */
8271 gen_set_pc_im(s, s->pc);
8272 s->is_jmp = DISAS_SWI;
8273 break;
8274 default:
8275 illegal_op:
8276 gen_exception_insn(s, 4, EXCP_UDEF);
8277 break;
8282 /* Return true if this is a Thumb-2 logical op. */
8283 static int
8284 thumb2_logic_op(int op)
8286 return (op < 8);
8289 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
8290 then set condition code flags based on the result of the operation.
8291 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
8292 to the high bit of T1.
8293 Returns zero if the opcode is valid. */
8295 static int
8296 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
8297 TCGv_i32 t0, TCGv_i32 t1)
8299 int logic_cc;
8301 logic_cc = 0;
8302 switch (op) {
8303 case 0: /* and */
8304 tcg_gen_and_i32(t0, t0, t1);
8305 logic_cc = conds;
8306 break;
8307 case 1: /* bic */
8308 tcg_gen_andc_i32(t0, t0, t1);
8309 logic_cc = conds;
8310 break;
8311 case 2: /* orr */
8312 tcg_gen_or_i32(t0, t0, t1);
8313 logic_cc = conds;
8314 break;
8315 case 3: /* orn */
8316 tcg_gen_orc_i32(t0, t0, t1);
8317 logic_cc = conds;
8318 break;
8319 case 4: /* eor */
8320 tcg_gen_xor_i32(t0, t0, t1);
8321 logic_cc = conds;
8322 break;
8323 case 8: /* add */
8324 if (conds)
8325 gen_add_CC(t0, t0, t1);
8326 else
8327 tcg_gen_add_i32(t0, t0, t1);
8328 break;
8329 case 10: /* adc */
8330 if (conds)
8331 gen_adc_CC(t0, t0, t1);
8332 else
8333 gen_adc(t0, t1);
8334 break;
8335 case 11: /* sbc */
8336 if (conds) {
8337 gen_sbc_CC(t0, t0, t1);
8338 } else {
8339 gen_sub_carry(t0, t0, t1);
8341 break;
8342 case 13: /* sub */
8343 if (conds)
8344 gen_sub_CC(t0, t0, t1);
8345 else
8346 tcg_gen_sub_i32(t0, t0, t1);
8347 break;
8348 case 14: /* rsb */
8349 if (conds)
8350 gen_sub_CC(t0, t1, t0);
8351 else
8352 tcg_gen_sub_i32(t0, t1, t0);
8353 break;
8354 default: /* 5, 6, 7, 9, 12, 15. */
8355 return 1;
8357 if (logic_cc) {
8358 gen_logic_CC(t0);
8359 if (shifter_out)
8360 gen_set_CF_bit31(t1);
8362 return 0;
8365 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
8366 is not legal. */
8367 static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
8369 uint32_t insn, imm, shift, offset;
8370 uint32_t rd, rn, rm, rs;
8371 TCGv_i32 tmp;
8372 TCGv_i32 tmp2;
8373 TCGv_i32 tmp3;
8374 TCGv_i32 addr;
8375 TCGv_i64 tmp64;
8376 int op;
8377 int shiftop;
8378 int conds;
8379 int logic_cc;
8381 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
8382 || arm_feature (env, ARM_FEATURE_M))) {
8383 /* Thumb-1 cores may need to treat bl and blx as a pair of
8384 16-bit instructions to get correct prefetch abort behavior. */
8385 insn = insn_hw1;
8386 if ((insn & (1 << 12)) == 0) {
8387 ARCH(5);
8388 /* Second half of blx. */
8389 offset = ((insn & 0x7ff) << 1);
8390 tmp = load_reg(s, 14);
8391 tcg_gen_addi_i32(tmp, tmp, offset);
8392 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
8394 tmp2 = tcg_temp_new_i32();
8395 tcg_gen_movi_i32(tmp2, s->pc | 1);
8396 store_reg(s, 14, tmp2);
8397 gen_bx(s, tmp);
8398 return 0;
8400 if (insn & (1 << 11)) {
8401 /* Second half of bl. */
8402 offset = ((insn & 0x7ff) << 1) | 1;
8403 tmp = load_reg(s, 14);
8404 tcg_gen_addi_i32(tmp, tmp, offset);
8406 tmp2 = tcg_temp_new_i32();
8407 tcg_gen_movi_i32(tmp2, s->pc | 1);
8408 store_reg(s, 14, tmp2);
8409 gen_bx(s, tmp);
8410 return 0;
8412 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
8413 /* Instruction spans a page boundary. Implement it as two
8414 16-bit instructions in case the second half causes an
8415 prefetch abort. */
8416 offset = ((int32_t)insn << 21) >> 9;
8417 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
8418 return 0;
8420 /* Fall through to 32-bit decode. */
8423 insn = arm_lduw_code(env, s->pc, s->bswap_code);
8424 s->pc += 2;
8425 insn |= (uint32_t)insn_hw1 << 16;
8427 if ((insn & 0xf800e800) != 0xf000e800) {
8428 ARCH(6T2);
8431 rn = (insn >> 16) & 0xf;
8432 rs = (insn >> 12) & 0xf;
8433 rd = (insn >> 8) & 0xf;
8434 rm = insn & 0xf;
8435 switch ((insn >> 25) & 0xf) {
8436 case 0: case 1: case 2: case 3:
8437 /* 16-bit instructions. Should never happen. */
8438 abort();
8439 case 4:
8440 if (insn & (1 << 22)) {
8441 /* Other load/store, table branch. */
8442 if (insn & 0x01200000) {
8443 /* Load/store doubleword. */
8444 if (rn == 15) {
8445 addr = tcg_temp_new_i32();
8446 tcg_gen_movi_i32(addr, s->pc & ~3);
8447 } else {
8448 addr = load_reg(s, rn);
8450 offset = (insn & 0xff) * 4;
8451 if ((insn & (1 << 23)) == 0)
8452 offset = -offset;
8453 if (insn & (1 << 24)) {
8454 tcg_gen_addi_i32(addr, addr, offset);
8455 offset = 0;
8457 if (insn & (1 << 20)) {
8458 /* ldrd */
8459 tmp = tcg_temp_new_i32();
8460 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8461 store_reg(s, rs, tmp);
8462 tcg_gen_addi_i32(addr, addr, 4);
8463 tmp = tcg_temp_new_i32();
8464 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8465 store_reg(s, rd, tmp);
8466 } else {
8467 /* strd */
8468 tmp = load_reg(s, rs);
8469 gen_aa32_st32(tmp, addr, IS_USER(s));
8470 tcg_temp_free_i32(tmp);
8471 tcg_gen_addi_i32(addr, addr, 4);
8472 tmp = load_reg(s, rd);
8473 gen_aa32_st32(tmp, addr, IS_USER(s));
8474 tcg_temp_free_i32(tmp);
8476 if (insn & (1 << 21)) {
8477 /* Base writeback. */
8478 if (rn == 15)
8479 goto illegal_op;
8480 tcg_gen_addi_i32(addr, addr, offset - 4);
8481 store_reg(s, rn, addr);
8482 } else {
8483 tcg_temp_free_i32(addr);
8485 } else if ((insn & (1 << 23)) == 0) {
8486 /* Load/store exclusive word. */
8487 addr = tcg_temp_local_new_i32();
8488 load_reg_var(s, addr, rn);
8489 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
8490 if (insn & (1 << 20)) {
8491 gen_load_exclusive(s, rs, 15, addr, 2);
8492 } else {
8493 gen_store_exclusive(s, rd, rs, 15, addr, 2);
8495 tcg_temp_free_i32(addr);
8496 } else if ((insn & (7 << 5)) == 0) {
8497 /* Table Branch. */
8498 if (rn == 15) {
8499 addr = tcg_temp_new_i32();
8500 tcg_gen_movi_i32(addr, s->pc);
8501 } else {
8502 addr = load_reg(s, rn);
8504 tmp = load_reg(s, rm);
8505 tcg_gen_add_i32(addr, addr, tmp);
8506 if (insn & (1 << 4)) {
8507 /* tbh */
8508 tcg_gen_add_i32(addr, addr, tmp);
8509 tcg_temp_free_i32(tmp);
8510 tmp = tcg_temp_new_i32();
8511 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8512 } else { /* tbb */
8513 tcg_temp_free_i32(tmp);
8514 tmp = tcg_temp_new_i32();
8515 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8517 tcg_temp_free_i32(addr);
8518 tcg_gen_shli_i32(tmp, tmp, 1);
8519 tcg_gen_addi_i32(tmp, tmp, s->pc);
8520 store_reg(s, 15, tmp);
8521 } else {
8522 int op2 = (insn >> 6) & 0x3;
8523 op = (insn >> 4) & 0x3;
8524 switch (op2) {
8525 case 0:
8526 goto illegal_op;
8527 case 1:
8528 /* Load/store exclusive byte/halfword/doubleword */
8529 if (op == 2) {
8530 goto illegal_op;
8532 ARCH(7);
8533 break;
8534 case 2:
8535 /* Load-acquire/store-release */
8536 if (op == 3) {
8537 goto illegal_op;
8539 /* Fall through */
8540 case 3:
8541 /* Load-acquire/store-release exclusive */
8542 ARCH(8);
8543 break;
8545 addr = tcg_temp_local_new_i32();
8546 load_reg_var(s, addr, rn);
8547 if (!(op2 & 1)) {
8548 if (insn & (1 << 20)) {
8549 tmp = tcg_temp_new_i32();
8550 switch (op) {
8551 case 0: /* ldab */
8552 gen_aa32_ld8u(tmp, addr, IS_USER(s));
8553 break;
8554 case 1: /* ldah */
8555 gen_aa32_ld16u(tmp, addr, IS_USER(s));
8556 break;
8557 case 2: /* lda */
8558 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8559 break;
8560 default:
8561 abort();
8563 store_reg(s, rs, tmp);
8564 } else {
8565 tmp = load_reg(s, rs);
8566 switch (op) {
8567 case 0: /* stlb */
8568 gen_aa32_st8(tmp, addr, IS_USER(s));
8569 break;
8570 case 1: /* stlh */
8571 gen_aa32_st16(tmp, addr, IS_USER(s));
8572 break;
8573 case 2: /* stl */
8574 gen_aa32_st32(tmp, addr, IS_USER(s));
8575 break;
8576 default:
8577 abort();
8579 tcg_temp_free_i32(tmp);
8581 } else if (insn & (1 << 20)) {
8582 gen_load_exclusive(s, rs, rd, addr, op);
8583 } else {
8584 gen_store_exclusive(s, rm, rs, rd, addr, op);
8586 tcg_temp_free_i32(addr);
8588 } else {
8589 /* Load/store multiple, RFE, SRS. */
8590 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
8591 /* RFE, SRS: not available in user mode or on M profile */
8592 if (IS_USER(s) || IS_M(env)) {
8593 goto illegal_op;
8595 if (insn & (1 << 20)) {
8596 /* rfe */
8597 addr = load_reg(s, rn);
8598 if ((insn & (1 << 24)) == 0)
8599 tcg_gen_addi_i32(addr, addr, -8);
8600 /* Load PC into tmp and CPSR into tmp2. */
8601 tmp = tcg_temp_new_i32();
8602 gen_aa32_ld32u(tmp, addr, 0);
8603 tcg_gen_addi_i32(addr, addr, 4);
8604 tmp2 = tcg_temp_new_i32();
8605 gen_aa32_ld32u(tmp2, addr, 0);
8606 if (insn & (1 << 21)) {
8607 /* Base writeback. */
8608 if (insn & (1 << 24)) {
8609 tcg_gen_addi_i32(addr, addr, 4);
8610 } else {
8611 tcg_gen_addi_i32(addr, addr, -4);
8613 store_reg(s, rn, addr);
8614 } else {
8615 tcg_temp_free_i32(addr);
8617 gen_rfe(s, tmp, tmp2);
8618 } else {
8619 /* srs */
8620 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
8621 insn & (1 << 21));
8623 } else {
8624 int i, loaded_base = 0;
8625 TCGv_i32 loaded_var;
8626 /* Load/store multiple. */
8627 addr = load_reg(s, rn);
8628 offset = 0;
8629 for (i = 0; i < 16; i++) {
8630 if (insn & (1 << i))
8631 offset += 4;
8633 if (insn & (1 << 24)) {
8634 tcg_gen_addi_i32(addr, addr, -offset);
8637 TCGV_UNUSED_I32(loaded_var);
8638 for (i = 0; i < 16; i++) {
8639 if ((insn & (1 << i)) == 0)
8640 continue;
8641 if (insn & (1 << 20)) {
8642 /* Load. */
8643 tmp = tcg_temp_new_i32();
8644 gen_aa32_ld32u(tmp, addr, IS_USER(s));
8645 if (i == 15) {
8646 gen_bx(s, tmp);
8647 } else if (i == rn) {
8648 loaded_var = tmp;
8649 loaded_base = 1;
8650 } else {
8651 store_reg(s, i, tmp);
8653 } else {
8654 /* Store. */
8655 tmp = load_reg(s, i);
8656 gen_aa32_st32(tmp, addr, IS_USER(s));
8657 tcg_temp_free_i32(tmp);
8659 tcg_gen_addi_i32(addr, addr, 4);
8661 if (loaded_base) {
8662 store_reg(s, rn, loaded_var);
8664 if (insn & (1 << 21)) {
8665 /* Base register writeback. */
8666 if (insn & (1 << 24)) {
8667 tcg_gen_addi_i32(addr, addr, -offset);
8669 /* Fault if writeback register is in register list. */
8670 if (insn & (1 << rn))
8671 goto illegal_op;
8672 store_reg(s, rn, addr);
8673 } else {
8674 tcg_temp_free_i32(addr);
8678 break;
8679 case 5:
8681 op = (insn >> 21) & 0xf;
8682 if (op == 6) {
8683 /* Halfword pack. */
8684 tmp = load_reg(s, rn);
8685 tmp2 = load_reg(s, rm);
8686 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
8687 if (insn & (1 << 5)) {
8688 /* pkhtb */
8689 if (shift == 0)
8690 shift = 31;
8691 tcg_gen_sari_i32(tmp2, tmp2, shift);
8692 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8693 tcg_gen_ext16u_i32(tmp2, tmp2);
8694 } else {
8695 /* pkhbt */
8696 if (shift)
8697 tcg_gen_shli_i32(tmp2, tmp2, shift);
8698 tcg_gen_ext16u_i32(tmp, tmp);
8699 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8701 tcg_gen_or_i32(tmp, tmp, tmp2);
8702 tcg_temp_free_i32(tmp2);
8703 store_reg(s, rd, tmp);
8704 } else {
8705 /* Data processing register constant shift. */
8706 if (rn == 15) {
8707 tmp = tcg_temp_new_i32();
8708 tcg_gen_movi_i32(tmp, 0);
8709 } else {
8710 tmp = load_reg(s, rn);
8712 tmp2 = load_reg(s, rm);
8714 shiftop = (insn >> 4) & 3;
8715 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
8716 conds = (insn & (1 << 20)) != 0;
8717 logic_cc = (conds && thumb2_logic_op(op));
8718 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8719 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
8720 goto illegal_op;
8721 tcg_temp_free_i32(tmp2);
8722 if (rd != 15) {
8723 store_reg(s, rd, tmp);
8724 } else {
8725 tcg_temp_free_i32(tmp);
8728 break;
8729 case 13: /* Misc data processing. */
8730 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
8731 if (op < 4 && (insn & 0xf000) != 0xf000)
8732 goto illegal_op;
8733 switch (op) {
8734 case 0: /* Register controlled shift. */
8735 tmp = load_reg(s, rn);
8736 tmp2 = load_reg(s, rm);
8737 if ((insn & 0x70) != 0)
8738 goto illegal_op;
8739 op = (insn >> 21) & 3;
8740 logic_cc = (insn & (1 << 20)) != 0;
8741 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
8742 if (logic_cc)
8743 gen_logic_CC(tmp);
8744 store_reg_bx(env, s, rd, tmp);
8745 break;
8746 case 1: /* Sign/zero extend. */
8747 tmp = load_reg(s, rm);
8748 shift = (insn >> 4) & 3;
8749 /* ??? In many cases it's not necessary to do a
8750 rotate, a shift is sufficient. */
8751 if (shift != 0)
8752 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8753 op = (insn >> 20) & 7;
8754 switch (op) {
8755 case 0: gen_sxth(tmp); break;
8756 case 1: gen_uxth(tmp); break;
8757 case 2: gen_sxtb16(tmp); break;
8758 case 3: gen_uxtb16(tmp); break;
8759 case 4: gen_sxtb(tmp); break;
8760 case 5: gen_uxtb(tmp); break;
8761 default: goto illegal_op;
8763 if (rn != 15) {
8764 tmp2 = load_reg(s, rn);
8765 if ((op >> 1) == 1) {
8766 gen_add16(tmp, tmp2);
8767 } else {
8768 tcg_gen_add_i32(tmp, tmp, tmp2);
8769 tcg_temp_free_i32(tmp2);
8772 store_reg(s, rd, tmp);
8773 break;
8774 case 2: /* SIMD add/subtract. */
8775 op = (insn >> 20) & 7;
8776 shift = (insn >> 4) & 7;
8777 if ((op & 3) == 3 || (shift & 3) == 3)
8778 goto illegal_op;
8779 tmp = load_reg(s, rn);
8780 tmp2 = load_reg(s, rm);
8781 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
8782 tcg_temp_free_i32(tmp2);
8783 store_reg(s, rd, tmp);
8784 break;
8785 case 3: /* Other data processing. */
8786 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
8787 if (op < 4) {
8788 /* Saturating add/subtract. */
8789 tmp = load_reg(s, rn);
8790 tmp2 = load_reg(s, rm);
8791 if (op & 1)
8792 gen_helper_double_saturate(tmp, cpu_env, tmp);
8793 if (op & 2)
8794 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
8795 else
8796 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
8797 tcg_temp_free_i32(tmp2);
8798 } else {
8799 tmp = load_reg(s, rn);
8800 switch (op) {
8801 case 0x0a: /* rbit */
8802 gen_helper_rbit(tmp, tmp);
8803 break;
8804 case 0x08: /* rev */
8805 tcg_gen_bswap32_i32(tmp, tmp);
8806 break;
8807 case 0x09: /* rev16 */
8808 gen_rev16(tmp);
8809 break;
8810 case 0x0b: /* revsh */
8811 gen_revsh(tmp);
8812 break;
8813 case 0x10: /* sel */
8814 tmp2 = load_reg(s, rm);
8815 tmp3 = tcg_temp_new_i32();
8816 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8817 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8818 tcg_temp_free_i32(tmp3);
8819 tcg_temp_free_i32(tmp2);
8820 break;
8821 case 0x18: /* clz */
8822 gen_helper_clz(tmp, tmp);
8823 break;
8824 default:
8825 goto illegal_op;
8828 store_reg(s, rd, tmp);
8829 break;
8830 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
8831 op = (insn >> 4) & 0xf;
8832 tmp = load_reg(s, rn);
8833 tmp2 = load_reg(s, rm);
8834 switch ((insn >> 20) & 7) {
8835 case 0: /* 32 x 32 -> 32 */
8836 tcg_gen_mul_i32(tmp, tmp, tmp2);
8837 tcg_temp_free_i32(tmp2);
8838 if (rs != 15) {
8839 tmp2 = load_reg(s, rs);
8840 if (op)
8841 tcg_gen_sub_i32(tmp, tmp2, tmp);
8842 else
8843 tcg_gen_add_i32(tmp, tmp, tmp2);
8844 tcg_temp_free_i32(tmp2);
8846 break;
8847 case 1: /* 16 x 16 -> 32 */
8848 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8849 tcg_temp_free_i32(tmp2);
8850 if (rs != 15) {
8851 tmp2 = load_reg(s, rs);
8852 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8853 tcg_temp_free_i32(tmp2);
8855 break;
8856 case 2: /* Dual multiply add. */
8857 case 4: /* Dual multiply subtract. */
8858 if (op)
8859 gen_swap_half(tmp2);
8860 gen_smul_dual(tmp, tmp2);
8861 if (insn & (1 << 22)) {
8862 /* This subtraction cannot overflow. */
8863 tcg_gen_sub_i32(tmp, tmp, tmp2);
8864 } else {
8865 /* This addition cannot overflow 32 bits;
8866 * however it may overflow considered as a signed
8867 * operation, in which case we must set the Q flag.
8869 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8871 tcg_temp_free_i32(tmp2);
8872 if (rs != 15)
8874 tmp2 = load_reg(s, rs);
8875 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8876 tcg_temp_free_i32(tmp2);
8878 break;
8879 case 3: /* 32 * 16 -> 32msb */
8880 if (op)
8881 tcg_gen_sari_i32(tmp2, tmp2, 16);
8882 else
8883 gen_sxth(tmp2);
8884 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8885 tcg_gen_shri_i64(tmp64, tmp64, 16);
8886 tmp = tcg_temp_new_i32();
8887 tcg_gen_trunc_i64_i32(tmp, tmp64);
8888 tcg_temp_free_i64(tmp64);
8889 if (rs != 15)
8891 tmp2 = load_reg(s, rs);
8892 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8893 tcg_temp_free_i32(tmp2);
8895 break;
8896 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
8897 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8898 if (rs != 15) {
8899 tmp = load_reg(s, rs);
8900 if (insn & (1 << 20)) {
8901 tmp64 = gen_addq_msw(tmp64, tmp);
8902 } else {
8903 tmp64 = gen_subq_msw(tmp64, tmp);
8906 if (insn & (1 << 4)) {
8907 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8909 tcg_gen_shri_i64(tmp64, tmp64, 32);
8910 tmp = tcg_temp_new_i32();
8911 tcg_gen_trunc_i64_i32(tmp, tmp64);
8912 tcg_temp_free_i64(tmp64);
8913 break;
8914 case 7: /* Unsigned sum of absolute differences. */
8915 gen_helper_usad8(tmp, tmp, tmp2);
8916 tcg_temp_free_i32(tmp2);
8917 if (rs != 15) {
8918 tmp2 = load_reg(s, rs);
8919 tcg_gen_add_i32(tmp, tmp, tmp2);
8920 tcg_temp_free_i32(tmp2);
8922 break;
8924 store_reg(s, rd, tmp);
8925 break;
8926 case 6: case 7: /* 64-bit multiply, Divide. */
8927 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
8928 tmp = load_reg(s, rn);
8929 tmp2 = load_reg(s, rm);
8930 if ((op & 0x50) == 0x10) {
8931 /* sdiv, udiv */
8932 if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
8933 goto illegal_op;
8935 if (op & 0x20)
8936 gen_helper_udiv(tmp, tmp, tmp2);
8937 else
8938 gen_helper_sdiv(tmp, tmp, tmp2);
8939 tcg_temp_free_i32(tmp2);
8940 store_reg(s, rd, tmp);
8941 } else if ((op & 0xe) == 0xc) {
8942 /* Dual multiply accumulate long. */
8943 if (op & 1)
8944 gen_swap_half(tmp2);
8945 gen_smul_dual(tmp, tmp2);
8946 if (op & 0x10) {
8947 tcg_gen_sub_i32(tmp, tmp, tmp2);
8948 } else {
8949 tcg_gen_add_i32(tmp, tmp, tmp2);
8951 tcg_temp_free_i32(tmp2);
8952 /* BUGFIX */
8953 tmp64 = tcg_temp_new_i64();
8954 tcg_gen_ext_i32_i64(tmp64, tmp);
8955 tcg_temp_free_i32(tmp);
8956 gen_addq(s, tmp64, rs, rd);
8957 gen_storeq_reg(s, rs, rd, tmp64);
8958 tcg_temp_free_i64(tmp64);
8959 } else {
8960 if (op & 0x20) {
8961 /* Unsigned 64-bit multiply */
8962 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8963 } else {
8964 if (op & 8) {
8965 /* smlalxy */
8966 gen_mulxy(tmp, tmp2, op & 2, op & 1);
8967 tcg_temp_free_i32(tmp2);
8968 tmp64 = tcg_temp_new_i64();
8969 tcg_gen_ext_i32_i64(tmp64, tmp);
8970 tcg_temp_free_i32(tmp);
8971 } else {
8972 /* Signed 64-bit multiply */
8973 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8976 if (op & 4) {
8977 /* umaal */
8978 gen_addq_lo(s, tmp64, rs);
8979 gen_addq_lo(s, tmp64, rd);
8980 } else if (op & 0x40) {
8981 /* 64-bit accumulate. */
8982 gen_addq(s, tmp64, rs, rd);
8984 gen_storeq_reg(s, rs, rd, tmp64);
8985 tcg_temp_free_i64(tmp64);
8987 break;
8989 break;
8990 case 6: case 7: case 14: case 15:
8991 /* Coprocessor. */
8992 if (((insn >> 24) & 3) == 3) {
8993 /* Translate into the equivalent ARM encoding. */
8994 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
8995 if (disas_neon_data_insn(env, s, insn))
8996 goto illegal_op;
8997 } else if (((insn >> 8) & 0xe) == 10) {
8998 if (disas_vfp_insn(env, s, insn)) {
8999 goto illegal_op;
9001 } else {
9002 if (insn & (1 << 28))
9003 goto illegal_op;
9004 if (disas_coproc_insn (env, s, insn))
9005 goto illegal_op;
9007 break;
9008 case 8: case 9: case 10: case 11:
9009 if (insn & (1 << 15)) {
9010 /* Branches, misc control. */
9011 if (insn & 0x5000) {
9012 /* Unconditional branch. */
9013 /* signextend(hw1[10:0]) -> offset[:12]. */
9014 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
9015 /* hw1[10:0] -> offset[11:1]. */
9016 offset |= (insn & 0x7ff) << 1;
9017 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
9018 offset[24:22] already have the same value because of the
9019 sign extension above. */
9020 offset ^= ((~insn) & (1 << 13)) << 10;
9021 offset ^= ((~insn) & (1 << 11)) << 11;
9023 if (insn & (1 << 14)) {
9024 /* Branch and link. */
9025 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
9028 offset += s->pc;
9029 if (insn & (1 << 12)) {
9030 /* b/bl */
9031 gen_jmp(s, offset);
9032 } else {
9033 /* blx */
9034 offset &= ~(uint32_t)2;
9035 /* thumb2 bx, no need to check */
9036 gen_bx_im(s, offset);
9038 } else if (((insn >> 23) & 7) == 7) {
9039 /* Misc control */
9040 if (insn & (1 << 13))
9041 goto illegal_op;
9043 if (insn & (1 << 26)) {
9044 /* Secure monitor call (v6Z) */
9045 qemu_log_mask(LOG_UNIMP,
9046 "arm: unimplemented secure monitor call\n");
9047 goto illegal_op; /* not implemented. */
9048 } else {
9049 op = (insn >> 20) & 7;
9050 switch (op) {
9051 case 0: /* msr cpsr. */
9052 if (IS_M(env)) {
9053 tmp = load_reg(s, rn);
9054 addr = tcg_const_i32(insn & 0xff);
9055 gen_helper_v7m_msr(cpu_env, addr, tmp);
9056 tcg_temp_free_i32(addr);
9057 tcg_temp_free_i32(tmp);
9058 gen_lookup_tb(s);
9059 break;
9061 /* fall through */
9062 case 1: /* msr spsr. */
9063 if (IS_M(env))
9064 goto illegal_op;
9065 tmp = load_reg(s, rn);
9066 if (gen_set_psr(s,
9067 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
9068 op == 1, tmp))
9069 goto illegal_op;
9070 break;
9071 case 2: /* cps, nop-hint. */
9072 if (((insn >> 8) & 7) == 0) {
9073 gen_nop_hint(s, insn & 0xff);
9075 /* Implemented as NOP in user mode. */
9076 if (IS_USER(s))
9077 break;
9078 offset = 0;
9079 imm = 0;
9080 if (insn & (1 << 10)) {
9081 if (insn & (1 << 7))
9082 offset |= CPSR_A;
9083 if (insn & (1 << 6))
9084 offset |= CPSR_I;
9085 if (insn & (1 << 5))
9086 offset |= CPSR_F;
9087 if (insn & (1 << 9))
9088 imm = CPSR_A | CPSR_I | CPSR_F;
9090 if (insn & (1 << 8)) {
9091 offset |= 0x1f;
9092 imm |= (insn & 0x1f);
9094 if (offset) {
9095 gen_set_psr_im(s, offset, 0, imm);
9097 break;
9098 case 3: /* Special control operations. */
9099 ARCH(7);
9100 op = (insn >> 4) & 0xf;
9101 switch (op) {
9102 case 2: /* clrex */
9103 gen_clrex(s);
9104 break;
9105 case 4: /* dsb */
9106 case 5: /* dmb */
9107 case 6: /* isb */
9108 /* These execute as NOPs. */
9109 break;
9110 default:
9111 goto illegal_op;
9113 break;
9114 case 4: /* bxj */
9115 /* Trivial implementation equivalent to bx. */
9116 tmp = load_reg(s, rn);
9117 gen_bx(s, tmp);
9118 break;
9119 case 5: /* Exception return. */
9120 if (IS_USER(s)) {
9121 goto illegal_op;
9123 if (rn != 14 || rd != 15) {
9124 goto illegal_op;
9126 tmp = load_reg(s, rn);
9127 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
9128 gen_exception_return(s, tmp);
9129 break;
9130 case 6: /* mrs cpsr. */
9131 tmp = tcg_temp_new_i32();
9132 if (IS_M(env)) {
9133 addr = tcg_const_i32(insn & 0xff);
9134 gen_helper_v7m_mrs(tmp, cpu_env, addr);
9135 tcg_temp_free_i32(addr);
9136 } else {
9137 gen_helper_cpsr_read(tmp, cpu_env);
9139 store_reg(s, rd, tmp);
9140 break;
9141 case 7: /* mrs spsr. */
9142 /* Not accessible in user mode. */
9143 if (IS_USER(s) || IS_M(env))
9144 goto illegal_op;
9145 tmp = load_cpu_field(spsr);
9146 store_reg(s, rd, tmp);
9147 break;
9150 } else {
9151 /* Conditional branch. */
9152 op = (insn >> 22) & 0xf;
9153 /* Generate a conditional jump to next instruction. */
9154 s->condlabel = gen_new_label();
9155 arm_gen_test_cc(op ^ 1, s->condlabel);
9156 s->condjmp = 1;
9158 /* offset[11:1] = insn[10:0] */
9159 offset = (insn & 0x7ff) << 1;
9160 /* offset[17:12] = insn[21:16]. */
9161 offset |= (insn & 0x003f0000) >> 4;
9162 /* offset[31:20] = insn[26]. */
9163 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
9164 /* offset[18] = insn[13]. */
9165 offset |= (insn & (1 << 13)) << 5;
9166 /* offset[19] = insn[11]. */
9167 offset |= (insn & (1 << 11)) << 8;
9169 /* jump to the offset */
9170 gen_jmp(s, s->pc + offset);
9172 } else {
9173 /* Data processing immediate. */
9174 if (insn & (1 << 25)) {
9175 if (insn & (1 << 24)) {
9176 if (insn & (1 << 20))
9177 goto illegal_op;
9178 /* Bitfield/Saturate. */
9179 op = (insn >> 21) & 7;
9180 imm = insn & 0x1f;
9181 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
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 switch (op) {
9189 case 2: /* Signed bitfield extract. */
9190 imm++;
9191 if (shift + imm > 32)
9192 goto illegal_op;
9193 if (imm < 32)
9194 gen_sbfx(tmp, shift, imm);
9195 break;
9196 case 6: /* Unsigned bitfield extract. */
9197 imm++;
9198 if (shift + imm > 32)
9199 goto illegal_op;
9200 if (imm < 32)
9201 gen_ubfx(tmp, shift, (1u << imm) - 1);
9202 break;
9203 case 3: /* Bitfield insert/clear. */
9204 if (imm < shift)
9205 goto illegal_op;
9206 imm = imm + 1 - shift;
9207 if (imm != 32) {
9208 tmp2 = load_reg(s, rd);
9209 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
9210 tcg_temp_free_i32(tmp2);
9212 break;
9213 case 7:
9214 goto illegal_op;
9215 default: /* Saturate. */
9216 if (shift) {
9217 if (op & 1)
9218 tcg_gen_sari_i32(tmp, tmp, shift);
9219 else
9220 tcg_gen_shli_i32(tmp, tmp, shift);
9222 tmp2 = tcg_const_i32(imm);
9223 if (op & 4) {
9224 /* Unsigned. */
9225 if ((op & 1) && shift == 0)
9226 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9227 else
9228 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9229 } else {
9230 /* Signed. */
9231 if ((op & 1) && shift == 0)
9232 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9233 else
9234 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9236 tcg_temp_free_i32(tmp2);
9237 break;
9239 store_reg(s, rd, tmp);
9240 } else {
9241 imm = ((insn & 0x04000000) >> 15)
9242 | ((insn & 0x7000) >> 4) | (insn & 0xff);
9243 if (insn & (1 << 22)) {
9244 /* 16-bit immediate. */
9245 imm |= (insn >> 4) & 0xf000;
9246 if (insn & (1 << 23)) {
9247 /* movt */
9248 tmp = load_reg(s, rd);
9249 tcg_gen_ext16u_i32(tmp, tmp);
9250 tcg_gen_ori_i32(tmp, tmp, imm << 16);
9251 } else {
9252 /* movw */
9253 tmp = tcg_temp_new_i32();
9254 tcg_gen_movi_i32(tmp, imm);
9256 } else {
9257 /* Add/sub 12-bit immediate. */
9258 if (rn == 15) {
9259 offset = s->pc & ~(uint32_t)3;
9260 if (insn & (1 << 23))
9261 offset -= imm;
9262 else
9263 offset += imm;
9264 tmp = tcg_temp_new_i32();
9265 tcg_gen_movi_i32(tmp, offset);
9266 } else {
9267 tmp = load_reg(s, rn);
9268 if (insn & (1 << 23))
9269 tcg_gen_subi_i32(tmp, tmp, imm);
9270 else
9271 tcg_gen_addi_i32(tmp, tmp, imm);
9274 store_reg(s, rd, tmp);
9276 } else {
9277 int shifter_out = 0;
9278 /* modified 12-bit immediate. */
9279 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
9280 imm = (insn & 0xff);
9281 switch (shift) {
9282 case 0: /* XY */
9283 /* Nothing to do. */
9284 break;
9285 case 1: /* 00XY00XY */
9286 imm |= imm << 16;
9287 break;
9288 case 2: /* XY00XY00 */
9289 imm |= imm << 16;
9290 imm <<= 8;
9291 break;
9292 case 3: /* XYXYXYXY */
9293 imm |= imm << 16;
9294 imm |= imm << 8;
9295 break;
9296 default: /* Rotated constant. */
9297 shift = (shift << 1) | (imm >> 7);
9298 imm |= 0x80;
9299 imm = imm << (32 - shift);
9300 shifter_out = 1;
9301 break;
9303 tmp2 = tcg_temp_new_i32();
9304 tcg_gen_movi_i32(tmp2, imm);
9305 rn = (insn >> 16) & 0xf;
9306 if (rn == 15) {
9307 tmp = tcg_temp_new_i32();
9308 tcg_gen_movi_i32(tmp, 0);
9309 } else {
9310 tmp = load_reg(s, rn);
9312 op = (insn >> 21) & 0xf;
9313 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
9314 shifter_out, tmp, tmp2))
9315 goto illegal_op;
9316 tcg_temp_free_i32(tmp2);
9317 rd = (insn >> 8) & 0xf;
9318 if (rd != 15) {
9319 store_reg(s, rd, tmp);
9320 } else {
9321 tcg_temp_free_i32(tmp);
9325 break;
9326 case 12: /* Load/store single data item. */
9328 int postinc = 0;
9329 int writeback = 0;
9330 int user;
9331 if ((insn & 0x01100000) == 0x01000000) {
9332 if (disas_neon_ls_insn(env, s, insn))
9333 goto illegal_op;
9334 break;
9336 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
9337 if (rs == 15) {
9338 if (!(insn & (1 << 20))) {
9339 goto illegal_op;
9341 if (op != 2) {
9342 /* Byte or halfword load space with dest == r15 : memory hints.
9343 * Catch them early so we don't emit pointless addressing code.
9344 * This space is a mix of:
9345 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
9346 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
9347 * cores)
9348 * unallocated hints, which must be treated as NOPs
9349 * UNPREDICTABLE space, which we NOP or UNDEF depending on
9350 * which is easiest for the decoding logic
9351 * Some space which must UNDEF
9353 int op1 = (insn >> 23) & 3;
9354 int op2 = (insn >> 6) & 0x3f;
9355 if (op & 2) {
9356 goto illegal_op;
9358 if (rn == 15) {
9359 /* UNPREDICTABLE, unallocated hint or
9360 * PLD/PLDW/PLI (literal)
9362 return 0;
9364 if (op1 & 1) {
9365 return 0; /* PLD/PLDW/PLI or unallocated hint */
9367 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
9368 return 0; /* PLD/PLDW/PLI or unallocated hint */
9370 /* UNDEF space, or an UNPREDICTABLE */
9371 return 1;
9374 user = IS_USER(s);
9375 if (rn == 15) {
9376 addr = tcg_temp_new_i32();
9377 /* PC relative. */
9378 /* s->pc has already been incremented by 4. */
9379 imm = s->pc & 0xfffffffc;
9380 if (insn & (1 << 23))
9381 imm += insn & 0xfff;
9382 else
9383 imm -= insn & 0xfff;
9384 tcg_gen_movi_i32(addr, imm);
9385 } else {
9386 addr = load_reg(s, rn);
9387 if (insn & (1 << 23)) {
9388 /* Positive offset. */
9389 imm = insn & 0xfff;
9390 tcg_gen_addi_i32(addr, addr, imm);
9391 } else {
9392 imm = insn & 0xff;
9393 switch ((insn >> 8) & 0xf) {
9394 case 0x0: /* Shifted Register. */
9395 shift = (insn >> 4) & 0xf;
9396 if (shift > 3) {
9397 tcg_temp_free_i32(addr);
9398 goto illegal_op;
9400 tmp = load_reg(s, rm);
9401 if (shift)
9402 tcg_gen_shli_i32(tmp, tmp, shift);
9403 tcg_gen_add_i32(addr, addr, tmp);
9404 tcg_temp_free_i32(tmp);
9405 break;
9406 case 0xc: /* Negative offset. */
9407 tcg_gen_addi_i32(addr, addr, -imm);
9408 break;
9409 case 0xe: /* User privilege. */
9410 tcg_gen_addi_i32(addr, addr, imm);
9411 user = 1;
9412 break;
9413 case 0x9: /* Post-decrement. */
9414 imm = -imm;
9415 /* Fall through. */
9416 case 0xb: /* Post-increment. */
9417 postinc = 1;
9418 writeback = 1;
9419 break;
9420 case 0xd: /* Pre-decrement. */
9421 imm = -imm;
9422 /* Fall through. */
9423 case 0xf: /* Pre-increment. */
9424 tcg_gen_addi_i32(addr, addr, imm);
9425 writeback = 1;
9426 break;
9427 default:
9428 tcg_temp_free_i32(addr);
9429 goto illegal_op;
9433 if (insn & (1 << 20)) {
9434 /* Load. */
9435 tmp = tcg_temp_new_i32();
9436 switch (op) {
9437 case 0:
9438 gen_aa32_ld8u(tmp, addr, user);
9439 break;
9440 case 4:
9441 gen_aa32_ld8s(tmp, addr, user);
9442 break;
9443 case 1:
9444 gen_aa32_ld16u(tmp, addr, user);
9445 break;
9446 case 5:
9447 gen_aa32_ld16s(tmp, addr, user);
9448 break;
9449 case 2:
9450 gen_aa32_ld32u(tmp, addr, user);
9451 break;
9452 default:
9453 tcg_temp_free_i32(tmp);
9454 tcg_temp_free_i32(addr);
9455 goto illegal_op;
9457 if (rs == 15) {
9458 gen_bx(s, tmp);
9459 } else {
9460 store_reg(s, rs, tmp);
9462 } else {
9463 /* Store. */
9464 tmp = load_reg(s, rs);
9465 switch (op) {
9466 case 0:
9467 gen_aa32_st8(tmp, addr, user);
9468 break;
9469 case 1:
9470 gen_aa32_st16(tmp, addr, user);
9471 break;
9472 case 2:
9473 gen_aa32_st32(tmp, addr, user);
9474 break;
9475 default:
9476 tcg_temp_free_i32(tmp);
9477 tcg_temp_free_i32(addr);
9478 goto illegal_op;
9480 tcg_temp_free_i32(tmp);
9482 if (postinc)
9483 tcg_gen_addi_i32(addr, addr, imm);
9484 if (writeback) {
9485 store_reg(s, rn, addr);
9486 } else {
9487 tcg_temp_free_i32(addr);
9490 break;
9491 default:
9492 goto illegal_op;
9494 return 0;
9495 illegal_op:
9496 return 1;
9499 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
9501 uint32_t val, insn, op, rm, rn, rd, shift, cond;
9502 int32_t offset;
9503 int i;
9504 TCGv_i32 tmp;
9505 TCGv_i32 tmp2;
9506 TCGv_i32 addr;
9508 if (s->condexec_mask) {
9509 cond = s->condexec_cond;
9510 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
9511 s->condlabel = gen_new_label();
9512 arm_gen_test_cc(cond ^ 1, s->condlabel);
9513 s->condjmp = 1;
9517 insn = arm_lduw_code(env, s->pc, s->bswap_code);
9518 s->pc += 2;
9520 switch (insn >> 12) {
9521 case 0: case 1:
9523 rd = insn & 7;
9524 op = (insn >> 11) & 3;
9525 if (op == 3) {
9526 /* add/subtract */
9527 rn = (insn >> 3) & 7;
9528 tmp = load_reg(s, rn);
9529 if (insn & (1 << 10)) {
9530 /* immediate */
9531 tmp2 = tcg_temp_new_i32();
9532 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
9533 } else {
9534 /* reg */
9535 rm = (insn >> 6) & 7;
9536 tmp2 = load_reg(s, rm);
9538 if (insn & (1 << 9)) {
9539 if (s->condexec_mask)
9540 tcg_gen_sub_i32(tmp, tmp, tmp2);
9541 else
9542 gen_sub_CC(tmp, tmp, tmp2);
9543 } else {
9544 if (s->condexec_mask)
9545 tcg_gen_add_i32(tmp, tmp, tmp2);
9546 else
9547 gen_add_CC(tmp, tmp, tmp2);
9549 tcg_temp_free_i32(tmp2);
9550 store_reg(s, rd, tmp);
9551 } else {
9552 /* shift immediate */
9553 rm = (insn >> 3) & 7;
9554 shift = (insn >> 6) & 0x1f;
9555 tmp = load_reg(s, rm);
9556 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
9557 if (!s->condexec_mask)
9558 gen_logic_CC(tmp);
9559 store_reg(s, rd, tmp);
9561 break;
9562 case 2: case 3:
9563 /* arithmetic large immediate */
9564 op = (insn >> 11) & 3;
9565 rd = (insn >> 8) & 0x7;
9566 if (op == 0) { /* mov */
9567 tmp = tcg_temp_new_i32();
9568 tcg_gen_movi_i32(tmp, insn & 0xff);
9569 if (!s->condexec_mask)
9570 gen_logic_CC(tmp);
9571 store_reg(s, rd, tmp);
9572 } else {
9573 tmp = load_reg(s, rd);
9574 tmp2 = tcg_temp_new_i32();
9575 tcg_gen_movi_i32(tmp2, insn & 0xff);
9576 switch (op) {
9577 case 1: /* cmp */
9578 gen_sub_CC(tmp, tmp, tmp2);
9579 tcg_temp_free_i32(tmp);
9580 tcg_temp_free_i32(tmp2);
9581 break;
9582 case 2: /* add */
9583 if (s->condexec_mask)
9584 tcg_gen_add_i32(tmp, tmp, tmp2);
9585 else
9586 gen_add_CC(tmp, tmp, tmp2);
9587 tcg_temp_free_i32(tmp2);
9588 store_reg(s, rd, tmp);
9589 break;
9590 case 3: /* sub */
9591 if (s->condexec_mask)
9592 tcg_gen_sub_i32(tmp, tmp, tmp2);
9593 else
9594 gen_sub_CC(tmp, tmp, tmp2);
9595 tcg_temp_free_i32(tmp2);
9596 store_reg(s, rd, tmp);
9597 break;
9600 break;
9601 case 4:
9602 if (insn & (1 << 11)) {
9603 rd = (insn >> 8) & 7;
9604 /* load pc-relative. Bit 1 of PC is ignored. */
9605 val = s->pc + 2 + ((insn & 0xff) * 4);
9606 val &= ~(uint32_t)2;
9607 addr = tcg_temp_new_i32();
9608 tcg_gen_movi_i32(addr, val);
9609 tmp = tcg_temp_new_i32();
9610 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9611 tcg_temp_free_i32(addr);
9612 store_reg(s, rd, tmp);
9613 break;
9615 if (insn & (1 << 10)) {
9616 /* data processing extended or blx */
9617 rd = (insn & 7) | ((insn >> 4) & 8);
9618 rm = (insn >> 3) & 0xf;
9619 op = (insn >> 8) & 3;
9620 switch (op) {
9621 case 0: /* add */
9622 tmp = load_reg(s, rd);
9623 tmp2 = load_reg(s, rm);
9624 tcg_gen_add_i32(tmp, tmp, tmp2);
9625 tcg_temp_free_i32(tmp2);
9626 store_reg(s, rd, tmp);
9627 break;
9628 case 1: /* cmp */
9629 tmp = load_reg(s, rd);
9630 tmp2 = load_reg(s, rm);
9631 gen_sub_CC(tmp, tmp, tmp2);
9632 tcg_temp_free_i32(tmp2);
9633 tcg_temp_free_i32(tmp);
9634 break;
9635 case 2: /* mov/cpy */
9636 tmp = load_reg(s, rm);
9637 store_reg(s, rd, tmp);
9638 break;
9639 case 3:/* branch [and link] exchange thumb register */
9640 tmp = load_reg(s, rm);
9641 if (insn & (1 << 7)) {
9642 ARCH(5);
9643 val = (uint32_t)s->pc | 1;
9644 tmp2 = tcg_temp_new_i32();
9645 tcg_gen_movi_i32(tmp2, val);
9646 store_reg(s, 14, tmp2);
9648 /* already thumb, no need to check */
9649 gen_bx(s, tmp);
9650 break;
9652 break;
9655 /* data processing register */
9656 rd = insn & 7;
9657 rm = (insn >> 3) & 7;
9658 op = (insn >> 6) & 0xf;
9659 if (op == 2 || op == 3 || op == 4 || op == 7) {
9660 /* the shift/rotate ops want the operands backwards */
9661 val = rm;
9662 rm = rd;
9663 rd = val;
9664 val = 1;
9665 } else {
9666 val = 0;
9669 if (op == 9) { /* neg */
9670 tmp = tcg_temp_new_i32();
9671 tcg_gen_movi_i32(tmp, 0);
9672 } else if (op != 0xf) { /* mvn doesn't read its first operand */
9673 tmp = load_reg(s, rd);
9674 } else {
9675 TCGV_UNUSED_I32(tmp);
9678 tmp2 = load_reg(s, rm);
9679 switch (op) {
9680 case 0x0: /* and */
9681 tcg_gen_and_i32(tmp, tmp, tmp2);
9682 if (!s->condexec_mask)
9683 gen_logic_CC(tmp);
9684 break;
9685 case 0x1: /* eor */
9686 tcg_gen_xor_i32(tmp, tmp, tmp2);
9687 if (!s->condexec_mask)
9688 gen_logic_CC(tmp);
9689 break;
9690 case 0x2: /* lsl */
9691 if (s->condexec_mask) {
9692 gen_shl(tmp2, tmp2, tmp);
9693 } else {
9694 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
9695 gen_logic_CC(tmp2);
9697 break;
9698 case 0x3: /* lsr */
9699 if (s->condexec_mask) {
9700 gen_shr(tmp2, tmp2, tmp);
9701 } else {
9702 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
9703 gen_logic_CC(tmp2);
9705 break;
9706 case 0x4: /* asr */
9707 if (s->condexec_mask) {
9708 gen_sar(tmp2, tmp2, tmp);
9709 } else {
9710 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
9711 gen_logic_CC(tmp2);
9713 break;
9714 case 0x5: /* adc */
9715 if (s->condexec_mask) {
9716 gen_adc(tmp, tmp2);
9717 } else {
9718 gen_adc_CC(tmp, tmp, tmp2);
9720 break;
9721 case 0x6: /* sbc */
9722 if (s->condexec_mask) {
9723 gen_sub_carry(tmp, tmp, tmp2);
9724 } else {
9725 gen_sbc_CC(tmp, tmp, tmp2);
9727 break;
9728 case 0x7: /* ror */
9729 if (s->condexec_mask) {
9730 tcg_gen_andi_i32(tmp, tmp, 0x1f);
9731 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
9732 } else {
9733 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
9734 gen_logic_CC(tmp2);
9736 break;
9737 case 0x8: /* tst */
9738 tcg_gen_and_i32(tmp, tmp, tmp2);
9739 gen_logic_CC(tmp);
9740 rd = 16;
9741 break;
9742 case 0x9: /* neg */
9743 if (s->condexec_mask)
9744 tcg_gen_neg_i32(tmp, tmp2);
9745 else
9746 gen_sub_CC(tmp, tmp, tmp2);
9747 break;
9748 case 0xa: /* cmp */
9749 gen_sub_CC(tmp, tmp, tmp2);
9750 rd = 16;
9751 break;
9752 case 0xb: /* cmn */
9753 gen_add_CC(tmp, tmp, tmp2);
9754 rd = 16;
9755 break;
9756 case 0xc: /* orr */
9757 tcg_gen_or_i32(tmp, tmp, tmp2);
9758 if (!s->condexec_mask)
9759 gen_logic_CC(tmp);
9760 break;
9761 case 0xd: /* mul */
9762 tcg_gen_mul_i32(tmp, tmp, tmp2);
9763 if (!s->condexec_mask)
9764 gen_logic_CC(tmp);
9765 break;
9766 case 0xe: /* bic */
9767 tcg_gen_andc_i32(tmp, tmp, tmp2);
9768 if (!s->condexec_mask)
9769 gen_logic_CC(tmp);
9770 break;
9771 case 0xf: /* mvn */
9772 tcg_gen_not_i32(tmp2, tmp2);
9773 if (!s->condexec_mask)
9774 gen_logic_CC(tmp2);
9775 val = 1;
9776 rm = rd;
9777 break;
9779 if (rd != 16) {
9780 if (val) {
9781 store_reg(s, rm, tmp2);
9782 if (op != 0xf)
9783 tcg_temp_free_i32(tmp);
9784 } else {
9785 store_reg(s, rd, tmp);
9786 tcg_temp_free_i32(tmp2);
9788 } else {
9789 tcg_temp_free_i32(tmp);
9790 tcg_temp_free_i32(tmp2);
9792 break;
9794 case 5:
9795 /* load/store register offset. */
9796 rd = insn & 7;
9797 rn = (insn >> 3) & 7;
9798 rm = (insn >> 6) & 7;
9799 op = (insn >> 9) & 7;
9800 addr = load_reg(s, rn);
9801 tmp = load_reg(s, rm);
9802 tcg_gen_add_i32(addr, addr, tmp);
9803 tcg_temp_free_i32(tmp);
9805 if (op < 3) { /* store */
9806 tmp = load_reg(s, rd);
9807 } else {
9808 tmp = tcg_temp_new_i32();
9811 switch (op) {
9812 case 0: /* str */
9813 gen_aa32_st32(tmp, addr, IS_USER(s));
9814 break;
9815 case 1: /* strh */
9816 gen_aa32_st16(tmp, addr, IS_USER(s));
9817 break;
9818 case 2: /* strb */
9819 gen_aa32_st8(tmp, addr, IS_USER(s));
9820 break;
9821 case 3: /* ldrsb */
9822 gen_aa32_ld8s(tmp, addr, IS_USER(s));
9823 break;
9824 case 4: /* ldr */
9825 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9826 break;
9827 case 5: /* ldrh */
9828 gen_aa32_ld16u(tmp, addr, IS_USER(s));
9829 break;
9830 case 6: /* ldrb */
9831 gen_aa32_ld8u(tmp, addr, IS_USER(s));
9832 break;
9833 case 7: /* ldrsh */
9834 gen_aa32_ld16s(tmp, addr, IS_USER(s));
9835 break;
9837 if (op >= 3) { /* load */
9838 store_reg(s, rd, tmp);
9839 } else {
9840 tcg_temp_free_i32(tmp);
9842 tcg_temp_free_i32(addr);
9843 break;
9845 case 6:
9846 /* load/store word immediate offset */
9847 rd = insn & 7;
9848 rn = (insn >> 3) & 7;
9849 addr = load_reg(s, rn);
9850 val = (insn >> 4) & 0x7c;
9851 tcg_gen_addi_i32(addr, addr, val);
9853 if (insn & (1 << 11)) {
9854 /* load */
9855 tmp = tcg_temp_new_i32();
9856 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9857 store_reg(s, rd, tmp);
9858 } else {
9859 /* store */
9860 tmp = load_reg(s, rd);
9861 gen_aa32_st32(tmp, addr, IS_USER(s));
9862 tcg_temp_free_i32(tmp);
9864 tcg_temp_free_i32(addr);
9865 break;
9867 case 7:
9868 /* load/store byte immediate offset */
9869 rd = insn & 7;
9870 rn = (insn >> 3) & 7;
9871 addr = load_reg(s, rn);
9872 val = (insn >> 6) & 0x1f;
9873 tcg_gen_addi_i32(addr, addr, val);
9875 if (insn & (1 << 11)) {
9876 /* load */
9877 tmp = tcg_temp_new_i32();
9878 gen_aa32_ld8u(tmp, addr, IS_USER(s));
9879 store_reg(s, rd, tmp);
9880 } else {
9881 /* store */
9882 tmp = load_reg(s, rd);
9883 gen_aa32_st8(tmp, addr, IS_USER(s));
9884 tcg_temp_free_i32(tmp);
9886 tcg_temp_free_i32(addr);
9887 break;
9889 case 8:
9890 /* load/store halfword immediate offset */
9891 rd = insn & 7;
9892 rn = (insn >> 3) & 7;
9893 addr = load_reg(s, rn);
9894 val = (insn >> 5) & 0x3e;
9895 tcg_gen_addi_i32(addr, addr, val);
9897 if (insn & (1 << 11)) {
9898 /* load */
9899 tmp = tcg_temp_new_i32();
9900 gen_aa32_ld16u(tmp, addr, IS_USER(s));
9901 store_reg(s, rd, tmp);
9902 } else {
9903 /* store */
9904 tmp = load_reg(s, rd);
9905 gen_aa32_st16(tmp, addr, IS_USER(s));
9906 tcg_temp_free_i32(tmp);
9908 tcg_temp_free_i32(addr);
9909 break;
9911 case 9:
9912 /* load/store from stack */
9913 rd = (insn >> 8) & 7;
9914 addr = load_reg(s, 13);
9915 val = (insn & 0xff) * 4;
9916 tcg_gen_addi_i32(addr, addr, val);
9918 if (insn & (1 << 11)) {
9919 /* load */
9920 tmp = tcg_temp_new_i32();
9921 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9922 store_reg(s, rd, tmp);
9923 } else {
9924 /* store */
9925 tmp = load_reg(s, rd);
9926 gen_aa32_st32(tmp, addr, IS_USER(s));
9927 tcg_temp_free_i32(tmp);
9929 tcg_temp_free_i32(addr);
9930 break;
9932 case 10:
9933 /* add to high reg */
9934 rd = (insn >> 8) & 7;
9935 if (insn & (1 << 11)) {
9936 /* SP */
9937 tmp = load_reg(s, 13);
9938 } else {
9939 /* PC. bit 1 is ignored. */
9940 tmp = tcg_temp_new_i32();
9941 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
9943 val = (insn & 0xff) * 4;
9944 tcg_gen_addi_i32(tmp, tmp, val);
9945 store_reg(s, rd, tmp);
9946 break;
9948 case 11:
9949 /* misc */
9950 op = (insn >> 8) & 0xf;
9951 switch (op) {
9952 case 0:
9953 /* adjust stack pointer */
9954 tmp = load_reg(s, 13);
9955 val = (insn & 0x7f) * 4;
9956 if (insn & (1 << 7))
9957 val = -(int32_t)val;
9958 tcg_gen_addi_i32(tmp, tmp, val);
9959 store_reg(s, 13, tmp);
9960 break;
9962 case 2: /* sign/zero extend. */
9963 ARCH(6);
9964 rd = insn & 7;
9965 rm = (insn >> 3) & 7;
9966 tmp = load_reg(s, rm);
9967 switch ((insn >> 6) & 3) {
9968 case 0: gen_sxth(tmp); break;
9969 case 1: gen_sxtb(tmp); break;
9970 case 2: gen_uxth(tmp); break;
9971 case 3: gen_uxtb(tmp); break;
9973 store_reg(s, rd, tmp);
9974 break;
9975 case 4: case 5: case 0xc: case 0xd:
9976 /* push/pop */
9977 addr = load_reg(s, 13);
9978 if (insn & (1 << 8))
9979 offset = 4;
9980 else
9981 offset = 0;
9982 for (i = 0; i < 8; i++) {
9983 if (insn & (1 << i))
9984 offset += 4;
9986 if ((insn & (1 << 11)) == 0) {
9987 tcg_gen_addi_i32(addr, addr, -offset);
9989 for (i = 0; i < 8; i++) {
9990 if (insn & (1 << i)) {
9991 if (insn & (1 << 11)) {
9992 /* pop */
9993 tmp = tcg_temp_new_i32();
9994 gen_aa32_ld32u(tmp, addr, IS_USER(s));
9995 store_reg(s, i, tmp);
9996 } else {
9997 /* push */
9998 tmp = load_reg(s, i);
9999 gen_aa32_st32(tmp, addr, IS_USER(s));
10000 tcg_temp_free_i32(tmp);
10002 /* advance to the next address. */
10003 tcg_gen_addi_i32(addr, addr, 4);
10006 TCGV_UNUSED_I32(tmp);
10007 if (insn & (1 << 8)) {
10008 if (insn & (1 << 11)) {
10009 /* pop pc */
10010 tmp = tcg_temp_new_i32();
10011 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10012 /* don't set the pc until the rest of the instruction
10013 has completed */
10014 } else {
10015 /* push lr */
10016 tmp = load_reg(s, 14);
10017 gen_aa32_st32(tmp, addr, IS_USER(s));
10018 tcg_temp_free_i32(tmp);
10020 tcg_gen_addi_i32(addr, addr, 4);
10022 if ((insn & (1 << 11)) == 0) {
10023 tcg_gen_addi_i32(addr, addr, -offset);
10025 /* write back the new stack pointer */
10026 store_reg(s, 13, addr);
10027 /* set the new PC value */
10028 if ((insn & 0x0900) == 0x0900) {
10029 store_reg_from_load(env, s, 15, tmp);
10031 break;
10033 case 1: case 3: case 9: case 11: /* czb */
10034 rm = insn & 7;
10035 tmp = load_reg(s, rm);
10036 s->condlabel = gen_new_label();
10037 s->condjmp = 1;
10038 if (insn & (1 << 11))
10039 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
10040 else
10041 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
10042 tcg_temp_free_i32(tmp);
10043 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
10044 val = (uint32_t)s->pc + 2;
10045 val += offset;
10046 gen_jmp(s, val);
10047 break;
10049 case 15: /* IT, nop-hint. */
10050 if ((insn & 0xf) == 0) {
10051 gen_nop_hint(s, (insn >> 4) & 0xf);
10052 break;
10054 /* If Then. */
10055 s->condexec_cond = (insn >> 4) & 0xe;
10056 s->condexec_mask = insn & 0x1f;
10057 /* No actual code generated for this insn, just setup state. */
10058 break;
10060 case 0xe: /* bkpt */
10061 ARCH(5);
10062 gen_exception_insn(s, 2, EXCP_BKPT);
10063 break;
10065 case 0xa: /* rev */
10066 ARCH(6);
10067 rn = (insn >> 3) & 0x7;
10068 rd = insn & 0x7;
10069 tmp = load_reg(s, rn);
10070 switch ((insn >> 6) & 3) {
10071 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
10072 case 1: gen_rev16(tmp); break;
10073 case 3: gen_revsh(tmp); break;
10074 default: goto illegal_op;
10076 store_reg(s, rd, tmp);
10077 break;
10079 case 6:
10080 switch ((insn >> 5) & 7) {
10081 case 2:
10082 /* setend */
10083 ARCH(6);
10084 if (((insn >> 3) & 1) != s->bswap_code) {
10085 /* Dynamic endianness switching not implemented. */
10086 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
10087 goto illegal_op;
10089 break;
10090 case 3:
10091 /* cps */
10092 ARCH(6);
10093 if (IS_USER(s)) {
10094 break;
10096 if (IS_M(env)) {
10097 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
10098 /* FAULTMASK */
10099 if (insn & 1) {
10100 addr = tcg_const_i32(19);
10101 gen_helper_v7m_msr(cpu_env, addr, tmp);
10102 tcg_temp_free_i32(addr);
10104 /* PRIMASK */
10105 if (insn & 2) {
10106 addr = tcg_const_i32(16);
10107 gen_helper_v7m_msr(cpu_env, addr, tmp);
10108 tcg_temp_free_i32(addr);
10110 tcg_temp_free_i32(tmp);
10111 gen_lookup_tb(s);
10112 } else {
10113 if (insn & (1 << 4)) {
10114 shift = CPSR_A | CPSR_I | CPSR_F;
10115 } else {
10116 shift = 0;
10118 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
10120 break;
10121 default:
10122 goto undef;
10124 break;
10126 default:
10127 goto undef;
10129 break;
10131 case 12:
10133 /* load/store multiple */
10134 TCGv_i32 loaded_var;
10135 TCGV_UNUSED_I32(loaded_var);
10136 rn = (insn >> 8) & 0x7;
10137 addr = load_reg(s, rn);
10138 for (i = 0; i < 8; i++) {
10139 if (insn & (1 << i)) {
10140 if (insn & (1 << 11)) {
10141 /* load */
10142 tmp = tcg_temp_new_i32();
10143 gen_aa32_ld32u(tmp, addr, IS_USER(s));
10144 if (i == rn) {
10145 loaded_var = tmp;
10146 } else {
10147 store_reg(s, i, tmp);
10149 } else {
10150 /* store */
10151 tmp = load_reg(s, i);
10152 gen_aa32_st32(tmp, addr, IS_USER(s));
10153 tcg_temp_free_i32(tmp);
10155 /* advance to the next address */
10156 tcg_gen_addi_i32(addr, addr, 4);
10159 if ((insn & (1 << rn)) == 0) {
10160 /* base reg not in list: base register writeback */
10161 store_reg(s, rn, addr);
10162 } else {
10163 /* base reg in list: if load, complete it now */
10164 if (insn & (1 << 11)) {
10165 store_reg(s, rn, loaded_var);
10167 tcg_temp_free_i32(addr);
10169 break;
10171 case 13:
10172 /* conditional branch or swi */
10173 cond = (insn >> 8) & 0xf;
10174 if (cond == 0xe)
10175 goto undef;
10177 if (cond == 0xf) {
10178 /* swi */
10179 gen_set_pc_im(s, s->pc);
10180 s->is_jmp = DISAS_SWI;
10181 break;
10183 /* generate a conditional jump to next instruction */
10184 s->condlabel = gen_new_label();
10185 arm_gen_test_cc(cond ^ 1, s->condlabel);
10186 s->condjmp = 1;
10188 /* jump to the offset */
10189 val = (uint32_t)s->pc + 2;
10190 offset = ((int32_t)insn << 24) >> 24;
10191 val += offset << 1;
10192 gen_jmp(s, val);
10193 break;
10195 case 14:
10196 if (insn & (1 << 11)) {
10197 if (disas_thumb2_insn(env, s, insn))
10198 goto undef32;
10199 break;
10201 /* unconditional branch */
10202 val = (uint32_t)s->pc;
10203 offset = ((int32_t)insn << 21) >> 21;
10204 val += (offset << 1) + 2;
10205 gen_jmp(s, val);
10206 break;
10208 case 15:
10209 if (disas_thumb2_insn(env, s, insn))
10210 goto undef32;
10211 break;
10213 return;
10214 undef32:
10215 gen_exception_insn(s, 4, EXCP_UDEF);
10216 return;
10217 illegal_op:
10218 undef:
10219 gen_exception_insn(s, 2, EXCP_UDEF);
10222 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
10223 basic block 'tb'. If search_pc is TRUE, also generate PC
10224 information for each intermediate instruction. */
10225 static inline void gen_intermediate_code_internal(ARMCPU *cpu,
10226 TranslationBlock *tb,
10227 bool search_pc)
10229 CPUState *cs = CPU(cpu);
10230 CPUARMState *env = &cpu->env;
10231 DisasContext dc1, *dc = &dc1;
10232 CPUBreakpoint *bp;
10233 uint16_t *gen_opc_end;
10234 int j, lj;
10235 target_ulong pc_start;
10236 target_ulong next_page_start;
10237 int num_insns;
10238 int max_insns;
10240 /* generate intermediate code */
10242 /* The A64 decoder has its own top level loop, because it doesn't need
10243 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
10245 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
10246 gen_intermediate_code_internal_a64(cpu, tb, search_pc);
10247 return;
10250 pc_start = tb->pc;
10252 dc->tb = tb;
10254 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
10256 dc->is_jmp = DISAS_NEXT;
10257 dc->pc = pc_start;
10258 dc->singlestep_enabled = cs->singlestep_enabled;
10259 dc->condjmp = 0;
10261 dc->aarch64 = 0;
10262 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
10263 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
10264 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
10265 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
10266 #if !defined(CONFIG_USER_ONLY)
10267 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
10268 #endif
10269 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
10270 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
10271 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
10273 cpu_F0s = tcg_temp_new_i32();
10274 cpu_F1s = tcg_temp_new_i32();
10275 cpu_F0d = tcg_temp_new_i64();
10276 cpu_F1d = tcg_temp_new_i64();
10277 cpu_V0 = cpu_F0d;
10278 cpu_V1 = cpu_F1d;
10279 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
10280 cpu_M0 = tcg_temp_new_i64();
10281 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
10282 lj = -1;
10283 num_insns = 0;
10284 max_insns = tb->cflags & CF_COUNT_MASK;
10285 if (max_insns == 0)
10286 max_insns = CF_COUNT_MASK;
10288 gen_tb_start();
10290 tcg_clear_temp_count();
10292 /* A note on handling of the condexec (IT) bits:
10294 * We want to avoid the overhead of having to write the updated condexec
10295 * bits back to the CPUARMState for every instruction in an IT block. So:
10296 * (1) if the condexec bits are not already zero then we write
10297 * zero back into the CPUARMState now. This avoids complications trying
10298 * to do it at the end of the block. (For example if we don't do this
10299 * it's hard to identify whether we can safely skip writing condexec
10300 * at the end of the TB, which we definitely want to do for the case
10301 * where a TB doesn't do anything with the IT state at all.)
10302 * (2) if we are going to leave the TB then we call gen_set_condexec()
10303 * which will write the correct value into CPUARMState if zero is wrong.
10304 * This is done both for leaving the TB at the end, and for leaving
10305 * it because of an exception we know will happen, which is done in
10306 * gen_exception_insn(). The latter is necessary because we need to
10307 * leave the TB with the PC/IT state just prior to execution of the
10308 * instruction which caused the exception.
10309 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
10310 * then the CPUARMState will be wrong and we need to reset it.
10311 * This is handled in the same way as restoration of the
10312 * PC in these situations: we will be called again with search_pc=1
10313 * and generate a mapping of the condexec bits for each PC in
10314 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
10315 * this to restore the condexec bits.
10317 * Note that there are no instructions which can read the condexec
10318 * bits, and none which can write non-static values to them, so
10319 * we don't need to care about whether CPUARMState is correct in the
10320 * middle of a TB.
10323 /* Reset the conditional execution bits immediately. This avoids
10324 complications trying to do it at the end of the block. */
10325 if (dc->condexec_mask || dc->condexec_cond)
10327 TCGv_i32 tmp = tcg_temp_new_i32();
10328 tcg_gen_movi_i32(tmp, 0);
10329 store_cpu_field(tmp, condexec_bits);
10331 do {
10332 #ifdef CONFIG_USER_ONLY
10333 /* Intercept jump to the magic kernel page. */
10334 if (dc->pc >= 0xffff0000) {
10335 /* We always get here via a jump, so know we are not in a
10336 conditional execution block. */
10337 gen_exception(EXCP_KERNEL_TRAP);
10338 dc->is_jmp = DISAS_UPDATE;
10339 break;
10341 #else
10342 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
10343 /* We always get here via a jump, so know we are not in a
10344 conditional execution block. */
10345 gen_exception(EXCP_EXCEPTION_EXIT);
10346 dc->is_jmp = DISAS_UPDATE;
10347 break;
10349 #endif
10351 if (unlikely(!QTAILQ_EMPTY(&env->breakpoints))) {
10352 QTAILQ_FOREACH(bp, &env->breakpoints, entry) {
10353 if (bp->pc == dc->pc) {
10354 gen_exception_insn(dc, 0, EXCP_DEBUG);
10355 /* Advance PC so that clearing the breakpoint will
10356 invalidate this TB. */
10357 dc->pc += 2;
10358 goto done_generating;
10362 if (search_pc) {
10363 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10364 if (lj < j) {
10365 lj++;
10366 while (lj < j)
10367 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10369 tcg_ctx.gen_opc_pc[lj] = dc->pc;
10370 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
10371 tcg_ctx.gen_opc_instr_start[lj] = 1;
10372 tcg_ctx.gen_opc_icount[lj] = num_insns;
10375 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
10376 gen_io_start();
10378 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
10379 tcg_gen_debug_insn_start(dc->pc);
10382 if (dc->thumb) {
10383 disas_thumb_insn(env, dc);
10384 if (dc->condexec_mask) {
10385 dc->condexec_cond = (dc->condexec_cond & 0xe)
10386 | ((dc->condexec_mask >> 4) & 1);
10387 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
10388 if (dc->condexec_mask == 0) {
10389 dc->condexec_cond = 0;
10392 } else {
10393 disas_arm_insn(env, dc);
10396 if (dc->condjmp && !dc->is_jmp) {
10397 gen_set_label(dc->condlabel);
10398 dc->condjmp = 0;
10401 if (tcg_check_temp_count()) {
10402 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
10403 dc->pc);
10406 /* Translation stops when a conditional branch is encountered.
10407 * Otherwise the subsequent code could get translated several times.
10408 * Also stop translation when a page boundary is reached. This
10409 * ensures prefetch aborts occur at the right place. */
10410 num_insns ++;
10411 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
10412 !cs->singlestep_enabled &&
10413 !singlestep &&
10414 dc->pc < next_page_start &&
10415 num_insns < max_insns);
10417 if (tb->cflags & CF_LAST_IO) {
10418 if (dc->condjmp) {
10419 /* FIXME: This can theoretically happen with self-modifying
10420 code. */
10421 cpu_abort(env, "IO on conditional branch instruction");
10423 gen_io_end();
10426 /* At this stage dc->condjmp will only be set when the skipped
10427 instruction was a conditional branch or trap, and the PC has
10428 already been written. */
10429 if (unlikely(cs->singlestep_enabled)) {
10430 /* Make sure the pc is updated, and raise a debug exception. */
10431 if (dc->condjmp) {
10432 gen_set_condexec(dc);
10433 if (dc->is_jmp == DISAS_SWI) {
10434 gen_exception(EXCP_SWI);
10435 } else {
10436 gen_exception(EXCP_DEBUG);
10438 gen_set_label(dc->condlabel);
10440 if (dc->condjmp || !dc->is_jmp) {
10441 gen_set_pc_im(dc, dc->pc);
10442 dc->condjmp = 0;
10444 gen_set_condexec(dc);
10445 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
10446 gen_exception(EXCP_SWI);
10447 } else {
10448 /* FIXME: Single stepping a WFI insn will not halt
10449 the CPU. */
10450 gen_exception(EXCP_DEBUG);
10452 } else {
10453 /* While branches must always occur at the end of an IT block,
10454 there are a few other things that can cause us to terminate
10455 the TB in the middle of an IT block:
10456 - Exception generating instructions (bkpt, swi, undefined).
10457 - Page boundaries.
10458 - Hardware watchpoints.
10459 Hardware breakpoints have already been handled and skip this code.
10461 gen_set_condexec(dc);
10462 switch(dc->is_jmp) {
10463 case DISAS_NEXT:
10464 gen_goto_tb(dc, 1, dc->pc);
10465 break;
10466 default:
10467 case DISAS_JUMP:
10468 case DISAS_UPDATE:
10469 /* indicate that the hash table must be used to find the next TB */
10470 tcg_gen_exit_tb(0);
10471 break;
10472 case DISAS_TB_JUMP:
10473 /* nothing more to generate */
10474 break;
10475 case DISAS_WFI:
10476 gen_helper_wfi(cpu_env);
10477 break;
10478 case DISAS_SWI:
10479 gen_exception(EXCP_SWI);
10480 break;
10482 if (dc->condjmp) {
10483 gen_set_label(dc->condlabel);
10484 gen_set_condexec(dc);
10485 gen_goto_tb(dc, 1, dc->pc);
10486 dc->condjmp = 0;
10490 done_generating:
10491 gen_tb_end(tb, num_insns);
10492 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
10494 #ifdef DEBUG_DISAS
10495 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
10496 qemu_log("----------------\n");
10497 qemu_log("IN: %s\n", lookup_symbol(pc_start));
10498 log_target_disas(env, pc_start, dc->pc - pc_start,
10499 dc->thumb | (dc->bswap_code << 1));
10500 qemu_log("\n");
10502 #endif
10503 if (search_pc) {
10504 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10505 lj++;
10506 while (lj <= j)
10507 tcg_ctx.gen_opc_instr_start[lj++] = 0;
10508 } else {
10509 tb->size = dc->pc - pc_start;
10510 tb->icount = num_insns;
10514 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
10516 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
10519 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
10521 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
10524 static const char *cpu_mode_names[16] = {
10525 "usr", "fiq", "irq", "svc", "???", "???", "???", "abt",
10526 "???", "???", "???", "und", "???", "???", "???", "sys"
10529 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
10530 int flags)
10532 ARMCPU *cpu = ARM_CPU(cs);
10533 CPUARMState *env = &cpu->env;
10534 int i;
10535 uint32_t psr;
10537 for(i=0;i<16;i++) {
10538 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
10539 if ((i % 4) == 3)
10540 cpu_fprintf(f, "\n");
10541 else
10542 cpu_fprintf(f, " ");
10544 psr = cpsr_read(env);
10545 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
10546 psr,
10547 psr & (1 << 31) ? 'N' : '-',
10548 psr & (1 << 30) ? 'Z' : '-',
10549 psr & (1 << 29) ? 'C' : '-',
10550 psr & (1 << 28) ? 'V' : '-',
10551 psr & CPSR_T ? 'T' : 'A',
10552 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
10554 if (flags & CPU_DUMP_FPU) {
10555 int numvfpregs = 0;
10556 if (arm_feature(env, ARM_FEATURE_VFP)) {
10557 numvfpregs += 16;
10559 if (arm_feature(env, ARM_FEATURE_VFP3)) {
10560 numvfpregs += 16;
10562 for (i = 0; i < numvfpregs; i++) {
10563 uint64_t v = float64_val(env->vfp.regs[i]);
10564 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
10565 i * 2, (uint32_t)v,
10566 i * 2 + 1, (uint32_t)(v >> 32),
10567 i, v);
10569 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
10573 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
10575 if (is_a64(env)) {
10576 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
10577 env->condexec_bits = 0;
10578 } else {
10579 env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
10580 env->condexec_bits = gen_opc_condexec_bits[pc_pos];