tests: disable global props test for old glib
[qemu/ar7.git] / target-arm / translate.c
blob2c0b1deaea81f8c1686494dc8ecb74a37d80497c
1 /*
2 * ARM translation
4 * Copyright (c) 2003 Fabrice Bellard
5 * Copyright (c) 2005-2007 CodeSourcery
6 * Copyright (c) 2007 OpenedHand, Ltd.
8 * This library is free software; you can redistribute it and/or
9 * modify it under the terms of the GNU Lesser General Public
10 * License as published by the Free Software Foundation; either
11 * version 2 of the License, or (at your option) any later version.
13 * This library is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
16 * Lesser General Public License for more details.
18 * You should have received a copy of the GNU Lesser General Public
19 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21 #include <stdarg.h>
22 #include <stdlib.h>
23 #include <stdio.h>
24 #include <string.h>
25 #include <inttypes.h>
27 #include "cpu.h"
28 #include "internals.h"
29 #include "disas/disas.h"
30 #include "tcg-op.h"
31 #include "qemu/log.h"
32 #include "qemu/bitops.h"
33 #include "arm_ldst.h"
35 #include "exec/helper-proto.h"
36 #include "exec/helper-gen.h"
38 #include "trace-tcg.h"
41 #define ENABLE_ARCH_4T arm_feature(env, ARM_FEATURE_V4T)
42 #define ENABLE_ARCH_5 arm_feature(env, ARM_FEATURE_V5)
43 /* currently all emulated v5 cores are also v5TE, so don't bother */
44 #define ENABLE_ARCH_5TE arm_feature(env, ARM_FEATURE_V5)
45 #define ENABLE_ARCH_5J 0
46 #define ENABLE_ARCH_6 arm_feature(env, ARM_FEATURE_V6)
47 #define ENABLE_ARCH_6K arm_feature(env, ARM_FEATURE_V6K)
48 #define ENABLE_ARCH_6T2 arm_feature(env, ARM_FEATURE_THUMB2)
49 #define ENABLE_ARCH_7 arm_feature(env, ARM_FEATURE_V7)
50 #define ENABLE_ARCH_8 arm_feature(env, ARM_FEATURE_V8)
52 #define ARCH(x) do { if (!ENABLE_ARCH_##x) goto illegal_op; } while(0)
54 #include "translate.h"
55 static uint32_t gen_opc_condexec_bits[OPC_BUF_SIZE];
57 #if defined(CONFIG_USER_ONLY)
58 #define IS_USER(s) 1
59 #else
60 #define IS_USER(s) (s->user)
61 #endif
63 TCGv_ptr cpu_env;
64 /* We reuse the same 64-bit temporaries for efficiency. */
65 static TCGv_i64 cpu_V0, cpu_V1, cpu_M0;
66 static TCGv_i32 cpu_R[16];
67 static TCGv_i32 cpu_CF, cpu_NF, cpu_VF, cpu_ZF;
68 static TCGv_i64 cpu_exclusive_addr;
69 static TCGv_i64 cpu_exclusive_val;
70 #ifdef CONFIG_USER_ONLY
71 static TCGv_i64 cpu_exclusive_test;
72 static TCGv_i32 cpu_exclusive_info;
73 #endif
75 /* FIXME: These should be removed. */
76 static TCGv_i32 cpu_F0s, cpu_F1s;
77 static TCGv_i64 cpu_F0d, cpu_F1d;
79 #include "exec/gen-icount.h"
81 static const char *regnames[] =
82 { "r0", "r1", "r2", "r3", "r4", "r5", "r6", "r7",
83 "r8", "r9", "r10", "r11", "r12", "r13", "r14", "pc" };
85 /* initialize TCG globals. */
86 void arm_translate_init(void)
88 int i;
90 cpu_env = tcg_global_reg_new_ptr(TCG_AREG0, "env");
92 for (i = 0; i < 16; i++) {
93 cpu_R[i] = tcg_global_mem_new_i32(TCG_AREG0,
94 offsetof(CPUARMState, regs[i]),
95 regnames[i]);
97 cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
98 cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
99 cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
100 cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
102 cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
103 offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
104 cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
105 offsetof(CPUARMState, exclusive_val), "exclusive_val");
106 #ifdef CONFIG_USER_ONLY
107 cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
108 offsetof(CPUARMState, exclusive_test), "exclusive_test");
109 cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
110 offsetof(CPUARMState, exclusive_info), "exclusive_info");
111 #endif
113 a64_translate_init();
116 static inline TCGv_i32 load_cpu_offset(int offset)
118 TCGv_i32 tmp = tcg_temp_new_i32();
119 tcg_gen_ld_i32(tmp, cpu_env, offset);
120 return tmp;
123 #define load_cpu_field(name) load_cpu_offset(offsetof(CPUARMState, name))
125 static inline void store_cpu_offset(TCGv_i32 var, int offset)
127 tcg_gen_st_i32(var, cpu_env, offset);
128 tcg_temp_free_i32(var);
131 #define store_cpu_field(var, name) \
132 store_cpu_offset(var, offsetof(CPUARMState, name))
134 /* Set a variable to the value of a CPU register. */
135 static void load_reg_var(DisasContext *s, TCGv_i32 var, int reg)
137 if (reg == 15) {
138 uint32_t addr;
139 /* normally, since we updated PC, we need only to add one insn */
140 if (s->thumb)
141 addr = (long)s->pc + 2;
142 else
143 addr = (long)s->pc + 4;
144 tcg_gen_movi_i32(var, addr);
145 } else {
146 tcg_gen_mov_i32(var, cpu_R[reg]);
150 /* Create a new temporary and set it to the value of a CPU register. */
151 static inline TCGv_i32 load_reg(DisasContext *s, int reg)
153 TCGv_i32 tmp = tcg_temp_new_i32();
154 load_reg_var(s, tmp, reg);
155 return tmp;
158 /* Set a CPU register. The source must be a temporary and will be
159 marked as dead. */
160 static void store_reg(DisasContext *s, int reg, TCGv_i32 var)
162 if (reg == 15) {
163 tcg_gen_andi_i32(var, var, ~1);
164 s->is_jmp = DISAS_JUMP;
166 tcg_gen_mov_i32(cpu_R[reg], var);
167 tcg_temp_free_i32(var);
170 /* Value extensions. */
171 #define gen_uxtb(var) tcg_gen_ext8u_i32(var, var)
172 #define gen_uxth(var) tcg_gen_ext16u_i32(var, var)
173 #define gen_sxtb(var) tcg_gen_ext8s_i32(var, var)
174 #define gen_sxth(var) tcg_gen_ext16s_i32(var, var)
176 #define gen_sxtb16(var) gen_helper_sxtb16(var, var)
177 #define gen_uxtb16(var) gen_helper_uxtb16(var, var)
180 static inline void gen_set_cpsr(TCGv_i32 var, uint32_t mask)
182 TCGv_i32 tmp_mask = tcg_const_i32(mask);
183 gen_helper_cpsr_write(cpu_env, var, tmp_mask);
184 tcg_temp_free_i32(tmp_mask);
186 /* Set NZCV flags from the high 4 bits of var. */
187 #define gen_set_nzcv(var) gen_set_cpsr(var, CPSR_NZCV)
189 static void gen_exception_internal(int excp)
191 TCGv_i32 tcg_excp = tcg_const_i32(excp);
193 assert(excp_is_internal(excp));
194 gen_helper_exception_internal(cpu_env, tcg_excp);
195 tcg_temp_free_i32(tcg_excp);
198 static void gen_exception(int excp, uint32_t syndrome)
200 TCGv_i32 tcg_excp = tcg_const_i32(excp);
201 TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
203 gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn);
204 tcg_temp_free_i32(tcg_syn);
205 tcg_temp_free_i32(tcg_excp);
208 static void gen_ss_advance(DisasContext *s)
210 /* If the singlestep state is Active-not-pending, advance to
211 * Active-pending.
213 if (s->ss_active) {
214 s->pstate_ss = 0;
215 gen_helper_clear_pstate_ss(cpu_env);
219 static void gen_step_complete_exception(DisasContext *s)
221 /* We just completed step of an insn. Move from Active-not-pending
222 * to Active-pending, and then also take the swstep exception.
223 * This corresponds to making the (IMPDEF) choice to prioritize
224 * swstep exceptions over asynchronous exceptions taken to an exception
225 * level where debug is disabled. This choice has the advantage that
226 * we do not need to maintain internal state corresponding to the
227 * ISV/EX syndrome bits between completion of the step and generation
228 * of the exception, and our syndrome information is always correct.
230 gen_ss_advance(s);
231 gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex));
232 s->is_jmp = DISAS_EXC;
235 static void gen_smul_dual(TCGv_i32 a, TCGv_i32 b)
237 TCGv_i32 tmp1 = tcg_temp_new_i32();
238 TCGv_i32 tmp2 = tcg_temp_new_i32();
239 tcg_gen_ext16s_i32(tmp1, a);
240 tcg_gen_ext16s_i32(tmp2, b);
241 tcg_gen_mul_i32(tmp1, tmp1, tmp2);
242 tcg_temp_free_i32(tmp2);
243 tcg_gen_sari_i32(a, a, 16);
244 tcg_gen_sari_i32(b, b, 16);
245 tcg_gen_mul_i32(b, b, a);
246 tcg_gen_mov_i32(a, tmp1);
247 tcg_temp_free_i32(tmp1);
250 /* Byteswap each halfword. */
251 static void gen_rev16(TCGv_i32 var)
253 TCGv_i32 tmp = tcg_temp_new_i32();
254 tcg_gen_shri_i32(tmp, var, 8);
255 tcg_gen_andi_i32(tmp, tmp, 0x00ff00ff);
256 tcg_gen_shli_i32(var, var, 8);
257 tcg_gen_andi_i32(var, var, 0xff00ff00);
258 tcg_gen_or_i32(var, var, tmp);
259 tcg_temp_free_i32(tmp);
262 /* Byteswap low halfword and sign extend. */
263 static void gen_revsh(TCGv_i32 var)
265 tcg_gen_ext16u_i32(var, var);
266 tcg_gen_bswap16_i32(var, var);
267 tcg_gen_ext16s_i32(var, var);
270 /* Unsigned bitfield extract. */
271 static void gen_ubfx(TCGv_i32 var, int shift, uint32_t mask)
273 if (shift)
274 tcg_gen_shri_i32(var, var, shift);
275 tcg_gen_andi_i32(var, var, mask);
278 /* Signed bitfield extract. */
279 static void gen_sbfx(TCGv_i32 var, int shift, int width)
281 uint32_t signbit;
283 if (shift)
284 tcg_gen_sari_i32(var, var, shift);
285 if (shift + width < 32) {
286 signbit = 1u << (width - 1);
287 tcg_gen_andi_i32(var, var, (1u << width) - 1);
288 tcg_gen_xori_i32(var, var, signbit);
289 tcg_gen_subi_i32(var, var, signbit);
293 /* Return (b << 32) + a. Mark inputs as dead */
294 static TCGv_i64 gen_addq_msw(TCGv_i64 a, TCGv_i32 b)
296 TCGv_i64 tmp64 = tcg_temp_new_i64();
298 tcg_gen_extu_i32_i64(tmp64, b);
299 tcg_temp_free_i32(b);
300 tcg_gen_shli_i64(tmp64, tmp64, 32);
301 tcg_gen_add_i64(a, tmp64, a);
303 tcg_temp_free_i64(tmp64);
304 return a;
307 /* Return (b << 32) - a. Mark inputs as dead. */
308 static TCGv_i64 gen_subq_msw(TCGv_i64 a, TCGv_i32 b)
310 TCGv_i64 tmp64 = tcg_temp_new_i64();
312 tcg_gen_extu_i32_i64(tmp64, b);
313 tcg_temp_free_i32(b);
314 tcg_gen_shli_i64(tmp64, tmp64, 32);
315 tcg_gen_sub_i64(a, tmp64, a);
317 tcg_temp_free_i64(tmp64);
318 return a;
321 /* 32x32->64 multiply. Marks inputs as dead. */
322 static TCGv_i64 gen_mulu_i64_i32(TCGv_i32 a, TCGv_i32 b)
324 TCGv_i32 lo = tcg_temp_new_i32();
325 TCGv_i32 hi = tcg_temp_new_i32();
326 TCGv_i64 ret;
328 tcg_gen_mulu2_i32(lo, hi, a, b);
329 tcg_temp_free_i32(a);
330 tcg_temp_free_i32(b);
332 ret = tcg_temp_new_i64();
333 tcg_gen_concat_i32_i64(ret, lo, hi);
334 tcg_temp_free_i32(lo);
335 tcg_temp_free_i32(hi);
337 return ret;
340 static TCGv_i64 gen_muls_i64_i32(TCGv_i32 a, TCGv_i32 b)
342 TCGv_i32 lo = tcg_temp_new_i32();
343 TCGv_i32 hi = tcg_temp_new_i32();
344 TCGv_i64 ret;
346 tcg_gen_muls2_i32(lo, hi, a, b);
347 tcg_temp_free_i32(a);
348 tcg_temp_free_i32(b);
350 ret = tcg_temp_new_i64();
351 tcg_gen_concat_i32_i64(ret, lo, hi);
352 tcg_temp_free_i32(lo);
353 tcg_temp_free_i32(hi);
355 return ret;
358 /* Swap low and high halfwords. */
359 static void gen_swap_half(TCGv_i32 var)
361 TCGv_i32 tmp = tcg_temp_new_i32();
362 tcg_gen_shri_i32(tmp, var, 16);
363 tcg_gen_shli_i32(var, var, 16);
364 tcg_gen_or_i32(var, var, tmp);
365 tcg_temp_free_i32(tmp);
368 /* Dual 16-bit add. Result placed in t0 and t1 is marked as dead.
369 tmp = (t0 ^ t1) & 0x8000;
370 t0 &= ~0x8000;
371 t1 &= ~0x8000;
372 t0 = (t0 + t1) ^ tmp;
375 static void gen_add16(TCGv_i32 t0, TCGv_i32 t1)
377 TCGv_i32 tmp = tcg_temp_new_i32();
378 tcg_gen_xor_i32(tmp, t0, t1);
379 tcg_gen_andi_i32(tmp, tmp, 0x8000);
380 tcg_gen_andi_i32(t0, t0, ~0x8000);
381 tcg_gen_andi_i32(t1, t1, ~0x8000);
382 tcg_gen_add_i32(t0, t0, t1);
383 tcg_gen_xor_i32(t0, t0, tmp);
384 tcg_temp_free_i32(tmp);
385 tcg_temp_free_i32(t1);
388 /* Set CF to the top bit of var. */
389 static void gen_set_CF_bit31(TCGv_i32 var)
391 tcg_gen_shri_i32(cpu_CF, var, 31);
394 /* Set N and Z flags from var. */
395 static inline void gen_logic_CC(TCGv_i32 var)
397 tcg_gen_mov_i32(cpu_NF, var);
398 tcg_gen_mov_i32(cpu_ZF, var);
401 /* T0 += T1 + CF. */
402 static void gen_adc(TCGv_i32 t0, TCGv_i32 t1)
404 tcg_gen_add_i32(t0, t0, t1);
405 tcg_gen_add_i32(t0, t0, cpu_CF);
408 /* dest = T0 + T1 + CF. */
409 static void gen_add_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
411 tcg_gen_add_i32(dest, t0, t1);
412 tcg_gen_add_i32(dest, dest, cpu_CF);
415 /* dest = T0 - T1 + CF - 1. */
416 static void gen_sub_carry(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
418 tcg_gen_sub_i32(dest, t0, t1);
419 tcg_gen_add_i32(dest, dest, cpu_CF);
420 tcg_gen_subi_i32(dest, dest, 1);
423 /* dest = T0 + T1. Compute C, N, V and Z flags */
424 static void gen_add_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
426 TCGv_i32 tmp = tcg_temp_new_i32();
427 tcg_gen_movi_i32(tmp, 0);
428 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, t1, tmp);
429 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
430 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
431 tcg_gen_xor_i32(tmp, t0, t1);
432 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
433 tcg_temp_free_i32(tmp);
434 tcg_gen_mov_i32(dest, cpu_NF);
437 /* dest = T0 + T1 + CF. Compute C, N, V and Z flags */
438 static void gen_adc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
440 TCGv_i32 tmp = tcg_temp_new_i32();
441 if (TCG_TARGET_HAS_add2_i32) {
442 tcg_gen_movi_i32(tmp, 0);
443 tcg_gen_add2_i32(cpu_NF, cpu_CF, t0, tmp, cpu_CF, tmp);
444 tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1, tmp);
445 } else {
446 TCGv_i64 q0 = tcg_temp_new_i64();
447 TCGv_i64 q1 = tcg_temp_new_i64();
448 tcg_gen_extu_i32_i64(q0, t0);
449 tcg_gen_extu_i32_i64(q1, t1);
450 tcg_gen_add_i64(q0, q0, q1);
451 tcg_gen_extu_i32_i64(q1, cpu_CF);
452 tcg_gen_add_i64(q0, q0, q1);
453 tcg_gen_extr_i64_i32(cpu_NF, cpu_CF, q0);
454 tcg_temp_free_i64(q0);
455 tcg_temp_free_i64(q1);
457 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
458 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
459 tcg_gen_xor_i32(tmp, t0, t1);
460 tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
461 tcg_temp_free_i32(tmp);
462 tcg_gen_mov_i32(dest, cpu_NF);
465 /* dest = T0 - T1. Compute C, N, V and Z flags */
466 static void gen_sub_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
468 TCGv_i32 tmp;
469 tcg_gen_sub_i32(cpu_NF, t0, t1);
470 tcg_gen_mov_i32(cpu_ZF, cpu_NF);
471 tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0, t1);
472 tcg_gen_xor_i32(cpu_VF, cpu_NF, t0);
473 tmp = tcg_temp_new_i32();
474 tcg_gen_xor_i32(tmp, t0, t1);
475 tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
476 tcg_temp_free_i32(tmp);
477 tcg_gen_mov_i32(dest, cpu_NF);
480 /* dest = T0 + ~T1 + CF. Compute C, N, V and Z flags */
481 static void gen_sbc_CC(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
483 TCGv_i32 tmp = tcg_temp_new_i32();
484 tcg_gen_not_i32(tmp, t1);
485 gen_adc_CC(dest, t0, tmp);
486 tcg_temp_free_i32(tmp);
489 #define GEN_SHIFT(name) \
490 static void gen_##name(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1) \
492 TCGv_i32 tmp1, tmp2, tmp3; \
493 tmp1 = tcg_temp_new_i32(); \
494 tcg_gen_andi_i32(tmp1, t1, 0xff); \
495 tmp2 = tcg_const_i32(0); \
496 tmp3 = tcg_const_i32(0x1f); \
497 tcg_gen_movcond_i32(TCG_COND_GTU, tmp2, tmp1, tmp3, tmp2, t0); \
498 tcg_temp_free_i32(tmp3); \
499 tcg_gen_andi_i32(tmp1, tmp1, 0x1f); \
500 tcg_gen_##name##_i32(dest, tmp2, tmp1); \
501 tcg_temp_free_i32(tmp2); \
502 tcg_temp_free_i32(tmp1); \
504 GEN_SHIFT(shl)
505 GEN_SHIFT(shr)
506 #undef GEN_SHIFT
508 static void gen_sar(TCGv_i32 dest, TCGv_i32 t0, TCGv_i32 t1)
510 TCGv_i32 tmp1, tmp2;
511 tmp1 = tcg_temp_new_i32();
512 tcg_gen_andi_i32(tmp1, t1, 0xff);
513 tmp2 = tcg_const_i32(0x1f);
514 tcg_gen_movcond_i32(TCG_COND_GTU, tmp1, tmp1, tmp2, tmp2, tmp1);
515 tcg_temp_free_i32(tmp2);
516 tcg_gen_sar_i32(dest, t0, tmp1);
517 tcg_temp_free_i32(tmp1);
520 static void tcg_gen_abs_i32(TCGv_i32 dest, TCGv_i32 src)
522 TCGv_i32 c0 = tcg_const_i32(0);
523 TCGv_i32 tmp = tcg_temp_new_i32();
524 tcg_gen_neg_i32(tmp, src);
525 tcg_gen_movcond_i32(TCG_COND_GT, dest, src, c0, src, tmp);
526 tcg_temp_free_i32(c0);
527 tcg_temp_free_i32(tmp);
530 static void shifter_out_im(TCGv_i32 var, int shift)
532 if (shift == 0) {
533 tcg_gen_andi_i32(cpu_CF, var, 1);
534 } else {
535 tcg_gen_shri_i32(cpu_CF, var, shift);
536 if (shift != 31) {
537 tcg_gen_andi_i32(cpu_CF, cpu_CF, 1);
542 /* Shift by immediate. Includes special handling for shift == 0. */
543 static inline void gen_arm_shift_im(TCGv_i32 var, int shiftop,
544 int shift, int flags)
546 switch (shiftop) {
547 case 0: /* LSL */
548 if (shift != 0) {
549 if (flags)
550 shifter_out_im(var, 32 - shift);
551 tcg_gen_shli_i32(var, var, shift);
553 break;
554 case 1: /* LSR */
555 if (shift == 0) {
556 if (flags) {
557 tcg_gen_shri_i32(cpu_CF, var, 31);
559 tcg_gen_movi_i32(var, 0);
560 } else {
561 if (flags)
562 shifter_out_im(var, shift - 1);
563 tcg_gen_shri_i32(var, var, shift);
565 break;
566 case 2: /* ASR */
567 if (shift == 0)
568 shift = 32;
569 if (flags)
570 shifter_out_im(var, shift - 1);
571 if (shift == 32)
572 shift = 31;
573 tcg_gen_sari_i32(var, var, shift);
574 break;
575 case 3: /* ROR/RRX */
576 if (shift != 0) {
577 if (flags)
578 shifter_out_im(var, shift - 1);
579 tcg_gen_rotri_i32(var, var, shift); break;
580 } else {
581 TCGv_i32 tmp = tcg_temp_new_i32();
582 tcg_gen_shli_i32(tmp, cpu_CF, 31);
583 if (flags)
584 shifter_out_im(var, 0);
585 tcg_gen_shri_i32(var, var, 1);
586 tcg_gen_or_i32(var, var, tmp);
587 tcg_temp_free_i32(tmp);
592 static inline void gen_arm_shift_reg(TCGv_i32 var, int shiftop,
593 TCGv_i32 shift, int flags)
595 if (flags) {
596 switch (shiftop) {
597 case 0: gen_helper_shl_cc(var, cpu_env, var, shift); break;
598 case 1: gen_helper_shr_cc(var, cpu_env, var, shift); break;
599 case 2: gen_helper_sar_cc(var, cpu_env, var, shift); break;
600 case 3: gen_helper_ror_cc(var, cpu_env, var, shift); break;
602 } else {
603 switch (shiftop) {
604 case 0:
605 gen_shl(var, var, shift);
606 break;
607 case 1:
608 gen_shr(var, var, shift);
609 break;
610 case 2:
611 gen_sar(var, var, shift);
612 break;
613 case 3: tcg_gen_andi_i32(shift, shift, 0x1f);
614 tcg_gen_rotr_i32(var, var, shift); break;
617 tcg_temp_free_i32(shift);
620 #define PAS_OP(pfx) \
621 switch (op2) { \
622 case 0: gen_pas_helper(glue(pfx,add16)); break; \
623 case 1: gen_pas_helper(glue(pfx,addsubx)); break; \
624 case 2: gen_pas_helper(glue(pfx,subaddx)); break; \
625 case 3: gen_pas_helper(glue(pfx,sub16)); break; \
626 case 4: gen_pas_helper(glue(pfx,add8)); break; \
627 case 7: gen_pas_helper(glue(pfx,sub8)); break; \
629 static void gen_arm_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
631 TCGv_ptr tmp;
633 switch (op1) {
634 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
635 case 1:
636 tmp = tcg_temp_new_ptr();
637 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
638 PAS_OP(s)
639 tcg_temp_free_ptr(tmp);
640 break;
641 case 5:
642 tmp = tcg_temp_new_ptr();
643 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
644 PAS_OP(u)
645 tcg_temp_free_ptr(tmp);
646 break;
647 #undef gen_pas_helper
648 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
649 case 2:
650 PAS_OP(q);
651 break;
652 case 3:
653 PAS_OP(sh);
654 break;
655 case 6:
656 PAS_OP(uq);
657 break;
658 case 7:
659 PAS_OP(uh);
660 break;
661 #undef gen_pas_helper
664 #undef PAS_OP
666 /* For unknown reasons Arm and Thumb-2 use arbitrarily different encodings. */
667 #define PAS_OP(pfx) \
668 switch (op1) { \
669 case 0: gen_pas_helper(glue(pfx,add8)); break; \
670 case 1: gen_pas_helper(glue(pfx,add16)); break; \
671 case 2: gen_pas_helper(glue(pfx,addsubx)); break; \
672 case 4: gen_pas_helper(glue(pfx,sub8)); break; \
673 case 5: gen_pas_helper(glue(pfx,sub16)); break; \
674 case 6: gen_pas_helper(glue(pfx,subaddx)); break; \
676 static void gen_thumb2_parallel_addsub(int op1, int op2, TCGv_i32 a, TCGv_i32 b)
678 TCGv_ptr tmp;
680 switch (op2) {
681 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b, tmp)
682 case 0:
683 tmp = tcg_temp_new_ptr();
684 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
685 PAS_OP(s)
686 tcg_temp_free_ptr(tmp);
687 break;
688 case 4:
689 tmp = tcg_temp_new_ptr();
690 tcg_gen_addi_ptr(tmp, cpu_env, offsetof(CPUARMState, GE));
691 PAS_OP(u)
692 tcg_temp_free_ptr(tmp);
693 break;
694 #undef gen_pas_helper
695 #define gen_pas_helper(name) glue(gen_helper_,name)(a, a, b)
696 case 1:
697 PAS_OP(q);
698 break;
699 case 2:
700 PAS_OP(sh);
701 break;
702 case 5:
703 PAS_OP(uq);
704 break;
705 case 6:
706 PAS_OP(uh);
707 break;
708 #undef gen_pas_helper
711 #undef PAS_OP
714 * generate a conditional branch based on ARM condition code cc.
715 * This is common between ARM and Aarch64 targets.
717 void arm_gen_test_cc(int cc, int label)
719 TCGv_i32 tmp;
720 int inv;
722 switch (cc) {
723 case 0: /* eq: Z */
724 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
725 break;
726 case 1: /* ne: !Z */
727 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
728 break;
729 case 2: /* cs: C */
730 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_CF, 0, label);
731 break;
732 case 3: /* cc: !C */
733 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
734 break;
735 case 4: /* mi: N */
736 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_NF, 0, label);
737 break;
738 case 5: /* pl: !N */
739 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_NF, 0, label);
740 break;
741 case 6: /* vs: V */
742 tcg_gen_brcondi_i32(TCG_COND_LT, cpu_VF, 0, label);
743 break;
744 case 7: /* vc: !V */
745 tcg_gen_brcondi_i32(TCG_COND_GE, cpu_VF, 0, label);
746 break;
747 case 8: /* hi: C && !Z */
748 inv = gen_new_label();
749 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, inv);
750 tcg_gen_brcondi_i32(TCG_COND_NE, cpu_ZF, 0, label);
751 gen_set_label(inv);
752 break;
753 case 9: /* ls: !C || Z */
754 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_CF, 0, label);
755 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
756 break;
757 case 10: /* ge: N == V -> N ^ V == 0 */
758 tmp = tcg_temp_new_i32();
759 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
760 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
761 tcg_temp_free_i32(tmp);
762 break;
763 case 11: /* lt: N != V -> N ^ V != 0 */
764 tmp = tcg_temp_new_i32();
765 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
766 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
767 tcg_temp_free_i32(tmp);
768 break;
769 case 12: /* gt: !Z && N == V */
770 inv = gen_new_label();
771 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, inv);
772 tmp = tcg_temp_new_i32();
773 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
774 tcg_gen_brcondi_i32(TCG_COND_GE, tmp, 0, label);
775 tcg_temp_free_i32(tmp);
776 gen_set_label(inv);
777 break;
778 case 13: /* le: Z || N != V */
779 tcg_gen_brcondi_i32(TCG_COND_EQ, cpu_ZF, 0, label);
780 tmp = tcg_temp_new_i32();
781 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
782 tcg_gen_brcondi_i32(TCG_COND_LT, tmp, 0, label);
783 tcg_temp_free_i32(tmp);
784 break;
785 default:
786 fprintf(stderr, "Bad condition code 0x%x\n", cc);
787 abort();
791 static const uint8_t table_logic_cc[16] = {
792 1, /* and */
793 1, /* xor */
794 0, /* sub */
795 0, /* rsb */
796 0, /* add */
797 0, /* adc */
798 0, /* sbc */
799 0, /* rsc */
800 1, /* andl */
801 1, /* xorl */
802 0, /* cmp */
803 0, /* cmn */
804 1, /* orr */
805 1, /* mov */
806 1, /* bic */
807 1, /* mvn */
810 /* Set PC and Thumb state from an immediate address. */
811 static inline void gen_bx_im(DisasContext *s, uint32_t addr)
813 TCGv_i32 tmp;
815 s->is_jmp = DISAS_UPDATE;
816 if (s->thumb != (addr & 1)) {
817 tmp = tcg_temp_new_i32();
818 tcg_gen_movi_i32(tmp, addr & 1);
819 tcg_gen_st_i32(tmp, cpu_env, offsetof(CPUARMState, thumb));
820 tcg_temp_free_i32(tmp);
822 tcg_gen_movi_i32(cpu_R[15], addr & ~1);
825 /* Set PC and Thumb state from var. var is marked as dead. */
826 static inline void gen_bx(DisasContext *s, TCGv_i32 var)
828 s->is_jmp = DISAS_UPDATE;
829 tcg_gen_andi_i32(cpu_R[15], var, ~1);
830 tcg_gen_andi_i32(var, var, 1);
831 store_cpu_field(var, thumb);
834 /* Variant of store_reg which uses branch&exchange logic when storing
835 to r15 in ARM architecture v7 and above. The source must be a temporary
836 and will be marked as dead. */
837 static inline void store_reg_bx(CPUARMState *env, DisasContext *s,
838 int reg, TCGv_i32 var)
840 if (reg == 15 && ENABLE_ARCH_7) {
841 gen_bx(s, var);
842 } else {
843 store_reg(s, reg, var);
847 /* Variant of store_reg which uses branch&exchange logic when storing
848 * to r15 in ARM architecture v5T and above. This is used for storing
849 * the results of a LDR/LDM/POP into r15, and corresponds to the cases
850 * in the ARM ARM which use the LoadWritePC() pseudocode function. */
851 static inline void store_reg_from_load(CPUARMState *env, DisasContext *s,
852 int reg, TCGv_i32 var)
854 if (reg == 15 && ENABLE_ARCH_5) {
855 gen_bx(s, var);
856 } else {
857 store_reg(s, reg, var);
861 /* Abstractions of "generate code to do a guest load/store for
862 * AArch32", where a vaddr is always 32 bits (and is zero
863 * extended if we're a 64 bit core) and data is also
864 * 32 bits unless specifically doing a 64 bit access.
865 * These functions work like tcg_gen_qemu_{ld,st}* except
866 * that the address argument is TCGv_i32 rather than TCGv.
868 #if TARGET_LONG_BITS == 32
870 #define DO_GEN_LD(SUFF, OPC) \
871 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
873 tcg_gen_qemu_ld_i32(val, addr, index, OPC); \
876 #define DO_GEN_ST(SUFF, OPC) \
877 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
879 tcg_gen_qemu_st_i32(val, addr, index, OPC); \
882 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
884 tcg_gen_qemu_ld_i64(val, addr, index, MO_TEQ);
887 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
889 tcg_gen_qemu_st_i64(val, addr, index, MO_TEQ);
892 #else
894 #define DO_GEN_LD(SUFF, OPC) \
895 static inline void gen_aa32_ld##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
897 TCGv addr64 = tcg_temp_new(); \
898 tcg_gen_extu_i32_i64(addr64, addr); \
899 tcg_gen_qemu_ld_i32(val, addr64, index, OPC); \
900 tcg_temp_free(addr64); \
903 #define DO_GEN_ST(SUFF, OPC) \
904 static inline void gen_aa32_st##SUFF(TCGv_i32 val, TCGv_i32 addr, int index) \
906 TCGv addr64 = tcg_temp_new(); \
907 tcg_gen_extu_i32_i64(addr64, addr); \
908 tcg_gen_qemu_st_i32(val, addr64, index, OPC); \
909 tcg_temp_free(addr64); \
912 static inline void gen_aa32_ld64(TCGv_i64 val, TCGv_i32 addr, int index)
914 TCGv addr64 = tcg_temp_new();
915 tcg_gen_extu_i32_i64(addr64, addr);
916 tcg_gen_qemu_ld_i64(val, addr64, index, MO_TEQ);
917 tcg_temp_free(addr64);
920 static inline void gen_aa32_st64(TCGv_i64 val, TCGv_i32 addr, int index)
922 TCGv addr64 = tcg_temp_new();
923 tcg_gen_extu_i32_i64(addr64, addr);
924 tcg_gen_qemu_st_i64(val, addr64, index, MO_TEQ);
925 tcg_temp_free(addr64);
928 #endif
930 DO_GEN_LD(8s, MO_SB)
931 DO_GEN_LD(8u, MO_UB)
932 DO_GEN_LD(16s, MO_TESW)
933 DO_GEN_LD(16u, MO_TEUW)
934 DO_GEN_LD(32u, MO_TEUL)
935 DO_GEN_ST(8, MO_UB)
936 DO_GEN_ST(16, MO_TEUW)
937 DO_GEN_ST(32, MO_TEUL)
939 static inline void gen_set_pc_im(DisasContext *s, target_ulong val)
941 tcg_gen_movi_i32(cpu_R[15], val);
944 static inline void
945 gen_set_condexec (DisasContext *s)
947 if (s->condexec_mask) {
948 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
949 TCGv_i32 tmp = tcg_temp_new_i32();
950 tcg_gen_movi_i32(tmp, val);
951 store_cpu_field(tmp, condexec_bits);
955 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
957 gen_set_condexec(s);
958 gen_set_pc_im(s, s->pc - offset);
959 gen_exception_internal(excp);
960 s->is_jmp = DISAS_JUMP;
963 static void gen_exception_insn(DisasContext *s, int offset, int excp, int syn)
965 gen_set_condexec(s);
966 gen_set_pc_im(s, s->pc - offset);
967 gen_exception(excp, syn);
968 s->is_jmp = DISAS_JUMP;
971 /* Force a TB lookup after an instruction that changes the CPU state. */
972 static inline void gen_lookup_tb(DisasContext *s)
974 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
975 s->is_jmp = DISAS_UPDATE;
978 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
979 TCGv_i32 var)
981 int val, rm, shift, shiftop;
982 TCGv_i32 offset;
984 if (!(insn & (1 << 25))) {
985 /* immediate */
986 val = insn & 0xfff;
987 if (!(insn & (1 << 23)))
988 val = -val;
989 if (val != 0)
990 tcg_gen_addi_i32(var, var, val);
991 } else {
992 /* shift/register */
993 rm = (insn) & 0xf;
994 shift = (insn >> 7) & 0x1f;
995 shiftop = (insn >> 5) & 3;
996 offset = load_reg(s, rm);
997 gen_arm_shift_im(offset, shiftop, shift, 0);
998 if (!(insn & (1 << 23)))
999 tcg_gen_sub_i32(var, var, offset);
1000 else
1001 tcg_gen_add_i32(var, var, offset);
1002 tcg_temp_free_i32(offset);
1006 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
1007 int extra, TCGv_i32 var)
1009 int val, rm;
1010 TCGv_i32 offset;
1012 if (insn & (1 << 22)) {
1013 /* immediate */
1014 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1015 if (!(insn & (1 << 23)))
1016 val = -val;
1017 val += extra;
1018 if (val != 0)
1019 tcg_gen_addi_i32(var, var, val);
1020 } else {
1021 /* register */
1022 if (extra)
1023 tcg_gen_addi_i32(var, var, extra);
1024 rm = (insn) & 0xf;
1025 offset = load_reg(s, rm);
1026 if (!(insn & (1 << 23)))
1027 tcg_gen_sub_i32(var, var, offset);
1028 else
1029 tcg_gen_add_i32(var, var, offset);
1030 tcg_temp_free_i32(offset);
1034 static TCGv_ptr get_fpstatus_ptr(int neon)
1036 TCGv_ptr statusptr = tcg_temp_new_ptr();
1037 int offset;
1038 if (neon) {
1039 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1040 } else {
1041 offset = offsetof(CPUARMState, vfp.fp_status);
1043 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1044 return statusptr;
1047 #define VFP_OP2(name) \
1048 static inline void gen_vfp_##name(int dp) \
1050 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1051 if (dp) { \
1052 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1053 } else { \
1054 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1056 tcg_temp_free_ptr(fpst); \
1059 VFP_OP2(add)
1060 VFP_OP2(sub)
1061 VFP_OP2(mul)
1062 VFP_OP2(div)
1064 #undef VFP_OP2
1066 static inline void gen_vfp_F1_mul(int dp)
1068 /* Like gen_vfp_mul() but put result in F1 */
1069 TCGv_ptr fpst = get_fpstatus_ptr(0);
1070 if (dp) {
1071 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1072 } else {
1073 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1075 tcg_temp_free_ptr(fpst);
1078 static inline void gen_vfp_F1_neg(int dp)
1080 /* Like gen_vfp_neg() but put result in F1 */
1081 if (dp) {
1082 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1083 } else {
1084 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1088 static inline void gen_vfp_abs(int dp)
1090 if (dp)
1091 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1092 else
1093 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1096 static inline void gen_vfp_neg(int dp)
1098 if (dp)
1099 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1100 else
1101 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1104 static inline void gen_vfp_sqrt(int dp)
1106 if (dp)
1107 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1108 else
1109 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1112 static inline void gen_vfp_cmp(int dp)
1114 if (dp)
1115 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1116 else
1117 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1120 static inline void gen_vfp_cmpe(int dp)
1122 if (dp)
1123 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1124 else
1125 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1128 static inline void gen_vfp_F1_ld0(int dp)
1130 if (dp)
1131 tcg_gen_movi_i64(cpu_F1d, 0);
1132 else
1133 tcg_gen_movi_i32(cpu_F1s, 0);
1136 #define VFP_GEN_ITOF(name) \
1137 static inline void gen_vfp_##name(int dp, int neon) \
1139 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1140 if (dp) { \
1141 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1142 } else { \
1143 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1145 tcg_temp_free_ptr(statusptr); \
1148 VFP_GEN_ITOF(uito)
1149 VFP_GEN_ITOF(sito)
1150 #undef VFP_GEN_ITOF
1152 #define VFP_GEN_FTOI(name) \
1153 static inline void gen_vfp_##name(int dp, int neon) \
1155 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1156 if (dp) { \
1157 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1158 } else { \
1159 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1161 tcg_temp_free_ptr(statusptr); \
1164 VFP_GEN_FTOI(toui)
1165 VFP_GEN_FTOI(touiz)
1166 VFP_GEN_FTOI(tosi)
1167 VFP_GEN_FTOI(tosiz)
1168 #undef VFP_GEN_FTOI
1170 #define VFP_GEN_FIX(name, round) \
1171 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1173 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1174 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1175 if (dp) { \
1176 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1177 statusptr); \
1178 } else { \
1179 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1180 statusptr); \
1182 tcg_temp_free_i32(tmp_shift); \
1183 tcg_temp_free_ptr(statusptr); \
1185 VFP_GEN_FIX(tosh, _round_to_zero)
1186 VFP_GEN_FIX(tosl, _round_to_zero)
1187 VFP_GEN_FIX(touh, _round_to_zero)
1188 VFP_GEN_FIX(toul, _round_to_zero)
1189 VFP_GEN_FIX(shto, )
1190 VFP_GEN_FIX(slto, )
1191 VFP_GEN_FIX(uhto, )
1192 VFP_GEN_FIX(ulto, )
1193 #undef VFP_GEN_FIX
1195 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1197 if (dp) {
1198 gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
1199 } else {
1200 gen_aa32_ld32u(cpu_F0s, addr, get_mem_index(s));
1204 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1206 if (dp) {
1207 gen_aa32_st64(cpu_F0d, addr, get_mem_index(s));
1208 } else {
1209 gen_aa32_st32(cpu_F0s, addr, get_mem_index(s));
1213 static inline long
1214 vfp_reg_offset (int dp, int reg)
1216 if (dp)
1217 return offsetof(CPUARMState, vfp.regs[reg]);
1218 else if (reg & 1) {
1219 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1220 + offsetof(CPU_DoubleU, l.upper);
1221 } else {
1222 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1223 + offsetof(CPU_DoubleU, l.lower);
1227 /* Return the offset of a 32-bit piece of a NEON register.
1228 zero is the least significant end of the register. */
1229 static inline long
1230 neon_reg_offset (int reg, int n)
1232 int sreg;
1233 sreg = reg * 2 + n;
1234 return vfp_reg_offset(0, sreg);
1237 static TCGv_i32 neon_load_reg(int reg, int pass)
1239 TCGv_i32 tmp = tcg_temp_new_i32();
1240 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1241 return tmp;
1244 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1246 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1247 tcg_temp_free_i32(var);
1250 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1252 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1255 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1257 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1260 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1261 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1262 #define tcg_gen_st_f32 tcg_gen_st_i32
1263 #define tcg_gen_st_f64 tcg_gen_st_i64
1265 static inline void gen_mov_F0_vreg(int dp, int reg)
1267 if (dp)
1268 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1269 else
1270 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1273 static inline void gen_mov_F1_vreg(int dp, int reg)
1275 if (dp)
1276 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1277 else
1278 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1281 static inline void gen_mov_vreg_F0(int dp, int reg)
1283 if (dp)
1284 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1285 else
1286 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1289 #define ARM_CP_RW_BIT (1 << 20)
1291 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1293 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1296 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1298 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1301 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1303 TCGv_i32 var = tcg_temp_new_i32();
1304 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1305 return var;
1308 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1310 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1311 tcg_temp_free_i32(var);
1314 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1316 iwmmxt_store_reg(cpu_M0, rn);
1319 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1321 iwmmxt_load_reg(cpu_M0, rn);
1324 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1326 iwmmxt_load_reg(cpu_V1, rn);
1327 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1330 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1332 iwmmxt_load_reg(cpu_V1, rn);
1333 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1336 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1338 iwmmxt_load_reg(cpu_V1, rn);
1339 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1342 #define IWMMXT_OP(name) \
1343 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1345 iwmmxt_load_reg(cpu_V1, rn); \
1346 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1349 #define IWMMXT_OP_ENV(name) \
1350 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1352 iwmmxt_load_reg(cpu_V1, rn); \
1353 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1356 #define IWMMXT_OP_ENV_SIZE(name) \
1357 IWMMXT_OP_ENV(name##b) \
1358 IWMMXT_OP_ENV(name##w) \
1359 IWMMXT_OP_ENV(name##l)
1361 #define IWMMXT_OP_ENV1(name) \
1362 static inline void gen_op_iwmmxt_##name##_M0(void) \
1364 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1367 IWMMXT_OP(maddsq)
1368 IWMMXT_OP(madduq)
1369 IWMMXT_OP(sadb)
1370 IWMMXT_OP(sadw)
1371 IWMMXT_OP(mulslw)
1372 IWMMXT_OP(mulshw)
1373 IWMMXT_OP(mululw)
1374 IWMMXT_OP(muluhw)
1375 IWMMXT_OP(macsw)
1376 IWMMXT_OP(macuw)
1378 IWMMXT_OP_ENV_SIZE(unpackl)
1379 IWMMXT_OP_ENV_SIZE(unpackh)
1381 IWMMXT_OP_ENV1(unpacklub)
1382 IWMMXT_OP_ENV1(unpackluw)
1383 IWMMXT_OP_ENV1(unpacklul)
1384 IWMMXT_OP_ENV1(unpackhub)
1385 IWMMXT_OP_ENV1(unpackhuw)
1386 IWMMXT_OP_ENV1(unpackhul)
1387 IWMMXT_OP_ENV1(unpacklsb)
1388 IWMMXT_OP_ENV1(unpacklsw)
1389 IWMMXT_OP_ENV1(unpacklsl)
1390 IWMMXT_OP_ENV1(unpackhsb)
1391 IWMMXT_OP_ENV1(unpackhsw)
1392 IWMMXT_OP_ENV1(unpackhsl)
1394 IWMMXT_OP_ENV_SIZE(cmpeq)
1395 IWMMXT_OP_ENV_SIZE(cmpgtu)
1396 IWMMXT_OP_ENV_SIZE(cmpgts)
1398 IWMMXT_OP_ENV_SIZE(mins)
1399 IWMMXT_OP_ENV_SIZE(minu)
1400 IWMMXT_OP_ENV_SIZE(maxs)
1401 IWMMXT_OP_ENV_SIZE(maxu)
1403 IWMMXT_OP_ENV_SIZE(subn)
1404 IWMMXT_OP_ENV_SIZE(addn)
1405 IWMMXT_OP_ENV_SIZE(subu)
1406 IWMMXT_OP_ENV_SIZE(addu)
1407 IWMMXT_OP_ENV_SIZE(subs)
1408 IWMMXT_OP_ENV_SIZE(adds)
1410 IWMMXT_OP_ENV(avgb0)
1411 IWMMXT_OP_ENV(avgb1)
1412 IWMMXT_OP_ENV(avgw0)
1413 IWMMXT_OP_ENV(avgw1)
1415 IWMMXT_OP_ENV(packuw)
1416 IWMMXT_OP_ENV(packul)
1417 IWMMXT_OP_ENV(packuq)
1418 IWMMXT_OP_ENV(packsw)
1419 IWMMXT_OP_ENV(packsl)
1420 IWMMXT_OP_ENV(packsq)
1422 static void gen_op_iwmmxt_set_mup(void)
1424 TCGv_i32 tmp;
1425 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1426 tcg_gen_ori_i32(tmp, tmp, 2);
1427 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1430 static void gen_op_iwmmxt_set_cup(void)
1432 TCGv_i32 tmp;
1433 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1434 tcg_gen_ori_i32(tmp, tmp, 1);
1435 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1438 static void gen_op_iwmmxt_setpsr_nz(void)
1440 TCGv_i32 tmp = tcg_temp_new_i32();
1441 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1442 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1445 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1447 iwmmxt_load_reg(cpu_V1, rn);
1448 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1449 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1452 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1453 TCGv_i32 dest)
1455 int rd;
1456 uint32_t offset;
1457 TCGv_i32 tmp;
1459 rd = (insn >> 16) & 0xf;
1460 tmp = load_reg(s, rd);
1462 offset = (insn & 0xff) << ((insn >> 7) & 2);
1463 if (insn & (1 << 24)) {
1464 /* Pre indexed */
1465 if (insn & (1 << 23))
1466 tcg_gen_addi_i32(tmp, tmp, offset);
1467 else
1468 tcg_gen_addi_i32(tmp, tmp, -offset);
1469 tcg_gen_mov_i32(dest, tmp);
1470 if (insn & (1 << 21))
1471 store_reg(s, rd, tmp);
1472 else
1473 tcg_temp_free_i32(tmp);
1474 } else if (insn & (1 << 21)) {
1475 /* Post indexed */
1476 tcg_gen_mov_i32(dest, tmp);
1477 if (insn & (1 << 23))
1478 tcg_gen_addi_i32(tmp, tmp, offset);
1479 else
1480 tcg_gen_addi_i32(tmp, tmp, -offset);
1481 store_reg(s, rd, tmp);
1482 } else if (!(insn & (1 << 23)))
1483 return 1;
1484 return 0;
1487 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1489 int rd = (insn >> 0) & 0xf;
1490 TCGv_i32 tmp;
1492 if (insn & (1 << 8)) {
1493 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1494 return 1;
1495 } else {
1496 tmp = iwmmxt_load_creg(rd);
1498 } else {
1499 tmp = tcg_temp_new_i32();
1500 iwmmxt_load_reg(cpu_V0, rd);
1501 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1503 tcg_gen_andi_i32(tmp, tmp, mask);
1504 tcg_gen_mov_i32(dest, tmp);
1505 tcg_temp_free_i32(tmp);
1506 return 0;
1509 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1510 (ie. an undefined instruction). */
1511 static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
1513 int rd, wrd;
1514 int rdhi, rdlo, rd0, rd1, i;
1515 TCGv_i32 addr;
1516 TCGv_i32 tmp, tmp2, tmp3;
1518 if ((insn & 0x0e000e00) == 0x0c000000) {
1519 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1520 wrd = insn & 0xf;
1521 rdlo = (insn >> 12) & 0xf;
1522 rdhi = (insn >> 16) & 0xf;
1523 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1524 iwmmxt_load_reg(cpu_V0, wrd);
1525 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1526 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1527 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1528 } else { /* TMCRR */
1529 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1530 iwmmxt_store_reg(cpu_V0, wrd);
1531 gen_op_iwmmxt_set_mup();
1533 return 0;
1536 wrd = (insn >> 12) & 0xf;
1537 addr = tcg_temp_new_i32();
1538 if (gen_iwmmxt_address(s, insn, addr)) {
1539 tcg_temp_free_i32(addr);
1540 return 1;
1542 if (insn & ARM_CP_RW_BIT) {
1543 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1544 tmp = tcg_temp_new_i32();
1545 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
1546 iwmmxt_store_creg(wrd, tmp);
1547 } else {
1548 i = 1;
1549 if (insn & (1 << 8)) {
1550 if (insn & (1 << 22)) { /* WLDRD */
1551 gen_aa32_ld64(cpu_M0, addr, get_mem_index(s));
1552 i = 0;
1553 } else { /* WLDRW wRd */
1554 tmp = tcg_temp_new_i32();
1555 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
1557 } else {
1558 tmp = tcg_temp_new_i32();
1559 if (insn & (1 << 22)) { /* WLDRH */
1560 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
1561 } else { /* WLDRB */
1562 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
1565 if (i) {
1566 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1567 tcg_temp_free_i32(tmp);
1569 gen_op_iwmmxt_movq_wRn_M0(wrd);
1571 } else {
1572 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1573 tmp = iwmmxt_load_creg(wrd);
1574 gen_aa32_st32(tmp, addr, get_mem_index(s));
1575 } else {
1576 gen_op_iwmmxt_movq_M0_wRn(wrd);
1577 tmp = tcg_temp_new_i32();
1578 if (insn & (1 << 8)) {
1579 if (insn & (1 << 22)) { /* WSTRD */
1580 gen_aa32_st64(cpu_M0, addr, get_mem_index(s));
1581 } else { /* WSTRW wRd */
1582 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1583 gen_aa32_st32(tmp, addr, get_mem_index(s));
1585 } else {
1586 if (insn & (1 << 22)) { /* WSTRH */
1587 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1588 gen_aa32_st16(tmp, addr, get_mem_index(s));
1589 } else { /* WSTRB */
1590 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1591 gen_aa32_st8(tmp, addr, get_mem_index(s));
1595 tcg_temp_free_i32(tmp);
1597 tcg_temp_free_i32(addr);
1598 return 0;
1601 if ((insn & 0x0f000000) != 0x0e000000)
1602 return 1;
1604 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1605 case 0x000: /* WOR */
1606 wrd = (insn >> 12) & 0xf;
1607 rd0 = (insn >> 0) & 0xf;
1608 rd1 = (insn >> 16) & 0xf;
1609 gen_op_iwmmxt_movq_M0_wRn(rd0);
1610 gen_op_iwmmxt_orq_M0_wRn(rd1);
1611 gen_op_iwmmxt_setpsr_nz();
1612 gen_op_iwmmxt_movq_wRn_M0(wrd);
1613 gen_op_iwmmxt_set_mup();
1614 gen_op_iwmmxt_set_cup();
1615 break;
1616 case 0x011: /* TMCR */
1617 if (insn & 0xf)
1618 return 1;
1619 rd = (insn >> 12) & 0xf;
1620 wrd = (insn >> 16) & 0xf;
1621 switch (wrd) {
1622 case ARM_IWMMXT_wCID:
1623 case ARM_IWMMXT_wCASF:
1624 break;
1625 case ARM_IWMMXT_wCon:
1626 gen_op_iwmmxt_set_cup();
1627 /* Fall through. */
1628 case ARM_IWMMXT_wCSSF:
1629 tmp = iwmmxt_load_creg(wrd);
1630 tmp2 = load_reg(s, rd);
1631 tcg_gen_andc_i32(tmp, tmp, tmp2);
1632 tcg_temp_free_i32(tmp2);
1633 iwmmxt_store_creg(wrd, tmp);
1634 break;
1635 case ARM_IWMMXT_wCGR0:
1636 case ARM_IWMMXT_wCGR1:
1637 case ARM_IWMMXT_wCGR2:
1638 case ARM_IWMMXT_wCGR3:
1639 gen_op_iwmmxt_set_cup();
1640 tmp = load_reg(s, rd);
1641 iwmmxt_store_creg(wrd, tmp);
1642 break;
1643 default:
1644 return 1;
1646 break;
1647 case 0x100: /* WXOR */
1648 wrd = (insn >> 12) & 0xf;
1649 rd0 = (insn >> 0) & 0xf;
1650 rd1 = (insn >> 16) & 0xf;
1651 gen_op_iwmmxt_movq_M0_wRn(rd0);
1652 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1653 gen_op_iwmmxt_setpsr_nz();
1654 gen_op_iwmmxt_movq_wRn_M0(wrd);
1655 gen_op_iwmmxt_set_mup();
1656 gen_op_iwmmxt_set_cup();
1657 break;
1658 case 0x111: /* TMRC */
1659 if (insn & 0xf)
1660 return 1;
1661 rd = (insn >> 12) & 0xf;
1662 wrd = (insn >> 16) & 0xf;
1663 tmp = iwmmxt_load_creg(wrd);
1664 store_reg(s, rd, tmp);
1665 break;
1666 case 0x300: /* WANDN */
1667 wrd = (insn >> 12) & 0xf;
1668 rd0 = (insn >> 0) & 0xf;
1669 rd1 = (insn >> 16) & 0xf;
1670 gen_op_iwmmxt_movq_M0_wRn(rd0);
1671 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1672 gen_op_iwmmxt_andq_M0_wRn(rd1);
1673 gen_op_iwmmxt_setpsr_nz();
1674 gen_op_iwmmxt_movq_wRn_M0(wrd);
1675 gen_op_iwmmxt_set_mup();
1676 gen_op_iwmmxt_set_cup();
1677 break;
1678 case 0x200: /* WAND */
1679 wrd = (insn >> 12) & 0xf;
1680 rd0 = (insn >> 0) & 0xf;
1681 rd1 = (insn >> 16) & 0xf;
1682 gen_op_iwmmxt_movq_M0_wRn(rd0);
1683 gen_op_iwmmxt_andq_M0_wRn(rd1);
1684 gen_op_iwmmxt_setpsr_nz();
1685 gen_op_iwmmxt_movq_wRn_M0(wrd);
1686 gen_op_iwmmxt_set_mup();
1687 gen_op_iwmmxt_set_cup();
1688 break;
1689 case 0x810: case 0xa10: /* WMADD */
1690 wrd = (insn >> 12) & 0xf;
1691 rd0 = (insn >> 0) & 0xf;
1692 rd1 = (insn >> 16) & 0xf;
1693 gen_op_iwmmxt_movq_M0_wRn(rd0);
1694 if (insn & (1 << 21))
1695 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1696 else
1697 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1698 gen_op_iwmmxt_movq_wRn_M0(wrd);
1699 gen_op_iwmmxt_set_mup();
1700 break;
1701 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1702 wrd = (insn >> 12) & 0xf;
1703 rd0 = (insn >> 16) & 0xf;
1704 rd1 = (insn >> 0) & 0xf;
1705 gen_op_iwmmxt_movq_M0_wRn(rd0);
1706 switch ((insn >> 22) & 3) {
1707 case 0:
1708 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1709 break;
1710 case 1:
1711 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1712 break;
1713 case 2:
1714 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1715 break;
1716 case 3:
1717 return 1;
1719 gen_op_iwmmxt_movq_wRn_M0(wrd);
1720 gen_op_iwmmxt_set_mup();
1721 gen_op_iwmmxt_set_cup();
1722 break;
1723 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1724 wrd = (insn >> 12) & 0xf;
1725 rd0 = (insn >> 16) & 0xf;
1726 rd1 = (insn >> 0) & 0xf;
1727 gen_op_iwmmxt_movq_M0_wRn(rd0);
1728 switch ((insn >> 22) & 3) {
1729 case 0:
1730 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1731 break;
1732 case 1:
1733 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1734 break;
1735 case 2:
1736 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1737 break;
1738 case 3:
1739 return 1;
1741 gen_op_iwmmxt_movq_wRn_M0(wrd);
1742 gen_op_iwmmxt_set_mup();
1743 gen_op_iwmmxt_set_cup();
1744 break;
1745 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
1746 wrd = (insn >> 12) & 0xf;
1747 rd0 = (insn >> 16) & 0xf;
1748 rd1 = (insn >> 0) & 0xf;
1749 gen_op_iwmmxt_movq_M0_wRn(rd0);
1750 if (insn & (1 << 22))
1751 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1752 else
1753 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1754 if (!(insn & (1 << 20)))
1755 gen_op_iwmmxt_addl_M0_wRn(wrd);
1756 gen_op_iwmmxt_movq_wRn_M0(wrd);
1757 gen_op_iwmmxt_set_mup();
1758 break;
1759 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1760 wrd = (insn >> 12) & 0xf;
1761 rd0 = (insn >> 16) & 0xf;
1762 rd1 = (insn >> 0) & 0xf;
1763 gen_op_iwmmxt_movq_M0_wRn(rd0);
1764 if (insn & (1 << 21)) {
1765 if (insn & (1 << 20))
1766 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1767 else
1768 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1769 } else {
1770 if (insn & (1 << 20))
1771 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1772 else
1773 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1775 gen_op_iwmmxt_movq_wRn_M0(wrd);
1776 gen_op_iwmmxt_set_mup();
1777 break;
1778 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1779 wrd = (insn >> 12) & 0xf;
1780 rd0 = (insn >> 16) & 0xf;
1781 rd1 = (insn >> 0) & 0xf;
1782 gen_op_iwmmxt_movq_M0_wRn(rd0);
1783 if (insn & (1 << 21))
1784 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1785 else
1786 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1787 if (!(insn & (1 << 20))) {
1788 iwmmxt_load_reg(cpu_V1, wrd);
1789 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1791 gen_op_iwmmxt_movq_wRn_M0(wrd);
1792 gen_op_iwmmxt_set_mup();
1793 break;
1794 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1795 wrd = (insn >> 12) & 0xf;
1796 rd0 = (insn >> 16) & 0xf;
1797 rd1 = (insn >> 0) & 0xf;
1798 gen_op_iwmmxt_movq_M0_wRn(rd0);
1799 switch ((insn >> 22) & 3) {
1800 case 0:
1801 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1802 break;
1803 case 1:
1804 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1805 break;
1806 case 2:
1807 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1808 break;
1809 case 3:
1810 return 1;
1812 gen_op_iwmmxt_movq_wRn_M0(wrd);
1813 gen_op_iwmmxt_set_mup();
1814 gen_op_iwmmxt_set_cup();
1815 break;
1816 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1817 wrd = (insn >> 12) & 0xf;
1818 rd0 = (insn >> 16) & 0xf;
1819 rd1 = (insn >> 0) & 0xf;
1820 gen_op_iwmmxt_movq_M0_wRn(rd0);
1821 if (insn & (1 << 22)) {
1822 if (insn & (1 << 20))
1823 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1824 else
1825 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1826 } else {
1827 if (insn & (1 << 20))
1828 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1829 else
1830 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1832 gen_op_iwmmxt_movq_wRn_M0(wrd);
1833 gen_op_iwmmxt_set_mup();
1834 gen_op_iwmmxt_set_cup();
1835 break;
1836 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1837 wrd = (insn >> 12) & 0xf;
1838 rd0 = (insn >> 16) & 0xf;
1839 rd1 = (insn >> 0) & 0xf;
1840 gen_op_iwmmxt_movq_M0_wRn(rd0);
1841 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1842 tcg_gen_andi_i32(tmp, tmp, 7);
1843 iwmmxt_load_reg(cpu_V1, rd1);
1844 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1845 tcg_temp_free_i32(tmp);
1846 gen_op_iwmmxt_movq_wRn_M0(wrd);
1847 gen_op_iwmmxt_set_mup();
1848 break;
1849 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1850 if (((insn >> 6) & 3) == 3)
1851 return 1;
1852 rd = (insn >> 12) & 0xf;
1853 wrd = (insn >> 16) & 0xf;
1854 tmp = load_reg(s, rd);
1855 gen_op_iwmmxt_movq_M0_wRn(wrd);
1856 switch ((insn >> 6) & 3) {
1857 case 0:
1858 tmp2 = tcg_const_i32(0xff);
1859 tmp3 = tcg_const_i32((insn & 7) << 3);
1860 break;
1861 case 1:
1862 tmp2 = tcg_const_i32(0xffff);
1863 tmp3 = tcg_const_i32((insn & 3) << 4);
1864 break;
1865 case 2:
1866 tmp2 = tcg_const_i32(0xffffffff);
1867 tmp3 = tcg_const_i32((insn & 1) << 5);
1868 break;
1869 default:
1870 TCGV_UNUSED_I32(tmp2);
1871 TCGV_UNUSED_I32(tmp3);
1873 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1874 tcg_temp_free_i32(tmp3);
1875 tcg_temp_free_i32(tmp2);
1876 tcg_temp_free_i32(tmp);
1877 gen_op_iwmmxt_movq_wRn_M0(wrd);
1878 gen_op_iwmmxt_set_mup();
1879 break;
1880 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1881 rd = (insn >> 12) & 0xf;
1882 wrd = (insn >> 16) & 0xf;
1883 if (rd == 15 || ((insn >> 22) & 3) == 3)
1884 return 1;
1885 gen_op_iwmmxt_movq_M0_wRn(wrd);
1886 tmp = tcg_temp_new_i32();
1887 switch ((insn >> 22) & 3) {
1888 case 0:
1889 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1890 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1891 if (insn & 8) {
1892 tcg_gen_ext8s_i32(tmp, tmp);
1893 } else {
1894 tcg_gen_andi_i32(tmp, tmp, 0xff);
1896 break;
1897 case 1:
1898 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1899 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1900 if (insn & 8) {
1901 tcg_gen_ext16s_i32(tmp, tmp);
1902 } else {
1903 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1905 break;
1906 case 2:
1907 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1908 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1909 break;
1911 store_reg(s, rd, tmp);
1912 break;
1913 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1914 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1915 return 1;
1916 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1917 switch ((insn >> 22) & 3) {
1918 case 0:
1919 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1920 break;
1921 case 1:
1922 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1923 break;
1924 case 2:
1925 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1926 break;
1928 tcg_gen_shli_i32(tmp, tmp, 28);
1929 gen_set_nzcv(tmp);
1930 tcg_temp_free_i32(tmp);
1931 break;
1932 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1933 if (((insn >> 6) & 3) == 3)
1934 return 1;
1935 rd = (insn >> 12) & 0xf;
1936 wrd = (insn >> 16) & 0xf;
1937 tmp = load_reg(s, rd);
1938 switch ((insn >> 6) & 3) {
1939 case 0:
1940 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1941 break;
1942 case 1:
1943 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1944 break;
1945 case 2:
1946 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1947 break;
1949 tcg_temp_free_i32(tmp);
1950 gen_op_iwmmxt_movq_wRn_M0(wrd);
1951 gen_op_iwmmxt_set_mup();
1952 break;
1953 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1954 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1955 return 1;
1956 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1957 tmp2 = tcg_temp_new_i32();
1958 tcg_gen_mov_i32(tmp2, tmp);
1959 switch ((insn >> 22) & 3) {
1960 case 0:
1961 for (i = 0; i < 7; i ++) {
1962 tcg_gen_shli_i32(tmp2, tmp2, 4);
1963 tcg_gen_and_i32(tmp, tmp, tmp2);
1965 break;
1966 case 1:
1967 for (i = 0; i < 3; i ++) {
1968 tcg_gen_shli_i32(tmp2, tmp2, 8);
1969 tcg_gen_and_i32(tmp, tmp, tmp2);
1971 break;
1972 case 2:
1973 tcg_gen_shli_i32(tmp2, tmp2, 16);
1974 tcg_gen_and_i32(tmp, tmp, tmp2);
1975 break;
1977 gen_set_nzcv(tmp);
1978 tcg_temp_free_i32(tmp2);
1979 tcg_temp_free_i32(tmp);
1980 break;
1981 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
1982 wrd = (insn >> 12) & 0xf;
1983 rd0 = (insn >> 16) & 0xf;
1984 gen_op_iwmmxt_movq_M0_wRn(rd0);
1985 switch ((insn >> 22) & 3) {
1986 case 0:
1987 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
1988 break;
1989 case 1:
1990 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
1991 break;
1992 case 2:
1993 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
1994 break;
1995 case 3:
1996 return 1;
1998 gen_op_iwmmxt_movq_wRn_M0(wrd);
1999 gen_op_iwmmxt_set_mup();
2000 break;
2001 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
2002 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2003 return 1;
2004 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2005 tmp2 = tcg_temp_new_i32();
2006 tcg_gen_mov_i32(tmp2, tmp);
2007 switch ((insn >> 22) & 3) {
2008 case 0:
2009 for (i = 0; i < 7; i ++) {
2010 tcg_gen_shli_i32(tmp2, tmp2, 4);
2011 tcg_gen_or_i32(tmp, tmp, tmp2);
2013 break;
2014 case 1:
2015 for (i = 0; i < 3; i ++) {
2016 tcg_gen_shli_i32(tmp2, tmp2, 8);
2017 tcg_gen_or_i32(tmp, tmp, tmp2);
2019 break;
2020 case 2:
2021 tcg_gen_shli_i32(tmp2, tmp2, 16);
2022 tcg_gen_or_i32(tmp, tmp, tmp2);
2023 break;
2025 gen_set_nzcv(tmp);
2026 tcg_temp_free_i32(tmp2);
2027 tcg_temp_free_i32(tmp);
2028 break;
2029 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2030 rd = (insn >> 12) & 0xf;
2031 rd0 = (insn >> 16) & 0xf;
2032 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2033 return 1;
2034 gen_op_iwmmxt_movq_M0_wRn(rd0);
2035 tmp = tcg_temp_new_i32();
2036 switch ((insn >> 22) & 3) {
2037 case 0:
2038 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2039 break;
2040 case 1:
2041 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2042 break;
2043 case 2:
2044 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2045 break;
2047 store_reg(s, rd, tmp);
2048 break;
2049 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2050 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2051 wrd = (insn >> 12) & 0xf;
2052 rd0 = (insn >> 16) & 0xf;
2053 rd1 = (insn >> 0) & 0xf;
2054 gen_op_iwmmxt_movq_M0_wRn(rd0);
2055 switch ((insn >> 22) & 3) {
2056 case 0:
2057 if (insn & (1 << 21))
2058 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2059 else
2060 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2061 break;
2062 case 1:
2063 if (insn & (1 << 21))
2064 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2065 else
2066 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2067 break;
2068 case 2:
2069 if (insn & (1 << 21))
2070 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2071 else
2072 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2073 break;
2074 case 3:
2075 return 1;
2077 gen_op_iwmmxt_movq_wRn_M0(wrd);
2078 gen_op_iwmmxt_set_mup();
2079 gen_op_iwmmxt_set_cup();
2080 break;
2081 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2082 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2083 wrd = (insn >> 12) & 0xf;
2084 rd0 = (insn >> 16) & 0xf;
2085 gen_op_iwmmxt_movq_M0_wRn(rd0);
2086 switch ((insn >> 22) & 3) {
2087 case 0:
2088 if (insn & (1 << 21))
2089 gen_op_iwmmxt_unpacklsb_M0();
2090 else
2091 gen_op_iwmmxt_unpacklub_M0();
2092 break;
2093 case 1:
2094 if (insn & (1 << 21))
2095 gen_op_iwmmxt_unpacklsw_M0();
2096 else
2097 gen_op_iwmmxt_unpackluw_M0();
2098 break;
2099 case 2:
2100 if (insn & (1 << 21))
2101 gen_op_iwmmxt_unpacklsl_M0();
2102 else
2103 gen_op_iwmmxt_unpacklul_M0();
2104 break;
2105 case 3:
2106 return 1;
2108 gen_op_iwmmxt_movq_wRn_M0(wrd);
2109 gen_op_iwmmxt_set_mup();
2110 gen_op_iwmmxt_set_cup();
2111 break;
2112 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2113 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2114 wrd = (insn >> 12) & 0xf;
2115 rd0 = (insn >> 16) & 0xf;
2116 gen_op_iwmmxt_movq_M0_wRn(rd0);
2117 switch ((insn >> 22) & 3) {
2118 case 0:
2119 if (insn & (1 << 21))
2120 gen_op_iwmmxt_unpackhsb_M0();
2121 else
2122 gen_op_iwmmxt_unpackhub_M0();
2123 break;
2124 case 1:
2125 if (insn & (1 << 21))
2126 gen_op_iwmmxt_unpackhsw_M0();
2127 else
2128 gen_op_iwmmxt_unpackhuw_M0();
2129 break;
2130 case 2:
2131 if (insn & (1 << 21))
2132 gen_op_iwmmxt_unpackhsl_M0();
2133 else
2134 gen_op_iwmmxt_unpackhul_M0();
2135 break;
2136 case 3:
2137 return 1;
2139 gen_op_iwmmxt_movq_wRn_M0(wrd);
2140 gen_op_iwmmxt_set_mup();
2141 gen_op_iwmmxt_set_cup();
2142 break;
2143 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2144 case 0x214: case 0x614: case 0xa14: case 0xe14:
2145 if (((insn >> 22) & 3) == 0)
2146 return 1;
2147 wrd = (insn >> 12) & 0xf;
2148 rd0 = (insn >> 16) & 0xf;
2149 gen_op_iwmmxt_movq_M0_wRn(rd0);
2150 tmp = tcg_temp_new_i32();
2151 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2152 tcg_temp_free_i32(tmp);
2153 return 1;
2155 switch ((insn >> 22) & 3) {
2156 case 1:
2157 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2158 break;
2159 case 2:
2160 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2161 break;
2162 case 3:
2163 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2164 break;
2166 tcg_temp_free_i32(tmp);
2167 gen_op_iwmmxt_movq_wRn_M0(wrd);
2168 gen_op_iwmmxt_set_mup();
2169 gen_op_iwmmxt_set_cup();
2170 break;
2171 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2172 case 0x014: case 0x414: case 0x814: case 0xc14:
2173 if (((insn >> 22) & 3) == 0)
2174 return 1;
2175 wrd = (insn >> 12) & 0xf;
2176 rd0 = (insn >> 16) & 0xf;
2177 gen_op_iwmmxt_movq_M0_wRn(rd0);
2178 tmp = tcg_temp_new_i32();
2179 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2180 tcg_temp_free_i32(tmp);
2181 return 1;
2183 switch ((insn >> 22) & 3) {
2184 case 1:
2185 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2186 break;
2187 case 2:
2188 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2189 break;
2190 case 3:
2191 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2192 break;
2194 tcg_temp_free_i32(tmp);
2195 gen_op_iwmmxt_movq_wRn_M0(wrd);
2196 gen_op_iwmmxt_set_mup();
2197 gen_op_iwmmxt_set_cup();
2198 break;
2199 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2200 case 0x114: case 0x514: case 0x914: case 0xd14:
2201 if (((insn >> 22) & 3) == 0)
2202 return 1;
2203 wrd = (insn >> 12) & 0xf;
2204 rd0 = (insn >> 16) & 0xf;
2205 gen_op_iwmmxt_movq_M0_wRn(rd0);
2206 tmp = tcg_temp_new_i32();
2207 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2208 tcg_temp_free_i32(tmp);
2209 return 1;
2211 switch ((insn >> 22) & 3) {
2212 case 1:
2213 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2214 break;
2215 case 2:
2216 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2217 break;
2218 case 3:
2219 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2220 break;
2222 tcg_temp_free_i32(tmp);
2223 gen_op_iwmmxt_movq_wRn_M0(wrd);
2224 gen_op_iwmmxt_set_mup();
2225 gen_op_iwmmxt_set_cup();
2226 break;
2227 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2228 case 0x314: case 0x714: case 0xb14: case 0xf14:
2229 if (((insn >> 22) & 3) == 0)
2230 return 1;
2231 wrd = (insn >> 12) & 0xf;
2232 rd0 = (insn >> 16) & 0xf;
2233 gen_op_iwmmxt_movq_M0_wRn(rd0);
2234 tmp = tcg_temp_new_i32();
2235 switch ((insn >> 22) & 3) {
2236 case 1:
2237 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2238 tcg_temp_free_i32(tmp);
2239 return 1;
2241 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2242 break;
2243 case 2:
2244 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2245 tcg_temp_free_i32(tmp);
2246 return 1;
2248 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2249 break;
2250 case 3:
2251 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2252 tcg_temp_free_i32(tmp);
2253 return 1;
2255 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2256 break;
2258 tcg_temp_free_i32(tmp);
2259 gen_op_iwmmxt_movq_wRn_M0(wrd);
2260 gen_op_iwmmxt_set_mup();
2261 gen_op_iwmmxt_set_cup();
2262 break;
2263 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2264 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2265 wrd = (insn >> 12) & 0xf;
2266 rd0 = (insn >> 16) & 0xf;
2267 rd1 = (insn >> 0) & 0xf;
2268 gen_op_iwmmxt_movq_M0_wRn(rd0);
2269 switch ((insn >> 22) & 3) {
2270 case 0:
2271 if (insn & (1 << 21))
2272 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2273 else
2274 gen_op_iwmmxt_minub_M0_wRn(rd1);
2275 break;
2276 case 1:
2277 if (insn & (1 << 21))
2278 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2279 else
2280 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2281 break;
2282 case 2:
2283 if (insn & (1 << 21))
2284 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2285 else
2286 gen_op_iwmmxt_minul_M0_wRn(rd1);
2287 break;
2288 case 3:
2289 return 1;
2291 gen_op_iwmmxt_movq_wRn_M0(wrd);
2292 gen_op_iwmmxt_set_mup();
2293 break;
2294 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2295 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2296 wrd = (insn >> 12) & 0xf;
2297 rd0 = (insn >> 16) & 0xf;
2298 rd1 = (insn >> 0) & 0xf;
2299 gen_op_iwmmxt_movq_M0_wRn(rd0);
2300 switch ((insn >> 22) & 3) {
2301 case 0:
2302 if (insn & (1 << 21))
2303 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2304 else
2305 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2306 break;
2307 case 1:
2308 if (insn & (1 << 21))
2309 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2310 else
2311 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2312 break;
2313 case 2:
2314 if (insn & (1 << 21))
2315 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2316 else
2317 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2318 break;
2319 case 3:
2320 return 1;
2322 gen_op_iwmmxt_movq_wRn_M0(wrd);
2323 gen_op_iwmmxt_set_mup();
2324 break;
2325 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2326 case 0x402: case 0x502: case 0x602: case 0x702:
2327 wrd = (insn >> 12) & 0xf;
2328 rd0 = (insn >> 16) & 0xf;
2329 rd1 = (insn >> 0) & 0xf;
2330 gen_op_iwmmxt_movq_M0_wRn(rd0);
2331 tmp = tcg_const_i32((insn >> 20) & 3);
2332 iwmmxt_load_reg(cpu_V1, rd1);
2333 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2334 tcg_temp_free_i32(tmp);
2335 gen_op_iwmmxt_movq_wRn_M0(wrd);
2336 gen_op_iwmmxt_set_mup();
2337 break;
2338 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2339 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2340 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2341 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2342 wrd = (insn >> 12) & 0xf;
2343 rd0 = (insn >> 16) & 0xf;
2344 rd1 = (insn >> 0) & 0xf;
2345 gen_op_iwmmxt_movq_M0_wRn(rd0);
2346 switch ((insn >> 20) & 0xf) {
2347 case 0x0:
2348 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2349 break;
2350 case 0x1:
2351 gen_op_iwmmxt_subub_M0_wRn(rd1);
2352 break;
2353 case 0x3:
2354 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2355 break;
2356 case 0x4:
2357 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2358 break;
2359 case 0x5:
2360 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2361 break;
2362 case 0x7:
2363 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2364 break;
2365 case 0x8:
2366 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2367 break;
2368 case 0x9:
2369 gen_op_iwmmxt_subul_M0_wRn(rd1);
2370 break;
2371 case 0xb:
2372 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2373 break;
2374 default:
2375 return 1;
2377 gen_op_iwmmxt_movq_wRn_M0(wrd);
2378 gen_op_iwmmxt_set_mup();
2379 gen_op_iwmmxt_set_cup();
2380 break;
2381 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2382 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2383 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2384 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2385 wrd = (insn >> 12) & 0xf;
2386 rd0 = (insn >> 16) & 0xf;
2387 gen_op_iwmmxt_movq_M0_wRn(rd0);
2388 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2389 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2390 tcg_temp_free_i32(tmp);
2391 gen_op_iwmmxt_movq_wRn_M0(wrd);
2392 gen_op_iwmmxt_set_mup();
2393 gen_op_iwmmxt_set_cup();
2394 break;
2395 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2396 case 0x418: case 0x518: case 0x618: case 0x718:
2397 case 0x818: case 0x918: case 0xa18: case 0xb18:
2398 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2399 wrd = (insn >> 12) & 0xf;
2400 rd0 = (insn >> 16) & 0xf;
2401 rd1 = (insn >> 0) & 0xf;
2402 gen_op_iwmmxt_movq_M0_wRn(rd0);
2403 switch ((insn >> 20) & 0xf) {
2404 case 0x0:
2405 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2406 break;
2407 case 0x1:
2408 gen_op_iwmmxt_addub_M0_wRn(rd1);
2409 break;
2410 case 0x3:
2411 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2412 break;
2413 case 0x4:
2414 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2415 break;
2416 case 0x5:
2417 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2418 break;
2419 case 0x7:
2420 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2421 break;
2422 case 0x8:
2423 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2424 break;
2425 case 0x9:
2426 gen_op_iwmmxt_addul_M0_wRn(rd1);
2427 break;
2428 case 0xb:
2429 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2430 break;
2431 default:
2432 return 1;
2434 gen_op_iwmmxt_movq_wRn_M0(wrd);
2435 gen_op_iwmmxt_set_mup();
2436 gen_op_iwmmxt_set_cup();
2437 break;
2438 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2439 case 0x408: case 0x508: case 0x608: case 0x708:
2440 case 0x808: case 0x908: case 0xa08: case 0xb08:
2441 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2442 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2443 return 1;
2444 wrd = (insn >> 12) & 0xf;
2445 rd0 = (insn >> 16) & 0xf;
2446 rd1 = (insn >> 0) & 0xf;
2447 gen_op_iwmmxt_movq_M0_wRn(rd0);
2448 switch ((insn >> 22) & 3) {
2449 case 1:
2450 if (insn & (1 << 21))
2451 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2452 else
2453 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2454 break;
2455 case 2:
2456 if (insn & (1 << 21))
2457 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2458 else
2459 gen_op_iwmmxt_packul_M0_wRn(rd1);
2460 break;
2461 case 3:
2462 if (insn & (1 << 21))
2463 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2464 else
2465 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2466 break;
2468 gen_op_iwmmxt_movq_wRn_M0(wrd);
2469 gen_op_iwmmxt_set_mup();
2470 gen_op_iwmmxt_set_cup();
2471 break;
2472 case 0x201: case 0x203: case 0x205: case 0x207:
2473 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2474 case 0x211: case 0x213: case 0x215: case 0x217:
2475 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2476 wrd = (insn >> 5) & 0xf;
2477 rd0 = (insn >> 12) & 0xf;
2478 rd1 = (insn >> 0) & 0xf;
2479 if (rd0 == 0xf || rd1 == 0xf)
2480 return 1;
2481 gen_op_iwmmxt_movq_M0_wRn(wrd);
2482 tmp = load_reg(s, rd0);
2483 tmp2 = load_reg(s, rd1);
2484 switch ((insn >> 16) & 0xf) {
2485 case 0x0: /* TMIA */
2486 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2487 break;
2488 case 0x8: /* TMIAPH */
2489 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2490 break;
2491 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2492 if (insn & (1 << 16))
2493 tcg_gen_shri_i32(tmp, tmp, 16);
2494 if (insn & (1 << 17))
2495 tcg_gen_shri_i32(tmp2, tmp2, 16);
2496 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2497 break;
2498 default:
2499 tcg_temp_free_i32(tmp2);
2500 tcg_temp_free_i32(tmp);
2501 return 1;
2503 tcg_temp_free_i32(tmp2);
2504 tcg_temp_free_i32(tmp);
2505 gen_op_iwmmxt_movq_wRn_M0(wrd);
2506 gen_op_iwmmxt_set_mup();
2507 break;
2508 default:
2509 return 1;
2512 return 0;
2515 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2516 (ie. an undefined instruction). */
2517 static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2519 int acc, rd0, rd1, rdhi, rdlo;
2520 TCGv_i32 tmp, tmp2;
2522 if ((insn & 0x0ff00f10) == 0x0e200010) {
2523 /* Multiply with Internal Accumulate Format */
2524 rd0 = (insn >> 12) & 0xf;
2525 rd1 = insn & 0xf;
2526 acc = (insn >> 5) & 7;
2528 if (acc != 0)
2529 return 1;
2531 tmp = load_reg(s, rd0);
2532 tmp2 = load_reg(s, rd1);
2533 switch ((insn >> 16) & 0xf) {
2534 case 0x0: /* MIA */
2535 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2536 break;
2537 case 0x8: /* MIAPH */
2538 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2539 break;
2540 case 0xc: /* MIABB */
2541 case 0xd: /* MIABT */
2542 case 0xe: /* MIATB */
2543 case 0xf: /* MIATT */
2544 if (insn & (1 << 16))
2545 tcg_gen_shri_i32(tmp, tmp, 16);
2546 if (insn & (1 << 17))
2547 tcg_gen_shri_i32(tmp2, tmp2, 16);
2548 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2549 break;
2550 default:
2551 return 1;
2553 tcg_temp_free_i32(tmp2);
2554 tcg_temp_free_i32(tmp);
2556 gen_op_iwmmxt_movq_wRn_M0(acc);
2557 return 0;
2560 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2561 /* Internal Accumulator Access Format */
2562 rdhi = (insn >> 16) & 0xf;
2563 rdlo = (insn >> 12) & 0xf;
2564 acc = insn & 7;
2566 if (acc != 0)
2567 return 1;
2569 if (insn & ARM_CP_RW_BIT) { /* MRA */
2570 iwmmxt_load_reg(cpu_V0, acc);
2571 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2572 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2573 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2574 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2575 } else { /* MAR */
2576 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2577 iwmmxt_store_reg(cpu_V0, acc);
2579 return 0;
2582 return 1;
2585 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2586 #define VFP_SREG(insn, bigbit, smallbit) \
2587 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2588 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2589 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2590 reg = (((insn) >> (bigbit)) & 0x0f) \
2591 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2592 } else { \
2593 if (insn & (1 << (smallbit))) \
2594 return 1; \
2595 reg = ((insn) >> (bigbit)) & 0x0f; \
2596 }} while (0)
2598 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2599 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2600 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2601 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2602 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2603 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2605 /* Move between integer and VFP cores. */
2606 static TCGv_i32 gen_vfp_mrs(void)
2608 TCGv_i32 tmp = tcg_temp_new_i32();
2609 tcg_gen_mov_i32(tmp, cpu_F0s);
2610 return tmp;
2613 static void gen_vfp_msr(TCGv_i32 tmp)
2615 tcg_gen_mov_i32(cpu_F0s, tmp);
2616 tcg_temp_free_i32(tmp);
2619 static void gen_neon_dup_u8(TCGv_i32 var, int shift)
2621 TCGv_i32 tmp = tcg_temp_new_i32();
2622 if (shift)
2623 tcg_gen_shri_i32(var, var, shift);
2624 tcg_gen_ext8u_i32(var, var);
2625 tcg_gen_shli_i32(tmp, var, 8);
2626 tcg_gen_or_i32(var, var, tmp);
2627 tcg_gen_shli_i32(tmp, var, 16);
2628 tcg_gen_or_i32(var, var, tmp);
2629 tcg_temp_free_i32(tmp);
2632 static void gen_neon_dup_low16(TCGv_i32 var)
2634 TCGv_i32 tmp = tcg_temp_new_i32();
2635 tcg_gen_ext16u_i32(var, var);
2636 tcg_gen_shli_i32(tmp, var, 16);
2637 tcg_gen_or_i32(var, var, tmp);
2638 tcg_temp_free_i32(tmp);
2641 static void gen_neon_dup_high16(TCGv_i32 var)
2643 TCGv_i32 tmp = tcg_temp_new_i32();
2644 tcg_gen_andi_i32(var, var, 0xffff0000);
2645 tcg_gen_shri_i32(tmp, var, 16);
2646 tcg_gen_or_i32(var, var, tmp);
2647 tcg_temp_free_i32(tmp);
2650 static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
2652 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2653 TCGv_i32 tmp = tcg_temp_new_i32();
2654 switch (size) {
2655 case 0:
2656 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
2657 gen_neon_dup_u8(tmp, 0);
2658 break;
2659 case 1:
2660 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
2661 gen_neon_dup_low16(tmp);
2662 break;
2663 case 2:
2664 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
2665 break;
2666 default: /* Avoid compiler warnings. */
2667 abort();
2669 return tmp;
2672 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2673 uint32_t dp)
2675 uint32_t cc = extract32(insn, 20, 2);
2677 if (dp) {
2678 TCGv_i64 frn, frm, dest;
2679 TCGv_i64 tmp, zero, zf, nf, vf;
2681 zero = tcg_const_i64(0);
2683 frn = tcg_temp_new_i64();
2684 frm = tcg_temp_new_i64();
2685 dest = tcg_temp_new_i64();
2687 zf = tcg_temp_new_i64();
2688 nf = tcg_temp_new_i64();
2689 vf = tcg_temp_new_i64();
2691 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2692 tcg_gen_ext_i32_i64(nf, cpu_NF);
2693 tcg_gen_ext_i32_i64(vf, cpu_VF);
2695 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2696 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2697 switch (cc) {
2698 case 0: /* eq: Z */
2699 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2700 frn, frm);
2701 break;
2702 case 1: /* vs: V */
2703 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2704 frn, frm);
2705 break;
2706 case 2: /* ge: N == V -> N ^ V == 0 */
2707 tmp = tcg_temp_new_i64();
2708 tcg_gen_xor_i64(tmp, vf, nf);
2709 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2710 frn, frm);
2711 tcg_temp_free_i64(tmp);
2712 break;
2713 case 3: /* gt: !Z && N == V */
2714 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2715 frn, frm);
2716 tmp = tcg_temp_new_i64();
2717 tcg_gen_xor_i64(tmp, vf, nf);
2718 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2719 dest, frm);
2720 tcg_temp_free_i64(tmp);
2721 break;
2723 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2724 tcg_temp_free_i64(frn);
2725 tcg_temp_free_i64(frm);
2726 tcg_temp_free_i64(dest);
2728 tcg_temp_free_i64(zf);
2729 tcg_temp_free_i64(nf);
2730 tcg_temp_free_i64(vf);
2732 tcg_temp_free_i64(zero);
2733 } else {
2734 TCGv_i32 frn, frm, dest;
2735 TCGv_i32 tmp, zero;
2737 zero = tcg_const_i32(0);
2739 frn = tcg_temp_new_i32();
2740 frm = tcg_temp_new_i32();
2741 dest = tcg_temp_new_i32();
2742 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2743 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2744 switch (cc) {
2745 case 0: /* eq: Z */
2746 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2747 frn, frm);
2748 break;
2749 case 1: /* vs: V */
2750 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2751 frn, frm);
2752 break;
2753 case 2: /* ge: N == V -> N ^ V == 0 */
2754 tmp = tcg_temp_new_i32();
2755 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2756 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2757 frn, frm);
2758 tcg_temp_free_i32(tmp);
2759 break;
2760 case 3: /* gt: !Z && N == V */
2761 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2762 frn, frm);
2763 tmp = tcg_temp_new_i32();
2764 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2765 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2766 dest, frm);
2767 tcg_temp_free_i32(tmp);
2768 break;
2770 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2771 tcg_temp_free_i32(frn);
2772 tcg_temp_free_i32(frm);
2773 tcg_temp_free_i32(dest);
2775 tcg_temp_free_i32(zero);
2778 return 0;
2781 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2782 uint32_t rm, uint32_t dp)
2784 uint32_t vmin = extract32(insn, 6, 1);
2785 TCGv_ptr fpst = get_fpstatus_ptr(0);
2787 if (dp) {
2788 TCGv_i64 frn, frm, dest;
2790 frn = tcg_temp_new_i64();
2791 frm = tcg_temp_new_i64();
2792 dest = tcg_temp_new_i64();
2794 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2795 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2796 if (vmin) {
2797 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
2798 } else {
2799 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
2801 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2802 tcg_temp_free_i64(frn);
2803 tcg_temp_free_i64(frm);
2804 tcg_temp_free_i64(dest);
2805 } else {
2806 TCGv_i32 frn, frm, dest;
2808 frn = tcg_temp_new_i32();
2809 frm = tcg_temp_new_i32();
2810 dest = tcg_temp_new_i32();
2812 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2813 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2814 if (vmin) {
2815 gen_helper_vfp_minnums(dest, frn, frm, fpst);
2816 } else {
2817 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
2819 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2820 tcg_temp_free_i32(frn);
2821 tcg_temp_free_i32(frm);
2822 tcg_temp_free_i32(dest);
2825 tcg_temp_free_ptr(fpst);
2826 return 0;
2829 static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2830 int rounding)
2832 TCGv_ptr fpst = get_fpstatus_ptr(0);
2833 TCGv_i32 tcg_rmode;
2835 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2836 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2838 if (dp) {
2839 TCGv_i64 tcg_op;
2840 TCGv_i64 tcg_res;
2841 tcg_op = tcg_temp_new_i64();
2842 tcg_res = tcg_temp_new_i64();
2843 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2844 gen_helper_rintd(tcg_res, tcg_op, fpst);
2845 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2846 tcg_temp_free_i64(tcg_op);
2847 tcg_temp_free_i64(tcg_res);
2848 } else {
2849 TCGv_i32 tcg_op;
2850 TCGv_i32 tcg_res;
2851 tcg_op = tcg_temp_new_i32();
2852 tcg_res = tcg_temp_new_i32();
2853 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2854 gen_helper_rints(tcg_res, tcg_op, fpst);
2855 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2856 tcg_temp_free_i32(tcg_op);
2857 tcg_temp_free_i32(tcg_res);
2860 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2861 tcg_temp_free_i32(tcg_rmode);
2863 tcg_temp_free_ptr(fpst);
2864 return 0;
2867 static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2868 int rounding)
2870 bool is_signed = extract32(insn, 7, 1);
2871 TCGv_ptr fpst = get_fpstatus_ptr(0);
2872 TCGv_i32 tcg_rmode, tcg_shift;
2874 tcg_shift = tcg_const_i32(0);
2876 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2877 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2879 if (dp) {
2880 TCGv_i64 tcg_double, tcg_res;
2881 TCGv_i32 tcg_tmp;
2882 /* Rd is encoded as a single precision register even when the source
2883 * is double precision.
2885 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
2886 tcg_double = tcg_temp_new_i64();
2887 tcg_res = tcg_temp_new_i64();
2888 tcg_tmp = tcg_temp_new_i32();
2889 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
2890 if (is_signed) {
2891 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
2892 } else {
2893 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
2895 tcg_gen_trunc_i64_i32(tcg_tmp, tcg_res);
2896 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
2897 tcg_temp_free_i32(tcg_tmp);
2898 tcg_temp_free_i64(tcg_res);
2899 tcg_temp_free_i64(tcg_double);
2900 } else {
2901 TCGv_i32 tcg_single, tcg_res;
2902 tcg_single = tcg_temp_new_i32();
2903 tcg_res = tcg_temp_new_i32();
2904 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
2905 if (is_signed) {
2906 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
2907 } else {
2908 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
2910 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
2911 tcg_temp_free_i32(tcg_res);
2912 tcg_temp_free_i32(tcg_single);
2915 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2916 tcg_temp_free_i32(tcg_rmode);
2918 tcg_temp_free_i32(tcg_shift);
2920 tcg_temp_free_ptr(fpst);
2922 return 0;
2925 /* Table for converting the most common AArch32 encoding of
2926 * rounding mode to arm_fprounding order (which matches the
2927 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
2929 static const uint8_t fp_decode_rm[] = {
2930 FPROUNDING_TIEAWAY,
2931 FPROUNDING_TIEEVEN,
2932 FPROUNDING_POSINF,
2933 FPROUNDING_NEGINF,
2936 static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2938 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
2940 if (!arm_feature(env, ARM_FEATURE_V8)) {
2941 return 1;
2944 if (dp) {
2945 VFP_DREG_D(rd, insn);
2946 VFP_DREG_N(rn, insn);
2947 VFP_DREG_M(rm, insn);
2948 } else {
2949 rd = VFP_SREG_D(insn);
2950 rn = VFP_SREG_N(insn);
2951 rm = VFP_SREG_M(insn);
2954 if ((insn & 0x0f800e50) == 0x0e000a00) {
2955 return handle_vsel(insn, rd, rn, rm, dp);
2956 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
2957 return handle_vminmaxnm(insn, rd, rn, rm, dp);
2958 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
2959 /* VRINTA, VRINTN, VRINTP, VRINTM */
2960 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2961 return handle_vrint(insn, rd, rm, dp, rounding);
2962 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
2963 /* VCVTA, VCVTN, VCVTP, VCVTM */
2964 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2965 return handle_vcvt(insn, rd, rm, dp, rounding);
2967 return 1;
2970 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
2971 (ie. an undefined instruction). */
2972 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
2974 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
2975 int dp, veclen;
2976 TCGv_i32 addr;
2977 TCGv_i32 tmp;
2978 TCGv_i32 tmp2;
2980 if (!arm_feature(env, ARM_FEATURE_VFP))
2981 return 1;
2983 /* FIXME: this access check should not take precedence over UNDEF
2984 * for invalid encodings; we will generate incorrect syndrome information
2985 * for attempts to execute invalid vfp/neon encodings with FP disabled.
2987 if (!s->cpacr_fpen) {
2988 gen_exception_insn(s, 4, EXCP_UDEF,
2989 syn_fp_access_trap(1, 0xe, s->thumb));
2990 return 0;
2993 if (!s->vfp_enabled) {
2994 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
2995 if ((insn & 0x0fe00fff) != 0x0ee00a10)
2996 return 1;
2997 rn = (insn >> 16) & 0xf;
2998 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
2999 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
3000 return 1;
3004 if (extract32(insn, 28, 4) == 0xf) {
3005 /* Encodings with T=1 (Thumb) or unconditional (ARM):
3006 * only used in v8 and above.
3008 return disas_vfp_v8_insn(env, s, insn);
3011 dp = ((insn & 0xf00) == 0xb00);
3012 switch ((insn >> 24) & 0xf) {
3013 case 0xe:
3014 if (insn & (1 << 4)) {
3015 /* single register transfer */
3016 rd = (insn >> 12) & 0xf;
3017 if (dp) {
3018 int size;
3019 int pass;
3021 VFP_DREG_N(rn, insn);
3022 if (insn & 0xf)
3023 return 1;
3024 if (insn & 0x00c00060
3025 && !arm_feature(env, ARM_FEATURE_NEON))
3026 return 1;
3028 pass = (insn >> 21) & 1;
3029 if (insn & (1 << 22)) {
3030 size = 0;
3031 offset = ((insn >> 5) & 3) * 8;
3032 } else if (insn & (1 << 5)) {
3033 size = 1;
3034 offset = (insn & (1 << 6)) ? 16 : 0;
3035 } else {
3036 size = 2;
3037 offset = 0;
3039 if (insn & ARM_CP_RW_BIT) {
3040 /* vfp->arm */
3041 tmp = neon_load_reg(rn, pass);
3042 switch (size) {
3043 case 0:
3044 if (offset)
3045 tcg_gen_shri_i32(tmp, tmp, offset);
3046 if (insn & (1 << 23))
3047 gen_uxtb(tmp);
3048 else
3049 gen_sxtb(tmp);
3050 break;
3051 case 1:
3052 if (insn & (1 << 23)) {
3053 if (offset) {
3054 tcg_gen_shri_i32(tmp, tmp, 16);
3055 } else {
3056 gen_uxth(tmp);
3058 } else {
3059 if (offset) {
3060 tcg_gen_sari_i32(tmp, tmp, 16);
3061 } else {
3062 gen_sxth(tmp);
3065 break;
3066 case 2:
3067 break;
3069 store_reg(s, rd, tmp);
3070 } else {
3071 /* arm->vfp */
3072 tmp = load_reg(s, rd);
3073 if (insn & (1 << 23)) {
3074 /* VDUP */
3075 if (size == 0) {
3076 gen_neon_dup_u8(tmp, 0);
3077 } else if (size == 1) {
3078 gen_neon_dup_low16(tmp);
3080 for (n = 0; n <= pass * 2; n++) {
3081 tmp2 = tcg_temp_new_i32();
3082 tcg_gen_mov_i32(tmp2, tmp);
3083 neon_store_reg(rn, n, tmp2);
3085 neon_store_reg(rn, n, tmp);
3086 } else {
3087 /* VMOV */
3088 switch (size) {
3089 case 0:
3090 tmp2 = neon_load_reg(rn, pass);
3091 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
3092 tcg_temp_free_i32(tmp2);
3093 break;
3094 case 1:
3095 tmp2 = neon_load_reg(rn, pass);
3096 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
3097 tcg_temp_free_i32(tmp2);
3098 break;
3099 case 2:
3100 break;
3102 neon_store_reg(rn, pass, tmp);
3105 } else { /* !dp */
3106 if ((insn & 0x6f) != 0x00)
3107 return 1;
3108 rn = VFP_SREG_N(insn);
3109 if (insn & ARM_CP_RW_BIT) {
3110 /* vfp->arm */
3111 if (insn & (1 << 21)) {
3112 /* system register */
3113 rn >>= 1;
3115 switch (rn) {
3116 case ARM_VFP_FPSID:
3117 /* VFP2 allows access to FSID from userspace.
3118 VFP3 restricts all id registers to privileged
3119 accesses. */
3120 if (IS_USER(s)
3121 && arm_feature(env, ARM_FEATURE_VFP3))
3122 return 1;
3123 tmp = load_cpu_field(vfp.xregs[rn]);
3124 break;
3125 case ARM_VFP_FPEXC:
3126 if (IS_USER(s))
3127 return 1;
3128 tmp = load_cpu_field(vfp.xregs[rn]);
3129 break;
3130 case ARM_VFP_FPINST:
3131 case ARM_VFP_FPINST2:
3132 /* Not present in VFP3. */
3133 if (IS_USER(s)
3134 || arm_feature(env, ARM_FEATURE_VFP3))
3135 return 1;
3136 tmp = load_cpu_field(vfp.xregs[rn]);
3137 break;
3138 case ARM_VFP_FPSCR:
3139 if (rd == 15) {
3140 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3141 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3142 } else {
3143 tmp = tcg_temp_new_i32();
3144 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3146 break;
3147 case ARM_VFP_MVFR2:
3148 if (!arm_feature(env, ARM_FEATURE_V8)) {
3149 return 1;
3151 /* fall through */
3152 case ARM_VFP_MVFR0:
3153 case ARM_VFP_MVFR1:
3154 if (IS_USER(s)
3155 || !arm_feature(env, ARM_FEATURE_MVFR))
3156 return 1;
3157 tmp = load_cpu_field(vfp.xregs[rn]);
3158 break;
3159 default:
3160 return 1;
3162 } else {
3163 gen_mov_F0_vreg(0, rn);
3164 tmp = gen_vfp_mrs();
3166 if (rd == 15) {
3167 /* Set the 4 flag bits in the CPSR. */
3168 gen_set_nzcv(tmp);
3169 tcg_temp_free_i32(tmp);
3170 } else {
3171 store_reg(s, rd, tmp);
3173 } else {
3174 /* arm->vfp */
3175 if (insn & (1 << 21)) {
3176 rn >>= 1;
3177 /* system register */
3178 switch (rn) {
3179 case ARM_VFP_FPSID:
3180 case ARM_VFP_MVFR0:
3181 case ARM_VFP_MVFR1:
3182 /* Writes are ignored. */
3183 break;
3184 case ARM_VFP_FPSCR:
3185 tmp = load_reg(s, rd);
3186 gen_helper_vfp_set_fpscr(cpu_env, tmp);
3187 tcg_temp_free_i32(tmp);
3188 gen_lookup_tb(s);
3189 break;
3190 case ARM_VFP_FPEXC:
3191 if (IS_USER(s))
3192 return 1;
3193 /* TODO: VFP subarchitecture support.
3194 * For now, keep the EN bit only */
3195 tmp = load_reg(s, rd);
3196 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3197 store_cpu_field(tmp, vfp.xregs[rn]);
3198 gen_lookup_tb(s);
3199 break;
3200 case ARM_VFP_FPINST:
3201 case ARM_VFP_FPINST2:
3202 tmp = load_reg(s, rd);
3203 store_cpu_field(tmp, vfp.xregs[rn]);
3204 break;
3205 default:
3206 return 1;
3208 } else {
3209 tmp = load_reg(s, rd);
3210 gen_vfp_msr(tmp);
3211 gen_mov_vreg_F0(0, rn);
3215 } else {
3216 /* data processing */
3217 /* The opcode is in bits 23, 21, 20 and 6. */
3218 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3219 if (dp) {
3220 if (op == 15) {
3221 /* rn is opcode */
3222 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3223 } else {
3224 /* rn is register number */
3225 VFP_DREG_N(rn, insn);
3228 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
3229 ((rn & 0x1e) == 0x6))) {
3230 /* Integer or single/half precision destination. */
3231 rd = VFP_SREG_D(insn);
3232 } else {
3233 VFP_DREG_D(rd, insn);
3235 if (op == 15 &&
3236 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
3237 ((rn & 0x1e) == 0x4))) {
3238 /* VCVT from int or half precision is always from S reg
3239 * regardless of dp bit. VCVT with immediate frac_bits
3240 * has same format as SREG_M.
3242 rm = VFP_SREG_M(insn);
3243 } else {
3244 VFP_DREG_M(rm, insn);
3246 } else {
3247 rn = VFP_SREG_N(insn);
3248 if (op == 15 && rn == 15) {
3249 /* Double precision destination. */
3250 VFP_DREG_D(rd, insn);
3251 } else {
3252 rd = VFP_SREG_D(insn);
3254 /* NB that we implicitly rely on the encoding for the frac_bits
3255 * in VCVT of fixed to float being the same as that of an SREG_M
3257 rm = VFP_SREG_M(insn);
3260 veclen = s->vec_len;
3261 if (op == 15 && rn > 3)
3262 veclen = 0;
3264 /* Shut up compiler warnings. */
3265 delta_m = 0;
3266 delta_d = 0;
3267 bank_mask = 0;
3269 if (veclen > 0) {
3270 if (dp)
3271 bank_mask = 0xc;
3272 else
3273 bank_mask = 0x18;
3275 /* Figure out what type of vector operation this is. */
3276 if ((rd & bank_mask) == 0) {
3277 /* scalar */
3278 veclen = 0;
3279 } else {
3280 if (dp)
3281 delta_d = (s->vec_stride >> 1) + 1;
3282 else
3283 delta_d = s->vec_stride + 1;
3285 if ((rm & bank_mask) == 0) {
3286 /* mixed scalar/vector */
3287 delta_m = 0;
3288 } else {
3289 /* vector */
3290 delta_m = delta_d;
3295 /* Load the initial operands. */
3296 if (op == 15) {
3297 switch (rn) {
3298 case 16:
3299 case 17:
3300 /* Integer source */
3301 gen_mov_F0_vreg(0, rm);
3302 break;
3303 case 8:
3304 case 9:
3305 /* Compare */
3306 gen_mov_F0_vreg(dp, rd);
3307 gen_mov_F1_vreg(dp, rm);
3308 break;
3309 case 10:
3310 case 11:
3311 /* Compare with zero */
3312 gen_mov_F0_vreg(dp, rd);
3313 gen_vfp_F1_ld0(dp);
3314 break;
3315 case 20:
3316 case 21:
3317 case 22:
3318 case 23:
3319 case 28:
3320 case 29:
3321 case 30:
3322 case 31:
3323 /* Source and destination the same. */
3324 gen_mov_F0_vreg(dp, rd);
3325 break;
3326 case 4:
3327 case 5:
3328 case 6:
3329 case 7:
3330 /* VCVTB, VCVTT: only present with the halfprec extension
3331 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3332 * (we choose to UNDEF)
3334 if ((dp && !arm_feature(env, ARM_FEATURE_V8)) ||
3335 !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3336 return 1;
3338 if (!extract32(rn, 1, 1)) {
3339 /* Half precision source. */
3340 gen_mov_F0_vreg(0, rm);
3341 break;
3343 /* Otherwise fall through */
3344 default:
3345 /* One source operand. */
3346 gen_mov_F0_vreg(dp, rm);
3347 break;
3349 } else {
3350 /* Two source operands. */
3351 gen_mov_F0_vreg(dp, rn);
3352 gen_mov_F1_vreg(dp, rm);
3355 for (;;) {
3356 /* Perform the calculation. */
3357 switch (op) {
3358 case 0: /* VMLA: fd + (fn * fm) */
3359 /* Note that order of inputs to the add matters for NaNs */
3360 gen_vfp_F1_mul(dp);
3361 gen_mov_F0_vreg(dp, rd);
3362 gen_vfp_add(dp);
3363 break;
3364 case 1: /* VMLS: fd + -(fn * fm) */
3365 gen_vfp_mul(dp);
3366 gen_vfp_F1_neg(dp);
3367 gen_mov_F0_vreg(dp, rd);
3368 gen_vfp_add(dp);
3369 break;
3370 case 2: /* VNMLS: -fd + (fn * fm) */
3371 /* Note that it isn't valid to replace (-A + B) with (B - A)
3372 * or similar plausible looking simplifications
3373 * because this will give wrong results for NaNs.
3375 gen_vfp_F1_mul(dp);
3376 gen_mov_F0_vreg(dp, rd);
3377 gen_vfp_neg(dp);
3378 gen_vfp_add(dp);
3379 break;
3380 case 3: /* VNMLA: -fd + -(fn * fm) */
3381 gen_vfp_mul(dp);
3382 gen_vfp_F1_neg(dp);
3383 gen_mov_F0_vreg(dp, rd);
3384 gen_vfp_neg(dp);
3385 gen_vfp_add(dp);
3386 break;
3387 case 4: /* mul: fn * fm */
3388 gen_vfp_mul(dp);
3389 break;
3390 case 5: /* nmul: -(fn * fm) */
3391 gen_vfp_mul(dp);
3392 gen_vfp_neg(dp);
3393 break;
3394 case 6: /* add: fn + fm */
3395 gen_vfp_add(dp);
3396 break;
3397 case 7: /* sub: fn - fm */
3398 gen_vfp_sub(dp);
3399 break;
3400 case 8: /* div: fn / fm */
3401 gen_vfp_div(dp);
3402 break;
3403 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3404 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3405 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3406 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3407 /* These are fused multiply-add, and must be done as one
3408 * floating point operation with no rounding between the
3409 * multiplication and addition steps.
3410 * NB that doing the negations here as separate steps is
3411 * correct : an input NaN should come out with its sign bit
3412 * flipped if it is a negated-input.
3414 if (!arm_feature(env, ARM_FEATURE_VFP4)) {
3415 return 1;
3417 if (dp) {
3418 TCGv_ptr fpst;
3419 TCGv_i64 frd;
3420 if (op & 1) {
3421 /* VFNMS, VFMS */
3422 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3424 frd = tcg_temp_new_i64();
3425 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3426 if (op & 2) {
3427 /* VFNMA, VFNMS */
3428 gen_helper_vfp_negd(frd, frd);
3430 fpst = get_fpstatus_ptr(0);
3431 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3432 cpu_F1d, frd, fpst);
3433 tcg_temp_free_ptr(fpst);
3434 tcg_temp_free_i64(frd);
3435 } else {
3436 TCGv_ptr fpst;
3437 TCGv_i32 frd;
3438 if (op & 1) {
3439 /* VFNMS, VFMS */
3440 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3442 frd = tcg_temp_new_i32();
3443 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3444 if (op & 2) {
3445 gen_helper_vfp_negs(frd, frd);
3447 fpst = get_fpstatus_ptr(0);
3448 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3449 cpu_F1s, frd, fpst);
3450 tcg_temp_free_ptr(fpst);
3451 tcg_temp_free_i32(frd);
3453 break;
3454 case 14: /* fconst */
3455 if (!arm_feature(env, ARM_FEATURE_VFP3))
3456 return 1;
3458 n = (insn << 12) & 0x80000000;
3459 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3460 if (dp) {
3461 if (i & 0x40)
3462 i |= 0x3f80;
3463 else
3464 i |= 0x4000;
3465 n |= i << 16;
3466 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3467 } else {
3468 if (i & 0x40)
3469 i |= 0x780;
3470 else
3471 i |= 0x800;
3472 n |= i << 19;
3473 tcg_gen_movi_i32(cpu_F0s, n);
3475 break;
3476 case 15: /* extension space */
3477 switch (rn) {
3478 case 0: /* cpy */
3479 /* no-op */
3480 break;
3481 case 1: /* abs */
3482 gen_vfp_abs(dp);
3483 break;
3484 case 2: /* neg */
3485 gen_vfp_neg(dp);
3486 break;
3487 case 3: /* sqrt */
3488 gen_vfp_sqrt(dp);
3489 break;
3490 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
3491 tmp = gen_vfp_mrs();
3492 tcg_gen_ext16u_i32(tmp, tmp);
3493 if (dp) {
3494 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3495 cpu_env);
3496 } else {
3497 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3498 cpu_env);
3500 tcg_temp_free_i32(tmp);
3501 break;
3502 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
3503 tmp = gen_vfp_mrs();
3504 tcg_gen_shri_i32(tmp, tmp, 16);
3505 if (dp) {
3506 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3507 cpu_env);
3508 } else {
3509 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3510 cpu_env);
3512 tcg_temp_free_i32(tmp);
3513 break;
3514 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3515 tmp = tcg_temp_new_i32();
3516 if (dp) {
3517 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3518 cpu_env);
3519 } else {
3520 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3521 cpu_env);
3523 gen_mov_F0_vreg(0, rd);
3524 tmp2 = gen_vfp_mrs();
3525 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3526 tcg_gen_or_i32(tmp, tmp, tmp2);
3527 tcg_temp_free_i32(tmp2);
3528 gen_vfp_msr(tmp);
3529 break;
3530 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3531 tmp = tcg_temp_new_i32();
3532 if (dp) {
3533 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3534 cpu_env);
3535 } else {
3536 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3537 cpu_env);
3539 tcg_gen_shli_i32(tmp, tmp, 16);
3540 gen_mov_F0_vreg(0, rd);
3541 tmp2 = gen_vfp_mrs();
3542 tcg_gen_ext16u_i32(tmp2, tmp2);
3543 tcg_gen_or_i32(tmp, tmp, tmp2);
3544 tcg_temp_free_i32(tmp2);
3545 gen_vfp_msr(tmp);
3546 break;
3547 case 8: /* cmp */
3548 gen_vfp_cmp(dp);
3549 break;
3550 case 9: /* cmpe */
3551 gen_vfp_cmpe(dp);
3552 break;
3553 case 10: /* cmpz */
3554 gen_vfp_cmp(dp);
3555 break;
3556 case 11: /* cmpez */
3557 gen_vfp_F1_ld0(dp);
3558 gen_vfp_cmpe(dp);
3559 break;
3560 case 12: /* vrintr */
3562 TCGv_ptr fpst = get_fpstatus_ptr(0);
3563 if (dp) {
3564 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3565 } else {
3566 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3568 tcg_temp_free_ptr(fpst);
3569 break;
3571 case 13: /* vrintz */
3573 TCGv_ptr fpst = get_fpstatus_ptr(0);
3574 TCGv_i32 tcg_rmode;
3575 tcg_rmode = tcg_const_i32(float_round_to_zero);
3576 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3577 if (dp) {
3578 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3579 } else {
3580 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3582 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3583 tcg_temp_free_i32(tcg_rmode);
3584 tcg_temp_free_ptr(fpst);
3585 break;
3587 case 14: /* vrintx */
3589 TCGv_ptr fpst = get_fpstatus_ptr(0);
3590 if (dp) {
3591 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3592 } else {
3593 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3595 tcg_temp_free_ptr(fpst);
3596 break;
3598 case 15: /* single<->double conversion */
3599 if (dp)
3600 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3601 else
3602 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3603 break;
3604 case 16: /* fuito */
3605 gen_vfp_uito(dp, 0);
3606 break;
3607 case 17: /* fsito */
3608 gen_vfp_sito(dp, 0);
3609 break;
3610 case 20: /* fshto */
3611 if (!arm_feature(env, ARM_FEATURE_VFP3))
3612 return 1;
3613 gen_vfp_shto(dp, 16 - rm, 0);
3614 break;
3615 case 21: /* fslto */
3616 if (!arm_feature(env, ARM_FEATURE_VFP3))
3617 return 1;
3618 gen_vfp_slto(dp, 32 - rm, 0);
3619 break;
3620 case 22: /* fuhto */
3621 if (!arm_feature(env, ARM_FEATURE_VFP3))
3622 return 1;
3623 gen_vfp_uhto(dp, 16 - rm, 0);
3624 break;
3625 case 23: /* fulto */
3626 if (!arm_feature(env, ARM_FEATURE_VFP3))
3627 return 1;
3628 gen_vfp_ulto(dp, 32 - rm, 0);
3629 break;
3630 case 24: /* ftoui */
3631 gen_vfp_toui(dp, 0);
3632 break;
3633 case 25: /* ftouiz */
3634 gen_vfp_touiz(dp, 0);
3635 break;
3636 case 26: /* ftosi */
3637 gen_vfp_tosi(dp, 0);
3638 break;
3639 case 27: /* ftosiz */
3640 gen_vfp_tosiz(dp, 0);
3641 break;
3642 case 28: /* ftosh */
3643 if (!arm_feature(env, ARM_FEATURE_VFP3))
3644 return 1;
3645 gen_vfp_tosh(dp, 16 - rm, 0);
3646 break;
3647 case 29: /* ftosl */
3648 if (!arm_feature(env, ARM_FEATURE_VFP3))
3649 return 1;
3650 gen_vfp_tosl(dp, 32 - rm, 0);
3651 break;
3652 case 30: /* ftouh */
3653 if (!arm_feature(env, ARM_FEATURE_VFP3))
3654 return 1;
3655 gen_vfp_touh(dp, 16 - rm, 0);
3656 break;
3657 case 31: /* ftoul */
3658 if (!arm_feature(env, ARM_FEATURE_VFP3))
3659 return 1;
3660 gen_vfp_toul(dp, 32 - rm, 0);
3661 break;
3662 default: /* undefined */
3663 return 1;
3665 break;
3666 default: /* undefined */
3667 return 1;
3670 /* Write back the result. */
3671 if (op == 15 && (rn >= 8 && rn <= 11)) {
3672 /* Comparison, do nothing. */
3673 } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
3674 (rn & 0x1e) == 0x6)) {
3675 /* VCVT double to int: always integer result.
3676 * VCVT double to half precision is always a single
3677 * precision result.
3679 gen_mov_vreg_F0(0, rd);
3680 } else if (op == 15 && rn == 15) {
3681 /* conversion */
3682 gen_mov_vreg_F0(!dp, rd);
3683 } else {
3684 gen_mov_vreg_F0(dp, rd);
3687 /* break out of the loop if we have finished */
3688 if (veclen == 0)
3689 break;
3691 if (op == 15 && delta_m == 0) {
3692 /* single source one-many */
3693 while (veclen--) {
3694 rd = ((rd + delta_d) & (bank_mask - 1))
3695 | (rd & bank_mask);
3696 gen_mov_vreg_F0(dp, rd);
3698 break;
3700 /* Setup the next operands. */
3701 veclen--;
3702 rd = ((rd + delta_d) & (bank_mask - 1))
3703 | (rd & bank_mask);
3705 if (op == 15) {
3706 /* One source operand. */
3707 rm = ((rm + delta_m) & (bank_mask - 1))
3708 | (rm & bank_mask);
3709 gen_mov_F0_vreg(dp, rm);
3710 } else {
3711 /* Two source operands. */
3712 rn = ((rn + delta_d) & (bank_mask - 1))
3713 | (rn & bank_mask);
3714 gen_mov_F0_vreg(dp, rn);
3715 if (delta_m) {
3716 rm = ((rm + delta_m) & (bank_mask - 1))
3717 | (rm & bank_mask);
3718 gen_mov_F1_vreg(dp, rm);
3723 break;
3724 case 0xc:
3725 case 0xd:
3726 if ((insn & 0x03e00000) == 0x00400000) {
3727 /* two-register transfer */
3728 rn = (insn >> 16) & 0xf;
3729 rd = (insn >> 12) & 0xf;
3730 if (dp) {
3731 VFP_DREG_M(rm, insn);
3732 } else {
3733 rm = VFP_SREG_M(insn);
3736 if (insn & ARM_CP_RW_BIT) {
3737 /* vfp->arm */
3738 if (dp) {
3739 gen_mov_F0_vreg(0, rm * 2);
3740 tmp = gen_vfp_mrs();
3741 store_reg(s, rd, tmp);
3742 gen_mov_F0_vreg(0, rm * 2 + 1);
3743 tmp = gen_vfp_mrs();
3744 store_reg(s, rn, tmp);
3745 } else {
3746 gen_mov_F0_vreg(0, rm);
3747 tmp = gen_vfp_mrs();
3748 store_reg(s, rd, tmp);
3749 gen_mov_F0_vreg(0, rm + 1);
3750 tmp = gen_vfp_mrs();
3751 store_reg(s, rn, tmp);
3753 } else {
3754 /* arm->vfp */
3755 if (dp) {
3756 tmp = load_reg(s, rd);
3757 gen_vfp_msr(tmp);
3758 gen_mov_vreg_F0(0, rm * 2);
3759 tmp = load_reg(s, rn);
3760 gen_vfp_msr(tmp);
3761 gen_mov_vreg_F0(0, rm * 2 + 1);
3762 } else {
3763 tmp = load_reg(s, rd);
3764 gen_vfp_msr(tmp);
3765 gen_mov_vreg_F0(0, rm);
3766 tmp = load_reg(s, rn);
3767 gen_vfp_msr(tmp);
3768 gen_mov_vreg_F0(0, rm + 1);
3771 } else {
3772 /* Load/store */
3773 rn = (insn >> 16) & 0xf;
3774 if (dp)
3775 VFP_DREG_D(rd, insn);
3776 else
3777 rd = VFP_SREG_D(insn);
3778 if ((insn & 0x01200000) == 0x01000000) {
3779 /* Single load/store */
3780 offset = (insn & 0xff) << 2;
3781 if ((insn & (1 << 23)) == 0)
3782 offset = -offset;
3783 if (s->thumb && rn == 15) {
3784 /* This is actually UNPREDICTABLE */
3785 addr = tcg_temp_new_i32();
3786 tcg_gen_movi_i32(addr, s->pc & ~2);
3787 } else {
3788 addr = load_reg(s, rn);
3790 tcg_gen_addi_i32(addr, addr, offset);
3791 if (insn & (1 << 20)) {
3792 gen_vfp_ld(s, dp, addr);
3793 gen_mov_vreg_F0(dp, rd);
3794 } else {
3795 gen_mov_F0_vreg(dp, rd);
3796 gen_vfp_st(s, dp, addr);
3798 tcg_temp_free_i32(addr);
3799 } else {
3800 /* load/store multiple */
3801 int w = insn & (1 << 21);
3802 if (dp)
3803 n = (insn >> 1) & 0x7f;
3804 else
3805 n = insn & 0xff;
3807 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3808 /* P == U , W == 1 => UNDEF */
3809 return 1;
3811 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3812 /* UNPREDICTABLE cases for bad immediates: we choose to
3813 * UNDEF to avoid generating huge numbers of TCG ops
3815 return 1;
3817 if (rn == 15 && w) {
3818 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3819 return 1;
3822 if (s->thumb && rn == 15) {
3823 /* This is actually UNPREDICTABLE */
3824 addr = tcg_temp_new_i32();
3825 tcg_gen_movi_i32(addr, s->pc & ~2);
3826 } else {
3827 addr = load_reg(s, rn);
3829 if (insn & (1 << 24)) /* pre-decrement */
3830 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3832 if (dp)
3833 offset = 8;
3834 else
3835 offset = 4;
3836 for (i = 0; i < n; i++) {
3837 if (insn & ARM_CP_RW_BIT) {
3838 /* load */
3839 gen_vfp_ld(s, dp, addr);
3840 gen_mov_vreg_F0(dp, rd + i);
3841 } else {
3842 /* store */
3843 gen_mov_F0_vreg(dp, rd + i);
3844 gen_vfp_st(s, dp, addr);
3846 tcg_gen_addi_i32(addr, addr, offset);
3848 if (w) {
3849 /* writeback */
3850 if (insn & (1 << 24))
3851 offset = -offset * n;
3852 else if (dp && (insn & 1))
3853 offset = 4;
3854 else
3855 offset = 0;
3857 if (offset != 0)
3858 tcg_gen_addi_i32(addr, addr, offset);
3859 store_reg(s, rn, addr);
3860 } else {
3861 tcg_temp_free_i32(addr);
3865 break;
3866 default:
3867 /* Should never happen. */
3868 return 1;
3870 return 0;
3873 static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
3875 TranslationBlock *tb;
3877 tb = s->tb;
3878 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3879 tcg_gen_goto_tb(n);
3880 gen_set_pc_im(s, dest);
3881 tcg_gen_exit_tb((uintptr_t)tb + n);
3882 } else {
3883 gen_set_pc_im(s, dest);
3884 tcg_gen_exit_tb(0);
3888 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3890 if (unlikely(s->singlestep_enabled || s->ss_active)) {
3891 /* An indirect jump so that we still trigger the debug exception. */
3892 if (s->thumb)
3893 dest |= 1;
3894 gen_bx_im(s, dest);
3895 } else {
3896 gen_goto_tb(s, 0, dest);
3897 s->is_jmp = DISAS_TB_JUMP;
3901 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
3903 if (x)
3904 tcg_gen_sari_i32(t0, t0, 16);
3905 else
3906 gen_sxth(t0);
3907 if (y)
3908 tcg_gen_sari_i32(t1, t1, 16);
3909 else
3910 gen_sxth(t1);
3911 tcg_gen_mul_i32(t0, t0, t1);
3914 /* Return the mask of PSR bits set by a MSR instruction. */
3915 static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
3916 uint32_t mask;
3918 mask = 0;
3919 if (flags & (1 << 0))
3920 mask |= 0xff;
3921 if (flags & (1 << 1))
3922 mask |= 0xff00;
3923 if (flags & (1 << 2))
3924 mask |= 0xff0000;
3925 if (flags & (1 << 3))
3926 mask |= 0xff000000;
3928 /* Mask out undefined bits. */
3929 mask &= ~CPSR_RESERVED;
3930 if (!arm_feature(env, ARM_FEATURE_V4T))
3931 mask &= ~CPSR_T;
3932 if (!arm_feature(env, ARM_FEATURE_V5))
3933 mask &= ~CPSR_Q; /* V5TE in reality*/
3934 if (!arm_feature(env, ARM_FEATURE_V6))
3935 mask &= ~(CPSR_E | CPSR_GE);
3936 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3937 mask &= ~CPSR_IT;
3938 /* Mask out execution state and reserved bits. */
3939 if (!spsr) {
3940 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
3942 /* Mask out privileged bits. */
3943 if (IS_USER(s))
3944 mask &= CPSR_USER;
3945 return mask;
3948 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3949 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
3951 TCGv_i32 tmp;
3952 if (spsr) {
3953 /* ??? This is also undefined in system mode. */
3954 if (IS_USER(s))
3955 return 1;
3957 tmp = load_cpu_field(spsr);
3958 tcg_gen_andi_i32(tmp, tmp, ~mask);
3959 tcg_gen_andi_i32(t0, t0, mask);
3960 tcg_gen_or_i32(tmp, tmp, t0);
3961 store_cpu_field(tmp, spsr);
3962 } else {
3963 gen_set_cpsr(t0, mask);
3965 tcg_temp_free_i32(t0);
3966 gen_lookup_tb(s);
3967 return 0;
3970 /* Returns nonzero if access to the PSR is not permitted. */
3971 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
3973 TCGv_i32 tmp;
3974 tmp = tcg_temp_new_i32();
3975 tcg_gen_movi_i32(tmp, val);
3976 return gen_set_psr(s, mask, spsr, tmp);
3979 /* Generate an old-style exception return. Marks pc as dead. */
3980 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
3982 TCGv_i32 tmp;
3983 store_reg(s, 15, pc);
3984 tmp = load_cpu_field(spsr);
3985 gen_set_cpsr(tmp, CPSR_ERET_MASK);
3986 tcg_temp_free_i32(tmp);
3987 s->is_jmp = DISAS_UPDATE;
3990 /* Generate a v6 exception return. Marks both values as dead. */
3991 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
3993 gen_set_cpsr(cpsr, CPSR_ERET_MASK);
3994 tcg_temp_free_i32(cpsr);
3995 store_reg(s, 15, pc);
3996 s->is_jmp = DISAS_UPDATE;
3999 static void gen_nop_hint(DisasContext *s, int val)
4001 switch (val) {
4002 case 3: /* wfi */
4003 gen_set_pc_im(s, s->pc);
4004 s->is_jmp = DISAS_WFI;
4005 break;
4006 case 2: /* wfe */
4007 gen_set_pc_im(s, s->pc);
4008 s->is_jmp = DISAS_WFE;
4009 break;
4010 case 4: /* sev */
4011 case 5: /* sevl */
4012 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
4013 default: /* nop */
4014 break;
4018 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
4020 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
4022 switch (size) {
4023 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4024 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4025 case 2: tcg_gen_add_i32(t0, t0, t1); break;
4026 default: abort();
4030 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
4032 switch (size) {
4033 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4034 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4035 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
4036 default: return;
4040 /* 32-bit pairwise ops end up the same as the elementwise versions. */
4041 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
4042 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
4043 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
4044 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
4046 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
4047 switch ((size << 1) | u) { \
4048 case 0: \
4049 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
4050 break; \
4051 case 1: \
4052 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
4053 break; \
4054 case 2: \
4055 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
4056 break; \
4057 case 3: \
4058 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
4059 break; \
4060 case 4: \
4061 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
4062 break; \
4063 case 5: \
4064 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
4065 break; \
4066 default: return 1; \
4067 }} while (0)
4069 #define GEN_NEON_INTEGER_OP(name) do { \
4070 switch ((size << 1) | u) { \
4071 case 0: \
4072 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4073 break; \
4074 case 1: \
4075 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4076 break; \
4077 case 2: \
4078 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4079 break; \
4080 case 3: \
4081 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4082 break; \
4083 case 4: \
4084 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4085 break; \
4086 case 5: \
4087 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4088 break; \
4089 default: return 1; \
4090 }} while (0)
4092 static TCGv_i32 neon_load_scratch(int scratch)
4094 TCGv_i32 tmp = tcg_temp_new_i32();
4095 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4096 return tmp;
4099 static void neon_store_scratch(int scratch, TCGv_i32 var)
4101 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4102 tcg_temp_free_i32(var);
4105 static inline TCGv_i32 neon_get_scalar(int size, int reg)
4107 TCGv_i32 tmp;
4108 if (size == 1) {
4109 tmp = neon_load_reg(reg & 7, reg >> 4);
4110 if (reg & 8) {
4111 gen_neon_dup_high16(tmp);
4112 } else {
4113 gen_neon_dup_low16(tmp);
4115 } else {
4116 tmp = neon_load_reg(reg & 15, reg >> 4);
4118 return tmp;
4121 static int gen_neon_unzip(int rd, int rm, int size, int q)
4123 TCGv_i32 tmp, tmp2;
4124 if (!q && size == 2) {
4125 return 1;
4127 tmp = tcg_const_i32(rd);
4128 tmp2 = tcg_const_i32(rm);
4129 if (q) {
4130 switch (size) {
4131 case 0:
4132 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
4133 break;
4134 case 1:
4135 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
4136 break;
4137 case 2:
4138 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
4139 break;
4140 default:
4141 abort();
4143 } else {
4144 switch (size) {
4145 case 0:
4146 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
4147 break;
4148 case 1:
4149 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
4150 break;
4151 default:
4152 abort();
4155 tcg_temp_free_i32(tmp);
4156 tcg_temp_free_i32(tmp2);
4157 return 0;
4160 static int gen_neon_zip(int rd, int rm, int size, int q)
4162 TCGv_i32 tmp, tmp2;
4163 if (!q && size == 2) {
4164 return 1;
4166 tmp = tcg_const_i32(rd);
4167 tmp2 = tcg_const_i32(rm);
4168 if (q) {
4169 switch (size) {
4170 case 0:
4171 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
4172 break;
4173 case 1:
4174 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
4175 break;
4176 case 2:
4177 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
4178 break;
4179 default:
4180 abort();
4182 } else {
4183 switch (size) {
4184 case 0:
4185 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
4186 break;
4187 case 1:
4188 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
4189 break;
4190 default:
4191 abort();
4194 tcg_temp_free_i32(tmp);
4195 tcg_temp_free_i32(tmp2);
4196 return 0;
4199 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
4201 TCGv_i32 rd, tmp;
4203 rd = tcg_temp_new_i32();
4204 tmp = tcg_temp_new_i32();
4206 tcg_gen_shli_i32(rd, t0, 8);
4207 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4208 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4209 tcg_gen_or_i32(rd, rd, tmp);
4211 tcg_gen_shri_i32(t1, t1, 8);
4212 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4213 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4214 tcg_gen_or_i32(t1, t1, tmp);
4215 tcg_gen_mov_i32(t0, rd);
4217 tcg_temp_free_i32(tmp);
4218 tcg_temp_free_i32(rd);
4221 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
4223 TCGv_i32 rd, tmp;
4225 rd = tcg_temp_new_i32();
4226 tmp = tcg_temp_new_i32();
4228 tcg_gen_shli_i32(rd, t0, 16);
4229 tcg_gen_andi_i32(tmp, t1, 0xffff);
4230 tcg_gen_or_i32(rd, rd, tmp);
4231 tcg_gen_shri_i32(t1, t1, 16);
4232 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4233 tcg_gen_or_i32(t1, t1, tmp);
4234 tcg_gen_mov_i32(t0, rd);
4236 tcg_temp_free_i32(tmp);
4237 tcg_temp_free_i32(rd);
4241 static struct {
4242 int nregs;
4243 int interleave;
4244 int spacing;
4245 } neon_ls_element_type[11] = {
4246 {4, 4, 1},
4247 {4, 4, 2},
4248 {4, 1, 1},
4249 {4, 2, 1},
4250 {3, 3, 1},
4251 {3, 3, 2},
4252 {3, 1, 1},
4253 {1, 1, 1},
4254 {2, 2, 1},
4255 {2, 2, 2},
4256 {2, 1, 1}
4259 /* Translate a NEON load/store element instruction. Return nonzero if the
4260 instruction is invalid. */
4261 static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4263 int rd, rn, rm;
4264 int op;
4265 int nregs;
4266 int interleave;
4267 int spacing;
4268 int stride;
4269 int size;
4270 int reg;
4271 int pass;
4272 int load;
4273 int shift;
4274 int n;
4275 TCGv_i32 addr;
4276 TCGv_i32 tmp;
4277 TCGv_i32 tmp2;
4278 TCGv_i64 tmp64;
4280 /* FIXME: this access check should not take precedence over UNDEF
4281 * for invalid encodings; we will generate incorrect syndrome information
4282 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4284 if (!s->cpacr_fpen) {
4285 gen_exception_insn(s, 4, EXCP_UDEF,
4286 syn_fp_access_trap(1, 0xe, s->thumb));
4287 return 0;
4290 if (!s->vfp_enabled)
4291 return 1;
4292 VFP_DREG_D(rd, insn);
4293 rn = (insn >> 16) & 0xf;
4294 rm = insn & 0xf;
4295 load = (insn & (1 << 21)) != 0;
4296 if ((insn & (1 << 23)) == 0) {
4297 /* Load store all elements. */
4298 op = (insn >> 8) & 0xf;
4299 size = (insn >> 6) & 3;
4300 if (op > 10)
4301 return 1;
4302 /* Catch UNDEF cases for bad values of align field */
4303 switch (op & 0xc) {
4304 case 4:
4305 if (((insn >> 5) & 1) == 1) {
4306 return 1;
4308 break;
4309 case 8:
4310 if (((insn >> 4) & 3) == 3) {
4311 return 1;
4313 break;
4314 default:
4315 break;
4317 nregs = neon_ls_element_type[op].nregs;
4318 interleave = neon_ls_element_type[op].interleave;
4319 spacing = neon_ls_element_type[op].spacing;
4320 if (size == 3 && (interleave | spacing) != 1)
4321 return 1;
4322 addr = tcg_temp_new_i32();
4323 load_reg_var(s, addr, rn);
4324 stride = (1 << size) * interleave;
4325 for (reg = 0; reg < nregs; reg++) {
4326 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
4327 load_reg_var(s, addr, rn);
4328 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
4329 } else if (interleave == 2 && nregs == 4 && reg == 2) {
4330 load_reg_var(s, addr, rn);
4331 tcg_gen_addi_i32(addr, addr, 1 << size);
4333 if (size == 3) {
4334 tmp64 = tcg_temp_new_i64();
4335 if (load) {
4336 gen_aa32_ld64(tmp64, addr, get_mem_index(s));
4337 neon_store_reg64(tmp64, rd);
4338 } else {
4339 neon_load_reg64(tmp64, rd);
4340 gen_aa32_st64(tmp64, addr, get_mem_index(s));
4342 tcg_temp_free_i64(tmp64);
4343 tcg_gen_addi_i32(addr, addr, stride);
4344 } else {
4345 for (pass = 0; pass < 2; pass++) {
4346 if (size == 2) {
4347 if (load) {
4348 tmp = tcg_temp_new_i32();
4349 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
4350 neon_store_reg(rd, pass, tmp);
4351 } else {
4352 tmp = neon_load_reg(rd, pass);
4353 gen_aa32_st32(tmp, addr, get_mem_index(s));
4354 tcg_temp_free_i32(tmp);
4356 tcg_gen_addi_i32(addr, addr, stride);
4357 } else if (size == 1) {
4358 if (load) {
4359 tmp = tcg_temp_new_i32();
4360 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
4361 tcg_gen_addi_i32(addr, addr, stride);
4362 tmp2 = tcg_temp_new_i32();
4363 gen_aa32_ld16u(tmp2, addr, get_mem_index(s));
4364 tcg_gen_addi_i32(addr, addr, stride);
4365 tcg_gen_shli_i32(tmp2, tmp2, 16);
4366 tcg_gen_or_i32(tmp, tmp, tmp2);
4367 tcg_temp_free_i32(tmp2);
4368 neon_store_reg(rd, pass, tmp);
4369 } else {
4370 tmp = neon_load_reg(rd, pass);
4371 tmp2 = tcg_temp_new_i32();
4372 tcg_gen_shri_i32(tmp2, tmp, 16);
4373 gen_aa32_st16(tmp, addr, get_mem_index(s));
4374 tcg_temp_free_i32(tmp);
4375 tcg_gen_addi_i32(addr, addr, stride);
4376 gen_aa32_st16(tmp2, addr, get_mem_index(s));
4377 tcg_temp_free_i32(tmp2);
4378 tcg_gen_addi_i32(addr, addr, stride);
4380 } else /* size == 0 */ {
4381 if (load) {
4382 TCGV_UNUSED_I32(tmp2);
4383 for (n = 0; n < 4; n++) {
4384 tmp = tcg_temp_new_i32();
4385 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
4386 tcg_gen_addi_i32(addr, addr, stride);
4387 if (n == 0) {
4388 tmp2 = tmp;
4389 } else {
4390 tcg_gen_shli_i32(tmp, tmp, n * 8);
4391 tcg_gen_or_i32(tmp2, tmp2, tmp);
4392 tcg_temp_free_i32(tmp);
4395 neon_store_reg(rd, pass, tmp2);
4396 } else {
4397 tmp2 = neon_load_reg(rd, pass);
4398 for (n = 0; n < 4; n++) {
4399 tmp = tcg_temp_new_i32();
4400 if (n == 0) {
4401 tcg_gen_mov_i32(tmp, tmp2);
4402 } else {
4403 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4405 gen_aa32_st8(tmp, addr, get_mem_index(s));
4406 tcg_temp_free_i32(tmp);
4407 tcg_gen_addi_i32(addr, addr, stride);
4409 tcg_temp_free_i32(tmp2);
4414 rd += spacing;
4416 tcg_temp_free_i32(addr);
4417 stride = nregs * 8;
4418 } else {
4419 size = (insn >> 10) & 3;
4420 if (size == 3) {
4421 /* Load single element to all lanes. */
4422 int a = (insn >> 4) & 1;
4423 if (!load) {
4424 return 1;
4426 size = (insn >> 6) & 3;
4427 nregs = ((insn >> 8) & 3) + 1;
4429 if (size == 3) {
4430 if (nregs != 4 || a == 0) {
4431 return 1;
4433 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4434 size = 2;
4436 if (nregs == 1 && a == 1 && size == 0) {
4437 return 1;
4439 if (nregs == 3 && a == 1) {
4440 return 1;
4442 addr = tcg_temp_new_i32();
4443 load_reg_var(s, addr, rn);
4444 if (nregs == 1) {
4445 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4446 tmp = gen_load_and_replicate(s, addr, size);
4447 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4448 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4449 if (insn & (1 << 5)) {
4450 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4451 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4453 tcg_temp_free_i32(tmp);
4454 } else {
4455 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4456 stride = (insn & (1 << 5)) ? 2 : 1;
4457 for (reg = 0; reg < nregs; reg++) {
4458 tmp = gen_load_and_replicate(s, addr, size);
4459 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4460 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4461 tcg_temp_free_i32(tmp);
4462 tcg_gen_addi_i32(addr, addr, 1 << size);
4463 rd += stride;
4466 tcg_temp_free_i32(addr);
4467 stride = (1 << size) * nregs;
4468 } else {
4469 /* Single element. */
4470 int idx = (insn >> 4) & 0xf;
4471 pass = (insn >> 7) & 1;
4472 switch (size) {
4473 case 0:
4474 shift = ((insn >> 5) & 3) * 8;
4475 stride = 1;
4476 break;
4477 case 1:
4478 shift = ((insn >> 6) & 1) * 16;
4479 stride = (insn & (1 << 5)) ? 2 : 1;
4480 break;
4481 case 2:
4482 shift = 0;
4483 stride = (insn & (1 << 6)) ? 2 : 1;
4484 break;
4485 default:
4486 abort();
4488 nregs = ((insn >> 8) & 3) + 1;
4489 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4490 switch (nregs) {
4491 case 1:
4492 if (((idx & (1 << size)) != 0) ||
4493 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4494 return 1;
4496 break;
4497 case 3:
4498 if ((idx & 1) != 0) {
4499 return 1;
4501 /* fall through */
4502 case 2:
4503 if (size == 2 && (idx & 2) != 0) {
4504 return 1;
4506 break;
4507 case 4:
4508 if ((size == 2) && ((idx & 3) == 3)) {
4509 return 1;
4511 break;
4512 default:
4513 abort();
4515 if ((rd + stride * (nregs - 1)) > 31) {
4516 /* Attempts to write off the end of the register file
4517 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4518 * the neon_load_reg() would write off the end of the array.
4520 return 1;
4522 addr = tcg_temp_new_i32();
4523 load_reg_var(s, addr, rn);
4524 for (reg = 0; reg < nregs; reg++) {
4525 if (load) {
4526 tmp = tcg_temp_new_i32();
4527 switch (size) {
4528 case 0:
4529 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
4530 break;
4531 case 1:
4532 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
4533 break;
4534 case 2:
4535 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
4536 break;
4537 default: /* Avoid compiler warnings. */
4538 abort();
4540 if (size != 2) {
4541 tmp2 = neon_load_reg(rd, pass);
4542 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4543 shift, size ? 16 : 8);
4544 tcg_temp_free_i32(tmp2);
4546 neon_store_reg(rd, pass, tmp);
4547 } else { /* Store */
4548 tmp = neon_load_reg(rd, pass);
4549 if (shift)
4550 tcg_gen_shri_i32(tmp, tmp, shift);
4551 switch (size) {
4552 case 0:
4553 gen_aa32_st8(tmp, addr, get_mem_index(s));
4554 break;
4555 case 1:
4556 gen_aa32_st16(tmp, addr, get_mem_index(s));
4557 break;
4558 case 2:
4559 gen_aa32_st32(tmp, addr, get_mem_index(s));
4560 break;
4562 tcg_temp_free_i32(tmp);
4564 rd += stride;
4565 tcg_gen_addi_i32(addr, addr, 1 << size);
4567 tcg_temp_free_i32(addr);
4568 stride = nregs * (1 << size);
4571 if (rm != 15) {
4572 TCGv_i32 base;
4574 base = load_reg(s, rn);
4575 if (rm == 13) {
4576 tcg_gen_addi_i32(base, base, stride);
4577 } else {
4578 TCGv_i32 index;
4579 index = load_reg(s, rm);
4580 tcg_gen_add_i32(base, base, index);
4581 tcg_temp_free_i32(index);
4583 store_reg(s, rn, base);
4585 return 0;
4588 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4589 static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
4591 tcg_gen_and_i32(t, t, c);
4592 tcg_gen_andc_i32(f, f, c);
4593 tcg_gen_or_i32(dest, t, f);
4596 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4598 switch (size) {
4599 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4600 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4601 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4602 default: abort();
4606 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4608 switch (size) {
4609 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4610 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4611 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4612 default: abort();
4616 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
4618 switch (size) {
4619 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4620 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4621 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4622 default: abort();
4626 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4628 switch (size) {
4629 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4630 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4631 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4632 default: abort();
4636 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
4637 int q, int u)
4639 if (q) {
4640 if (u) {
4641 switch (size) {
4642 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4643 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4644 default: abort();
4646 } else {
4647 switch (size) {
4648 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4649 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4650 default: abort();
4653 } else {
4654 if (u) {
4655 switch (size) {
4656 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4657 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4658 default: abort();
4660 } else {
4661 switch (size) {
4662 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4663 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4664 default: abort();
4670 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
4672 if (u) {
4673 switch (size) {
4674 case 0: gen_helper_neon_widen_u8(dest, src); break;
4675 case 1: gen_helper_neon_widen_u16(dest, src); break;
4676 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4677 default: abort();
4679 } else {
4680 switch (size) {
4681 case 0: gen_helper_neon_widen_s8(dest, src); break;
4682 case 1: gen_helper_neon_widen_s16(dest, src); break;
4683 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4684 default: abort();
4687 tcg_temp_free_i32(src);
4690 static inline void gen_neon_addl(int size)
4692 switch (size) {
4693 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4694 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4695 case 2: tcg_gen_add_i64(CPU_V001); break;
4696 default: abort();
4700 static inline void gen_neon_subl(int size)
4702 switch (size) {
4703 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4704 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4705 case 2: tcg_gen_sub_i64(CPU_V001); break;
4706 default: abort();
4710 static inline void gen_neon_negl(TCGv_i64 var, int size)
4712 switch (size) {
4713 case 0: gen_helper_neon_negl_u16(var, var); break;
4714 case 1: gen_helper_neon_negl_u32(var, var); break;
4715 case 2:
4716 tcg_gen_neg_i64(var, var);
4717 break;
4718 default: abort();
4722 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4724 switch (size) {
4725 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4726 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4727 default: abort();
4731 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4732 int size, int u)
4734 TCGv_i64 tmp;
4736 switch ((size << 1) | u) {
4737 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4738 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4739 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4740 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4741 case 4:
4742 tmp = gen_muls_i64_i32(a, b);
4743 tcg_gen_mov_i64(dest, tmp);
4744 tcg_temp_free_i64(tmp);
4745 break;
4746 case 5:
4747 tmp = gen_mulu_i64_i32(a, b);
4748 tcg_gen_mov_i64(dest, tmp);
4749 tcg_temp_free_i64(tmp);
4750 break;
4751 default: abort();
4754 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4755 Don't forget to clean them now. */
4756 if (size < 2) {
4757 tcg_temp_free_i32(a);
4758 tcg_temp_free_i32(b);
4762 static void gen_neon_narrow_op(int op, int u, int size,
4763 TCGv_i32 dest, TCGv_i64 src)
4765 if (op) {
4766 if (u) {
4767 gen_neon_unarrow_sats(size, dest, src);
4768 } else {
4769 gen_neon_narrow(size, dest, src);
4771 } else {
4772 if (u) {
4773 gen_neon_narrow_satu(size, dest, src);
4774 } else {
4775 gen_neon_narrow_sats(size, dest, src);
4780 /* Symbolic constants for op fields for Neon 3-register same-length.
4781 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4782 * table A7-9.
4784 #define NEON_3R_VHADD 0
4785 #define NEON_3R_VQADD 1
4786 #define NEON_3R_VRHADD 2
4787 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4788 #define NEON_3R_VHSUB 4
4789 #define NEON_3R_VQSUB 5
4790 #define NEON_3R_VCGT 6
4791 #define NEON_3R_VCGE 7
4792 #define NEON_3R_VSHL 8
4793 #define NEON_3R_VQSHL 9
4794 #define NEON_3R_VRSHL 10
4795 #define NEON_3R_VQRSHL 11
4796 #define NEON_3R_VMAX 12
4797 #define NEON_3R_VMIN 13
4798 #define NEON_3R_VABD 14
4799 #define NEON_3R_VABA 15
4800 #define NEON_3R_VADD_VSUB 16
4801 #define NEON_3R_VTST_VCEQ 17
4802 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4803 #define NEON_3R_VMUL 19
4804 #define NEON_3R_VPMAX 20
4805 #define NEON_3R_VPMIN 21
4806 #define NEON_3R_VQDMULH_VQRDMULH 22
4807 #define NEON_3R_VPADD 23
4808 #define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
4809 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4810 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4811 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4812 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4813 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4814 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4815 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
4817 static const uint8_t neon_3r_sizes[] = {
4818 [NEON_3R_VHADD] = 0x7,
4819 [NEON_3R_VQADD] = 0xf,
4820 [NEON_3R_VRHADD] = 0x7,
4821 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4822 [NEON_3R_VHSUB] = 0x7,
4823 [NEON_3R_VQSUB] = 0xf,
4824 [NEON_3R_VCGT] = 0x7,
4825 [NEON_3R_VCGE] = 0x7,
4826 [NEON_3R_VSHL] = 0xf,
4827 [NEON_3R_VQSHL] = 0xf,
4828 [NEON_3R_VRSHL] = 0xf,
4829 [NEON_3R_VQRSHL] = 0xf,
4830 [NEON_3R_VMAX] = 0x7,
4831 [NEON_3R_VMIN] = 0x7,
4832 [NEON_3R_VABD] = 0x7,
4833 [NEON_3R_VABA] = 0x7,
4834 [NEON_3R_VADD_VSUB] = 0xf,
4835 [NEON_3R_VTST_VCEQ] = 0x7,
4836 [NEON_3R_VML] = 0x7,
4837 [NEON_3R_VMUL] = 0x7,
4838 [NEON_3R_VPMAX] = 0x7,
4839 [NEON_3R_VPMIN] = 0x7,
4840 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4841 [NEON_3R_VPADD] = 0x7,
4842 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
4843 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
4844 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4845 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4846 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4847 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4848 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4849 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
4852 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4853 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4854 * table A7-13.
4856 #define NEON_2RM_VREV64 0
4857 #define NEON_2RM_VREV32 1
4858 #define NEON_2RM_VREV16 2
4859 #define NEON_2RM_VPADDL 4
4860 #define NEON_2RM_VPADDL_U 5
4861 #define NEON_2RM_AESE 6 /* Includes AESD */
4862 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
4863 #define NEON_2RM_VCLS 8
4864 #define NEON_2RM_VCLZ 9
4865 #define NEON_2RM_VCNT 10
4866 #define NEON_2RM_VMVN 11
4867 #define NEON_2RM_VPADAL 12
4868 #define NEON_2RM_VPADAL_U 13
4869 #define NEON_2RM_VQABS 14
4870 #define NEON_2RM_VQNEG 15
4871 #define NEON_2RM_VCGT0 16
4872 #define NEON_2RM_VCGE0 17
4873 #define NEON_2RM_VCEQ0 18
4874 #define NEON_2RM_VCLE0 19
4875 #define NEON_2RM_VCLT0 20
4876 #define NEON_2RM_SHA1H 21
4877 #define NEON_2RM_VABS 22
4878 #define NEON_2RM_VNEG 23
4879 #define NEON_2RM_VCGT0_F 24
4880 #define NEON_2RM_VCGE0_F 25
4881 #define NEON_2RM_VCEQ0_F 26
4882 #define NEON_2RM_VCLE0_F 27
4883 #define NEON_2RM_VCLT0_F 28
4884 #define NEON_2RM_VABS_F 30
4885 #define NEON_2RM_VNEG_F 31
4886 #define NEON_2RM_VSWP 32
4887 #define NEON_2RM_VTRN 33
4888 #define NEON_2RM_VUZP 34
4889 #define NEON_2RM_VZIP 35
4890 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4891 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4892 #define NEON_2RM_VSHLL 38
4893 #define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
4894 #define NEON_2RM_VRINTN 40
4895 #define NEON_2RM_VRINTX 41
4896 #define NEON_2RM_VRINTA 42
4897 #define NEON_2RM_VRINTZ 43
4898 #define NEON_2RM_VCVT_F16_F32 44
4899 #define NEON_2RM_VRINTM 45
4900 #define NEON_2RM_VCVT_F32_F16 46
4901 #define NEON_2RM_VRINTP 47
4902 #define NEON_2RM_VCVTAU 48
4903 #define NEON_2RM_VCVTAS 49
4904 #define NEON_2RM_VCVTNU 50
4905 #define NEON_2RM_VCVTNS 51
4906 #define NEON_2RM_VCVTPU 52
4907 #define NEON_2RM_VCVTPS 53
4908 #define NEON_2RM_VCVTMU 54
4909 #define NEON_2RM_VCVTMS 55
4910 #define NEON_2RM_VRECPE 56
4911 #define NEON_2RM_VRSQRTE 57
4912 #define NEON_2RM_VRECPE_F 58
4913 #define NEON_2RM_VRSQRTE_F 59
4914 #define NEON_2RM_VCVT_FS 60
4915 #define NEON_2RM_VCVT_FU 61
4916 #define NEON_2RM_VCVT_SF 62
4917 #define NEON_2RM_VCVT_UF 63
4919 static int neon_2rm_is_float_op(int op)
4921 /* Return true if this neon 2reg-misc op is float-to-float */
4922 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4923 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
4924 op == NEON_2RM_VRINTM ||
4925 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
4926 op >= NEON_2RM_VRECPE_F);
4929 /* Each entry in this array has bit n set if the insn allows
4930 * size value n (otherwise it will UNDEF). Since unallocated
4931 * op values will have no bits set they always UNDEF.
4933 static const uint8_t neon_2rm_sizes[] = {
4934 [NEON_2RM_VREV64] = 0x7,
4935 [NEON_2RM_VREV32] = 0x3,
4936 [NEON_2RM_VREV16] = 0x1,
4937 [NEON_2RM_VPADDL] = 0x7,
4938 [NEON_2RM_VPADDL_U] = 0x7,
4939 [NEON_2RM_AESE] = 0x1,
4940 [NEON_2RM_AESMC] = 0x1,
4941 [NEON_2RM_VCLS] = 0x7,
4942 [NEON_2RM_VCLZ] = 0x7,
4943 [NEON_2RM_VCNT] = 0x1,
4944 [NEON_2RM_VMVN] = 0x1,
4945 [NEON_2RM_VPADAL] = 0x7,
4946 [NEON_2RM_VPADAL_U] = 0x7,
4947 [NEON_2RM_VQABS] = 0x7,
4948 [NEON_2RM_VQNEG] = 0x7,
4949 [NEON_2RM_VCGT0] = 0x7,
4950 [NEON_2RM_VCGE0] = 0x7,
4951 [NEON_2RM_VCEQ0] = 0x7,
4952 [NEON_2RM_VCLE0] = 0x7,
4953 [NEON_2RM_VCLT0] = 0x7,
4954 [NEON_2RM_SHA1H] = 0x4,
4955 [NEON_2RM_VABS] = 0x7,
4956 [NEON_2RM_VNEG] = 0x7,
4957 [NEON_2RM_VCGT0_F] = 0x4,
4958 [NEON_2RM_VCGE0_F] = 0x4,
4959 [NEON_2RM_VCEQ0_F] = 0x4,
4960 [NEON_2RM_VCLE0_F] = 0x4,
4961 [NEON_2RM_VCLT0_F] = 0x4,
4962 [NEON_2RM_VABS_F] = 0x4,
4963 [NEON_2RM_VNEG_F] = 0x4,
4964 [NEON_2RM_VSWP] = 0x1,
4965 [NEON_2RM_VTRN] = 0x7,
4966 [NEON_2RM_VUZP] = 0x7,
4967 [NEON_2RM_VZIP] = 0x7,
4968 [NEON_2RM_VMOVN] = 0x7,
4969 [NEON_2RM_VQMOVN] = 0x7,
4970 [NEON_2RM_VSHLL] = 0x7,
4971 [NEON_2RM_SHA1SU1] = 0x4,
4972 [NEON_2RM_VRINTN] = 0x4,
4973 [NEON_2RM_VRINTX] = 0x4,
4974 [NEON_2RM_VRINTA] = 0x4,
4975 [NEON_2RM_VRINTZ] = 0x4,
4976 [NEON_2RM_VCVT_F16_F32] = 0x2,
4977 [NEON_2RM_VRINTM] = 0x4,
4978 [NEON_2RM_VCVT_F32_F16] = 0x2,
4979 [NEON_2RM_VRINTP] = 0x4,
4980 [NEON_2RM_VCVTAU] = 0x4,
4981 [NEON_2RM_VCVTAS] = 0x4,
4982 [NEON_2RM_VCVTNU] = 0x4,
4983 [NEON_2RM_VCVTNS] = 0x4,
4984 [NEON_2RM_VCVTPU] = 0x4,
4985 [NEON_2RM_VCVTPS] = 0x4,
4986 [NEON_2RM_VCVTMU] = 0x4,
4987 [NEON_2RM_VCVTMS] = 0x4,
4988 [NEON_2RM_VRECPE] = 0x4,
4989 [NEON_2RM_VRSQRTE] = 0x4,
4990 [NEON_2RM_VRECPE_F] = 0x4,
4991 [NEON_2RM_VRSQRTE_F] = 0x4,
4992 [NEON_2RM_VCVT_FS] = 0x4,
4993 [NEON_2RM_VCVT_FU] = 0x4,
4994 [NEON_2RM_VCVT_SF] = 0x4,
4995 [NEON_2RM_VCVT_UF] = 0x4,
4998 /* Translate a NEON data processing instruction. Return nonzero if the
4999 instruction is invalid.
5000 We process data in a mixture of 32-bit and 64-bit chunks.
5001 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
5003 static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
5005 int op;
5006 int q;
5007 int rd, rn, rm;
5008 int size;
5009 int shift;
5010 int pass;
5011 int count;
5012 int pairwise;
5013 int u;
5014 uint32_t imm, mask;
5015 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
5016 TCGv_i64 tmp64;
5018 /* FIXME: this access check should not take precedence over UNDEF
5019 * for invalid encodings; we will generate incorrect syndrome information
5020 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5022 if (!s->cpacr_fpen) {
5023 gen_exception_insn(s, 4, EXCP_UDEF,
5024 syn_fp_access_trap(1, 0xe, s->thumb));
5025 return 0;
5028 if (!s->vfp_enabled)
5029 return 1;
5030 q = (insn & (1 << 6)) != 0;
5031 u = (insn >> 24) & 1;
5032 VFP_DREG_D(rd, insn);
5033 VFP_DREG_N(rn, insn);
5034 VFP_DREG_M(rm, insn);
5035 size = (insn >> 20) & 3;
5036 if ((insn & (1 << 23)) == 0) {
5037 /* Three register same length. */
5038 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
5039 /* Catch invalid op and bad size combinations: UNDEF */
5040 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
5041 return 1;
5043 /* All insns of this form UNDEF for either this condition or the
5044 * superset of cases "Q==1"; we catch the latter later.
5046 if (q && ((rd | rn | rm) & 1)) {
5047 return 1;
5050 * The SHA-1/SHA-256 3-register instructions require special treatment
5051 * here, as their size field is overloaded as an op type selector, and
5052 * they all consume their input in a single pass.
5054 if (op == NEON_3R_SHA) {
5055 if (!q) {
5056 return 1;
5058 if (!u) { /* SHA-1 */
5059 if (!arm_feature(env, ARM_FEATURE_V8_SHA1)) {
5060 return 1;
5062 tmp = tcg_const_i32(rd);
5063 tmp2 = tcg_const_i32(rn);
5064 tmp3 = tcg_const_i32(rm);
5065 tmp4 = tcg_const_i32(size);
5066 gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4);
5067 tcg_temp_free_i32(tmp4);
5068 } else { /* SHA-256 */
5069 if (!arm_feature(env, ARM_FEATURE_V8_SHA256) || size == 3) {
5070 return 1;
5072 tmp = tcg_const_i32(rd);
5073 tmp2 = tcg_const_i32(rn);
5074 tmp3 = tcg_const_i32(rm);
5075 switch (size) {
5076 case 0:
5077 gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3);
5078 break;
5079 case 1:
5080 gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3);
5081 break;
5082 case 2:
5083 gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3);
5084 break;
5087 tcg_temp_free_i32(tmp);
5088 tcg_temp_free_i32(tmp2);
5089 tcg_temp_free_i32(tmp3);
5090 return 0;
5092 if (size == 3 && op != NEON_3R_LOGIC) {
5093 /* 64-bit element instructions. */
5094 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5095 neon_load_reg64(cpu_V0, rn + pass);
5096 neon_load_reg64(cpu_V1, rm + pass);
5097 switch (op) {
5098 case NEON_3R_VQADD:
5099 if (u) {
5100 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
5101 cpu_V0, cpu_V1);
5102 } else {
5103 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
5104 cpu_V0, cpu_V1);
5106 break;
5107 case NEON_3R_VQSUB:
5108 if (u) {
5109 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
5110 cpu_V0, cpu_V1);
5111 } else {
5112 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
5113 cpu_V0, cpu_V1);
5115 break;
5116 case NEON_3R_VSHL:
5117 if (u) {
5118 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5119 } else {
5120 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5122 break;
5123 case NEON_3R_VQSHL:
5124 if (u) {
5125 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5126 cpu_V1, cpu_V0);
5127 } else {
5128 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5129 cpu_V1, cpu_V0);
5131 break;
5132 case NEON_3R_VRSHL:
5133 if (u) {
5134 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
5135 } else {
5136 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5138 break;
5139 case NEON_3R_VQRSHL:
5140 if (u) {
5141 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5142 cpu_V1, cpu_V0);
5143 } else {
5144 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5145 cpu_V1, cpu_V0);
5147 break;
5148 case NEON_3R_VADD_VSUB:
5149 if (u) {
5150 tcg_gen_sub_i64(CPU_V001);
5151 } else {
5152 tcg_gen_add_i64(CPU_V001);
5154 break;
5155 default:
5156 abort();
5158 neon_store_reg64(cpu_V0, rd + pass);
5160 return 0;
5162 pairwise = 0;
5163 switch (op) {
5164 case NEON_3R_VSHL:
5165 case NEON_3R_VQSHL:
5166 case NEON_3R_VRSHL:
5167 case NEON_3R_VQRSHL:
5169 int rtmp;
5170 /* Shift instruction operands are reversed. */
5171 rtmp = rn;
5172 rn = rm;
5173 rm = rtmp;
5175 break;
5176 case NEON_3R_VPADD:
5177 if (u) {
5178 return 1;
5180 /* Fall through */
5181 case NEON_3R_VPMAX:
5182 case NEON_3R_VPMIN:
5183 pairwise = 1;
5184 break;
5185 case NEON_3R_FLOAT_ARITH:
5186 pairwise = (u && size < 2); /* if VPADD (float) */
5187 break;
5188 case NEON_3R_FLOAT_MINMAX:
5189 pairwise = u; /* if VPMIN/VPMAX (float) */
5190 break;
5191 case NEON_3R_FLOAT_CMP:
5192 if (!u && size) {
5193 /* no encoding for U=0 C=1x */
5194 return 1;
5196 break;
5197 case NEON_3R_FLOAT_ACMP:
5198 if (!u) {
5199 return 1;
5201 break;
5202 case NEON_3R_FLOAT_MISC:
5203 /* VMAXNM/VMINNM in ARMv8 */
5204 if (u && !arm_feature(env, ARM_FEATURE_V8)) {
5205 return 1;
5207 break;
5208 case NEON_3R_VMUL:
5209 if (u && (size != 0)) {
5210 /* UNDEF on invalid size for polynomial subcase */
5211 return 1;
5213 break;
5214 case NEON_3R_VFM:
5215 if (!arm_feature(env, ARM_FEATURE_VFP4) || u) {
5216 return 1;
5218 break;
5219 default:
5220 break;
5223 if (pairwise && q) {
5224 /* All the pairwise insns UNDEF if Q is set */
5225 return 1;
5228 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5230 if (pairwise) {
5231 /* Pairwise. */
5232 if (pass < 1) {
5233 tmp = neon_load_reg(rn, 0);
5234 tmp2 = neon_load_reg(rn, 1);
5235 } else {
5236 tmp = neon_load_reg(rm, 0);
5237 tmp2 = neon_load_reg(rm, 1);
5239 } else {
5240 /* Elementwise. */
5241 tmp = neon_load_reg(rn, pass);
5242 tmp2 = neon_load_reg(rm, pass);
5244 switch (op) {
5245 case NEON_3R_VHADD:
5246 GEN_NEON_INTEGER_OP(hadd);
5247 break;
5248 case NEON_3R_VQADD:
5249 GEN_NEON_INTEGER_OP_ENV(qadd);
5250 break;
5251 case NEON_3R_VRHADD:
5252 GEN_NEON_INTEGER_OP(rhadd);
5253 break;
5254 case NEON_3R_LOGIC: /* Logic ops. */
5255 switch ((u << 2) | size) {
5256 case 0: /* VAND */
5257 tcg_gen_and_i32(tmp, tmp, tmp2);
5258 break;
5259 case 1: /* BIC */
5260 tcg_gen_andc_i32(tmp, tmp, tmp2);
5261 break;
5262 case 2: /* VORR */
5263 tcg_gen_or_i32(tmp, tmp, tmp2);
5264 break;
5265 case 3: /* VORN */
5266 tcg_gen_orc_i32(tmp, tmp, tmp2);
5267 break;
5268 case 4: /* VEOR */
5269 tcg_gen_xor_i32(tmp, tmp, tmp2);
5270 break;
5271 case 5: /* VBSL */
5272 tmp3 = neon_load_reg(rd, pass);
5273 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
5274 tcg_temp_free_i32(tmp3);
5275 break;
5276 case 6: /* VBIT */
5277 tmp3 = neon_load_reg(rd, pass);
5278 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
5279 tcg_temp_free_i32(tmp3);
5280 break;
5281 case 7: /* VBIF */
5282 tmp3 = neon_load_reg(rd, pass);
5283 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
5284 tcg_temp_free_i32(tmp3);
5285 break;
5287 break;
5288 case NEON_3R_VHSUB:
5289 GEN_NEON_INTEGER_OP(hsub);
5290 break;
5291 case NEON_3R_VQSUB:
5292 GEN_NEON_INTEGER_OP_ENV(qsub);
5293 break;
5294 case NEON_3R_VCGT:
5295 GEN_NEON_INTEGER_OP(cgt);
5296 break;
5297 case NEON_3R_VCGE:
5298 GEN_NEON_INTEGER_OP(cge);
5299 break;
5300 case NEON_3R_VSHL:
5301 GEN_NEON_INTEGER_OP(shl);
5302 break;
5303 case NEON_3R_VQSHL:
5304 GEN_NEON_INTEGER_OP_ENV(qshl);
5305 break;
5306 case NEON_3R_VRSHL:
5307 GEN_NEON_INTEGER_OP(rshl);
5308 break;
5309 case NEON_3R_VQRSHL:
5310 GEN_NEON_INTEGER_OP_ENV(qrshl);
5311 break;
5312 case NEON_3R_VMAX:
5313 GEN_NEON_INTEGER_OP(max);
5314 break;
5315 case NEON_3R_VMIN:
5316 GEN_NEON_INTEGER_OP(min);
5317 break;
5318 case NEON_3R_VABD:
5319 GEN_NEON_INTEGER_OP(abd);
5320 break;
5321 case NEON_3R_VABA:
5322 GEN_NEON_INTEGER_OP(abd);
5323 tcg_temp_free_i32(tmp2);
5324 tmp2 = neon_load_reg(rd, pass);
5325 gen_neon_add(size, tmp, tmp2);
5326 break;
5327 case NEON_3R_VADD_VSUB:
5328 if (!u) { /* VADD */
5329 gen_neon_add(size, tmp, tmp2);
5330 } else { /* VSUB */
5331 switch (size) {
5332 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
5333 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
5334 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
5335 default: abort();
5338 break;
5339 case NEON_3R_VTST_VCEQ:
5340 if (!u) { /* VTST */
5341 switch (size) {
5342 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
5343 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
5344 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
5345 default: abort();
5347 } else { /* VCEQ */
5348 switch (size) {
5349 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5350 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5351 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5352 default: abort();
5355 break;
5356 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
5357 switch (size) {
5358 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5359 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5360 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5361 default: abort();
5363 tcg_temp_free_i32(tmp2);
5364 tmp2 = neon_load_reg(rd, pass);
5365 if (u) { /* VMLS */
5366 gen_neon_rsb(size, tmp, tmp2);
5367 } else { /* VMLA */
5368 gen_neon_add(size, tmp, tmp2);
5370 break;
5371 case NEON_3R_VMUL:
5372 if (u) { /* polynomial */
5373 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
5374 } else { /* Integer */
5375 switch (size) {
5376 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5377 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5378 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5379 default: abort();
5382 break;
5383 case NEON_3R_VPMAX:
5384 GEN_NEON_INTEGER_OP(pmax);
5385 break;
5386 case NEON_3R_VPMIN:
5387 GEN_NEON_INTEGER_OP(pmin);
5388 break;
5389 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
5390 if (!u) { /* VQDMULH */
5391 switch (size) {
5392 case 1:
5393 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5394 break;
5395 case 2:
5396 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5397 break;
5398 default: abort();
5400 } else { /* VQRDMULH */
5401 switch (size) {
5402 case 1:
5403 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5404 break;
5405 case 2:
5406 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5407 break;
5408 default: abort();
5411 break;
5412 case NEON_3R_VPADD:
5413 switch (size) {
5414 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5415 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5416 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5417 default: abort();
5419 break;
5420 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
5422 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5423 switch ((u << 2) | size) {
5424 case 0: /* VADD */
5425 case 4: /* VPADD */
5426 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5427 break;
5428 case 2: /* VSUB */
5429 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
5430 break;
5431 case 6: /* VABD */
5432 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
5433 break;
5434 default:
5435 abort();
5437 tcg_temp_free_ptr(fpstatus);
5438 break;
5440 case NEON_3R_FLOAT_MULTIPLY:
5442 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5443 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5444 if (!u) {
5445 tcg_temp_free_i32(tmp2);
5446 tmp2 = neon_load_reg(rd, pass);
5447 if (size == 0) {
5448 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5449 } else {
5450 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5453 tcg_temp_free_ptr(fpstatus);
5454 break;
5456 case NEON_3R_FLOAT_CMP:
5458 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5459 if (!u) {
5460 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5461 } else {
5462 if (size == 0) {
5463 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5464 } else {
5465 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5468 tcg_temp_free_ptr(fpstatus);
5469 break;
5471 case NEON_3R_FLOAT_ACMP:
5473 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5474 if (size == 0) {
5475 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5476 } else {
5477 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5479 tcg_temp_free_ptr(fpstatus);
5480 break;
5482 case NEON_3R_FLOAT_MINMAX:
5484 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5485 if (size == 0) {
5486 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
5487 } else {
5488 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
5490 tcg_temp_free_ptr(fpstatus);
5491 break;
5493 case NEON_3R_FLOAT_MISC:
5494 if (u) {
5495 /* VMAXNM/VMINNM */
5496 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5497 if (size == 0) {
5498 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
5499 } else {
5500 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
5502 tcg_temp_free_ptr(fpstatus);
5503 } else {
5504 if (size == 0) {
5505 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5506 } else {
5507 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5510 break;
5511 case NEON_3R_VFM:
5513 /* VFMA, VFMS: fused multiply-add */
5514 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5515 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5516 if (size) {
5517 /* VFMS */
5518 gen_helper_vfp_negs(tmp, tmp);
5520 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5521 tcg_temp_free_i32(tmp3);
5522 tcg_temp_free_ptr(fpstatus);
5523 break;
5525 default:
5526 abort();
5528 tcg_temp_free_i32(tmp2);
5530 /* Save the result. For elementwise operations we can put it
5531 straight into the destination register. For pairwise operations
5532 we have to be careful to avoid clobbering the source operands. */
5533 if (pairwise && rd == rm) {
5534 neon_store_scratch(pass, tmp);
5535 } else {
5536 neon_store_reg(rd, pass, tmp);
5539 } /* for pass */
5540 if (pairwise && rd == rm) {
5541 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5542 tmp = neon_load_scratch(pass);
5543 neon_store_reg(rd, pass, tmp);
5546 /* End of 3 register same size operations. */
5547 } else if (insn & (1 << 4)) {
5548 if ((insn & 0x00380080) != 0) {
5549 /* Two registers and shift. */
5550 op = (insn >> 8) & 0xf;
5551 if (insn & (1 << 7)) {
5552 /* 64-bit shift. */
5553 if (op > 7) {
5554 return 1;
5556 size = 3;
5557 } else {
5558 size = 2;
5559 while ((insn & (1 << (size + 19))) == 0)
5560 size--;
5562 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5563 /* To avoid excessive duplication of ops we implement shift
5564 by immediate using the variable shift operations. */
5565 if (op < 8) {
5566 /* Shift by immediate:
5567 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5568 if (q && ((rd | rm) & 1)) {
5569 return 1;
5571 if (!u && (op == 4 || op == 6)) {
5572 return 1;
5574 /* Right shifts are encoded as N - shift, where N is the
5575 element size in bits. */
5576 if (op <= 4)
5577 shift = shift - (1 << (size + 3));
5578 if (size == 3) {
5579 count = q + 1;
5580 } else {
5581 count = q ? 4: 2;
5583 switch (size) {
5584 case 0:
5585 imm = (uint8_t) shift;
5586 imm |= imm << 8;
5587 imm |= imm << 16;
5588 break;
5589 case 1:
5590 imm = (uint16_t) shift;
5591 imm |= imm << 16;
5592 break;
5593 case 2:
5594 case 3:
5595 imm = shift;
5596 break;
5597 default:
5598 abort();
5601 for (pass = 0; pass < count; pass++) {
5602 if (size == 3) {
5603 neon_load_reg64(cpu_V0, rm + pass);
5604 tcg_gen_movi_i64(cpu_V1, imm);
5605 switch (op) {
5606 case 0: /* VSHR */
5607 case 1: /* VSRA */
5608 if (u)
5609 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5610 else
5611 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5612 break;
5613 case 2: /* VRSHR */
5614 case 3: /* VRSRA */
5615 if (u)
5616 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5617 else
5618 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5619 break;
5620 case 4: /* VSRI */
5621 case 5: /* VSHL, VSLI */
5622 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5623 break;
5624 case 6: /* VQSHLU */
5625 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5626 cpu_V0, cpu_V1);
5627 break;
5628 case 7: /* VQSHL */
5629 if (u) {
5630 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5631 cpu_V0, cpu_V1);
5632 } else {
5633 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5634 cpu_V0, cpu_V1);
5636 break;
5638 if (op == 1 || op == 3) {
5639 /* Accumulate. */
5640 neon_load_reg64(cpu_V1, rd + pass);
5641 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5642 } else if (op == 4 || (op == 5 && u)) {
5643 /* Insert */
5644 neon_load_reg64(cpu_V1, rd + pass);
5645 uint64_t mask;
5646 if (shift < -63 || shift > 63) {
5647 mask = 0;
5648 } else {
5649 if (op == 4) {
5650 mask = 0xffffffffffffffffull >> -shift;
5651 } else {
5652 mask = 0xffffffffffffffffull << shift;
5655 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5656 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5658 neon_store_reg64(cpu_V0, rd + pass);
5659 } else { /* size < 3 */
5660 /* Operands in T0 and T1. */
5661 tmp = neon_load_reg(rm, pass);
5662 tmp2 = tcg_temp_new_i32();
5663 tcg_gen_movi_i32(tmp2, imm);
5664 switch (op) {
5665 case 0: /* VSHR */
5666 case 1: /* VSRA */
5667 GEN_NEON_INTEGER_OP(shl);
5668 break;
5669 case 2: /* VRSHR */
5670 case 3: /* VRSRA */
5671 GEN_NEON_INTEGER_OP(rshl);
5672 break;
5673 case 4: /* VSRI */
5674 case 5: /* VSHL, VSLI */
5675 switch (size) {
5676 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5677 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5678 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5679 default: abort();
5681 break;
5682 case 6: /* VQSHLU */
5683 switch (size) {
5684 case 0:
5685 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5686 tmp, tmp2);
5687 break;
5688 case 1:
5689 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5690 tmp, tmp2);
5691 break;
5692 case 2:
5693 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5694 tmp, tmp2);
5695 break;
5696 default:
5697 abort();
5699 break;
5700 case 7: /* VQSHL */
5701 GEN_NEON_INTEGER_OP_ENV(qshl);
5702 break;
5704 tcg_temp_free_i32(tmp2);
5706 if (op == 1 || op == 3) {
5707 /* Accumulate. */
5708 tmp2 = neon_load_reg(rd, pass);
5709 gen_neon_add(size, tmp, tmp2);
5710 tcg_temp_free_i32(tmp2);
5711 } else if (op == 4 || (op == 5 && u)) {
5712 /* Insert */
5713 switch (size) {
5714 case 0:
5715 if (op == 4)
5716 mask = 0xff >> -shift;
5717 else
5718 mask = (uint8_t)(0xff << shift);
5719 mask |= mask << 8;
5720 mask |= mask << 16;
5721 break;
5722 case 1:
5723 if (op == 4)
5724 mask = 0xffff >> -shift;
5725 else
5726 mask = (uint16_t)(0xffff << shift);
5727 mask |= mask << 16;
5728 break;
5729 case 2:
5730 if (shift < -31 || shift > 31) {
5731 mask = 0;
5732 } else {
5733 if (op == 4)
5734 mask = 0xffffffffu >> -shift;
5735 else
5736 mask = 0xffffffffu << shift;
5738 break;
5739 default:
5740 abort();
5742 tmp2 = neon_load_reg(rd, pass);
5743 tcg_gen_andi_i32(tmp, tmp, mask);
5744 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5745 tcg_gen_or_i32(tmp, tmp, tmp2);
5746 tcg_temp_free_i32(tmp2);
5748 neon_store_reg(rd, pass, tmp);
5750 } /* for pass */
5751 } else if (op < 10) {
5752 /* Shift by immediate and narrow:
5753 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5754 int input_unsigned = (op == 8) ? !u : u;
5755 if (rm & 1) {
5756 return 1;
5758 shift = shift - (1 << (size + 3));
5759 size++;
5760 if (size == 3) {
5761 tmp64 = tcg_const_i64(shift);
5762 neon_load_reg64(cpu_V0, rm);
5763 neon_load_reg64(cpu_V1, rm + 1);
5764 for (pass = 0; pass < 2; pass++) {
5765 TCGv_i64 in;
5766 if (pass == 0) {
5767 in = cpu_V0;
5768 } else {
5769 in = cpu_V1;
5771 if (q) {
5772 if (input_unsigned) {
5773 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5774 } else {
5775 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5777 } else {
5778 if (input_unsigned) {
5779 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5780 } else {
5781 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5784 tmp = tcg_temp_new_i32();
5785 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5786 neon_store_reg(rd, pass, tmp);
5787 } /* for pass */
5788 tcg_temp_free_i64(tmp64);
5789 } else {
5790 if (size == 1) {
5791 imm = (uint16_t)shift;
5792 imm |= imm << 16;
5793 } else {
5794 /* size == 2 */
5795 imm = (uint32_t)shift;
5797 tmp2 = tcg_const_i32(imm);
5798 tmp4 = neon_load_reg(rm + 1, 0);
5799 tmp5 = neon_load_reg(rm + 1, 1);
5800 for (pass = 0; pass < 2; pass++) {
5801 if (pass == 0) {
5802 tmp = neon_load_reg(rm, 0);
5803 } else {
5804 tmp = tmp4;
5806 gen_neon_shift_narrow(size, tmp, tmp2, q,
5807 input_unsigned);
5808 if (pass == 0) {
5809 tmp3 = neon_load_reg(rm, 1);
5810 } else {
5811 tmp3 = tmp5;
5813 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5814 input_unsigned);
5815 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5816 tcg_temp_free_i32(tmp);
5817 tcg_temp_free_i32(tmp3);
5818 tmp = tcg_temp_new_i32();
5819 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5820 neon_store_reg(rd, pass, tmp);
5821 } /* for pass */
5822 tcg_temp_free_i32(tmp2);
5824 } else if (op == 10) {
5825 /* VSHLL, VMOVL */
5826 if (q || (rd & 1)) {
5827 return 1;
5829 tmp = neon_load_reg(rm, 0);
5830 tmp2 = neon_load_reg(rm, 1);
5831 for (pass = 0; pass < 2; pass++) {
5832 if (pass == 1)
5833 tmp = tmp2;
5835 gen_neon_widen(cpu_V0, tmp, size, u);
5837 if (shift != 0) {
5838 /* The shift is less than the width of the source
5839 type, so we can just shift the whole register. */
5840 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5841 /* Widen the result of shift: we need to clear
5842 * the potential overflow bits resulting from
5843 * left bits of the narrow input appearing as
5844 * right bits of left the neighbour narrow
5845 * input. */
5846 if (size < 2 || !u) {
5847 uint64_t imm64;
5848 if (size == 0) {
5849 imm = (0xffu >> (8 - shift));
5850 imm |= imm << 16;
5851 } else if (size == 1) {
5852 imm = 0xffff >> (16 - shift);
5853 } else {
5854 /* size == 2 */
5855 imm = 0xffffffff >> (32 - shift);
5857 if (size < 2) {
5858 imm64 = imm | (((uint64_t)imm) << 32);
5859 } else {
5860 imm64 = imm;
5862 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5865 neon_store_reg64(cpu_V0, rd + pass);
5867 } else if (op >= 14) {
5868 /* VCVT fixed-point. */
5869 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5870 return 1;
5872 /* We have already masked out the must-be-1 top bit of imm6,
5873 * hence this 32-shift where the ARM ARM has 64-imm6.
5875 shift = 32 - shift;
5876 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5877 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5878 if (!(op & 1)) {
5879 if (u)
5880 gen_vfp_ulto(0, shift, 1);
5881 else
5882 gen_vfp_slto(0, shift, 1);
5883 } else {
5884 if (u)
5885 gen_vfp_toul(0, shift, 1);
5886 else
5887 gen_vfp_tosl(0, shift, 1);
5889 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5891 } else {
5892 return 1;
5894 } else { /* (insn & 0x00380080) == 0 */
5895 int invert;
5896 if (q && (rd & 1)) {
5897 return 1;
5900 op = (insn >> 8) & 0xf;
5901 /* One register and immediate. */
5902 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5903 invert = (insn & (1 << 5)) != 0;
5904 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5905 * We choose to not special-case this and will behave as if a
5906 * valid constant encoding of 0 had been given.
5908 switch (op) {
5909 case 0: case 1:
5910 /* no-op */
5911 break;
5912 case 2: case 3:
5913 imm <<= 8;
5914 break;
5915 case 4: case 5:
5916 imm <<= 16;
5917 break;
5918 case 6: case 7:
5919 imm <<= 24;
5920 break;
5921 case 8: case 9:
5922 imm |= imm << 16;
5923 break;
5924 case 10: case 11:
5925 imm = (imm << 8) | (imm << 24);
5926 break;
5927 case 12:
5928 imm = (imm << 8) | 0xff;
5929 break;
5930 case 13:
5931 imm = (imm << 16) | 0xffff;
5932 break;
5933 case 14:
5934 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5935 if (invert)
5936 imm = ~imm;
5937 break;
5938 case 15:
5939 if (invert) {
5940 return 1;
5942 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5943 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5944 break;
5946 if (invert)
5947 imm = ~imm;
5949 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5950 if (op & 1 && op < 12) {
5951 tmp = neon_load_reg(rd, pass);
5952 if (invert) {
5953 /* The immediate value has already been inverted, so
5954 BIC becomes AND. */
5955 tcg_gen_andi_i32(tmp, tmp, imm);
5956 } else {
5957 tcg_gen_ori_i32(tmp, tmp, imm);
5959 } else {
5960 /* VMOV, VMVN. */
5961 tmp = tcg_temp_new_i32();
5962 if (op == 14 && invert) {
5963 int n;
5964 uint32_t val;
5965 val = 0;
5966 for (n = 0; n < 4; n++) {
5967 if (imm & (1 << (n + (pass & 1) * 4)))
5968 val |= 0xff << (n * 8);
5970 tcg_gen_movi_i32(tmp, val);
5971 } else {
5972 tcg_gen_movi_i32(tmp, imm);
5975 neon_store_reg(rd, pass, tmp);
5978 } else { /* (insn & 0x00800010 == 0x00800000) */
5979 if (size != 3) {
5980 op = (insn >> 8) & 0xf;
5981 if ((insn & (1 << 6)) == 0) {
5982 /* Three registers of different lengths. */
5983 int src1_wide;
5984 int src2_wide;
5985 int prewiden;
5986 /* undefreq: bit 0 : UNDEF if size == 0
5987 * bit 1 : UNDEF if size == 1
5988 * bit 2 : UNDEF if size == 2
5989 * bit 3 : UNDEF if U == 1
5990 * Note that [2:0] set implies 'always UNDEF'
5992 int undefreq;
5993 /* prewiden, src1_wide, src2_wide, undefreq */
5994 static const int neon_3reg_wide[16][4] = {
5995 {1, 0, 0, 0}, /* VADDL */
5996 {1, 1, 0, 0}, /* VADDW */
5997 {1, 0, 0, 0}, /* VSUBL */
5998 {1, 1, 0, 0}, /* VSUBW */
5999 {0, 1, 1, 0}, /* VADDHN */
6000 {0, 0, 0, 0}, /* VABAL */
6001 {0, 1, 1, 0}, /* VSUBHN */
6002 {0, 0, 0, 0}, /* VABDL */
6003 {0, 0, 0, 0}, /* VMLAL */
6004 {0, 0, 0, 9}, /* VQDMLAL */
6005 {0, 0, 0, 0}, /* VMLSL */
6006 {0, 0, 0, 9}, /* VQDMLSL */
6007 {0, 0, 0, 0}, /* Integer VMULL */
6008 {0, 0, 0, 1}, /* VQDMULL */
6009 {0, 0, 0, 0xa}, /* Polynomial VMULL */
6010 {0, 0, 0, 7}, /* Reserved: always UNDEF */
6013 prewiden = neon_3reg_wide[op][0];
6014 src1_wide = neon_3reg_wide[op][1];
6015 src2_wide = neon_3reg_wide[op][2];
6016 undefreq = neon_3reg_wide[op][3];
6018 if ((undefreq & (1 << size)) ||
6019 ((undefreq & 8) && u)) {
6020 return 1;
6022 if ((src1_wide && (rn & 1)) ||
6023 (src2_wide && (rm & 1)) ||
6024 (!src2_wide && (rd & 1))) {
6025 return 1;
6028 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
6029 * outside the loop below as it only performs a single pass.
6031 if (op == 14 && size == 2) {
6032 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
6034 if (!arm_feature(env, ARM_FEATURE_V8_PMULL)) {
6035 return 1;
6037 tcg_rn = tcg_temp_new_i64();
6038 tcg_rm = tcg_temp_new_i64();
6039 tcg_rd = tcg_temp_new_i64();
6040 neon_load_reg64(tcg_rn, rn);
6041 neon_load_reg64(tcg_rm, rm);
6042 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
6043 neon_store_reg64(tcg_rd, rd);
6044 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
6045 neon_store_reg64(tcg_rd, rd + 1);
6046 tcg_temp_free_i64(tcg_rn);
6047 tcg_temp_free_i64(tcg_rm);
6048 tcg_temp_free_i64(tcg_rd);
6049 return 0;
6052 /* Avoid overlapping operands. Wide source operands are
6053 always aligned so will never overlap with wide
6054 destinations in problematic ways. */
6055 if (rd == rm && !src2_wide) {
6056 tmp = neon_load_reg(rm, 1);
6057 neon_store_scratch(2, tmp);
6058 } else if (rd == rn && !src1_wide) {
6059 tmp = neon_load_reg(rn, 1);
6060 neon_store_scratch(2, tmp);
6062 TCGV_UNUSED_I32(tmp3);
6063 for (pass = 0; pass < 2; pass++) {
6064 if (src1_wide) {
6065 neon_load_reg64(cpu_V0, rn + pass);
6066 TCGV_UNUSED_I32(tmp);
6067 } else {
6068 if (pass == 1 && rd == rn) {
6069 tmp = neon_load_scratch(2);
6070 } else {
6071 tmp = neon_load_reg(rn, pass);
6073 if (prewiden) {
6074 gen_neon_widen(cpu_V0, tmp, size, u);
6077 if (src2_wide) {
6078 neon_load_reg64(cpu_V1, rm + pass);
6079 TCGV_UNUSED_I32(tmp2);
6080 } else {
6081 if (pass == 1 && rd == rm) {
6082 tmp2 = neon_load_scratch(2);
6083 } else {
6084 tmp2 = neon_load_reg(rm, pass);
6086 if (prewiden) {
6087 gen_neon_widen(cpu_V1, tmp2, size, u);
6090 switch (op) {
6091 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
6092 gen_neon_addl(size);
6093 break;
6094 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
6095 gen_neon_subl(size);
6096 break;
6097 case 5: case 7: /* VABAL, VABDL */
6098 switch ((size << 1) | u) {
6099 case 0:
6100 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
6101 break;
6102 case 1:
6103 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
6104 break;
6105 case 2:
6106 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
6107 break;
6108 case 3:
6109 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
6110 break;
6111 case 4:
6112 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
6113 break;
6114 case 5:
6115 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
6116 break;
6117 default: abort();
6119 tcg_temp_free_i32(tmp2);
6120 tcg_temp_free_i32(tmp);
6121 break;
6122 case 8: case 9: case 10: case 11: case 12: case 13:
6123 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
6124 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6125 break;
6126 case 14: /* Polynomial VMULL */
6127 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
6128 tcg_temp_free_i32(tmp2);
6129 tcg_temp_free_i32(tmp);
6130 break;
6131 default: /* 15 is RESERVED: caught earlier */
6132 abort();
6134 if (op == 13) {
6135 /* VQDMULL */
6136 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6137 neon_store_reg64(cpu_V0, rd + pass);
6138 } else if (op == 5 || (op >= 8 && op <= 11)) {
6139 /* Accumulate. */
6140 neon_load_reg64(cpu_V1, rd + pass);
6141 switch (op) {
6142 case 10: /* VMLSL */
6143 gen_neon_negl(cpu_V0, size);
6144 /* Fall through */
6145 case 5: case 8: /* VABAL, VMLAL */
6146 gen_neon_addl(size);
6147 break;
6148 case 9: case 11: /* VQDMLAL, VQDMLSL */
6149 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6150 if (op == 11) {
6151 gen_neon_negl(cpu_V0, size);
6153 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6154 break;
6155 default:
6156 abort();
6158 neon_store_reg64(cpu_V0, rd + pass);
6159 } else if (op == 4 || op == 6) {
6160 /* Narrowing operation. */
6161 tmp = tcg_temp_new_i32();
6162 if (!u) {
6163 switch (size) {
6164 case 0:
6165 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6166 break;
6167 case 1:
6168 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6169 break;
6170 case 2:
6171 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6172 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
6173 break;
6174 default: abort();
6176 } else {
6177 switch (size) {
6178 case 0:
6179 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6180 break;
6181 case 1:
6182 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6183 break;
6184 case 2:
6185 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6186 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6187 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
6188 break;
6189 default: abort();
6192 if (pass == 0) {
6193 tmp3 = tmp;
6194 } else {
6195 neon_store_reg(rd, 0, tmp3);
6196 neon_store_reg(rd, 1, tmp);
6198 } else {
6199 /* Write back the result. */
6200 neon_store_reg64(cpu_V0, rd + pass);
6203 } else {
6204 /* Two registers and a scalar. NB that for ops of this form
6205 * the ARM ARM labels bit 24 as Q, but it is in our variable
6206 * 'u', not 'q'.
6208 if (size == 0) {
6209 return 1;
6211 switch (op) {
6212 case 1: /* Float VMLA scalar */
6213 case 5: /* Floating point VMLS scalar */
6214 case 9: /* Floating point VMUL scalar */
6215 if (size == 1) {
6216 return 1;
6218 /* fall through */
6219 case 0: /* Integer VMLA scalar */
6220 case 4: /* Integer VMLS scalar */
6221 case 8: /* Integer VMUL scalar */
6222 case 12: /* VQDMULH scalar */
6223 case 13: /* VQRDMULH scalar */
6224 if (u && ((rd | rn) & 1)) {
6225 return 1;
6227 tmp = neon_get_scalar(size, rm);
6228 neon_store_scratch(0, tmp);
6229 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6230 tmp = neon_load_scratch(0);
6231 tmp2 = neon_load_reg(rn, pass);
6232 if (op == 12) {
6233 if (size == 1) {
6234 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6235 } else {
6236 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6238 } else if (op == 13) {
6239 if (size == 1) {
6240 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6241 } else {
6242 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6244 } else if (op & 1) {
6245 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6246 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6247 tcg_temp_free_ptr(fpstatus);
6248 } else {
6249 switch (size) {
6250 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6251 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6252 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
6253 default: abort();
6256 tcg_temp_free_i32(tmp2);
6257 if (op < 8) {
6258 /* Accumulate. */
6259 tmp2 = neon_load_reg(rd, pass);
6260 switch (op) {
6261 case 0:
6262 gen_neon_add(size, tmp, tmp2);
6263 break;
6264 case 1:
6266 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6267 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6268 tcg_temp_free_ptr(fpstatus);
6269 break;
6271 case 4:
6272 gen_neon_rsb(size, tmp, tmp2);
6273 break;
6274 case 5:
6276 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6277 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6278 tcg_temp_free_ptr(fpstatus);
6279 break;
6281 default:
6282 abort();
6284 tcg_temp_free_i32(tmp2);
6286 neon_store_reg(rd, pass, tmp);
6288 break;
6289 case 3: /* VQDMLAL scalar */
6290 case 7: /* VQDMLSL scalar */
6291 case 11: /* VQDMULL scalar */
6292 if (u == 1) {
6293 return 1;
6295 /* fall through */
6296 case 2: /* VMLAL sclar */
6297 case 6: /* VMLSL scalar */
6298 case 10: /* VMULL scalar */
6299 if (rd & 1) {
6300 return 1;
6302 tmp2 = neon_get_scalar(size, rm);
6303 /* We need a copy of tmp2 because gen_neon_mull
6304 * deletes it during pass 0. */
6305 tmp4 = tcg_temp_new_i32();
6306 tcg_gen_mov_i32(tmp4, tmp2);
6307 tmp3 = neon_load_reg(rn, 1);
6309 for (pass = 0; pass < 2; pass++) {
6310 if (pass == 0) {
6311 tmp = neon_load_reg(rn, 0);
6312 } else {
6313 tmp = tmp3;
6314 tmp2 = tmp4;
6316 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6317 if (op != 11) {
6318 neon_load_reg64(cpu_V1, rd + pass);
6320 switch (op) {
6321 case 6:
6322 gen_neon_negl(cpu_V0, size);
6323 /* Fall through */
6324 case 2:
6325 gen_neon_addl(size);
6326 break;
6327 case 3: case 7:
6328 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6329 if (op == 7) {
6330 gen_neon_negl(cpu_V0, size);
6332 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6333 break;
6334 case 10:
6335 /* no-op */
6336 break;
6337 case 11:
6338 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6339 break;
6340 default:
6341 abort();
6343 neon_store_reg64(cpu_V0, rd + pass);
6347 break;
6348 default: /* 14 and 15 are RESERVED */
6349 return 1;
6352 } else { /* size == 3 */
6353 if (!u) {
6354 /* Extract. */
6355 imm = (insn >> 8) & 0xf;
6357 if (imm > 7 && !q)
6358 return 1;
6360 if (q && ((rd | rn | rm) & 1)) {
6361 return 1;
6364 if (imm == 0) {
6365 neon_load_reg64(cpu_V0, rn);
6366 if (q) {
6367 neon_load_reg64(cpu_V1, rn + 1);
6369 } else if (imm == 8) {
6370 neon_load_reg64(cpu_V0, rn + 1);
6371 if (q) {
6372 neon_load_reg64(cpu_V1, rm);
6374 } else if (q) {
6375 tmp64 = tcg_temp_new_i64();
6376 if (imm < 8) {
6377 neon_load_reg64(cpu_V0, rn);
6378 neon_load_reg64(tmp64, rn + 1);
6379 } else {
6380 neon_load_reg64(cpu_V0, rn + 1);
6381 neon_load_reg64(tmp64, rm);
6383 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
6384 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
6385 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6386 if (imm < 8) {
6387 neon_load_reg64(cpu_V1, rm);
6388 } else {
6389 neon_load_reg64(cpu_V1, rm + 1);
6390 imm -= 8;
6392 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6393 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6394 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
6395 tcg_temp_free_i64(tmp64);
6396 } else {
6397 /* BUGFIX */
6398 neon_load_reg64(cpu_V0, rn);
6399 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
6400 neon_load_reg64(cpu_V1, rm);
6401 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6402 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6404 neon_store_reg64(cpu_V0, rd);
6405 if (q) {
6406 neon_store_reg64(cpu_V1, rd + 1);
6408 } else if ((insn & (1 << 11)) == 0) {
6409 /* Two register misc. */
6410 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6411 size = (insn >> 18) & 3;
6412 /* UNDEF for unknown op values and bad op-size combinations */
6413 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6414 return 1;
6416 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6417 q && ((rm | rd) & 1)) {
6418 return 1;
6420 switch (op) {
6421 case NEON_2RM_VREV64:
6422 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6423 tmp = neon_load_reg(rm, pass * 2);
6424 tmp2 = neon_load_reg(rm, pass * 2 + 1);
6425 switch (size) {
6426 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6427 case 1: gen_swap_half(tmp); break;
6428 case 2: /* no-op */ break;
6429 default: abort();
6431 neon_store_reg(rd, pass * 2 + 1, tmp);
6432 if (size == 2) {
6433 neon_store_reg(rd, pass * 2, tmp2);
6434 } else {
6435 switch (size) {
6436 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6437 case 1: gen_swap_half(tmp2); break;
6438 default: abort();
6440 neon_store_reg(rd, pass * 2, tmp2);
6443 break;
6444 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6445 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
6446 for (pass = 0; pass < q + 1; pass++) {
6447 tmp = neon_load_reg(rm, pass * 2);
6448 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6449 tmp = neon_load_reg(rm, pass * 2 + 1);
6450 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6451 switch (size) {
6452 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6453 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6454 case 2: tcg_gen_add_i64(CPU_V001); break;
6455 default: abort();
6457 if (op >= NEON_2RM_VPADAL) {
6458 /* Accumulate. */
6459 neon_load_reg64(cpu_V1, rd + pass);
6460 gen_neon_addl(size);
6462 neon_store_reg64(cpu_V0, rd + pass);
6464 break;
6465 case NEON_2RM_VTRN:
6466 if (size == 2) {
6467 int n;
6468 for (n = 0; n < (q ? 4 : 2); n += 2) {
6469 tmp = neon_load_reg(rm, n);
6470 tmp2 = neon_load_reg(rd, n + 1);
6471 neon_store_reg(rm, n, tmp2);
6472 neon_store_reg(rd, n + 1, tmp);
6474 } else {
6475 goto elementwise;
6477 break;
6478 case NEON_2RM_VUZP:
6479 if (gen_neon_unzip(rd, rm, size, q)) {
6480 return 1;
6482 break;
6483 case NEON_2RM_VZIP:
6484 if (gen_neon_zip(rd, rm, size, q)) {
6485 return 1;
6487 break;
6488 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6489 /* also VQMOVUN; op field and mnemonics don't line up */
6490 if (rm & 1) {
6491 return 1;
6493 TCGV_UNUSED_I32(tmp2);
6494 for (pass = 0; pass < 2; pass++) {
6495 neon_load_reg64(cpu_V0, rm + pass);
6496 tmp = tcg_temp_new_i32();
6497 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6498 tmp, cpu_V0);
6499 if (pass == 0) {
6500 tmp2 = tmp;
6501 } else {
6502 neon_store_reg(rd, 0, tmp2);
6503 neon_store_reg(rd, 1, tmp);
6506 break;
6507 case NEON_2RM_VSHLL:
6508 if (q || (rd & 1)) {
6509 return 1;
6511 tmp = neon_load_reg(rm, 0);
6512 tmp2 = neon_load_reg(rm, 1);
6513 for (pass = 0; pass < 2; pass++) {
6514 if (pass == 1)
6515 tmp = tmp2;
6516 gen_neon_widen(cpu_V0, tmp, size, 1);
6517 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
6518 neon_store_reg64(cpu_V0, rd + pass);
6520 break;
6521 case NEON_2RM_VCVT_F16_F32:
6522 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6523 q || (rm & 1)) {
6524 return 1;
6526 tmp = tcg_temp_new_i32();
6527 tmp2 = tcg_temp_new_i32();
6528 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
6529 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6530 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
6531 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6532 tcg_gen_shli_i32(tmp2, tmp2, 16);
6533 tcg_gen_or_i32(tmp2, tmp2, tmp);
6534 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
6535 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6536 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6537 neon_store_reg(rd, 0, tmp2);
6538 tmp2 = tcg_temp_new_i32();
6539 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6540 tcg_gen_shli_i32(tmp2, tmp2, 16);
6541 tcg_gen_or_i32(tmp2, tmp2, tmp);
6542 neon_store_reg(rd, 1, tmp2);
6543 tcg_temp_free_i32(tmp);
6544 break;
6545 case NEON_2RM_VCVT_F32_F16:
6546 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6547 q || (rd & 1)) {
6548 return 1;
6550 tmp3 = tcg_temp_new_i32();
6551 tmp = neon_load_reg(rm, 0);
6552 tmp2 = neon_load_reg(rm, 1);
6553 tcg_gen_ext16u_i32(tmp3, tmp);
6554 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6555 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6556 tcg_gen_shri_i32(tmp3, tmp, 16);
6557 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6558 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6559 tcg_temp_free_i32(tmp);
6560 tcg_gen_ext16u_i32(tmp3, tmp2);
6561 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6562 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6563 tcg_gen_shri_i32(tmp3, tmp2, 16);
6564 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6565 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6566 tcg_temp_free_i32(tmp2);
6567 tcg_temp_free_i32(tmp3);
6568 break;
6569 case NEON_2RM_AESE: case NEON_2RM_AESMC:
6570 if (!arm_feature(env, ARM_FEATURE_V8_AES)
6571 || ((rm | rd) & 1)) {
6572 return 1;
6574 tmp = tcg_const_i32(rd);
6575 tmp2 = tcg_const_i32(rm);
6577 /* Bit 6 is the lowest opcode bit; it distinguishes between
6578 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6580 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6582 if (op == NEON_2RM_AESE) {
6583 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6584 } else {
6585 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6587 tcg_temp_free_i32(tmp);
6588 tcg_temp_free_i32(tmp2);
6589 tcg_temp_free_i32(tmp3);
6590 break;
6591 case NEON_2RM_SHA1H:
6592 if (!arm_feature(env, ARM_FEATURE_V8_SHA1)
6593 || ((rm | rd) & 1)) {
6594 return 1;
6596 tmp = tcg_const_i32(rd);
6597 tmp2 = tcg_const_i32(rm);
6599 gen_helper_crypto_sha1h(cpu_env, tmp, tmp2);
6601 tcg_temp_free_i32(tmp);
6602 tcg_temp_free_i32(tmp2);
6603 break;
6604 case NEON_2RM_SHA1SU1:
6605 if ((rm | rd) & 1) {
6606 return 1;
6608 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
6609 if (q) {
6610 if (!arm_feature(env, ARM_FEATURE_V8_SHA256)) {
6611 return 1;
6613 } else if (!arm_feature(env, ARM_FEATURE_V8_SHA1)) {
6614 return 1;
6616 tmp = tcg_const_i32(rd);
6617 tmp2 = tcg_const_i32(rm);
6618 if (q) {
6619 gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2);
6620 } else {
6621 gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2);
6623 tcg_temp_free_i32(tmp);
6624 tcg_temp_free_i32(tmp2);
6625 break;
6626 default:
6627 elementwise:
6628 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6629 if (neon_2rm_is_float_op(op)) {
6630 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6631 neon_reg_offset(rm, pass));
6632 TCGV_UNUSED_I32(tmp);
6633 } else {
6634 tmp = neon_load_reg(rm, pass);
6636 switch (op) {
6637 case NEON_2RM_VREV32:
6638 switch (size) {
6639 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6640 case 1: gen_swap_half(tmp); break;
6641 default: abort();
6643 break;
6644 case NEON_2RM_VREV16:
6645 gen_rev16(tmp);
6646 break;
6647 case NEON_2RM_VCLS:
6648 switch (size) {
6649 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6650 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6651 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6652 default: abort();
6654 break;
6655 case NEON_2RM_VCLZ:
6656 switch (size) {
6657 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6658 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6659 case 2: gen_helper_clz(tmp, tmp); break;
6660 default: abort();
6662 break;
6663 case NEON_2RM_VCNT:
6664 gen_helper_neon_cnt_u8(tmp, tmp);
6665 break;
6666 case NEON_2RM_VMVN:
6667 tcg_gen_not_i32(tmp, tmp);
6668 break;
6669 case NEON_2RM_VQABS:
6670 switch (size) {
6671 case 0:
6672 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6673 break;
6674 case 1:
6675 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6676 break;
6677 case 2:
6678 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6679 break;
6680 default: abort();
6682 break;
6683 case NEON_2RM_VQNEG:
6684 switch (size) {
6685 case 0:
6686 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6687 break;
6688 case 1:
6689 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6690 break;
6691 case 2:
6692 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6693 break;
6694 default: abort();
6696 break;
6697 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6698 tmp2 = tcg_const_i32(0);
6699 switch(size) {
6700 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6701 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6702 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6703 default: abort();
6705 tcg_temp_free_i32(tmp2);
6706 if (op == NEON_2RM_VCLE0) {
6707 tcg_gen_not_i32(tmp, tmp);
6709 break;
6710 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6711 tmp2 = tcg_const_i32(0);
6712 switch(size) {
6713 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6714 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6715 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6716 default: abort();
6718 tcg_temp_free_i32(tmp2);
6719 if (op == NEON_2RM_VCLT0) {
6720 tcg_gen_not_i32(tmp, tmp);
6722 break;
6723 case NEON_2RM_VCEQ0:
6724 tmp2 = tcg_const_i32(0);
6725 switch(size) {
6726 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6727 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6728 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6729 default: abort();
6731 tcg_temp_free_i32(tmp2);
6732 break;
6733 case NEON_2RM_VABS:
6734 switch(size) {
6735 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6736 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6737 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6738 default: abort();
6740 break;
6741 case NEON_2RM_VNEG:
6742 tmp2 = tcg_const_i32(0);
6743 gen_neon_rsb(size, tmp, tmp2);
6744 tcg_temp_free_i32(tmp2);
6745 break;
6746 case NEON_2RM_VCGT0_F:
6748 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6749 tmp2 = tcg_const_i32(0);
6750 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6751 tcg_temp_free_i32(tmp2);
6752 tcg_temp_free_ptr(fpstatus);
6753 break;
6755 case NEON_2RM_VCGE0_F:
6757 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6758 tmp2 = tcg_const_i32(0);
6759 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6760 tcg_temp_free_i32(tmp2);
6761 tcg_temp_free_ptr(fpstatus);
6762 break;
6764 case NEON_2RM_VCEQ0_F:
6766 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6767 tmp2 = tcg_const_i32(0);
6768 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6769 tcg_temp_free_i32(tmp2);
6770 tcg_temp_free_ptr(fpstatus);
6771 break;
6773 case NEON_2RM_VCLE0_F:
6775 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6776 tmp2 = tcg_const_i32(0);
6777 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6778 tcg_temp_free_i32(tmp2);
6779 tcg_temp_free_ptr(fpstatus);
6780 break;
6782 case NEON_2RM_VCLT0_F:
6784 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6785 tmp2 = tcg_const_i32(0);
6786 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6787 tcg_temp_free_i32(tmp2);
6788 tcg_temp_free_ptr(fpstatus);
6789 break;
6791 case NEON_2RM_VABS_F:
6792 gen_vfp_abs(0);
6793 break;
6794 case NEON_2RM_VNEG_F:
6795 gen_vfp_neg(0);
6796 break;
6797 case NEON_2RM_VSWP:
6798 tmp2 = neon_load_reg(rd, pass);
6799 neon_store_reg(rm, pass, tmp2);
6800 break;
6801 case NEON_2RM_VTRN:
6802 tmp2 = neon_load_reg(rd, pass);
6803 switch (size) {
6804 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6805 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6806 default: abort();
6808 neon_store_reg(rm, pass, tmp2);
6809 break;
6810 case NEON_2RM_VRINTN:
6811 case NEON_2RM_VRINTA:
6812 case NEON_2RM_VRINTM:
6813 case NEON_2RM_VRINTP:
6814 case NEON_2RM_VRINTZ:
6816 TCGv_i32 tcg_rmode;
6817 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6818 int rmode;
6820 if (op == NEON_2RM_VRINTZ) {
6821 rmode = FPROUNDING_ZERO;
6822 } else {
6823 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6826 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6827 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6828 cpu_env);
6829 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
6830 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6831 cpu_env);
6832 tcg_temp_free_ptr(fpstatus);
6833 tcg_temp_free_i32(tcg_rmode);
6834 break;
6836 case NEON_2RM_VRINTX:
6838 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6839 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
6840 tcg_temp_free_ptr(fpstatus);
6841 break;
6843 case NEON_2RM_VCVTAU:
6844 case NEON_2RM_VCVTAS:
6845 case NEON_2RM_VCVTNU:
6846 case NEON_2RM_VCVTNS:
6847 case NEON_2RM_VCVTPU:
6848 case NEON_2RM_VCVTPS:
6849 case NEON_2RM_VCVTMU:
6850 case NEON_2RM_VCVTMS:
6852 bool is_signed = !extract32(insn, 7, 1);
6853 TCGv_ptr fpst = get_fpstatus_ptr(1);
6854 TCGv_i32 tcg_rmode, tcg_shift;
6855 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6857 tcg_shift = tcg_const_i32(0);
6858 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6859 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6860 cpu_env);
6862 if (is_signed) {
6863 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
6864 tcg_shift, fpst);
6865 } else {
6866 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
6867 tcg_shift, fpst);
6870 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6871 cpu_env);
6872 tcg_temp_free_i32(tcg_rmode);
6873 tcg_temp_free_i32(tcg_shift);
6874 tcg_temp_free_ptr(fpst);
6875 break;
6877 case NEON_2RM_VRECPE:
6879 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6880 gen_helper_recpe_u32(tmp, tmp, fpstatus);
6881 tcg_temp_free_ptr(fpstatus);
6882 break;
6884 case NEON_2RM_VRSQRTE:
6886 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6887 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
6888 tcg_temp_free_ptr(fpstatus);
6889 break;
6891 case NEON_2RM_VRECPE_F:
6893 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6894 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
6895 tcg_temp_free_ptr(fpstatus);
6896 break;
6898 case NEON_2RM_VRSQRTE_F:
6900 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6901 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
6902 tcg_temp_free_ptr(fpstatus);
6903 break;
6905 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6906 gen_vfp_sito(0, 1);
6907 break;
6908 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6909 gen_vfp_uito(0, 1);
6910 break;
6911 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6912 gen_vfp_tosiz(0, 1);
6913 break;
6914 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6915 gen_vfp_touiz(0, 1);
6916 break;
6917 default:
6918 /* Reserved op values were caught by the
6919 * neon_2rm_sizes[] check earlier.
6921 abort();
6923 if (neon_2rm_is_float_op(op)) {
6924 tcg_gen_st_f32(cpu_F0s, cpu_env,
6925 neon_reg_offset(rd, pass));
6926 } else {
6927 neon_store_reg(rd, pass, tmp);
6930 break;
6932 } else if ((insn & (1 << 10)) == 0) {
6933 /* VTBL, VTBX. */
6934 int n = ((insn >> 8) & 3) + 1;
6935 if ((rn + n) > 32) {
6936 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6937 * helper function running off the end of the register file.
6939 return 1;
6941 n <<= 3;
6942 if (insn & (1 << 6)) {
6943 tmp = neon_load_reg(rd, 0);
6944 } else {
6945 tmp = tcg_temp_new_i32();
6946 tcg_gen_movi_i32(tmp, 0);
6948 tmp2 = neon_load_reg(rm, 0);
6949 tmp4 = tcg_const_i32(rn);
6950 tmp5 = tcg_const_i32(n);
6951 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
6952 tcg_temp_free_i32(tmp);
6953 if (insn & (1 << 6)) {
6954 tmp = neon_load_reg(rd, 1);
6955 } else {
6956 tmp = tcg_temp_new_i32();
6957 tcg_gen_movi_i32(tmp, 0);
6959 tmp3 = neon_load_reg(rm, 1);
6960 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
6961 tcg_temp_free_i32(tmp5);
6962 tcg_temp_free_i32(tmp4);
6963 neon_store_reg(rd, 0, tmp2);
6964 neon_store_reg(rd, 1, tmp3);
6965 tcg_temp_free_i32(tmp);
6966 } else if ((insn & 0x380) == 0) {
6967 /* VDUP */
6968 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
6969 return 1;
6971 if (insn & (1 << 19)) {
6972 tmp = neon_load_reg(rm, 1);
6973 } else {
6974 tmp = neon_load_reg(rm, 0);
6976 if (insn & (1 << 16)) {
6977 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
6978 } else if (insn & (1 << 17)) {
6979 if ((insn >> 18) & 1)
6980 gen_neon_dup_high16(tmp);
6981 else
6982 gen_neon_dup_low16(tmp);
6984 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6985 tmp2 = tcg_temp_new_i32();
6986 tcg_gen_mov_i32(tmp2, tmp);
6987 neon_store_reg(rd, pass, tmp2);
6989 tcg_temp_free_i32(tmp);
6990 } else {
6991 return 1;
6995 return 0;
6998 static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
7000 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7001 const ARMCPRegInfo *ri;
7003 cpnum = (insn >> 8) & 0xf;
7004 if (arm_feature(env, ARM_FEATURE_XSCALE)
7005 && ((env->cp15.c15_cpar ^ 0x3fff) & (1 << cpnum)))
7006 return 1;
7008 /* First check for coprocessor space used for actual instructions */
7009 switch (cpnum) {
7010 case 0:
7011 case 1:
7012 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7013 return disas_iwmmxt_insn(env, s, insn);
7014 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
7015 return disas_dsp_insn(env, s, insn);
7017 return 1;
7018 default:
7019 break;
7022 /* Otherwise treat as a generic register access */
7023 is64 = (insn & (1 << 25)) == 0;
7024 if (!is64 && ((insn & (1 << 4)) == 0)) {
7025 /* cdp */
7026 return 1;
7029 crm = insn & 0xf;
7030 if (is64) {
7031 crn = 0;
7032 opc1 = (insn >> 4) & 0xf;
7033 opc2 = 0;
7034 rt2 = (insn >> 16) & 0xf;
7035 } else {
7036 crn = (insn >> 16) & 0xf;
7037 opc1 = (insn >> 21) & 7;
7038 opc2 = (insn >> 5) & 7;
7039 rt2 = 0;
7041 isread = (insn >> 20) & 1;
7042 rt = (insn >> 12) & 0xf;
7044 ri = get_arm_cp_reginfo(s->cp_regs,
7045 ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
7046 if (ri) {
7047 /* Check access permissions */
7048 if (!cp_access_ok(s->current_pl, ri, isread)) {
7049 return 1;
7052 if (ri->accessfn) {
7053 /* Emit code to perform further access permissions checks at
7054 * runtime; this may result in an exception.
7056 TCGv_ptr tmpptr;
7057 TCGv_i32 tcg_syn;
7058 uint32_t syndrome;
7060 /* Note that since we are an implementation which takes an
7061 * exception on a trapped conditional instruction only if the
7062 * instruction passes its condition code check, we can take
7063 * advantage of the clause in the ARM ARM that allows us to set
7064 * the COND field in the instruction to 0xE in all cases.
7065 * We could fish the actual condition out of the insn (ARM)
7066 * or the condexec bits (Thumb) but it isn't necessary.
7068 switch (cpnum) {
7069 case 14:
7070 if (is64) {
7071 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7072 isread, s->thumb);
7073 } else {
7074 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7075 rt, isread, s->thumb);
7077 break;
7078 case 15:
7079 if (is64) {
7080 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7081 isread, s->thumb);
7082 } else {
7083 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7084 rt, isread, s->thumb);
7086 break;
7087 default:
7088 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7089 * so this can only happen if this is an ARMv7 or earlier CPU,
7090 * in which case the syndrome information won't actually be
7091 * guest visible.
7093 assert(!arm_feature(env, ARM_FEATURE_V8));
7094 syndrome = syn_uncategorized();
7095 break;
7098 gen_set_pc_im(s, s->pc);
7099 tmpptr = tcg_const_ptr(ri);
7100 tcg_syn = tcg_const_i32(syndrome);
7101 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
7102 tcg_temp_free_ptr(tmpptr);
7103 tcg_temp_free_i32(tcg_syn);
7106 /* Handle special cases first */
7107 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7108 case ARM_CP_NOP:
7109 return 0;
7110 case ARM_CP_WFI:
7111 if (isread) {
7112 return 1;
7114 gen_set_pc_im(s, s->pc);
7115 s->is_jmp = DISAS_WFI;
7116 return 0;
7117 default:
7118 break;
7121 if (use_icount && (ri->type & ARM_CP_IO)) {
7122 gen_io_start();
7125 if (isread) {
7126 /* Read */
7127 if (is64) {
7128 TCGv_i64 tmp64;
7129 TCGv_i32 tmp;
7130 if (ri->type & ARM_CP_CONST) {
7131 tmp64 = tcg_const_i64(ri->resetvalue);
7132 } else if (ri->readfn) {
7133 TCGv_ptr tmpptr;
7134 tmp64 = tcg_temp_new_i64();
7135 tmpptr = tcg_const_ptr(ri);
7136 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7137 tcg_temp_free_ptr(tmpptr);
7138 } else {
7139 tmp64 = tcg_temp_new_i64();
7140 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7142 tmp = tcg_temp_new_i32();
7143 tcg_gen_trunc_i64_i32(tmp, tmp64);
7144 store_reg(s, rt, tmp);
7145 tcg_gen_shri_i64(tmp64, tmp64, 32);
7146 tmp = tcg_temp_new_i32();
7147 tcg_gen_trunc_i64_i32(tmp, tmp64);
7148 tcg_temp_free_i64(tmp64);
7149 store_reg(s, rt2, tmp);
7150 } else {
7151 TCGv_i32 tmp;
7152 if (ri->type & ARM_CP_CONST) {
7153 tmp = tcg_const_i32(ri->resetvalue);
7154 } else if (ri->readfn) {
7155 TCGv_ptr tmpptr;
7156 tmp = tcg_temp_new_i32();
7157 tmpptr = tcg_const_ptr(ri);
7158 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7159 tcg_temp_free_ptr(tmpptr);
7160 } else {
7161 tmp = load_cpu_offset(ri->fieldoffset);
7163 if (rt == 15) {
7164 /* Destination register of r15 for 32 bit loads sets
7165 * the condition codes from the high 4 bits of the value
7167 gen_set_nzcv(tmp);
7168 tcg_temp_free_i32(tmp);
7169 } else {
7170 store_reg(s, rt, tmp);
7173 } else {
7174 /* Write */
7175 if (ri->type & ARM_CP_CONST) {
7176 /* If not forbidden by access permissions, treat as WI */
7177 return 0;
7180 if (is64) {
7181 TCGv_i32 tmplo, tmphi;
7182 TCGv_i64 tmp64 = tcg_temp_new_i64();
7183 tmplo = load_reg(s, rt);
7184 tmphi = load_reg(s, rt2);
7185 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7186 tcg_temp_free_i32(tmplo);
7187 tcg_temp_free_i32(tmphi);
7188 if (ri->writefn) {
7189 TCGv_ptr tmpptr = tcg_const_ptr(ri);
7190 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7191 tcg_temp_free_ptr(tmpptr);
7192 } else {
7193 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7195 tcg_temp_free_i64(tmp64);
7196 } else {
7197 if (ri->writefn) {
7198 TCGv_i32 tmp;
7199 TCGv_ptr tmpptr;
7200 tmp = load_reg(s, rt);
7201 tmpptr = tcg_const_ptr(ri);
7202 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7203 tcg_temp_free_ptr(tmpptr);
7204 tcg_temp_free_i32(tmp);
7205 } else {
7206 TCGv_i32 tmp = load_reg(s, rt);
7207 store_cpu_offset(tmp, ri->fieldoffset);
7212 if (use_icount && (ri->type & ARM_CP_IO)) {
7213 /* I/O operations must end the TB here (whether read or write) */
7214 gen_io_end();
7215 gen_lookup_tb(s);
7216 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
7217 /* We default to ending the TB on a coprocessor register write,
7218 * but allow this to be suppressed by the register definition
7219 * (usually only necessary to work around guest bugs).
7221 gen_lookup_tb(s);
7224 return 0;
7227 /* Unknown register; this might be a guest error or a QEMU
7228 * unimplemented feature.
7230 if (is64) {
7231 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7232 "64 bit system register cp:%d opc1: %d crm:%d\n",
7233 isread ? "read" : "write", cpnum, opc1, crm);
7234 } else {
7235 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7236 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d\n",
7237 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2);
7240 return 1;
7244 /* Store a 64-bit value to a register pair. Clobbers val. */
7245 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
7247 TCGv_i32 tmp;
7248 tmp = tcg_temp_new_i32();
7249 tcg_gen_trunc_i64_i32(tmp, val);
7250 store_reg(s, rlow, tmp);
7251 tmp = tcg_temp_new_i32();
7252 tcg_gen_shri_i64(val, val, 32);
7253 tcg_gen_trunc_i64_i32(tmp, val);
7254 store_reg(s, rhigh, tmp);
7257 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
7258 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
7260 TCGv_i64 tmp;
7261 TCGv_i32 tmp2;
7263 /* Load value and extend to 64 bits. */
7264 tmp = tcg_temp_new_i64();
7265 tmp2 = load_reg(s, rlow);
7266 tcg_gen_extu_i32_i64(tmp, tmp2);
7267 tcg_temp_free_i32(tmp2);
7268 tcg_gen_add_i64(val, val, tmp);
7269 tcg_temp_free_i64(tmp);
7272 /* load and add a 64-bit value from a register pair. */
7273 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
7275 TCGv_i64 tmp;
7276 TCGv_i32 tmpl;
7277 TCGv_i32 tmph;
7279 /* Load 64-bit value rd:rn. */
7280 tmpl = load_reg(s, rlow);
7281 tmph = load_reg(s, rhigh);
7282 tmp = tcg_temp_new_i64();
7283 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7284 tcg_temp_free_i32(tmpl);
7285 tcg_temp_free_i32(tmph);
7286 tcg_gen_add_i64(val, val, tmp);
7287 tcg_temp_free_i64(tmp);
7290 /* Set N and Z flags from hi|lo. */
7291 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
7293 tcg_gen_mov_i32(cpu_NF, hi);
7294 tcg_gen_or_i32(cpu_ZF, lo, hi);
7297 /* Load/Store exclusive instructions are implemented by remembering
7298 the value/address loaded, and seeing if these are the same
7299 when the store is performed. This should be sufficient to implement
7300 the architecturally mandated semantics, and avoids having to monitor
7301 regular stores.
7303 In system emulation mode only one CPU will be running at once, so
7304 this sequence is effectively atomic. In user emulation mode we
7305 throw an exception and handle the atomic operation elsewhere. */
7306 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
7307 TCGv_i32 addr, int size)
7309 TCGv_i32 tmp = tcg_temp_new_i32();
7311 s->is_ldex = true;
7313 switch (size) {
7314 case 0:
7315 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
7316 break;
7317 case 1:
7318 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
7319 break;
7320 case 2:
7321 case 3:
7322 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7323 break;
7324 default:
7325 abort();
7328 if (size == 3) {
7329 TCGv_i32 tmp2 = tcg_temp_new_i32();
7330 TCGv_i32 tmp3 = tcg_temp_new_i32();
7332 tcg_gen_addi_i32(tmp2, addr, 4);
7333 gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
7334 tcg_temp_free_i32(tmp2);
7335 tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
7336 store_reg(s, rt2, tmp3);
7337 } else {
7338 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
7341 store_reg(s, rt, tmp);
7342 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
7345 static void gen_clrex(DisasContext *s)
7347 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7350 #ifdef CONFIG_USER_ONLY
7351 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7352 TCGv_i32 addr, int size)
7354 tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
7355 tcg_gen_movi_i32(cpu_exclusive_info,
7356 size | (rd << 4) | (rt << 8) | (rt2 << 12));
7357 gen_exception_internal_insn(s, 4, EXCP_STREX);
7359 #else
7360 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7361 TCGv_i32 addr, int size)
7363 TCGv_i32 tmp;
7364 TCGv_i64 val64, extaddr;
7365 int done_label;
7366 int fail_label;
7368 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7369 [addr] = {Rt};
7370 {Rd} = 0;
7371 } else {
7372 {Rd} = 1;
7373 } */
7374 fail_label = gen_new_label();
7375 done_label = gen_new_label();
7376 extaddr = tcg_temp_new_i64();
7377 tcg_gen_extu_i32_i64(extaddr, addr);
7378 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7379 tcg_temp_free_i64(extaddr);
7381 tmp = tcg_temp_new_i32();
7382 switch (size) {
7383 case 0:
7384 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
7385 break;
7386 case 1:
7387 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
7388 break;
7389 case 2:
7390 case 3:
7391 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7392 break;
7393 default:
7394 abort();
7397 val64 = tcg_temp_new_i64();
7398 if (size == 3) {
7399 TCGv_i32 tmp2 = tcg_temp_new_i32();
7400 TCGv_i32 tmp3 = tcg_temp_new_i32();
7401 tcg_gen_addi_i32(tmp2, addr, 4);
7402 gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
7403 tcg_temp_free_i32(tmp2);
7404 tcg_gen_concat_i32_i64(val64, tmp, tmp3);
7405 tcg_temp_free_i32(tmp3);
7406 } else {
7407 tcg_gen_extu_i32_i64(val64, tmp);
7409 tcg_temp_free_i32(tmp);
7411 tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
7412 tcg_temp_free_i64(val64);
7414 tmp = load_reg(s, rt);
7415 switch (size) {
7416 case 0:
7417 gen_aa32_st8(tmp, addr, get_mem_index(s));
7418 break;
7419 case 1:
7420 gen_aa32_st16(tmp, addr, get_mem_index(s));
7421 break;
7422 case 2:
7423 case 3:
7424 gen_aa32_st32(tmp, addr, get_mem_index(s));
7425 break;
7426 default:
7427 abort();
7429 tcg_temp_free_i32(tmp);
7430 if (size == 3) {
7431 tcg_gen_addi_i32(addr, addr, 4);
7432 tmp = load_reg(s, rt2);
7433 gen_aa32_st32(tmp, addr, get_mem_index(s));
7434 tcg_temp_free_i32(tmp);
7436 tcg_gen_movi_i32(cpu_R[rd], 0);
7437 tcg_gen_br(done_label);
7438 gen_set_label(fail_label);
7439 tcg_gen_movi_i32(cpu_R[rd], 1);
7440 gen_set_label(done_label);
7441 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7443 #endif
7445 /* gen_srs:
7446 * @env: CPUARMState
7447 * @s: DisasContext
7448 * @mode: mode field from insn (which stack to store to)
7449 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7450 * @writeback: true if writeback bit set
7452 * Generate code for the SRS (Store Return State) insn.
7454 static void gen_srs(DisasContext *s,
7455 uint32_t mode, uint32_t amode, bool writeback)
7457 int32_t offset;
7458 TCGv_i32 addr = tcg_temp_new_i32();
7459 TCGv_i32 tmp = tcg_const_i32(mode);
7460 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7461 tcg_temp_free_i32(tmp);
7462 switch (amode) {
7463 case 0: /* DA */
7464 offset = -4;
7465 break;
7466 case 1: /* IA */
7467 offset = 0;
7468 break;
7469 case 2: /* DB */
7470 offset = -8;
7471 break;
7472 case 3: /* IB */
7473 offset = 4;
7474 break;
7475 default:
7476 abort();
7478 tcg_gen_addi_i32(addr, addr, offset);
7479 tmp = load_reg(s, 14);
7480 gen_aa32_st32(tmp, addr, get_mem_index(s));
7481 tcg_temp_free_i32(tmp);
7482 tmp = load_cpu_field(spsr);
7483 tcg_gen_addi_i32(addr, addr, 4);
7484 gen_aa32_st32(tmp, addr, get_mem_index(s));
7485 tcg_temp_free_i32(tmp);
7486 if (writeback) {
7487 switch (amode) {
7488 case 0:
7489 offset = -8;
7490 break;
7491 case 1:
7492 offset = 4;
7493 break;
7494 case 2:
7495 offset = -4;
7496 break;
7497 case 3:
7498 offset = 0;
7499 break;
7500 default:
7501 abort();
7503 tcg_gen_addi_i32(addr, addr, offset);
7504 tmp = tcg_const_i32(mode);
7505 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7506 tcg_temp_free_i32(tmp);
7508 tcg_temp_free_i32(addr);
7511 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
7513 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
7514 TCGv_i32 tmp;
7515 TCGv_i32 tmp2;
7516 TCGv_i32 tmp3;
7517 TCGv_i32 addr;
7518 TCGv_i64 tmp64;
7520 insn = arm_ldl_code(env, s->pc, s->bswap_code);
7521 s->pc += 4;
7523 /* M variants do not implement ARM mode. */
7524 if (IS_M(env))
7525 goto illegal_op;
7526 cond = insn >> 28;
7527 if (cond == 0xf){
7528 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
7529 * choose to UNDEF. In ARMv5 and above the space is used
7530 * for miscellaneous unconditional instructions.
7532 ARCH(5);
7534 /* Unconditional instructions. */
7535 if (((insn >> 25) & 7) == 1) {
7536 /* NEON Data processing. */
7537 if (!arm_feature(env, ARM_FEATURE_NEON))
7538 goto illegal_op;
7540 if (disas_neon_data_insn(env, s, insn))
7541 goto illegal_op;
7542 return;
7544 if ((insn & 0x0f100000) == 0x04000000) {
7545 /* NEON load/store. */
7546 if (!arm_feature(env, ARM_FEATURE_NEON))
7547 goto illegal_op;
7549 if (disas_neon_ls_insn(env, s, insn))
7550 goto illegal_op;
7551 return;
7553 if ((insn & 0x0f000e10) == 0x0e000a00) {
7554 /* VFP. */
7555 if (disas_vfp_insn(env, s, insn)) {
7556 goto illegal_op;
7558 return;
7560 if (((insn & 0x0f30f000) == 0x0510f000) ||
7561 ((insn & 0x0f30f010) == 0x0710f000)) {
7562 if ((insn & (1 << 22)) == 0) {
7563 /* PLDW; v7MP */
7564 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7565 goto illegal_op;
7568 /* Otherwise PLD; v5TE+ */
7569 ARCH(5TE);
7570 return;
7572 if (((insn & 0x0f70f000) == 0x0450f000) ||
7573 ((insn & 0x0f70f010) == 0x0650f000)) {
7574 ARCH(7);
7575 return; /* PLI; V7 */
7577 if (((insn & 0x0f700000) == 0x04100000) ||
7578 ((insn & 0x0f700010) == 0x06100000)) {
7579 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7580 goto illegal_op;
7582 return; /* v7MP: Unallocated memory hint: must NOP */
7585 if ((insn & 0x0ffffdff) == 0x01010000) {
7586 ARCH(6);
7587 /* setend */
7588 if (((insn >> 9) & 1) != s->bswap_code) {
7589 /* Dynamic endianness switching not implemented. */
7590 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
7591 goto illegal_op;
7593 return;
7594 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7595 switch ((insn >> 4) & 0xf) {
7596 case 1: /* clrex */
7597 ARCH(6K);
7598 gen_clrex(s);
7599 return;
7600 case 4: /* dsb */
7601 case 5: /* dmb */
7602 case 6: /* isb */
7603 ARCH(7);
7604 /* We don't emulate caches so these are a no-op. */
7605 return;
7606 default:
7607 goto illegal_op;
7609 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7610 /* srs */
7611 if (IS_USER(s)) {
7612 goto illegal_op;
7614 ARCH(6);
7615 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
7616 return;
7617 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
7618 /* rfe */
7619 int32_t offset;
7620 if (IS_USER(s))
7621 goto illegal_op;
7622 ARCH(6);
7623 rn = (insn >> 16) & 0xf;
7624 addr = load_reg(s, rn);
7625 i = (insn >> 23) & 3;
7626 switch (i) {
7627 case 0: offset = -4; break; /* DA */
7628 case 1: offset = 0; break; /* IA */
7629 case 2: offset = -8; break; /* DB */
7630 case 3: offset = 4; break; /* IB */
7631 default: abort();
7633 if (offset)
7634 tcg_gen_addi_i32(addr, addr, offset);
7635 /* Load PC into tmp and CPSR into tmp2. */
7636 tmp = tcg_temp_new_i32();
7637 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7638 tcg_gen_addi_i32(addr, addr, 4);
7639 tmp2 = tcg_temp_new_i32();
7640 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
7641 if (insn & (1 << 21)) {
7642 /* Base writeback. */
7643 switch (i) {
7644 case 0: offset = -8; break;
7645 case 1: offset = 4; break;
7646 case 2: offset = -4; break;
7647 case 3: offset = 0; break;
7648 default: abort();
7650 if (offset)
7651 tcg_gen_addi_i32(addr, addr, offset);
7652 store_reg(s, rn, addr);
7653 } else {
7654 tcg_temp_free_i32(addr);
7656 gen_rfe(s, tmp, tmp2);
7657 return;
7658 } else if ((insn & 0x0e000000) == 0x0a000000) {
7659 /* branch link and change to thumb (blx <offset>) */
7660 int32_t offset;
7662 val = (uint32_t)s->pc;
7663 tmp = tcg_temp_new_i32();
7664 tcg_gen_movi_i32(tmp, val);
7665 store_reg(s, 14, tmp);
7666 /* Sign-extend the 24-bit offset */
7667 offset = (((int32_t)insn) << 8) >> 8;
7668 /* offset * 4 + bit24 * 2 + (thumb bit) */
7669 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7670 /* pipeline offset */
7671 val += 4;
7672 /* protected by ARCH(5); above, near the start of uncond block */
7673 gen_bx_im(s, val);
7674 return;
7675 } else if ((insn & 0x0e000f00) == 0x0c000100) {
7676 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7677 /* iWMMXt register transfer. */
7678 if (env->cp15.c15_cpar & (1 << 1))
7679 if (!disas_iwmmxt_insn(env, s, insn))
7680 return;
7682 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7683 /* Coprocessor double register transfer. */
7684 ARCH(5TE);
7685 } else if ((insn & 0x0f000010) == 0x0e000010) {
7686 /* Additional coprocessor register transfer. */
7687 } else if ((insn & 0x0ff10020) == 0x01000000) {
7688 uint32_t mask;
7689 uint32_t val;
7690 /* cps (privileged) */
7691 if (IS_USER(s))
7692 return;
7693 mask = val = 0;
7694 if (insn & (1 << 19)) {
7695 if (insn & (1 << 8))
7696 mask |= CPSR_A;
7697 if (insn & (1 << 7))
7698 mask |= CPSR_I;
7699 if (insn & (1 << 6))
7700 mask |= CPSR_F;
7701 if (insn & (1 << 18))
7702 val |= mask;
7704 if (insn & (1 << 17)) {
7705 mask |= CPSR_M;
7706 val |= (insn & 0x1f);
7708 if (mask) {
7709 gen_set_psr_im(s, mask, 0, val);
7711 return;
7713 goto illegal_op;
7715 if (cond != 0xe) {
7716 /* if not always execute, we generate a conditional jump to
7717 next instruction */
7718 s->condlabel = gen_new_label();
7719 arm_gen_test_cc(cond ^ 1, s->condlabel);
7720 s->condjmp = 1;
7722 if ((insn & 0x0f900000) == 0x03000000) {
7723 if ((insn & (1 << 21)) == 0) {
7724 ARCH(6T2);
7725 rd = (insn >> 12) & 0xf;
7726 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7727 if ((insn & (1 << 22)) == 0) {
7728 /* MOVW */
7729 tmp = tcg_temp_new_i32();
7730 tcg_gen_movi_i32(tmp, val);
7731 } else {
7732 /* MOVT */
7733 tmp = load_reg(s, rd);
7734 tcg_gen_ext16u_i32(tmp, tmp);
7735 tcg_gen_ori_i32(tmp, tmp, val << 16);
7737 store_reg(s, rd, tmp);
7738 } else {
7739 if (((insn >> 12) & 0xf) != 0xf)
7740 goto illegal_op;
7741 if (((insn >> 16) & 0xf) == 0) {
7742 gen_nop_hint(s, insn & 0xff);
7743 } else {
7744 /* CPSR = immediate */
7745 val = insn & 0xff;
7746 shift = ((insn >> 8) & 0xf) * 2;
7747 if (shift)
7748 val = (val >> shift) | (val << (32 - shift));
7749 i = ((insn & (1 << 22)) != 0);
7750 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
7751 goto illegal_op;
7754 } else if ((insn & 0x0f900000) == 0x01000000
7755 && (insn & 0x00000090) != 0x00000090) {
7756 /* miscellaneous instructions */
7757 op1 = (insn >> 21) & 3;
7758 sh = (insn >> 4) & 0xf;
7759 rm = insn & 0xf;
7760 switch (sh) {
7761 case 0x0: /* move program status register */
7762 if (op1 & 1) {
7763 /* PSR = reg */
7764 tmp = load_reg(s, rm);
7765 i = ((op1 & 2) != 0);
7766 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
7767 goto illegal_op;
7768 } else {
7769 /* reg = PSR */
7770 rd = (insn >> 12) & 0xf;
7771 if (op1 & 2) {
7772 if (IS_USER(s))
7773 goto illegal_op;
7774 tmp = load_cpu_field(spsr);
7775 } else {
7776 tmp = tcg_temp_new_i32();
7777 gen_helper_cpsr_read(tmp, cpu_env);
7779 store_reg(s, rd, tmp);
7781 break;
7782 case 0x1:
7783 if (op1 == 1) {
7784 /* branch/exchange thumb (bx). */
7785 ARCH(4T);
7786 tmp = load_reg(s, rm);
7787 gen_bx(s, tmp);
7788 } else if (op1 == 3) {
7789 /* clz */
7790 ARCH(5);
7791 rd = (insn >> 12) & 0xf;
7792 tmp = load_reg(s, rm);
7793 gen_helper_clz(tmp, tmp);
7794 store_reg(s, rd, tmp);
7795 } else {
7796 goto illegal_op;
7798 break;
7799 case 0x2:
7800 if (op1 == 1) {
7801 ARCH(5J); /* bxj */
7802 /* Trivial implementation equivalent to bx. */
7803 tmp = load_reg(s, rm);
7804 gen_bx(s, tmp);
7805 } else {
7806 goto illegal_op;
7808 break;
7809 case 0x3:
7810 if (op1 != 1)
7811 goto illegal_op;
7813 ARCH(5);
7814 /* branch link/exchange thumb (blx) */
7815 tmp = load_reg(s, rm);
7816 tmp2 = tcg_temp_new_i32();
7817 tcg_gen_movi_i32(tmp2, s->pc);
7818 store_reg(s, 14, tmp2);
7819 gen_bx(s, tmp);
7820 break;
7821 case 0x4:
7823 /* crc32/crc32c */
7824 uint32_t c = extract32(insn, 8, 4);
7826 /* Check this CPU supports ARMv8 CRC instructions.
7827 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
7828 * Bits 8, 10 and 11 should be zero.
7830 if (!arm_feature(env, ARM_FEATURE_CRC) || op1 == 0x3 ||
7831 (c & 0xd) != 0) {
7832 goto illegal_op;
7835 rn = extract32(insn, 16, 4);
7836 rd = extract32(insn, 12, 4);
7838 tmp = load_reg(s, rn);
7839 tmp2 = load_reg(s, rm);
7840 if (op1 == 0) {
7841 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
7842 } else if (op1 == 1) {
7843 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
7845 tmp3 = tcg_const_i32(1 << op1);
7846 if (c & 0x2) {
7847 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
7848 } else {
7849 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
7851 tcg_temp_free_i32(tmp2);
7852 tcg_temp_free_i32(tmp3);
7853 store_reg(s, rd, tmp);
7854 break;
7856 case 0x5: /* saturating add/subtract */
7857 ARCH(5TE);
7858 rd = (insn >> 12) & 0xf;
7859 rn = (insn >> 16) & 0xf;
7860 tmp = load_reg(s, rm);
7861 tmp2 = load_reg(s, rn);
7862 if (op1 & 2)
7863 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
7864 if (op1 & 1)
7865 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
7866 else
7867 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7868 tcg_temp_free_i32(tmp2);
7869 store_reg(s, rd, tmp);
7870 break;
7871 case 7:
7873 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
7874 /* SMC instruction (op1 == 3)
7875 and undefined instructions (op1 == 0 || op1 == 2)
7876 will trap */
7877 if (op1 != 1) {
7878 goto illegal_op;
7880 /* bkpt */
7881 ARCH(5);
7882 gen_exception_insn(s, 4, EXCP_BKPT, syn_aa32_bkpt(imm16, false));
7883 break;
7885 case 0x8: /* signed multiply */
7886 case 0xa:
7887 case 0xc:
7888 case 0xe:
7889 ARCH(5TE);
7890 rs = (insn >> 8) & 0xf;
7891 rn = (insn >> 12) & 0xf;
7892 rd = (insn >> 16) & 0xf;
7893 if (op1 == 1) {
7894 /* (32 * 16) >> 16 */
7895 tmp = load_reg(s, rm);
7896 tmp2 = load_reg(s, rs);
7897 if (sh & 4)
7898 tcg_gen_sari_i32(tmp2, tmp2, 16);
7899 else
7900 gen_sxth(tmp2);
7901 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7902 tcg_gen_shri_i64(tmp64, tmp64, 16);
7903 tmp = tcg_temp_new_i32();
7904 tcg_gen_trunc_i64_i32(tmp, tmp64);
7905 tcg_temp_free_i64(tmp64);
7906 if ((sh & 2) == 0) {
7907 tmp2 = load_reg(s, rn);
7908 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7909 tcg_temp_free_i32(tmp2);
7911 store_reg(s, rd, tmp);
7912 } else {
7913 /* 16 * 16 */
7914 tmp = load_reg(s, rm);
7915 tmp2 = load_reg(s, rs);
7916 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7917 tcg_temp_free_i32(tmp2);
7918 if (op1 == 2) {
7919 tmp64 = tcg_temp_new_i64();
7920 tcg_gen_ext_i32_i64(tmp64, tmp);
7921 tcg_temp_free_i32(tmp);
7922 gen_addq(s, tmp64, rn, rd);
7923 gen_storeq_reg(s, rn, rd, tmp64);
7924 tcg_temp_free_i64(tmp64);
7925 } else {
7926 if (op1 == 0) {
7927 tmp2 = load_reg(s, rn);
7928 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7929 tcg_temp_free_i32(tmp2);
7931 store_reg(s, rd, tmp);
7934 break;
7935 default:
7936 goto illegal_op;
7938 } else if (((insn & 0x0e000000) == 0 &&
7939 (insn & 0x00000090) != 0x90) ||
7940 ((insn & 0x0e000000) == (1 << 25))) {
7941 int set_cc, logic_cc, shiftop;
7943 op1 = (insn >> 21) & 0xf;
7944 set_cc = (insn >> 20) & 1;
7945 logic_cc = table_logic_cc[op1] & set_cc;
7947 /* data processing instruction */
7948 if (insn & (1 << 25)) {
7949 /* immediate operand */
7950 val = insn & 0xff;
7951 shift = ((insn >> 8) & 0xf) * 2;
7952 if (shift) {
7953 val = (val >> shift) | (val << (32 - shift));
7955 tmp2 = tcg_temp_new_i32();
7956 tcg_gen_movi_i32(tmp2, val);
7957 if (logic_cc && shift) {
7958 gen_set_CF_bit31(tmp2);
7960 } else {
7961 /* register */
7962 rm = (insn) & 0xf;
7963 tmp2 = load_reg(s, rm);
7964 shiftop = (insn >> 5) & 3;
7965 if (!(insn & (1 << 4))) {
7966 shift = (insn >> 7) & 0x1f;
7967 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7968 } else {
7969 rs = (insn >> 8) & 0xf;
7970 tmp = load_reg(s, rs);
7971 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7974 if (op1 != 0x0f && op1 != 0x0d) {
7975 rn = (insn >> 16) & 0xf;
7976 tmp = load_reg(s, rn);
7977 } else {
7978 TCGV_UNUSED_I32(tmp);
7980 rd = (insn >> 12) & 0xf;
7981 switch(op1) {
7982 case 0x00:
7983 tcg_gen_and_i32(tmp, tmp, tmp2);
7984 if (logic_cc) {
7985 gen_logic_CC(tmp);
7987 store_reg_bx(env, s, rd, tmp);
7988 break;
7989 case 0x01:
7990 tcg_gen_xor_i32(tmp, tmp, tmp2);
7991 if (logic_cc) {
7992 gen_logic_CC(tmp);
7994 store_reg_bx(env, s, rd, tmp);
7995 break;
7996 case 0x02:
7997 if (set_cc && rd == 15) {
7998 /* SUBS r15, ... is used for exception return. */
7999 if (IS_USER(s)) {
8000 goto illegal_op;
8002 gen_sub_CC(tmp, tmp, tmp2);
8003 gen_exception_return(s, tmp);
8004 } else {
8005 if (set_cc) {
8006 gen_sub_CC(tmp, tmp, tmp2);
8007 } else {
8008 tcg_gen_sub_i32(tmp, tmp, tmp2);
8010 store_reg_bx(env, s, rd, tmp);
8012 break;
8013 case 0x03:
8014 if (set_cc) {
8015 gen_sub_CC(tmp, tmp2, tmp);
8016 } else {
8017 tcg_gen_sub_i32(tmp, tmp2, tmp);
8019 store_reg_bx(env, s, rd, tmp);
8020 break;
8021 case 0x04:
8022 if (set_cc) {
8023 gen_add_CC(tmp, tmp, tmp2);
8024 } else {
8025 tcg_gen_add_i32(tmp, tmp, tmp2);
8027 store_reg_bx(env, s, rd, tmp);
8028 break;
8029 case 0x05:
8030 if (set_cc) {
8031 gen_adc_CC(tmp, tmp, tmp2);
8032 } else {
8033 gen_add_carry(tmp, tmp, tmp2);
8035 store_reg_bx(env, s, rd, tmp);
8036 break;
8037 case 0x06:
8038 if (set_cc) {
8039 gen_sbc_CC(tmp, tmp, tmp2);
8040 } else {
8041 gen_sub_carry(tmp, tmp, tmp2);
8043 store_reg_bx(env, s, rd, tmp);
8044 break;
8045 case 0x07:
8046 if (set_cc) {
8047 gen_sbc_CC(tmp, tmp2, tmp);
8048 } else {
8049 gen_sub_carry(tmp, tmp2, tmp);
8051 store_reg_bx(env, s, rd, tmp);
8052 break;
8053 case 0x08:
8054 if (set_cc) {
8055 tcg_gen_and_i32(tmp, tmp, tmp2);
8056 gen_logic_CC(tmp);
8058 tcg_temp_free_i32(tmp);
8059 break;
8060 case 0x09:
8061 if (set_cc) {
8062 tcg_gen_xor_i32(tmp, tmp, tmp2);
8063 gen_logic_CC(tmp);
8065 tcg_temp_free_i32(tmp);
8066 break;
8067 case 0x0a:
8068 if (set_cc) {
8069 gen_sub_CC(tmp, tmp, tmp2);
8071 tcg_temp_free_i32(tmp);
8072 break;
8073 case 0x0b:
8074 if (set_cc) {
8075 gen_add_CC(tmp, tmp, tmp2);
8077 tcg_temp_free_i32(tmp);
8078 break;
8079 case 0x0c:
8080 tcg_gen_or_i32(tmp, tmp, tmp2);
8081 if (logic_cc) {
8082 gen_logic_CC(tmp);
8084 store_reg_bx(env, s, rd, tmp);
8085 break;
8086 case 0x0d:
8087 if (logic_cc && rd == 15) {
8088 /* MOVS r15, ... is used for exception return. */
8089 if (IS_USER(s)) {
8090 goto illegal_op;
8092 gen_exception_return(s, tmp2);
8093 } else {
8094 if (logic_cc) {
8095 gen_logic_CC(tmp2);
8097 store_reg_bx(env, s, rd, tmp2);
8099 break;
8100 case 0x0e:
8101 tcg_gen_andc_i32(tmp, tmp, tmp2);
8102 if (logic_cc) {
8103 gen_logic_CC(tmp);
8105 store_reg_bx(env, s, rd, tmp);
8106 break;
8107 default:
8108 case 0x0f:
8109 tcg_gen_not_i32(tmp2, tmp2);
8110 if (logic_cc) {
8111 gen_logic_CC(tmp2);
8113 store_reg_bx(env, s, rd, tmp2);
8114 break;
8116 if (op1 != 0x0f && op1 != 0x0d) {
8117 tcg_temp_free_i32(tmp2);
8119 } else {
8120 /* other instructions */
8121 op1 = (insn >> 24) & 0xf;
8122 switch(op1) {
8123 case 0x0:
8124 case 0x1:
8125 /* multiplies, extra load/stores */
8126 sh = (insn >> 5) & 3;
8127 if (sh == 0) {
8128 if (op1 == 0x0) {
8129 rd = (insn >> 16) & 0xf;
8130 rn = (insn >> 12) & 0xf;
8131 rs = (insn >> 8) & 0xf;
8132 rm = (insn) & 0xf;
8133 op1 = (insn >> 20) & 0xf;
8134 switch (op1) {
8135 case 0: case 1: case 2: case 3: case 6:
8136 /* 32 bit mul */
8137 tmp = load_reg(s, rs);
8138 tmp2 = load_reg(s, rm);
8139 tcg_gen_mul_i32(tmp, tmp, tmp2);
8140 tcg_temp_free_i32(tmp2);
8141 if (insn & (1 << 22)) {
8142 /* Subtract (mls) */
8143 ARCH(6T2);
8144 tmp2 = load_reg(s, rn);
8145 tcg_gen_sub_i32(tmp, tmp2, tmp);
8146 tcg_temp_free_i32(tmp2);
8147 } else if (insn & (1 << 21)) {
8148 /* Add */
8149 tmp2 = load_reg(s, rn);
8150 tcg_gen_add_i32(tmp, tmp, tmp2);
8151 tcg_temp_free_i32(tmp2);
8153 if (insn & (1 << 20))
8154 gen_logic_CC(tmp);
8155 store_reg(s, rd, tmp);
8156 break;
8157 case 4:
8158 /* 64 bit mul double accumulate (UMAAL) */
8159 ARCH(6);
8160 tmp = load_reg(s, rs);
8161 tmp2 = load_reg(s, rm);
8162 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8163 gen_addq_lo(s, tmp64, rn);
8164 gen_addq_lo(s, tmp64, rd);
8165 gen_storeq_reg(s, rn, rd, tmp64);
8166 tcg_temp_free_i64(tmp64);
8167 break;
8168 case 8: case 9: case 10: case 11:
8169 case 12: case 13: case 14: case 15:
8170 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
8171 tmp = load_reg(s, rs);
8172 tmp2 = load_reg(s, rm);
8173 if (insn & (1 << 22)) {
8174 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8175 } else {
8176 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8178 if (insn & (1 << 21)) { /* mult accumulate */
8179 TCGv_i32 al = load_reg(s, rn);
8180 TCGv_i32 ah = load_reg(s, rd);
8181 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
8182 tcg_temp_free_i32(al);
8183 tcg_temp_free_i32(ah);
8185 if (insn & (1 << 20)) {
8186 gen_logicq_cc(tmp, tmp2);
8188 store_reg(s, rn, tmp);
8189 store_reg(s, rd, tmp2);
8190 break;
8191 default:
8192 goto illegal_op;
8194 } else {
8195 rn = (insn >> 16) & 0xf;
8196 rd = (insn >> 12) & 0xf;
8197 if (insn & (1 << 23)) {
8198 /* load/store exclusive */
8199 int op2 = (insn >> 8) & 3;
8200 op1 = (insn >> 21) & 0x3;
8202 switch (op2) {
8203 case 0: /* lda/stl */
8204 if (op1 == 1) {
8205 goto illegal_op;
8207 ARCH(8);
8208 break;
8209 case 1: /* reserved */
8210 goto illegal_op;
8211 case 2: /* ldaex/stlex */
8212 ARCH(8);
8213 break;
8214 case 3: /* ldrex/strex */
8215 if (op1) {
8216 ARCH(6K);
8217 } else {
8218 ARCH(6);
8220 break;
8223 addr = tcg_temp_local_new_i32();
8224 load_reg_var(s, addr, rn);
8226 /* Since the emulation does not have barriers,
8227 the acquire/release semantics need no special
8228 handling */
8229 if (op2 == 0) {
8230 if (insn & (1 << 20)) {
8231 tmp = tcg_temp_new_i32();
8232 switch (op1) {
8233 case 0: /* lda */
8234 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8235 break;
8236 case 2: /* ldab */
8237 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
8238 break;
8239 case 3: /* ldah */
8240 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
8241 break;
8242 default:
8243 abort();
8245 store_reg(s, rd, tmp);
8246 } else {
8247 rm = insn & 0xf;
8248 tmp = load_reg(s, rm);
8249 switch (op1) {
8250 case 0: /* stl */
8251 gen_aa32_st32(tmp, addr, get_mem_index(s));
8252 break;
8253 case 2: /* stlb */
8254 gen_aa32_st8(tmp, addr, get_mem_index(s));
8255 break;
8256 case 3: /* stlh */
8257 gen_aa32_st16(tmp, addr, get_mem_index(s));
8258 break;
8259 default:
8260 abort();
8262 tcg_temp_free_i32(tmp);
8264 } else if (insn & (1 << 20)) {
8265 switch (op1) {
8266 case 0: /* ldrex */
8267 gen_load_exclusive(s, rd, 15, addr, 2);
8268 break;
8269 case 1: /* ldrexd */
8270 gen_load_exclusive(s, rd, rd + 1, addr, 3);
8271 break;
8272 case 2: /* ldrexb */
8273 gen_load_exclusive(s, rd, 15, addr, 0);
8274 break;
8275 case 3: /* ldrexh */
8276 gen_load_exclusive(s, rd, 15, addr, 1);
8277 break;
8278 default:
8279 abort();
8281 } else {
8282 rm = insn & 0xf;
8283 switch (op1) {
8284 case 0: /* strex */
8285 gen_store_exclusive(s, rd, rm, 15, addr, 2);
8286 break;
8287 case 1: /* strexd */
8288 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
8289 break;
8290 case 2: /* strexb */
8291 gen_store_exclusive(s, rd, rm, 15, addr, 0);
8292 break;
8293 case 3: /* strexh */
8294 gen_store_exclusive(s, rd, rm, 15, addr, 1);
8295 break;
8296 default:
8297 abort();
8300 tcg_temp_free_i32(addr);
8301 } else {
8302 /* SWP instruction */
8303 rm = (insn) & 0xf;
8305 /* ??? This is not really atomic. However we know
8306 we never have multiple CPUs running in parallel,
8307 so it is good enough. */
8308 addr = load_reg(s, rn);
8309 tmp = load_reg(s, rm);
8310 tmp2 = tcg_temp_new_i32();
8311 if (insn & (1 << 22)) {
8312 gen_aa32_ld8u(tmp2, addr, get_mem_index(s));
8313 gen_aa32_st8(tmp, addr, get_mem_index(s));
8314 } else {
8315 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
8316 gen_aa32_st32(tmp, addr, get_mem_index(s));
8318 tcg_temp_free_i32(tmp);
8319 tcg_temp_free_i32(addr);
8320 store_reg(s, rd, tmp2);
8323 } else {
8324 int address_offset;
8325 int load;
8326 /* Misc load/store */
8327 rn = (insn >> 16) & 0xf;
8328 rd = (insn >> 12) & 0xf;
8329 addr = load_reg(s, rn);
8330 if (insn & (1 << 24))
8331 gen_add_datah_offset(s, insn, 0, addr);
8332 address_offset = 0;
8333 if (insn & (1 << 20)) {
8334 /* load */
8335 tmp = tcg_temp_new_i32();
8336 switch(sh) {
8337 case 1:
8338 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
8339 break;
8340 case 2:
8341 gen_aa32_ld8s(tmp, addr, get_mem_index(s));
8342 break;
8343 default:
8344 case 3:
8345 gen_aa32_ld16s(tmp, addr, get_mem_index(s));
8346 break;
8348 load = 1;
8349 } else if (sh & 2) {
8350 ARCH(5TE);
8351 /* doubleword */
8352 if (sh & 1) {
8353 /* store */
8354 tmp = load_reg(s, rd);
8355 gen_aa32_st32(tmp, addr, get_mem_index(s));
8356 tcg_temp_free_i32(tmp);
8357 tcg_gen_addi_i32(addr, addr, 4);
8358 tmp = load_reg(s, rd + 1);
8359 gen_aa32_st32(tmp, addr, get_mem_index(s));
8360 tcg_temp_free_i32(tmp);
8361 load = 0;
8362 } else {
8363 /* load */
8364 tmp = tcg_temp_new_i32();
8365 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8366 store_reg(s, rd, tmp);
8367 tcg_gen_addi_i32(addr, addr, 4);
8368 tmp = tcg_temp_new_i32();
8369 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8370 rd++;
8371 load = 1;
8373 address_offset = -4;
8374 } else {
8375 /* store */
8376 tmp = load_reg(s, rd);
8377 gen_aa32_st16(tmp, addr, get_mem_index(s));
8378 tcg_temp_free_i32(tmp);
8379 load = 0;
8381 /* Perform base writeback before the loaded value to
8382 ensure correct behavior with overlapping index registers.
8383 ldrd with base writeback is is undefined if the
8384 destination and index registers overlap. */
8385 if (!(insn & (1 << 24))) {
8386 gen_add_datah_offset(s, insn, address_offset, addr);
8387 store_reg(s, rn, addr);
8388 } else if (insn & (1 << 21)) {
8389 if (address_offset)
8390 tcg_gen_addi_i32(addr, addr, address_offset);
8391 store_reg(s, rn, addr);
8392 } else {
8393 tcg_temp_free_i32(addr);
8395 if (load) {
8396 /* Complete the load. */
8397 store_reg(s, rd, tmp);
8400 break;
8401 case 0x4:
8402 case 0x5:
8403 goto do_ldst;
8404 case 0x6:
8405 case 0x7:
8406 if (insn & (1 << 4)) {
8407 ARCH(6);
8408 /* Armv6 Media instructions. */
8409 rm = insn & 0xf;
8410 rn = (insn >> 16) & 0xf;
8411 rd = (insn >> 12) & 0xf;
8412 rs = (insn >> 8) & 0xf;
8413 switch ((insn >> 23) & 3) {
8414 case 0: /* Parallel add/subtract. */
8415 op1 = (insn >> 20) & 7;
8416 tmp = load_reg(s, rn);
8417 tmp2 = load_reg(s, rm);
8418 sh = (insn >> 5) & 7;
8419 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8420 goto illegal_op;
8421 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
8422 tcg_temp_free_i32(tmp2);
8423 store_reg(s, rd, tmp);
8424 break;
8425 case 1:
8426 if ((insn & 0x00700020) == 0) {
8427 /* Halfword pack. */
8428 tmp = load_reg(s, rn);
8429 tmp2 = load_reg(s, rm);
8430 shift = (insn >> 7) & 0x1f;
8431 if (insn & (1 << 6)) {
8432 /* pkhtb */
8433 if (shift == 0)
8434 shift = 31;
8435 tcg_gen_sari_i32(tmp2, tmp2, shift);
8436 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8437 tcg_gen_ext16u_i32(tmp2, tmp2);
8438 } else {
8439 /* pkhbt */
8440 if (shift)
8441 tcg_gen_shli_i32(tmp2, tmp2, shift);
8442 tcg_gen_ext16u_i32(tmp, tmp);
8443 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8445 tcg_gen_or_i32(tmp, tmp, tmp2);
8446 tcg_temp_free_i32(tmp2);
8447 store_reg(s, rd, tmp);
8448 } else if ((insn & 0x00200020) == 0x00200000) {
8449 /* [us]sat */
8450 tmp = load_reg(s, rm);
8451 shift = (insn >> 7) & 0x1f;
8452 if (insn & (1 << 6)) {
8453 if (shift == 0)
8454 shift = 31;
8455 tcg_gen_sari_i32(tmp, tmp, shift);
8456 } else {
8457 tcg_gen_shli_i32(tmp, tmp, shift);
8459 sh = (insn >> 16) & 0x1f;
8460 tmp2 = tcg_const_i32(sh);
8461 if (insn & (1 << 22))
8462 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
8463 else
8464 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
8465 tcg_temp_free_i32(tmp2);
8466 store_reg(s, rd, tmp);
8467 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8468 /* [us]sat16 */
8469 tmp = load_reg(s, rm);
8470 sh = (insn >> 16) & 0x1f;
8471 tmp2 = tcg_const_i32(sh);
8472 if (insn & (1 << 22))
8473 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
8474 else
8475 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
8476 tcg_temp_free_i32(tmp2);
8477 store_reg(s, rd, tmp);
8478 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8479 /* Select bytes. */
8480 tmp = load_reg(s, rn);
8481 tmp2 = load_reg(s, rm);
8482 tmp3 = tcg_temp_new_i32();
8483 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8484 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8485 tcg_temp_free_i32(tmp3);
8486 tcg_temp_free_i32(tmp2);
8487 store_reg(s, rd, tmp);
8488 } else if ((insn & 0x000003e0) == 0x00000060) {
8489 tmp = load_reg(s, rm);
8490 shift = (insn >> 10) & 3;
8491 /* ??? In many cases it's not necessary to do a
8492 rotate, a shift is sufficient. */
8493 if (shift != 0)
8494 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8495 op1 = (insn >> 20) & 7;
8496 switch (op1) {
8497 case 0: gen_sxtb16(tmp); break;
8498 case 2: gen_sxtb(tmp); break;
8499 case 3: gen_sxth(tmp); break;
8500 case 4: gen_uxtb16(tmp); break;
8501 case 6: gen_uxtb(tmp); break;
8502 case 7: gen_uxth(tmp); break;
8503 default: goto illegal_op;
8505 if (rn != 15) {
8506 tmp2 = load_reg(s, rn);
8507 if ((op1 & 3) == 0) {
8508 gen_add16(tmp, tmp2);
8509 } else {
8510 tcg_gen_add_i32(tmp, tmp, tmp2);
8511 tcg_temp_free_i32(tmp2);
8514 store_reg(s, rd, tmp);
8515 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
8516 /* rev */
8517 tmp = load_reg(s, rm);
8518 if (insn & (1 << 22)) {
8519 if (insn & (1 << 7)) {
8520 gen_revsh(tmp);
8521 } else {
8522 ARCH(6T2);
8523 gen_helper_rbit(tmp, tmp);
8525 } else {
8526 if (insn & (1 << 7))
8527 gen_rev16(tmp);
8528 else
8529 tcg_gen_bswap32_i32(tmp, tmp);
8531 store_reg(s, rd, tmp);
8532 } else {
8533 goto illegal_op;
8535 break;
8536 case 2: /* Multiplies (Type 3). */
8537 switch ((insn >> 20) & 0x7) {
8538 case 5:
8539 if (((insn >> 6) ^ (insn >> 7)) & 1) {
8540 /* op2 not 00x or 11x : UNDEF */
8541 goto illegal_op;
8543 /* Signed multiply most significant [accumulate].
8544 (SMMUL, SMMLA, SMMLS) */
8545 tmp = load_reg(s, rm);
8546 tmp2 = load_reg(s, rs);
8547 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8549 if (rd != 15) {
8550 tmp = load_reg(s, rd);
8551 if (insn & (1 << 6)) {
8552 tmp64 = gen_subq_msw(tmp64, tmp);
8553 } else {
8554 tmp64 = gen_addq_msw(tmp64, tmp);
8557 if (insn & (1 << 5)) {
8558 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8560 tcg_gen_shri_i64(tmp64, tmp64, 32);
8561 tmp = tcg_temp_new_i32();
8562 tcg_gen_trunc_i64_i32(tmp, tmp64);
8563 tcg_temp_free_i64(tmp64);
8564 store_reg(s, rn, tmp);
8565 break;
8566 case 0:
8567 case 4:
8568 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
8569 if (insn & (1 << 7)) {
8570 goto illegal_op;
8572 tmp = load_reg(s, rm);
8573 tmp2 = load_reg(s, rs);
8574 if (insn & (1 << 5))
8575 gen_swap_half(tmp2);
8576 gen_smul_dual(tmp, tmp2);
8577 if (insn & (1 << 22)) {
8578 /* smlald, smlsld */
8579 TCGv_i64 tmp64_2;
8581 tmp64 = tcg_temp_new_i64();
8582 tmp64_2 = tcg_temp_new_i64();
8583 tcg_gen_ext_i32_i64(tmp64, tmp);
8584 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
8585 tcg_temp_free_i32(tmp);
8586 tcg_temp_free_i32(tmp2);
8587 if (insn & (1 << 6)) {
8588 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
8589 } else {
8590 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
8592 tcg_temp_free_i64(tmp64_2);
8593 gen_addq(s, tmp64, rd, rn);
8594 gen_storeq_reg(s, rd, rn, tmp64);
8595 tcg_temp_free_i64(tmp64);
8596 } else {
8597 /* smuad, smusd, smlad, smlsd */
8598 if (insn & (1 << 6)) {
8599 /* This subtraction cannot overflow. */
8600 tcg_gen_sub_i32(tmp, tmp, tmp2);
8601 } else {
8602 /* This addition cannot overflow 32 bits;
8603 * however it may overflow considered as a
8604 * signed operation, in which case we must set
8605 * the Q flag.
8607 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8609 tcg_temp_free_i32(tmp2);
8610 if (rd != 15)
8612 tmp2 = load_reg(s, rd);
8613 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8614 tcg_temp_free_i32(tmp2);
8616 store_reg(s, rn, tmp);
8618 break;
8619 case 1:
8620 case 3:
8621 /* SDIV, UDIV */
8622 if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
8623 goto illegal_op;
8625 if (((insn >> 5) & 7) || (rd != 15)) {
8626 goto illegal_op;
8628 tmp = load_reg(s, rm);
8629 tmp2 = load_reg(s, rs);
8630 if (insn & (1 << 21)) {
8631 gen_helper_udiv(tmp, tmp, tmp2);
8632 } else {
8633 gen_helper_sdiv(tmp, tmp, tmp2);
8635 tcg_temp_free_i32(tmp2);
8636 store_reg(s, rn, tmp);
8637 break;
8638 default:
8639 goto illegal_op;
8641 break;
8642 case 3:
8643 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8644 switch (op1) {
8645 case 0: /* Unsigned sum of absolute differences. */
8646 ARCH(6);
8647 tmp = load_reg(s, rm);
8648 tmp2 = load_reg(s, rs);
8649 gen_helper_usad8(tmp, tmp, tmp2);
8650 tcg_temp_free_i32(tmp2);
8651 if (rd != 15) {
8652 tmp2 = load_reg(s, rd);
8653 tcg_gen_add_i32(tmp, tmp, tmp2);
8654 tcg_temp_free_i32(tmp2);
8656 store_reg(s, rn, tmp);
8657 break;
8658 case 0x20: case 0x24: case 0x28: case 0x2c:
8659 /* Bitfield insert/clear. */
8660 ARCH(6T2);
8661 shift = (insn >> 7) & 0x1f;
8662 i = (insn >> 16) & 0x1f;
8663 i = i + 1 - shift;
8664 if (rm == 15) {
8665 tmp = tcg_temp_new_i32();
8666 tcg_gen_movi_i32(tmp, 0);
8667 } else {
8668 tmp = load_reg(s, rm);
8670 if (i != 32) {
8671 tmp2 = load_reg(s, rd);
8672 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
8673 tcg_temp_free_i32(tmp2);
8675 store_reg(s, rd, tmp);
8676 break;
8677 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8678 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
8679 ARCH(6T2);
8680 tmp = load_reg(s, rm);
8681 shift = (insn >> 7) & 0x1f;
8682 i = ((insn >> 16) & 0x1f) + 1;
8683 if (shift + i > 32)
8684 goto illegal_op;
8685 if (i < 32) {
8686 if (op1 & 0x20) {
8687 gen_ubfx(tmp, shift, (1u << i) - 1);
8688 } else {
8689 gen_sbfx(tmp, shift, i);
8692 store_reg(s, rd, tmp);
8693 break;
8694 default:
8695 goto illegal_op;
8697 break;
8699 break;
8701 do_ldst:
8702 /* Check for undefined extension instructions
8703 * per the ARM Bible IE:
8704 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
8706 sh = (0xf << 20) | (0xf << 4);
8707 if (op1 == 0x7 && ((insn & sh) == sh))
8709 goto illegal_op;
8711 /* load/store byte/word */
8712 rn = (insn >> 16) & 0xf;
8713 rd = (insn >> 12) & 0xf;
8714 tmp2 = load_reg(s, rn);
8715 if ((insn & 0x01200000) == 0x00200000) {
8716 /* ldrt/strt */
8717 i = MMU_USER_IDX;
8718 } else {
8719 i = get_mem_index(s);
8721 if (insn & (1 << 24))
8722 gen_add_data_offset(s, insn, tmp2);
8723 if (insn & (1 << 20)) {
8724 /* load */
8725 tmp = tcg_temp_new_i32();
8726 if (insn & (1 << 22)) {
8727 gen_aa32_ld8u(tmp, tmp2, i);
8728 } else {
8729 gen_aa32_ld32u(tmp, tmp2, i);
8731 } else {
8732 /* store */
8733 tmp = load_reg(s, rd);
8734 if (insn & (1 << 22)) {
8735 gen_aa32_st8(tmp, tmp2, i);
8736 } else {
8737 gen_aa32_st32(tmp, tmp2, i);
8739 tcg_temp_free_i32(tmp);
8741 if (!(insn & (1 << 24))) {
8742 gen_add_data_offset(s, insn, tmp2);
8743 store_reg(s, rn, tmp2);
8744 } else if (insn & (1 << 21)) {
8745 store_reg(s, rn, tmp2);
8746 } else {
8747 tcg_temp_free_i32(tmp2);
8749 if (insn & (1 << 20)) {
8750 /* Complete the load. */
8751 store_reg_from_load(env, s, rd, tmp);
8753 break;
8754 case 0x08:
8755 case 0x09:
8757 int j, n, user, loaded_base;
8758 TCGv_i32 loaded_var;
8759 /* load/store multiple words */
8760 /* XXX: store correct base if write back */
8761 user = 0;
8762 if (insn & (1 << 22)) {
8763 if (IS_USER(s))
8764 goto illegal_op; /* only usable in supervisor mode */
8766 if ((insn & (1 << 15)) == 0)
8767 user = 1;
8769 rn = (insn >> 16) & 0xf;
8770 addr = load_reg(s, rn);
8772 /* compute total size */
8773 loaded_base = 0;
8774 TCGV_UNUSED_I32(loaded_var);
8775 n = 0;
8776 for(i=0;i<16;i++) {
8777 if (insn & (1 << i))
8778 n++;
8780 /* XXX: test invalid n == 0 case ? */
8781 if (insn & (1 << 23)) {
8782 if (insn & (1 << 24)) {
8783 /* pre increment */
8784 tcg_gen_addi_i32(addr, addr, 4);
8785 } else {
8786 /* post increment */
8788 } else {
8789 if (insn & (1 << 24)) {
8790 /* pre decrement */
8791 tcg_gen_addi_i32(addr, addr, -(n * 4));
8792 } else {
8793 /* post decrement */
8794 if (n != 1)
8795 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8798 j = 0;
8799 for(i=0;i<16;i++) {
8800 if (insn & (1 << i)) {
8801 if (insn & (1 << 20)) {
8802 /* load */
8803 tmp = tcg_temp_new_i32();
8804 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8805 if (user) {
8806 tmp2 = tcg_const_i32(i);
8807 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
8808 tcg_temp_free_i32(tmp2);
8809 tcg_temp_free_i32(tmp);
8810 } else if (i == rn) {
8811 loaded_var = tmp;
8812 loaded_base = 1;
8813 } else {
8814 store_reg_from_load(env, s, i, tmp);
8816 } else {
8817 /* store */
8818 if (i == 15) {
8819 /* special case: r15 = PC + 8 */
8820 val = (long)s->pc + 4;
8821 tmp = tcg_temp_new_i32();
8822 tcg_gen_movi_i32(tmp, val);
8823 } else if (user) {
8824 tmp = tcg_temp_new_i32();
8825 tmp2 = tcg_const_i32(i);
8826 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
8827 tcg_temp_free_i32(tmp2);
8828 } else {
8829 tmp = load_reg(s, i);
8831 gen_aa32_st32(tmp, addr, get_mem_index(s));
8832 tcg_temp_free_i32(tmp);
8834 j++;
8835 /* no need to add after the last transfer */
8836 if (j != n)
8837 tcg_gen_addi_i32(addr, addr, 4);
8840 if (insn & (1 << 21)) {
8841 /* write back */
8842 if (insn & (1 << 23)) {
8843 if (insn & (1 << 24)) {
8844 /* pre increment */
8845 } else {
8846 /* post increment */
8847 tcg_gen_addi_i32(addr, addr, 4);
8849 } else {
8850 if (insn & (1 << 24)) {
8851 /* pre decrement */
8852 if (n != 1)
8853 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8854 } else {
8855 /* post decrement */
8856 tcg_gen_addi_i32(addr, addr, -(n * 4));
8859 store_reg(s, rn, addr);
8860 } else {
8861 tcg_temp_free_i32(addr);
8863 if (loaded_base) {
8864 store_reg(s, rn, loaded_var);
8866 if ((insn & (1 << 22)) && !user) {
8867 /* Restore CPSR from SPSR. */
8868 tmp = load_cpu_field(spsr);
8869 gen_set_cpsr(tmp, CPSR_ERET_MASK);
8870 tcg_temp_free_i32(tmp);
8871 s->is_jmp = DISAS_UPDATE;
8874 break;
8875 case 0xa:
8876 case 0xb:
8878 int32_t offset;
8880 /* branch (and link) */
8881 val = (int32_t)s->pc;
8882 if (insn & (1 << 24)) {
8883 tmp = tcg_temp_new_i32();
8884 tcg_gen_movi_i32(tmp, val);
8885 store_reg(s, 14, tmp);
8887 offset = sextract32(insn << 2, 0, 26);
8888 val += offset + 4;
8889 gen_jmp(s, val);
8891 break;
8892 case 0xc:
8893 case 0xd:
8894 case 0xe:
8895 if (((insn >> 8) & 0xe) == 10) {
8896 /* VFP. */
8897 if (disas_vfp_insn(env, s, insn)) {
8898 goto illegal_op;
8900 } else if (disas_coproc_insn(env, s, insn)) {
8901 /* Coprocessor. */
8902 goto illegal_op;
8904 break;
8905 case 0xf:
8906 /* swi */
8907 gen_set_pc_im(s, s->pc);
8908 s->svc_imm = extract32(insn, 0, 24);
8909 s->is_jmp = DISAS_SWI;
8910 break;
8911 default:
8912 illegal_op:
8913 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
8914 break;
8919 /* Return true if this is a Thumb-2 logical op. */
8920 static int
8921 thumb2_logic_op(int op)
8923 return (op < 8);
8926 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
8927 then set condition code flags based on the result of the operation.
8928 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
8929 to the high bit of T1.
8930 Returns zero if the opcode is valid. */
8932 static int
8933 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
8934 TCGv_i32 t0, TCGv_i32 t1)
8936 int logic_cc;
8938 logic_cc = 0;
8939 switch (op) {
8940 case 0: /* and */
8941 tcg_gen_and_i32(t0, t0, t1);
8942 logic_cc = conds;
8943 break;
8944 case 1: /* bic */
8945 tcg_gen_andc_i32(t0, t0, t1);
8946 logic_cc = conds;
8947 break;
8948 case 2: /* orr */
8949 tcg_gen_or_i32(t0, t0, t1);
8950 logic_cc = conds;
8951 break;
8952 case 3: /* orn */
8953 tcg_gen_orc_i32(t0, t0, t1);
8954 logic_cc = conds;
8955 break;
8956 case 4: /* eor */
8957 tcg_gen_xor_i32(t0, t0, t1);
8958 logic_cc = conds;
8959 break;
8960 case 8: /* add */
8961 if (conds)
8962 gen_add_CC(t0, t0, t1);
8963 else
8964 tcg_gen_add_i32(t0, t0, t1);
8965 break;
8966 case 10: /* adc */
8967 if (conds)
8968 gen_adc_CC(t0, t0, t1);
8969 else
8970 gen_adc(t0, t1);
8971 break;
8972 case 11: /* sbc */
8973 if (conds) {
8974 gen_sbc_CC(t0, t0, t1);
8975 } else {
8976 gen_sub_carry(t0, t0, t1);
8978 break;
8979 case 13: /* sub */
8980 if (conds)
8981 gen_sub_CC(t0, t0, t1);
8982 else
8983 tcg_gen_sub_i32(t0, t0, t1);
8984 break;
8985 case 14: /* rsb */
8986 if (conds)
8987 gen_sub_CC(t0, t1, t0);
8988 else
8989 tcg_gen_sub_i32(t0, t1, t0);
8990 break;
8991 default: /* 5, 6, 7, 9, 12, 15. */
8992 return 1;
8994 if (logic_cc) {
8995 gen_logic_CC(t0);
8996 if (shifter_out)
8997 gen_set_CF_bit31(t1);
8999 return 0;
9002 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
9003 is not legal. */
9004 static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
9006 uint32_t insn, imm, shift, offset;
9007 uint32_t rd, rn, rm, rs;
9008 TCGv_i32 tmp;
9009 TCGv_i32 tmp2;
9010 TCGv_i32 tmp3;
9011 TCGv_i32 addr;
9012 TCGv_i64 tmp64;
9013 int op;
9014 int shiftop;
9015 int conds;
9016 int logic_cc;
9018 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
9019 || arm_feature (env, ARM_FEATURE_M))) {
9020 /* Thumb-1 cores may need to treat bl and blx as a pair of
9021 16-bit instructions to get correct prefetch abort behavior. */
9022 insn = insn_hw1;
9023 if ((insn & (1 << 12)) == 0) {
9024 ARCH(5);
9025 /* Second half of blx. */
9026 offset = ((insn & 0x7ff) << 1);
9027 tmp = load_reg(s, 14);
9028 tcg_gen_addi_i32(tmp, tmp, offset);
9029 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
9031 tmp2 = tcg_temp_new_i32();
9032 tcg_gen_movi_i32(tmp2, s->pc | 1);
9033 store_reg(s, 14, tmp2);
9034 gen_bx(s, tmp);
9035 return 0;
9037 if (insn & (1 << 11)) {
9038 /* Second half of bl. */
9039 offset = ((insn & 0x7ff) << 1) | 1;
9040 tmp = load_reg(s, 14);
9041 tcg_gen_addi_i32(tmp, tmp, offset);
9043 tmp2 = tcg_temp_new_i32();
9044 tcg_gen_movi_i32(tmp2, s->pc | 1);
9045 store_reg(s, 14, tmp2);
9046 gen_bx(s, tmp);
9047 return 0;
9049 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
9050 /* Instruction spans a page boundary. Implement it as two
9051 16-bit instructions in case the second half causes an
9052 prefetch abort. */
9053 offset = ((int32_t)insn << 21) >> 9;
9054 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
9055 return 0;
9057 /* Fall through to 32-bit decode. */
9060 insn = arm_lduw_code(env, s->pc, s->bswap_code);
9061 s->pc += 2;
9062 insn |= (uint32_t)insn_hw1 << 16;
9064 if ((insn & 0xf800e800) != 0xf000e800) {
9065 ARCH(6T2);
9068 rn = (insn >> 16) & 0xf;
9069 rs = (insn >> 12) & 0xf;
9070 rd = (insn >> 8) & 0xf;
9071 rm = insn & 0xf;
9072 switch ((insn >> 25) & 0xf) {
9073 case 0: case 1: case 2: case 3:
9074 /* 16-bit instructions. Should never happen. */
9075 abort();
9076 case 4:
9077 if (insn & (1 << 22)) {
9078 /* Other load/store, table branch. */
9079 if (insn & 0x01200000) {
9080 /* Load/store doubleword. */
9081 if (rn == 15) {
9082 addr = tcg_temp_new_i32();
9083 tcg_gen_movi_i32(addr, s->pc & ~3);
9084 } else {
9085 addr = load_reg(s, rn);
9087 offset = (insn & 0xff) * 4;
9088 if ((insn & (1 << 23)) == 0)
9089 offset = -offset;
9090 if (insn & (1 << 24)) {
9091 tcg_gen_addi_i32(addr, addr, offset);
9092 offset = 0;
9094 if (insn & (1 << 20)) {
9095 /* ldrd */
9096 tmp = tcg_temp_new_i32();
9097 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9098 store_reg(s, rs, tmp);
9099 tcg_gen_addi_i32(addr, addr, 4);
9100 tmp = tcg_temp_new_i32();
9101 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9102 store_reg(s, rd, tmp);
9103 } else {
9104 /* strd */
9105 tmp = load_reg(s, rs);
9106 gen_aa32_st32(tmp, addr, get_mem_index(s));
9107 tcg_temp_free_i32(tmp);
9108 tcg_gen_addi_i32(addr, addr, 4);
9109 tmp = load_reg(s, rd);
9110 gen_aa32_st32(tmp, addr, get_mem_index(s));
9111 tcg_temp_free_i32(tmp);
9113 if (insn & (1 << 21)) {
9114 /* Base writeback. */
9115 if (rn == 15)
9116 goto illegal_op;
9117 tcg_gen_addi_i32(addr, addr, offset - 4);
9118 store_reg(s, rn, addr);
9119 } else {
9120 tcg_temp_free_i32(addr);
9122 } else if ((insn & (1 << 23)) == 0) {
9123 /* Load/store exclusive word. */
9124 addr = tcg_temp_local_new_i32();
9125 load_reg_var(s, addr, rn);
9126 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
9127 if (insn & (1 << 20)) {
9128 gen_load_exclusive(s, rs, 15, addr, 2);
9129 } else {
9130 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9132 tcg_temp_free_i32(addr);
9133 } else if ((insn & (7 << 5)) == 0) {
9134 /* Table Branch. */
9135 if (rn == 15) {
9136 addr = tcg_temp_new_i32();
9137 tcg_gen_movi_i32(addr, s->pc);
9138 } else {
9139 addr = load_reg(s, rn);
9141 tmp = load_reg(s, rm);
9142 tcg_gen_add_i32(addr, addr, tmp);
9143 if (insn & (1 << 4)) {
9144 /* tbh */
9145 tcg_gen_add_i32(addr, addr, tmp);
9146 tcg_temp_free_i32(tmp);
9147 tmp = tcg_temp_new_i32();
9148 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
9149 } else { /* tbb */
9150 tcg_temp_free_i32(tmp);
9151 tmp = tcg_temp_new_i32();
9152 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
9154 tcg_temp_free_i32(addr);
9155 tcg_gen_shli_i32(tmp, tmp, 1);
9156 tcg_gen_addi_i32(tmp, tmp, s->pc);
9157 store_reg(s, 15, tmp);
9158 } else {
9159 int op2 = (insn >> 6) & 0x3;
9160 op = (insn >> 4) & 0x3;
9161 switch (op2) {
9162 case 0:
9163 goto illegal_op;
9164 case 1:
9165 /* Load/store exclusive byte/halfword/doubleword */
9166 if (op == 2) {
9167 goto illegal_op;
9169 ARCH(7);
9170 break;
9171 case 2:
9172 /* Load-acquire/store-release */
9173 if (op == 3) {
9174 goto illegal_op;
9176 /* Fall through */
9177 case 3:
9178 /* Load-acquire/store-release exclusive */
9179 ARCH(8);
9180 break;
9182 addr = tcg_temp_local_new_i32();
9183 load_reg_var(s, addr, rn);
9184 if (!(op2 & 1)) {
9185 if (insn & (1 << 20)) {
9186 tmp = tcg_temp_new_i32();
9187 switch (op) {
9188 case 0: /* ldab */
9189 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
9190 break;
9191 case 1: /* ldah */
9192 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
9193 break;
9194 case 2: /* lda */
9195 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9196 break;
9197 default:
9198 abort();
9200 store_reg(s, rs, tmp);
9201 } else {
9202 tmp = load_reg(s, rs);
9203 switch (op) {
9204 case 0: /* stlb */
9205 gen_aa32_st8(tmp, addr, get_mem_index(s));
9206 break;
9207 case 1: /* stlh */
9208 gen_aa32_st16(tmp, addr, get_mem_index(s));
9209 break;
9210 case 2: /* stl */
9211 gen_aa32_st32(tmp, addr, get_mem_index(s));
9212 break;
9213 default:
9214 abort();
9216 tcg_temp_free_i32(tmp);
9218 } else if (insn & (1 << 20)) {
9219 gen_load_exclusive(s, rs, rd, addr, op);
9220 } else {
9221 gen_store_exclusive(s, rm, rs, rd, addr, op);
9223 tcg_temp_free_i32(addr);
9225 } else {
9226 /* Load/store multiple, RFE, SRS. */
9227 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
9228 /* RFE, SRS: not available in user mode or on M profile */
9229 if (IS_USER(s) || IS_M(env)) {
9230 goto illegal_op;
9232 if (insn & (1 << 20)) {
9233 /* rfe */
9234 addr = load_reg(s, rn);
9235 if ((insn & (1 << 24)) == 0)
9236 tcg_gen_addi_i32(addr, addr, -8);
9237 /* Load PC into tmp and CPSR into tmp2. */
9238 tmp = tcg_temp_new_i32();
9239 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9240 tcg_gen_addi_i32(addr, addr, 4);
9241 tmp2 = tcg_temp_new_i32();
9242 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
9243 if (insn & (1 << 21)) {
9244 /* Base writeback. */
9245 if (insn & (1 << 24)) {
9246 tcg_gen_addi_i32(addr, addr, 4);
9247 } else {
9248 tcg_gen_addi_i32(addr, addr, -4);
9250 store_reg(s, rn, addr);
9251 } else {
9252 tcg_temp_free_i32(addr);
9254 gen_rfe(s, tmp, tmp2);
9255 } else {
9256 /* srs */
9257 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
9258 insn & (1 << 21));
9260 } else {
9261 int i, loaded_base = 0;
9262 TCGv_i32 loaded_var;
9263 /* Load/store multiple. */
9264 addr = load_reg(s, rn);
9265 offset = 0;
9266 for (i = 0; i < 16; i++) {
9267 if (insn & (1 << i))
9268 offset += 4;
9270 if (insn & (1 << 24)) {
9271 tcg_gen_addi_i32(addr, addr, -offset);
9274 TCGV_UNUSED_I32(loaded_var);
9275 for (i = 0; i < 16; i++) {
9276 if ((insn & (1 << i)) == 0)
9277 continue;
9278 if (insn & (1 << 20)) {
9279 /* Load. */
9280 tmp = tcg_temp_new_i32();
9281 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9282 if (i == 15) {
9283 gen_bx(s, tmp);
9284 } else if (i == rn) {
9285 loaded_var = tmp;
9286 loaded_base = 1;
9287 } else {
9288 store_reg(s, i, tmp);
9290 } else {
9291 /* Store. */
9292 tmp = load_reg(s, i);
9293 gen_aa32_st32(tmp, addr, get_mem_index(s));
9294 tcg_temp_free_i32(tmp);
9296 tcg_gen_addi_i32(addr, addr, 4);
9298 if (loaded_base) {
9299 store_reg(s, rn, loaded_var);
9301 if (insn & (1 << 21)) {
9302 /* Base register writeback. */
9303 if (insn & (1 << 24)) {
9304 tcg_gen_addi_i32(addr, addr, -offset);
9306 /* Fault if writeback register is in register list. */
9307 if (insn & (1 << rn))
9308 goto illegal_op;
9309 store_reg(s, rn, addr);
9310 } else {
9311 tcg_temp_free_i32(addr);
9315 break;
9316 case 5:
9318 op = (insn >> 21) & 0xf;
9319 if (op == 6) {
9320 /* Halfword pack. */
9321 tmp = load_reg(s, rn);
9322 tmp2 = load_reg(s, rm);
9323 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
9324 if (insn & (1 << 5)) {
9325 /* pkhtb */
9326 if (shift == 0)
9327 shift = 31;
9328 tcg_gen_sari_i32(tmp2, tmp2, shift);
9329 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9330 tcg_gen_ext16u_i32(tmp2, tmp2);
9331 } else {
9332 /* pkhbt */
9333 if (shift)
9334 tcg_gen_shli_i32(tmp2, tmp2, shift);
9335 tcg_gen_ext16u_i32(tmp, tmp);
9336 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9338 tcg_gen_or_i32(tmp, tmp, tmp2);
9339 tcg_temp_free_i32(tmp2);
9340 store_reg(s, rd, tmp);
9341 } else {
9342 /* Data processing register constant shift. */
9343 if (rn == 15) {
9344 tmp = tcg_temp_new_i32();
9345 tcg_gen_movi_i32(tmp, 0);
9346 } else {
9347 tmp = load_reg(s, rn);
9349 tmp2 = load_reg(s, rm);
9351 shiftop = (insn >> 4) & 3;
9352 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9353 conds = (insn & (1 << 20)) != 0;
9354 logic_cc = (conds && thumb2_logic_op(op));
9355 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9356 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9357 goto illegal_op;
9358 tcg_temp_free_i32(tmp2);
9359 if (rd != 15) {
9360 store_reg(s, rd, tmp);
9361 } else {
9362 tcg_temp_free_i32(tmp);
9365 break;
9366 case 13: /* Misc data processing. */
9367 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9368 if (op < 4 && (insn & 0xf000) != 0xf000)
9369 goto illegal_op;
9370 switch (op) {
9371 case 0: /* Register controlled shift. */
9372 tmp = load_reg(s, rn);
9373 tmp2 = load_reg(s, rm);
9374 if ((insn & 0x70) != 0)
9375 goto illegal_op;
9376 op = (insn >> 21) & 3;
9377 logic_cc = (insn & (1 << 20)) != 0;
9378 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9379 if (logic_cc)
9380 gen_logic_CC(tmp);
9381 store_reg_bx(env, s, rd, tmp);
9382 break;
9383 case 1: /* Sign/zero extend. */
9384 tmp = load_reg(s, rm);
9385 shift = (insn >> 4) & 3;
9386 /* ??? In many cases it's not necessary to do a
9387 rotate, a shift is sufficient. */
9388 if (shift != 0)
9389 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9390 op = (insn >> 20) & 7;
9391 switch (op) {
9392 case 0: gen_sxth(tmp); break;
9393 case 1: gen_uxth(tmp); break;
9394 case 2: gen_sxtb16(tmp); break;
9395 case 3: gen_uxtb16(tmp); break;
9396 case 4: gen_sxtb(tmp); break;
9397 case 5: gen_uxtb(tmp); break;
9398 default: goto illegal_op;
9400 if (rn != 15) {
9401 tmp2 = load_reg(s, rn);
9402 if ((op >> 1) == 1) {
9403 gen_add16(tmp, tmp2);
9404 } else {
9405 tcg_gen_add_i32(tmp, tmp, tmp2);
9406 tcg_temp_free_i32(tmp2);
9409 store_reg(s, rd, tmp);
9410 break;
9411 case 2: /* SIMD add/subtract. */
9412 op = (insn >> 20) & 7;
9413 shift = (insn >> 4) & 7;
9414 if ((op & 3) == 3 || (shift & 3) == 3)
9415 goto illegal_op;
9416 tmp = load_reg(s, rn);
9417 tmp2 = load_reg(s, rm);
9418 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
9419 tcg_temp_free_i32(tmp2);
9420 store_reg(s, rd, tmp);
9421 break;
9422 case 3: /* Other data processing. */
9423 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9424 if (op < 4) {
9425 /* Saturating add/subtract. */
9426 tmp = load_reg(s, rn);
9427 tmp2 = load_reg(s, rm);
9428 if (op & 1)
9429 gen_helper_double_saturate(tmp, cpu_env, tmp);
9430 if (op & 2)
9431 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9432 else
9433 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
9434 tcg_temp_free_i32(tmp2);
9435 } else {
9436 tmp = load_reg(s, rn);
9437 switch (op) {
9438 case 0x0a: /* rbit */
9439 gen_helper_rbit(tmp, tmp);
9440 break;
9441 case 0x08: /* rev */
9442 tcg_gen_bswap32_i32(tmp, tmp);
9443 break;
9444 case 0x09: /* rev16 */
9445 gen_rev16(tmp);
9446 break;
9447 case 0x0b: /* revsh */
9448 gen_revsh(tmp);
9449 break;
9450 case 0x10: /* sel */
9451 tmp2 = load_reg(s, rm);
9452 tmp3 = tcg_temp_new_i32();
9453 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
9454 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
9455 tcg_temp_free_i32(tmp3);
9456 tcg_temp_free_i32(tmp2);
9457 break;
9458 case 0x18: /* clz */
9459 gen_helper_clz(tmp, tmp);
9460 break;
9461 case 0x20:
9462 case 0x21:
9463 case 0x22:
9464 case 0x28:
9465 case 0x29:
9466 case 0x2a:
9468 /* crc32/crc32c */
9469 uint32_t sz = op & 0x3;
9470 uint32_t c = op & 0x8;
9472 if (!arm_feature(env, ARM_FEATURE_CRC)) {
9473 goto illegal_op;
9476 tmp2 = load_reg(s, rm);
9477 if (sz == 0) {
9478 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
9479 } else if (sz == 1) {
9480 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
9482 tmp3 = tcg_const_i32(1 << sz);
9483 if (c) {
9484 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
9485 } else {
9486 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
9488 tcg_temp_free_i32(tmp2);
9489 tcg_temp_free_i32(tmp3);
9490 break;
9492 default:
9493 goto illegal_op;
9496 store_reg(s, rd, tmp);
9497 break;
9498 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
9499 op = (insn >> 4) & 0xf;
9500 tmp = load_reg(s, rn);
9501 tmp2 = load_reg(s, rm);
9502 switch ((insn >> 20) & 7) {
9503 case 0: /* 32 x 32 -> 32 */
9504 tcg_gen_mul_i32(tmp, tmp, tmp2);
9505 tcg_temp_free_i32(tmp2);
9506 if (rs != 15) {
9507 tmp2 = load_reg(s, rs);
9508 if (op)
9509 tcg_gen_sub_i32(tmp, tmp2, tmp);
9510 else
9511 tcg_gen_add_i32(tmp, tmp, tmp2);
9512 tcg_temp_free_i32(tmp2);
9514 break;
9515 case 1: /* 16 x 16 -> 32 */
9516 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9517 tcg_temp_free_i32(tmp2);
9518 if (rs != 15) {
9519 tmp2 = load_reg(s, rs);
9520 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9521 tcg_temp_free_i32(tmp2);
9523 break;
9524 case 2: /* Dual multiply add. */
9525 case 4: /* Dual multiply subtract. */
9526 if (op)
9527 gen_swap_half(tmp2);
9528 gen_smul_dual(tmp, tmp2);
9529 if (insn & (1 << 22)) {
9530 /* This subtraction cannot overflow. */
9531 tcg_gen_sub_i32(tmp, tmp, tmp2);
9532 } else {
9533 /* This addition cannot overflow 32 bits;
9534 * however it may overflow considered as a signed
9535 * operation, in which case we must set the Q flag.
9537 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9539 tcg_temp_free_i32(tmp2);
9540 if (rs != 15)
9542 tmp2 = load_reg(s, rs);
9543 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9544 tcg_temp_free_i32(tmp2);
9546 break;
9547 case 3: /* 32 * 16 -> 32msb */
9548 if (op)
9549 tcg_gen_sari_i32(tmp2, tmp2, 16);
9550 else
9551 gen_sxth(tmp2);
9552 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9553 tcg_gen_shri_i64(tmp64, tmp64, 16);
9554 tmp = tcg_temp_new_i32();
9555 tcg_gen_trunc_i64_i32(tmp, tmp64);
9556 tcg_temp_free_i64(tmp64);
9557 if (rs != 15)
9559 tmp2 = load_reg(s, rs);
9560 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9561 tcg_temp_free_i32(tmp2);
9563 break;
9564 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
9565 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9566 if (rs != 15) {
9567 tmp = load_reg(s, rs);
9568 if (insn & (1 << 20)) {
9569 tmp64 = gen_addq_msw(tmp64, tmp);
9570 } else {
9571 tmp64 = gen_subq_msw(tmp64, tmp);
9574 if (insn & (1 << 4)) {
9575 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9577 tcg_gen_shri_i64(tmp64, tmp64, 32);
9578 tmp = tcg_temp_new_i32();
9579 tcg_gen_trunc_i64_i32(tmp, tmp64);
9580 tcg_temp_free_i64(tmp64);
9581 break;
9582 case 7: /* Unsigned sum of absolute differences. */
9583 gen_helper_usad8(tmp, tmp, tmp2);
9584 tcg_temp_free_i32(tmp2);
9585 if (rs != 15) {
9586 tmp2 = load_reg(s, rs);
9587 tcg_gen_add_i32(tmp, tmp, tmp2);
9588 tcg_temp_free_i32(tmp2);
9590 break;
9592 store_reg(s, rd, tmp);
9593 break;
9594 case 6: case 7: /* 64-bit multiply, Divide. */
9595 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
9596 tmp = load_reg(s, rn);
9597 tmp2 = load_reg(s, rm);
9598 if ((op & 0x50) == 0x10) {
9599 /* sdiv, udiv */
9600 if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
9601 goto illegal_op;
9603 if (op & 0x20)
9604 gen_helper_udiv(tmp, tmp, tmp2);
9605 else
9606 gen_helper_sdiv(tmp, tmp, tmp2);
9607 tcg_temp_free_i32(tmp2);
9608 store_reg(s, rd, tmp);
9609 } else if ((op & 0xe) == 0xc) {
9610 /* Dual multiply accumulate long. */
9611 if (op & 1)
9612 gen_swap_half(tmp2);
9613 gen_smul_dual(tmp, tmp2);
9614 if (op & 0x10) {
9615 tcg_gen_sub_i32(tmp, tmp, tmp2);
9616 } else {
9617 tcg_gen_add_i32(tmp, tmp, tmp2);
9619 tcg_temp_free_i32(tmp2);
9620 /* BUGFIX */
9621 tmp64 = tcg_temp_new_i64();
9622 tcg_gen_ext_i32_i64(tmp64, tmp);
9623 tcg_temp_free_i32(tmp);
9624 gen_addq(s, tmp64, rs, rd);
9625 gen_storeq_reg(s, rs, rd, tmp64);
9626 tcg_temp_free_i64(tmp64);
9627 } else {
9628 if (op & 0x20) {
9629 /* Unsigned 64-bit multiply */
9630 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9631 } else {
9632 if (op & 8) {
9633 /* smlalxy */
9634 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9635 tcg_temp_free_i32(tmp2);
9636 tmp64 = tcg_temp_new_i64();
9637 tcg_gen_ext_i32_i64(tmp64, tmp);
9638 tcg_temp_free_i32(tmp);
9639 } else {
9640 /* Signed 64-bit multiply */
9641 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9644 if (op & 4) {
9645 /* umaal */
9646 gen_addq_lo(s, tmp64, rs);
9647 gen_addq_lo(s, tmp64, rd);
9648 } else if (op & 0x40) {
9649 /* 64-bit accumulate. */
9650 gen_addq(s, tmp64, rs, rd);
9652 gen_storeq_reg(s, rs, rd, tmp64);
9653 tcg_temp_free_i64(tmp64);
9655 break;
9657 break;
9658 case 6: case 7: case 14: case 15:
9659 /* Coprocessor. */
9660 if (((insn >> 24) & 3) == 3) {
9661 /* Translate into the equivalent ARM encoding. */
9662 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
9663 if (disas_neon_data_insn(env, s, insn))
9664 goto illegal_op;
9665 } else if (((insn >> 8) & 0xe) == 10) {
9666 if (disas_vfp_insn(env, s, insn)) {
9667 goto illegal_op;
9669 } else {
9670 if (insn & (1 << 28))
9671 goto illegal_op;
9672 if (disas_coproc_insn (env, s, insn))
9673 goto illegal_op;
9675 break;
9676 case 8: case 9: case 10: case 11:
9677 if (insn & (1 << 15)) {
9678 /* Branches, misc control. */
9679 if (insn & 0x5000) {
9680 /* Unconditional branch. */
9681 /* signextend(hw1[10:0]) -> offset[:12]. */
9682 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
9683 /* hw1[10:0] -> offset[11:1]. */
9684 offset |= (insn & 0x7ff) << 1;
9685 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
9686 offset[24:22] already have the same value because of the
9687 sign extension above. */
9688 offset ^= ((~insn) & (1 << 13)) << 10;
9689 offset ^= ((~insn) & (1 << 11)) << 11;
9691 if (insn & (1 << 14)) {
9692 /* Branch and link. */
9693 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
9696 offset += s->pc;
9697 if (insn & (1 << 12)) {
9698 /* b/bl */
9699 gen_jmp(s, offset);
9700 } else {
9701 /* blx */
9702 offset &= ~(uint32_t)2;
9703 /* thumb2 bx, no need to check */
9704 gen_bx_im(s, offset);
9706 } else if (((insn >> 23) & 7) == 7) {
9707 /* Misc control */
9708 if (insn & (1 << 13))
9709 goto illegal_op;
9711 if (insn & (1 << 26)) {
9712 /* Secure monitor call (v6Z) */
9713 qemu_log_mask(LOG_UNIMP,
9714 "arm: unimplemented secure monitor call\n");
9715 goto illegal_op; /* not implemented. */
9716 } else {
9717 op = (insn >> 20) & 7;
9718 switch (op) {
9719 case 0: /* msr cpsr. */
9720 if (IS_M(env)) {
9721 tmp = load_reg(s, rn);
9722 addr = tcg_const_i32(insn & 0xff);
9723 gen_helper_v7m_msr(cpu_env, addr, tmp);
9724 tcg_temp_free_i32(addr);
9725 tcg_temp_free_i32(tmp);
9726 gen_lookup_tb(s);
9727 break;
9729 /* fall through */
9730 case 1: /* msr spsr. */
9731 if (IS_M(env))
9732 goto illegal_op;
9733 tmp = load_reg(s, rn);
9734 if (gen_set_psr(s,
9735 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
9736 op == 1, tmp))
9737 goto illegal_op;
9738 break;
9739 case 2: /* cps, nop-hint. */
9740 if (((insn >> 8) & 7) == 0) {
9741 gen_nop_hint(s, insn & 0xff);
9743 /* Implemented as NOP in user mode. */
9744 if (IS_USER(s))
9745 break;
9746 offset = 0;
9747 imm = 0;
9748 if (insn & (1 << 10)) {
9749 if (insn & (1 << 7))
9750 offset |= CPSR_A;
9751 if (insn & (1 << 6))
9752 offset |= CPSR_I;
9753 if (insn & (1 << 5))
9754 offset |= CPSR_F;
9755 if (insn & (1 << 9))
9756 imm = CPSR_A | CPSR_I | CPSR_F;
9758 if (insn & (1 << 8)) {
9759 offset |= 0x1f;
9760 imm |= (insn & 0x1f);
9762 if (offset) {
9763 gen_set_psr_im(s, offset, 0, imm);
9765 break;
9766 case 3: /* Special control operations. */
9767 ARCH(7);
9768 op = (insn >> 4) & 0xf;
9769 switch (op) {
9770 case 2: /* clrex */
9771 gen_clrex(s);
9772 break;
9773 case 4: /* dsb */
9774 case 5: /* dmb */
9775 case 6: /* isb */
9776 /* These execute as NOPs. */
9777 break;
9778 default:
9779 goto illegal_op;
9781 break;
9782 case 4: /* bxj */
9783 /* Trivial implementation equivalent to bx. */
9784 tmp = load_reg(s, rn);
9785 gen_bx(s, tmp);
9786 break;
9787 case 5: /* Exception return. */
9788 if (IS_USER(s)) {
9789 goto illegal_op;
9791 if (rn != 14 || rd != 15) {
9792 goto illegal_op;
9794 tmp = load_reg(s, rn);
9795 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
9796 gen_exception_return(s, tmp);
9797 break;
9798 case 6: /* mrs cpsr. */
9799 tmp = tcg_temp_new_i32();
9800 if (IS_M(env)) {
9801 addr = tcg_const_i32(insn & 0xff);
9802 gen_helper_v7m_mrs(tmp, cpu_env, addr);
9803 tcg_temp_free_i32(addr);
9804 } else {
9805 gen_helper_cpsr_read(tmp, cpu_env);
9807 store_reg(s, rd, tmp);
9808 break;
9809 case 7: /* mrs spsr. */
9810 /* Not accessible in user mode. */
9811 if (IS_USER(s) || IS_M(env))
9812 goto illegal_op;
9813 tmp = load_cpu_field(spsr);
9814 store_reg(s, rd, tmp);
9815 break;
9818 } else {
9819 /* Conditional branch. */
9820 op = (insn >> 22) & 0xf;
9821 /* Generate a conditional jump to next instruction. */
9822 s->condlabel = gen_new_label();
9823 arm_gen_test_cc(op ^ 1, s->condlabel);
9824 s->condjmp = 1;
9826 /* offset[11:1] = insn[10:0] */
9827 offset = (insn & 0x7ff) << 1;
9828 /* offset[17:12] = insn[21:16]. */
9829 offset |= (insn & 0x003f0000) >> 4;
9830 /* offset[31:20] = insn[26]. */
9831 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
9832 /* offset[18] = insn[13]. */
9833 offset |= (insn & (1 << 13)) << 5;
9834 /* offset[19] = insn[11]. */
9835 offset |= (insn & (1 << 11)) << 8;
9837 /* jump to the offset */
9838 gen_jmp(s, s->pc + offset);
9840 } else {
9841 /* Data processing immediate. */
9842 if (insn & (1 << 25)) {
9843 if (insn & (1 << 24)) {
9844 if (insn & (1 << 20))
9845 goto illegal_op;
9846 /* Bitfield/Saturate. */
9847 op = (insn >> 21) & 7;
9848 imm = insn & 0x1f;
9849 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9850 if (rn == 15) {
9851 tmp = tcg_temp_new_i32();
9852 tcg_gen_movi_i32(tmp, 0);
9853 } else {
9854 tmp = load_reg(s, rn);
9856 switch (op) {
9857 case 2: /* Signed bitfield extract. */
9858 imm++;
9859 if (shift + imm > 32)
9860 goto illegal_op;
9861 if (imm < 32)
9862 gen_sbfx(tmp, shift, imm);
9863 break;
9864 case 6: /* Unsigned bitfield extract. */
9865 imm++;
9866 if (shift + imm > 32)
9867 goto illegal_op;
9868 if (imm < 32)
9869 gen_ubfx(tmp, shift, (1u << imm) - 1);
9870 break;
9871 case 3: /* Bitfield insert/clear. */
9872 if (imm < shift)
9873 goto illegal_op;
9874 imm = imm + 1 - shift;
9875 if (imm != 32) {
9876 tmp2 = load_reg(s, rd);
9877 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
9878 tcg_temp_free_i32(tmp2);
9880 break;
9881 case 7:
9882 goto illegal_op;
9883 default: /* Saturate. */
9884 if (shift) {
9885 if (op & 1)
9886 tcg_gen_sari_i32(tmp, tmp, shift);
9887 else
9888 tcg_gen_shli_i32(tmp, tmp, shift);
9890 tmp2 = tcg_const_i32(imm);
9891 if (op & 4) {
9892 /* Unsigned. */
9893 if ((op & 1) && shift == 0)
9894 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9895 else
9896 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9897 } else {
9898 /* Signed. */
9899 if ((op & 1) && shift == 0)
9900 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9901 else
9902 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9904 tcg_temp_free_i32(tmp2);
9905 break;
9907 store_reg(s, rd, tmp);
9908 } else {
9909 imm = ((insn & 0x04000000) >> 15)
9910 | ((insn & 0x7000) >> 4) | (insn & 0xff);
9911 if (insn & (1 << 22)) {
9912 /* 16-bit immediate. */
9913 imm |= (insn >> 4) & 0xf000;
9914 if (insn & (1 << 23)) {
9915 /* movt */
9916 tmp = load_reg(s, rd);
9917 tcg_gen_ext16u_i32(tmp, tmp);
9918 tcg_gen_ori_i32(tmp, tmp, imm << 16);
9919 } else {
9920 /* movw */
9921 tmp = tcg_temp_new_i32();
9922 tcg_gen_movi_i32(tmp, imm);
9924 } else {
9925 /* Add/sub 12-bit immediate. */
9926 if (rn == 15) {
9927 offset = s->pc & ~(uint32_t)3;
9928 if (insn & (1 << 23))
9929 offset -= imm;
9930 else
9931 offset += imm;
9932 tmp = tcg_temp_new_i32();
9933 tcg_gen_movi_i32(tmp, offset);
9934 } else {
9935 tmp = load_reg(s, rn);
9936 if (insn & (1 << 23))
9937 tcg_gen_subi_i32(tmp, tmp, imm);
9938 else
9939 tcg_gen_addi_i32(tmp, tmp, imm);
9942 store_reg(s, rd, tmp);
9944 } else {
9945 int shifter_out = 0;
9946 /* modified 12-bit immediate. */
9947 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
9948 imm = (insn & 0xff);
9949 switch (shift) {
9950 case 0: /* XY */
9951 /* Nothing to do. */
9952 break;
9953 case 1: /* 00XY00XY */
9954 imm |= imm << 16;
9955 break;
9956 case 2: /* XY00XY00 */
9957 imm |= imm << 16;
9958 imm <<= 8;
9959 break;
9960 case 3: /* XYXYXYXY */
9961 imm |= imm << 16;
9962 imm |= imm << 8;
9963 break;
9964 default: /* Rotated constant. */
9965 shift = (shift << 1) | (imm >> 7);
9966 imm |= 0x80;
9967 imm = imm << (32 - shift);
9968 shifter_out = 1;
9969 break;
9971 tmp2 = tcg_temp_new_i32();
9972 tcg_gen_movi_i32(tmp2, imm);
9973 rn = (insn >> 16) & 0xf;
9974 if (rn == 15) {
9975 tmp = tcg_temp_new_i32();
9976 tcg_gen_movi_i32(tmp, 0);
9977 } else {
9978 tmp = load_reg(s, rn);
9980 op = (insn >> 21) & 0xf;
9981 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
9982 shifter_out, tmp, tmp2))
9983 goto illegal_op;
9984 tcg_temp_free_i32(tmp2);
9985 rd = (insn >> 8) & 0xf;
9986 if (rd != 15) {
9987 store_reg(s, rd, tmp);
9988 } else {
9989 tcg_temp_free_i32(tmp);
9993 break;
9994 case 12: /* Load/store single data item. */
9996 int postinc = 0;
9997 int writeback = 0;
9998 int memidx;
9999 if ((insn & 0x01100000) == 0x01000000) {
10000 if (disas_neon_ls_insn(env, s, insn))
10001 goto illegal_op;
10002 break;
10004 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
10005 if (rs == 15) {
10006 if (!(insn & (1 << 20))) {
10007 goto illegal_op;
10009 if (op != 2) {
10010 /* Byte or halfword load space with dest == r15 : memory hints.
10011 * Catch them early so we don't emit pointless addressing code.
10012 * This space is a mix of:
10013 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
10014 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
10015 * cores)
10016 * unallocated hints, which must be treated as NOPs
10017 * UNPREDICTABLE space, which we NOP or UNDEF depending on
10018 * which is easiest for the decoding logic
10019 * Some space which must UNDEF
10021 int op1 = (insn >> 23) & 3;
10022 int op2 = (insn >> 6) & 0x3f;
10023 if (op & 2) {
10024 goto illegal_op;
10026 if (rn == 15) {
10027 /* UNPREDICTABLE, unallocated hint or
10028 * PLD/PLDW/PLI (literal)
10030 return 0;
10032 if (op1 & 1) {
10033 return 0; /* PLD/PLDW/PLI or unallocated hint */
10035 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
10036 return 0; /* PLD/PLDW/PLI or unallocated hint */
10038 /* UNDEF space, or an UNPREDICTABLE */
10039 return 1;
10042 memidx = get_mem_index(s);
10043 if (rn == 15) {
10044 addr = tcg_temp_new_i32();
10045 /* PC relative. */
10046 /* s->pc has already been incremented by 4. */
10047 imm = s->pc & 0xfffffffc;
10048 if (insn & (1 << 23))
10049 imm += insn & 0xfff;
10050 else
10051 imm -= insn & 0xfff;
10052 tcg_gen_movi_i32(addr, imm);
10053 } else {
10054 addr = load_reg(s, rn);
10055 if (insn & (1 << 23)) {
10056 /* Positive offset. */
10057 imm = insn & 0xfff;
10058 tcg_gen_addi_i32(addr, addr, imm);
10059 } else {
10060 imm = insn & 0xff;
10061 switch ((insn >> 8) & 0xf) {
10062 case 0x0: /* Shifted Register. */
10063 shift = (insn >> 4) & 0xf;
10064 if (shift > 3) {
10065 tcg_temp_free_i32(addr);
10066 goto illegal_op;
10068 tmp = load_reg(s, rm);
10069 if (shift)
10070 tcg_gen_shli_i32(tmp, tmp, shift);
10071 tcg_gen_add_i32(addr, addr, tmp);
10072 tcg_temp_free_i32(tmp);
10073 break;
10074 case 0xc: /* Negative offset. */
10075 tcg_gen_addi_i32(addr, addr, -imm);
10076 break;
10077 case 0xe: /* User privilege. */
10078 tcg_gen_addi_i32(addr, addr, imm);
10079 memidx = MMU_USER_IDX;
10080 break;
10081 case 0x9: /* Post-decrement. */
10082 imm = -imm;
10083 /* Fall through. */
10084 case 0xb: /* Post-increment. */
10085 postinc = 1;
10086 writeback = 1;
10087 break;
10088 case 0xd: /* Pre-decrement. */
10089 imm = -imm;
10090 /* Fall through. */
10091 case 0xf: /* Pre-increment. */
10092 tcg_gen_addi_i32(addr, addr, imm);
10093 writeback = 1;
10094 break;
10095 default:
10096 tcg_temp_free_i32(addr);
10097 goto illegal_op;
10101 if (insn & (1 << 20)) {
10102 /* Load. */
10103 tmp = tcg_temp_new_i32();
10104 switch (op) {
10105 case 0:
10106 gen_aa32_ld8u(tmp, addr, memidx);
10107 break;
10108 case 4:
10109 gen_aa32_ld8s(tmp, addr, memidx);
10110 break;
10111 case 1:
10112 gen_aa32_ld16u(tmp, addr, memidx);
10113 break;
10114 case 5:
10115 gen_aa32_ld16s(tmp, addr, memidx);
10116 break;
10117 case 2:
10118 gen_aa32_ld32u(tmp, addr, memidx);
10119 break;
10120 default:
10121 tcg_temp_free_i32(tmp);
10122 tcg_temp_free_i32(addr);
10123 goto illegal_op;
10125 if (rs == 15) {
10126 gen_bx(s, tmp);
10127 } else {
10128 store_reg(s, rs, tmp);
10130 } else {
10131 /* Store. */
10132 tmp = load_reg(s, rs);
10133 switch (op) {
10134 case 0:
10135 gen_aa32_st8(tmp, addr, memidx);
10136 break;
10137 case 1:
10138 gen_aa32_st16(tmp, addr, memidx);
10139 break;
10140 case 2:
10141 gen_aa32_st32(tmp, addr, memidx);
10142 break;
10143 default:
10144 tcg_temp_free_i32(tmp);
10145 tcg_temp_free_i32(addr);
10146 goto illegal_op;
10148 tcg_temp_free_i32(tmp);
10150 if (postinc)
10151 tcg_gen_addi_i32(addr, addr, imm);
10152 if (writeback) {
10153 store_reg(s, rn, addr);
10154 } else {
10155 tcg_temp_free_i32(addr);
10158 break;
10159 default:
10160 goto illegal_op;
10162 return 0;
10163 illegal_op:
10164 return 1;
10167 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
10169 uint32_t val, insn, op, rm, rn, rd, shift, cond;
10170 int32_t offset;
10171 int i;
10172 TCGv_i32 tmp;
10173 TCGv_i32 tmp2;
10174 TCGv_i32 addr;
10176 if (s->condexec_mask) {
10177 cond = s->condexec_cond;
10178 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
10179 s->condlabel = gen_new_label();
10180 arm_gen_test_cc(cond ^ 1, s->condlabel);
10181 s->condjmp = 1;
10185 insn = arm_lduw_code(env, s->pc, s->bswap_code);
10186 s->pc += 2;
10188 switch (insn >> 12) {
10189 case 0: case 1:
10191 rd = insn & 7;
10192 op = (insn >> 11) & 3;
10193 if (op == 3) {
10194 /* add/subtract */
10195 rn = (insn >> 3) & 7;
10196 tmp = load_reg(s, rn);
10197 if (insn & (1 << 10)) {
10198 /* immediate */
10199 tmp2 = tcg_temp_new_i32();
10200 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
10201 } else {
10202 /* reg */
10203 rm = (insn >> 6) & 7;
10204 tmp2 = load_reg(s, rm);
10206 if (insn & (1 << 9)) {
10207 if (s->condexec_mask)
10208 tcg_gen_sub_i32(tmp, tmp, tmp2);
10209 else
10210 gen_sub_CC(tmp, tmp, tmp2);
10211 } else {
10212 if (s->condexec_mask)
10213 tcg_gen_add_i32(tmp, tmp, tmp2);
10214 else
10215 gen_add_CC(tmp, tmp, tmp2);
10217 tcg_temp_free_i32(tmp2);
10218 store_reg(s, rd, tmp);
10219 } else {
10220 /* shift immediate */
10221 rm = (insn >> 3) & 7;
10222 shift = (insn >> 6) & 0x1f;
10223 tmp = load_reg(s, rm);
10224 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
10225 if (!s->condexec_mask)
10226 gen_logic_CC(tmp);
10227 store_reg(s, rd, tmp);
10229 break;
10230 case 2: case 3:
10231 /* arithmetic large immediate */
10232 op = (insn >> 11) & 3;
10233 rd = (insn >> 8) & 0x7;
10234 if (op == 0) { /* mov */
10235 tmp = tcg_temp_new_i32();
10236 tcg_gen_movi_i32(tmp, insn & 0xff);
10237 if (!s->condexec_mask)
10238 gen_logic_CC(tmp);
10239 store_reg(s, rd, tmp);
10240 } else {
10241 tmp = load_reg(s, rd);
10242 tmp2 = tcg_temp_new_i32();
10243 tcg_gen_movi_i32(tmp2, insn & 0xff);
10244 switch (op) {
10245 case 1: /* cmp */
10246 gen_sub_CC(tmp, tmp, tmp2);
10247 tcg_temp_free_i32(tmp);
10248 tcg_temp_free_i32(tmp2);
10249 break;
10250 case 2: /* add */
10251 if (s->condexec_mask)
10252 tcg_gen_add_i32(tmp, tmp, tmp2);
10253 else
10254 gen_add_CC(tmp, tmp, tmp2);
10255 tcg_temp_free_i32(tmp2);
10256 store_reg(s, rd, tmp);
10257 break;
10258 case 3: /* sub */
10259 if (s->condexec_mask)
10260 tcg_gen_sub_i32(tmp, tmp, tmp2);
10261 else
10262 gen_sub_CC(tmp, tmp, tmp2);
10263 tcg_temp_free_i32(tmp2);
10264 store_reg(s, rd, tmp);
10265 break;
10268 break;
10269 case 4:
10270 if (insn & (1 << 11)) {
10271 rd = (insn >> 8) & 7;
10272 /* load pc-relative. Bit 1 of PC is ignored. */
10273 val = s->pc + 2 + ((insn & 0xff) * 4);
10274 val &= ~(uint32_t)2;
10275 addr = tcg_temp_new_i32();
10276 tcg_gen_movi_i32(addr, val);
10277 tmp = tcg_temp_new_i32();
10278 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10279 tcg_temp_free_i32(addr);
10280 store_reg(s, rd, tmp);
10281 break;
10283 if (insn & (1 << 10)) {
10284 /* data processing extended or blx */
10285 rd = (insn & 7) | ((insn >> 4) & 8);
10286 rm = (insn >> 3) & 0xf;
10287 op = (insn >> 8) & 3;
10288 switch (op) {
10289 case 0: /* add */
10290 tmp = load_reg(s, rd);
10291 tmp2 = load_reg(s, rm);
10292 tcg_gen_add_i32(tmp, tmp, tmp2);
10293 tcg_temp_free_i32(tmp2);
10294 store_reg(s, rd, tmp);
10295 break;
10296 case 1: /* cmp */
10297 tmp = load_reg(s, rd);
10298 tmp2 = load_reg(s, rm);
10299 gen_sub_CC(tmp, tmp, tmp2);
10300 tcg_temp_free_i32(tmp2);
10301 tcg_temp_free_i32(tmp);
10302 break;
10303 case 2: /* mov/cpy */
10304 tmp = load_reg(s, rm);
10305 store_reg(s, rd, tmp);
10306 break;
10307 case 3:/* branch [and link] exchange thumb register */
10308 tmp = load_reg(s, rm);
10309 if (insn & (1 << 7)) {
10310 ARCH(5);
10311 val = (uint32_t)s->pc | 1;
10312 tmp2 = tcg_temp_new_i32();
10313 tcg_gen_movi_i32(tmp2, val);
10314 store_reg(s, 14, tmp2);
10316 /* already thumb, no need to check */
10317 gen_bx(s, tmp);
10318 break;
10320 break;
10323 /* data processing register */
10324 rd = insn & 7;
10325 rm = (insn >> 3) & 7;
10326 op = (insn >> 6) & 0xf;
10327 if (op == 2 || op == 3 || op == 4 || op == 7) {
10328 /* the shift/rotate ops want the operands backwards */
10329 val = rm;
10330 rm = rd;
10331 rd = val;
10332 val = 1;
10333 } else {
10334 val = 0;
10337 if (op == 9) { /* neg */
10338 tmp = tcg_temp_new_i32();
10339 tcg_gen_movi_i32(tmp, 0);
10340 } else if (op != 0xf) { /* mvn doesn't read its first operand */
10341 tmp = load_reg(s, rd);
10342 } else {
10343 TCGV_UNUSED_I32(tmp);
10346 tmp2 = load_reg(s, rm);
10347 switch (op) {
10348 case 0x0: /* and */
10349 tcg_gen_and_i32(tmp, tmp, tmp2);
10350 if (!s->condexec_mask)
10351 gen_logic_CC(tmp);
10352 break;
10353 case 0x1: /* eor */
10354 tcg_gen_xor_i32(tmp, tmp, tmp2);
10355 if (!s->condexec_mask)
10356 gen_logic_CC(tmp);
10357 break;
10358 case 0x2: /* lsl */
10359 if (s->condexec_mask) {
10360 gen_shl(tmp2, tmp2, tmp);
10361 } else {
10362 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
10363 gen_logic_CC(tmp2);
10365 break;
10366 case 0x3: /* lsr */
10367 if (s->condexec_mask) {
10368 gen_shr(tmp2, tmp2, tmp);
10369 } else {
10370 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
10371 gen_logic_CC(tmp2);
10373 break;
10374 case 0x4: /* asr */
10375 if (s->condexec_mask) {
10376 gen_sar(tmp2, tmp2, tmp);
10377 } else {
10378 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
10379 gen_logic_CC(tmp2);
10381 break;
10382 case 0x5: /* adc */
10383 if (s->condexec_mask) {
10384 gen_adc(tmp, tmp2);
10385 } else {
10386 gen_adc_CC(tmp, tmp, tmp2);
10388 break;
10389 case 0x6: /* sbc */
10390 if (s->condexec_mask) {
10391 gen_sub_carry(tmp, tmp, tmp2);
10392 } else {
10393 gen_sbc_CC(tmp, tmp, tmp2);
10395 break;
10396 case 0x7: /* ror */
10397 if (s->condexec_mask) {
10398 tcg_gen_andi_i32(tmp, tmp, 0x1f);
10399 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
10400 } else {
10401 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
10402 gen_logic_CC(tmp2);
10404 break;
10405 case 0x8: /* tst */
10406 tcg_gen_and_i32(tmp, tmp, tmp2);
10407 gen_logic_CC(tmp);
10408 rd = 16;
10409 break;
10410 case 0x9: /* neg */
10411 if (s->condexec_mask)
10412 tcg_gen_neg_i32(tmp, tmp2);
10413 else
10414 gen_sub_CC(tmp, tmp, tmp2);
10415 break;
10416 case 0xa: /* cmp */
10417 gen_sub_CC(tmp, tmp, tmp2);
10418 rd = 16;
10419 break;
10420 case 0xb: /* cmn */
10421 gen_add_CC(tmp, tmp, tmp2);
10422 rd = 16;
10423 break;
10424 case 0xc: /* orr */
10425 tcg_gen_or_i32(tmp, tmp, tmp2);
10426 if (!s->condexec_mask)
10427 gen_logic_CC(tmp);
10428 break;
10429 case 0xd: /* mul */
10430 tcg_gen_mul_i32(tmp, tmp, tmp2);
10431 if (!s->condexec_mask)
10432 gen_logic_CC(tmp);
10433 break;
10434 case 0xe: /* bic */
10435 tcg_gen_andc_i32(tmp, tmp, tmp2);
10436 if (!s->condexec_mask)
10437 gen_logic_CC(tmp);
10438 break;
10439 case 0xf: /* mvn */
10440 tcg_gen_not_i32(tmp2, tmp2);
10441 if (!s->condexec_mask)
10442 gen_logic_CC(tmp2);
10443 val = 1;
10444 rm = rd;
10445 break;
10447 if (rd != 16) {
10448 if (val) {
10449 store_reg(s, rm, tmp2);
10450 if (op != 0xf)
10451 tcg_temp_free_i32(tmp);
10452 } else {
10453 store_reg(s, rd, tmp);
10454 tcg_temp_free_i32(tmp2);
10456 } else {
10457 tcg_temp_free_i32(tmp);
10458 tcg_temp_free_i32(tmp2);
10460 break;
10462 case 5:
10463 /* load/store register offset. */
10464 rd = insn & 7;
10465 rn = (insn >> 3) & 7;
10466 rm = (insn >> 6) & 7;
10467 op = (insn >> 9) & 7;
10468 addr = load_reg(s, rn);
10469 tmp = load_reg(s, rm);
10470 tcg_gen_add_i32(addr, addr, tmp);
10471 tcg_temp_free_i32(tmp);
10473 if (op < 3) { /* store */
10474 tmp = load_reg(s, rd);
10475 } else {
10476 tmp = tcg_temp_new_i32();
10479 switch (op) {
10480 case 0: /* str */
10481 gen_aa32_st32(tmp, addr, get_mem_index(s));
10482 break;
10483 case 1: /* strh */
10484 gen_aa32_st16(tmp, addr, get_mem_index(s));
10485 break;
10486 case 2: /* strb */
10487 gen_aa32_st8(tmp, addr, get_mem_index(s));
10488 break;
10489 case 3: /* ldrsb */
10490 gen_aa32_ld8s(tmp, addr, get_mem_index(s));
10491 break;
10492 case 4: /* ldr */
10493 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10494 break;
10495 case 5: /* ldrh */
10496 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
10497 break;
10498 case 6: /* ldrb */
10499 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
10500 break;
10501 case 7: /* ldrsh */
10502 gen_aa32_ld16s(tmp, addr, get_mem_index(s));
10503 break;
10505 if (op >= 3) { /* load */
10506 store_reg(s, rd, tmp);
10507 } else {
10508 tcg_temp_free_i32(tmp);
10510 tcg_temp_free_i32(addr);
10511 break;
10513 case 6:
10514 /* load/store word immediate offset */
10515 rd = insn & 7;
10516 rn = (insn >> 3) & 7;
10517 addr = load_reg(s, rn);
10518 val = (insn >> 4) & 0x7c;
10519 tcg_gen_addi_i32(addr, addr, val);
10521 if (insn & (1 << 11)) {
10522 /* load */
10523 tmp = tcg_temp_new_i32();
10524 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10525 store_reg(s, rd, tmp);
10526 } else {
10527 /* store */
10528 tmp = load_reg(s, rd);
10529 gen_aa32_st32(tmp, addr, get_mem_index(s));
10530 tcg_temp_free_i32(tmp);
10532 tcg_temp_free_i32(addr);
10533 break;
10535 case 7:
10536 /* load/store byte immediate offset */
10537 rd = insn & 7;
10538 rn = (insn >> 3) & 7;
10539 addr = load_reg(s, rn);
10540 val = (insn >> 6) & 0x1f;
10541 tcg_gen_addi_i32(addr, addr, val);
10543 if (insn & (1 << 11)) {
10544 /* load */
10545 tmp = tcg_temp_new_i32();
10546 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
10547 store_reg(s, rd, tmp);
10548 } else {
10549 /* store */
10550 tmp = load_reg(s, rd);
10551 gen_aa32_st8(tmp, addr, get_mem_index(s));
10552 tcg_temp_free_i32(tmp);
10554 tcg_temp_free_i32(addr);
10555 break;
10557 case 8:
10558 /* load/store halfword immediate offset */
10559 rd = insn & 7;
10560 rn = (insn >> 3) & 7;
10561 addr = load_reg(s, rn);
10562 val = (insn >> 5) & 0x3e;
10563 tcg_gen_addi_i32(addr, addr, val);
10565 if (insn & (1 << 11)) {
10566 /* load */
10567 tmp = tcg_temp_new_i32();
10568 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
10569 store_reg(s, rd, tmp);
10570 } else {
10571 /* store */
10572 tmp = load_reg(s, rd);
10573 gen_aa32_st16(tmp, addr, get_mem_index(s));
10574 tcg_temp_free_i32(tmp);
10576 tcg_temp_free_i32(addr);
10577 break;
10579 case 9:
10580 /* load/store from stack */
10581 rd = (insn >> 8) & 7;
10582 addr = load_reg(s, 13);
10583 val = (insn & 0xff) * 4;
10584 tcg_gen_addi_i32(addr, addr, val);
10586 if (insn & (1 << 11)) {
10587 /* load */
10588 tmp = tcg_temp_new_i32();
10589 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10590 store_reg(s, rd, tmp);
10591 } else {
10592 /* store */
10593 tmp = load_reg(s, rd);
10594 gen_aa32_st32(tmp, addr, get_mem_index(s));
10595 tcg_temp_free_i32(tmp);
10597 tcg_temp_free_i32(addr);
10598 break;
10600 case 10:
10601 /* add to high reg */
10602 rd = (insn >> 8) & 7;
10603 if (insn & (1 << 11)) {
10604 /* SP */
10605 tmp = load_reg(s, 13);
10606 } else {
10607 /* PC. bit 1 is ignored. */
10608 tmp = tcg_temp_new_i32();
10609 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
10611 val = (insn & 0xff) * 4;
10612 tcg_gen_addi_i32(tmp, tmp, val);
10613 store_reg(s, rd, tmp);
10614 break;
10616 case 11:
10617 /* misc */
10618 op = (insn >> 8) & 0xf;
10619 switch (op) {
10620 case 0:
10621 /* adjust stack pointer */
10622 tmp = load_reg(s, 13);
10623 val = (insn & 0x7f) * 4;
10624 if (insn & (1 << 7))
10625 val = -(int32_t)val;
10626 tcg_gen_addi_i32(tmp, tmp, val);
10627 store_reg(s, 13, tmp);
10628 break;
10630 case 2: /* sign/zero extend. */
10631 ARCH(6);
10632 rd = insn & 7;
10633 rm = (insn >> 3) & 7;
10634 tmp = load_reg(s, rm);
10635 switch ((insn >> 6) & 3) {
10636 case 0: gen_sxth(tmp); break;
10637 case 1: gen_sxtb(tmp); break;
10638 case 2: gen_uxth(tmp); break;
10639 case 3: gen_uxtb(tmp); break;
10641 store_reg(s, rd, tmp);
10642 break;
10643 case 4: case 5: case 0xc: case 0xd:
10644 /* push/pop */
10645 addr = load_reg(s, 13);
10646 if (insn & (1 << 8))
10647 offset = 4;
10648 else
10649 offset = 0;
10650 for (i = 0; i < 8; i++) {
10651 if (insn & (1 << i))
10652 offset += 4;
10654 if ((insn & (1 << 11)) == 0) {
10655 tcg_gen_addi_i32(addr, addr, -offset);
10657 for (i = 0; i < 8; i++) {
10658 if (insn & (1 << i)) {
10659 if (insn & (1 << 11)) {
10660 /* pop */
10661 tmp = tcg_temp_new_i32();
10662 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10663 store_reg(s, i, tmp);
10664 } else {
10665 /* push */
10666 tmp = load_reg(s, i);
10667 gen_aa32_st32(tmp, addr, get_mem_index(s));
10668 tcg_temp_free_i32(tmp);
10670 /* advance to the next address. */
10671 tcg_gen_addi_i32(addr, addr, 4);
10674 TCGV_UNUSED_I32(tmp);
10675 if (insn & (1 << 8)) {
10676 if (insn & (1 << 11)) {
10677 /* pop pc */
10678 tmp = tcg_temp_new_i32();
10679 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10680 /* don't set the pc until the rest of the instruction
10681 has completed */
10682 } else {
10683 /* push lr */
10684 tmp = load_reg(s, 14);
10685 gen_aa32_st32(tmp, addr, get_mem_index(s));
10686 tcg_temp_free_i32(tmp);
10688 tcg_gen_addi_i32(addr, addr, 4);
10690 if ((insn & (1 << 11)) == 0) {
10691 tcg_gen_addi_i32(addr, addr, -offset);
10693 /* write back the new stack pointer */
10694 store_reg(s, 13, addr);
10695 /* set the new PC value */
10696 if ((insn & 0x0900) == 0x0900) {
10697 store_reg_from_load(env, s, 15, tmp);
10699 break;
10701 case 1: case 3: case 9: case 11: /* czb */
10702 rm = insn & 7;
10703 tmp = load_reg(s, rm);
10704 s->condlabel = gen_new_label();
10705 s->condjmp = 1;
10706 if (insn & (1 << 11))
10707 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
10708 else
10709 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
10710 tcg_temp_free_i32(tmp);
10711 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
10712 val = (uint32_t)s->pc + 2;
10713 val += offset;
10714 gen_jmp(s, val);
10715 break;
10717 case 15: /* IT, nop-hint. */
10718 if ((insn & 0xf) == 0) {
10719 gen_nop_hint(s, (insn >> 4) & 0xf);
10720 break;
10722 /* If Then. */
10723 s->condexec_cond = (insn >> 4) & 0xe;
10724 s->condexec_mask = insn & 0x1f;
10725 /* No actual code generated for this insn, just setup state. */
10726 break;
10728 case 0xe: /* bkpt */
10730 int imm8 = extract32(insn, 0, 8);
10731 ARCH(5);
10732 gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true));
10733 break;
10736 case 0xa: /* rev */
10737 ARCH(6);
10738 rn = (insn >> 3) & 0x7;
10739 rd = insn & 0x7;
10740 tmp = load_reg(s, rn);
10741 switch ((insn >> 6) & 3) {
10742 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
10743 case 1: gen_rev16(tmp); break;
10744 case 3: gen_revsh(tmp); break;
10745 default: goto illegal_op;
10747 store_reg(s, rd, tmp);
10748 break;
10750 case 6:
10751 switch ((insn >> 5) & 7) {
10752 case 2:
10753 /* setend */
10754 ARCH(6);
10755 if (((insn >> 3) & 1) != s->bswap_code) {
10756 /* Dynamic endianness switching not implemented. */
10757 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
10758 goto illegal_op;
10760 break;
10761 case 3:
10762 /* cps */
10763 ARCH(6);
10764 if (IS_USER(s)) {
10765 break;
10767 if (IS_M(env)) {
10768 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
10769 /* FAULTMASK */
10770 if (insn & 1) {
10771 addr = tcg_const_i32(19);
10772 gen_helper_v7m_msr(cpu_env, addr, tmp);
10773 tcg_temp_free_i32(addr);
10775 /* PRIMASK */
10776 if (insn & 2) {
10777 addr = tcg_const_i32(16);
10778 gen_helper_v7m_msr(cpu_env, addr, tmp);
10779 tcg_temp_free_i32(addr);
10781 tcg_temp_free_i32(tmp);
10782 gen_lookup_tb(s);
10783 } else {
10784 if (insn & (1 << 4)) {
10785 shift = CPSR_A | CPSR_I | CPSR_F;
10786 } else {
10787 shift = 0;
10789 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
10791 break;
10792 default:
10793 goto undef;
10795 break;
10797 default:
10798 goto undef;
10800 break;
10802 case 12:
10804 /* load/store multiple */
10805 TCGv_i32 loaded_var;
10806 TCGV_UNUSED_I32(loaded_var);
10807 rn = (insn >> 8) & 0x7;
10808 addr = load_reg(s, rn);
10809 for (i = 0; i < 8; i++) {
10810 if (insn & (1 << i)) {
10811 if (insn & (1 << 11)) {
10812 /* load */
10813 tmp = tcg_temp_new_i32();
10814 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10815 if (i == rn) {
10816 loaded_var = tmp;
10817 } else {
10818 store_reg(s, i, tmp);
10820 } else {
10821 /* store */
10822 tmp = load_reg(s, i);
10823 gen_aa32_st32(tmp, addr, get_mem_index(s));
10824 tcg_temp_free_i32(tmp);
10826 /* advance to the next address */
10827 tcg_gen_addi_i32(addr, addr, 4);
10830 if ((insn & (1 << rn)) == 0) {
10831 /* base reg not in list: base register writeback */
10832 store_reg(s, rn, addr);
10833 } else {
10834 /* base reg in list: if load, complete it now */
10835 if (insn & (1 << 11)) {
10836 store_reg(s, rn, loaded_var);
10838 tcg_temp_free_i32(addr);
10840 break;
10842 case 13:
10843 /* conditional branch or swi */
10844 cond = (insn >> 8) & 0xf;
10845 if (cond == 0xe)
10846 goto undef;
10848 if (cond == 0xf) {
10849 /* swi */
10850 gen_set_pc_im(s, s->pc);
10851 s->svc_imm = extract32(insn, 0, 8);
10852 s->is_jmp = DISAS_SWI;
10853 break;
10855 /* generate a conditional jump to next instruction */
10856 s->condlabel = gen_new_label();
10857 arm_gen_test_cc(cond ^ 1, s->condlabel);
10858 s->condjmp = 1;
10860 /* jump to the offset */
10861 val = (uint32_t)s->pc + 2;
10862 offset = ((int32_t)insn << 24) >> 24;
10863 val += offset << 1;
10864 gen_jmp(s, val);
10865 break;
10867 case 14:
10868 if (insn & (1 << 11)) {
10869 if (disas_thumb2_insn(env, s, insn))
10870 goto undef32;
10871 break;
10873 /* unconditional branch */
10874 val = (uint32_t)s->pc;
10875 offset = ((int32_t)insn << 21) >> 21;
10876 val += (offset << 1) + 2;
10877 gen_jmp(s, val);
10878 break;
10880 case 15:
10881 if (disas_thumb2_insn(env, s, insn))
10882 goto undef32;
10883 break;
10885 return;
10886 undef32:
10887 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
10888 return;
10889 illegal_op:
10890 undef:
10891 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized());
10894 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
10895 basic block 'tb'. If search_pc is TRUE, also generate PC
10896 information for each intermediate instruction. */
10897 static inline void gen_intermediate_code_internal(ARMCPU *cpu,
10898 TranslationBlock *tb,
10899 bool search_pc)
10901 CPUState *cs = CPU(cpu);
10902 CPUARMState *env = &cpu->env;
10903 DisasContext dc1, *dc = &dc1;
10904 CPUBreakpoint *bp;
10905 uint16_t *gen_opc_end;
10906 int j, lj;
10907 target_ulong pc_start;
10908 target_ulong next_page_start;
10909 int num_insns;
10910 int max_insns;
10912 /* generate intermediate code */
10914 /* The A64 decoder has its own top level loop, because it doesn't need
10915 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
10917 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
10918 gen_intermediate_code_internal_a64(cpu, tb, search_pc);
10919 return;
10922 pc_start = tb->pc;
10924 dc->tb = tb;
10926 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
10928 dc->is_jmp = DISAS_NEXT;
10929 dc->pc = pc_start;
10930 dc->singlestep_enabled = cs->singlestep_enabled;
10931 dc->condjmp = 0;
10933 dc->aarch64 = 0;
10934 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
10935 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
10936 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
10937 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
10938 #if !defined(CONFIG_USER_ONLY)
10939 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
10940 #endif
10941 dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
10942 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
10943 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
10944 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
10945 dc->cp_regs = cpu->cp_regs;
10946 dc->current_pl = arm_current_pl(env);
10947 dc->features = env->features;
10949 /* Single step state. The code-generation logic here is:
10950 * SS_ACTIVE == 0:
10951 * generate code with no special handling for single-stepping (except
10952 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
10953 * this happens anyway because those changes are all system register or
10954 * PSTATE writes).
10955 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
10956 * emit code for one insn
10957 * emit code to clear PSTATE.SS
10958 * emit code to generate software step exception for completed step
10959 * end TB (as usual for having generated an exception)
10960 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
10961 * emit code to generate a software step exception
10962 * end the TB
10964 dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);
10965 dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);
10966 dc->is_ldex = false;
10967 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
10969 cpu_F0s = tcg_temp_new_i32();
10970 cpu_F1s = tcg_temp_new_i32();
10971 cpu_F0d = tcg_temp_new_i64();
10972 cpu_F1d = tcg_temp_new_i64();
10973 cpu_V0 = cpu_F0d;
10974 cpu_V1 = cpu_F1d;
10975 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
10976 cpu_M0 = tcg_temp_new_i64();
10977 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
10978 lj = -1;
10979 num_insns = 0;
10980 max_insns = tb->cflags & CF_COUNT_MASK;
10981 if (max_insns == 0)
10982 max_insns = CF_COUNT_MASK;
10984 gen_tb_start();
10986 tcg_clear_temp_count();
10988 /* A note on handling of the condexec (IT) bits:
10990 * We want to avoid the overhead of having to write the updated condexec
10991 * bits back to the CPUARMState for every instruction in an IT block. So:
10992 * (1) if the condexec bits are not already zero then we write
10993 * zero back into the CPUARMState now. This avoids complications trying
10994 * to do it at the end of the block. (For example if we don't do this
10995 * it's hard to identify whether we can safely skip writing condexec
10996 * at the end of the TB, which we definitely want to do for the case
10997 * where a TB doesn't do anything with the IT state at all.)
10998 * (2) if we are going to leave the TB then we call gen_set_condexec()
10999 * which will write the correct value into CPUARMState if zero is wrong.
11000 * This is done both for leaving the TB at the end, and for leaving
11001 * it because of an exception we know will happen, which is done in
11002 * gen_exception_insn(). The latter is necessary because we need to
11003 * leave the TB with the PC/IT state just prior to execution of the
11004 * instruction which caused the exception.
11005 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
11006 * then the CPUARMState will be wrong and we need to reset it.
11007 * This is handled in the same way as restoration of the
11008 * PC in these situations: we will be called again with search_pc=1
11009 * and generate a mapping of the condexec bits for each PC in
11010 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
11011 * this to restore the condexec bits.
11013 * Note that there are no instructions which can read the condexec
11014 * bits, and none which can write non-static values to them, so
11015 * we don't need to care about whether CPUARMState is correct in the
11016 * middle of a TB.
11019 /* Reset the conditional execution bits immediately. This avoids
11020 complications trying to do it at the end of the block. */
11021 if (dc->condexec_mask || dc->condexec_cond)
11023 TCGv_i32 tmp = tcg_temp_new_i32();
11024 tcg_gen_movi_i32(tmp, 0);
11025 store_cpu_field(tmp, condexec_bits);
11027 do {
11028 #ifdef CONFIG_USER_ONLY
11029 /* Intercept jump to the magic kernel page. */
11030 if (dc->pc >= 0xffff0000) {
11031 /* We always get here via a jump, so know we are not in a
11032 conditional execution block. */
11033 gen_exception_internal(EXCP_KERNEL_TRAP);
11034 dc->is_jmp = DISAS_UPDATE;
11035 break;
11037 #else
11038 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
11039 /* We always get here via a jump, so know we are not in a
11040 conditional execution block. */
11041 gen_exception_internal(EXCP_EXCEPTION_EXIT);
11042 dc->is_jmp = DISAS_UPDATE;
11043 break;
11045 #endif
11047 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
11048 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
11049 if (bp->pc == dc->pc) {
11050 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
11051 /* Advance PC so that clearing the breakpoint will
11052 invalidate this TB. */
11053 dc->pc += 2;
11054 goto done_generating;
11058 if (search_pc) {
11059 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
11060 if (lj < j) {
11061 lj++;
11062 while (lj < j)
11063 tcg_ctx.gen_opc_instr_start[lj++] = 0;
11065 tcg_ctx.gen_opc_pc[lj] = dc->pc;
11066 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
11067 tcg_ctx.gen_opc_instr_start[lj] = 1;
11068 tcg_ctx.gen_opc_icount[lj] = num_insns;
11071 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
11072 gen_io_start();
11074 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
11075 tcg_gen_debug_insn_start(dc->pc);
11078 if (dc->ss_active && !dc->pstate_ss) {
11079 /* Singlestep state is Active-pending.
11080 * If we're in this state at the start of a TB then either
11081 * a) we just took an exception to an EL which is being debugged
11082 * and this is the first insn in the exception handler
11083 * b) debug exceptions were masked and we just unmasked them
11084 * without changing EL (eg by clearing PSTATE.D)
11085 * In either case we're going to take a swstep exception in the
11086 * "did not step an insn" case, and so the syndrome ISV and EX
11087 * bits should be zero.
11089 assert(num_insns == 0);
11090 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0));
11091 goto done_generating;
11094 if (dc->thumb) {
11095 disas_thumb_insn(env, dc);
11096 if (dc->condexec_mask) {
11097 dc->condexec_cond = (dc->condexec_cond & 0xe)
11098 | ((dc->condexec_mask >> 4) & 1);
11099 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
11100 if (dc->condexec_mask == 0) {
11101 dc->condexec_cond = 0;
11104 } else {
11105 disas_arm_insn(env, dc);
11108 if (dc->condjmp && !dc->is_jmp) {
11109 gen_set_label(dc->condlabel);
11110 dc->condjmp = 0;
11113 if (tcg_check_temp_count()) {
11114 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
11115 dc->pc);
11118 /* Translation stops when a conditional branch is encountered.
11119 * Otherwise the subsequent code could get translated several times.
11120 * Also stop translation when a page boundary is reached. This
11121 * ensures prefetch aborts occur at the right place. */
11122 num_insns ++;
11123 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
11124 !cs->singlestep_enabled &&
11125 !singlestep &&
11126 !dc->ss_active &&
11127 dc->pc < next_page_start &&
11128 num_insns < max_insns);
11130 if (tb->cflags & CF_LAST_IO) {
11131 if (dc->condjmp) {
11132 /* FIXME: This can theoretically happen with self-modifying
11133 code. */
11134 cpu_abort(cs, "IO on conditional branch instruction");
11136 gen_io_end();
11139 /* At this stage dc->condjmp will only be set when the skipped
11140 instruction was a conditional branch or trap, and the PC has
11141 already been written. */
11142 if (unlikely(cs->singlestep_enabled || dc->ss_active)) {
11143 /* Make sure the pc is updated, and raise a debug exception. */
11144 if (dc->condjmp) {
11145 gen_set_condexec(dc);
11146 if (dc->is_jmp == DISAS_SWI) {
11147 gen_ss_advance(dc);
11148 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
11149 } else if (dc->ss_active) {
11150 gen_step_complete_exception(dc);
11151 } else {
11152 gen_exception_internal(EXCP_DEBUG);
11154 gen_set_label(dc->condlabel);
11156 if (dc->condjmp || !dc->is_jmp) {
11157 gen_set_pc_im(dc, dc->pc);
11158 dc->condjmp = 0;
11160 gen_set_condexec(dc);
11161 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
11162 gen_ss_advance(dc);
11163 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
11164 } else if (dc->ss_active) {
11165 gen_step_complete_exception(dc);
11166 } else {
11167 /* FIXME: Single stepping a WFI insn will not halt
11168 the CPU. */
11169 gen_exception_internal(EXCP_DEBUG);
11171 } else {
11172 /* While branches must always occur at the end of an IT block,
11173 there are a few other things that can cause us to terminate
11174 the TB in the middle of an IT block:
11175 - Exception generating instructions (bkpt, swi, undefined).
11176 - Page boundaries.
11177 - Hardware watchpoints.
11178 Hardware breakpoints have already been handled and skip this code.
11180 gen_set_condexec(dc);
11181 switch(dc->is_jmp) {
11182 case DISAS_NEXT:
11183 gen_goto_tb(dc, 1, dc->pc);
11184 break;
11185 default:
11186 case DISAS_JUMP:
11187 case DISAS_UPDATE:
11188 /* indicate that the hash table must be used to find the next TB */
11189 tcg_gen_exit_tb(0);
11190 break;
11191 case DISAS_TB_JUMP:
11192 /* nothing more to generate */
11193 break;
11194 case DISAS_WFI:
11195 gen_helper_wfi(cpu_env);
11196 break;
11197 case DISAS_WFE:
11198 gen_helper_wfe(cpu_env);
11199 break;
11200 case DISAS_SWI:
11201 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
11202 break;
11204 if (dc->condjmp) {
11205 gen_set_label(dc->condlabel);
11206 gen_set_condexec(dc);
11207 gen_goto_tb(dc, 1, dc->pc);
11208 dc->condjmp = 0;
11212 done_generating:
11213 gen_tb_end(tb, num_insns);
11214 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
11216 #ifdef DEBUG_DISAS
11217 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
11218 qemu_log("----------------\n");
11219 qemu_log("IN: %s\n", lookup_symbol(pc_start));
11220 log_target_disas(env, pc_start, dc->pc - pc_start,
11221 dc->thumb | (dc->bswap_code << 1));
11222 qemu_log("\n");
11224 #endif
11225 if (search_pc) {
11226 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
11227 lj++;
11228 while (lj <= j)
11229 tcg_ctx.gen_opc_instr_start[lj++] = 0;
11230 } else {
11231 tb->size = dc->pc - pc_start;
11232 tb->icount = num_insns;
11236 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
11238 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
11241 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
11243 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
11246 static const char *cpu_mode_names[16] = {
11247 "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
11248 "???", "???", "hyp", "und", "???", "???", "???", "sys"
11251 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11252 int flags)
11254 ARMCPU *cpu = ARM_CPU(cs);
11255 CPUARMState *env = &cpu->env;
11256 int i;
11257 uint32_t psr;
11259 if (is_a64(env)) {
11260 aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
11261 return;
11264 for(i=0;i<16;i++) {
11265 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
11266 if ((i % 4) == 3)
11267 cpu_fprintf(f, "\n");
11268 else
11269 cpu_fprintf(f, " ");
11271 psr = cpsr_read(env);
11272 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
11273 psr,
11274 psr & (1 << 31) ? 'N' : '-',
11275 psr & (1 << 30) ? 'Z' : '-',
11276 psr & (1 << 29) ? 'C' : '-',
11277 psr & (1 << 28) ? 'V' : '-',
11278 psr & CPSR_T ? 'T' : 'A',
11279 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
11281 if (flags & CPU_DUMP_FPU) {
11282 int numvfpregs = 0;
11283 if (arm_feature(env, ARM_FEATURE_VFP)) {
11284 numvfpregs += 16;
11286 if (arm_feature(env, ARM_FEATURE_VFP3)) {
11287 numvfpregs += 16;
11289 for (i = 0; i < numvfpregs; i++) {
11290 uint64_t v = float64_val(env->vfp.regs[i]);
11291 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
11292 i * 2, (uint32_t)v,
11293 i * 2 + 1, (uint32_t)(v >> 32),
11294 i, v);
11296 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
11300 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
11302 if (is_a64(env)) {
11303 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
11304 env->condexec_bits = 0;
11305 } else {
11306 env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
11307 env->condexec_bits = gen_opc_condexec_bits[pc_pos];