virtio-mmio: Drop useless bus->allow_hotplug = 0
[qemu/ar7.git] / target-arm / translate.c
blob8a2994fcb4a5a5a28b7fee7aa082b642dcbcb162
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;
7005 /* First check for coprocessor space used for XScale/iwMMXt insns */
7006 if (arm_feature(env, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
7007 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7008 return 1;
7010 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7011 return disas_iwmmxt_insn(env, s, insn);
7012 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
7013 return disas_dsp_insn(env, s, insn);
7015 return 1;
7018 /* Otherwise treat as a generic register access */
7019 is64 = (insn & (1 << 25)) == 0;
7020 if (!is64 && ((insn & (1 << 4)) == 0)) {
7021 /* cdp */
7022 return 1;
7025 crm = insn & 0xf;
7026 if (is64) {
7027 crn = 0;
7028 opc1 = (insn >> 4) & 0xf;
7029 opc2 = 0;
7030 rt2 = (insn >> 16) & 0xf;
7031 } else {
7032 crn = (insn >> 16) & 0xf;
7033 opc1 = (insn >> 21) & 7;
7034 opc2 = (insn >> 5) & 7;
7035 rt2 = 0;
7037 isread = (insn >> 20) & 1;
7038 rt = (insn >> 12) & 0xf;
7040 ri = get_arm_cp_reginfo(s->cp_regs,
7041 ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
7042 if (ri) {
7043 /* Check access permissions */
7044 if (!cp_access_ok(s->current_pl, ri, isread)) {
7045 return 1;
7048 if (ri->accessfn ||
7049 (arm_feature(env, ARM_FEATURE_XSCALE) && cpnum < 14)) {
7050 /* Emit code to perform further access permissions checks at
7051 * runtime; this may result in an exception.
7052 * Note that on XScale all cp0..c13 registers do an access check
7053 * call in order to handle c15_cpar.
7055 TCGv_ptr tmpptr;
7056 TCGv_i32 tcg_syn;
7057 uint32_t syndrome;
7059 /* Note that since we are an implementation which takes an
7060 * exception on a trapped conditional instruction only if the
7061 * instruction passes its condition code check, we can take
7062 * advantage of the clause in the ARM ARM that allows us to set
7063 * the COND field in the instruction to 0xE in all cases.
7064 * We could fish the actual condition out of the insn (ARM)
7065 * or the condexec bits (Thumb) but it isn't necessary.
7067 switch (cpnum) {
7068 case 14:
7069 if (is64) {
7070 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7071 isread, s->thumb);
7072 } else {
7073 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7074 rt, isread, s->thumb);
7076 break;
7077 case 15:
7078 if (is64) {
7079 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7080 isread, s->thumb);
7081 } else {
7082 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7083 rt, isread, s->thumb);
7085 break;
7086 default:
7087 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7088 * so this can only happen if this is an ARMv7 or earlier CPU,
7089 * in which case the syndrome information won't actually be
7090 * guest visible.
7092 assert(!arm_feature(env, ARM_FEATURE_V8));
7093 syndrome = syn_uncategorized();
7094 break;
7097 gen_set_pc_im(s, s->pc);
7098 tmpptr = tcg_const_ptr(ri);
7099 tcg_syn = tcg_const_i32(syndrome);
7100 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
7101 tcg_temp_free_ptr(tmpptr);
7102 tcg_temp_free_i32(tcg_syn);
7105 /* Handle special cases first */
7106 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7107 case ARM_CP_NOP:
7108 return 0;
7109 case ARM_CP_WFI:
7110 if (isread) {
7111 return 1;
7113 gen_set_pc_im(s, s->pc);
7114 s->is_jmp = DISAS_WFI;
7115 return 0;
7116 default:
7117 break;
7120 if (use_icount && (ri->type & ARM_CP_IO)) {
7121 gen_io_start();
7124 if (isread) {
7125 /* Read */
7126 if (is64) {
7127 TCGv_i64 tmp64;
7128 TCGv_i32 tmp;
7129 if (ri->type & ARM_CP_CONST) {
7130 tmp64 = tcg_const_i64(ri->resetvalue);
7131 } else if (ri->readfn) {
7132 TCGv_ptr tmpptr;
7133 tmp64 = tcg_temp_new_i64();
7134 tmpptr = tcg_const_ptr(ri);
7135 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7136 tcg_temp_free_ptr(tmpptr);
7137 } else {
7138 tmp64 = tcg_temp_new_i64();
7139 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7141 tmp = tcg_temp_new_i32();
7142 tcg_gen_trunc_i64_i32(tmp, tmp64);
7143 store_reg(s, rt, tmp);
7144 tcg_gen_shri_i64(tmp64, tmp64, 32);
7145 tmp = tcg_temp_new_i32();
7146 tcg_gen_trunc_i64_i32(tmp, tmp64);
7147 tcg_temp_free_i64(tmp64);
7148 store_reg(s, rt2, tmp);
7149 } else {
7150 TCGv_i32 tmp;
7151 if (ri->type & ARM_CP_CONST) {
7152 tmp = tcg_const_i32(ri->resetvalue);
7153 } else if (ri->readfn) {
7154 TCGv_ptr tmpptr;
7155 tmp = tcg_temp_new_i32();
7156 tmpptr = tcg_const_ptr(ri);
7157 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7158 tcg_temp_free_ptr(tmpptr);
7159 } else {
7160 tmp = load_cpu_offset(ri->fieldoffset);
7162 if (rt == 15) {
7163 /* Destination register of r15 for 32 bit loads sets
7164 * the condition codes from the high 4 bits of the value
7166 gen_set_nzcv(tmp);
7167 tcg_temp_free_i32(tmp);
7168 } else {
7169 store_reg(s, rt, tmp);
7172 } else {
7173 /* Write */
7174 if (ri->type & ARM_CP_CONST) {
7175 /* If not forbidden by access permissions, treat as WI */
7176 return 0;
7179 if (is64) {
7180 TCGv_i32 tmplo, tmphi;
7181 TCGv_i64 tmp64 = tcg_temp_new_i64();
7182 tmplo = load_reg(s, rt);
7183 tmphi = load_reg(s, rt2);
7184 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7185 tcg_temp_free_i32(tmplo);
7186 tcg_temp_free_i32(tmphi);
7187 if (ri->writefn) {
7188 TCGv_ptr tmpptr = tcg_const_ptr(ri);
7189 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7190 tcg_temp_free_ptr(tmpptr);
7191 } else {
7192 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7194 tcg_temp_free_i64(tmp64);
7195 } else {
7196 if (ri->writefn) {
7197 TCGv_i32 tmp;
7198 TCGv_ptr tmpptr;
7199 tmp = load_reg(s, rt);
7200 tmpptr = tcg_const_ptr(ri);
7201 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7202 tcg_temp_free_ptr(tmpptr);
7203 tcg_temp_free_i32(tmp);
7204 } else {
7205 TCGv_i32 tmp = load_reg(s, rt);
7206 store_cpu_offset(tmp, ri->fieldoffset);
7211 if (use_icount && (ri->type & ARM_CP_IO)) {
7212 /* I/O operations must end the TB here (whether read or write) */
7213 gen_io_end();
7214 gen_lookup_tb(s);
7215 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
7216 /* We default to ending the TB on a coprocessor register write,
7217 * but allow this to be suppressed by the register definition
7218 * (usually only necessary to work around guest bugs).
7220 gen_lookup_tb(s);
7223 return 0;
7226 /* Unknown register; this might be a guest error or a QEMU
7227 * unimplemented feature.
7229 if (is64) {
7230 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7231 "64 bit system register cp:%d opc1: %d crm:%d\n",
7232 isread ? "read" : "write", cpnum, opc1, crm);
7233 } else {
7234 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7235 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d\n",
7236 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2);
7239 return 1;
7243 /* Store a 64-bit value to a register pair. Clobbers val. */
7244 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
7246 TCGv_i32 tmp;
7247 tmp = tcg_temp_new_i32();
7248 tcg_gen_trunc_i64_i32(tmp, val);
7249 store_reg(s, rlow, tmp);
7250 tmp = tcg_temp_new_i32();
7251 tcg_gen_shri_i64(val, val, 32);
7252 tcg_gen_trunc_i64_i32(tmp, val);
7253 store_reg(s, rhigh, tmp);
7256 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
7257 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
7259 TCGv_i64 tmp;
7260 TCGv_i32 tmp2;
7262 /* Load value and extend to 64 bits. */
7263 tmp = tcg_temp_new_i64();
7264 tmp2 = load_reg(s, rlow);
7265 tcg_gen_extu_i32_i64(tmp, tmp2);
7266 tcg_temp_free_i32(tmp2);
7267 tcg_gen_add_i64(val, val, tmp);
7268 tcg_temp_free_i64(tmp);
7271 /* load and add a 64-bit value from a register pair. */
7272 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
7274 TCGv_i64 tmp;
7275 TCGv_i32 tmpl;
7276 TCGv_i32 tmph;
7278 /* Load 64-bit value rd:rn. */
7279 tmpl = load_reg(s, rlow);
7280 tmph = load_reg(s, rhigh);
7281 tmp = tcg_temp_new_i64();
7282 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7283 tcg_temp_free_i32(tmpl);
7284 tcg_temp_free_i32(tmph);
7285 tcg_gen_add_i64(val, val, tmp);
7286 tcg_temp_free_i64(tmp);
7289 /* Set N and Z flags from hi|lo. */
7290 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
7292 tcg_gen_mov_i32(cpu_NF, hi);
7293 tcg_gen_or_i32(cpu_ZF, lo, hi);
7296 /* Load/Store exclusive instructions are implemented by remembering
7297 the value/address loaded, and seeing if these are the same
7298 when the store is performed. This should be sufficient to implement
7299 the architecturally mandated semantics, and avoids having to monitor
7300 regular stores.
7302 In system emulation mode only one CPU will be running at once, so
7303 this sequence is effectively atomic. In user emulation mode we
7304 throw an exception and handle the atomic operation elsewhere. */
7305 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
7306 TCGv_i32 addr, int size)
7308 TCGv_i32 tmp = tcg_temp_new_i32();
7310 s->is_ldex = true;
7312 switch (size) {
7313 case 0:
7314 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
7315 break;
7316 case 1:
7317 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
7318 break;
7319 case 2:
7320 case 3:
7321 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7322 break;
7323 default:
7324 abort();
7327 if (size == 3) {
7328 TCGv_i32 tmp2 = tcg_temp_new_i32();
7329 TCGv_i32 tmp3 = tcg_temp_new_i32();
7331 tcg_gen_addi_i32(tmp2, addr, 4);
7332 gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
7333 tcg_temp_free_i32(tmp2);
7334 tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
7335 store_reg(s, rt2, tmp3);
7336 } else {
7337 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
7340 store_reg(s, rt, tmp);
7341 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
7344 static void gen_clrex(DisasContext *s)
7346 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7349 #ifdef CONFIG_USER_ONLY
7350 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7351 TCGv_i32 addr, int size)
7353 tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
7354 tcg_gen_movi_i32(cpu_exclusive_info,
7355 size | (rd << 4) | (rt << 8) | (rt2 << 12));
7356 gen_exception_internal_insn(s, 4, EXCP_STREX);
7358 #else
7359 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7360 TCGv_i32 addr, int size)
7362 TCGv_i32 tmp;
7363 TCGv_i64 val64, extaddr;
7364 int done_label;
7365 int fail_label;
7367 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7368 [addr] = {Rt};
7369 {Rd} = 0;
7370 } else {
7371 {Rd} = 1;
7372 } */
7373 fail_label = gen_new_label();
7374 done_label = gen_new_label();
7375 extaddr = tcg_temp_new_i64();
7376 tcg_gen_extu_i32_i64(extaddr, addr);
7377 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7378 tcg_temp_free_i64(extaddr);
7380 tmp = tcg_temp_new_i32();
7381 switch (size) {
7382 case 0:
7383 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
7384 break;
7385 case 1:
7386 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
7387 break;
7388 case 2:
7389 case 3:
7390 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7391 break;
7392 default:
7393 abort();
7396 val64 = tcg_temp_new_i64();
7397 if (size == 3) {
7398 TCGv_i32 tmp2 = tcg_temp_new_i32();
7399 TCGv_i32 tmp3 = tcg_temp_new_i32();
7400 tcg_gen_addi_i32(tmp2, addr, 4);
7401 gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
7402 tcg_temp_free_i32(tmp2);
7403 tcg_gen_concat_i32_i64(val64, tmp, tmp3);
7404 tcg_temp_free_i32(tmp3);
7405 } else {
7406 tcg_gen_extu_i32_i64(val64, tmp);
7408 tcg_temp_free_i32(tmp);
7410 tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
7411 tcg_temp_free_i64(val64);
7413 tmp = load_reg(s, rt);
7414 switch (size) {
7415 case 0:
7416 gen_aa32_st8(tmp, addr, get_mem_index(s));
7417 break;
7418 case 1:
7419 gen_aa32_st16(tmp, addr, get_mem_index(s));
7420 break;
7421 case 2:
7422 case 3:
7423 gen_aa32_st32(tmp, addr, get_mem_index(s));
7424 break;
7425 default:
7426 abort();
7428 tcg_temp_free_i32(tmp);
7429 if (size == 3) {
7430 tcg_gen_addi_i32(addr, addr, 4);
7431 tmp = load_reg(s, rt2);
7432 gen_aa32_st32(tmp, addr, get_mem_index(s));
7433 tcg_temp_free_i32(tmp);
7435 tcg_gen_movi_i32(cpu_R[rd], 0);
7436 tcg_gen_br(done_label);
7437 gen_set_label(fail_label);
7438 tcg_gen_movi_i32(cpu_R[rd], 1);
7439 gen_set_label(done_label);
7440 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7442 #endif
7444 /* gen_srs:
7445 * @env: CPUARMState
7446 * @s: DisasContext
7447 * @mode: mode field from insn (which stack to store to)
7448 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7449 * @writeback: true if writeback bit set
7451 * Generate code for the SRS (Store Return State) insn.
7453 static void gen_srs(DisasContext *s,
7454 uint32_t mode, uint32_t amode, bool writeback)
7456 int32_t offset;
7457 TCGv_i32 addr = tcg_temp_new_i32();
7458 TCGv_i32 tmp = tcg_const_i32(mode);
7459 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7460 tcg_temp_free_i32(tmp);
7461 switch (amode) {
7462 case 0: /* DA */
7463 offset = -4;
7464 break;
7465 case 1: /* IA */
7466 offset = 0;
7467 break;
7468 case 2: /* DB */
7469 offset = -8;
7470 break;
7471 case 3: /* IB */
7472 offset = 4;
7473 break;
7474 default:
7475 abort();
7477 tcg_gen_addi_i32(addr, addr, offset);
7478 tmp = load_reg(s, 14);
7479 gen_aa32_st32(tmp, addr, get_mem_index(s));
7480 tcg_temp_free_i32(tmp);
7481 tmp = load_cpu_field(spsr);
7482 tcg_gen_addi_i32(addr, addr, 4);
7483 gen_aa32_st32(tmp, addr, get_mem_index(s));
7484 tcg_temp_free_i32(tmp);
7485 if (writeback) {
7486 switch (amode) {
7487 case 0:
7488 offset = -8;
7489 break;
7490 case 1:
7491 offset = 4;
7492 break;
7493 case 2:
7494 offset = -4;
7495 break;
7496 case 3:
7497 offset = 0;
7498 break;
7499 default:
7500 abort();
7502 tcg_gen_addi_i32(addr, addr, offset);
7503 tmp = tcg_const_i32(mode);
7504 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7505 tcg_temp_free_i32(tmp);
7507 tcg_temp_free_i32(addr);
7510 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
7512 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
7513 TCGv_i32 tmp;
7514 TCGv_i32 tmp2;
7515 TCGv_i32 tmp3;
7516 TCGv_i32 addr;
7517 TCGv_i64 tmp64;
7519 insn = arm_ldl_code(env, s->pc, s->bswap_code);
7520 s->pc += 4;
7522 /* M variants do not implement ARM mode. */
7523 if (IS_M(env))
7524 goto illegal_op;
7525 cond = insn >> 28;
7526 if (cond == 0xf){
7527 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
7528 * choose to UNDEF. In ARMv5 and above the space is used
7529 * for miscellaneous unconditional instructions.
7531 ARCH(5);
7533 /* Unconditional instructions. */
7534 if (((insn >> 25) & 7) == 1) {
7535 /* NEON Data processing. */
7536 if (!arm_feature(env, ARM_FEATURE_NEON))
7537 goto illegal_op;
7539 if (disas_neon_data_insn(env, s, insn))
7540 goto illegal_op;
7541 return;
7543 if ((insn & 0x0f100000) == 0x04000000) {
7544 /* NEON load/store. */
7545 if (!arm_feature(env, ARM_FEATURE_NEON))
7546 goto illegal_op;
7548 if (disas_neon_ls_insn(env, s, insn))
7549 goto illegal_op;
7550 return;
7552 if ((insn & 0x0f000e10) == 0x0e000a00) {
7553 /* VFP. */
7554 if (disas_vfp_insn(env, s, insn)) {
7555 goto illegal_op;
7557 return;
7559 if (((insn & 0x0f30f000) == 0x0510f000) ||
7560 ((insn & 0x0f30f010) == 0x0710f000)) {
7561 if ((insn & (1 << 22)) == 0) {
7562 /* PLDW; v7MP */
7563 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7564 goto illegal_op;
7567 /* Otherwise PLD; v5TE+ */
7568 ARCH(5TE);
7569 return;
7571 if (((insn & 0x0f70f000) == 0x0450f000) ||
7572 ((insn & 0x0f70f010) == 0x0650f000)) {
7573 ARCH(7);
7574 return; /* PLI; V7 */
7576 if (((insn & 0x0f700000) == 0x04100000) ||
7577 ((insn & 0x0f700010) == 0x06100000)) {
7578 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7579 goto illegal_op;
7581 return; /* v7MP: Unallocated memory hint: must NOP */
7584 if ((insn & 0x0ffffdff) == 0x01010000) {
7585 ARCH(6);
7586 /* setend */
7587 if (((insn >> 9) & 1) != s->bswap_code) {
7588 /* Dynamic endianness switching not implemented. */
7589 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
7590 goto illegal_op;
7592 return;
7593 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7594 switch ((insn >> 4) & 0xf) {
7595 case 1: /* clrex */
7596 ARCH(6K);
7597 gen_clrex(s);
7598 return;
7599 case 4: /* dsb */
7600 case 5: /* dmb */
7601 case 6: /* isb */
7602 ARCH(7);
7603 /* We don't emulate caches so these are a no-op. */
7604 return;
7605 default:
7606 goto illegal_op;
7608 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7609 /* srs */
7610 if (IS_USER(s)) {
7611 goto illegal_op;
7613 ARCH(6);
7614 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
7615 return;
7616 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
7617 /* rfe */
7618 int32_t offset;
7619 if (IS_USER(s))
7620 goto illegal_op;
7621 ARCH(6);
7622 rn = (insn >> 16) & 0xf;
7623 addr = load_reg(s, rn);
7624 i = (insn >> 23) & 3;
7625 switch (i) {
7626 case 0: offset = -4; break; /* DA */
7627 case 1: offset = 0; break; /* IA */
7628 case 2: offset = -8; break; /* DB */
7629 case 3: offset = 4; break; /* IB */
7630 default: abort();
7632 if (offset)
7633 tcg_gen_addi_i32(addr, addr, offset);
7634 /* Load PC into tmp and CPSR into tmp2. */
7635 tmp = tcg_temp_new_i32();
7636 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7637 tcg_gen_addi_i32(addr, addr, 4);
7638 tmp2 = tcg_temp_new_i32();
7639 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
7640 if (insn & (1 << 21)) {
7641 /* Base writeback. */
7642 switch (i) {
7643 case 0: offset = -8; break;
7644 case 1: offset = 4; break;
7645 case 2: offset = -4; break;
7646 case 3: offset = 0; break;
7647 default: abort();
7649 if (offset)
7650 tcg_gen_addi_i32(addr, addr, offset);
7651 store_reg(s, rn, addr);
7652 } else {
7653 tcg_temp_free_i32(addr);
7655 gen_rfe(s, tmp, tmp2);
7656 return;
7657 } else if ((insn & 0x0e000000) == 0x0a000000) {
7658 /* branch link and change to thumb (blx <offset>) */
7659 int32_t offset;
7661 val = (uint32_t)s->pc;
7662 tmp = tcg_temp_new_i32();
7663 tcg_gen_movi_i32(tmp, val);
7664 store_reg(s, 14, tmp);
7665 /* Sign-extend the 24-bit offset */
7666 offset = (((int32_t)insn) << 8) >> 8;
7667 /* offset * 4 + bit24 * 2 + (thumb bit) */
7668 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7669 /* pipeline offset */
7670 val += 4;
7671 /* protected by ARCH(5); above, near the start of uncond block */
7672 gen_bx_im(s, val);
7673 return;
7674 } else if ((insn & 0x0e000f00) == 0x0c000100) {
7675 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7676 /* iWMMXt register transfer. */
7677 if (extract32(s->c15_cpar, 1, 1)) {
7678 if (!disas_iwmmxt_insn(env, s, insn)) {
7679 return;
7683 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7684 /* Coprocessor double register transfer. */
7685 ARCH(5TE);
7686 } else if ((insn & 0x0f000010) == 0x0e000010) {
7687 /* Additional coprocessor register transfer. */
7688 } else if ((insn & 0x0ff10020) == 0x01000000) {
7689 uint32_t mask;
7690 uint32_t val;
7691 /* cps (privileged) */
7692 if (IS_USER(s))
7693 return;
7694 mask = val = 0;
7695 if (insn & (1 << 19)) {
7696 if (insn & (1 << 8))
7697 mask |= CPSR_A;
7698 if (insn & (1 << 7))
7699 mask |= CPSR_I;
7700 if (insn & (1 << 6))
7701 mask |= CPSR_F;
7702 if (insn & (1 << 18))
7703 val |= mask;
7705 if (insn & (1 << 17)) {
7706 mask |= CPSR_M;
7707 val |= (insn & 0x1f);
7709 if (mask) {
7710 gen_set_psr_im(s, mask, 0, val);
7712 return;
7714 goto illegal_op;
7716 if (cond != 0xe) {
7717 /* if not always execute, we generate a conditional jump to
7718 next instruction */
7719 s->condlabel = gen_new_label();
7720 arm_gen_test_cc(cond ^ 1, s->condlabel);
7721 s->condjmp = 1;
7723 if ((insn & 0x0f900000) == 0x03000000) {
7724 if ((insn & (1 << 21)) == 0) {
7725 ARCH(6T2);
7726 rd = (insn >> 12) & 0xf;
7727 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7728 if ((insn & (1 << 22)) == 0) {
7729 /* MOVW */
7730 tmp = tcg_temp_new_i32();
7731 tcg_gen_movi_i32(tmp, val);
7732 } else {
7733 /* MOVT */
7734 tmp = load_reg(s, rd);
7735 tcg_gen_ext16u_i32(tmp, tmp);
7736 tcg_gen_ori_i32(tmp, tmp, val << 16);
7738 store_reg(s, rd, tmp);
7739 } else {
7740 if (((insn >> 12) & 0xf) != 0xf)
7741 goto illegal_op;
7742 if (((insn >> 16) & 0xf) == 0) {
7743 gen_nop_hint(s, insn & 0xff);
7744 } else {
7745 /* CPSR = immediate */
7746 val = insn & 0xff;
7747 shift = ((insn >> 8) & 0xf) * 2;
7748 if (shift)
7749 val = (val >> shift) | (val << (32 - shift));
7750 i = ((insn & (1 << 22)) != 0);
7751 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
7752 goto illegal_op;
7755 } else if ((insn & 0x0f900000) == 0x01000000
7756 && (insn & 0x00000090) != 0x00000090) {
7757 /* miscellaneous instructions */
7758 op1 = (insn >> 21) & 3;
7759 sh = (insn >> 4) & 0xf;
7760 rm = insn & 0xf;
7761 switch (sh) {
7762 case 0x0: /* move program status register */
7763 if (op1 & 1) {
7764 /* PSR = reg */
7765 tmp = load_reg(s, rm);
7766 i = ((op1 & 2) != 0);
7767 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
7768 goto illegal_op;
7769 } else {
7770 /* reg = PSR */
7771 rd = (insn >> 12) & 0xf;
7772 if (op1 & 2) {
7773 if (IS_USER(s))
7774 goto illegal_op;
7775 tmp = load_cpu_field(spsr);
7776 } else {
7777 tmp = tcg_temp_new_i32();
7778 gen_helper_cpsr_read(tmp, cpu_env);
7780 store_reg(s, rd, tmp);
7782 break;
7783 case 0x1:
7784 if (op1 == 1) {
7785 /* branch/exchange thumb (bx). */
7786 ARCH(4T);
7787 tmp = load_reg(s, rm);
7788 gen_bx(s, tmp);
7789 } else if (op1 == 3) {
7790 /* clz */
7791 ARCH(5);
7792 rd = (insn >> 12) & 0xf;
7793 tmp = load_reg(s, rm);
7794 gen_helper_clz(tmp, tmp);
7795 store_reg(s, rd, tmp);
7796 } else {
7797 goto illegal_op;
7799 break;
7800 case 0x2:
7801 if (op1 == 1) {
7802 ARCH(5J); /* bxj */
7803 /* Trivial implementation equivalent to bx. */
7804 tmp = load_reg(s, rm);
7805 gen_bx(s, tmp);
7806 } else {
7807 goto illegal_op;
7809 break;
7810 case 0x3:
7811 if (op1 != 1)
7812 goto illegal_op;
7814 ARCH(5);
7815 /* branch link/exchange thumb (blx) */
7816 tmp = load_reg(s, rm);
7817 tmp2 = tcg_temp_new_i32();
7818 tcg_gen_movi_i32(tmp2, s->pc);
7819 store_reg(s, 14, tmp2);
7820 gen_bx(s, tmp);
7821 break;
7822 case 0x4:
7824 /* crc32/crc32c */
7825 uint32_t c = extract32(insn, 8, 4);
7827 /* Check this CPU supports ARMv8 CRC instructions.
7828 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
7829 * Bits 8, 10 and 11 should be zero.
7831 if (!arm_feature(env, ARM_FEATURE_CRC) || op1 == 0x3 ||
7832 (c & 0xd) != 0) {
7833 goto illegal_op;
7836 rn = extract32(insn, 16, 4);
7837 rd = extract32(insn, 12, 4);
7839 tmp = load_reg(s, rn);
7840 tmp2 = load_reg(s, rm);
7841 if (op1 == 0) {
7842 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
7843 } else if (op1 == 1) {
7844 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
7846 tmp3 = tcg_const_i32(1 << op1);
7847 if (c & 0x2) {
7848 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
7849 } else {
7850 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
7852 tcg_temp_free_i32(tmp2);
7853 tcg_temp_free_i32(tmp3);
7854 store_reg(s, rd, tmp);
7855 break;
7857 case 0x5: /* saturating add/subtract */
7858 ARCH(5TE);
7859 rd = (insn >> 12) & 0xf;
7860 rn = (insn >> 16) & 0xf;
7861 tmp = load_reg(s, rm);
7862 tmp2 = load_reg(s, rn);
7863 if (op1 & 2)
7864 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
7865 if (op1 & 1)
7866 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
7867 else
7868 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7869 tcg_temp_free_i32(tmp2);
7870 store_reg(s, rd, tmp);
7871 break;
7872 case 7:
7874 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
7875 /* SMC instruction (op1 == 3)
7876 and undefined instructions (op1 == 0 || op1 == 2)
7877 will trap */
7878 if (op1 != 1) {
7879 goto illegal_op;
7881 /* bkpt */
7882 ARCH(5);
7883 gen_exception_insn(s, 4, EXCP_BKPT, syn_aa32_bkpt(imm16, false));
7884 break;
7886 case 0x8: /* signed multiply */
7887 case 0xa:
7888 case 0xc:
7889 case 0xe:
7890 ARCH(5TE);
7891 rs = (insn >> 8) & 0xf;
7892 rn = (insn >> 12) & 0xf;
7893 rd = (insn >> 16) & 0xf;
7894 if (op1 == 1) {
7895 /* (32 * 16) >> 16 */
7896 tmp = load_reg(s, rm);
7897 tmp2 = load_reg(s, rs);
7898 if (sh & 4)
7899 tcg_gen_sari_i32(tmp2, tmp2, 16);
7900 else
7901 gen_sxth(tmp2);
7902 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7903 tcg_gen_shri_i64(tmp64, tmp64, 16);
7904 tmp = tcg_temp_new_i32();
7905 tcg_gen_trunc_i64_i32(tmp, tmp64);
7906 tcg_temp_free_i64(tmp64);
7907 if ((sh & 2) == 0) {
7908 tmp2 = load_reg(s, rn);
7909 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7910 tcg_temp_free_i32(tmp2);
7912 store_reg(s, rd, tmp);
7913 } else {
7914 /* 16 * 16 */
7915 tmp = load_reg(s, rm);
7916 tmp2 = load_reg(s, rs);
7917 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7918 tcg_temp_free_i32(tmp2);
7919 if (op1 == 2) {
7920 tmp64 = tcg_temp_new_i64();
7921 tcg_gen_ext_i32_i64(tmp64, tmp);
7922 tcg_temp_free_i32(tmp);
7923 gen_addq(s, tmp64, rn, rd);
7924 gen_storeq_reg(s, rn, rd, tmp64);
7925 tcg_temp_free_i64(tmp64);
7926 } else {
7927 if (op1 == 0) {
7928 tmp2 = load_reg(s, rn);
7929 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7930 tcg_temp_free_i32(tmp2);
7932 store_reg(s, rd, tmp);
7935 break;
7936 default:
7937 goto illegal_op;
7939 } else if (((insn & 0x0e000000) == 0 &&
7940 (insn & 0x00000090) != 0x90) ||
7941 ((insn & 0x0e000000) == (1 << 25))) {
7942 int set_cc, logic_cc, shiftop;
7944 op1 = (insn >> 21) & 0xf;
7945 set_cc = (insn >> 20) & 1;
7946 logic_cc = table_logic_cc[op1] & set_cc;
7948 /* data processing instruction */
7949 if (insn & (1 << 25)) {
7950 /* immediate operand */
7951 val = insn & 0xff;
7952 shift = ((insn >> 8) & 0xf) * 2;
7953 if (shift) {
7954 val = (val >> shift) | (val << (32 - shift));
7956 tmp2 = tcg_temp_new_i32();
7957 tcg_gen_movi_i32(tmp2, val);
7958 if (logic_cc && shift) {
7959 gen_set_CF_bit31(tmp2);
7961 } else {
7962 /* register */
7963 rm = (insn) & 0xf;
7964 tmp2 = load_reg(s, rm);
7965 shiftop = (insn >> 5) & 3;
7966 if (!(insn & (1 << 4))) {
7967 shift = (insn >> 7) & 0x1f;
7968 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
7969 } else {
7970 rs = (insn >> 8) & 0xf;
7971 tmp = load_reg(s, rs);
7972 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
7975 if (op1 != 0x0f && op1 != 0x0d) {
7976 rn = (insn >> 16) & 0xf;
7977 tmp = load_reg(s, rn);
7978 } else {
7979 TCGV_UNUSED_I32(tmp);
7981 rd = (insn >> 12) & 0xf;
7982 switch(op1) {
7983 case 0x00:
7984 tcg_gen_and_i32(tmp, tmp, tmp2);
7985 if (logic_cc) {
7986 gen_logic_CC(tmp);
7988 store_reg_bx(env, s, rd, tmp);
7989 break;
7990 case 0x01:
7991 tcg_gen_xor_i32(tmp, tmp, tmp2);
7992 if (logic_cc) {
7993 gen_logic_CC(tmp);
7995 store_reg_bx(env, s, rd, tmp);
7996 break;
7997 case 0x02:
7998 if (set_cc && rd == 15) {
7999 /* SUBS r15, ... is used for exception return. */
8000 if (IS_USER(s)) {
8001 goto illegal_op;
8003 gen_sub_CC(tmp, tmp, tmp2);
8004 gen_exception_return(s, tmp);
8005 } else {
8006 if (set_cc) {
8007 gen_sub_CC(tmp, tmp, tmp2);
8008 } else {
8009 tcg_gen_sub_i32(tmp, tmp, tmp2);
8011 store_reg_bx(env, s, rd, tmp);
8013 break;
8014 case 0x03:
8015 if (set_cc) {
8016 gen_sub_CC(tmp, tmp2, tmp);
8017 } else {
8018 tcg_gen_sub_i32(tmp, tmp2, tmp);
8020 store_reg_bx(env, s, rd, tmp);
8021 break;
8022 case 0x04:
8023 if (set_cc) {
8024 gen_add_CC(tmp, tmp, tmp2);
8025 } else {
8026 tcg_gen_add_i32(tmp, tmp, tmp2);
8028 store_reg_bx(env, s, rd, tmp);
8029 break;
8030 case 0x05:
8031 if (set_cc) {
8032 gen_adc_CC(tmp, tmp, tmp2);
8033 } else {
8034 gen_add_carry(tmp, tmp, tmp2);
8036 store_reg_bx(env, s, rd, tmp);
8037 break;
8038 case 0x06:
8039 if (set_cc) {
8040 gen_sbc_CC(tmp, tmp, tmp2);
8041 } else {
8042 gen_sub_carry(tmp, tmp, tmp2);
8044 store_reg_bx(env, s, rd, tmp);
8045 break;
8046 case 0x07:
8047 if (set_cc) {
8048 gen_sbc_CC(tmp, tmp2, tmp);
8049 } else {
8050 gen_sub_carry(tmp, tmp2, tmp);
8052 store_reg_bx(env, s, rd, tmp);
8053 break;
8054 case 0x08:
8055 if (set_cc) {
8056 tcg_gen_and_i32(tmp, tmp, tmp2);
8057 gen_logic_CC(tmp);
8059 tcg_temp_free_i32(tmp);
8060 break;
8061 case 0x09:
8062 if (set_cc) {
8063 tcg_gen_xor_i32(tmp, tmp, tmp2);
8064 gen_logic_CC(tmp);
8066 tcg_temp_free_i32(tmp);
8067 break;
8068 case 0x0a:
8069 if (set_cc) {
8070 gen_sub_CC(tmp, tmp, tmp2);
8072 tcg_temp_free_i32(tmp);
8073 break;
8074 case 0x0b:
8075 if (set_cc) {
8076 gen_add_CC(tmp, tmp, tmp2);
8078 tcg_temp_free_i32(tmp);
8079 break;
8080 case 0x0c:
8081 tcg_gen_or_i32(tmp, tmp, tmp2);
8082 if (logic_cc) {
8083 gen_logic_CC(tmp);
8085 store_reg_bx(env, s, rd, tmp);
8086 break;
8087 case 0x0d:
8088 if (logic_cc && rd == 15) {
8089 /* MOVS r15, ... is used for exception return. */
8090 if (IS_USER(s)) {
8091 goto illegal_op;
8093 gen_exception_return(s, tmp2);
8094 } else {
8095 if (logic_cc) {
8096 gen_logic_CC(tmp2);
8098 store_reg_bx(env, s, rd, tmp2);
8100 break;
8101 case 0x0e:
8102 tcg_gen_andc_i32(tmp, tmp, tmp2);
8103 if (logic_cc) {
8104 gen_logic_CC(tmp);
8106 store_reg_bx(env, s, rd, tmp);
8107 break;
8108 default:
8109 case 0x0f:
8110 tcg_gen_not_i32(tmp2, tmp2);
8111 if (logic_cc) {
8112 gen_logic_CC(tmp2);
8114 store_reg_bx(env, s, rd, tmp2);
8115 break;
8117 if (op1 != 0x0f && op1 != 0x0d) {
8118 tcg_temp_free_i32(tmp2);
8120 } else {
8121 /* other instructions */
8122 op1 = (insn >> 24) & 0xf;
8123 switch(op1) {
8124 case 0x0:
8125 case 0x1:
8126 /* multiplies, extra load/stores */
8127 sh = (insn >> 5) & 3;
8128 if (sh == 0) {
8129 if (op1 == 0x0) {
8130 rd = (insn >> 16) & 0xf;
8131 rn = (insn >> 12) & 0xf;
8132 rs = (insn >> 8) & 0xf;
8133 rm = (insn) & 0xf;
8134 op1 = (insn >> 20) & 0xf;
8135 switch (op1) {
8136 case 0: case 1: case 2: case 3: case 6:
8137 /* 32 bit mul */
8138 tmp = load_reg(s, rs);
8139 tmp2 = load_reg(s, rm);
8140 tcg_gen_mul_i32(tmp, tmp, tmp2);
8141 tcg_temp_free_i32(tmp2);
8142 if (insn & (1 << 22)) {
8143 /* Subtract (mls) */
8144 ARCH(6T2);
8145 tmp2 = load_reg(s, rn);
8146 tcg_gen_sub_i32(tmp, tmp2, tmp);
8147 tcg_temp_free_i32(tmp2);
8148 } else if (insn & (1 << 21)) {
8149 /* Add */
8150 tmp2 = load_reg(s, rn);
8151 tcg_gen_add_i32(tmp, tmp, tmp2);
8152 tcg_temp_free_i32(tmp2);
8154 if (insn & (1 << 20))
8155 gen_logic_CC(tmp);
8156 store_reg(s, rd, tmp);
8157 break;
8158 case 4:
8159 /* 64 bit mul double accumulate (UMAAL) */
8160 ARCH(6);
8161 tmp = load_reg(s, rs);
8162 tmp2 = load_reg(s, rm);
8163 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8164 gen_addq_lo(s, tmp64, rn);
8165 gen_addq_lo(s, tmp64, rd);
8166 gen_storeq_reg(s, rn, rd, tmp64);
8167 tcg_temp_free_i64(tmp64);
8168 break;
8169 case 8: case 9: case 10: case 11:
8170 case 12: case 13: case 14: case 15:
8171 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
8172 tmp = load_reg(s, rs);
8173 tmp2 = load_reg(s, rm);
8174 if (insn & (1 << 22)) {
8175 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8176 } else {
8177 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8179 if (insn & (1 << 21)) { /* mult accumulate */
8180 TCGv_i32 al = load_reg(s, rn);
8181 TCGv_i32 ah = load_reg(s, rd);
8182 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
8183 tcg_temp_free_i32(al);
8184 tcg_temp_free_i32(ah);
8186 if (insn & (1 << 20)) {
8187 gen_logicq_cc(tmp, tmp2);
8189 store_reg(s, rn, tmp);
8190 store_reg(s, rd, tmp2);
8191 break;
8192 default:
8193 goto illegal_op;
8195 } else {
8196 rn = (insn >> 16) & 0xf;
8197 rd = (insn >> 12) & 0xf;
8198 if (insn & (1 << 23)) {
8199 /* load/store exclusive */
8200 int op2 = (insn >> 8) & 3;
8201 op1 = (insn >> 21) & 0x3;
8203 switch (op2) {
8204 case 0: /* lda/stl */
8205 if (op1 == 1) {
8206 goto illegal_op;
8208 ARCH(8);
8209 break;
8210 case 1: /* reserved */
8211 goto illegal_op;
8212 case 2: /* ldaex/stlex */
8213 ARCH(8);
8214 break;
8215 case 3: /* ldrex/strex */
8216 if (op1) {
8217 ARCH(6K);
8218 } else {
8219 ARCH(6);
8221 break;
8224 addr = tcg_temp_local_new_i32();
8225 load_reg_var(s, addr, rn);
8227 /* Since the emulation does not have barriers,
8228 the acquire/release semantics need no special
8229 handling */
8230 if (op2 == 0) {
8231 if (insn & (1 << 20)) {
8232 tmp = tcg_temp_new_i32();
8233 switch (op1) {
8234 case 0: /* lda */
8235 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8236 break;
8237 case 2: /* ldab */
8238 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
8239 break;
8240 case 3: /* ldah */
8241 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
8242 break;
8243 default:
8244 abort();
8246 store_reg(s, rd, tmp);
8247 } else {
8248 rm = insn & 0xf;
8249 tmp = load_reg(s, rm);
8250 switch (op1) {
8251 case 0: /* stl */
8252 gen_aa32_st32(tmp, addr, get_mem_index(s));
8253 break;
8254 case 2: /* stlb */
8255 gen_aa32_st8(tmp, addr, get_mem_index(s));
8256 break;
8257 case 3: /* stlh */
8258 gen_aa32_st16(tmp, addr, get_mem_index(s));
8259 break;
8260 default:
8261 abort();
8263 tcg_temp_free_i32(tmp);
8265 } else if (insn & (1 << 20)) {
8266 switch (op1) {
8267 case 0: /* ldrex */
8268 gen_load_exclusive(s, rd, 15, addr, 2);
8269 break;
8270 case 1: /* ldrexd */
8271 gen_load_exclusive(s, rd, rd + 1, addr, 3);
8272 break;
8273 case 2: /* ldrexb */
8274 gen_load_exclusive(s, rd, 15, addr, 0);
8275 break;
8276 case 3: /* ldrexh */
8277 gen_load_exclusive(s, rd, 15, addr, 1);
8278 break;
8279 default:
8280 abort();
8282 } else {
8283 rm = insn & 0xf;
8284 switch (op1) {
8285 case 0: /* strex */
8286 gen_store_exclusive(s, rd, rm, 15, addr, 2);
8287 break;
8288 case 1: /* strexd */
8289 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
8290 break;
8291 case 2: /* strexb */
8292 gen_store_exclusive(s, rd, rm, 15, addr, 0);
8293 break;
8294 case 3: /* strexh */
8295 gen_store_exclusive(s, rd, rm, 15, addr, 1);
8296 break;
8297 default:
8298 abort();
8301 tcg_temp_free_i32(addr);
8302 } else {
8303 /* SWP instruction */
8304 rm = (insn) & 0xf;
8306 /* ??? This is not really atomic. However we know
8307 we never have multiple CPUs running in parallel,
8308 so it is good enough. */
8309 addr = load_reg(s, rn);
8310 tmp = load_reg(s, rm);
8311 tmp2 = tcg_temp_new_i32();
8312 if (insn & (1 << 22)) {
8313 gen_aa32_ld8u(tmp2, addr, get_mem_index(s));
8314 gen_aa32_st8(tmp, addr, get_mem_index(s));
8315 } else {
8316 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
8317 gen_aa32_st32(tmp, addr, get_mem_index(s));
8319 tcg_temp_free_i32(tmp);
8320 tcg_temp_free_i32(addr);
8321 store_reg(s, rd, tmp2);
8324 } else {
8325 int address_offset;
8326 int load;
8327 /* Misc load/store */
8328 rn = (insn >> 16) & 0xf;
8329 rd = (insn >> 12) & 0xf;
8330 addr = load_reg(s, rn);
8331 if (insn & (1 << 24))
8332 gen_add_datah_offset(s, insn, 0, addr);
8333 address_offset = 0;
8334 if (insn & (1 << 20)) {
8335 /* load */
8336 tmp = tcg_temp_new_i32();
8337 switch(sh) {
8338 case 1:
8339 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
8340 break;
8341 case 2:
8342 gen_aa32_ld8s(tmp, addr, get_mem_index(s));
8343 break;
8344 default:
8345 case 3:
8346 gen_aa32_ld16s(tmp, addr, get_mem_index(s));
8347 break;
8349 load = 1;
8350 } else if (sh & 2) {
8351 ARCH(5TE);
8352 /* doubleword */
8353 if (sh & 1) {
8354 /* store */
8355 tmp = load_reg(s, rd);
8356 gen_aa32_st32(tmp, addr, get_mem_index(s));
8357 tcg_temp_free_i32(tmp);
8358 tcg_gen_addi_i32(addr, addr, 4);
8359 tmp = load_reg(s, rd + 1);
8360 gen_aa32_st32(tmp, addr, get_mem_index(s));
8361 tcg_temp_free_i32(tmp);
8362 load = 0;
8363 } else {
8364 /* load */
8365 tmp = tcg_temp_new_i32();
8366 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8367 store_reg(s, rd, tmp);
8368 tcg_gen_addi_i32(addr, addr, 4);
8369 tmp = tcg_temp_new_i32();
8370 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8371 rd++;
8372 load = 1;
8374 address_offset = -4;
8375 } else {
8376 /* store */
8377 tmp = load_reg(s, rd);
8378 gen_aa32_st16(tmp, addr, get_mem_index(s));
8379 tcg_temp_free_i32(tmp);
8380 load = 0;
8382 /* Perform base writeback before the loaded value to
8383 ensure correct behavior with overlapping index registers.
8384 ldrd with base writeback is is undefined if the
8385 destination and index registers overlap. */
8386 if (!(insn & (1 << 24))) {
8387 gen_add_datah_offset(s, insn, address_offset, addr);
8388 store_reg(s, rn, addr);
8389 } else if (insn & (1 << 21)) {
8390 if (address_offset)
8391 tcg_gen_addi_i32(addr, addr, address_offset);
8392 store_reg(s, rn, addr);
8393 } else {
8394 tcg_temp_free_i32(addr);
8396 if (load) {
8397 /* Complete the load. */
8398 store_reg(s, rd, tmp);
8401 break;
8402 case 0x4:
8403 case 0x5:
8404 goto do_ldst;
8405 case 0x6:
8406 case 0x7:
8407 if (insn & (1 << 4)) {
8408 ARCH(6);
8409 /* Armv6 Media instructions. */
8410 rm = insn & 0xf;
8411 rn = (insn >> 16) & 0xf;
8412 rd = (insn >> 12) & 0xf;
8413 rs = (insn >> 8) & 0xf;
8414 switch ((insn >> 23) & 3) {
8415 case 0: /* Parallel add/subtract. */
8416 op1 = (insn >> 20) & 7;
8417 tmp = load_reg(s, rn);
8418 tmp2 = load_reg(s, rm);
8419 sh = (insn >> 5) & 7;
8420 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8421 goto illegal_op;
8422 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
8423 tcg_temp_free_i32(tmp2);
8424 store_reg(s, rd, tmp);
8425 break;
8426 case 1:
8427 if ((insn & 0x00700020) == 0) {
8428 /* Halfword pack. */
8429 tmp = load_reg(s, rn);
8430 tmp2 = load_reg(s, rm);
8431 shift = (insn >> 7) & 0x1f;
8432 if (insn & (1 << 6)) {
8433 /* pkhtb */
8434 if (shift == 0)
8435 shift = 31;
8436 tcg_gen_sari_i32(tmp2, tmp2, shift);
8437 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8438 tcg_gen_ext16u_i32(tmp2, tmp2);
8439 } else {
8440 /* pkhbt */
8441 if (shift)
8442 tcg_gen_shli_i32(tmp2, tmp2, shift);
8443 tcg_gen_ext16u_i32(tmp, tmp);
8444 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8446 tcg_gen_or_i32(tmp, tmp, tmp2);
8447 tcg_temp_free_i32(tmp2);
8448 store_reg(s, rd, tmp);
8449 } else if ((insn & 0x00200020) == 0x00200000) {
8450 /* [us]sat */
8451 tmp = load_reg(s, rm);
8452 shift = (insn >> 7) & 0x1f;
8453 if (insn & (1 << 6)) {
8454 if (shift == 0)
8455 shift = 31;
8456 tcg_gen_sari_i32(tmp, tmp, shift);
8457 } else {
8458 tcg_gen_shli_i32(tmp, tmp, shift);
8460 sh = (insn >> 16) & 0x1f;
8461 tmp2 = tcg_const_i32(sh);
8462 if (insn & (1 << 22))
8463 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
8464 else
8465 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
8466 tcg_temp_free_i32(tmp2);
8467 store_reg(s, rd, tmp);
8468 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8469 /* [us]sat16 */
8470 tmp = load_reg(s, rm);
8471 sh = (insn >> 16) & 0x1f;
8472 tmp2 = tcg_const_i32(sh);
8473 if (insn & (1 << 22))
8474 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
8475 else
8476 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
8477 tcg_temp_free_i32(tmp2);
8478 store_reg(s, rd, tmp);
8479 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8480 /* Select bytes. */
8481 tmp = load_reg(s, rn);
8482 tmp2 = load_reg(s, rm);
8483 tmp3 = tcg_temp_new_i32();
8484 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8485 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8486 tcg_temp_free_i32(tmp3);
8487 tcg_temp_free_i32(tmp2);
8488 store_reg(s, rd, tmp);
8489 } else if ((insn & 0x000003e0) == 0x00000060) {
8490 tmp = load_reg(s, rm);
8491 shift = (insn >> 10) & 3;
8492 /* ??? In many cases it's not necessary to do a
8493 rotate, a shift is sufficient. */
8494 if (shift != 0)
8495 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8496 op1 = (insn >> 20) & 7;
8497 switch (op1) {
8498 case 0: gen_sxtb16(tmp); break;
8499 case 2: gen_sxtb(tmp); break;
8500 case 3: gen_sxth(tmp); break;
8501 case 4: gen_uxtb16(tmp); break;
8502 case 6: gen_uxtb(tmp); break;
8503 case 7: gen_uxth(tmp); break;
8504 default: goto illegal_op;
8506 if (rn != 15) {
8507 tmp2 = load_reg(s, rn);
8508 if ((op1 & 3) == 0) {
8509 gen_add16(tmp, tmp2);
8510 } else {
8511 tcg_gen_add_i32(tmp, tmp, tmp2);
8512 tcg_temp_free_i32(tmp2);
8515 store_reg(s, rd, tmp);
8516 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
8517 /* rev */
8518 tmp = load_reg(s, rm);
8519 if (insn & (1 << 22)) {
8520 if (insn & (1 << 7)) {
8521 gen_revsh(tmp);
8522 } else {
8523 ARCH(6T2);
8524 gen_helper_rbit(tmp, tmp);
8526 } else {
8527 if (insn & (1 << 7))
8528 gen_rev16(tmp);
8529 else
8530 tcg_gen_bswap32_i32(tmp, tmp);
8532 store_reg(s, rd, tmp);
8533 } else {
8534 goto illegal_op;
8536 break;
8537 case 2: /* Multiplies (Type 3). */
8538 switch ((insn >> 20) & 0x7) {
8539 case 5:
8540 if (((insn >> 6) ^ (insn >> 7)) & 1) {
8541 /* op2 not 00x or 11x : UNDEF */
8542 goto illegal_op;
8544 /* Signed multiply most significant [accumulate].
8545 (SMMUL, SMMLA, SMMLS) */
8546 tmp = load_reg(s, rm);
8547 tmp2 = load_reg(s, rs);
8548 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8550 if (rd != 15) {
8551 tmp = load_reg(s, rd);
8552 if (insn & (1 << 6)) {
8553 tmp64 = gen_subq_msw(tmp64, tmp);
8554 } else {
8555 tmp64 = gen_addq_msw(tmp64, tmp);
8558 if (insn & (1 << 5)) {
8559 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8561 tcg_gen_shri_i64(tmp64, tmp64, 32);
8562 tmp = tcg_temp_new_i32();
8563 tcg_gen_trunc_i64_i32(tmp, tmp64);
8564 tcg_temp_free_i64(tmp64);
8565 store_reg(s, rn, tmp);
8566 break;
8567 case 0:
8568 case 4:
8569 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
8570 if (insn & (1 << 7)) {
8571 goto illegal_op;
8573 tmp = load_reg(s, rm);
8574 tmp2 = load_reg(s, rs);
8575 if (insn & (1 << 5))
8576 gen_swap_half(tmp2);
8577 gen_smul_dual(tmp, tmp2);
8578 if (insn & (1 << 22)) {
8579 /* smlald, smlsld */
8580 TCGv_i64 tmp64_2;
8582 tmp64 = tcg_temp_new_i64();
8583 tmp64_2 = tcg_temp_new_i64();
8584 tcg_gen_ext_i32_i64(tmp64, tmp);
8585 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
8586 tcg_temp_free_i32(tmp);
8587 tcg_temp_free_i32(tmp2);
8588 if (insn & (1 << 6)) {
8589 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
8590 } else {
8591 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
8593 tcg_temp_free_i64(tmp64_2);
8594 gen_addq(s, tmp64, rd, rn);
8595 gen_storeq_reg(s, rd, rn, tmp64);
8596 tcg_temp_free_i64(tmp64);
8597 } else {
8598 /* smuad, smusd, smlad, smlsd */
8599 if (insn & (1 << 6)) {
8600 /* This subtraction cannot overflow. */
8601 tcg_gen_sub_i32(tmp, tmp, tmp2);
8602 } else {
8603 /* This addition cannot overflow 32 bits;
8604 * however it may overflow considered as a
8605 * signed operation, in which case we must set
8606 * the Q flag.
8608 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8610 tcg_temp_free_i32(tmp2);
8611 if (rd != 15)
8613 tmp2 = load_reg(s, rd);
8614 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8615 tcg_temp_free_i32(tmp2);
8617 store_reg(s, rn, tmp);
8619 break;
8620 case 1:
8621 case 3:
8622 /* SDIV, UDIV */
8623 if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
8624 goto illegal_op;
8626 if (((insn >> 5) & 7) || (rd != 15)) {
8627 goto illegal_op;
8629 tmp = load_reg(s, rm);
8630 tmp2 = load_reg(s, rs);
8631 if (insn & (1 << 21)) {
8632 gen_helper_udiv(tmp, tmp, tmp2);
8633 } else {
8634 gen_helper_sdiv(tmp, tmp, tmp2);
8636 tcg_temp_free_i32(tmp2);
8637 store_reg(s, rn, tmp);
8638 break;
8639 default:
8640 goto illegal_op;
8642 break;
8643 case 3:
8644 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8645 switch (op1) {
8646 case 0: /* Unsigned sum of absolute differences. */
8647 ARCH(6);
8648 tmp = load_reg(s, rm);
8649 tmp2 = load_reg(s, rs);
8650 gen_helper_usad8(tmp, tmp, tmp2);
8651 tcg_temp_free_i32(tmp2);
8652 if (rd != 15) {
8653 tmp2 = load_reg(s, rd);
8654 tcg_gen_add_i32(tmp, tmp, tmp2);
8655 tcg_temp_free_i32(tmp2);
8657 store_reg(s, rn, tmp);
8658 break;
8659 case 0x20: case 0x24: case 0x28: case 0x2c:
8660 /* Bitfield insert/clear. */
8661 ARCH(6T2);
8662 shift = (insn >> 7) & 0x1f;
8663 i = (insn >> 16) & 0x1f;
8664 i = i + 1 - shift;
8665 if (rm == 15) {
8666 tmp = tcg_temp_new_i32();
8667 tcg_gen_movi_i32(tmp, 0);
8668 } else {
8669 tmp = load_reg(s, rm);
8671 if (i != 32) {
8672 tmp2 = load_reg(s, rd);
8673 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
8674 tcg_temp_free_i32(tmp2);
8676 store_reg(s, rd, tmp);
8677 break;
8678 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8679 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
8680 ARCH(6T2);
8681 tmp = load_reg(s, rm);
8682 shift = (insn >> 7) & 0x1f;
8683 i = ((insn >> 16) & 0x1f) + 1;
8684 if (shift + i > 32)
8685 goto illegal_op;
8686 if (i < 32) {
8687 if (op1 & 0x20) {
8688 gen_ubfx(tmp, shift, (1u << i) - 1);
8689 } else {
8690 gen_sbfx(tmp, shift, i);
8693 store_reg(s, rd, tmp);
8694 break;
8695 default:
8696 goto illegal_op;
8698 break;
8700 break;
8702 do_ldst:
8703 /* Check for undefined extension instructions
8704 * per the ARM Bible IE:
8705 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
8707 sh = (0xf << 20) | (0xf << 4);
8708 if (op1 == 0x7 && ((insn & sh) == sh))
8710 goto illegal_op;
8712 /* load/store byte/word */
8713 rn = (insn >> 16) & 0xf;
8714 rd = (insn >> 12) & 0xf;
8715 tmp2 = load_reg(s, rn);
8716 if ((insn & 0x01200000) == 0x00200000) {
8717 /* ldrt/strt */
8718 i = MMU_USER_IDX;
8719 } else {
8720 i = get_mem_index(s);
8722 if (insn & (1 << 24))
8723 gen_add_data_offset(s, insn, tmp2);
8724 if (insn & (1 << 20)) {
8725 /* load */
8726 tmp = tcg_temp_new_i32();
8727 if (insn & (1 << 22)) {
8728 gen_aa32_ld8u(tmp, tmp2, i);
8729 } else {
8730 gen_aa32_ld32u(tmp, tmp2, i);
8732 } else {
8733 /* store */
8734 tmp = load_reg(s, rd);
8735 if (insn & (1 << 22)) {
8736 gen_aa32_st8(tmp, tmp2, i);
8737 } else {
8738 gen_aa32_st32(tmp, tmp2, i);
8740 tcg_temp_free_i32(tmp);
8742 if (!(insn & (1 << 24))) {
8743 gen_add_data_offset(s, insn, tmp2);
8744 store_reg(s, rn, tmp2);
8745 } else if (insn & (1 << 21)) {
8746 store_reg(s, rn, tmp2);
8747 } else {
8748 tcg_temp_free_i32(tmp2);
8750 if (insn & (1 << 20)) {
8751 /* Complete the load. */
8752 store_reg_from_load(env, s, rd, tmp);
8754 break;
8755 case 0x08:
8756 case 0x09:
8758 int j, n, user, loaded_base;
8759 TCGv_i32 loaded_var;
8760 /* load/store multiple words */
8761 /* XXX: store correct base if write back */
8762 user = 0;
8763 if (insn & (1 << 22)) {
8764 if (IS_USER(s))
8765 goto illegal_op; /* only usable in supervisor mode */
8767 if ((insn & (1 << 15)) == 0)
8768 user = 1;
8770 rn = (insn >> 16) & 0xf;
8771 addr = load_reg(s, rn);
8773 /* compute total size */
8774 loaded_base = 0;
8775 TCGV_UNUSED_I32(loaded_var);
8776 n = 0;
8777 for(i=0;i<16;i++) {
8778 if (insn & (1 << i))
8779 n++;
8781 /* XXX: test invalid n == 0 case ? */
8782 if (insn & (1 << 23)) {
8783 if (insn & (1 << 24)) {
8784 /* pre increment */
8785 tcg_gen_addi_i32(addr, addr, 4);
8786 } else {
8787 /* post increment */
8789 } else {
8790 if (insn & (1 << 24)) {
8791 /* pre decrement */
8792 tcg_gen_addi_i32(addr, addr, -(n * 4));
8793 } else {
8794 /* post decrement */
8795 if (n != 1)
8796 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8799 j = 0;
8800 for(i=0;i<16;i++) {
8801 if (insn & (1 << i)) {
8802 if (insn & (1 << 20)) {
8803 /* load */
8804 tmp = tcg_temp_new_i32();
8805 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8806 if (user) {
8807 tmp2 = tcg_const_i32(i);
8808 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
8809 tcg_temp_free_i32(tmp2);
8810 tcg_temp_free_i32(tmp);
8811 } else if (i == rn) {
8812 loaded_var = tmp;
8813 loaded_base = 1;
8814 } else {
8815 store_reg_from_load(env, s, i, tmp);
8817 } else {
8818 /* store */
8819 if (i == 15) {
8820 /* special case: r15 = PC + 8 */
8821 val = (long)s->pc + 4;
8822 tmp = tcg_temp_new_i32();
8823 tcg_gen_movi_i32(tmp, val);
8824 } else if (user) {
8825 tmp = tcg_temp_new_i32();
8826 tmp2 = tcg_const_i32(i);
8827 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
8828 tcg_temp_free_i32(tmp2);
8829 } else {
8830 tmp = load_reg(s, i);
8832 gen_aa32_st32(tmp, addr, get_mem_index(s));
8833 tcg_temp_free_i32(tmp);
8835 j++;
8836 /* no need to add after the last transfer */
8837 if (j != n)
8838 tcg_gen_addi_i32(addr, addr, 4);
8841 if (insn & (1 << 21)) {
8842 /* write back */
8843 if (insn & (1 << 23)) {
8844 if (insn & (1 << 24)) {
8845 /* pre increment */
8846 } else {
8847 /* post increment */
8848 tcg_gen_addi_i32(addr, addr, 4);
8850 } else {
8851 if (insn & (1 << 24)) {
8852 /* pre decrement */
8853 if (n != 1)
8854 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8855 } else {
8856 /* post decrement */
8857 tcg_gen_addi_i32(addr, addr, -(n * 4));
8860 store_reg(s, rn, addr);
8861 } else {
8862 tcg_temp_free_i32(addr);
8864 if (loaded_base) {
8865 store_reg(s, rn, loaded_var);
8867 if ((insn & (1 << 22)) && !user) {
8868 /* Restore CPSR from SPSR. */
8869 tmp = load_cpu_field(spsr);
8870 gen_set_cpsr(tmp, CPSR_ERET_MASK);
8871 tcg_temp_free_i32(tmp);
8872 s->is_jmp = DISAS_UPDATE;
8875 break;
8876 case 0xa:
8877 case 0xb:
8879 int32_t offset;
8881 /* branch (and link) */
8882 val = (int32_t)s->pc;
8883 if (insn & (1 << 24)) {
8884 tmp = tcg_temp_new_i32();
8885 tcg_gen_movi_i32(tmp, val);
8886 store_reg(s, 14, tmp);
8888 offset = sextract32(insn << 2, 0, 26);
8889 val += offset + 4;
8890 gen_jmp(s, val);
8892 break;
8893 case 0xc:
8894 case 0xd:
8895 case 0xe:
8896 if (((insn >> 8) & 0xe) == 10) {
8897 /* VFP. */
8898 if (disas_vfp_insn(env, s, insn)) {
8899 goto illegal_op;
8901 } else if (disas_coproc_insn(env, s, insn)) {
8902 /* Coprocessor. */
8903 goto illegal_op;
8905 break;
8906 case 0xf:
8907 /* swi */
8908 gen_set_pc_im(s, s->pc);
8909 s->svc_imm = extract32(insn, 0, 24);
8910 s->is_jmp = DISAS_SWI;
8911 break;
8912 default:
8913 illegal_op:
8914 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
8915 break;
8920 /* Return true if this is a Thumb-2 logical op. */
8921 static int
8922 thumb2_logic_op(int op)
8924 return (op < 8);
8927 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
8928 then set condition code flags based on the result of the operation.
8929 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
8930 to the high bit of T1.
8931 Returns zero if the opcode is valid. */
8933 static int
8934 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
8935 TCGv_i32 t0, TCGv_i32 t1)
8937 int logic_cc;
8939 logic_cc = 0;
8940 switch (op) {
8941 case 0: /* and */
8942 tcg_gen_and_i32(t0, t0, t1);
8943 logic_cc = conds;
8944 break;
8945 case 1: /* bic */
8946 tcg_gen_andc_i32(t0, t0, t1);
8947 logic_cc = conds;
8948 break;
8949 case 2: /* orr */
8950 tcg_gen_or_i32(t0, t0, t1);
8951 logic_cc = conds;
8952 break;
8953 case 3: /* orn */
8954 tcg_gen_orc_i32(t0, t0, t1);
8955 logic_cc = conds;
8956 break;
8957 case 4: /* eor */
8958 tcg_gen_xor_i32(t0, t0, t1);
8959 logic_cc = conds;
8960 break;
8961 case 8: /* add */
8962 if (conds)
8963 gen_add_CC(t0, t0, t1);
8964 else
8965 tcg_gen_add_i32(t0, t0, t1);
8966 break;
8967 case 10: /* adc */
8968 if (conds)
8969 gen_adc_CC(t0, t0, t1);
8970 else
8971 gen_adc(t0, t1);
8972 break;
8973 case 11: /* sbc */
8974 if (conds) {
8975 gen_sbc_CC(t0, t0, t1);
8976 } else {
8977 gen_sub_carry(t0, t0, t1);
8979 break;
8980 case 13: /* sub */
8981 if (conds)
8982 gen_sub_CC(t0, t0, t1);
8983 else
8984 tcg_gen_sub_i32(t0, t0, t1);
8985 break;
8986 case 14: /* rsb */
8987 if (conds)
8988 gen_sub_CC(t0, t1, t0);
8989 else
8990 tcg_gen_sub_i32(t0, t1, t0);
8991 break;
8992 default: /* 5, 6, 7, 9, 12, 15. */
8993 return 1;
8995 if (logic_cc) {
8996 gen_logic_CC(t0);
8997 if (shifter_out)
8998 gen_set_CF_bit31(t1);
9000 return 0;
9003 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
9004 is not legal. */
9005 static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
9007 uint32_t insn, imm, shift, offset;
9008 uint32_t rd, rn, rm, rs;
9009 TCGv_i32 tmp;
9010 TCGv_i32 tmp2;
9011 TCGv_i32 tmp3;
9012 TCGv_i32 addr;
9013 TCGv_i64 tmp64;
9014 int op;
9015 int shiftop;
9016 int conds;
9017 int logic_cc;
9019 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
9020 || arm_feature (env, ARM_FEATURE_M))) {
9021 /* Thumb-1 cores may need to treat bl and blx as a pair of
9022 16-bit instructions to get correct prefetch abort behavior. */
9023 insn = insn_hw1;
9024 if ((insn & (1 << 12)) == 0) {
9025 ARCH(5);
9026 /* Second half of blx. */
9027 offset = ((insn & 0x7ff) << 1);
9028 tmp = load_reg(s, 14);
9029 tcg_gen_addi_i32(tmp, tmp, offset);
9030 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
9032 tmp2 = tcg_temp_new_i32();
9033 tcg_gen_movi_i32(tmp2, s->pc | 1);
9034 store_reg(s, 14, tmp2);
9035 gen_bx(s, tmp);
9036 return 0;
9038 if (insn & (1 << 11)) {
9039 /* Second half of bl. */
9040 offset = ((insn & 0x7ff) << 1) | 1;
9041 tmp = load_reg(s, 14);
9042 tcg_gen_addi_i32(tmp, tmp, offset);
9044 tmp2 = tcg_temp_new_i32();
9045 tcg_gen_movi_i32(tmp2, s->pc | 1);
9046 store_reg(s, 14, tmp2);
9047 gen_bx(s, tmp);
9048 return 0;
9050 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
9051 /* Instruction spans a page boundary. Implement it as two
9052 16-bit instructions in case the second half causes an
9053 prefetch abort. */
9054 offset = ((int32_t)insn << 21) >> 9;
9055 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
9056 return 0;
9058 /* Fall through to 32-bit decode. */
9061 insn = arm_lduw_code(env, s->pc, s->bswap_code);
9062 s->pc += 2;
9063 insn |= (uint32_t)insn_hw1 << 16;
9065 if ((insn & 0xf800e800) != 0xf000e800) {
9066 ARCH(6T2);
9069 rn = (insn >> 16) & 0xf;
9070 rs = (insn >> 12) & 0xf;
9071 rd = (insn >> 8) & 0xf;
9072 rm = insn & 0xf;
9073 switch ((insn >> 25) & 0xf) {
9074 case 0: case 1: case 2: case 3:
9075 /* 16-bit instructions. Should never happen. */
9076 abort();
9077 case 4:
9078 if (insn & (1 << 22)) {
9079 /* Other load/store, table branch. */
9080 if (insn & 0x01200000) {
9081 /* Load/store doubleword. */
9082 if (rn == 15) {
9083 addr = tcg_temp_new_i32();
9084 tcg_gen_movi_i32(addr, s->pc & ~3);
9085 } else {
9086 addr = load_reg(s, rn);
9088 offset = (insn & 0xff) * 4;
9089 if ((insn & (1 << 23)) == 0)
9090 offset = -offset;
9091 if (insn & (1 << 24)) {
9092 tcg_gen_addi_i32(addr, addr, offset);
9093 offset = 0;
9095 if (insn & (1 << 20)) {
9096 /* ldrd */
9097 tmp = tcg_temp_new_i32();
9098 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9099 store_reg(s, rs, tmp);
9100 tcg_gen_addi_i32(addr, addr, 4);
9101 tmp = tcg_temp_new_i32();
9102 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9103 store_reg(s, rd, tmp);
9104 } else {
9105 /* strd */
9106 tmp = load_reg(s, rs);
9107 gen_aa32_st32(tmp, addr, get_mem_index(s));
9108 tcg_temp_free_i32(tmp);
9109 tcg_gen_addi_i32(addr, addr, 4);
9110 tmp = load_reg(s, rd);
9111 gen_aa32_st32(tmp, addr, get_mem_index(s));
9112 tcg_temp_free_i32(tmp);
9114 if (insn & (1 << 21)) {
9115 /* Base writeback. */
9116 if (rn == 15)
9117 goto illegal_op;
9118 tcg_gen_addi_i32(addr, addr, offset - 4);
9119 store_reg(s, rn, addr);
9120 } else {
9121 tcg_temp_free_i32(addr);
9123 } else if ((insn & (1 << 23)) == 0) {
9124 /* Load/store exclusive word. */
9125 addr = tcg_temp_local_new_i32();
9126 load_reg_var(s, addr, rn);
9127 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
9128 if (insn & (1 << 20)) {
9129 gen_load_exclusive(s, rs, 15, addr, 2);
9130 } else {
9131 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9133 tcg_temp_free_i32(addr);
9134 } else if ((insn & (7 << 5)) == 0) {
9135 /* Table Branch. */
9136 if (rn == 15) {
9137 addr = tcg_temp_new_i32();
9138 tcg_gen_movi_i32(addr, s->pc);
9139 } else {
9140 addr = load_reg(s, rn);
9142 tmp = load_reg(s, rm);
9143 tcg_gen_add_i32(addr, addr, tmp);
9144 if (insn & (1 << 4)) {
9145 /* tbh */
9146 tcg_gen_add_i32(addr, addr, tmp);
9147 tcg_temp_free_i32(tmp);
9148 tmp = tcg_temp_new_i32();
9149 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
9150 } else { /* tbb */
9151 tcg_temp_free_i32(tmp);
9152 tmp = tcg_temp_new_i32();
9153 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
9155 tcg_temp_free_i32(addr);
9156 tcg_gen_shli_i32(tmp, tmp, 1);
9157 tcg_gen_addi_i32(tmp, tmp, s->pc);
9158 store_reg(s, 15, tmp);
9159 } else {
9160 int op2 = (insn >> 6) & 0x3;
9161 op = (insn >> 4) & 0x3;
9162 switch (op2) {
9163 case 0:
9164 goto illegal_op;
9165 case 1:
9166 /* Load/store exclusive byte/halfword/doubleword */
9167 if (op == 2) {
9168 goto illegal_op;
9170 ARCH(7);
9171 break;
9172 case 2:
9173 /* Load-acquire/store-release */
9174 if (op == 3) {
9175 goto illegal_op;
9177 /* Fall through */
9178 case 3:
9179 /* Load-acquire/store-release exclusive */
9180 ARCH(8);
9181 break;
9183 addr = tcg_temp_local_new_i32();
9184 load_reg_var(s, addr, rn);
9185 if (!(op2 & 1)) {
9186 if (insn & (1 << 20)) {
9187 tmp = tcg_temp_new_i32();
9188 switch (op) {
9189 case 0: /* ldab */
9190 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
9191 break;
9192 case 1: /* ldah */
9193 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
9194 break;
9195 case 2: /* lda */
9196 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9197 break;
9198 default:
9199 abort();
9201 store_reg(s, rs, tmp);
9202 } else {
9203 tmp = load_reg(s, rs);
9204 switch (op) {
9205 case 0: /* stlb */
9206 gen_aa32_st8(tmp, addr, get_mem_index(s));
9207 break;
9208 case 1: /* stlh */
9209 gen_aa32_st16(tmp, addr, get_mem_index(s));
9210 break;
9211 case 2: /* stl */
9212 gen_aa32_st32(tmp, addr, get_mem_index(s));
9213 break;
9214 default:
9215 abort();
9217 tcg_temp_free_i32(tmp);
9219 } else if (insn & (1 << 20)) {
9220 gen_load_exclusive(s, rs, rd, addr, op);
9221 } else {
9222 gen_store_exclusive(s, rm, rs, rd, addr, op);
9224 tcg_temp_free_i32(addr);
9226 } else {
9227 /* Load/store multiple, RFE, SRS. */
9228 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
9229 /* RFE, SRS: not available in user mode or on M profile */
9230 if (IS_USER(s) || IS_M(env)) {
9231 goto illegal_op;
9233 if (insn & (1 << 20)) {
9234 /* rfe */
9235 addr = load_reg(s, rn);
9236 if ((insn & (1 << 24)) == 0)
9237 tcg_gen_addi_i32(addr, addr, -8);
9238 /* Load PC into tmp and CPSR into tmp2. */
9239 tmp = tcg_temp_new_i32();
9240 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9241 tcg_gen_addi_i32(addr, addr, 4);
9242 tmp2 = tcg_temp_new_i32();
9243 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
9244 if (insn & (1 << 21)) {
9245 /* Base writeback. */
9246 if (insn & (1 << 24)) {
9247 tcg_gen_addi_i32(addr, addr, 4);
9248 } else {
9249 tcg_gen_addi_i32(addr, addr, -4);
9251 store_reg(s, rn, addr);
9252 } else {
9253 tcg_temp_free_i32(addr);
9255 gen_rfe(s, tmp, tmp2);
9256 } else {
9257 /* srs */
9258 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
9259 insn & (1 << 21));
9261 } else {
9262 int i, loaded_base = 0;
9263 TCGv_i32 loaded_var;
9264 /* Load/store multiple. */
9265 addr = load_reg(s, rn);
9266 offset = 0;
9267 for (i = 0; i < 16; i++) {
9268 if (insn & (1 << i))
9269 offset += 4;
9271 if (insn & (1 << 24)) {
9272 tcg_gen_addi_i32(addr, addr, -offset);
9275 TCGV_UNUSED_I32(loaded_var);
9276 for (i = 0; i < 16; i++) {
9277 if ((insn & (1 << i)) == 0)
9278 continue;
9279 if (insn & (1 << 20)) {
9280 /* Load. */
9281 tmp = tcg_temp_new_i32();
9282 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9283 if (i == 15) {
9284 gen_bx(s, tmp);
9285 } else if (i == rn) {
9286 loaded_var = tmp;
9287 loaded_base = 1;
9288 } else {
9289 store_reg(s, i, tmp);
9291 } else {
9292 /* Store. */
9293 tmp = load_reg(s, i);
9294 gen_aa32_st32(tmp, addr, get_mem_index(s));
9295 tcg_temp_free_i32(tmp);
9297 tcg_gen_addi_i32(addr, addr, 4);
9299 if (loaded_base) {
9300 store_reg(s, rn, loaded_var);
9302 if (insn & (1 << 21)) {
9303 /* Base register writeback. */
9304 if (insn & (1 << 24)) {
9305 tcg_gen_addi_i32(addr, addr, -offset);
9307 /* Fault if writeback register is in register list. */
9308 if (insn & (1 << rn))
9309 goto illegal_op;
9310 store_reg(s, rn, addr);
9311 } else {
9312 tcg_temp_free_i32(addr);
9316 break;
9317 case 5:
9319 op = (insn >> 21) & 0xf;
9320 if (op == 6) {
9321 /* Halfword pack. */
9322 tmp = load_reg(s, rn);
9323 tmp2 = load_reg(s, rm);
9324 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
9325 if (insn & (1 << 5)) {
9326 /* pkhtb */
9327 if (shift == 0)
9328 shift = 31;
9329 tcg_gen_sari_i32(tmp2, tmp2, shift);
9330 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9331 tcg_gen_ext16u_i32(tmp2, tmp2);
9332 } else {
9333 /* pkhbt */
9334 if (shift)
9335 tcg_gen_shli_i32(tmp2, tmp2, shift);
9336 tcg_gen_ext16u_i32(tmp, tmp);
9337 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9339 tcg_gen_or_i32(tmp, tmp, tmp2);
9340 tcg_temp_free_i32(tmp2);
9341 store_reg(s, rd, tmp);
9342 } else {
9343 /* Data processing register constant shift. */
9344 if (rn == 15) {
9345 tmp = tcg_temp_new_i32();
9346 tcg_gen_movi_i32(tmp, 0);
9347 } else {
9348 tmp = load_reg(s, rn);
9350 tmp2 = load_reg(s, rm);
9352 shiftop = (insn >> 4) & 3;
9353 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9354 conds = (insn & (1 << 20)) != 0;
9355 logic_cc = (conds && thumb2_logic_op(op));
9356 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9357 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9358 goto illegal_op;
9359 tcg_temp_free_i32(tmp2);
9360 if (rd != 15) {
9361 store_reg(s, rd, tmp);
9362 } else {
9363 tcg_temp_free_i32(tmp);
9366 break;
9367 case 13: /* Misc data processing. */
9368 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9369 if (op < 4 && (insn & 0xf000) != 0xf000)
9370 goto illegal_op;
9371 switch (op) {
9372 case 0: /* Register controlled shift. */
9373 tmp = load_reg(s, rn);
9374 tmp2 = load_reg(s, rm);
9375 if ((insn & 0x70) != 0)
9376 goto illegal_op;
9377 op = (insn >> 21) & 3;
9378 logic_cc = (insn & (1 << 20)) != 0;
9379 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9380 if (logic_cc)
9381 gen_logic_CC(tmp);
9382 store_reg_bx(env, s, rd, tmp);
9383 break;
9384 case 1: /* Sign/zero extend. */
9385 tmp = load_reg(s, rm);
9386 shift = (insn >> 4) & 3;
9387 /* ??? In many cases it's not necessary to do a
9388 rotate, a shift is sufficient. */
9389 if (shift != 0)
9390 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9391 op = (insn >> 20) & 7;
9392 switch (op) {
9393 case 0: gen_sxth(tmp); break;
9394 case 1: gen_uxth(tmp); break;
9395 case 2: gen_sxtb16(tmp); break;
9396 case 3: gen_uxtb16(tmp); break;
9397 case 4: gen_sxtb(tmp); break;
9398 case 5: gen_uxtb(tmp); break;
9399 default: goto illegal_op;
9401 if (rn != 15) {
9402 tmp2 = load_reg(s, rn);
9403 if ((op >> 1) == 1) {
9404 gen_add16(tmp, tmp2);
9405 } else {
9406 tcg_gen_add_i32(tmp, tmp, tmp2);
9407 tcg_temp_free_i32(tmp2);
9410 store_reg(s, rd, tmp);
9411 break;
9412 case 2: /* SIMD add/subtract. */
9413 op = (insn >> 20) & 7;
9414 shift = (insn >> 4) & 7;
9415 if ((op & 3) == 3 || (shift & 3) == 3)
9416 goto illegal_op;
9417 tmp = load_reg(s, rn);
9418 tmp2 = load_reg(s, rm);
9419 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
9420 tcg_temp_free_i32(tmp2);
9421 store_reg(s, rd, tmp);
9422 break;
9423 case 3: /* Other data processing. */
9424 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9425 if (op < 4) {
9426 /* Saturating add/subtract. */
9427 tmp = load_reg(s, rn);
9428 tmp2 = load_reg(s, rm);
9429 if (op & 1)
9430 gen_helper_double_saturate(tmp, cpu_env, tmp);
9431 if (op & 2)
9432 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9433 else
9434 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
9435 tcg_temp_free_i32(tmp2);
9436 } else {
9437 tmp = load_reg(s, rn);
9438 switch (op) {
9439 case 0x0a: /* rbit */
9440 gen_helper_rbit(tmp, tmp);
9441 break;
9442 case 0x08: /* rev */
9443 tcg_gen_bswap32_i32(tmp, tmp);
9444 break;
9445 case 0x09: /* rev16 */
9446 gen_rev16(tmp);
9447 break;
9448 case 0x0b: /* revsh */
9449 gen_revsh(tmp);
9450 break;
9451 case 0x10: /* sel */
9452 tmp2 = load_reg(s, rm);
9453 tmp3 = tcg_temp_new_i32();
9454 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
9455 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
9456 tcg_temp_free_i32(tmp3);
9457 tcg_temp_free_i32(tmp2);
9458 break;
9459 case 0x18: /* clz */
9460 gen_helper_clz(tmp, tmp);
9461 break;
9462 case 0x20:
9463 case 0x21:
9464 case 0x22:
9465 case 0x28:
9466 case 0x29:
9467 case 0x2a:
9469 /* crc32/crc32c */
9470 uint32_t sz = op & 0x3;
9471 uint32_t c = op & 0x8;
9473 if (!arm_feature(env, ARM_FEATURE_CRC)) {
9474 goto illegal_op;
9477 tmp2 = load_reg(s, rm);
9478 if (sz == 0) {
9479 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
9480 } else if (sz == 1) {
9481 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
9483 tmp3 = tcg_const_i32(1 << sz);
9484 if (c) {
9485 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
9486 } else {
9487 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
9489 tcg_temp_free_i32(tmp2);
9490 tcg_temp_free_i32(tmp3);
9491 break;
9493 default:
9494 goto illegal_op;
9497 store_reg(s, rd, tmp);
9498 break;
9499 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
9500 op = (insn >> 4) & 0xf;
9501 tmp = load_reg(s, rn);
9502 tmp2 = load_reg(s, rm);
9503 switch ((insn >> 20) & 7) {
9504 case 0: /* 32 x 32 -> 32 */
9505 tcg_gen_mul_i32(tmp, tmp, tmp2);
9506 tcg_temp_free_i32(tmp2);
9507 if (rs != 15) {
9508 tmp2 = load_reg(s, rs);
9509 if (op)
9510 tcg_gen_sub_i32(tmp, tmp2, tmp);
9511 else
9512 tcg_gen_add_i32(tmp, tmp, tmp2);
9513 tcg_temp_free_i32(tmp2);
9515 break;
9516 case 1: /* 16 x 16 -> 32 */
9517 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9518 tcg_temp_free_i32(tmp2);
9519 if (rs != 15) {
9520 tmp2 = load_reg(s, rs);
9521 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9522 tcg_temp_free_i32(tmp2);
9524 break;
9525 case 2: /* Dual multiply add. */
9526 case 4: /* Dual multiply subtract. */
9527 if (op)
9528 gen_swap_half(tmp2);
9529 gen_smul_dual(tmp, tmp2);
9530 if (insn & (1 << 22)) {
9531 /* This subtraction cannot overflow. */
9532 tcg_gen_sub_i32(tmp, tmp, tmp2);
9533 } else {
9534 /* This addition cannot overflow 32 bits;
9535 * however it may overflow considered as a signed
9536 * operation, in which case we must set the Q flag.
9538 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9540 tcg_temp_free_i32(tmp2);
9541 if (rs != 15)
9543 tmp2 = load_reg(s, rs);
9544 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9545 tcg_temp_free_i32(tmp2);
9547 break;
9548 case 3: /* 32 * 16 -> 32msb */
9549 if (op)
9550 tcg_gen_sari_i32(tmp2, tmp2, 16);
9551 else
9552 gen_sxth(tmp2);
9553 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9554 tcg_gen_shri_i64(tmp64, tmp64, 16);
9555 tmp = tcg_temp_new_i32();
9556 tcg_gen_trunc_i64_i32(tmp, tmp64);
9557 tcg_temp_free_i64(tmp64);
9558 if (rs != 15)
9560 tmp2 = load_reg(s, rs);
9561 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9562 tcg_temp_free_i32(tmp2);
9564 break;
9565 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
9566 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9567 if (rs != 15) {
9568 tmp = load_reg(s, rs);
9569 if (insn & (1 << 20)) {
9570 tmp64 = gen_addq_msw(tmp64, tmp);
9571 } else {
9572 tmp64 = gen_subq_msw(tmp64, tmp);
9575 if (insn & (1 << 4)) {
9576 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9578 tcg_gen_shri_i64(tmp64, tmp64, 32);
9579 tmp = tcg_temp_new_i32();
9580 tcg_gen_trunc_i64_i32(tmp, tmp64);
9581 tcg_temp_free_i64(tmp64);
9582 break;
9583 case 7: /* Unsigned sum of absolute differences. */
9584 gen_helper_usad8(tmp, tmp, tmp2);
9585 tcg_temp_free_i32(tmp2);
9586 if (rs != 15) {
9587 tmp2 = load_reg(s, rs);
9588 tcg_gen_add_i32(tmp, tmp, tmp2);
9589 tcg_temp_free_i32(tmp2);
9591 break;
9593 store_reg(s, rd, tmp);
9594 break;
9595 case 6: case 7: /* 64-bit multiply, Divide. */
9596 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
9597 tmp = load_reg(s, rn);
9598 tmp2 = load_reg(s, rm);
9599 if ((op & 0x50) == 0x10) {
9600 /* sdiv, udiv */
9601 if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
9602 goto illegal_op;
9604 if (op & 0x20)
9605 gen_helper_udiv(tmp, tmp, tmp2);
9606 else
9607 gen_helper_sdiv(tmp, tmp, tmp2);
9608 tcg_temp_free_i32(tmp2);
9609 store_reg(s, rd, tmp);
9610 } else if ((op & 0xe) == 0xc) {
9611 /* Dual multiply accumulate long. */
9612 if (op & 1)
9613 gen_swap_half(tmp2);
9614 gen_smul_dual(tmp, tmp2);
9615 if (op & 0x10) {
9616 tcg_gen_sub_i32(tmp, tmp, tmp2);
9617 } else {
9618 tcg_gen_add_i32(tmp, tmp, tmp2);
9620 tcg_temp_free_i32(tmp2);
9621 /* BUGFIX */
9622 tmp64 = tcg_temp_new_i64();
9623 tcg_gen_ext_i32_i64(tmp64, tmp);
9624 tcg_temp_free_i32(tmp);
9625 gen_addq(s, tmp64, rs, rd);
9626 gen_storeq_reg(s, rs, rd, tmp64);
9627 tcg_temp_free_i64(tmp64);
9628 } else {
9629 if (op & 0x20) {
9630 /* Unsigned 64-bit multiply */
9631 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9632 } else {
9633 if (op & 8) {
9634 /* smlalxy */
9635 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9636 tcg_temp_free_i32(tmp2);
9637 tmp64 = tcg_temp_new_i64();
9638 tcg_gen_ext_i32_i64(tmp64, tmp);
9639 tcg_temp_free_i32(tmp);
9640 } else {
9641 /* Signed 64-bit multiply */
9642 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9645 if (op & 4) {
9646 /* umaal */
9647 gen_addq_lo(s, tmp64, rs);
9648 gen_addq_lo(s, tmp64, rd);
9649 } else if (op & 0x40) {
9650 /* 64-bit accumulate. */
9651 gen_addq(s, tmp64, rs, rd);
9653 gen_storeq_reg(s, rs, rd, tmp64);
9654 tcg_temp_free_i64(tmp64);
9656 break;
9658 break;
9659 case 6: case 7: case 14: case 15:
9660 /* Coprocessor. */
9661 if (((insn >> 24) & 3) == 3) {
9662 /* Translate into the equivalent ARM encoding. */
9663 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
9664 if (disas_neon_data_insn(env, s, insn))
9665 goto illegal_op;
9666 } else if (((insn >> 8) & 0xe) == 10) {
9667 if (disas_vfp_insn(env, s, insn)) {
9668 goto illegal_op;
9670 } else {
9671 if (insn & (1 << 28))
9672 goto illegal_op;
9673 if (disas_coproc_insn (env, s, insn))
9674 goto illegal_op;
9676 break;
9677 case 8: case 9: case 10: case 11:
9678 if (insn & (1 << 15)) {
9679 /* Branches, misc control. */
9680 if (insn & 0x5000) {
9681 /* Unconditional branch. */
9682 /* signextend(hw1[10:0]) -> offset[:12]. */
9683 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
9684 /* hw1[10:0] -> offset[11:1]. */
9685 offset |= (insn & 0x7ff) << 1;
9686 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
9687 offset[24:22] already have the same value because of the
9688 sign extension above. */
9689 offset ^= ((~insn) & (1 << 13)) << 10;
9690 offset ^= ((~insn) & (1 << 11)) << 11;
9692 if (insn & (1 << 14)) {
9693 /* Branch and link. */
9694 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
9697 offset += s->pc;
9698 if (insn & (1 << 12)) {
9699 /* b/bl */
9700 gen_jmp(s, offset);
9701 } else {
9702 /* blx */
9703 offset &= ~(uint32_t)2;
9704 /* thumb2 bx, no need to check */
9705 gen_bx_im(s, offset);
9707 } else if (((insn >> 23) & 7) == 7) {
9708 /* Misc control */
9709 if (insn & (1 << 13))
9710 goto illegal_op;
9712 if (insn & (1 << 26)) {
9713 /* Secure monitor call (v6Z) */
9714 qemu_log_mask(LOG_UNIMP,
9715 "arm: unimplemented secure monitor call\n");
9716 goto illegal_op; /* not implemented. */
9717 } else {
9718 op = (insn >> 20) & 7;
9719 switch (op) {
9720 case 0: /* msr cpsr. */
9721 if (IS_M(env)) {
9722 tmp = load_reg(s, rn);
9723 addr = tcg_const_i32(insn & 0xff);
9724 gen_helper_v7m_msr(cpu_env, addr, tmp);
9725 tcg_temp_free_i32(addr);
9726 tcg_temp_free_i32(tmp);
9727 gen_lookup_tb(s);
9728 break;
9730 /* fall through */
9731 case 1: /* msr spsr. */
9732 if (IS_M(env))
9733 goto illegal_op;
9734 tmp = load_reg(s, rn);
9735 if (gen_set_psr(s,
9736 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
9737 op == 1, tmp))
9738 goto illegal_op;
9739 break;
9740 case 2: /* cps, nop-hint. */
9741 if (((insn >> 8) & 7) == 0) {
9742 gen_nop_hint(s, insn & 0xff);
9744 /* Implemented as NOP in user mode. */
9745 if (IS_USER(s))
9746 break;
9747 offset = 0;
9748 imm = 0;
9749 if (insn & (1 << 10)) {
9750 if (insn & (1 << 7))
9751 offset |= CPSR_A;
9752 if (insn & (1 << 6))
9753 offset |= CPSR_I;
9754 if (insn & (1 << 5))
9755 offset |= CPSR_F;
9756 if (insn & (1 << 9))
9757 imm = CPSR_A | CPSR_I | CPSR_F;
9759 if (insn & (1 << 8)) {
9760 offset |= 0x1f;
9761 imm |= (insn & 0x1f);
9763 if (offset) {
9764 gen_set_psr_im(s, offset, 0, imm);
9766 break;
9767 case 3: /* Special control operations. */
9768 ARCH(7);
9769 op = (insn >> 4) & 0xf;
9770 switch (op) {
9771 case 2: /* clrex */
9772 gen_clrex(s);
9773 break;
9774 case 4: /* dsb */
9775 case 5: /* dmb */
9776 case 6: /* isb */
9777 /* These execute as NOPs. */
9778 break;
9779 default:
9780 goto illegal_op;
9782 break;
9783 case 4: /* bxj */
9784 /* Trivial implementation equivalent to bx. */
9785 tmp = load_reg(s, rn);
9786 gen_bx(s, tmp);
9787 break;
9788 case 5: /* Exception return. */
9789 if (IS_USER(s)) {
9790 goto illegal_op;
9792 if (rn != 14 || rd != 15) {
9793 goto illegal_op;
9795 tmp = load_reg(s, rn);
9796 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
9797 gen_exception_return(s, tmp);
9798 break;
9799 case 6: /* mrs cpsr. */
9800 tmp = tcg_temp_new_i32();
9801 if (IS_M(env)) {
9802 addr = tcg_const_i32(insn & 0xff);
9803 gen_helper_v7m_mrs(tmp, cpu_env, addr);
9804 tcg_temp_free_i32(addr);
9805 } else {
9806 gen_helper_cpsr_read(tmp, cpu_env);
9808 store_reg(s, rd, tmp);
9809 break;
9810 case 7: /* mrs spsr. */
9811 /* Not accessible in user mode. */
9812 if (IS_USER(s) || IS_M(env))
9813 goto illegal_op;
9814 tmp = load_cpu_field(spsr);
9815 store_reg(s, rd, tmp);
9816 break;
9819 } else {
9820 /* Conditional branch. */
9821 op = (insn >> 22) & 0xf;
9822 /* Generate a conditional jump to next instruction. */
9823 s->condlabel = gen_new_label();
9824 arm_gen_test_cc(op ^ 1, s->condlabel);
9825 s->condjmp = 1;
9827 /* offset[11:1] = insn[10:0] */
9828 offset = (insn & 0x7ff) << 1;
9829 /* offset[17:12] = insn[21:16]. */
9830 offset |= (insn & 0x003f0000) >> 4;
9831 /* offset[31:20] = insn[26]. */
9832 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
9833 /* offset[18] = insn[13]. */
9834 offset |= (insn & (1 << 13)) << 5;
9835 /* offset[19] = insn[11]. */
9836 offset |= (insn & (1 << 11)) << 8;
9838 /* jump to the offset */
9839 gen_jmp(s, s->pc + offset);
9841 } else {
9842 /* Data processing immediate. */
9843 if (insn & (1 << 25)) {
9844 if (insn & (1 << 24)) {
9845 if (insn & (1 << 20))
9846 goto illegal_op;
9847 /* Bitfield/Saturate. */
9848 op = (insn >> 21) & 7;
9849 imm = insn & 0x1f;
9850 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9851 if (rn == 15) {
9852 tmp = tcg_temp_new_i32();
9853 tcg_gen_movi_i32(tmp, 0);
9854 } else {
9855 tmp = load_reg(s, rn);
9857 switch (op) {
9858 case 2: /* Signed bitfield extract. */
9859 imm++;
9860 if (shift + imm > 32)
9861 goto illegal_op;
9862 if (imm < 32)
9863 gen_sbfx(tmp, shift, imm);
9864 break;
9865 case 6: /* Unsigned bitfield extract. */
9866 imm++;
9867 if (shift + imm > 32)
9868 goto illegal_op;
9869 if (imm < 32)
9870 gen_ubfx(tmp, shift, (1u << imm) - 1);
9871 break;
9872 case 3: /* Bitfield insert/clear. */
9873 if (imm < shift)
9874 goto illegal_op;
9875 imm = imm + 1 - shift;
9876 if (imm != 32) {
9877 tmp2 = load_reg(s, rd);
9878 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
9879 tcg_temp_free_i32(tmp2);
9881 break;
9882 case 7:
9883 goto illegal_op;
9884 default: /* Saturate. */
9885 if (shift) {
9886 if (op & 1)
9887 tcg_gen_sari_i32(tmp, tmp, shift);
9888 else
9889 tcg_gen_shli_i32(tmp, tmp, shift);
9891 tmp2 = tcg_const_i32(imm);
9892 if (op & 4) {
9893 /* Unsigned. */
9894 if ((op & 1) && shift == 0)
9895 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9896 else
9897 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9898 } else {
9899 /* Signed. */
9900 if ((op & 1) && shift == 0)
9901 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9902 else
9903 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9905 tcg_temp_free_i32(tmp2);
9906 break;
9908 store_reg(s, rd, tmp);
9909 } else {
9910 imm = ((insn & 0x04000000) >> 15)
9911 | ((insn & 0x7000) >> 4) | (insn & 0xff);
9912 if (insn & (1 << 22)) {
9913 /* 16-bit immediate. */
9914 imm |= (insn >> 4) & 0xf000;
9915 if (insn & (1 << 23)) {
9916 /* movt */
9917 tmp = load_reg(s, rd);
9918 tcg_gen_ext16u_i32(tmp, tmp);
9919 tcg_gen_ori_i32(tmp, tmp, imm << 16);
9920 } else {
9921 /* movw */
9922 tmp = tcg_temp_new_i32();
9923 tcg_gen_movi_i32(tmp, imm);
9925 } else {
9926 /* Add/sub 12-bit immediate. */
9927 if (rn == 15) {
9928 offset = s->pc & ~(uint32_t)3;
9929 if (insn & (1 << 23))
9930 offset -= imm;
9931 else
9932 offset += imm;
9933 tmp = tcg_temp_new_i32();
9934 tcg_gen_movi_i32(tmp, offset);
9935 } else {
9936 tmp = load_reg(s, rn);
9937 if (insn & (1 << 23))
9938 tcg_gen_subi_i32(tmp, tmp, imm);
9939 else
9940 tcg_gen_addi_i32(tmp, tmp, imm);
9943 store_reg(s, rd, tmp);
9945 } else {
9946 int shifter_out = 0;
9947 /* modified 12-bit immediate. */
9948 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
9949 imm = (insn & 0xff);
9950 switch (shift) {
9951 case 0: /* XY */
9952 /* Nothing to do. */
9953 break;
9954 case 1: /* 00XY00XY */
9955 imm |= imm << 16;
9956 break;
9957 case 2: /* XY00XY00 */
9958 imm |= imm << 16;
9959 imm <<= 8;
9960 break;
9961 case 3: /* XYXYXYXY */
9962 imm |= imm << 16;
9963 imm |= imm << 8;
9964 break;
9965 default: /* Rotated constant. */
9966 shift = (shift << 1) | (imm >> 7);
9967 imm |= 0x80;
9968 imm = imm << (32 - shift);
9969 shifter_out = 1;
9970 break;
9972 tmp2 = tcg_temp_new_i32();
9973 tcg_gen_movi_i32(tmp2, imm);
9974 rn = (insn >> 16) & 0xf;
9975 if (rn == 15) {
9976 tmp = tcg_temp_new_i32();
9977 tcg_gen_movi_i32(tmp, 0);
9978 } else {
9979 tmp = load_reg(s, rn);
9981 op = (insn >> 21) & 0xf;
9982 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
9983 shifter_out, tmp, tmp2))
9984 goto illegal_op;
9985 tcg_temp_free_i32(tmp2);
9986 rd = (insn >> 8) & 0xf;
9987 if (rd != 15) {
9988 store_reg(s, rd, tmp);
9989 } else {
9990 tcg_temp_free_i32(tmp);
9994 break;
9995 case 12: /* Load/store single data item. */
9997 int postinc = 0;
9998 int writeback = 0;
9999 int memidx;
10000 if ((insn & 0x01100000) == 0x01000000) {
10001 if (disas_neon_ls_insn(env, s, insn))
10002 goto illegal_op;
10003 break;
10005 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
10006 if (rs == 15) {
10007 if (!(insn & (1 << 20))) {
10008 goto illegal_op;
10010 if (op != 2) {
10011 /* Byte or halfword load space with dest == r15 : memory hints.
10012 * Catch them early so we don't emit pointless addressing code.
10013 * This space is a mix of:
10014 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
10015 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
10016 * cores)
10017 * unallocated hints, which must be treated as NOPs
10018 * UNPREDICTABLE space, which we NOP or UNDEF depending on
10019 * which is easiest for the decoding logic
10020 * Some space which must UNDEF
10022 int op1 = (insn >> 23) & 3;
10023 int op2 = (insn >> 6) & 0x3f;
10024 if (op & 2) {
10025 goto illegal_op;
10027 if (rn == 15) {
10028 /* UNPREDICTABLE, unallocated hint or
10029 * PLD/PLDW/PLI (literal)
10031 return 0;
10033 if (op1 & 1) {
10034 return 0; /* PLD/PLDW/PLI or unallocated hint */
10036 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
10037 return 0; /* PLD/PLDW/PLI or unallocated hint */
10039 /* UNDEF space, or an UNPREDICTABLE */
10040 return 1;
10043 memidx = get_mem_index(s);
10044 if (rn == 15) {
10045 addr = tcg_temp_new_i32();
10046 /* PC relative. */
10047 /* s->pc has already been incremented by 4. */
10048 imm = s->pc & 0xfffffffc;
10049 if (insn & (1 << 23))
10050 imm += insn & 0xfff;
10051 else
10052 imm -= insn & 0xfff;
10053 tcg_gen_movi_i32(addr, imm);
10054 } else {
10055 addr = load_reg(s, rn);
10056 if (insn & (1 << 23)) {
10057 /* Positive offset. */
10058 imm = insn & 0xfff;
10059 tcg_gen_addi_i32(addr, addr, imm);
10060 } else {
10061 imm = insn & 0xff;
10062 switch ((insn >> 8) & 0xf) {
10063 case 0x0: /* Shifted Register. */
10064 shift = (insn >> 4) & 0xf;
10065 if (shift > 3) {
10066 tcg_temp_free_i32(addr);
10067 goto illegal_op;
10069 tmp = load_reg(s, rm);
10070 if (shift)
10071 tcg_gen_shli_i32(tmp, tmp, shift);
10072 tcg_gen_add_i32(addr, addr, tmp);
10073 tcg_temp_free_i32(tmp);
10074 break;
10075 case 0xc: /* Negative offset. */
10076 tcg_gen_addi_i32(addr, addr, -imm);
10077 break;
10078 case 0xe: /* User privilege. */
10079 tcg_gen_addi_i32(addr, addr, imm);
10080 memidx = MMU_USER_IDX;
10081 break;
10082 case 0x9: /* Post-decrement. */
10083 imm = -imm;
10084 /* Fall through. */
10085 case 0xb: /* Post-increment. */
10086 postinc = 1;
10087 writeback = 1;
10088 break;
10089 case 0xd: /* Pre-decrement. */
10090 imm = -imm;
10091 /* Fall through. */
10092 case 0xf: /* Pre-increment. */
10093 tcg_gen_addi_i32(addr, addr, imm);
10094 writeback = 1;
10095 break;
10096 default:
10097 tcg_temp_free_i32(addr);
10098 goto illegal_op;
10102 if (insn & (1 << 20)) {
10103 /* Load. */
10104 tmp = tcg_temp_new_i32();
10105 switch (op) {
10106 case 0:
10107 gen_aa32_ld8u(tmp, addr, memidx);
10108 break;
10109 case 4:
10110 gen_aa32_ld8s(tmp, addr, memidx);
10111 break;
10112 case 1:
10113 gen_aa32_ld16u(tmp, addr, memidx);
10114 break;
10115 case 5:
10116 gen_aa32_ld16s(tmp, addr, memidx);
10117 break;
10118 case 2:
10119 gen_aa32_ld32u(tmp, addr, memidx);
10120 break;
10121 default:
10122 tcg_temp_free_i32(tmp);
10123 tcg_temp_free_i32(addr);
10124 goto illegal_op;
10126 if (rs == 15) {
10127 gen_bx(s, tmp);
10128 } else {
10129 store_reg(s, rs, tmp);
10131 } else {
10132 /* Store. */
10133 tmp = load_reg(s, rs);
10134 switch (op) {
10135 case 0:
10136 gen_aa32_st8(tmp, addr, memidx);
10137 break;
10138 case 1:
10139 gen_aa32_st16(tmp, addr, memidx);
10140 break;
10141 case 2:
10142 gen_aa32_st32(tmp, addr, memidx);
10143 break;
10144 default:
10145 tcg_temp_free_i32(tmp);
10146 tcg_temp_free_i32(addr);
10147 goto illegal_op;
10149 tcg_temp_free_i32(tmp);
10151 if (postinc)
10152 tcg_gen_addi_i32(addr, addr, imm);
10153 if (writeback) {
10154 store_reg(s, rn, addr);
10155 } else {
10156 tcg_temp_free_i32(addr);
10159 break;
10160 default:
10161 goto illegal_op;
10163 return 0;
10164 illegal_op:
10165 return 1;
10168 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
10170 uint32_t val, insn, op, rm, rn, rd, shift, cond;
10171 int32_t offset;
10172 int i;
10173 TCGv_i32 tmp;
10174 TCGv_i32 tmp2;
10175 TCGv_i32 addr;
10177 if (s->condexec_mask) {
10178 cond = s->condexec_cond;
10179 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
10180 s->condlabel = gen_new_label();
10181 arm_gen_test_cc(cond ^ 1, s->condlabel);
10182 s->condjmp = 1;
10186 insn = arm_lduw_code(env, s->pc, s->bswap_code);
10187 s->pc += 2;
10189 switch (insn >> 12) {
10190 case 0: case 1:
10192 rd = insn & 7;
10193 op = (insn >> 11) & 3;
10194 if (op == 3) {
10195 /* add/subtract */
10196 rn = (insn >> 3) & 7;
10197 tmp = load_reg(s, rn);
10198 if (insn & (1 << 10)) {
10199 /* immediate */
10200 tmp2 = tcg_temp_new_i32();
10201 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
10202 } else {
10203 /* reg */
10204 rm = (insn >> 6) & 7;
10205 tmp2 = load_reg(s, rm);
10207 if (insn & (1 << 9)) {
10208 if (s->condexec_mask)
10209 tcg_gen_sub_i32(tmp, tmp, tmp2);
10210 else
10211 gen_sub_CC(tmp, tmp, tmp2);
10212 } else {
10213 if (s->condexec_mask)
10214 tcg_gen_add_i32(tmp, tmp, tmp2);
10215 else
10216 gen_add_CC(tmp, tmp, tmp2);
10218 tcg_temp_free_i32(tmp2);
10219 store_reg(s, rd, tmp);
10220 } else {
10221 /* shift immediate */
10222 rm = (insn >> 3) & 7;
10223 shift = (insn >> 6) & 0x1f;
10224 tmp = load_reg(s, rm);
10225 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
10226 if (!s->condexec_mask)
10227 gen_logic_CC(tmp);
10228 store_reg(s, rd, tmp);
10230 break;
10231 case 2: case 3:
10232 /* arithmetic large immediate */
10233 op = (insn >> 11) & 3;
10234 rd = (insn >> 8) & 0x7;
10235 if (op == 0) { /* mov */
10236 tmp = tcg_temp_new_i32();
10237 tcg_gen_movi_i32(tmp, insn & 0xff);
10238 if (!s->condexec_mask)
10239 gen_logic_CC(tmp);
10240 store_reg(s, rd, tmp);
10241 } else {
10242 tmp = load_reg(s, rd);
10243 tmp2 = tcg_temp_new_i32();
10244 tcg_gen_movi_i32(tmp2, insn & 0xff);
10245 switch (op) {
10246 case 1: /* cmp */
10247 gen_sub_CC(tmp, tmp, tmp2);
10248 tcg_temp_free_i32(tmp);
10249 tcg_temp_free_i32(tmp2);
10250 break;
10251 case 2: /* add */
10252 if (s->condexec_mask)
10253 tcg_gen_add_i32(tmp, tmp, tmp2);
10254 else
10255 gen_add_CC(tmp, tmp, tmp2);
10256 tcg_temp_free_i32(tmp2);
10257 store_reg(s, rd, tmp);
10258 break;
10259 case 3: /* sub */
10260 if (s->condexec_mask)
10261 tcg_gen_sub_i32(tmp, tmp, tmp2);
10262 else
10263 gen_sub_CC(tmp, tmp, tmp2);
10264 tcg_temp_free_i32(tmp2);
10265 store_reg(s, rd, tmp);
10266 break;
10269 break;
10270 case 4:
10271 if (insn & (1 << 11)) {
10272 rd = (insn >> 8) & 7;
10273 /* load pc-relative. Bit 1 of PC is ignored. */
10274 val = s->pc + 2 + ((insn & 0xff) * 4);
10275 val &= ~(uint32_t)2;
10276 addr = tcg_temp_new_i32();
10277 tcg_gen_movi_i32(addr, val);
10278 tmp = tcg_temp_new_i32();
10279 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10280 tcg_temp_free_i32(addr);
10281 store_reg(s, rd, tmp);
10282 break;
10284 if (insn & (1 << 10)) {
10285 /* data processing extended or blx */
10286 rd = (insn & 7) | ((insn >> 4) & 8);
10287 rm = (insn >> 3) & 0xf;
10288 op = (insn >> 8) & 3;
10289 switch (op) {
10290 case 0: /* add */
10291 tmp = load_reg(s, rd);
10292 tmp2 = load_reg(s, rm);
10293 tcg_gen_add_i32(tmp, tmp, tmp2);
10294 tcg_temp_free_i32(tmp2);
10295 store_reg(s, rd, tmp);
10296 break;
10297 case 1: /* cmp */
10298 tmp = load_reg(s, rd);
10299 tmp2 = load_reg(s, rm);
10300 gen_sub_CC(tmp, tmp, tmp2);
10301 tcg_temp_free_i32(tmp2);
10302 tcg_temp_free_i32(tmp);
10303 break;
10304 case 2: /* mov/cpy */
10305 tmp = load_reg(s, rm);
10306 store_reg(s, rd, tmp);
10307 break;
10308 case 3:/* branch [and link] exchange thumb register */
10309 tmp = load_reg(s, rm);
10310 if (insn & (1 << 7)) {
10311 ARCH(5);
10312 val = (uint32_t)s->pc | 1;
10313 tmp2 = tcg_temp_new_i32();
10314 tcg_gen_movi_i32(tmp2, val);
10315 store_reg(s, 14, tmp2);
10317 /* already thumb, no need to check */
10318 gen_bx(s, tmp);
10319 break;
10321 break;
10324 /* data processing register */
10325 rd = insn & 7;
10326 rm = (insn >> 3) & 7;
10327 op = (insn >> 6) & 0xf;
10328 if (op == 2 || op == 3 || op == 4 || op == 7) {
10329 /* the shift/rotate ops want the operands backwards */
10330 val = rm;
10331 rm = rd;
10332 rd = val;
10333 val = 1;
10334 } else {
10335 val = 0;
10338 if (op == 9) { /* neg */
10339 tmp = tcg_temp_new_i32();
10340 tcg_gen_movi_i32(tmp, 0);
10341 } else if (op != 0xf) { /* mvn doesn't read its first operand */
10342 tmp = load_reg(s, rd);
10343 } else {
10344 TCGV_UNUSED_I32(tmp);
10347 tmp2 = load_reg(s, rm);
10348 switch (op) {
10349 case 0x0: /* and */
10350 tcg_gen_and_i32(tmp, tmp, tmp2);
10351 if (!s->condexec_mask)
10352 gen_logic_CC(tmp);
10353 break;
10354 case 0x1: /* eor */
10355 tcg_gen_xor_i32(tmp, tmp, tmp2);
10356 if (!s->condexec_mask)
10357 gen_logic_CC(tmp);
10358 break;
10359 case 0x2: /* lsl */
10360 if (s->condexec_mask) {
10361 gen_shl(tmp2, tmp2, tmp);
10362 } else {
10363 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
10364 gen_logic_CC(tmp2);
10366 break;
10367 case 0x3: /* lsr */
10368 if (s->condexec_mask) {
10369 gen_shr(tmp2, tmp2, tmp);
10370 } else {
10371 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
10372 gen_logic_CC(tmp2);
10374 break;
10375 case 0x4: /* asr */
10376 if (s->condexec_mask) {
10377 gen_sar(tmp2, tmp2, tmp);
10378 } else {
10379 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
10380 gen_logic_CC(tmp2);
10382 break;
10383 case 0x5: /* adc */
10384 if (s->condexec_mask) {
10385 gen_adc(tmp, tmp2);
10386 } else {
10387 gen_adc_CC(tmp, tmp, tmp2);
10389 break;
10390 case 0x6: /* sbc */
10391 if (s->condexec_mask) {
10392 gen_sub_carry(tmp, tmp, tmp2);
10393 } else {
10394 gen_sbc_CC(tmp, tmp, tmp2);
10396 break;
10397 case 0x7: /* ror */
10398 if (s->condexec_mask) {
10399 tcg_gen_andi_i32(tmp, tmp, 0x1f);
10400 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
10401 } else {
10402 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
10403 gen_logic_CC(tmp2);
10405 break;
10406 case 0x8: /* tst */
10407 tcg_gen_and_i32(tmp, tmp, tmp2);
10408 gen_logic_CC(tmp);
10409 rd = 16;
10410 break;
10411 case 0x9: /* neg */
10412 if (s->condexec_mask)
10413 tcg_gen_neg_i32(tmp, tmp2);
10414 else
10415 gen_sub_CC(tmp, tmp, tmp2);
10416 break;
10417 case 0xa: /* cmp */
10418 gen_sub_CC(tmp, tmp, tmp2);
10419 rd = 16;
10420 break;
10421 case 0xb: /* cmn */
10422 gen_add_CC(tmp, tmp, tmp2);
10423 rd = 16;
10424 break;
10425 case 0xc: /* orr */
10426 tcg_gen_or_i32(tmp, tmp, tmp2);
10427 if (!s->condexec_mask)
10428 gen_logic_CC(tmp);
10429 break;
10430 case 0xd: /* mul */
10431 tcg_gen_mul_i32(tmp, tmp, tmp2);
10432 if (!s->condexec_mask)
10433 gen_logic_CC(tmp);
10434 break;
10435 case 0xe: /* bic */
10436 tcg_gen_andc_i32(tmp, tmp, tmp2);
10437 if (!s->condexec_mask)
10438 gen_logic_CC(tmp);
10439 break;
10440 case 0xf: /* mvn */
10441 tcg_gen_not_i32(tmp2, tmp2);
10442 if (!s->condexec_mask)
10443 gen_logic_CC(tmp2);
10444 val = 1;
10445 rm = rd;
10446 break;
10448 if (rd != 16) {
10449 if (val) {
10450 store_reg(s, rm, tmp2);
10451 if (op != 0xf)
10452 tcg_temp_free_i32(tmp);
10453 } else {
10454 store_reg(s, rd, tmp);
10455 tcg_temp_free_i32(tmp2);
10457 } else {
10458 tcg_temp_free_i32(tmp);
10459 tcg_temp_free_i32(tmp2);
10461 break;
10463 case 5:
10464 /* load/store register offset. */
10465 rd = insn & 7;
10466 rn = (insn >> 3) & 7;
10467 rm = (insn >> 6) & 7;
10468 op = (insn >> 9) & 7;
10469 addr = load_reg(s, rn);
10470 tmp = load_reg(s, rm);
10471 tcg_gen_add_i32(addr, addr, tmp);
10472 tcg_temp_free_i32(tmp);
10474 if (op < 3) { /* store */
10475 tmp = load_reg(s, rd);
10476 } else {
10477 tmp = tcg_temp_new_i32();
10480 switch (op) {
10481 case 0: /* str */
10482 gen_aa32_st32(tmp, addr, get_mem_index(s));
10483 break;
10484 case 1: /* strh */
10485 gen_aa32_st16(tmp, addr, get_mem_index(s));
10486 break;
10487 case 2: /* strb */
10488 gen_aa32_st8(tmp, addr, get_mem_index(s));
10489 break;
10490 case 3: /* ldrsb */
10491 gen_aa32_ld8s(tmp, addr, get_mem_index(s));
10492 break;
10493 case 4: /* ldr */
10494 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10495 break;
10496 case 5: /* ldrh */
10497 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
10498 break;
10499 case 6: /* ldrb */
10500 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
10501 break;
10502 case 7: /* ldrsh */
10503 gen_aa32_ld16s(tmp, addr, get_mem_index(s));
10504 break;
10506 if (op >= 3) { /* load */
10507 store_reg(s, rd, tmp);
10508 } else {
10509 tcg_temp_free_i32(tmp);
10511 tcg_temp_free_i32(addr);
10512 break;
10514 case 6:
10515 /* load/store word immediate offset */
10516 rd = insn & 7;
10517 rn = (insn >> 3) & 7;
10518 addr = load_reg(s, rn);
10519 val = (insn >> 4) & 0x7c;
10520 tcg_gen_addi_i32(addr, addr, val);
10522 if (insn & (1 << 11)) {
10523 /* load */
10524 tmp = tcg_temp_new_i32();
10525 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10526 store_reg(s, rd, tmp);
10527 } else {
10528 /* store */
10529 tmp = load_reg(s, rd);
10530 gen_aa32_st32(tmp, addr, get_mem_index(s));
10531 tcg_temp_free_i32(tmp);
10533 tcg_temp_free_i32(addr);
10534 break;
10536 case 7:
10537 /* load/store byte immediate offset */
10538 rd = insn & 7;
10539 rn = (insn >> 3) & 7;
10540 addr = load_reg(s, rn);
10541 val = (insn >> 6) & 0x1f;
10542 tcg_gen_addi_i32(addr, addr, val);
10544 if (insn & (1 << 11)) {
10545 /* load */
10546 tmp = tcg_temp_new_i32();
10547 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
10548 store_reg(s, rd, tmp);
10549 } else {
10550 /* store */
10551 tmp = load_reg(s, rd);
10552 gen_aa32_st8(tmp, addr, get_mem_index(s));
10553 tcg_temp_free_i32(tmp);
10555 tcg_temp_free_i32(addr);
10556 break;
10558 case 8:
10559 /* load/store halfword immediate offset */
10560 rd = insn & 7;
10561 rn = (insn >> 3) & 7;
10562 addr = load_reg(s, rn);
10563 val = (insn >> 5) & 0x3e;
10564 tcg_gen_addi_i32(addr, addr, val);
10566 if (insn & (1 << 11)) {
10567 /* load */
10568 tmp = tcg_temp_new_i32();
10569 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
10570 store_reg(s, rd, tmp);
10571 } else {
10572 /* store */
10573 tmp = load_reg(s, rd);
10574 gen_aa32_st16(tmp, addr, get_mem_index(s));
10575 tcg_temp_free_i32(tmp);
10577 tcg_temp_free_i32(addr);
10578 break;
10580 case 9:
10581 /* load/store from stack */
10582 rd = (insn >> 8) & 7;
10583 addr = load_reg(s, 13);
10584 val = (insn & 0xff) * 4;
10585 tcg_gen_addi_i32(addr, addr, val);
10587 if (insn & (1 << 11)) {
10588 /* load */
10589 tmp = tcg_temp_new_i32();
10590 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10591 store_reg(s, rd, tmp);
10592 } else {
10593 /* store */
10594 tmp = load_reg(s, rd);
10595 gen_aa32_st32(tmp, addr, get_mem_index(s));
10596 tcg_temp_free_i32(tmp);
10598 tcg_temp_free_i32(addr);
10599 break;
10601 case 10:
10602 /* add to high reg */
10603 rd = (insn >> 8) & 7;
10604 if (insn & (1 << 11)) {
10605 /* SP */
10606 tmp = load_reg(s, 13);
10607 } else {
10608 /* PC. bit 1 is ignored. */
10609 tmp = tcg_temp_new_i32();
10610 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
10612 val = (insn & 0xff) * 4;
10613 tcg_gen_addi_i32(tmp, tmp, val);
10614 store_reg(s, rd, tmp);
10615 break;
10617 case 11:
10618 /* misc */
10619 op = (insn >> 8) & 0xf;
10620 switch (op) {
10621 case 0:
10622 /* adjust stack pointer */
10623 tmp = load_reg(s, 13);
10624 val = (insn & 0x7f) * 4;
10625 if (insn & (1 << 7))
10626 val = -(int32_t)val;
10627 tcg_gen_addi_i32(tmp, tmp, val);
10628 store_reg(s, 13, tmp);
10629 break;
10631 case 2: /* sign/zero extend. */
10632 ARCH(6);
10633 rd = insn & 7;
10634 rm = (insn >> 3) & 7;
10635 tmp = load_reg(s, rm);
10636 switch ((insn >> 6) & 3) {
10637 case 0: gen_sxth(tmp); break;
10638 case 1: gen_sxtb(tmp); break;
10639 case 2: gen_uxth(tmp); break;
10640 case 3: gen_uxtb(tmp); break;
10642 store_reg(s, rd, tmp);
10643 break;
10644 case 4: case 5: case 0xc: case 0xd:
10645 /* push/pop */
10646 addr = load_reg(s, 13);
10647 if (insn & (1 << 8))
10648 offset = 4;
10649 else
10650 offset = 0;
10651 for (i = 0; i < 8; i++) {
10652 if (insn & (1 << i))
10653 offset += 4;
10655 if ((insn & (1 << 11)) == 0) {
10656 tcg_gen_addi_i32(addr, addr, -offset);
10658 for (i = 0; i < 8; i++) {
10659 if (insn & (1 << i)) {
10660 if (insn & (1 << 11)) {
10661 /* pop */
10662 tmp = tcg_temp_new_i32();
10663 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10664 store_reg(s, i, tmp);
10665 } else {
10666 /* push */
10667 tmp = load_reg(s, i);
10668 gen_aa32_st32(tmp, addr, get_mem_index(s));
10669 tcg_temp_free_i32(tmp);
10671 /* advance to the next address. */
10672 tcg_gen_addi_i32(addr, addr, 4);
10675 TCGV_UNUSED_I32(tmp);
10676 if (insn & (1 << 8)) {
10677 if (insn & (1 << 11)) {
10678 /* pop pc */
10679 tmp = tcg_temp_new_i32();
10680 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10681 /* don't set the pc until the rest of the instruction
10682 has completed */
10683 } else {
10684 /* push lr */
10685 tmp = load_reg(s, 14);
10686 gen_aa32_st32(tmp, addr, get_mem_index(s));
10687 tcg_temp_free_i32(tmp);
10689 tcg_gen_addi_i32(addr, addr, 4);
10691 if ((insn & (1 << 11)) == 0) {
10692 tcg_gen_addi_i32(addr, addr, -offset);
10694 /* write back the new stack pointer */
10695 store_reg(s, 13, addr);
10696 /* set the new PC value */
10697 if ((insn & 0x0900) == 0x0900) {
10698 store_reg_from_load(env, s, 15, tmp);
10700 break;
10702 case 1: case 3: case 9: case 11: /* czb */
10703 rm = insn & 7;
10704 tmp = load_reg(s, rm);
10705 s->condlabel = gen_new_label();
10706 s->condjmp = 1;
10707 if (insn & (1 << 11))
10708 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
10709 else
10710 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
10711 tcg_temp_free_i32(tmp);
10712 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
10713 val = (uint32_t)s->pc + 2;
10714 val += offset;
10715 gen_jmp(s, val);
10716 break;
10718 case 15: /* IT, nop-hint. */
10719 if ((insn & 0xf) == 0) {
10720 gen_nop_hint(s, (insn >> 4) & 0xf);
10721 break;
10723 /* If Then. */
10724 s->condexec_cond = (insn >> 4) & 0xe;
10725 s->condexec_mask = insn & 0x1f;
10726 /* No actual code generated for this insn, just setup state. */
10727 break;
10729 case 0xe: /* bkpt */
10731 int imm8 = extract32(insn, 0, 8);
10732 ARCH(5);
10733 gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true));
10734 break;
10737 case 0xa: /* rev */
10738 ARCH(6);
10739 rn = (insn >> 3) & 0x7;
10740 rd = insn & 0x7;
10741 tmp = load_reg(s, rn);
10742 switch ((insn >> 6) & 3) {
10743 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
10744 case 1: gen_rev16(tmp); break;
10745 case 3: gen_revsh(tmp); break;
10746 default: goto illegal_op;
10748 store_reg(s, rd, tmp);
10749 break;
10751 case 6:
10752 switch ((insn >> 5) & 7) {
10753 case 2:
10754 /* setend */
10755 ARCH(6);
10756 if (((insn >> 3) & 1) != s->bswap_code) {
10757 /* Dynamic endianness switching not implemented. */
10758 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
10759 goto illegal_op;
10761 break;
10762 case 3:
10763 /* cps */
10764 ARCH(6);
10765 if (IS_USER(s)) {
10766 break;
10768 if (IS_M(env)) {
10769 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
10770 /* FAULTMASK */
10771 if (insn & 1) {
10772 addr = tcg_const_i32(19);
10773 gen_helper_v7m_msr(cpu_env, addr, tmp);
10774 tcg_temp_free_i32(addr);
10776 /* PRIMASK */
10777 if (insn & 2) {
10778 addr = tcg_const_i32(16);
10779 gen_helper_v7m_msr(cpu_env, addr, tmp);
10780 tcg_temp_free_i32(addr);
10782 tcg_temp_free_i32(tmp);
10783 gen_lookup_tb(s);
10784 } else {
10785 if (insn & (1 << 4)) {
10786 shift = CPSR_A | CPSR_I | CPSR_F;
10787 } else {
10788 shift = 0;
10790 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
10792 break;
10793 default:
10794 goto undef;
10796 break;
10798 default:
10799 goto undef;
10801 break;
10803 case 12:
10805 /* load/store multiple */
10806 TCGv_i32 loaded_var;
10807 TCGV_UNUSED_I32(loaded_var);
10808 rn = (insn >> 8) & 0x7;
10809 addr = load_reg(s, rn);
10810 for (i = 0; i < 8; i++) {
10811 if (insn & (1 << i)) {
10812 if (insn & (1 << 11)) {
10813 /* load */
10814 tmp = tcg_temp_new_i32();
10815 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10816 if (i == rn) {
10817 loaded_var = tmp;
10818 } else {
10819 store_reg(s, i, tmp);
10821 } else {
10822 /* store */
10823 tmp = load_reg(s, i);
10824 gen_aa32_st32(tmp, addr, get_mem_index(s));
10825 tcg_temp_free_i32(tmp);
10827 /* advance to the next address */
10828 tcg_gen_addi_i32(addr, addr, 4);
10831 if ((insn & (1 << rn)) == 0) {
10832 /* base reg not in list: base register writeback */
10833 store_reg(s, rn, addr);
10834 } else {
10835 /* base reg in list: if load, complete it now */
10836 if (insn & (1 << 11)) {
10837 store_reg(s, rn, loaded_var);
10839 tcg_temp_free_i32(addr);
10841 break;
10843 case 13:
10844 /* conditional branch or swi */
10845 cond = (insn >> 8) & 0xf;
10846 if (cond == 0xe)
10847 goto undef;
10849 if (cond == 0xf) {
10850 /* swi */
10851 gen_set_pc_im(s, s->pc);
10852 s->svc_imm = extract32(insn, 0, 8);
10853 s->is_jmp = DISAS_SWI;
10854 break;
10856 /* generate a conditional jump to next instruction */
10857 s->condlabel = gen_new_label();
10858 arm_gen_test_cc(cond ^ 1, s->condlabel);
10859 s->condjmp = 1;
10861 /* jump to the offset */
10862 val = (uint32_t)s->pc + 2;
10863 offset = ((int32_t)insn << 24) >> 24;
10864 val += offset << 1;
10865 gen_jmp(s, val);
10866 break;
10868 case 14:
10869 if (insn & (1 << 11)) {
10870 if (disas_thumb2_insn(env, s, insn))
10871 goto undef32;
10872 break;
10874 /* unconditional branch */
10875 val = (uint32_t)s->pc;
10876 offset = ((int32_t)insn << 21) >> 21;
10877 val += (offset << 1) + 2;
10878 gen_jmp(s, val);
10879 break;
10881 case 15:
10882 if (disas_thumb2_insn(env, s, insn))
10883 goto undef32;
10884 break;
10886 return;
10887 undef32:
10888 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
10889 return;
10890 illegal_op:
10891 undef:
10892 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized());
10895 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
10896 basic block 'tb'. If search_pc is TRUE, also generate PC
10897 information for each intermediate instruction. */
10898 static inline void gen_intermediate_code_internal(ARMCPU *cpu,
10899 TranslationBlock *tb,
10900 bool search_pc)
10902 CPUState *cs = CPU(cpu);
10903 CPUARMState *env = &cpu->env;
10904 DisasContext dc1, *dc = &dc1;
10905 CPUBreakpoint *bp;
10906 uint16_t *gen_opc_end;
10907 int j, lj;
10908 target_ulong pc_start;
10909 target_ulong next_page_start;
10910 int num_insns;
10911 int max_insns;
10913 /* generate intermediate code */
10915 /* The A64 decoder has its own top level loop, because it doesn't need
10916 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
10918 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
10919 gen_intermediate_code_internal_a64(cpu, tb, search_pc);
10920 return;
10923 pc_start = tb->pc;
10925 dc->tb = tb;
10927 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
10929 dc->is_jmp = DISAS_NEXT;
10930 dc->pc = pc_start;
10931 dc->singlestep_enabled = cs->singlestep_enabled;
10932 dc->condjmp = 0;
10934 dc->aarch64 = 0;
10935 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
10936 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
10937 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
10938 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
10939 #if !defined(CONFIG_USER_ONLY)
10940 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
10941 #endif
10942 dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
10943 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
10944 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
10945 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
10946 dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
10947 dc->cp_regs = cpu->cp_regs;
10948 dc->current_pl = arm_current_pl(env);
10949 dc->features = env->features;
10951 /* Single step state. The code-generation logic here is:
10952 * SS_ACTIVE == 0:
10953 * generate code with no special handling for single-stepping (except
10954 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
10955 * this happens anyway because those changes are all system register or
10956 * PSTATE writes).
10957 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
10958 * emit code for one insn
10959 * emit code to clear PSTATE.SS
10960 * emit code to generate software step exception for completed step
10961 * end TB (as usual for having generated an exception)
10962 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
10963 * emit code to generate a software step exception
10964 * end the TB
10966 dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);
10967 dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);
10968 dc->is_ldex = false;
10969 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
10971 cpu_F0s = tcg_temp_new_i32();
10972 cpu_F1s = tcg_temp_new_i32();
10973 cpu_F0d = tcg_temp_new_i64();
10974 cpu_F1d = tcg_temp_new_i64();
10975 cpu_V0 = cpu_F0d;
10976 cpu_V1 = cpu_F1d;
10977 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
10978 cpu_M0 = tcg_temp_new_i64();
10979 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
10980 lj = -1;
10981 num_insns = 0;
10982 max_insns = tb->cflags & CF_COUNT_MASK;
10983 if (max_insns == 0)
10984 max_insns = CF_COUNT_MASK;
10986 gen_tb_start();
10988 tcg_clear_temp_count();
10990 /* A note on handling of the condexec (IT) bits:
10992 * We want to avoid the overhead of having to write the updated condexec
10993 * bits back to the CPUARMState for every instruction in an IT block. So:
10994 * (1) if the condexec bits are not already zero then we write
10995 * zero back into the CPUARMState now. This avoids complications trying
10996 * to do it at the end of the block. (For example if we don't do this
10997 * it's hard to identify whether we can safely skip writing condexec
10998 * at the end of the TB, which we definitely want to do for the case
10999 * where a TB doesn't do anything with the IT state at all.)
11000 * (2) if we are going to leave the TB then we call gen_set_condexec()
11001 * which will write the correct value into CPUARMState if zero is wrong.
11002 * This is done both for leaving the TB at the end, and for leaving
11003 * it because of an exception we know will happen, which is done in
11004 * gen_exception_insn(). The latter is necessary because we need to
11005 * leave the TB with the PC/IT state just prior to execution of the
11006 * instruction which caused the exception.
11007 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
11008 * then the CPUARMState will be wrong and we need to reset it.
11009 * This is handled in the same way as restoration of the
11010 * PC in these situations: we will be called again with search_pc=1
11011 * and generate a mapping of the condexec bits for each PC in
11012 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
11013 * this to restore the condexec bits.
11015 * Note that there are no instructions which can read the condexec
11016 * bits, and none which can write non-static values to them, so
11017 * we don't need to care about whether CPUARMState is correct in the
11018 * middle of a TB.
11021 /* Reset the conditional execution bits immediately. This avoids
11022 complications trying to do it at the end of the block. */
11023 if (dc->condexec_mask || dc->condexec_cond)
11025 TCGv_i32 tmp = tcg_temp_new_i32();
11026 tcg_gen_movi_i32(tmp, 0);
11027 store_cpu_field(tmp, condexec_bits);
11029 do {
11030 #ifdef CONFIG_USER_ONLY
11031 /* Intercept jump to the magic kernel page. */
11032 if (dc->pc >= 0xffff0000) {
11033 /* We always get here via a jump, so know we are not in a
11034 conditional execution block. */
11035 gen_exception_internal(EXCP_KERNEL_TRAP);
11036 dc->is_jmp = DISAS_UPDATE;
11037 break;
11039 #else
11040 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
11041 /* We always get here via a jump, so know we are not in a
11042 conditional execution block. */
11043 gen_exception_internal(EXCP_EXCEPTION_EXIT);
11044 dc->is_jmp = DISAS_UPDATE;
11045 break;
11047 #endif
11049 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
11050 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
11051 if (bp->pc == dc->pc) {
11052 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
11053 /* Advance PC so that clearing the breakpoint will
11054 invalidate this TB. */
11055 dc->pc += 2;
11056 goto done_generating;
11060 if (search_pc) {
11061 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
11062 if (lj < j) {
11063 lj++;
11064 while (lj < j)
11065 tcg_ctx.gen_opc_instr_start[lj++] = 0;
11067 tcg_ctx.gen_opc_pc[lj] = dc->pc;
11068 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
11069 tcg_ctx.gen_opc_instr_start[lj] = 1;
11070 tcg_ctx.gen_opc_icount[lj] = num_insns;
11073 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
11074 gen_io_start();
11076 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
11077 tcg_gen_debug_insn_start(dc->pc);
11080 if (dc->ss_active && !dc->pstate_ss) {
11081 /* Singlestep state is Active-pending.
11082 * If we're in this state at the start of a TB then either
11083 * a) we just took an exception to an EL which is being debugged
11084 * and this is the first insn in the exception handler
11085 * b) debug exceptions were masked and we just unmasked them
11086 * without changing EL (eg by clearing PSTATE.D)
11087 * In either case we're going to take a swstep exception in the
11088 * "did not step an insn" case, and so the syndrome ISV and EX
11089 * bits should be zero.
11091 assert(num_insns == 0);
11092 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0));
11093 goto done_generating;
11096 if (dc->thumb) {
11097 disas_thumb_insn(env, dc);
11098 if (dc->condexec_mask) {
11099 dc->condexec_cond = (dc->condexec_cond & 0xe)
11100 | ((dc->condexec_mask >> 4) & 1);
11101 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
11102 if (dc->condexec_mask == 0) {
11103 dc->condexec_cond = 0;
11106 } else {
11107 disas_arm_insn(env, dc);
11110 if (dc->condjmp && !dc->is_jmp) {
11111 gen_set_label(dc->condlabel);
11112 dc->condjmp = 0;
11115 if (tcg_check_temp_count()) {
11116 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
11117 dc->pc);
11120 /* Translation stops when a conditional branch is encountered.
11121 * Otherwise the subsequent code could get translated several times.
11122 * Also stop translation when a page boundary is reached. This
11123 * ensures prefetch aborts occur at the right place. */
11124 num_insns ++;
11125 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
11126 !cs->singlestep_enabled &&
11127 !singlestep &&
11128 !dc->ss_active &&
11129 dc->pc < next_page_start &&
11130 num_insns < max_insns);
11132 if (tb->cflags & CF_LAST_IO) {
11133 if (dc->condjmp) {
11134 /* FIXME: This can theoretically happen with self-modifying
11135 code. */
11136 cpu_abort(cs, "IO on conditional branch instruction");
11138 gen_io_end();
11141 /* At this stage dc->condjmp will only be set when the skipped
11142 instruction was a conditional branch or trap, and the PC has
11143 already been written. */
11144 if (unlikely(cs->singlestep_enabled || dc->ss_active)) {
11145 /* Make sure the pc is updated, and raise a debug exception. */
11146 if (dc->condjmp) {
11147 gen_set_condexec(dc);
11148 if (dc->is_jmp == DISAS_SWI) {
11149 gen_ss_advance(dc);
11150 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
11151 } else if (dc->ss_active) {
11152 gen_step_complete_exception(dc);
11153 } else {
11154 gen_exception_internal(EXCP_DEBUG);
11156 gen_set_label(dc->condlabel);
11158 if (dc->condjmp || !dc->is_jmp) {
11159 gen_set_pc_im(dc, dc->pc);
11160 dc->condjmp = 0;
11162 gen_set_condexec(dc);
11163 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
11164 gen_ss_advance(dc);
11165 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
11166 } else if (dc->ss_active) {
11167 gen_step_complete_exception(dc);
11168 } else {
11169 /* FIXME: Single stepping a WFI insn will not halt
11170 the CPU. */
11171 gen_exception_internal(EXCP_DEBUG);
11173 } else {
11174 /* While branches must always occur at the end of an IT block,
11175 there are a few other things that can cause us to terminate
11176 the TB in the middle of an IT block:
11177 - Exception generating instructions (bkpt, swi, undefined).
11178 - Page boundaries.
11179 - Hardware watchpoints.
11180 Hardware breakpoints have already been handled and skip this code.
11182 gen_set_condexec(dc);
11183 switch(dc->is_jmp) {
11184 case DISAS_NEXT:
11185 gen_goto_tb(dc, 1, dc->pc);
11186 break;
11187 default:
11188 case DISAS_JUMP:
11189 case DISAS_UPDATE:
11190 /* indicate that the hash table must be used to find the next TB */
11191 tcg_gen_exit_tb(0);
11192 break;
11193 case DISAS_TB_JUMP:
11194 /* nothing more to generate */
11195 break;
11196 case DISAS_WFI:
11197 gen_helper_wfi(cpu_env);
11198 break;
11199 case DISAS_WFE:
11200 gen_helper_wfe(cpu_env);
11201 break;
11202 case DISAS_SWI:
11203 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
11204 break;
11206 if (dc->condjmp) {
11207 gen_set_label(dc->condlabel);
11208 gen_set_condexec(dc);
11209 gen_goto_tb(dc, 1, dc->pc);
11210 dc->condjmp = 0;
11214 done_generating:
11215 gen_tb_end(tb, num_insns);
11216 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
11218 #ifdef DEBUG_DISAS
11219 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
11220 qemu_log("----------------\n");
11221 qemu_log("IN: %s\n", lookup_symbol(pc_start));
11222 log_target_disas(env, pc_start, dc->pc - pc_start,
11223 dc->thumb | (dc->bswap_code << 1));
11224 qemu_log("\n");
11226 #endif
11227 if (search_pc) {
11228 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
11229 lj++;
11230 while (lj <= j)
11231 tcg_ctx.gen_opc_instr_start[lj++] = 0;
11232 } else {
11233 tb->size = dc->pc - pc_start;
11234 tb->icount = num_insns;
11238 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
11240 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
11243 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
11245 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
11248 static const char *cpu_mode_names[16] = {
11249 "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
11250 "???", "???", "hyp", "und", "???", "???", "???", "sys"
11253 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11254 int flags)
11256 ARMCPU *cpu = ARM_CPU(cs);
11257 CPUARMState *env = &cpu->env;
11258 int i;
11259 uint32_t psr;
11261 if (is_a64(env)) {
11262 aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
11263 return;
11266 for(i=0;i<16;i++) {
11267 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
11268 if ((i % 4) == 3)
11269 cpu_fprintf(f, "\n");
11270 else
11271 cpu_fprintf(f, " ");
11273 psr = cpsr_read(env);
11274 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
11275 psr,
11276 psr & (1 << 31) ? 'N' : '-',
11277 psr & (1 << 30) ? 'Z' : '-',
11278 psr & (1 << 29) ? 'C' : '-',
11279 psr & (1 << 28) ? 'V' : '-',
11280 psr & CPSR_T ? 'T' : 'A',
11281 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
11283 if (flags & CPU_DUMP_FPU) {
11284 int numvfpregs = 0;
11285 if (arm_feature(env, ARM_FEATURE_VFP)) {
11286 numvfpregs += 16;
11288 if (arm_feature(env, ARM_FEATURE_VFP3)) {
11289 numvfpregs += 16;
11291 for (i = 0; i < numvfpregs; i++) {
11292 uint64_t v = float64_val(env->vfp.regs[i]);
11293 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
11294 i * 2, (uint32_t)v,
11295 i * 2 + 1, (uint32_t)(v >> 32),
11296 i, v);
11298 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
11302 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
11304 if (is_a64(env)) {
11305 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
11306 env->condexec_bits = 0;
11307 } else {
11308 env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
11309 env->condexec_bits = gen_opc_condexec_bits[pc_pos];