gtk: Install fullscreen accelerator on toplevel window
[qemu.git] / target-arm / translate.c
blob1d52e4774f4d26c6e361c57e7b23e6a735315b00
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 gen_hvc(DisasContext *s, int imm16)
946 /* The pre HVC helper handles cases when HVC gets trapped
947 * as an undefined insn by runtime configuration (ie before
948 * the insn really executes).
950 gen_set_pc_im(s, s->pc - 4);
951 gen_helper_pre_hvc(cpu_env);
952 /* Otherwise we will treat this as a real exception which
953 * happens after execution of the insn. (The distinction matters
954 * for the PC value reported to the exception handler and also
955 * for single stepping.)
957 s->svc_imm = imm16;
958 gen_set_pc_im(s, s->pc);
959 s->is_jmp = DISAS_HVC;
962 static inline void gen_smc(DisasContext *s)
964 /* As with HVC, we may take an exception either before or after
965 * the insn executes.
967 TCGv_i32 tmp;
969 gen_set_pc_im(s, s->pc - 4);
970 tmp = tcg_const_i32(syn_aa32_smc());
971 gen_helper_pre_smc(cpu_env, tmp);
972 tcg_temp_free_i32(tmp);
973 gen_set_pc_im(s, s->pc);
974 s->is_jmp = DISAS_SMC;
977 static inline void
978 gen_set_condexec (DisasContext *s)
980 if (s->condexec_mask) {
981 uint32_t val = (s->condexec_cond << 4) | (s->condexec_mask >> 1);
982 TCGv_i32 tmp = tcg_temp_new_i32();
983 tcg_gen_movi_i32(tmp, val);
984 store_cpu_field(tmp, condexec_bits);
988 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
990 gen_set_condexec(s);
991 gen_set_pc_im(s, s->pc - offset);
992 gen_exception_internal(excp);
993 s->is_jmp = DISAS_JUMP;
996 static void gen_exception_insn(DisasContext *s, int offset, int excp, int syn)
998 gen_set_condexec(s);
999 gen_set_pc_im(s, s->pc - offset);
1000 gen_exception(excp, syn);
1001 s->is_jmp = DISAS_JUMP;
1004 /* Force a TB lookup after an instruction that changes the CPU state. */
1005 static inline void gen_lookup_tb(DisasContext *s)
1007 tcg_gen_movi_i32(cpu_R[15], s->pc & ~1);
1008 s->is_jmp = DISAS_UPDATE;
1011 static inline void gen_add_data_offset(DisasContext *s, unsigned int insn,
1012 TCGv_i32 var)
1014 int val, rm, shift, shiftop;
1015 TCGv_i32 offset;
1017 if (!(insn & (1 << 25))) {
1018 /* immediate */
1019 val = insn & 0xfff;
1020 if (!(insn & (1 << 23)))
1021 val = -val;
1022 if (val != 0)
1023 tcg_gen_addi_i32(var, var, val);
1024 } else {
1025 /* shift/register */
1026 rm = (insn) & 0xf;
1027 shift = (insn >> 7) & 0x1f;
1028 shiftop = (insn >> 5) & 3;
1029 offset = load_reg(s, rm);
1030 gen_arm_shift_im(offset, shiftop, shift, 0);
1031 if (!(insn & (1 << 23)))
1032 tcg_gen_sub_i32(var, var, offset);
1033 else
1034 tcg_gen_add_i32(var, var, offset);
1035 tcg_temp_free_i32(offset);
1039 static inline void gen_add_datah_offset(DisasContext *s, unsigned int insn,
1040 int extra, TCGv_i32 var)
1042 int val, rm;
1043 TCGv_i32 offset;
1045 if (insn & (1 << 22)) {
1046 /* immediate */
1047 val = (insn & 0xf) | ((insn >> 4) & 0xf0);
1048 if (!(insn & (1 << 23)))
1049 val = -val;
1050 val += extra;
1051 if (val != 0)
1052 tcg_gen_addi_i32(var, var, val);
1053 } else {
1054 /* register */
1055 if (extra)
1056 tcg_gen_addi_i32(var, var, extra);
1057 rm = (insn) & 0xf;
1058 offset = load_reg(s, rm);
1059 if (!(insn & (1 << 23)))
1060 tcg_gen_sub_i32(var, var, offset);
1061 else
1062 tcg_gen_add_i32(var, var, offset);
1063 tcg_temp_free_i32(offset);
1067 static TCGv_ptr get_fpstatus_ptr(int neon)
1069 TCGv_ptr statusptr = tcg_temp_new_ptr();
1070 int offset;
1071 if (neon) {
1072 offset = offsetof(CPUARMState, vfp.standard_fp_status);
1073 } else {
1074 offset = offsetof(CPUARMState, vfp.fp_status);
1076 tcg_gen_addi_ptr(statusptr, cpu_env, offset);
1077 return statusptr;
1080 #define VFP_OP2(name) \
1081 static inline void gen_vfp_##name(int dp) \
1083 TCGv_ptr fpst = get_fpstatus_ptr(0); \
1084 if (dp) { \
1085 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0d, cpu_F1d, fpst); \
1086 } else { \
1087 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, cpu_F1s, fpst); \
1089 tcg_temp_free_ptr(fpst); \
1092 VFP_OP2(add)
1093 VFP_OP2(sub)
1094 VFP_OP2(mul)
1095 VFP_OP2(div)
1097 #undef VFP_OP2
1099 static inline void gen_vfp_F1_mul(int dp)
1101 /* Like gen_vfp_mul() but put result in F1 */
1102 TCGv_ptr fpst = get_fpstatus_ptr(0);
1103 if (dp) {
1104 gen_helper_vfp_muld(cpu_F1d, cpu_F0d, cpu_F1d, fpst);
1105 } else {
1106 gen_helper_vfp_muls(cpu_F1s, cpu_F0s, cpu_F1s, fpst);
1108 tcg_temp_free_ptr(fpst);
1111 static inline void gen_vfp_F1_neg(int dp)
1113 /* Like gen_vfp_neg() but put result in F1 */
1114 if (dp) {
1115 gen_helper_vfp_negd(cpu_F1d, cpu_F0d);
1116 } else {
1117 gen_helper_vfp_negs(cpu_F1s, cpu_F0s);
1121 static inline void gen_vfp_abs(int dp)
1123 if (dp)
1124 gen_helper_vfp_absd(cpu_F0d, cpu_F0d);
1125 else
1126 gen_helper_vfp_abss(cpu_F0s, cpu_F0s);
1129 static inline void gen_vfp_neg(int dp)
1131 if (dp)
1132 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
1133 else
1134 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
1137 static inline void gen_vfp_sqrt(int dp)
1139 if (dp)
1140 gen_helper_vfp_sqrtd(cpu_F0d, cpu_F0d, cpu_env);
1141 else
1142 gen_helper_vfp_sqrts(cpu_F0s, cpu_F0s, cpu_env);
1145 static inline void gen_vfp_cmp(int dp)
1147 if (dp)
1148 gen_helper_vfp_cmpd(cpu_F0d, cpu_F1d, cpu_env);
1149 else
1150 gen_helper_vfp_cmps(cpu_F0s, cpu_F1s, cpu_env);
1153 static inline void gen_vfp_cmpe(int dp)
1155 if (dp)
1156 gen_helper_vfp_cmped(cpu_F0d, cpu_F1d, cpu_env);
1157 else
1158 gen_helper_vfp_cmpes(cpu_F0s, cpu_F1s, cpu_env);
1161 static inline void gen_vfp_F1_ld0(int dp)
1163 if (dp)
1164 tcg_gen_movi_i64(cpu_F1d, 0);
1165 else
1166 tcg_gen_movi_i32(cpu_F1s, 0);
1169 #define VFP_GEN_ITOF(name) \
1170 static inline void gen_vfp_##name(int dp, int neon) \
1172 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1173 if (dp) { \
1174 gen_helper_vfp_##name##d(cpu_F0d, cpu_F0s, statusptr); \
1175 } else { \
1176 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1178 tcg_temp_free_ptr(statusptr); \
1181 VFP_GEN_ITOF(uito)
1182 VFP_GEN_ITOF(sito)
1183 #undef VFP_GEN_ITOF
1185 #define VFP_GEN_FTOI(name) \
1186 static inline void gen_vfp_##name(int dp, int neon) \
1188 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1189 if (dp) { \
1190 gen_helper_vfp_##name##d(cpu_F0s, cpu_F0d, statusptr); \
1191 } else { \
1192 gen_helper_vfp_##name##s(cpu_F0s, cpu_F0s, statusptr); \
1194 tcg_temp_free_ptr(statusptr); \
1197 VFP_GEN_FTOI(toui)
1198 VFP_GEN_FTOI(touiz)
1199 VFP_GEN_FTOI(tosi)
1200 VFP_GEN_FTOI(tosiz)
1201 #undef VFP_GEN_FTOI
1203 #define VFP_GEN_FIX(name, round) \
1204 static inline void gen_vfp_##name(int dp, int shift, int neon) \
1206 TCGv_i32 tmp_shift = tcg_const_i32(shift); \
1207 TCGv_ptr statusptr = get_fpstatus_ptr(neon); \
1208 if (dp) { \
1209 gen_helper_vfp_##name##d##round(cpu_F0d, cpu_F0d, tmp_shift, \
1210 statusptr); \
1211 } else { \
1212 gen_helper_vfp_##name##s##round(cpu_F0s, cpu_F0s, tmp_shift, \
1213 statusptr); \
1215 tcg_temp_free_i32(tmp_shift); \
1216 tcg_temp_free_ptr(statusptr); \
1218 VFP_GEN_FIX(tosh, _round_to_zero)
1219 VFP_GEN_FIX(tosl, _round_to_zero)
1220 VFP_GEN_FIX(touh, _round_to_zero)
1221 VFP_GEN_FIX(toul, _round_to_zero)
1222 VFP_GEN_FIX(shto, )
1223 VFP_GEN_FIX(slto, )
1224 VFP_GEN_FIX(uhto, )
1225 VFP_GEN_FIX(ulto, )
1226 #undef VFP_GEN_FIX
1228 static inline void gen_vfp_ld(DisasContext *s, int dp, TCGv_i32 addr)
1230 if (dp) {
1231 gen_aa32_ld64(cpu_F0d, addr, get_mem_index(s));
1232 } else {
1233 gen_aa32_ld32u(cpu_F0s, addr, get_mem_index(s));
1237 static inline void gen_vfp_st(DisasContext *s, int dp, TCGv_i32 addr)
1239 if (dp) {
1240 gen_aa32_st64(cpu_F0d, addr, get_mem_index(s));
1241 } else {
1242 gen_aa32_st32(cpu_F0s, addr, get_mem_index(s));
1246 static inline long
1247 vfp_reg_offset (int dp, int reg)
1249 if (dp)
1250 return offsetof(CPUARMState, vfp.regs[reg]);
1251 else if (reg & 1) {
1252 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1253 + offsetof(CPU_DoubleU, l.upper);
1254 } else {
1255 return offsetof(CPUARMState, vfp.regs[reg >> 1])
1256 + offsetof(CPU_DoubleU, l.lower);
1260 /* Return the offset of a 32-bit piece of a NEON register.
1261 zero is the least significant end of the register. */
1262 static inline long
1263 neon_reg_offset (int reg, int n)
1265 int sreg;
1266 sreg = reg * 2 + n;
1267 return vfp_reg_offset(0, sreg);
1270 static TCGv_i32 neon_load_reg(int reg, int pass)
1272 TCGv_i32 tmp = tcg_temp_new_i32();
1273 tcg_gen_ld_i32(tmp, cpu_env, neon_reg_offset(reg, pass));
1274 return tmp;
1277 static void neon_store_reg(int reg, int pass, TCGv_i32 var)
1279 tcg_gen_st_i32(var, cpu_env, neon_reg_offset(reg, pass));
1280 tcg_temp_free_i32(var);
1283 static inline void neon_load_reg64(TCGv_i64 var, int reg)
1285 tcg_gen_ld_i64(var, cpu_env, vfp_reg_offset(1, reg));
1288 static inline void neon_store_reg64(TCGv_i64 var, int reg)
1290 tcg_gen_st_i64(var, cpu_env, vfp_reg_offset(1, reg));
1293 #define tcg_gen_ld_f32 tcg_gen_ld_i32
1294 #define tcg_gen_ld_f64 tcg_gen_ld_i64
1295 #define tcg_gen_st_f32 tcg_gen_st_i32
1296 #define tcg_gen_st_f64 tcg_gen_st_i64
1298 static inline void gen_mov_F0_vreg(int dp, int reg)
1300 if (dp)
1301 tcg_gen_ld_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1302 else
1303 tcg_gen_ld_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1306 static inline void gen_mov_F1_vreg(int dp, int reg)
1308 if (dp)
1309 tcg_gen_ld_f64(cpu_F1d, cpu_env, vfp_reg_offset(dp, reg));
1310 else
1311 tcg_gen_ld_f32(cpu_F1s, cpu_env, vfp_reg_offset(dp, reg));
1314 static inline void gen_mov_vreg_F0(int dp, int reg)
1316 if (dp)
1317 tcg_gen_st_f64(cpu_F0d, cpu_env, vfp_reg_offset(dp, reg));
1318 else
1319 tcg_gen_st_f32(cpu_F0s, cpu_env, vfp_reg_offset(dp, reg));
1322 #define ARM_CP_RW_BIT (1 << 20)
1324 static inline void iwmmxt_load_reg(TCGv_i64 var, int reg)
1326 tcg_gen_ld_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1329 static inline void iwmmxt_store_reg(TCGv_i64 var, int reg)
1331 tcg_gen_st_i64(var, cpu_env, offsetof(CPUARMState, iwmmxt.regs[reg]));
1334 static inline TCGv_i32 iwmmxt_load_creg(int reg)
1336 TCGv_i32 var = tcg_temp_new_i32();
1337 tcg_gen_ld_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1338 return var;
1341 static inline void iwmmxt_store_creg(int reg, TCGv_i32 var)
1343 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, iwmmxt.cregs[reg]));
1344 tcg_temp_free_i32(var);
1347 static inline void gen_op_iwmmxt_movq_wRn_M0(int rn)
1349 iwmmxt_store_reg(cpu_M0, rn);
1352 static inline void gen_op_iwmmxt_movq_M0_wRn(int rn)
1354 iwmmxt_load_reg(cpu_M0, rn);
1357 static inline void gen_op_iwmmxt_orq_M0_wRn(int rn)
1359 iwmmxt_load_reg(cpu_V1, rn);
1360 tcg_gen_or_i64(cpu_M0, cpu_M0, cpu_V1);
1363 static inline void gen_op_iwmmxt_andq_M0_wRn(int rn)
1365 iwmmxt_load_reg(cpu_V1, rn);
1366 tcg_gen_and_i64(cpu_M0, cpu_M0, cpu_V1);
1369 static inline void gen_op_iwmmxt_xorq_M0_wRn(int rn)
1371 iwmmxt_load_reg(cpu_V1, rn);
1372 tcg_gen_xor_i64(cpu_M0, cpu_M0, cpu_V1);
1375 #define IWMMXT_OP(name) \
1376 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1378 iwmmxt_load_reg(cpu_V1, rn); \
1379 gen_helper_iwmmxt_##name(cpu_M0, cpu_M0, cpu_V1); \
1382 #define IWMMXT_OP_ENV(name) \
1383 static inline void gen_op_iwmmxt_##name##_M0_wRn(int rn) \
1385 iwmmxt_load_reg(cpu_V1, rn); \
1386 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0, cpu_V1); \
1389 #define IWMMXT_OP_ENV_SIZE(name) \
1390 IWMMXT_OP_ENV(name##b) \
1391 IWMMXT_OP_ENV(name##w) \
1392 IWMMXT_OP_ENV(name##l)
1394 #define IWMMXT_OP_ENV1(name) \
1395 static inline void gen_op_iwmmxt_##name##_M0(void) \
1397 gen_helper_iwmmxt_##name(cpu_M0, cpu_env, cpu_M0); \
1400 IWMMXT_OP(maddsq)
1401 IWMMXT_OP(madduq)
1402 IWMMXT_OP(sadb)
1403 IWMMXT_OP(sadw)
1404 IWMMXT_OP(mulslw)
1405 IWMMXT_OP(mulshw)
1406 IWMMXT_OP(mululw)
1407 IWMMXT_OP(muluhw)
1408 IWMMXT_OP(macsw)
1409 IWMMXT_OP(macuw)
1411 IWMMXT_OP_ENV_SIZE(unpackl)
1412 IWMMXT_OP_ENV_SIZE(unpackh)
1414 IWMMXT_OP_ENV1(unpacklub)
1415 IWMMXT_OP_ENV1(unpackluw)
1416 IWMMXT_OP_ENV1(unpacklul)
1417 IWMMXT_OP_ENV1(unpackhub)
1418 IWMMXT_OP_ENV1(unpackhuw)
1419 IWMMXT_OP_ENV1(unpackhul)
1420 IWMMXT_OP_ENV1(unpacklsb)
1421 IWMMXT_OP_ENV1(unpacklsw)
1422 IWMMXT_OP_ENV1(unpacklsl)
1423 IWMMXT_OP_ENV1(unpackhsb)
1424 IWMMXT_OP_ENV1(unpackhsw)
1425 IWMMXT_OP_ENV1(unpackhsl)
1427 IWMMXT_OP_ENV_SIZE(cmpeq)
1428 IWMMXT_OP_ENV_SIZE(cmpgtu)
1429 IWMMXT_OP_ENV_SIZE(cmpgts)
1431 IWMMXT_OP_ENV_SIZE(mins)
1432 IWMMXT_OP_ENV_SIZE(minu)
1433 IWMMXT_OP_ENV_SIZE(maxs)
1434 IWMMXT_OP_ENV_SIZE(maxu)
1436 IWMMXT_OP_ENV_SIZE(subn)
1437 IWMMXT_OP_ENV_SIZE(addn)
1438 IWMMXT_OP_ENV_SIZE(subu)
1439 IWMMXT_OP_ENV_SIZE(addu)
1440 IWMMXT_OP_ENV_SIZE(subs)
1441 IWMMXT_OP_ENV_SIZE(adds)
1443 IWMMXT_OP_ENV(avgb0)
1444 IWMMXT_OP_ENV(avgb1)
1445 IWMMXT_OP_ENV(avgw0)
1446 IWMMXT_OP_ENV(avgw1)
1448 IWMMXT_OP_ENV(packuw)
1449 IWMMXT_OP_ENV(packul)
1450 IWMMXT_OP_ENV(packuq)
1451 IWMMXT_OP_ENV(packsw)
1452 IWMMXT_OP_ENV(packsl)
1453 IWMMXT_OP_ENV(packsq)
1455 static void gen_op_iwmmxt_set_mup(void)
1457 TCGv_i32 tmp;
1458 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1459 tcg_gen_ori_i32(tmp, tmp, 2);
1460 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1463 static void gen_op_iwmmxt_set_cup(void)
1465 TCGv_i32 tmp;
1466 tmp = load_cpu_field(iwmmxt.cregs[ARM_IWMMXT_wCon]);
1467 tcg_gen_ori_i32(tmp, tmp, 1);
1468 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCon]);
1471 static void gen_op_iwmmxt_setpsr_nz(void)
1473 TCGv_i32 tmp = tcg_temp_new_i32();
1474 gen_helper_iwmmxt_setpsr_nz(tmp, cpu_M0);
1475 store_cpu_field(tmp, iwmmxt.cregs[ARM_IWMMXT_wCASF]);
1478 static inline void gen_op_iwmmxt_addl_M0_wRn(int rn)
1480 iwmmxt_load_reg(cpu_V1, rn);
1481 tcg_gen_ext32u_i64(cpu_V1, cpu_V1);
1482 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1485 static inline int gen_iwmmxt_address(DisasContext *s, uint32_t insn,
1486 TCGv_i32 dest)
1488 int rd;
1489 uint32_t offset;
1490 TCGv_i32 tmp;
1492 rd = (insn >> 16) & 0xf;
1493 tmp = load_reg(s, rd);
1495 offset = (insn & 0xff) << ((insn >> 7) & 2);
1496 if (insn & (1 << 24)) {
1497 /* Pre indexed */
1498 if (insn & (1 << 23))
1499 tcg_gen_addi_i32(tmp, tmp, offset);
1500 else
1501 tcg_gen_addi_i32(tmp, tmp, -offset);
1502 tcg_gen_mov_i32(dest, tmp);
1503 if (insn & (1 << 21))
1504 store_reg(s, rd, tmp);
1505 else
1506 tcg_temp_free_i32(tmp);
1507 } else if (insn & (1 << 21)) {
1508 /* Post indexed */
1509 tcg_gen_mov_i32(dest, tmp);
1510 if (insn & (1 << 23))
1511 tcg_gen_addi_i32(tmp, tmp, offset);
1512 else
1513 tcg_gen_addi_i32(tmp, tmp, -offset);
1514 store_reg(s, rd, tmp);
1515 } else if (!(insn & (1 << 23)))
1516 return 1;
1517 return 0;
1520 static inline int gen_iwmmxt_shift(uint32_t insn, uint32_t mask, TCGv_i32 dest)
1522 int rd = (insn >> 0) & 0xf;
1523 TCGv_i32 tmp;
1525 if (insn & (1 << 8)) {
1526 if (rd < ARM_IWMMXT_wCGR0 || rd > ARM_IWMMXT_wCGR3) {
1527 return 1;
1528 } else {
1529 tmp = iwmmxt_load_creg(rd);
1531 } else {
1532 tmp = tcg_temp_new_i32();
1533 iwmmxt_load_reg(cpu_V0, rd);
1534 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
1536 tcg_gen_andi_i32(tmp, tmp, mask);
1537 tcg_gen_mov_i32(dest, tmp);
1538 tcg_temp_free_i32(tmp);
1539 return 0;
1542 /* Disassemble an iwMMXt instruction. Returns nonzero if an error occurred
1543 (ie. an undefined instruction). */
1544 static int disas_iwmmxt_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
1546 int rd, wrd;
1547 int rdhi, rdlo, rd0, rd1, i;
1548 TCGv_i32 addr;
1549 TCGv_i32 tmp, tmp2, tmp3;
1551 if ((insn & 0x0e000e00) == 0x0c000000) {
1552 if ((insn & 0x0fe00ff0) == 0x0c400000) {
1553 wrd = insn & 0xf;
1554 rdlo = (insn >> 12) & 0xf;
1555 rdhi = (insn >> 16) & 0xf;
1556 if (insn & ARM_CP_RW_BIT) { /* TMRRC */
1557 iwmmxt_load_reg(cpu_V0, wrd);
1558 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
1559 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
1560 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
1561 } else { /* TMCRR */
1562 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
1563 iwmmxt_store_reg(cpu_V0, wrd);
1564 gen_op_iwmmxt_set_mup();
1566 return 0;
1569 wrd = (insn >> 12) & 0xf;
1570 addr = tcg_temp_new_i32();
1571 if (gen_iwmmxt_address(s, insn, addr)) {
1572 tcg_temp_free_i32(addr);
1573 return 1;
1575 if (insn & ARM_CP_RW_BIT) {
1576 if ((insn >> 28) == 0xf) { /* WLDRW wCx */
1577 tmp = tcg_temp_new_i32();
1578 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
1579 iwmmxt_store_creg(wrd, tmp);
1580 } else {
1581 i = 1;
1582 if (insn & (1 << 8)) {
1583 if (insn & (1 << 22)) { /* WLDRD */
1584 gen_aa32_ld64(cpu_M0, addr, get_mem_index(s));
1585 i = 0;
1586 } else { /* WLDRW wRd */
1587 tmp = tcg_temp_new_i32();
1588 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
1590 } else {
1591 tmp = tcg_temp_new_i32();
1592 if (insn & (1 << 22)) { /* WLDRH */
1593 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
1594 } else { /* WLDRB */
1595 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
1598 if (i) {
1599 tcg_gen_extu_i32_i64(cpu_M0, tmp);
1600 tcg_temp_free_i32(tmp);
1602 gen_op_iwmmxt_movq_wRn_M0(wrd);
1604 } else {
1605 if ((insn >> 28) == 0xf) { /* WSTRW wCx */
1606 tmp = iwmmxt_load_creg(wrd);
1607 gen_aa32_st32(tmp, addr, get_mem_index(s));
1608 } else {
1609 gen_op_iwmmxt_movq_M0_wRn(wrd);
1610 tmp = tcg_temp_new_i32();
1611 if (insn & (1 << 8)) {
1612 if (insn & (1 << 22)) { /* WSTRD */
1613 gen_aa32_st64(cpu_M0, addr, get_mem_index(s));
1614 } else { /* WSTRW wRd */
1615 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1616 gen_aa32_st32(tmp, addr, get_mem_index(s));
1618 } else {
1619 if (insn & (1 << 22)) { /* WSTRH */
1620 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1621 gen_aa32_st16(tmp, addr, get_mem_index(s));
1622 } else { /* WSTRB */
1623 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1624 gen_aa32_st8(tmp, addr, get_mem_index(s));
1628 tcg_temp_free_i32(tmp);
1630 tcg_temp_free_i32(addr);
1631 return 0;
1634 if ((insn & 0x0f000000) != 0x0e000000)
1635 return 1;
1637 switch (((insn >> 12) & 0xf00) | ((insn >> 4) & 0xff)) {
1638 case 0x000: /* WOR */
1639 wrd = (insn >> 12) & 0xf;
1640 rd0 = (insn >> 0) & 0xf;
1641 rd1 = (insn >> 16) & 0xf;
1642 gen_op_iwmmxt_movq_M0_wRn(rd0);
1643 gen_op_iwmmxt_orq_M0_wRn(rd1);
1644 gen_op_iwmmxt_setpsr_nz();
1645 gen_op_iwmmxt_movq_wRn_M0(wrd);
1646 gen_op_iwmmxt_set_mup();
1647 gen_op_iwmmxt_set_cup();
1648 break;
1649 case 0x011: /* TMCR */
1650 if (insn & 0xf)
1651 return 1;
1652 rd = (insn >> 12) & 0xf;
1653 wrd = (insn >> 16) & 0xf;
1654 switch (wrd) {
1655 case ARM_IWMMXT_wCID:
1656 case ARM_IWMMXT_wCASF:
1657 break;
1658 case ARM_IWMMXT_wCon:
1659 gen_op_iwmmxt_set_cup();
1660 /* Fall through. */
1661 case ARM_IWMMXT_wCSSF:
1662 tmp = iwmmxt_load_creg(wrd);
1663 tmp2 = load_reg(s, rd);
1664 tcg_gen_andc_i32(tmp, tmp, tmp2);
1665 tcg_temp_free_i32(tmp2);
1666 iwmmxt_store_creg(wrd, tmp);
1667 break;
1668 case ARM_IWMMXT_wCGR0:
1669 case ARM_IWMMXT_wCGR1:
1670 case ARM_IWMMXT_wCGR2:
1671 case ARM_IWMMXT_wCGR3:
1672 gen_op_iwmmxt_set_cup();
1673 tmp = load_reg(s, rd);
1674 iwmmxt_store_creg(wrd, tmp);
1675 break;
1676 default:
1677 return 1;
1679 break;
1680 case 0x100: /* WXOR */
1681 wrd = (insn >> 12) & 0xf;
1682 rd0 = (insn >> 0) & 0xf;
1683 rd1 = (insn >> 16) & 0xf;
1684 gen_op_iwmmxt_movq_M0_wRn(rd0);
1685 gen_op_iwmmxt_xorq_M0_wRn(rd1);
1686 gen_op_iwmmxt_setpsr_nz();
1687 gen_op_iwmmxt_movq_wRn_M0(wrd);
1688 gen_op_iwmmxt_set_mup();
1689 gen_op_iwmmxt_set_cup();
1690 break;
1691 case 0x111: /* TMRC */
1692 if (insn & 0xf)
1693 return 1;
1694 rd = (insn >> 12) & 0xf;
1695 wrd = (insn >> 16) & 0xf;
1696 tmp = iwmmxt_load_creg(wrd);
1697 store_reg(s, rd, tmp);
1698 break;
1699 case 0x300: /* WANDN */
1700 wrd = (insn >> 12) & 0xf;
1701 rd0 = (insn >> 0) & 0xf;
1702 rd1 = (insn >> 16) & 0xf;
1703 gen_op_iwmmxt_movq_M0_wRn(rd0);
1704 tcg_gen_neg_i64(cpu_M0, cpu_M0);
1705 gen_op_iwmmxt_andq_M0_wRn(rd1);
1706 gen_op_iwmmxt_setpsr_nz();
1707 gen_op_iwmmxt_movq_wRn_M0(wrd);
1708 gen_op_iwmmxt_set_mup();
1709 gen_op_iwmmxt_set_cup();
1710 break;
1711 case 0x200: /* WAND */
1712 wrd = (insn >> 12) & 0xf;
1713 rd0 = (insn >> 0) & 0xf;
1714 rd1 = (insn >> 16) & 0xf;
1715 gen_op_iwmmxt_movq_M0_wRn(rd0);
1716 gen_op_iwmmxt_andq_M0_wRn(rd1);
1717 gen_op_iwmmxt_setpsr_nz();
1718 gen_op_iwmmxt_movq_wRn_M0(wrd);
1719 gen_op_iwmmxt_set_mup();
1720 gen_op_iwmmxt_set_cup();
1721 break;
1722 case 0x810: case 0xa10: /* WMADD */
1723 wrd = (insn >> 12) & 0xf;
1724 rd0 = (insn >> 0) & 0xf;
1725 rd1 = (insn >> 16) & 0xf;
1726 gen_op_iwmmxt_movq_M0_wRn(rd0);
1727 if (insn & (1 << 21))
1728 gen_op_iwmmxt_maddsq_M0_wRn(rd1);
1729 else
1730 gen_op_iwmmxt_madduq_M0_wRn(rd1);
1731 gen_op_iwmmxt_movq_wRn_M0(wrd);
1732 gen_op_iwmmxt_set_mup();
1733 break;
1734 case 0x10e: case 0x50e: case 0x90e: case 0xd0e: /* WUNPCKIL */
1735 wrd = (insn >> 12) & 0xf;
1736 rd0 = (insn >> 16) & 0xf;
1737 rd1 = (insn >> 0) & 0xf;
1738 gen_op_iwmmxt_movq_M0_wRn(rd0);
1739 switch ((insn >> 22) & 3) {
1740 case 0:
1741 gen_op_iwmmxt_unpacklb_M0_wRn(rd1);
1742 break;
1743 case 1:
1744 gen_op_iwmmxt_unpacklw_M0_wRn(rd1);
1745 break;
1746 case 2:
1747 gen_op_iwmmxt_unpackll_M0_wRn(rd1);
1748 break;
1749 case 3:
1750 return 1;
1752 gen_op_iwmmxt_movq_wRn_M0(wrd);
1753 gen_op_iwmmxt_set_mup();
1754 gen_op_iwmmxt_set_cup();
1755 break;
1756 case 0x10c: case 0x50c: case 0x90c: case 0xd0c: /* WUNPCKIH */
1757 wrd = (insn >> 12) & 0xf;
1758 rd0 = (insn >> 16) & 0xf;
1759 rd1 = (insn >> 0) & 0xf;
1760 gen_op_iwmmxt_movq_M0_wRn(rd0);
1761 switch ((insn >> 22) & 3) {
1762 case 0:
1763 gen_op_iwmmxt_unpackhb_M0_wRn(rd1);
1764 break;
1765 case 1:
1766 gen_op_iwmmxt_unpackhw_M0_wRn(rd1);
1767 break;
1768 case 2:
1769 gen_op_iwmmxt_unpackhl_M0_wRn(rd1);
1770 break;
1771 case 3:
1772 return 1;
1774 gen_op_iwmmxt_movq_wRn_M0(wrd);
1775 gen_op_iwmmxt_set_mup();
1776 gen_op_iwmmxt_set_cup();
1777 break;
1778 case 0x012: case 0x112: case 0x412: case 0x512: /* WSAD */
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 << 22))
1784 gen_op_iwmmxt_sadw_M0_wRn(rd1);
1785 else
1786 gen_op_iwmmxt_sadb_M0_wRn(rd1);
1787 if (!(insn & (1 << 20)))
1788 gen_op_iwmmxt_addl_M0_wRn(wrd);
1789 gen_op_iwmmxt_movq_wRn_M0(wrd);
1790 gen_op_iwmmxt_set_mup();
1791 break;
1792 case 0x010: case 0x110: case 0x210: case 0x310: /* WMUL */
1793 wrd = (insn >> 12) & 0xf;
1794 rd0 = (insn >> 16) & 0xf;
1795 rd1 = (insn >> 0) & 0xf;
1796 gen_op_iwmmxt_movq_M0_wRn(rd0);
1797 if (insn & (1 << 21)) {
1798 if (insn & (1 << 20))
1799 gen_op_iwmmxt_mulshw_M0_wRn(rd1);
1800 else
1801 gen_op_iwmmxt_mulslw_M0_wRn(rd1);
1802 } else {
1803 if (insn & (1 << 20))
1804 gen_op_iwmmxt_muluhw_M0_wRn(rd1);
1805 else
1806 gen_op_iwmmxt_mululw_M0_wRn(rd1);
1808 gen_op_iwmmxt_movq_wRn_M0(wrd);
1809 gen_op_iwmmxt_set_mup();
1810 break;
1811 case 0x410: case 0x510: case 0x610: case 0x710: /* WMAC */
1812 wrd = (insn >> 12) & 0xf;
1813 rd0 = (insn >> 16) & 0xf;
1814 rd1 = (insn >> 0) & 0xf;
1815 gen_op_iwmmxt_movq_M0_wRn(rd0);
1816 if (insn & (1 << 21))
1817 gen_op_iwmmxt_macsw_M0_wRn(rd1);
1818 else
1819 gen_op_iwmmxt_macuw_M0_wRn(rd1);
1820 if (!(insn & (1 << 20))) {
1821 iwmmxt_load_reg(cpu_V1, wrd);
1822 tcg_gen_add_i64(cpu_M0, cpu_M0, cpu_V1);
1824 gen_op_iwmmxt_movq_wRn_M0(wrd);
1825 gen_op_iwmmxt_set_mup();
1826 break;
1827 case 0x006: case 0x406: case 0x806: case 0xc06: /* WCMPEQ */
1828 wrd = (insn >> 12) & 0xf;
1829 rd0 = (insn >> 16) & 0xf;
1830 rd1 = (insn >> 0) & 0xf;
1831 gen_op_iwmmxt_movq_M0_wRn(rd0);
1832 switch ((insn >> 22) & 3) {
1833 case 0:
1834 gen_op_iwmmxt_cmpeqb_M0_wRn(rd1);
1835 break;
1836 case 1:
1837 gen_op_iwmmxt_cmpeqw_M0_wRn(rd1);
1838 break;
1839 case 2:
1840 gen_op_iwmmxt_cmpeql_M0_wRn(rd1);
1841 break;
1842 case 3:
1843 return 1;
1845 gen_op_iwmmxt_movq_wRn_M0(wrd);
1846 gen_op_iwmmxt_set_mup();
1847 gen_op_iwmmxt_set_cup();
1848 break;
1849 case 0x800: case 0x900: case 0xc00: case 0xd00: /* WAVG2 */
1850 wrd = (insn >> 12) & 0xf;
1851 rd0 = (insn >> 16) & 0xf;
1852 rd1 = (insn >> 0) & 0xf;
1853 gen_op_iwmmxt_movq_M0_wRn(rd0);
1854 if (insn & (1 << 22)) {
1855 if (insn & (1 << 20))
1856 gen_op_iwmmxt_avgw1_M0_wRn(rd1);
1857 else
1858 gen_op_iwmmxt_avgw0_M0_wRn(rd1);
1859 } else {
1860 if (insn & (1 << 20))
1861 gen_op_iwmmxt_avgb1_M0_wRn(rd1);
1862 else
1863 gen_op_iwmmxt_avgb0_M0_wRn(rd1);
1865 gen_op_iwmmxt_movq_wRn_M0(wrd);
1866 gen_op_iwmmxt_set_mup();
1867 gen_op_iwmmxt_set_cup();
1868 break;
1869 case 0x802: case 0x902: case 0xa02: case 0xb02: /* WALIGNR */
1870 wrd = (insn >> 12) & 0xf;
1871 rd0 = (insn >> 16) & 0xf;
1872 rd1 = (insn >> 0) & 0xf;
1873 gen_op_iwmmxt_movq_M0_wRn(rd0);
1874 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCGR0 + ((insn >> 20) & 3));
1875 tcg_gen_andi_i32(tmp, tmp, 7);
1876 iwmmxt_load_reg(cpu_V1, rd1);
1877 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
1878 tcg_temp_free_i32(tmp);
1879 gen_op_iwmmxt_movq_wRn_M0(wrd);
1880 gen_op_iwmmxt_set_mup();
1881 break;
1882 case 0x601: case 0x605: case 0x609: case 0x60d: /* TINSR */
1883 if (((insn >> 6) & 3) == 3)
1884 return 1;
1885 rd = (insn >> 12) & 0xf;
1886 wrd = (insn >> 16) & 0xf;
1887 tmp = load_reg(s, rd);
1888 gen_op_iwmmxt_movq_M0_wRn(wrd);
1889 switch ((insn >> 6) & 3) {
1890 case 0:
1891 tmp2 = tcg_const_i32(0xff);
1892 tmp3 = tcg_const_i32((insn & 7) << 3);
1893 break;
1894 case 1:
1895 tmp2 = tcg_const_i32(0xffff);
1896 tmp3 = tcg_const_i32((insn & 3) << 4);
1897 break;
1898 case 2:
1899 tmp2 = tcg_const_i32(0xffffffff);
1900 tmp3 = tcg_const_i32((insn & 1) << 5);
1901 break;
1902 default:
1903 TCGV_UNUSED_I32(tmp2);
1904 TCGV_UNUSED_I32(tmp3);
1906 gen_helper_iwmmxt_insr(cpu_M0, cpu_M0, tmp, tmp2, tmp3);
1907 tcg_temp_free_i32(tmp3);
1908 tcg_temp_free_i32(tmp2);
1909 tcg_temp_free_i32(tmp);
1910 gen_op_iwmmxt_movq_wRn_M0(wrd);
1911 gen_op_iwmmxt_set_mup();
1912 break;
1913 case 0x107: case 0x507: case 0x907: case 0xd07: /* TEXTRM */
1914 rd = (insn >> 12) & 0xf;
1915 wrd = (insn >> 16) & 0xf;
1916 if (rd == 15 || ((insn >> 22) & 3) == 3)
1917 return 1;
1918 gen_op_iwmmxt_movq_M0_wRn(wrd);
1919 tmp = tcg_temp_new_i32();
1920 switch ((insn >> 22) & 3) {
1921 case 0:
1922 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 7) << 3);
1923 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1924 if (insn & 8) {
1925 tcg_gen_ext8s_i32(tmp, tmp);
1926 } else {
1927 tcg_gen_andi_i32(tmp, tmp, 0xff);
1929 break;
1930 case 1:
1931 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 3) << 4);
1932 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1933 if (insn & 8) {
1934 tcg_gen_ext16s_i32(tmp, tmp);
1935 } else {
1936 tcg_gen_andi_i32(tmp, tmp, 0xffff);
1938 break;
1939 case 2:
1940 tcg_gen_shri_i64(cpu_M0, cpu_M0, (insn & 1) << 5);
1941 tcg_gen_trunc_i64_i32(tmp, cpu_M0);
1942 break;
1944 store_reg(s, rd, tmp);
1945 break;
1946 case 0x117: case 0x517: case 0x917: case 0xd17: /* TEXTRC */
1947 if ((insn & 0x000ff008) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1948 return 1;
1949 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1950 switch ((insn >> 22) & 3) {
1951 case 0:
1952 tcg_gen_shri_i32(tmp, tmp, ((insn & 7) << 2) + 0);
1953 break;
1954 case 1:
1955 tcg_gen_shri_i32(tmp, tmp, ((insn & 3) << 3) + 4);
1956 break;
1957 case 2:
1958 tcg_gen_shri_i32(tmp, tmp, ((insn & 1) << 4) + 12);
1959 break;
1961 tcg_gen_shli_i32(tmp, tmp, 28);
1962 gen_set_nzcv(tmp);
1963 tcg_temp_free_i32(tmp);
1964 break;
1965 case 0x401: case 0x405: case 0x409: case 0x40d: /* TBCST */
1966 if (((insn >> 6) & 3) == 3)
1967 return 1;
1968 rd = (insn >> 12) & 0xf;
1969 wrd = (insn >> 16) & 0xf;
1970 tmp = load_reg(s, rd);
1971 switch ((insn >> 6) & 3) {
1972 case 0:
1973 gen_helper_iwmmxt_bcstb(cpu_M0, tmp);
1974 break;
1975 case 1:
1976 gen_helper_iwmmxt_bcstw(cpu_M0, tmp);
1977 break;
1978 case 2:
1979 gen_helper_iwmmxt_bcstl(cpu_M0, tmp);
1980 break;
1982 tcg_temp_free_i32(tmp);
1983 gen_op_iwmmxt_movq_wRn_M0(wrd);
1984 gen_op_iwmmxt_set_mup();
1985 break;
1986 case 0x113: case 0x513: case 0x913: case 0xd13: /* TANDC */
1987 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
1988 return 1;
1989 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
1990 tmp2 = tcg_temp_new_i32();
1991 tcg_gen_mov_i32(tmp2, tmp);
1992 switch ((insn >> 22) & 3) {
1993 case 0:
1994 for (i = 0; i < 7; i ++) {
1995 tcg_gen_shli_i32(tmp2, tmp2, 4);
1996 tcg_gen_and_i32(tmp, tmp, tmp2);
1998 break;
1999 case 1:
2000 for (i = 0; i < 3; i ++) {
2001 tcg_gen_shli_i32(tmp2, tmp2, 8);
2002 tcg_gen_and_i32(tmp, tmp, tmp2);
2004 break;
2005 case 2:
2006 tcg_gen_shli_i32(tmp2, tmp2, 16);
2007 tcg_gen_and_i32(tmp, tmp, tmp2);
2008 break;
2010 gen_set_nzcv(tmp);
2011 tcg_temp_free_i32(tmp2);
2012 tcg_temp_free_i32(tmp);
2013 break;
2014 case 0x01c: case 0x41c: case 0x81c: case 0xc1c: /* WACC */
2015 wrd = (insn >> 12) & 0xf;
2016 rd0 = (insn >> 16) & 0xf;
2017 gen_op_iwmmxt_movq_M0_wRn(rd0);
2018 switch ((insn >> 22) & 3) {
2019 case 0:
2020 gen_helper_iwmmxt_addcb(cpu_M0, cpu_M0);
2021 break;
2022 case 1:
2023 gen_helper_iwmmxt_addcw(cpu_M0, cpu_M0);
2024 break;
2025 case 2:
2026 gen_helper_iwmmxt_addcl(cpu_M0, cpu_M0);
2027 break;
2028 case 3:
2029 return 1;
2031 gen_op_iwmmxt_movq_wRn_M0(wrd);
2032 gen_op_iwmmxt_set_mup();
2033 break;
2034 case 0x115: case 0x515: case 0x915: case 0xd15: /* TORC */
2035 if ((insn & 0x000ff00f) != 0x0003f000 || ((insn >> 22) & 3) == 3)
2036 return 1;
2037 tmp = iwmmxt_load_creg(ARM_IWMMXT_wCASF);
2038 tmp2 = tcg_temp_new_i32();
2039 tcg_gen_mov_i32(tmp2, tmp);
2040 switch ((insn >> 22) & 3) {
2041 case 0:
2042 for (i = 0; i < 7; i ++) {
2043 tcg_gen_shli_i32(tmp2, tmp2, 4);
2044 tcg_gen_or_i32(tmp, tmp, tmp2);
2046 break;
2047 case 1:
2048 for (i = 0; i < 3; i ++) {
2049 tcg_gen_shli_i32(tmp2, tmp2, 8);
2050 tcg_gen_or_i32(tmp, tmp, tmp2);
2052 break;
2053 case 2:
2054 tcg_gen_shli_i32(tmp2, tmp2, 16);
2055 tcg_gen_or_i32(tmp, tmp, tmp2);
2056 break;
2058 gen_set_nzcv(tmp);
2059 tcg_temp_free_i32(tmp2);
2060 tcg_temp_free_i32(tmp);
2061 break;
2062 case 0x103: case 0x503: case 0x903: case 0xd03: /* TMOVMSK */
2063 rd = (insn >> 12) & 0xf;
2064 rd0 = (insn >> 16) & 0xf;
2065 if ((insn & 0xf) != 0 || ((insn >> 22) & 3) == 3)
2066 return 1;
2067 gen_op_iwmmxt_movq_M0_wRn(rd0);
2068 tmp = tcg_temp_new_i32();
2069 switch ((insn >> 22) & 3) {
2070 case 0:
2071 gen_helper_iwmmxt_msbb(tmp, cpu_M0);
2072 break;
2073 case 1:
2074 gen_helper_iwmmxt_msbw(tmp, cpu_M0);
2075 break;
2076 case 2:
2077 gen_helper_iwmmxt_msbl(tmp, cpu_M0);
2078 break;
2080 store_reg(s, rd, tmp);
2081 break;
2082 case 0x106: case 0x306: case 0x506: case 0x706: /* WCMPGT */
2083 case 0x906: case 0xb06: case 0xd06: case 0xf06:
2084 wrd = (insn >> 12) & 0xf;
2085 rd0 = (insn >> 16) & 0xf;
2086 rd1 = (insn >> 0) & 0xf;
2087 gen_op_iwmmxt_movq_M0_wRn(rd0);
2088 switch ((insn >> 22) & 3) {
2089 case 0:
2090 if (insn & (1 << 21))
2091 gen_op_iwmmxt_cmpgtsb_M0_wRn(rd1);
2092 else
2093 gen_op_iwmmxt_cmpgtub_M0_wRn(rd1);
2094 break;
2095 case 1:
2096 if (insn & (1 << 21))
2097 gen_op_iwmmxt_cmpgtsw_M0_wRn(rd1);
2098 else
2099 gen_op_iwmmxt_cmpgtuw_M0_wRn(rd1);
2100 break;
2101 case 2:
2102 if (insn & (1 << 21))
2103 gen_op_iwmmxt_cmpgtsl_M0_wRn(rd1);
2104 else
2105 gen_op_iwmmxt_cmpgtul_M0_wRn(rd1);
2106 break;
2107 case 3:
2108 return 1;
2110 gen_op_iwmmxt_movq_wRn_M0(wrd);
2111 gen_op_iwmmxt_set_mup();
2112 gen_op_iwmmxt_set_cup();
2113 break;
2114 case 0x00e: case 0x20e: case 0x40e: case 0x60e: /* WUNPCKEL */
2115 case 0x80e: case 0xa0e: case 0xc0e: case 0xe0e:
2116 wrd = (insn >> 12) & 0xf;
2117 rd0 = (insn >> 16) & 0xf;
2118 gen_op_iwmmxt_movq_M0_wRn(rd0);
2119 switch ((insn >> 22) & 3) {
2120 case 0:
2121 if (insn & (1 << 21))
2122 gen_op_iwmmxt_unpacklsb_M0();
2123 else
2124 gen_op_iwmmxt_unpacklub_M0();
2125 break;
2126 case 1:
2127 if (insn & (1 << 21))
2128 gen_op_iwmmxt_unpacklsw_M0();
2129 else
2130 gen_op_iwmmxt_unpackluw_M0();
2131 break;
2132 case 2:
2133 if (insn & (1 << 21))
2134 gen_op_iwmmxt_unpacklsl_M0();
2135 else
2136 gen_op_iwmmxt_unpacklul_M0();
2137 break;
2138 case 3:
2139 return 1;
2141 gen_op_iwmmxt_movq_wRn_M0(wrd);
2142 gen_op_iwmmxt_set_mup();
2143 gen_op_iwmmxt_set_cup();
2144 break;
2145 case 0x00c: case 0x20c: case 0x40c: case 0x60c: /* WUNPCKEH */
2146 case 0x80c: case 0xa0c: case 0xc0c: case 0xe0c:
2147 wrd = (insn >> 12) & 0xf;
2148 rd0 = (insn >> 16) & 0xf;
2149 gen_op_iwmmxt_movq_M0_wRn(rd0);
2150 switch ((insn >> 22) & 3) {
2151 case 0:
2152 if (insn & (1 << 21))
2153 gen_op_iwmmxt_unpackhsb_M0();
2154 else
2155 gen_op_iwmmxt_unpackhub_M0();
2156 break;
2157 case 1:
2158 if (insn & (1 << 21))
2159 gen_op_iwmmxt_unpackhsw_M0();
2160 else
2161 gen_op_iwmmxt_unpackhuw_M0();
2162 break;
2163 case 2:
2164 if (insn & (1 << 21))
2165 gen_op_iwmmxt_unpackhsl_M0();
2166 else
2167 gen_op_iwmmxt_unpackhul_M0();
2168 break;
2169 case 3:
2170 return 1;
2172 gen_op_iwmmxt_movq_wRn_M0(wrd);
2173 gen_op_iwmmxt_set_mup();
2174 gen_op_iwmmxt_set_cup();
2175 break;
2176 case 0x204: case 0x604: case 0xa04: case 0xe04: /* WSRL */
2177 case 0x214: case 0x614: case 0xa14: case 0xe14:
2178 if (((insn >> 22) & 3) == 0)
2179 return 1;
2180 wrd = (insn >> 12) & 0xf;
2181 rd0 = (insn >> 16) & 0xf;
2182 gen_op_iwmmxt_movq_M0_wRn(rd0);
2183 tmp = tcg_temp_new_i32();
2184 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2185 tcg_temp_free_i32(tmp);
2186 return 1;
2188 switch ((insn >> 22) & 3) {
2189 case 1:
2190 gen_helper_iwmmxt_srlw(cpu_M0, cpu_env, cpu_M0, tmp);
2191 break;
2192 case 2:
2193 gen_helper_iwmmxt_srll(cpu_M0, cpu_env, cpu_M0, tmp);
2194 break;
2195 case 3:
2196 gen_helper_iwmmxt_srlq(cpu_M0, cpu_env, cpu_M0, tmp);
2197 break;
2199 tcg_temp_free_i32(tmp);
2200 gen_op_iwmmxt_movq_wRn_M0(wrd);
2201 gen_op_iwmmxt_set_mup();
2202 gen_op_iwmmxt_set_cup();
2203 break;
2204 case 0x004: case 0x404: case 0x804: case 0xc04: /* WSRA */
2205 case 0x014: case 0x414: case 0x814: case 0xc14:
2206 if (((insn >> 22) & 3) == 0)
2207 return 1;
2208 wrd = (insn >> 12) & 0xf;
2209 rd0 = (insn >> 16) & 0xf;
2210 gen_op_iwmmxt_movq_M0_wRn(rd0);
2211 tmp = tcg_temp_new_i32();
2212 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2213 tcg_temp_free_i32(tmp);
2214 return 1;
2216 switch ((insn >> 22) & 3) {
2217 case 1:
2218 gen_helper_iwmmxt_sraw(cpu_M0, cpu_env, cpu_M0, tmp);
2219 break;
2220 case 2:
2221 gen_helper_iwmmxt_sral(cpu_M0, cpu_env, cpu_M0, tmp);
2222 break;
2223 case 3:
2224 gen_helper_iwmmxt_sraq(cpu_M0, cpu_env, cpu_M0, tmp);
2225 break;
2227 tcg_temp_free_i32(tmp);
2228 gen_op_iwmmxt_movq_wRn_M0(wrd);
2229 gen_op_iwmmxt_set_mup();
2230 gen_op_iwmmxt_set_cup();
2231 break;
2232 case 0x104: case 0x504: case 0x904: case 0xd04: /* WSLL */
2233 case 0x114: case 0x514: case 0x914: case 0xd14:
2234 if (((insn >> 22) & 3) == 0)
2235 return 1;
2236 wrd = (insn >> 12) & 0xf;
2237 rd0 = (insn >> 16) & 0xf;
2238 gen_op_iwmmxt_movq_M0_wRn(rd0);
2239 tmp = tcg_temp_new_i32();
2240 if (gen_iwmmxt_shift(insn, 0xff, tmp)) {
2241 tcg_temp_free_i32(tmp);
2242 return 1;
2244 switch ((insn >> 22) & 3) {
2245 case 1:
2246 gen_helper_iwmmxt_sllw(cpu_M0, cpu_env, cpu_M0, tmp);
2247 break;
2248 case 2:
2249 gen_helper_iwmmxt_slll(cpu_M0, cpu_env, cpu_M0, tmp);
2250 break;
2251 case 3:
2252 gen_helper_iwmmxt_sllq(cpu_M0, cpu_env, cpu_M0, tmp);
2253 break;
2255 tcg_temp_free_i32(tmp);
2256 gen_op_iwmmxt_movq_wRn_M0(wrd);
2257 gen_op_iwmmxt_set_mup();
2258 gen_op_iwmmxt_set_cup();
2259 break;
2260 case 0x304: case 0x704: case 0xb04: case 0xf04: /* WROR */
2261 case 0x314: case 0x714: case 0xb14: case 0xf14:
2262 if (((insn >> 22) & 3) == 0)
2263 return 1;
2264 wrd = (insn >> 12) & 0xf;
2265 rd0 = (insn >> 16) & 0xf;
2266 gen_op_iwmmxt_movq_M0_wRn(rd0);
2267 tmp = tcg_temp_new_i32();
2268 switch ((insn >> 22) & 3) {
2269 case 1:
2270 if (gen_iwmmxt_shift(insn, 0xf, tmp)) {
2271 tcg_temp_free_i32(tmp);
2272 return 1;
2274 gen_helper_iwmmxt_rorw(cpu_M0, cpu_env, cpu_M0, tmp);
2275 break;
2276 case 2:
2277 if (gen_iwmmxt_shift(insn, 0x1f, tmp)) {
2278 tcg_temp_free_i32(tmp);
2279 return 1;
2281 gen_helper_iwmmxt_rorl(cpu_M0, cpu_env, cpu_M0, tmp);
2282 break;
2283 case 3:
2284 if (gen_iwmmxt_shift(insn, 0x3f, tmp)) {
2285 tcg_temp_free_i32(tmp);
2286 return 1;
2288 gen_helper_iwmmxt_rorq(cpu_M0, cpu_env, cpu_M0, tmp);
2289 break;
2291 tcg_temp_free_i32(tmp);
2292 gen_op_iwmmxt_movq_wRn_M0(wrd);
2293 gen_op_iwmmxt_set_mup();
2294 gen_op_iwmmxt_set_cup();
2295 break;
2296 case 0x116: case 0x316: case 0x516: case 0x716: /* WMIN */
2297 case 0x916: case 0xb16: case 0xd16: case 0xf16:
2298 wrd = (insn >> 12) & 0xf;
2299 rd0 = (insn >> 16) & 0xf;
2300 rd1 = (insn >> 0) & 0xf;
2301 gen_op_iwmmxt_movq_M0_wRn(rd0);
2302 switch ((insn >> 22) & 3) {
2303 case 0:
2304 if (insn & (1 << 21))
2305 gen_op_iwmmxt_minsb_M0_wRn(rd1);
2306 else
2307 gen_op_iwmmxt_minub_M0_wRn(rd1);
2308 break;
2309 case 1:
2310 if (insn & (1 << 21))
2311 gen_op_iwmmxt_minsw_M0_wRn(rd1);
2312 else
2313 gen_op_iwmmxt_minuw_M0_wRn(rd1);
2314 break;
2315 case 2:
2316 if (insn & (1 << 21))
2317 gen_op_iwmmxt_minsl_M0_wRn(rd1);
2318 else
2319 gen_op_iwmmxt_minul_M0_wRn(rd1);
2320 break;
2321 case 3:
2322 return 1;
2324 gen_op_iwmmxt_movq_wRn_M0(wrd);
2325 gen_op_iwmmxt_set_mup();
2326 break;
2327 case 0x016: case 0x216: case 0x416: case 0x616: /* WMAX */
2328 case 0x816: case 0xa16: case 0xc16: case 0xe16:
2329 wrd = (insn >> 12) & 0xf;
2330 rd0 = (insn >> 16) & 0xf;
2331 rd1 = (insn >> 0) & 0xf;
2332 gen_op_iwmmxt_movq_M0_wRn(rd0);
2333 switch ((insn >> 22) & 3) {
2334 case 0:
2335 if (insn & (1 << 21))
2336 gen_op_iwmmxt_maxsb_M0_wRn(rd1);
2337 else
2338 gen_op_iwmmxt_maxub_M0_wRn(rd1);
2339 break;
2340 case 1:
2341 if (insn & (1 << 21))
2342 gen_op_iwmmxt_maxsw_M0_wRn(rd1);
2343 else
2344 gen_op_iwmmxt_maxuw_M0_wRn(rd1);
2345 break;
2346 case 2:
2347 if (insn & (1 << 21))
2348 gen_op_iwmmxt_maxsl_M0_wRn(rd1);
2349 else
2350 gen_op_iwmmxt_maxul_M0_wRn(rd1);
2351 break;
2352 case 3:
2353 return 1;
2355 gen_op_iwmmxt_movq_wRn_M0(wrd);
2356 gen_op_iwmmxt_set_mup();
2357 break;
2358 case 0x002: case 0x102: case 0x202: case 0x302: /* WALIGNI */
2359 case 0x402: case 0x502: case 0x602: case 0x702:
2360 wrd = (insn >> 12) & 0xf;
2361 rd0 = (insn >> 16) & 0xf;
2362 rd1 = (insn >> 0) & 0xf;
2363 gen_op_iwmmxt_movq_M0_wRn(rd0);
2364 tmp = tcg_const_i32((insn >> 20) & 3);
2365 iwmmxt_load_reg(cpu_V1, rd1);
2366 gen_helper_iwmmxt_align(cpu_M0, cpu_M0, cpu_V1, tmp);
2367 tcg_temp_free_i32(tmp);
2368 gen_op_iwmmxt_movq_wRn_M0(wrd);
2369 gen_op_iwmmxt_set_mup();
2370 break;
2371 case 0x01a: case 0x11a: case 0x21a: case 0x31a: /* WSUB */
2372 case 0x41a: case 0x51a: case 0x61a: case 0x71a:
2373 case 0x81a: case 0x91a: case 0xa1a: case 0xb1a:
2374 case 0xc1a: case 0xd1a: case 0xe1a: case 0xf1a:
2375 wrd = (insn >> 12) & 0xf;
2376 rd0 = (insn >> 16) & 0xf;
2377 rd1 = (insn >> 0) & 0xf;
2378 gen_op_iwmmxt_movq_M0_wRn(rd0);
2379 switch ((insn >> 20) & 0xf) {
2380 case 0x0:
2381 gen_op_iwmmxt_subnb_M0_wRn(rd1);
2382 break;
2383 case 0x1:
2384 gen_op_iwmmxt_subub_M0_wRn(rd1);
2385 break;
2386 case 0x3:
2387 gen_op_iwmmxt_subsb_M0_wRn(rd1);
2388 break;
2389 case 0x4:
2390 gen_op_iwmmxt_subnw_M0_wRn(rd1);
2391 break;
2392 case 0x5:
2393 gen_op_iwmmxt_subuw_M0_wRn(rd1);
2394 break;
2395 case 0x7:
2396 gen_op_iwmmxt_subsw_M0_wRn(rd1);
2397 break;
2398 case 0x8:
2399 gen_op_iwmmxt_subnl_M0_wRn(rd1);
2400 break;
2401 case 0x9:
2402 gen_op_iwmmxt_subul_M0_wRn(rd1);
2403 break;
2404 case 0xb:
2405 gen_op_iwmmxt_subsl_M0_wRn(rd1);
2406 break;
2407 default:
2408 return 1;
2410 gen_op_iwmmxt_movq_wRn_M0(wrd);
2411 gen_op_iwmmxt_set_mup();
2412 gen_op_iwmmxt_set_cup();
2413 break;
2414 case 0x01e: case 0x11e: case 0x21e: case 0x31e: /* WSHUFH */
2415 case 0x41e: case 0x51e: case 0x61e: case 0x71e:
2416 case 0x81e: case 0x91e: case 0xa1e: case 0xb1e:
2417 case 0xc1e: case 0xd1e: case 0xe1e: case 0xf1e:
2418 wrd = (insn >> 12) & 0xf;
2419 rd0 = (insn >> 16) & 0xf;
2420 gen_op_iwmmxt_movq_M0_wRn(rd0);
2421 tmp = tcg_const_i32(((insn >> 16) & 0xf0) | (insn & 0x0f));
2422 gen_helper_iwmmxt_shufh(cpu_M0, cpu_env, cpu_M0, tmp);
2423 tcg_temp_free_i32(tmp);
2424 gen_op_iwmmxt_movq_wRn_M0(wrd);
2425 gen_op_iwmmxt_set_mup();
2426 gen_op_iwmmxt_set_cup();
2427 break;
2428 case 0x018: case 0x118: case 0x218: case 0x318: /* WADD */
2429 case 0x418: case 0x518: case 0x618: case 0x718:
2430 case 0x818: case 0x918: case 0xa18: case 0xb18:
2431 case 0xc18: case 0xd18: case 0xe18: case 0xf18:
2432 wrd = (insn >> 12) & 0xf;
2433 rd0 = (insn >> 16) & 0xf;
2434 rd1 = (insn >> 0) & 0xf;
2435 gen_op_iwmmxt_movq_M0_wRn(rd0);
2436 switch ((insn >> 20) & 0xf) {
2437 case 0x0:
2438 gen_op_iwmmxt_addnb_M0_wRn(rd1);
2439 break;
2440 case 0x1:
2441 gen_op_iwmmxt_addub_M0_wRn(rd1);
2442 break;
2443 case 0x3:
2444 gen_op_iwmmxt_addsb_M0_wRn(rd1);
2445 break;
2446 case 0x4:
2447 gen_op_iwmmxt_addnw_M0_wRn(rd1);
2448 break;
2449 case 0x5:
2450 gen_op_iwmmxt_adduw_M0_wRn(rd1);
2451 break;
2452 case 0x7:
2453 gen_op_iwmmxt_addsw_M0_wRn(rd1);
2454 break;
2455 case 0x8:
2456 gen_op_iwmmxt_addnl_M0_wRn(rd1);
2457 break;
2458 case 0x9:
2459 gen_op_iwmmxt_addul_M0_wRn(rd1);
2460 break;
2461 case 0xb:
2462 gen_op_iwmmxt_addsl_M0_wRn(rd1);
2463 break;
2464 default:
2465 return 1;
2467 gen_op_iwmmxt_movq_wRn_M0(wrd);
2468 gen_op_iwmmxt_set_mup();
2469 gen_op_iwmmxt_set_cup();
2470 break;
2471 case 0x008: case 0x108: case 0x208: case 0x308: /* WPACK */
2472 case 0x408: case 0x508: case 0x608: case 0x708:
2473 case 0x808: case 0x908: case 0xa08: case 0xb08:
2474 case 0xc08: case 0xd08: case 0xe08: case 0xf08:
2475 if (!(insn & (1 << 20)) || ((insn >> 22) & 3) == 0)
2476 return 1;
2477 wrd = (insn >> 12) & 0xf;
2478 rd0 = (insn >> 16) & 0xf;
2479 rd1 = (insn >> 0) & 0xf;
2480 gen_op_iwmmxt_movq_M0_wRn(rd0);
2481 switch ((insn >> 22) & 3) {
2482 case 1:
2483 if (insn & (1 << 21))
2484 gen_op_iwmmxt_packsw_M0_wRn(rd1);
2485 else
2486 gen_op_iwmmxt_packuw_M0_wRn(rd1);
2487 break;
2488 case 2:
2489 if (insn & (1 << 21))
2490 gen_op_iwmmxt_packsl_M0_wRn(rd1);
2491 else
2492 gen_op_iwmmxt_packul_M0_wRn(rd1);
2493 break;
2494 case 3:
2495 if (insn & (1 << 21))
2496 gen_op_iwmmxt_packsq_M0_wRn(rd1);
2497 else
2498 gen_op_iwmmxt_packuq_M0_wRn(rd1);
2499 break;
2501 gen_op_iwmmxt_movq_wRn_M0(wrd);
2502 gen_op_iwmmxt_set_mup();
2503 gen_op_iwmmxt_set_cup();
2504 break;
2505 case 0x201: case 0x203: case 0x205: case 0x207:
2506 case 0x209: case 0x20b: case 0x20d: case 0x20f:
2507 case 0x211: case 0x213: case 0x215: case 0x217:
2508 case 0x219: case 0x21b: case 0x21d: case 0x21f:
2509 wrd = (insn >> 5) & 0xf;
2510 rd0 = (insn >> 12) & 0xf;
2511 rd1 = (insn >> 0) & 0xf;
2512 if (rd0 == 0xf || rd1 == 0xf)
2513 return 1;
2514 gen_op_iwmmxt_movq_M0_wRn(wrd);
2515 tmp = load_reg(s, rd0);
2516 tmp2 = load_reg(s, rd1);
2517 switch ((insn >> 16) & 0xf) {
2518 case 0x0: /* TMIA */
2519 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2520 break;
2521 case 0x8: /* TMIAPH */
2522 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2523 break;
2524 case 0xc: case 0xd: case 0xe: case 0xf: /* TMIAxy */
2525 if (insn & (1 << 16))
2526 tcg_gen_shri_i32(tmp, tmp, 16);
2527 if (insn & (1 << 17))
2528 tcg_gen_shri_i32(tmp2, tmp2, 16);
2529 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2530 break;
2531 default:
2532 tcg_temp_free_i32(tmp2);
2533 tcg_temp_free_i32(tmp);
2534 return 1;
2536 tcg_temp_free_i32(tmp2);
2537 tcg_temp_free_i32(tmp);
2538 gen_op_iwmmxt_movq_wRn_M0(wrd);
2539 gen_op_iwmmxt_set_mup();
2540 break;
2541 default:
2542 return 1;
2545 return 0;
2548 /* Disassemble an XScale DSP instruction. Returns nonzero if an error occurred
2549 (ie. an undefined instruction). */
2550 static int disas_dsp_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2552 int acc, rd0, rd1, rdhi, rdlo;
2553 TCGv_i32 tmp, tmp2;
2555 if ((insn & 0x0ff00f10) == 0x0e200010) {
2556 /* Multiply with Internal Accumulate Format */
2557 rd0 = (insn >> 12) & 0xf;
2558 rd1 = insn & 0xf;
2559 acc = (insn >> 5) & 7;
2561 if (acc != 0)
2562 return 1;
2564 tmp = load_reg(s, rd0);
2565 tmp2 = load_reg(s, rd1);
2566 switch ((insn >> 16) & 0xf) {
2567 case 0x0: /* MIA */
2568 gen_helper_iwmmxt_muladdsl(cpu_M0, cpu_M0, tmp, tmp2);
2569 break;
2570 case 0x8: /* MIAPH */
2571 gen_helper_iwmmxt_muladdsw(cpu_M0, cpu_M0, tmp, tmp2);
2572 break;
2573 case 0xc: /* MIABB */
2574 case 0xd: /* MIABT */
2575 case 0xe: /* MIATB */
2576 case 0xf: /* MIATT */
2577 if (insn & (1 << 16))
2578 tcg_gen_shri_i32(tmp, tmp, 16);
2579 if (insn & (1 << 17))
2580 tcg_gen_shri_i32(tmp2, tmp2, 16);
2581 gen_helper_iwmmxt_muladdswl(cpu_M0, cpu_M0, tmp, tmp2);
2582 break;
2583 default:
2584 return 1;
2586 tcg_temp_free_i32(tmp2);
2587 tcg_temp_free_i32(tmp);
2589 gen_op_iwmmxt_movq_wRn_M0(acc);
2590 return 0;
2593 if ((insn & 0x0fe00ff8) == 0x0c400000) {
2594 /* Internal Accumulator Access Format */
2595 rdhi = (insn >> 16) & 0xf;
2596 rdlo = (insn >> 12) & 0xf;
2597 acc = insn & 7;
2599 if (acc != 0)
2600 return 1;
2602 if (insn & ARM_CP_RW_BIT) { /* MRA */
2603 iwmmxt_load_reg(cpu_V0, acc);
2604 tcg_gen_trunc_i64_i32(cpu_R[rdlo], cpu_V0);
2605 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
2606 tcg_gen_trunc_i64_i32(cpu_R[rdhi], cpu_V0);
2607 tcg_gen_andi_i32(cpu_R[rdhi], cpu_R[rdhi], (1 << (40 - 32)) - 1);
2608 } else { /* MAR */
2609 tcg_gen_concat_i32_i64(cpu_V0, cpu_R[rdlo], cpu_R[rdhi]);
2610 iwmmxt_store_reg(cpu_V0, acc);
2612 return 0;
2615 return 1;
2618 #define VFP_REG_SHR(x, n) (((n) > 0) ? (x) >> (n) : (x) << -(n))
2619 #define VFP_SREG(insn, bigbit, smallbit) \
2620 ((VFP_REG_SHR(insn, bigbit - 1) & 0x1e) | (((insn) >> (smallbit)) & 1))
2621 #define VFP_DREG(reg, insn, bigbit, smallbit) do { \
2622 if (arm_feature(env, ARM_FEATURE_VFP3)) { \
2623 reg = (((insn) >> (bigbit)) & 0x0f) \
2624 | (((insn) >> ((smallbit) - 4)) & 0x10); \
2625 } else { \
2626 if (insn & (1 << (smallbit))) \
2627 return 1; \
2628 reg = ((insn) >> (bigbit)) & 0x0f; \
2629 }} while (0)
2631 #define VFP_SREG_D(insn) VFP_SREG(insn, 12, 22)
2632 #define VFP_DREG_D(reg, insn) VFP_DREG(reg, insn, 12, 22)
2633 #define VFP_SREG_N(insn) VFP_SREG(insn, 16, 7)
2634 #define VFP_DREG_N(reg, insn) VFP_DREG(reg, insn, 16, 7)
2635 #define VFP_SREG_M(insn) VFP_SREG(insn, 0, 5)
2636 #define VFP_DREG_M(reg, insn) VFP_DREG(reg, insn, 0, 5)
2638 /* Move between integer and VFP cores. */
2639 static TCGv_i32 gen_vfp_mrs(void)
2641 TCGv_i32 tmp = tcg_temp_new_i32();
2642 tcg_gen_mov_i32(tmp, cpu_F0s);
2643 return tmp;
2646 static void gen_vfp_msr(TCGv_i32 tmp)
2648 tcg_gen_mov_i32(cpu_F0s, tmp);
2649 tcg_temp_free_i32(tmp);
2652 static void gen_neon_dup_u8(TCGv_i32 var, int shift)
2654 TCGv_i32 tmp = tcg_temp_new_i32();
2655 if (shift)
2656 tcg_gen_shri_i32(var, var, shift);
2657 tcg_gen_ext8u_i32(var, var);
2658 tcg_gen_shli_i32(tmp, var, 8);
2659 tcg_gen_or_i32(var, var, tmp);
2660 tcg_gen_shli_i32(tmp, var, 16);
2661 tcg_gen_or_i32(var, var, tmp);
2662 tcg_temp_free_i32(tmp);
2665 static void gen_neon_dup_low16(TCGv_i32 var)
2667 TCGv_i32 tmp = tcg_temp_new_i32();
2668 tcg_gen_ext16u_i32(var, var);
2669 tcg_gen_shli_i32(tmp, var, 16);
2670 tcg_gen_or_i32(var, var, tmp);
2671 tcg_temp_free_i32(tmp);
2674 static void gen_neon_dup_high16(TCGv_i32 var)
2676 TCGv_i32 tmp = tcg_temp_new_i32();
2677 tcg_gen_andi_i32(var, var, 0xffff0000);
2678 tcg_gen_shri_i32(tmp, var, 16);
2679 tcg_gen_or_i32(var, var, tmp);
2680 tcg_temp_free_i32(tmp);
2683 static TCGv_i32 gen_load_and_replicate(DisasContext *s, TCGv_i32 addr, int size)
2685 /* Load a single Neon element and replicate into a 32 bit TCG reg */
2686 TCGv_i32 tmp = tcg_temp_new_i32();
2687 switch (size) {
2688 case 0:
2689 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
2690 gen_neon_dup_u8(tmp, 0);
2691 break;
2692 case 1:
2693 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
2694 gen_neon_dup_low16(tmp);
2695 break;
2696 case 2:
2697 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
2698 break;
2699 default: /* Avoid compiler warnings. */
2700 abort();
2702 return tmp;
2705 static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
2706 uint32_t dp)
2708 uint32_t cc = extract32(insn, 20, 2);
2710 if (dp) {
2711 TCGv_i64 frn, frm, dest;
2712 TCGv_i64 tmp, zero, zf, nf, vf;
2714 zero = tcg_const_i64(0);
2716 frn = tcg_temp_new_i64();
2717 frm = tcg_temp_new_i64();
2718 dest = tcg_temp_new_i64();
2720 zf = tcg_temp_new_i64();
2721 nf = tcg_temp_new_i64();
2722 vf = tcg_temp_new_i64();
2724 tcg_gen_extu_i32_i64(zf, cpu_ZF);
2725 tcg_gen_ext_i32_i64(nf, cpu_NF);
2726 tcg_gen_ext_i32_i64(vf, cpu_VF);
2728 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2729 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2730 switch (cc) {
2731 case 0: /* eq: Z */
2732 tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
2733 frn, frm);
2734 break;
2735 case 1: /* vs: V */
2736 tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
2737 frn, frm);
2738 break;
2739 case 2: /* ge: N == V -> N ^ V == 0 */
2740 tmp = tcg_temp_new_i64();
2741 tcg_gen_xor_i64(tmp, vf, nf);
2742 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2743 frn, frm);
2744 tcg_temp_free_i64(tmp);
2745 break;
2746 case 3: /* gt: !Z && N == V */
2747 tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
2748 frn, frm);
2749 tmp = tcg_temp_new_i64();
2750 tcg_gen_xor_i64(tmp, vf, nf);
2751 tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
2752 dest, frm);
2753 tcg_temp_free_i64(tmp);
2754 break;
2756 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2757 tcg_temp_free_i64(frn);
2758 tcg_temp_free_i64(frm);
2759 tcg_temp_free_i64(dest);
2761 tcg_temp_free_i64(zf);
2762 tcg_temp_free_i64(nf);
2763 tcg_temp_free_i64(vf);
2765 tcg_temp_free_i64(zero);
2766 } else {
2767 TCGv_i32 frn, frm, dest;
2768 TCGv_i32 tmp, zero;
2770 zero = tcg_const_i32(0);
2772 frn = tcg_temp_new_i32();
2773 frm = tcg_temp_new_i32();
2774 dest = tcg_temp_new_i32();
2775 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2776 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2777 switch (cc) {
2778 case 0: /* eq: Z */
2779 tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
2780 frn, frm);
2781 break;
2782 case 1: /* vs: V */
2783 tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
2784 frn, frm);
2785 break;
2786 case 2: /* ge: N == V -> N ^ V == 0 */
2787 tmp = tcg_temp_new_i32();
2788 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2789 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2790 frn, frm);
2791 tcg_temp_free_i32(tmp);
2792 break;
2793 case 3: /* gt: !Z && N == V */
2794 tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
2795 frn, frm);
2796 tmp = tcg_temp_new_i32();
2797 tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
2798 tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
2799 dest, frm);
2800 tcg_temp_free_i32(tmp);
2801 break;
2803 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2804 tcg_temp_free_i32(frn);
2805 tcg_temp_free_i32(frm);
2806 tcg_temp_free_i32(dest);
2808 tcg_temp_free_i32(zero);
2811 return 0;
2814 static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
2815 uint32_t rm, uint32_t dp)
2817 uint32_t vmin = extract32(insn, 6, 1);
2818 TCGv_ptr fpst = get_fpstatus_ptr(0);
2820 if (dp) {
2821 TCGv_i64 frn, frm, dest;
2823 frn = tcg_temp_new_i64();
2824 frm = tcg_temp_new_i64();
2825 dest = tcg_temp_new_i64();
2827 tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
2828 tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
2829 if (vmin) {
2830 gen_helper_vfp_minnumd(dest, frn, frm, fpst);
2831 } else {
2832 gen_helper_vfp_maxnumd(dest, frn, frm, fpst);
2834 tcg_gen_st_f64(dest, cpu_env, vfp_reg_offset(dp, rd));
2835 tcg_temp_free_i64(frn);
2836 tcg_temp_free_i64(frm);
2837 tcg_temp_free_i64(dest);
2838 } else {
2839 TCGv_i32 frn, frm, dest;
2841 frn = tcg_temp_new_i32();
2842 frm = tcg_temp_new_i32();
2843 dest = tcg_temp_new_i32();
2845 tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
2846 tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
2847 if (vmin) {
2848 gen_helper_vfp_minnums(dest, frn, frm, fpst);
2849 } else {
2850 gen_helper_vfp_maxnums(dest, frn, frm, fpst);
2852 tcg_gen_st_f32(dest, cpu_env, vfp_reg_offset(dp, rd));
2853 tcg_temp_free_i32(frn);
2854 tcg_temp_free_i32(frm);
2855 tcg_temp_free_i32(dest);
2858 tcg_temp_free_ptr(fpst);
2859 return 0;
2862 static int handle_vrint(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2863 int rounding)
2865 TCGv_ptr fpst = get_fpstatus_ptr(0);
2866 TCGv_i32 tcg_rmode;
2868 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2869 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2871 if (dp) {
2872 TCGv_i64 tcg_op;
2873 TCGv_i64 tcg_res;
2874 tcg_op = tcg_temp_new_i64();
2875 tcg_res = tcg_temp_new_i64();
2876 tcg_gen_ld_f64(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2877 gen_helper_rintd(tcg_res, tcg_op, fpst);
2878 tcg_gen_st_f64(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2879 tcg_temp_free_i64(tcg_op);
2880 tcg_temp_free_i64(tcg_res);
2881 } else {
2882 TCGv_i32 tcg_op;
2883 TCGv_i32 tcg_res;
2884 tcg_op = tcg_temp_new_i32();
2885 tcg_res = tcg_temp_new_i32();
2886 tcg_gen_ld_f32(tcg_op, cpu_env, vfp_reg_offset(dp, rm));
2887 gen_helper_rints(tcg_res, tcg_op, fpst);
2888 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(dp, rd));
2889 tcg_temp_free_i32(tcg_op);
2890 tcg_temp_free_i32(tcg_res);
2893 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2894 tcg_temp_free_i32(tcg_rmode);
2896 tcg_temp_free_ptr(fpst);
2897 return 0;
2900 static int handle_vcvt(uint32_t insn, uint32_t rd, uint32_t rm, uint32_t dp,
2901 int rounding)
2903 bool is_signed = extract32(insn, 7, 1);
2904 TCGv_ptr fpst = get_fpstatus_ptr(0);
2905 TCGv_i32 tcg_rmode, tcg_shift;
2907 tcg_shift = tcg_const_i32(0);
2909 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
2910 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2912 if (dp) {
2913 TCGv_i64 tcg_double, tcg_res;
2914 TCGv_i32 tcg_tmp;
2915 /* Rd is encoded as a single precision register even when the source
2916 * is double precision.
2918 rd = ((rd << 1) & 0x1e) | ((rd >> 4) & 0x1);
2919 tcg_double = tcg_temp_new_i64();
2920 tcg_res = tcg_temp_new_i64();
2921 tcg_tmp = tcg_temp_new_i32();
2922 tcg_gen_ld_f64(tcg_double, cpu_env, vfp_reg_offset(1, rm));
2923 if (is_signed) {
2924 gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
2925 } else {
2926 gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
2928 tcg_gen_trunc_i64_i32(tcg_tmp, tcg_res);
2929 tcg_gen_st_f32(tcg_tmp, cpu_env, vfp_reg_offset(0, rd));
2930 tcg_temp_free_i32(tcg_tmp);
2931 tcg_temp_free_i64(tcg_res);
2932 tcg_temp_free_i64(tcg_double);
2933 } else {
2934 TCGv_i32 tcg_single, tcg_res;
2935 tcg_single = tcg_temp_new_i32();
2936 tcg_res = tcg_temp_new_i32();
2937 tcg_gen_ld_f32(tcg_single, cpu_env, vfp_reg_offset(0, rm));
2938 if (is_signed) {
2939 gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
2940 } else {
2941 gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
2943 tcg_gen_st_f32(tcg_res, cpu_env, vfp_reg_offset(0, rd));
2944 tcg_temp_free_i32(tcg_res);
2945 tcg_temp_free_i32(tcg_single);
2948 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
2949 tcg_temp_free_i32(tcg_rmode);
2951 tcg_temp_free_i32(tcg_shift);
2953 tcg_temp_free_ptr(fpst);
2955 return 0;
2958 /* Table for converting the most common AArch32 encoding of
2959 * rounding mode to arm_fprounding order (which matches the
2960 * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
2962 static const uint8_t fp_decode_rm[] = {
2963 FPROUNDING_TIEAWAY,
2964 FPROUNDING_TIEEVEN,
2965 FPROUNDING_POSINF,
2966 FPROUNDING_NEGINF,
2969 static int disas_vfp_v8_insn(CPUARMState *env, DisasContext *s, uint32_t insn)
2971 uint32_t rd, rn, rm, dp = extract32(insn, 8, 1);
2973 if (!arm_feature(env, ARM_FEATURE_V8)) {
2974 return 1;
2977 if (dp) {
2978 VFP_DREG_D(rd, insn);
2979 VFP_DREG_N(rn, insn);
2980 VFP_DREG_M(rm, insn);
2981 } else {
2982 rd = VFP_SREG_D(insn);
2983 rn = VFP_SREG_N(insn);
2984 rm = VFP_SREG_M(insn);
2987 if ((insn & 0x0f800e50) == 0x0e000a00) {
2988 return handle_vsel(insn, rd, rn, rm, dp);
2989 } else if ((insn & 0x0fb00e10) == 0x0e800a00) {
2990 return handle_vminmaxnm(insn, rd, rn, rm, dp);
2991 } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40) {
2992 /* VRINTA, VRINTN, VRINTP, VRINTM */
2993 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2994 return handle_vrint(insn, rd, rm, dp, rounding);
2995 } else if ((insn & 0x0fbc0e50) == 0x0ebc0a40) {
2996 /* VCVTA, VCVTN, VCVTP, VCVTM */
2997 int rounding = fp_decode_rm[extract32(insn, 16, 2)];
2998 return handle_vcvt(insn, rd, rm, dp, rounding);
3000 return 1;
3003 /* Disassemble a VFP instruction. Returns nonzero if an error occurred
3004 (ie. an undefined instruction). */
3005 static int disas_vfp_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
3007 uint32_t rd, rn, rm, op, i, n, offset, delta_d, delta_m, bank_mask;
3008 int dp, veclen;
3009 TCGv_i32 addr;
3010 TCGv_i32 tmp;
3011 TCGv_i32 tmp2;
3013 if (!arm_feature(env, ARM_FEATURE_VFP))
3014 return 1;
3016 /* FIXME: this access check should not take precedence over UNDEF
3017 * for invalid encodings; we will generate incorrect syndrome information
3018 * for attempts to execute invalid vfp/neon encodings with FP disabled.
3020 if (!s->cpacr_fpen) {
3021 gen_exception_insn(s, 4, EXCP_UDEF,
3022 syn_fp_access_trap(1, 0xe, s->thumb));
3023 return 0;
3026 if (!s->vfp_enabled) {
3027 /* VFP disabled. Only allow fmxr/fmrx to/from some control regs. */
3028 if ((insn & 0x0fe00fff) != 0x0ee00a10)
3029 return 1;
3030 rn = (insn >> 16) & 0xf;
3031 if (rn != ARM_VFP_FPSID && rn != ARM_VFP_FPEXC && rn != ARM_VFP_MVFR2
3032 && rn != ARM_VFP_MVFR1 && rn != ARM_VFP_MVFR0) {
3033 return 1;
3037 if (extract32(insn, 28, 4) == 0xf) {
3038 /* Encodings with T=1 (Thumb) or unconditional (ARM):
3039 * only used in v8 and above.
3041 return disas_vfp_v8_insn(env, s, insn);
3044 dp = ((insn & 0xf00) == 0xb00);
3045 switch ((insn >> 24) & 0xf) {
3046 case 0xe:
3047 if (insn & (1 << 4)) {
3048 /* single register transfer */
3049 rd = (insn >> 12) & 0xf;
3050 if (dp) {
3051 int size;
3052 int pass;
3054 VFP_DREG_N(rn, insn);
3055 if (insn & 0xf)
3056 return 1;
3057 if (insn & 0x00c00060
3058 && !arm_feature(env, ARM_FEATURE_NEON))
3059 return 1;
3061 pass = (insn >> 21) & 1;
3062 if (insn & (1 << 22)) {
3063 size = 0;
3064 offset = ((insn >> 5) & 3) * 8;
3065 } else if (insn & (1 << 5)) {
3066 size = 1;
3067 offset = (insn & (1 << 6)) ? 16 : 0;
3068 } else {
3069 size = 2;
3070 offset = 0;
3072 if (insn & ARM_CP_RW_BIT) {
3073 /* vfp->arm */
3074 tmp = neon_load_reg(rn, pass);
3075 switch (size) {
3076 case 0:
3077 if (offset)
3078 tcg_gen_shri_i32(tmp, tmp, offset);
3079 if (insn & (1 << 23))
3080 gen_uxtb(tmp);
3081 else
3082 gen_sxtb(tmp);
3083 break;
3084 case 1:
3085 if (insn & (1 << 23)) {
3086 if (offset) {
3087 tcg_gen_shri_i32(tmp, tmp, 16);
3088 } else {
3089 gen_uxth(tmp);
3091 } else {
3092 if (offset) {
3093 tcg_gen_sari_i32(tmp, tmp, 16);
3094 } else {
3095 gen_sxth(tmp);
3098 break;
3099 case 2:
3100 break;
3102 store_reg(s, rd, tmp);
3103 } else {
3104 /* arm->vfp */
3105 tmp = load_reg(s, rd);
3106 if (insn & (1 << 23)) {
3107 /* VDUP */
3108 if (size == 0) {
3109 gen_neon_dup_u8(tmp, 0);
3110 } else if (size == 1) {
3111 gen_neon_dup_low16(tmp);
3113 for (n = 0; n <= pass * 2; n++) {
3114 tmp2 = tcg_temp_new_i32();
3115 tcg_gen_mov_i32(tmp2, tmp);
3116 neon_store_reg(rn, n, tmp2);
3118 neon_store_reg(rn, n, tmp);
3119 } else {
3120 /* VMOV */
3121 switch (size) {
3122 case 0:
3123 tmp2 = neon_load_reg(rn, pass);
3124 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
3125 tcg_temp_free_i32(tmp2);
3126 break;
3127 case 1:
3128 tmp2 = neon_load_reg(rn, pass);
3129 tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
3130 tcg_temp_free_i32(tmp2);
3131 break;
3132 case 2:
3133 break;
3135 neon_store_reg(rn, pass, tmp);
3138 } else { /* !dp */
3139 if ((insn & 0x6f) != 0x00)
3140 return 1;
3141 rn = VFP_SREG_N(insn);
3142 if (insn & ARM_CP_RW_BIT) {
3143 /* vfp->arm */
3144 if (insn & (1 << 21)) {
3145 /* system register */
3146 rn >>= 1;
3148 switch (rn) {
3149 case ARM_VFP_FPSID:
3150 /* VFP2 allows access to FSID from userspace.
3151 VFP3 restricts all id registers to privileged
3152 accesses. */
3153 if (IS_USER(s)
3154 && arm_feature(env, ARM_FEATURE_VFP3))
3155 return 1;
3156 tmp = load_cpu_field(vfp.xregs[rn]);
3157 break;
3158 case ARM_VFP_FPEXC:
3159 if (IS_USER(s))
3160 return 1;
3161 tmp = load_cpu_field(vfp.xregs[rn]);
3162 break;
3163 case ARM_VFP_FPINST:
3164 case ARM_VFP_FPINST2:
3165 /* Not present in VFP3. */
3166 if (IS_USER(s)
3167 || arm_feature(env, ARM_FEATURE_VFP3))
3168 return 1;
3169 tmp = load_cpu_field(vfp.xregs[rn]);
3170 break;
3171 case ARM_VFP_FPSCR:
3172 if (rd == 15) {
3173 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
3174 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
3175 } else {
3176 tmp = tcg_temp_new_i32();
3177 gen_helper_vfp_get_fpscr(tmp, cpu_env);
3179 break;
3180 case ARM_VFP_MVFR2:
3181 if (!arm_feature(env, ARM_FEATURE_V8)) {
3182 return 1;
3184 /* fall through */
3185 case ARM_VFP_MVFR0:
3186 case ARM_VFP_MVFR1:
3187 if (IS_USER(s)
3188 || !arm_feature(env, ARM_FEATURE_MVFR))
3189 return 1;
3190 tmp = load_cpu_field(vfp.xregs[rn]);
3191 break;
3192 default:
3193 return 1;
3195 } else {
3196 gen_mov_F0_vreg(0, rn);
3197 tmp = gen_vfp_mrs();
3199 if (rd == 15) {
3200 /* Set the 4 flag bits in the CPSR. */
3201 gen_set_nzcv(tmp);
3202 tcg_temp_free_i32(tmp);
3203 } else {
3204 store_reg(s, rd, tmp);
3206 } else {
3207 /* arm->vfp */
3208 if (insn & (1 << 21)) {
3209 rn >>= 1;
3210 /* system register */
3211 switch (rn) {
3212 case ARM_VFP_FPSID:
3213 case ARM_VFP_MVFR0:
3214 case ARM_VFP_MVFR1:
3215 /* Writes are ignored. */
3216 break;
3217 case ARM_VFP_FPSCR:
3218 tmp = load_reg(s, rd);
3219 gen_helper_vfp_set_fpscr(cpu_env, tmp);
3220 tcg_temp_free_i32(tmp);
3221 gen_lookup_tb(s);
3222 break;
3223 case ARM_VFP_FPEXC:
3224 if (IS_USER(s))
3225 return 1;
3226 /* TODO: VFP subarchitecture support.
3227 * For now, keep the EN bit only */
3228 tmp = load_reg(s, rd);
3229 tcg_gen_andi_i32(tmp, tmp, 1 << 30);
3230 store_cpu_field(tmp, vfp.xregs[rn]);
3231 gen_lookup_tb(s);
3232 break;
3233 case ARM_VFP_FPINST:
3234 case ARM_VFP_FPINST2:
3235 if (IS_USER(s)) {
3236 return 1;
3238 tmp = load_reg(s, rd);
3239 store_cpu_field(tmp, vfp.xregs[rn]);
3240 break;
3241 default:
3242 return 1;
3244 } else {
3245 tmp = load_reg(s, rd);
3246 gen_vfp_msr(tmp);
3247 gen_mov_vreg_F0(0, rn);
3251 } else {
3252 /* data processing */
3253 /* The opcode is in bits 23, 21, 20 and 6. */
3254 op = ((insn >> 20) & 8) | ((insn >> 19) & 6) | ((insn >> 6) & 1);
3255 if (dp) {
3256 if (op == 15) {
3257 /* rn is opcode */
3258 rn = ((insn >> 15) & 0x1e) | ((insn >> 7) & 1);
3259 } else {
3260 /* rn is register number */
3261 VFP_DREG_N(rn, insn);
3264 if (op == 15 && (rn == 15 || ((rn & 0x1c) == 0x18) ||
3265 ((rn & 0x1e) == 0x6))) {
3266 /* Integer or single/half precision destination. */
3267 rd = VFP_SREG_D(insn);
3268 } else {
3269 VFP_DREG_D(rd, insn);
3271 if (op == 15 &&
3272 (((rn & 0x1c) == 0x10) || ((rn & 0x14) == 0x14) ||
3273 ((rn & 0x1e) == 0x4))) {
3274 /* VCVT from int or half precision is always from S reg
3275 * regardless of dp bit. VCVT with immediate frac_bits
3276 * has same format as SREG_M.
3278 rm = VFP_SREG_M(insn);
3279 } else {
3280 VFP_DREG_M(rm, insn);
3282 } else {
3283 rn = VFP_SREG_N(insn);
3284 if (op == 15 && rn == 15) {
3285 /* Double precision destination. */
3286 VFP_DREG_D(rd, insn);
3287 } else {
3288 rd = VFP_SREG_D(insn);
3290 /* NB that we implicitly rely on the encoding for the frac_bits
3291 * in VCVT of fixed to float being the same as that of an SREG_M
3293 rm = VFP_SREG_M(insn);
3296 veclen = s->vec_len;
3297 if (op == 15 && rn > 3)
3298 veclen = 0;
3300 /* Shut up compiler warnings. */
3301 delta_m = 0;
3302 delta_d = 0;
3303 bank_mask = 0;
3305 if (veclen > 0) {
3306 if (dp)
3307 bank_mask = 0xc;
3308 else
3309 bank_mask = 0x18;
3311 /* Figure out what type of vector operation this is. */
3312 if ((rd & bank_mask) == 0) {
3313 /* scalar */
3314 veclen = 0;
3315 } else {
3316 if (dp)
3317 delta_d = (s->vec_stride >> 1) + 1;
3318 else
3319 delta_d = s->vec_stride + 1;
3321 if ((rm & bank_mask) == 0) {
3322 /* mixed scalar/vector */
3323 delta_m = 0;
3324 } else {
3325 /* vector */
3326 delta_m = delta_d;
3331 /* Load the initial operands. */
3332 if (op == 15) {
3333 switch (rn) {
3334 case 16:
3335 case 17:
3336 /* Integer source */
3337 gen_mov_F0_vreg(0, rm);
3338 break;
3339 case 8:
3340 case 9:
3341 /* Compare */
3342 gen_mov_F0_vreg(dp, rd);
3343 gen_mov_F1_vreg(dp, rm);
3344 break;
3345 case 10:
3346 case 11:
3347 /* Compare with zero */
3348 gen_mov_F0_vreg(dp, rd);
3349 gen_vfp_F1_ld0(dp);
3350 break;
3351 case 20:
3352 case 21:
3353 case 22:
3354 case 23:
3355 case 28:
3356 case 29:
3357 case 30:
3358 case 31:
3359 /* Source and destination the same. */
3360 gen_mov_F0_vreg(dp, rd);
3361 break;
3362 case 4:
3363 case 5:
3364 case 6:
3365 case 7:
3366 /* VCVTB, VCVTT: only present with the halfprec extension
3367 * UNPREDICTABLE if bit 8 is set prior to ARMv8
3368 * (we choose to UNDEF)
3370 if ((dp && !arm_feature(env, ARM_FEATURE_V8)) ||
3371 !arm_feature(env, ARM_FEATURE_VFP_FP16)) {
3372 return 1;
3374 if (!extract32(rn, 1, 1)) {
3375 /* Half precision source. */
3376 gen_mov_F0_vreg(0, rm);
3377 break;
3379 /* Otherwise fall through */
3380 default:
3381 /* One source operand. */
3382 gen_mov_F0_vreg(dp, rm);
3383 break;
3385 } else {
3386 /* Two source operands. */
3387 gen_mov_F0_vreg(dp, rn);
3388 gen_mov_F1_vreg(dp, rm);
3391 for (;;) {
3392 /* Perform the calculation. */
3393 switch (op) {
3394 case 0: /* VMLA: fd + (fn * fm) */
3395 /* Note that order of inputs to the add matters for NaNs */
3396 gen_vfp_F1_mul(dp);
3397 gen_mov_F0_vreg(dp, rd);
3398 gen_vfp_add(dp);
3399 break;
3400 case 1: /* VMLS: fd + -(fn * fm) */
3401 gen_vfp_mul(dp);
3402 gen_vfp_F1_neg(dp);
3403 gen_mov_F0_vreg(dp, rd);
3404 gen_vfp_add(dp);
3405 break;
3406 case 2: /* VNMLS: -fd + (fn * fm) */
3407 /* Note that it isn't valid to replace (-A + B) with (B - A)
3408 * or similar plausible looking simplifications
3409 * because this will give wrong results for NaNs.
3411 gen_vfp_F1_mul(dp);
3412 gen_mov_F0_vreg(dp, rd);
3413 gen_vfp_neg(dp);
3414 gen_vfp_add(dp);
3415 break;
3416 case 3: /* VNMLA: -fd + -(fn * fm) */
3417 gen_vfp_mul(dp);
3418 gen_vfp_F1_neg(dp);
3419 gen_mov_F0_vreg(dp, rd);
3420 gen_vfp_neg(dp);
3421 gen_vfp_add(dp);
3422 break;
3423 case 4: /* mul: fn * fm */
3424 gen_vfp_mul(dp);
3425 break;
3426 case 5: /* nmul: -(fn * fm) */
3427 gen_vfp_mul(dp);
3428 gen_vfp_neg(dp);
3429 break;
3430 case 6: /* add: fn + fm */
3431 gen_vfp_add(dp);
3432 break;
3433 case 7: /* sub: fn - fm */
3434 gen_vfp_sub(dp);
3435 break;
3436 case 8: /* div: fn / fm */
3437 gen_vfp_div(dp);
3438 break;
3439 case 10: /* VFNMA : fd = muladd(-fd, fn, fm) */
3440 case 11: /* VFNMS : fd = muladd(-fd, -fn, fm) */
3441 case 12: /* VFMA : fd = muladd( fd, fn, fm) */
3442 case 13: /* VFMS : fd = muladd( fd, -fn, fm) */
3443 /* These are fused multiply-add, and must be done as one
3444 * floating point operation with no rounding between the
3445 * multiplication and addition steps.
3446 * NB that doing the negations here as separate steps is
3447 * correct : an input NaN should come out with its sign bit
3448 * flipped if it is a negated-input.
3450 if (!arm_feature(env, ARM_FEATURE_VFP4)) {
3451 return 1;
3453 if (dp) {
3454 TCGv_ptr fpst;
3455 TCGv_i64 frd;
3456 if (op & 1) {
3457 /* VFNMS, VFMS */
3458 gen_helper_vfp_negd(cpu_F0d, cpu_F0d);
3460 frd = tcg_temp_new_i64();
3461 tcg_gen_ld_f64(frd, cpu_env, vfp_reg_offset(dp, rd));
3462 if (op & 2) {
3463 /* VFNMA, VFNMS */
3464 gen_helper_vfp_negd(frd, frd);
3466 fpst = get_fpstatus_ptr(0);
3467 gen_helper_vfp_muladdd(cpu_F0d, cpu_F0d,
3468 cpu_F1d, frd, fpst);
3469 tcg_temp_free_ptr(fpst);
3470 tcg_temp_free_i64(frd);
3471 } else {
3472 TCGv_ptr fpst;
3473 TCGv_i32 frd;
3474 if (op & 1) {
3475 /* VFNMS, VFMS */
3476 gen_helper_vfp_negs(cpu_F0s, cpu_F0s);
3478 frd = tcg_temp_new_i32();
3479 tcg_gen_ld_f32(frd, cpu_env, vfp_reg_offset(dp, rd));
3480 if (op & 2) {
3481 gen_helper_vfp_negs(frd, frd);
3483 fpst = get_fpstatus_ptr(0);
3484 gen_helper_vfp_muladds(cpu_F0s, cpu_F0s,
3485 cpu_F1s, frd, fpst);
3486 tcg_temp_free_ptr(fpst);
3487 tcg_temp_free_i32(frd);
3489 break;
3490 case 14: /* fconst */
3491 if (!arm_feature(env, ARM_FEATURE_VFP3))
3492 return 1;
3494 n = (insn << 12) & 0x80000000;
3495 i = ((insn >> 12) & 0x70) | (insn & 0xf);
3496 if (dp) {
3497 if (i & 0x40)
3498 i |= 0x3f80;
3499 else
3500 i |= 0x4000;
3501 n |= i << 16;
3502 tcg_gen_movi_i64(cpu_F0d, ((uint64_t)n) << 32);
3503 } else {
3504 if (i & 0x40)
3505 i |= 0x780;
3506 else
3507 i |= 0x800;
3508 n |= i << 19;
3509 tcg_gen_movi_i32(cpu_F0s, n);
3511 break;
3512 case 15: /* extension space */
3513 switch (rn) {
3514 case 0: /* cpy */
3515 /* no-op */
3516 break;
3517 case 1: /* abs */
3518 gen_vfp_abs(dp);
3519 break;
3520 case 2: /* neg */
3521 gen_vfp_neg(dp);
3522 break;
3523 case 3: /* sqrt */
3524 gen_vfp_sqrt(dp);
3525 break;
3526 case 4: /* vcvtb.f32.f16, vcvtb.f64.f16 */
3527 tmp = gen_vfp_mrs();
3528 tcg_gen_ext16u_i32(tmp, tmp);
3529 if (dp) {
3530 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3531 cpu_env);
3532 } else {
3533 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3534 cpu_env);
3536 tcg_temp_free_i32(tmp);
3537 break;
3538 case 5: /* vcvtt.f32.f16, vcvtt.f64.f16 */
3539 tmp = gen_vfp_mrs();
3540 tcg_gen_shri_i32(tmp, tmp, 16);
3541 if (dp) {
3542 gen_helper_vfp_fcvt_f16_to_f64(cpu_F0d, tmp,
3543 cpu_env);
3544 } else {
3545 gen_helper_vfp_fcvt_f16_to_f32(cpu_F0s, tmp,
3546 cpu_env);
3548 tcg_temp_free_i32(tmp);
3549 break;
3550 case 6: /* vcvtb.f16.f32, vcvtb.f16.f64 */
3551 tmp = tcg_temp_new_i32();
3552 if (dp) {
3553 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3554 cpu_env);
3555 } else {
3556 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3557 cpu_env);
3559 gen_mov_F0_vreg(0, rd);
3560 tmp2 = gen_vfp_mrs();
3561 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
3562 tcg_gen_or_i32(tmp, tmp, tmp2);
3563 tcg_temp_free_i32(tmp2);
3564 gen_vfp_msr(tmp);
3565 break;
3566 case 7: /* vcvtt.f16.f32, vcvtt.f16.f64 */
3567 tmp = tcg_temp_new_i32();
3568 if (dp) {
3569 gen_helper_vfp_fcvt_f64_to_f16(tmp, cpu_F0d,
3570 cpu_env);
3571 } else {
3572 gen_helper_vfp_fcvt_f32_to_f16(tmp, cpu_F0s,
3573 cpu_env);
3575 tcg_gen_shli_i32(tmp, tmp, 16);
3576 gen_mov_F0_vreg(0, rd);
3577 tmp2 = gen_vfp_mrs();
3578 tcg_gen_ext16u_i32(tmp2, tmp2);
3579 tcg_gen_or_i32(tmp, tmp, tmp2);
3580 tcg_temp_free_i32(tmp2);
3581 gen_vfp_msr(tmp);
3582 break;
3583 case 8: /* cmp */
3584 gen_vfp_cmp(dp);
3585 break;
3586 case 9: /* cmpe */
3587 gen_vfp_cmpe(dp);
3588 break;
3589 case 10: /* cmpz */
3590 gen_vfp_cmp(dp);
3591 break;
3592 case 11: /* cmpez */
3593 gen_vfp_F1_ld0(dp);
3594 gen_vfp_cmpe(dp);
3595 break;
3596 case 12: /* vrintr */
3598 TCGv_ptr fpst = get_fpstatus_ptr(0);
3599 if (dp) {
3600 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3601 } else {
3602 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3604 tcg_temp_free_ptr(fpst);
3605 break;
3607 case 13: /* vrintz */
3609 TCGv_ptr fpst = get_fpstatus_ptr(0);
3610 TCGv_i32 tcg_rmode;
3611 tcg_rmode = tcg_const_i32(float_round_to_zero);
3612 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3613 if (dp) {
3614 gen_helper_rintd(cpu_F0d, cpu_F0d, fpst);
3615 } else {
3616 gen_helper_rints(cpu_F0s, cpu_F0s, fpst);
3618 gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
3619 tcg_temp_free_i32(tcg_rmode);
3620 tcg_temp_free_ptr(fpst);
3621 break;
3623 case 14: /* vrintx */
3625 TCGv_ptr fpst = get_fpstatus_ptr(0);
3626 if (dp) {
3627 gen_helper_rintd_exact(cpu_F0d, cpu_F0d, fpst);
3628 } else {
3629 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpst);
3631 tcg_temp_free_ptr(fpst);
3632 break;
3634 case 15: /* single<->double conversion */
3635 if (dp)
3636 gen_helper_vfp_fcvtsd(cpu_F0s, cpu_F0d, cpu_env);
3637 else
3638 gen_helper_vfp_fcvtds(cpu_F0d, cpu_F0s, cpu_env);
3639 break;
3640 case 16: /* fuito */
3641 gen_vfp_uito(dp, 0);
3642 break;
3643 case 17: /* fsito */
3644 gen_vfp_sito(dp, 0);
3645 break;
3646 case 20: /* fshto */
3647 if (!arm_feature(env, ARM_FEATURE_VFP3))
3648 return 1;
3649 gen_vfp_shto(dp, 16 - rm, 0);
3650 break;
3651 case 21: /* fslto */
3652 if (!arm_feature(env, ARM_FEATURE_VFP3))
3653 return 1;
3654 gen_vfp_slto(dp, 32 - rm, 0);
3655 break;
3656 case 22: /* fuhto */
3657 if (!arm_feature(env, ARM_FEATURE_VFP3))
3658 return 1;
3659 gen_vfp_uhto(dp, 16 - rm, 0);
3660 break;
3661 case 23: /* fulto */
3662 if (!arm_feature(env, ARM_FEATURE_VFP3))
3663 return 1;
3664 gen_vfp_ulto(dp, 32 - rm, 0);
3665 break;
3666 case 24: /* ftoui */
3667 gen_vfp_toui(dp, 0);
3668 break;
3669 case 25: /* ftouiz */
3670 gen_vfp_touiz(dp, 0);
3671 break;
3672 case 26: /* ftosi */
3673 gen_vfp_tosi(dp, 0);
3674 break;
3675 case 27: /* ftosiz */
3676 gen_vfp_tosiz(dp, 0);
3677 break;
3678 case 28: /* ftosh */
3679 if (!arm_feature(env, ARM_FEATURE_VFP3))
3680 return 1;
3681 gen_vfp_tosh(dp, 16 - rm, 0);
3682 break;
3683 case 29: /* ftosl */
3684 if (!arm_feature(env, ARM_FEATURE_VFP3))
3685 return 1;
3686 gen_vfp_tosl(dp, 32 - rm, 0);
3687 break;
3688 case 30: /* ftouh */
3689 if (!arm_feature(env, ARM_FEATURE_VFP3))
3690 return 1;
3691 gen_vfp_touh(dp, 16 - rm, 0);
3692 break;
3693 case 31: /* ftoul */
3694 if (!arm_feature(env, ARM_FEATURE_VFP3))
3695 return 1;
3696 gen_vfp_toul(dp, 32 - rm, 0);
3697 break;
3698 default: /* undefined */
3699 return 1;
3701 break;
3702 default: /* undefined */
3703 return 1;
3706 /* Write back the result. */
3707 if (op == 15 && (rn >= 8 && rn <= 11)) {
3708 /* Comparison, do nothing. */
3709 } else if (op == 15 && dp && ((rn & 0x1c) == 0x18 ||
3710 (rn & 0x1e) == 0x6)) {
3711 /* VCVT double to int: always integer result.
3712 * VCVT double to half precision is always a single
3713 * precision result.
3715 gen_mov_vreg_F0(0, rd);
3716 } else if (op == 15 && rn == 15) {
3717 /* conversion */
3718 gen_mov_vreg_F0(!dp, rd);
3719 } else {
3720 gen_mov_vreg_F0(dp, rd);
3723 /* break out of the loop if we have finished */
3724 if (veclen == 0)
3725 break;
3727 if (op == 15 && delta_m == 0) {
3728 /* single source one-many */
3729 while (veclen--) {
3730 rd = ((rd + delta_d) & (bank_mask - 1))
3731 | (rd & bank_mask);
3732 gen_mov_vreg_F0(dp, rd);
3734 break;
3736 /* Setup the next operands. */
3737 veclen--;
3738 rd = ((rd + delta_d) & (bank_mask - 1))
3739 | (rd & bank_mask);
3741 if (op == 15) {
3742 /* One source operand. */
3743 rm = ((rm + delta_m) & (bank_mask - 1))
3744 | (rm & bank_mask);
3745 gen_mov_F0_vreg(dp, rm);
3746 } else {
3747 /* Two source operands. */
3748 rn = ((rn + delta_d) & (bank_mask - 1))
3749 | (rn & bank_mask);
3750 gen_mov_F0_vreg(dp, rn);
3751 if (delta_m) {
3752 rm = ((rm + delta_m) & (bank_mask - 1))
3753 | (rm & bank_mask);
3754 gen_mov_F1_vreg(dp, rm);
3759 break;
3760 case 0xc:
3761 case 0xd:
3762 if ((insn & 0x03e00000) == 0x00400000) {
3763 /* two-register transfer */
3764 rn = (insn >> 16) & 0xf;
3765 rd = (insn >> 12) & 0xf;
3766 if (dp) {
3767 VFP_DREG_M(rm, insn);
3768 } else {
3769 rm = VFP_SREG_M(insn);
3772 if (insn & ARM_CP_RW_BIT) {
3773 /* vfp->arm */
3774 if (dp) {
3775 gen_mov_F0_vreg(0, rm * 2);
3776 tmp = gen_vfp_mrs();
3777 store_reg(s, rd, tmp);
3778 gen_mov_F0_vreg(0, rm * 2 + 1);
3779 tmp = gen_vfp_mrs();
3780 store_reg(s, rn, tmp);
3781 } else {
3782 gen_mov_F0_vreg(0, rm);
3783 tmp = gen_vfp_mrs();
3784 store_reg(s, rd, tmp);
3785 gen_mov_F0_vreg(0, rm + 1);
3786 tmp = gen_vfp_mrs();
3787 store_reg(s, rn, tmp);
3789 } else {
3790 /* arm->vfp */
3791 if (dp) {
3792 tmp = load_reg(s, rd);
3793 gen_vfp_msr(tmp);
3794 gen_mov_vreg_F0(0, rm * 2);
3795 tmp = load_reg(s, rn);
3796 gen_vfp_msr(tmp);
3797 gen_mov_vreg_F0(0, rm * 2 + 1);
3798 } else {
3799 tmp = load_reg(s, rd);
3800 gen_vfp_msr(tmp);
3801 gen_mov_vreg_F0(0, rm);
3802 tmp = load_reg(s, rn);
3803 gen_vfp_msr(tmp);
3804 gen_mov_vreg_F0(0, rm + 1);
3807 } else {
3808 /* Load/store */
3809 rn = (insn >> 16) & 0xf;
3810 if (dp)
3811 VFP_DREG_D(rd, insn);
3812 else
3813 rd = VFP_SREG_D(insn);
3814 if ((insn & 0x01200000) == 0x01000000) {
3815 /* Single load/store */
3816 offset = (insn & 0xff) << 2;
3817 if ((insn & (1 << 23)) == 0)
3818 offset = -offset;
3819 if (s->thumb && rn == 15) {
3820 /* This is actually UNPREDICTABLE */
3821 addr = tcg_temp_new_i32();
3822 tcg_gen_movi_i32(addr, s->pc & ~2);
3823 } else {
3824 addr = load_reg(s, rn);
3826 tcg_gen_addi_i32(addr, addr, offset);
3827 if (insn & (1 << 20)) {
3828 gen_vfp_ld(s, dp, addr);
3829 gen_mov_vreg_F0(dp, rd);
3830 } else {
3831 gen_mov_F0_vreg(dp, rd);
3832 gen_vfp_st(s, dp, addr);
3834 tcg_temp_free_i32(addr);
3835 } else {
3836 /* load/store multiple */
3837 int w = insn & (1 << 21);
3838 if (dp)
3839 n = (insn >> 1) & 0x7f;
3840 else
3841 n = insn & 0xff;
3843 if (w && !(((insn >> 23) ^ (insn >> 24)) & 1)) {
3844 /* P == U , W == 1 => UNDEF */
3845 return 1;
3847 if (n == 0 || (rd + n) > 32 || (dp && n > 16)) {
3848 /* UNPREDICTABLE cases for bad immediates: we choose to
3849 * UNDEF to avoid generating huge numbers of TCG ops
3851 return 1;
3853 if (rn == 15 && w) {
3854 /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
3855 return 1;
3858 if (s->thumb && rn == 15) {
3859 /* This is actually UNPREDICTABLE */
3860 addr = tcg_temp_new_i32();
3861 tcg_gen_movi_i32(addr, s->pc & ~2);
3862 } else {
3863 addr = load_reg(s, rn);
3865 if (insn & (1 << 24)) /* pre-decrement */
3866 tcg_gen_addi_i32(addr, addr, -((insn & 0xff) << 2));
3868 if (dp)
3869 offset = 8;
3870 else
3871 offset = 4;
3872 for (i = 0; i < n; i++) {
3873 if (insn & ARM_CP_RW_BIT) {
3874 /* load */
3875 gen_vfp_ld(s, dp, addr);
3876 gen_mov_vreg_F0(dp, rd + i);
3877 } else {
3878 /* store */
3879 gen_mov_F0_vreg(dp, rd + i);
3880 gen_vfp_st(s, dp, addr);
3882 tcg_gen_addi_i32(addr, addr, offset);
3884 if (w) {
3885 /* writeback */
3886 if (insn & (1 << 24))
3887 offset = -offset * n;
3888 else if (dp && (insn & 1))
3889 offset = 4;
3890 else
3891 offset = 0;
3893 if (offset != 0)
3894 tcg_gen_addi_i32(addr, addr, offset);
3895 store_reg(s, rn, addr);
3896 } else {
3897 tcg_temp_free_i32(addr);
3901 break;
3902 default:
3903 /* Should never happen. */
3904 return 1;
3906 return 0;
3909 static inline void gen_goto_tb(DisasContext *s, int n, target_ulong dest)
3911 TranslationBlock *tb;
3913 tb = s->tb;
3914 if ((tb->pc & TARGET_PAGE_MASK) == (dest & TARGET_PAGE_MASK)) {
3915 tcg_gen_goto_tb(n);
3916 gen_set_pc_im(s, dest);
3917 tcg_gen_exit_tb((uintptr_t)tb + n);
3918 } else {
3919 gen_set_pc_im(s, dest);
3920 tcg_gen_exit_tb(0);
3924 static inline void gen_jmp (DisasContext *s, uint32_t dest)
3926 if (unlikely(s->singlestep_enabled || s->ss_active)) {
3927 /* An indirect jump so that we still trigger the debug exception. */
3928 if (s->thumb)
3929 dest |= 1;
3930 gen_bx_im(s, dest);
3931 } else {
3932 gen_goto_tb(s, 0, dest);
3933 s->is_jmp = DISAS_TB_JUMP;
3937 static inline void gen_mulxy(TCGv_i32 t0, TCGv_i32 t1, int x, int y)
3939 if (x)
3940 tcg_gen_sari_i32(t0, t0, 16);
3941 else
3942 gen_sxth(t0);
3943 if (y)
3944 tcg_gen_sari_i32(t1, t1, 16);
3945 else
3946 gen_sxth(t1);
3947 tcg_gen_mul_i32(t0, t0, t1);
3950 /* Return the mask of PSR bits set by a MSR instruction. */
3951 static uint32_t msr_mask(CPUARMState *env, DisasContext *s, int flags, int spsr) {
3952 uint32_t mask;
3954 mask = 0;
3955 if (flags & (1 << 0))
3956 mask |= 0xff;
3957 if (flags & (1 << 1))
3958 mask |= 0xff00;
3959 if (flags & (1 << 2))
3960 mask |= 0xff0000;
3961 if (flags & (1 << 3))
3962 mask |= 0xff000000;
3964 /* Mask out undefined bits. */
3965 mask &= ~CPSR_RESERVED;
3966 if (!arm_feature(env, ARM_FEATURE_V4T))
3967 mask &= ~CPSR_T;
3968 if (!arm_feature(env, ARM_FEATURE_V5))
3969 mask &= ~CPSR_Q; /* V5TE in reality*/
3970 if (!arm_feature(env, ARM_FEATURE_V6))
3971 mask &= ~(CPSR_E | CPSR_GE);
3972 if (!arm_feature(env, ARM_FEATURE_THUMB2))
3973 mask &= ~CPSR_IT;
3974 /* Mask out execution state and reserved bits. */
3975 if (!spsr) {
3976 mask &= ~(CPSR_EXEC | CPSR_RESERVED);
3978 /* Mask out privileged bits. */
3979 if (IS_USER(s))
3980 mask &= CPSR_USER;
3981 return mask;
3984 /* Returns nonzero if access to the PSR is not permitted. Marks t0 as dead. */
3985 static int gen_set_psr(DisasContext *s, uint32_t mask, int spsr, TCGv_i32 t0)
3987 TCGv_i32 tmp;
3988 if (spsr) {
3989 /* ??? This is also undefined in system mode. */
3990 if (IS_USER(s))
3991 return 1;
3993 tmp = load_cpu_field(spsr);
3994 tcg_gen_andi_i32(tmp, tmp, ~mask);
3995 tcg_gen_andi_i32(t0, t0, mask);
3996 tcg_gen_or_i32(tmp, tmp, t0);
3997 store_cpu_field(tmp, spsr);
3998 } else {
3999 gen_set_cpsr(t0, mask);
4001 tcg_temp_free_i32(t0);
4002 gen_lookup_tb(s);
4003 return 0;
4006 /* Returns nonzero if access to the PSR is not permitted. */
4007 static int gen_set_psr_im(DisasContext *s, uint32_t mask, int spsr, uint32_t val)
4009 TCGv_i32 tmp;
4010 tmp = tcg_temp_new_i32();
4011 tcg_gen_movi_i32(tmp, val);
4012 return gen_set_psr(s, mask, spsr, tmp);
4015 /* Generate an old-style exception return. Marks pc as dead. */
4016 static void gen_exception_return(DisasContext *s, TCGv_i32 pc)
4018 TCGv_i32 tmp;
4019 store_reg(s, 15, pc);
4020 tmp = load_cpu_field(spsr);
4021 gen_set_cpsr(tmp, CPSR_ERET_MASK);
4022 tcg_temp_free_i32(tmp);
4023 s->is_jmp = DISAS_UPDATE;
4026 /* Generate a v6 exception return. Marks both values as dead. */
4027 static void gen_rfe(DisasContext *s, TCGv_i32 pc, TCGv_i32 cpsr)
4029 gen_set_cpsr(cpsr, CPSR_ERET_MASK);
4030 tcg_temp_free_i32(cpsr);
4031 store_reg(s, 15, pc);
4032 s->is_jmp = DISAS_UPDATE;
4035 static void gen_nop_hint(DisasContext *s, int val)
4037 switch (val) {
4038 case 3: /* wfi */
4039 gen_set_pc_im(s, s->pc);
4040 s->is_jmp = DISAS_WFI;
4041 break;
4042 case 2: /* wfe */
4043 gen_set_pc_im(s, s->pc);
4044 s->is_jmp = DISAS_WFE;
4045 break;
4046 case 4: /* sev */
4047 case 5: /* sevl */
4048 /* TODO: Implement SEV, SEVL and WFE. May help SMP performance. */
4049 default: /* nop */
4050 break;
4054 #define CPU_V001 cpu_V0, cpu_V0, cpu_V1
4056 static inline void gen_neon_add(int size, TCGv_i32 t0, TCGv_i32 t1)
4058 switch (size) {
4059 case 0: gen_helper_neon_add_u8(t0, t0, t1); break;
4060 case 1: gen_helper_neon_add_u16(t0, t0, t1); break;
4061 case 2: tcg_gen_add_i32(t0, t0, t1); break;
4062 default: abort();
4066 static inline void gen_neon_rsb(int size, TCGv_i32 t0, TCGv_i32 t1)
4068 switch (size) {
4069 case 0: gen_helper_neon_sub_u8(t0, t1, t0); break;
4070 case 1: gen_helper_neon_sub_u16(t0, t1, t0); break;
4071 case 2: tcg_gen_sub_i32(t0, t1, t0); break;
4072 default: return;
4076 /* 32-bit pairwise ops end up the same as the elementwise versions. */
4077 #define gen_helper_neon_pmax_s32 gen_helper_neon_max_s32
4078 #define gen_helper_neon_pmax_u32 gen_helper_neon_max_u32
4079 #define gen_helper_neon_pmin_s32 gen_helper_neon_min_s32
4080 #define gen_helper_neon_pmin_u32 gen_helper_neon_min_u32
4082 #define GEN_NEON_INTEGER_OP_ENV(name) do { \
4083 switch ((size << 1) | u) { \
4084 case 0: \
4085 gen_helper_neon_##name##_s8(tmp, cpu_env, tmp, tmp2); \
4086 break; \
4087 case 1: \
4088 gen_helper_neon_##name##_u8(tmp, cpu_env, tmp, tmp2); \
4089 break; \
4090 case 2: \
4091 gen_helper_neon_##name##_s16(tmp, cpu_env, tmp, tmp2); \
4092 break; \
4093 case 3: \
4094 gen_helper_neon_##name##_u16(tmp, cpu_env, tmp, tmp2); \
4095 break; \
4096 case 4: \
4097 gen_helper_neon_##name##_s32(tmp, cpu_env, tmp, tmp2); \
4098 break; \
4099 case 5: \
4100 gen_helper_neon_##name##_u32(tmp, cpu_env, tmp, tmp2); \
4101 break; \
4102 default: return 1; \
4103 }} while (0)
4105 #define GEN_NEON_INTEGER_OP(name) do { \
4106 switch ((size << 1) | u) { \
4107 case 0: \
4108 gen_helper_neon_##name##_s8(tmp, tmp, tmp2); \
4109 break; \
4110 case 1: \
4111 gen_helper_neon_##name##_u8(tmp, tmp, tmp2); \
4112 break; \
4113 case 2: \
4114 gen_helper_neon_##name##_s16(tmp, tmp, tmp2); \
4115 break; \
4116 case 3: \
4117 gen_helper_neon_##name##_u16(tmp, tmp, tmp2); \
4118 break; \
4119 case 4: \
4120 gen_helper_neon_##name##_s32(tmp, tmp, tmp2); \
4121 break; \
4122 case 5: \
4123 gen_helper_neon_##name##_u32(tmp, tmp, tmp2); \
4124 break; \
4125 default: return 1; \
4126 }} while (0)
4128 static TCGv_i32 neon_load_scratch(int scratch)
4130 TCGv_i32 tmp = tcg_temp_new_i32();
4131 tcg_gen_ld_i32(tmp, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4132 return tmp;
4135 static void neon_store_scratch(int scratch, TCGv_i32 var)
4137 tcg_gen_st_i32(var, cpu_env, offsetof(CPUARMState, vfp.scratch[scratch]));
4138 tcg_temp_free_i32(var);
4141 static inline TCGv_i32 neon_get_scalar(int size, int reg)
4143 TCGv_i32 tmp;
4144 if (size == 1) {
4145 tmp = neon_load_reg(reg & 7, reg >> 4);
4146 if (reg & 8) {
4147 gen_neon_dup_high16(tmp);
4148 } else {
4149 gen_neon_dup_low16(tmp);
4151 } else {
4152 tmp = neon_load_reg(reg & 15, reg >> 4);
4154 return tmp;
4157 static int gen_neon_unzip(int rd, int rm, int size, int q)
4159 TCGv_i32 tmp, tmp2;
4160 if (!q && size == 2) {
4161 return 1;
4163 tmp = tcg_const_i32(rd);
4164 tmp2 = tcg_const_i32(rm);
4165 if (q) {
4166 switch (size) {
4167 case 0:
4168 gen_helper_neon_qunzip8(cpu_env, tmp, tmp2);
4169 break;
4170 case 1:
4171 gen_helper_neon_qunzip16(cpu_env, tmp, tmp2);
4172 break;
4173 case 2:
4174 gen_helper_neon_qunzip32(cpu_env, tmp, tmp2);
4175 break;
4176 default:
4177 abort();
4179 } else {
4180 switch (size) {
4181 case 0:
4182 gen_helper_neon_unzip8(cpu_env, tmp, tmp2);
4183 break;
4184 case 1:
4185 gen_helper_neon_unzip16(cpu_env, tmp, tmp2);
4186 break;
4187 default:
4188 abort();
4191 tcg_temp_free_i32(tmp);
4192 tcg_temp_free_i32(tmp2);
4193 return 0;
4196 static int gen_neon_zip(int rd, int rm, int size, int q)
4198 TCGv_i32 tmp, tmp2;
4199 if (!q && size == 2) {
4200 return 1;
4202 tmp = tcg_const_i32(rd);
4203 tmp2 = tcg_const_i32(rm);
4204 if (q) {
4205 switch (size) {
4206 case 0:
4207 gen_helper_neon_qzip8(cpu_env, tmp, tmp2);
4208 break;
4209 case 1:
4210 gen_helper_neon_qzip16(cpu_env, tmp, tmp2);
4211 break;
4212 case 2:
4213 gen_helper_neon_qzip32(cpu_env, tmp, tmp2);
4214 break;
4215 default:
4216 abort();
4218 } else {
4219 switch (size) {
4220 case 0:
4221 gen_helper_neon_zip8(cpu_env, tmp, tmp2);
4222 break;
4223 case 1:
4224 gen_helper_neon_zip16(cpu_env, tmp, tmp2);
4225 break;
4226 default:
4227 abort();
4230 tcg_temp_free_i32(tmp);
4231 tcg_temp_free_i32(tmp2);
4232 return 0;
4235 static void gen_neon_trn_u8(TCGv_i32 t0, TCGv_i32 t1)
4237 TCGv_i32 rd, tmp;
4239 rd = tcg_temp_new_i32();
4240 tmp = tcg_temp_new_i32();
4242 tcg_gen_shli_i32(rd, t0, 8);
4243 tcg_gen_andi_i32(rd, rd, 0xff00ff00);
4244 tcg_gen_andi_i32(tmp, t1, 0x00ff00ff);
4245 tcg_gen_or_i32(rd, rd, tmp);
4247 tcg_gen_shri_i32(t1, t1, 8);
4248 tcg_gen_andi_i32(t1, t1, 0x00ff00ff);
4249 tcg_gen_andi_i32(tmp, t0, 0xff00ff00);
4250 tcg_gen_or_i32(t1, t1, tmp);
4251 tcg_gen_mov_i32(t0, rd);
4253 tcg_temp_free_i32(tmp);
4254 tcg_temp_free_i32(rd);
4257 static void gen_neon_trn_u16(TCGv_i32 t0, TCGv_i32 t1)
4259 TCGv_i32 rd, tmp;
4261 rd = tcg_temp_new_i32();
4262 tmp = tcg_temp_new_i32();
4264 tcg_gen_shli_i32(rd, t0, 16);
4265 tcg_gen_andi_i32(tmp, t1, 0xffff);
4266 tcg_gen_or_i32(rd, rd, tmp);
4267 tcg_gen_shri_i32(t1, t1, 16);
4268 tcg_gen_andi_i32(tmp, t0, 0xffff0000);
4269 tcg_gen_or_i32(t1, t1, tmp);
4270 tcg_gen_mov_i32(t0, rd);
4272 tcg_temp_free_i32(tmp);
4273 tcg_temp_free_i32(rd);
4277 static struct {
4278 int nregs;
4279 int interleave;
4280 int spacing;
4281 } neon_ls_element_type[11] = {
4282 {4, 4, 1},
4283 {4, 4, 2},
4284 {4, 1, 1},
4285 {4, 2, 1},
4286 {3, 3, 1},
4287 {3, 3, 2},
4288 {3, 1, 1},
4289 {1, 1, 1},
4290 {2, 2, 1},
4291 {2, 2, 2},
4292 {2, 1, 1}
4295 /* Translate a NEON load/store element instruction. Return nonzero if the
4296 instruction is invalid. */
4297 static int disas_neon_ls_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
4299 int rd, rn, rm;
4300 int op;
4301 int nregs;
4302 int interleave;
4303 int spacing;
4304 int stride;
4305 int size;
4306 int reg;
4307 int pass;
4308 int load;
4309 int shift;
4310 int n;
4311 TCGv_i32 addr;
4312 TCGv_i32 tmp;
4313 TCGv_i32 tmp2;
4314 TCGv_i64 tmp64;
4316 /* FIXME: this access check should not take precedence over UNDEF
4317 * for invalid encodings; we will generate incorrect syndrome information
4318 * for attempts to execute invalid vfp/neon encodings with FP disabled.
4320 if (!s->cpacr_fpen) {
4321 gen_exception_insn(s, 4, EXCP_UDEF,
4322 syn_fp_access_trap(1, 0xe, s->thumb));
4323 return 0;
4326 if (!s->vfp_enabled)
4327 return 1;
4328 VFP_DREG_D(rd, insn);
4329 rn = (insn >> 16) & 0xf;
4330 rm = insn & 0xf;
4331 load = (insn & (1 << 21)) != 0;
4332 if ((insn & (1 << 23)) == 0) {
4333 /* Load store all elements. */
4334 op = (insn >> 8) & 0xf;
4335 size = (insn >> 6) & 3;
4336 if (op > 10)
4337 return 1;
4338 /* Catch UNDEF cases for bad values of align field */
4339 switch (op & 0xc) {
4340 case 4:
4341 if (((insn >> 5) & 1) == 1) {
4342 return 1;
4344 break;
4345 case 8:
4346 if (((insn >> 4) & 3) == 3) {
4347 return 1;
4349 break;
4350 default:
4351 break;
4353 nregs = neon_ls_element_type[op].nregs;
4354 interleave = neon_ls_element_type[op].interleave;
4355 spacing = neon_ls_element_type[op].spacing;
4356 if (size == 3 && (interleave | spacing) != 1)
4357 return 1;
4358 addr = tcg_temp_new_i32();
4359 load_reg_var(s, addr, rn);
4360 stride = (1 << size) * interleave;
4361 for (reg = 0; reg < nregs; reg++) {
4362 if (interleave > 2 || (interleave == 2 && nregs == 2)) {
4363 load_reg_var(s, addr, rn);
4364 tcg_gen_addi_i32(addr, addr, (1 << size) * reg);
4365 } else if (interleave == 2 && nregs == 4 && reg == 2) {
4366 load_reg_var(s, addr, rn);
4367 tcg_gen_addi_i32(addr, addr, 1 << size);
4369 if (size == 3) {
4370 tmp64 = tcg_temp_new_i64();
4371 if (load) {
4372 gen_aa32_ld64(tmp64, addr, get_mem_index(s));
4373 neon_store_reg64(tmp64, rd);
4374 } else {
4375 neon_load_reg64(tmp64, rd);
4376 gen_aa32_st64(tmp64, addr, get_mem_index(s));
4378 tcg_temp_free_i64(tmp64);
4379 tcg_gen_addi_i32(addr, addr, stride);
4380 } else {
4381 for (pass = 0; pass < 2; pass++) {
4382 if (size == 2) {
4383 if (load) {
4384 tmp = tcg_temp_new_i32();
4385 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
4386 neon_store_reg(rd, pass, tmp);
4387 } else {
4388 tmp = neon_load_reg(rd, pass);
4389 gen_aa32_st32(tmp, addr, get_mem_index(s));
4390 tcg_temp_free_i32(tmp);
4392 tcg_gen_addi_i32(addr, addr, stride);
4393 } else if (size == 1) {
4394 if (load) {
4395 tmp = tcg_temp_new_i32();
4396 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
4397 tcg_gen_addi_i32(addr, addr, stride);
4398 tmp2 = tcg_temp_new_i32();
4399 gen_aa32_ld16u(tmp2, addr, get_mem_index(s));
4400 tcg_gen_addi_i32(addr, addr, stride);
4401 tcg_gen_shli_i32(tmp2, tmp2, 16);
4402 tcg_gen_or_i32(tmp, tmp, tmp2);
4403 tcg_temp_free_i32(tmp2);
4404 neon_store_reg(rd, pass, tmp);
4405 } else {
4406 tmp = neon_load_reg(rd, pass);
4407 tmp2 = tcg_temp_new_i32();
4408 tcg_gen_shri_i32(tmp2, tmp, 16);
4409 gen_aa32_st16(tmp, addr, get_mem_index(s));
4410 tcg_temp_free_i32(tmp);
4411 tcg_gen_addi_i32(addr, addr, stride);
4412 gen_aa32_st16(tmp2, addr, get_mem_index(s));
4413 tcg_temp_free_i32(tmp2);
4414 tcg_gen_addi_i32(addr, addr, stride);
4416 } else /* size == 0 */ {
4417 if (load) {
4418 TCGV_UNUSED_I32(tmp2);
4419 for (n = 0; n < 4; n++) {
4420 tmp = tcg_temp_new_i32();
4421 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
4422 tcg_gen_addi_i32(addr, addr, stride);
4423 if (n == 0) {
4424 tmp2 = tmp;
4425 } else {
4426 tcg_gen_shli_i32(tmp, tmp, n * 8);
4427 tcg_gen_or_i32(tmp2, tmp2, tmp);
4428 tcg_temp_free_i32(tmp);
4431 neon_store_reg(rd, pass, tmp2);
4432 } else {
4433 tmp2 = neon_load_reg(rd, pass);
4434 for (n = 0; n < 4; n++) {
4435 tmp = tcg_temp_new_i32();
4436 if (n == 0) {
4437 tcg_gen_mov_i32(tmp, tmp2);
4438 } else {
4439 tcg_gen_shri_i32(tmp, tmp2, n * 8);
4441 gen_aa32_st8(tmp, addr, get_mem_index(s));
4442 tcg_temp_free_i32(tmp);
4443 tcg_gen_addi_i32(addr, addr, stride);
4445 tcg_temp_free_i32(tmp2);
4450 rd += spacing;
4452 tcg_temp_free_i32(addr);
4453 stride = nregs * 8;
4454 } else {
4455 size = (insn >> 10) & 3;
4456 if (size == 3) {
4457 /* Load single element to all lanes. */
4458 int a = (insn >> 4) & 1;
4459 if (!load) {
4460 return 1;
4462 size = (insn >> 6) & 3;
4463 nregs = ((insn >> 8) & 3) + 1;
4465 if (size == 3) {
4466 if (nregs != 4 || a == 0) {
4467 return 1;
4469 /* For VLD4 size==3 a == 1 means 32 bits at 16 byte alignment */
4470 size = 2;
4472 if (nregs == 1 && a == 1 && size == 0) {
4473 return 1;
4475 if (nregs == 3 && a == 1) {
4476 return 1;
4478 addr = tcg_temp_new_i32();
4479 load_reg_var(s, addr, rn);
4480 if (nregs == 1) {
4481 /* VLD1 to all lanes: bit 5 indicates how many Dregs to write */
4482 tmp = gen_load_and_replicate(s, addr, size);
4483 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4484 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4485 if (insn & (1 << 5)) {
4486 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 0));
4487 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd + 1, 1));
4489 tcg_temp_free_i32(tmp);
4490 } else {
4491 /* VLD2/3/4 to all lanes: bit 5 indicates register stride */
4492 stride = (insn & (1 << 5)) ? 2 : 1;
4493 for (reg = 0; reg < nregs; reg++) {
4494 tmp = gen_load_and_replicate(s, addr, size);
4495 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 0));
4496 tcg_gen_st_i32(tmp, cpu_env, neon_reg_offset(rd, 1));
4497 tcg_temp_free_i32(tmp);
4498 tcg_gen_addi_i32(addr, addr, 1 << size);
4499 rd += stride;
4502 tcg_temp_free_i32(addr);
4503 stride = (1 << size) * nregs;
4504 } else {
4505 /* Single element. */
4506 int idx = (insn >> 4) & 0xf;
4507 pass = (insn >> 7) & 1;
4508 switch (size) {
4509 case 0:
4510 shift = ((insn >> 5) & 3) * 8;
4511 stride = 1;
4512 break;
4513 case 1:
4514 shift = ((insn >> 6) & 1) * 16;
4515 stride = (insn & (1 << 5)) ? 2 : 1;
4516 break;
4517 case 2:
4518 shift = 0;
4519 stride = (insn & (1 << 6)) ? 2 : 1;
4520 break;
4521 default:
4522 abort();
4524 nregs = ((insn >> 8) & 3) + 1;
4525 /* Catch the UNDEF cases. This is unavoidably a bit messy. */
4526 switch (nregs) {
4527 case 1:
4528 if (((idx & (1 << size)) != 0) ||
4529 (size == 2 && ((idx & 3) == 1 || (idx & 3) == 2))) {
4530 return 1;
4532 break;
4533 case 3:
4534 if ((idx & 1) != 0) {
4535 return 1;
4537 /* fall through */
4538 case 2:
4539 if (size == 2 && (idx & 2) != 0) {
4540 return 1;
4542 break;
4543 case 4:
4544 if ((size == 2) && ((idx & 3) == 3)) {
4545 return 1;
4547 break;
4548 default:
4549 abort();
4551 if ((rd + stride * (nregs - 1)) > 31) {
4552 /* Attempts to write off the end of the register file
4553 * are UNPREDICTABLE; we choose to UNDEF because otherwise
4554 * the neon_load_reg() would write off the end of the array.
4556 return 1;
4558 addr = tcg_temp_new_i32();
4559 load_reg_var(s, addr, rn);
4560 for (reg = 0; reg < nregs; reg++) {
4561 if (load) {
4562 tmp = tcg_temp_new_i32();
4563 switch (size) {
4564 case 0:
4565 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
4566 break;
4567 case 1:
4568 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
4569 break;
4570 case 2:
4571 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
4572 break;
4573 default: /* Avoid compiler warnings. */
4574 abort();
4576 if (size != 2) {
4577 tmp2 = neon_load_reg(rd, pass);
4578 tcg_gen_deposit_i32(tmp, tmp2, tmp,
4579 shift, size ? 16 : 8);
4580 tcg_temp_free_i32(tmp2);
4582 neon_store_reg(rd, pass, tmp);
4583 } else { /* Store */
4584 tmp = neon_load_reg(rd, pass);
4585 if (shift)
4586 tcg_gen_shri_i32(tmp, tmp, shift);
4587 switch (size) {
4588 case 0:
4589 gen_aa32_st8(tmp, addr, get_mem_index(s));
4590 break;
4591 case 1:
4592 gen_aa32_st16(tmp, addr, get_mem_index(s));
4593 break;
4594 case 2:
4595 gen_aa32_st32(tmp, addr, get_mem_index(s));
4596 break;
4598 tcg_temp_free_i32(tmp);
4600 rd += stride;
4601 tcg_gen_addi_i32(addr, addr, 1 << size);
4603 tcg_temp_free_i32(addr);
4604 stride = nregs * (1 << size);
4607 if (rm != 15) {
4608 TCGv_i32 base;
4610 base = load_reg(s, rn);
4611 if (rm == 13) {
4612 tcg_gen_addi_i32(base, base, stride);
4613 } else {
4614 TCGv_i32 index;
4615 index = load_reg(s, rm);
4616 tcg_gen_add_i32(base, base, index);
4617 tcg_temp_free_i32(index);
4619 store_reg(s, rn, base);
4621 return 0;
4624 /* Bitwise select. dest = c ? t : f. Clobbers T and F. */
4625 static void gen_neon_bsl(TCGv_i32 dest, TCGv_i32 t, TCGv_i32 f, TCGv_i32 c)
4627 tcg_gen_and_i32(t, t, c);
4628 tcg_gen_andc_i32(f, f, c);
4629 tcg_gen_or_i32(dest, t, f);
4632 static inline void gen_neon_narrow(int size, TCGv_i32 dest, TCGv_i64 src)
4634 switch (size) {
4635 case 0: gen_helper_neon_narrow_u8(dest, src); break;
4636 case 1: gen_helper_neon_narrow_u16(dest, src); break;
4637 case 2: tcg_gen_trunc_i64_i32(dest, src); break;
4638 default: abort();
4642 static inline void gen_neon_narrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4644 switch (size) {
4645 case 0: gen_helper_neon_narrow_sat_s8(dest, cpu_env, src); break;
4646 case 1: gen_helper_neon_narrow_sat_s16(dest, cpu_env, src); break;
4647 case 2: gen_helper_neon_narrow_sat_s32(dest, cpu_env, src); break;
4648 default: abort();
4652 static inline void gen_neon_narrow_satu(int size, TCGv_i32 dest, TCGv_i64 src)
4654 switch (size) {
4655 case 0: gen_helper_neon_narrow_sat_u8(dest, cpu_env, src); break;
4656 case 1: gen_helper_neon_narrow_sat_u16(dest, cpu_env, src); break;
4657 case 2: gen_helper_neon_narrow_sat_u32(dest, cpu_env, src); break;
4658 default: abort();
4662 static inline void gen_neon_unarrow_sats(int size, TCGv_i32 dest, TCGv_i64 src)
4664 switch (size) {
4665 case 0: gen_helper_neon_unarrow_sat8(dest, cpu_env, src); break;
4666 case 1: gen_helper_neon_unarrow_sat16(dest, cpu_env, src); break;
4667 case 2: gen_helper_neon_unarrow_sat32(dest, cpu_env, src); break;
4668 default: abort();
4672 static inline void gen_neon_shift_narrow(int size, TCGv_i32 var, TCGv_i32 shift,
4673 int q, int u)
4675 if (q) {
4676 if (u) {
4677 switch (size) {
4678 case 1: gen_helper_neon_rshl_u16(var, var, shift); break;
4679 case 2: gen_helper_neon_rshl_u32(var, var, shift); break;
4680 default: abort();
4682 } else {
4683 switch (size) {
4684 case 1: gen_helper_neon_rshl_s16(var, var, shift); break;
4685 case 2: gen_helper_neon_rshl_s32(var, var, shift); break;
4686 default: abort();
4689 } else {
4690 if (u) {
4691 switch (size) {
4692 case 1: gen_helper_neon_shl_u16(var, var, shift); break;
4693 case 2: gen_helper_neon_shl_u32(var, var, shift); break;
4694 default: abort();
4696 } else {
4697 switch (size) {
4698 case 1: gen_helper_neon_shl_s16(var, var, shift); break;
4699 case 2: gen_helper_neon_shl_s32(var, var, shift); break;
4700 default: abort();
4706 static inline void gen_neon_widen(TCGv_i64 dest, TCGv_i32 src, int size, int u)
4708 if (u) {
4709 switch (size) {
4710 case 0: gen_helper_neon_widen_u8(dest, src); break;
4711 case 1: gen_helper_neon_widen_u16(dest, src); break;
4712 case 2: tcg_gen_extu_i32_i64(dest, src); break;
4713 default: abort();
4715 } else {
4716 switch (size) {
4717 case 0: gen_helper_neon_widen_s8(dest, src); break;
4718 case 1: gen_helper_neon_widen_s16(dest, src); break;
4719 case 2: tcg_gen_ext_i32_i64(dest, src); break;
4720 default: abort();
4723 tcg_temp_free_i32(src);
4726 static inline void gen_neon_addl(int size)
4728 switch (size) {
4729 case 0: gen_helper_neon_addl_u16(CPU_V001); break;
4730 case 1: gen_helper_neon_addl_u32(CPU_V001); break;
4731 case 2: tcg_gen_add_i64(CPU_V001); break;
4732 default: abort();
4736 static inline void gen_neon_subl(int size)
4738 switch (size) {
4739 case 0: gen_helper_neon_subl_u16(CPU_V001); break;
4740 case 1: gen_helper_neon_subl_u32(CPU_V001); break;
4741 case 2: tcg_gen_sub_i64(CPU_V001); break;
4742 default: abort();
4746 static inline void gen_neon_negl(TCGv_i64 var, int size)
4748 switch (size) {
4749 case 0: gen_helper_neon_negl_u16(var, var); break;
4750 case 1: gen_helper_neon_negl_u32(var, var); break;
4751 case 2:
4752 tcg_gen_neg_i64(var, var);
4753 break;
4754 default: abort();
4758 static inline void gen_neon_addl_saturate(TCGv_i64 op0, TCGv_i64 op1, int size)
4760 switch (size) {
4761 case 1: gen_helper_neon_addl_saturate_s32(op0, cpu_env, op0, op1); break;
4762 case 2: gen_helper_neon_addl_saturate_s64(op0, cpu_env, op0, op1); break;
4763 default: abort();
4767 static inline void gen_neon_mull(TCGv_i64 dest, TCGv_i32 a, TCGv_i32 b,
4768 int size, int u)
4770 TCGv_i64 tmp;
4772 switch ((size << 1) | u) {
4773 case 0: gen_helper_neon_mull_s8(dest, a, b); break;
4774 case 1: gen_helper_neon_mull_u8(dest, a, b); break;
4775 case 2: gen_helper_neon_mull_s16(dest, a, b); break;
4776 case 3: gen_helper_neon_mull_u16(dest, a, b); break;
4777 case 4:
4778 tmp = gen_muls_i64_i32(a, b);
4779 tcg_gen_mov_i64(dest, tmp);
4780 tcg_temp_free_i64(tmp);
4781 break;
4782 case 5:
4783 tmp = gen_mulu_i64_i32(a, b);
4784 tcg_gen_mov_i64(dest, tmp);
4785 tcg_temp_free_i64(tmp);
4786 break;
4787 default: abort();
4790 /* gen_helper_neon_mull_[su]{8|16} do not free their parameters.
4791 Don't forget to clean them now. */
4792 if (size < 2) {
4793 tcg_temp_free_i32(a);
4794 tcg_temp_free_i32(b);
4798 static void gen_neon_narrow_op(int op, int u, int size,
4799 TCGv_i32 dest, TCGv_i64 src)
4801 if (op) {
4802 if (u) {
4803 gen_neon_unarrow_sats(size, dest, src);
4804 } else {
4805 gen_neon_narrow(size, dest, src);
4807 } else {
4808 if (u) {
4809 gen_neon_narrow_satu(size, dest, src);
4810 } else {
4811 gen_neon_narrow_sats(size, dest, src);
4816 /* Symbolic constants for op fields for Neon 3-register same-length.
4817 * The values correspond to bits [11:8,4]; see the ARM ARM DDI0406B
4818 * table A7-9.
4820 #define NEON_3R_VHADD 0
4821 #define NEON_3R_VQADD 1
4822 #define NEON_3R_VRHADD 2
4823 #define NEON_3R_LOGIC 3 /* VAND,VBIC,VORR,VMOV,VORN,VEOR,VBIF,VBIT,VBSL */
4824 #define NEON_3R_VHSUB 4
4825 #define NEON_3R_VQSUB 5
4826 #define NEON_3R_VCGT 6
4827 #define NEON_3R_VCGE 7
4828 #define NEON_3R_VSHL 8
4829 #define NEON_3R_VQSHL 9
4830 #define NEON_3R_VRSHL 10
4831 #define NEON_3R_VQRSHL 11
4832 #define NEON_3R_VMAX 12
4833 #define NEON_3R_VMIN 13
4834 #define NEON_3R_VABD 14
4835 #define NEON_3R_VABA 15
4836 #define NEON_3R_VADD_VSUB 16
4837 #define NEON_3R_VTST_VCEQ 17
4838 #define NEON_3R_VML 18 /* VMLA, VMLAL, VMLS, VMLSL */
4839 #define NEON_3R_VMUL 19
4840 #define NEON_3R_VPMAX 20
4841 #define NEON_3R_VPMIN 21
4842 #define NEON_3R_VQDMULH_VQRDMULH 22
4843 #define NEON_3R_VPADD 23
4844 #define NEON_3R_SHA 24 /* SHA1C,SHA1P,SHA1M,SHA1SU0,SHA256H{2},SHA256SU1 */
4845 #define NEON_3R_VFM 25 /* VFMA, VFMS : float fused multiply-add */
4846 #define NEON_3R_FLOAT_ARITH 26 /* float VADD, VSUB, VPADD, VABD */
4847 #define NEON_3R_FLOAT_MULTIPLY 27 /* float VMLA, VMLS, VMUL */
4848 #define NEON_3R_FLOAT_CMP 28 /* float VCEQ, VCGE, VCGT */
4849 #define NEON_3R_FLOAT_ACMP 29 /* float VACGE, VACGT, VACLE, VACLT */
4850 #define NEON_3R_FLOAT_MINMAX 30 /* float VMIN, VMAX */
4851 #define NEON_3R_FLOAT_MISC 31 /* float VRECPS, VRSQRTS, VMAXNM/MINNM */
4853 static const uint8_t neon_3r_sizes[] = {
4854 [NEON_3R_VHADD] = 0x7,
4855 [NEON_3R_VQADD] = 0xf,
4856 [NEON_3R_VRHADD] = 0x7,
4857 [NEON_3R_LOGIC] = 0xf, /* size field encodes op type */
4858 [NEON_3R_VHSUB] = 0x7,
4859 [NEON_3R_VQSUB] = 0xf,
4860 [NEON_3R_VCGT] = 0x7,
4861 [NEON_3R_VCGE] = 0x7,
4862 [NEON_3R_VSHL] = 0xf,
4863 [NEON_3R_VQSHL] = 0xf,
4864 [NEON_3R_VRSHL] = 0xf,
4865 [NEON_3R_VQRSHL] = 0xf,
4866 [NEON_3R_VMAX] = 0x7,
4867 [NEON_3R_VMIN] = 0x7,
4868 [NEON_3R_VABD] = 0x7,
4869 [NEON_3R_VABA] = 0x7,
4870 [NEON_3R_VADD_VSUB] = 0xf,
4871 [NEON_3R_VTST_VCEQ] = 0x7,
4872 [NEON_3R_VML] = 0x7,
4873 [NEON_3R_VMUL] = 0x7,
4874 [NEON_3R_VPMAX] = 0x7,
4875 [NEON_3R_VPMIN] = 0x7,
4876 [NEON_3R_VQDMULH_VQRDMULH] = 0x6,
4877 [NEON_3R_VPADD] = 0x7,
4878 [NEON_3R_SHA] = 0xf, /* size field encodes op type */
4879 [NEON_3R_VFM] = 0x5, /* size bit 1 encodes op */
4880 [NEON_3R_FLOAT_ARITH] = 0x5, /* size bit 1 encodes op */
4881 [NEON_3R_FLOAT_MULTIPLY] = 0x5, /* size bit 1 encodes op */
4882 [NEON_3R_FLOAT_CMP] = 0x5, /* size bit 1 encodes op */
4883 [NEON_3R_FLOAT_ACMP] = 0x5, /* size bit 1 encodes op */
4884 [NEON_3R_FLOAT_MINMAX] = 0x5, /* size bit 1 encodes op */
4885 [NEON_3R_FLOAT_MISC] = 0x5, /* size bit 1 encodes op */
4888 /* Symbolic constants for op fields for Neon 2-register miscellaneous.
4889 * The values correspond to bits [17:16,10:7]; see the ARM ARM DDI0406B
4890 * table A7-13.
4892 #define NEON_2RM_VREV64 0
4893 #define NEON_2RM_VREV32 1
4894 #define NEON_2RM_VREV16 2
4895 #define NEON_2RM_VPADDL 4
4896 #define NEON_2RM_VPADDL_U 5
4897 #define NEON_2RM_AESE 6 /* Includes AESD */
4898 #define NEON_2RM_AESMC 7 /* Includes AESIMC */
4899 #define NEON_2RM_VCLS 8
4900 #define NEON_2RM_VCLZ 9
4901 #define NEON_2RM_VCNT 10
4902 #define NEON_2RM_VMVN 11
4903 #define NEON_2RM_VPADAL 12
4904 #define NEON_2RM_VPADAL_U 13
4905 #define NEON_2RM_VQABS 14
4906 #define NEON_2RM_VQNEG 15
4907 #define NEON_2RM_VCGT0 16
4908 #define NEON_2RM_VCGE0 17
4909 #define NEON_2RM_VCEQ0 18
4910 #define NEON_2RM_VCLE0 19
4911 #define NEON_2RM_VCLT0 20
4912 #define NEON_2RM_SHA1H 21
4913 #define NEON_2RM_VABS 22
4914 #define NEON_2RM_VNEG 23
4915 #define NEON_2RM_VCGT0_F 24
4916 #define NEON_2RM_VCGE0_F 25
4917 #define NEON_2RM_VCEQ0_F 26
4918 #define NEON_2RM_VCLE0_F 27
4919 #define NEON_2RM_VCLT0_F 28
4920 #define NEON_2RM_VABS_F 30
4921 #define NEON_2RM_VNEG_F 31
4922 #define NEON_2RM_VSWP 32
4923 #define NEON_2RM_VTRN 33
4924 #define NEON_2RM_VUZP 34
4925 #define NEON_2RM_VZIP 35
4926 #define NEON_2RM_VMOVN 36 /* Includes VQMOVN, VQMOVUN */
4927 #define NEON_2RM_VQMOVN 37 /* Includes VQMOVUN */
4928 #define NEON_2RM_VSHLL 38
4929 #define NEON_2RM_SHA1SU1 39 /* Includes SHA256SU0 */
4930 #define NEON_2RM_VRINTN 40
4931 #define NEON_2RM_VRINTX 41
4932 #define NEON_2RM_VRINTA 42
4933 #define NEON_2RM_VRINTZ 43
4934 #define NEON_2RM_VCVT_F16_F32 44
4935 #define NEON_2RM_VRINTM 45
4936 #define NEON_2RM_VCVT_F32_F16 46
4937 #define NEON_2RM_VRINTP 47
4938 #define NEON_2RM_VCVTAU 48
4939 #define NEON_2RM_VCVTAS 49
4940 #define NEON_2RM_VCVTNU 50
4941 #define NEON_2RM_VCVTNS 51
4942 #define NEON_2RM_VCVTPU 52
4943 #define NEON_2RM_VCVTPS 53
4944 #define NEON_2RM_VCVTMU 54
4945 #define NEON_2RM_VCVTMS 55
4946 #define NEON_2RM_VRECPE 56
4947 #define NEON_2RM_VRSQRTE 57
4948 #define NEON_2RM_VRECPE_F 58
4949 #define NEON_2RM_VRSQRTE_F 59
4950 #define NEON_2RM_VCVT_FS 60
4951 #define NEON_2RM_VCVT_FU 61
4952 #define NEON_2RM_VCVT_SF 62
4953 #define NEON_2RM_VCVT_UF 63
4955 static int neon_2rm_is_float_op(int op)
4957 /* Return true if this neon 2reg-misc op is float-to-float */
4958 return (op == NEON_2RM_VABS_F || op == NEON_2RM_VNEG_F ||
4959 (op >= NEON_2RM_VRINTN && op <= NEON_2RM_VRINTZ) ||
4960 op == NEON_2RM_VRINTM ||
4961 (op >= NEON_2RM_VRINTP && op <= NEON_2RM_VCVTMS) ||
4962 op >= NEON_2RM_VRECPE_F);
4965 /* Each entry in this array has bit n set if the insn allows
4966 * size value n (otherwise it will UNDEF). Since unallocated
4967 * op values will have no bits set they always UNDEF.
4969 static const uint8_t neon_2rm_sizes[] = {
4970 [NEON_2RM_VREV64] = 0x7,
4971 [NEON_2RM_VREV32] = 0x3,
4972 [NEON_2RM_VREV16] = 0x1,
4973 [NEON_2RM_VPADDL] = 0x7,
4974 [NEON_2RM_VPADDL_U] = 0x7,
4975 [NEON_2RM_AESE] = 0x1,
4976 [NEON_2RM_AESMC] = 0x1,
4977 [NEON_2RM_VCLS] = 0x7,
4978 [NEON_2RM_VCLZ] = 0x7,
4979 [NEON_2RM_VCNT] = 0x1,
4980 [NEON_2RM_VMVN] = 0x1,
4981 [NEON_2RM_VPADAL] = 0x7,
4982 [NEON_2RM_VPADAL_U] = 0x7,
4983 [NEON_2RM_VQABS] = 0x7,
4984 [NEON_2RM_VQNEG] = 0x7,
4985 [NEON_2RM_VCGT0] = 0x7,
4986 [NEON_2RM_VCGE0] = 0x7,
4987 [NEON_2RM_VCEQ0] = 0x7,
4988 [NEON_2RM_VCLE0] = 0x7,
4989 [NEON_2RM_VCLT0] = 0x7,
4990 [NEON_2RM_SHA1H] = 0x4,
4991 [NEON_2RM_VABS] = 0x7,
4992 [NEON_2RM_VNEG] = 0x7,
4993 [NEON_2RM_VCGT0_F] = 0x4,
4994 [NEON_2RM_VCGE0_F] = 0x4,
4995 [NEON_2RM_VCEQ0_F] = 0x4,
4996 [NEON_2RM_VCLE0_F] = 0x4,
4997 [NEON_2RM_VCLT0_F] = 0x4,
4998 [NEON_2RM_VABS_F] = 0x4,
4999 [NEON_2RM_VNEG_F] = 0x4,
5000 [NEON_2RM_VSWP] = 0x1,
5001 [NEON_2RM_VTRN] = 0x7,
5002 [NEON_2RM_VUZP] = 0x7,
5003 [NEON_2RM_VZIP] = 0x7,
5004 [NEON_2RM_VMOVN] = 0x7,
5005 [NEON_2RM_VQMOVN] = 0x7,
5006 [NEON_2RM_VSHLL] = 0x7,
5007 [NEON_2RM_SHA1SU1] = 0x4,
5008 [NEON_2RM_VRINTN] = 0x4,
5009 [NEON_2RM_VRINTX] = 0x4,
5010 [NEON_2RM_VRINTA] = 0x4,
5011 [NEON_2RM_VRINTZ] = 0x4,
5012 [NEON_2RM_VCVT_F16_F32] = 0x2,
5013 [NEON_2RM_VRINTM] = 0x4,
5014 [NEON_2RM_VCVT_F32_F16] = 0x2,
5015 [NEON_2RM_VRINTP] = 0x4,
5016 [NEON_2RM_VCVTAU] = 0x4,
5017 [NEON_2RM_VCVTAS] = 0x4,
5018 [NEON_2RM_VCVTNU] = 0x4,
5019 [NEON_2RM_VCVTNS] = 0x4,
5020 [NEON_2RM_VCVTPU] = 0x4,
5021 [NEON_2RM_VCVTPS] = 0x4,
5022 [NEON_2RM_VCVTMU] = 0x4,
5023 [NEON_2RM_VCVTMS] = 0x4,
5024 [NEON_2RM_VRECPE] = 0x4,
5025 [NEON_2RM_VRSQRTE] = 0x4,
5026 [NEON_2RM_VRECPE_F] = 0x4,
5027 [NEON_2RM_VRSQRTE_F] = 0x4,
5028 [NEON_2RM_VCVT_FS] = 0x4,
5029 [NEON_2RM_VCVT_FU] = 0x4,
5030 [NEON_2RM_VCVT_SF] = 0x4,
5031 [NEON_2RM_VCVT_UF] = 0x4,
5034 /* Translate a NEON data processing instruction. Return nonzero if the
5035 instruction is invalid.
5036 We process data in a mixture of 32-bit and 64-bit chunks.
5037 Mostly we use 32-bit chunks so we can use normal scalar instructions. */
5039 static int disas_neon_data_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
5041 int op;
5042 int q;
5043 int rd, rn, rm;
5044 int size;
5045 int shift;
5046 int pass;
5047 int count;
5048 int pairwise;
5049 int u;
5050 uint32_t imm, mask;
5051 TCGv_i32 tmp, tmp2, tmp3, tmp4, tmp5;
5052 TCGv_i64 tmp64;
5054 /* FIXME: this access check should not take precedence over UNDEF
5055 * for invalid encodings; we will generate incorrect syndrome information
5056 * for attempts to execute invalid vfp/neon encodings with FP disabled.
5058 if (!s->cpacr_fpen) {
5059 gen_exception_insn(s, 4, EXCP_UDEF,
5060 syn_fp_access_trap(1, 0xe, s->thumb));
5061 return 0;
5064 if (!s->vfp_enabled)
5065 return 1;
5066 q = (insn & (1 << 6)) != 0;
5067 u = (insn >> 24) & 1;
5068 VFP_DREG_D(rd, insn);
5069 VFP_DREG_N(rn, insn);
5070 VFP_DREG_M(rm, insn);
5071 size = (insn >> 20) & 3;
5072 if ((insn & (1 << 23)) == 0) {
5073 /* Three register same length. */
5074 op = ((insn >> 7) & 0x1e) | ((insn >> 4) & 1);
5075 /* Catch invalid op and bad size combinations: UNDEF */
5076 if ((neon_3r_sizes[op] & (1 << size)) == 0) {
5077 return 1;
5079 /* All insns of this form UNDEF for either this condition or the
5080 * superset of cases "Q==1"; we catch the latter later.
5082 if (q && ((rd | rn | rm) & 1)) {
5083 return 1;
5086 * The SHA-1/SHA-256 3-register instructions require special treatment
5087 * here, as their size field is overloaded as an op type selector, and
5088 * they all consume their input in a single pass.
5090 if (op == NEON_3R_SHA) {
5091 if (!q) {
5092 return 1;
5094 if (!u) { /* SHA-1 */
5095 if (!arm_feature(env, ARM_FEATURE_V8_SHA1)) {
5096 return 1;
5098 tmp = tcg_const_i32(rd);
5099 tmp2 = tcg_const_i32(rn);
5100 tmp3 = tcg_const_i32(rm);
5101 tmp4 = tcg_const_i32(size);
5102 gen_helper_crypto_sha1_3reg(cpu_env, tmp, tmp2, tmp3, tmp4);
5103 tcg_temp_free_i32(tmp4);
5104 } else { /* SHA-256 */
5105 if (!arm_feature(env, ARM_FEATURE_V8_SHA256) || size == 3) {
5106 return 1;
5108 tmp = tcg_const_i32(rd);
5109 tmp2 = tcg_const_i32(rn);
5110 tmp3 = tcg_const_i32(rm);
5111 switch (size) {
5112 case 0:
5113 gen_helper_crypto_sha256h(cpu_env, tmp, tmp2, tmp3);
5114 break;
5115 case 1:
5116 gen_helper_crypto_sha256h2(cpu_env, tmp, tmp2, tmp3);
5117 break;
5118 case 2:
5119 gen_helper_crypto_sha256su1(cpu_env, tmp, tmp2, tmp3);
5120 break;
5123 tcg_temp_free_i32(tmp);
5124 tcg_temp_free_i32(tmp2);
5125 tcg_temp_free_i32(tmp3);
5126 return 0;
5128 if (size == 3 && op != NEON_3R_LOGIC) {
5129 /* 64-bit element instructions. */
5130 for (pass = 0; pass < (q ? 2 : 1); pass++) {
5131 neon_load_reg64(cpu_V0, rn + pass);
5132 neon_load_reg64(cpu_V1, rm + pass);
5133 switch (op) {
5134 case NEON_3R_VQADD:
5135 if (u) {
5136 gen_helper_neon_qadd_u64(cpu_V0, cpu_env,
5137 cpu_V0, cpu_V1);
5138 } else {
5139 gen_helper_neon_qadd_s64(cpu_V0, cpu_env,
5140 cpu_V0, cpu_V1);
5142 break;
5143 case NEON_3R_VQSUB:
5144 if (u) {
5145 gen_helper_neon_qsub_u64(cpu_V0, cpu_env,
5146 cpu_V0, cpu_V1);
5147 } else {
5148 gen_helper_neon_qsub_s64(cpu_V0, cpu_env,
5149 cpu_V0, cpu_V1);
5151 break;
5152 case NEON_3R_VSHL:
5153 if (u) {
5154 gen_helper_neon_shl_u64(cpu_V0, cpu_V1, cpu_V0);
5155 } else {
5156 gen_helper_neon_shl_s64(cpu_V0, cpu_V1, cpu_V0);
5158 break;
5159 case NEON_3R_VQSHL:
5160 if (u) {
5161 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5162 cpu_V1, cpu_V0);
5163 } else {
5164 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5165 cpu_V1, cpu_V0);
5167 break;
5168 case NEON_3R_VRSHL:
5169 if (u) {
5170 gen_helper_neon_rshl_u64(cpu_V0, cpu_V1, cpu_V0);
5171 } else {
5172 gen_helper_neon_rshl_s64(cpu_V0, cpu_V1, cpu_V0);
5174 break;
5175 case NEON_3R_VQRSHL:
5176 if (u) {
5177 gen_helper_neon_qrshl_u64(cpu_V0, cpu_env,
5178 cpu_V1, cpu_V0);
5179 } else {
5180 gen_helper_neon_qrshl_s64(cpu_V0, cpu_env,
5181 cpu_V1, cpu_V0);
5183 break;
5184 case NEON_3R_VADD_VSUB:
5185 if (u) {
5186 tcg_gen_sub_i64(CPU_V001);
5187 } else {
5188 tcg_gen_add_i64(CPU_V001);
5190 break;
5191 default:
5192 abort();
5194 neon_store_reg64(cpu_V0, rd + pass);
5196 return 0;
5198 pairwise = 0;
5199 switch (op) {
5200 case NEON_3R_VSHL:
5201 case NEON_3R_VQSHL:
5202 case NEON_3R_VRSHL:
5203 case NEON_3R_VQRSHL:
5205 int rtmp;
5206 /* Shift instruction operands are reversed. */
5207 rtmp = rn;
5208 rn = rm;
5209 rm = rtmp;
5211 break;
5212 case NEON_3R_VPADD:
5213 if (u) {
5214 return 1;
5216 /* Fall through */
5217 case NEON_3R_VPMAX:
5218 case NEON_3R_VPMIN:
5219 pairwise = 1;
5220 break;
5221 case NEON_3R_FLOAT_ARITH:
5222 pairwise = (u && size < 2); /* if VPADD (float) */
5223 break;
5224 case NEON_3R_FLOAT_MINMAX:
5225 pairwise = u; /* if VPMIN/VPMAX (float) */
5226 break;
5227 case NEON_3R_FLOAT_CMP:
5228 if (!u && size) {
5229 /* no encoding for U=0 C=1x */
5230 return 1;
5232 break;
5233 case NEON_3R_FLOAT_ACMP:
5234 if (!u) {
5235 return 1;
5237 break;
5238 case NEON_3R_FLOAT_MISC:
5239 /* VMAXNM/VMINNM in ARMv8 */
5240 if (u && !arm_feature(env, ARM_FEATURE_V8)) {
5241 return 1;
5243 break;
5244 case NEON_3R_VMUL:
5245 if (u && (size != 0)) {
5246 /* UNDEF on invalid size for polynomial subcase */
5247 return 1;
5249 break;
5250 case NEON_3R_VFM:
5251 if (!arm_feature(env, ARM_FEATURE_VFP4) || u) {
5252 return 1;
5254 break;
5255 default:
5256 break;
5259 if (pairwise && q) {
5260 /* All the pairwise insns UNDEF if Q is set */
5261 return 1;
5264 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5266 if (pairwise) {
5267 /* Pairwise. */
5268 if (pass < 1) {
5269 tmp = neon_load_reg(rn, 0);
5270 tmp2 = neon_load_reg(rn, 1);
5271 } else {
5272 tmp = neon_load_reg(rm, 0);
5273 tmp2 = neon_load_reg(rm, 1);
5275 } else {
5276 /* Elementwise. */
5277 tmp = neon_load_reg(rn, pass);
5278 tmp2 = neon_load_reg(rm, pass);
5280 switch (op) {
5281 case NEON_3R_VHADD:
5282 GEN_NEON_INTEGER_OP(hadd);
5283 break;
5284 case NEON_3R_VQADD:
5285 GEN_NEON_INTEGER_OP_ENV(qadd);
5286 break;
5287 case NEON_3R_VRHADD:
5288 GEN_NEON_INTEGER_OP(rhadd);
5289 break;
5290 case NEON_3R_LOGIC: /* Logic ops. */
5291 switch ((u << 2) | size) {
5292 case 0: /* VAND */
5293 tcg_gen_and_i32(tmp, tmp, tmp2);
5294 break;
5295 case 1: /* BIC */
5296 tcg_gen_andc_i32(tmp, tmp, tmp2);
5297 break;
5298 case 2: /* VORR */
5299 tcg_gen_or_i32(tmp, tmp, tmp2);
5300 break;
5301 case 3: /* VORN */
5302 tcg_gen_orc_i32(tmp, tmp, tmp2);
5303 break;
5304 case 4: /* VEOR */
5305 tcg_gen_xor_i32(tmp, tmp, tmp2);
5306 break;
5307 case 5: /* VBSL */
5308 tmp3 = neon_load_reg(rd, pass);
5309 gen_neon_bsl(tmp, tmp, tmp2, tmp3);
5310 tcg_temp_free_i32(tmp3);
5311 break;
5312 case 6: /* VBIT */
5313 tmp3 = neon_load_reg(rd, pass);
5314 gen_neon_bsl(tmp, tmp, tmp3, tmp2);
5315 tcg_temp_free_i32(tmp3);
5316 break;
5317 case 7: /* VBIF */
5318 tmp3 = neon_load_reg(rd, pass);
5319 gen_neon_bsl(tmp, tmp3, tmp, tmp2);
5320 tcg_temp_free_i32(tmp3);
5321 break;
5323 break;
5324 case NEON_3R_VHSUB:
5325 GEN_NEON_INTEGER_OP(hsub);
5326 break;
5327 case NEON_3R_VQSUB:
5328 GEN_NEON_INTEGER_OP_ENV(qsub);
5329 break;
5330 case NEON_3R_VCGT:
5331 GEN_NEON_INTEGER_OP(cgt);
5332 break;
5333 case NEON_3R_VCGE:
5334 GEN_NEON_INTEGER_OP(cge);
5335 break;
5336 case NEON_3R_VSHL:
5337 GEN_NEON_INTEGER_OP(shl);
5338 break;
5339 case NEON_3R_VQSHL:
5340 GEN_NEON_INTEGER_OP_ENV(qshl);
5341 break;
5342 case NEON_3R_VRSHL:
5343 GEN_NEON_INTEGER_OP(rshl);
5344 break;
5345 case NEON_3R_VQRSHL:
5346 GEN_NEON_INTEGER_OP_ENV(qrshl);
5347 break;
5348 case NEON_3R_VMAX:
5349 GEN_NEON_INTEGER_OP(max);
5350 break;
5351 case NEON_3R_VMIN:
5352 GEN_NEON_INTEGER_OP(min);
5353 break;
5354 case NEON_3R_VABD:
5355 GEN_NEON_INTEGER_OP(abd);
5356 break;
5357 case NEON_3R_VABA:
5358 GEN_NEON_INTEGER_OP(abd);
5359 tcg_temp_free_i32(tmp2);
5360 tmp2 = neon_load_reg(rd, pass);
5361 gen_neon_add(size, tmp, tmp2);
5362 break;
5363 case NEON_3R_VADD_VSUB:
5364 if (!u) { /* VADD */
5365 gen_neon_add(size, tmp, tmp2);
5366 } else { /* VSUB */
5367 switch (size) {
5368 case 0: gen_helper_neon_sub_u8(tmp, tmp, tmp2); break;
5369 case 1: gen_helper_neon_sub_u16(tmp, tmp, tmp2); break;
5370 case 2: tcg_gen_sub_i32(tmp, tmp, tmp2); break;
5371 default: abort();
5374 break;
5375 case NEON_3R_VTST_VCEQ:
5376 if (!u) { /* VTST */
5377 switch (size) {
5378 case 0: gen_helper_neon_tst_u8(tmp, tmp, tmp2); break;
5379 case 1: gen_helper_neon_tst_u16(tmp, tmp, tmp2); break;
5380 case 2: gen_helper_neon_tst_u32(tmp, tmp, tmp2); break;
5381 default: abort();
5383 } else { /* VCEQ */
5384 switch (size) {
5385 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
5386 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
5387 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
5388 default: abort();
5391 break;
5392 case NEON_3R_VML: /* VMLA, VMLAL, VMLS,VMLSL */
5393 switch (size) {
5394 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5395 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5396 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5397 default: abort();
5399 tcg_temp_free_i32(tmp2);
5400 tmp2 = neon_load_reg(rd, pass);
5401 if (u) { /* VMLS */
5402 gen_neon_rsb(size, tmp, tmp2);
5403 } else { /* VMLA */
5404 gen_neon_add(size, tmp, tmp2);
5406 break;
5407 case NEON_3R_VMUL:
5408 if (u) { /* polynomial */
5409 gen_helper_neon_mul_p8(tmp, tmp, tmp2);
5410 } else { /* Integer */
5411 switch (size) {
5412 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
5413 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
5414 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
5415 default: abort();
5418 break;
5419 case NEON_3R_VPMAX:
5420 GEN_NEON_INTEGER_OP(pmax);
5421 break;
5422 case NEON_3R_VPMIN:
5423 GEN_NEON_INTEGER_OP(pmin);
5424 break;
5425 case NEON_3R_VQDMULH_VQRDMULH: /* Multiply high. */
5426 if (!u) { /* VQDMULH */
5427 switch (size) {
5428 case 1:
5429 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
5430 break;
5431 case 2:
5432 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
5433 break;
5434 default: abort();
5436 } else { /* VQRDMULH */
5437 switch (size) {
5438 case 1:
5439 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
5440 break;
5441 case 2:
5442 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
5443 break;
5444 default: abort();
5447 break;
5448 case NEON_3R_VPADD:
5449 switch (size) {
5450 case 0: gen_helper_neon_padd_u8(tmp, tmp, tmp2); break;
5451 case 1: gen_helper_neon_padd_u16(tmp, tmp, tmp2); break;
5452 case 2: tcg_gen_add_i32(tmp, tmp, tmp2); break;
5453 default: abort();
5455 break;
5456 case NEON_3R_FLOAT_ARITH: /* Floating point arithmetic. */
5458 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5459 switch ((u << 2) | size) {
5460 case 0: /* VADD */
5461 case 4: /* VPADD */
5462 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5463 break;
5464 case 2: /* VSUB */
5465 gen_helper_vfp_subs(tmp, tmp, tmp2, fpstatus);
5466 break;
5467 case 6: /* VABD */
5468 gen_helper_neon_abd_f32(tmp, tmp, tmp2, fpstatus);
5469 break;
5470 default:
5471 abort();
5473 tcg_temp_free_ptr(fpstatus);
5474 break;
5476 case NEON_3R_FLOAT_MULTIPLY:
5478 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5479 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
5480 if (!u) {
5481 tcg_temp_free_i32(tmp2);
5482 tmp2 = neon_load_reg(rd, pass);
5483 if (size == 0) {
5484 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
5485 } else {
5486 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
5489 tcg_temp_free_ptr(fpstatus);
5490 break;
5492 case NEON_3R_FLOAT_CMP:
5494 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5495 if (!u) {
5496 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
5497 } else {
5498 if (size == 0) {
5499 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
5500 } else {
5501 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
5504 tcg_temp_free_ptr(fpstatus);
5505 break;
5507 case NEON_3R_FLOAT_ACMP:
5509 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5510 if (size == 0) {
5511 gen_helper_neon_acge_f32(tmp, tmp, tmp2, fpstatus);
5512 } else {
5513 gen_helper_neon_acgt_f32(tmp, tmp, tmp2, fpstatus);
5515 tcg_temp_free_ptr(fpstatus);
5516 break;
5518 case NEON_3R_FLOAT_MINMAX:
5520 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5521 if (size == 0) {
5522 gen_helper_vfp_maxs(tmp, tmp, tmp2, fpstatus);
5523 } else {
5524 gen_helper_vfp_mins(tmp, tmp, tmp2, fpstatus);
5526 tcg_temp_free_ptr(fpstatus);
5527 break;
5529 case NEON_3R_FLOAT_MISC:
5530 if (u) {
5531 /* VMAXNM/VMINNM */
5532 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5533 if (size == 0) {
5534 gen_helper_vfp_maxnums(tmp, tmp, tmp2, fpstatus);
5535 } else {
5536 gen_helper_vfp_minnums(tmp, tmp, tmp2, fpstatus);
5538 tcg_temp_free_ptr(fpstatus);
5539 } else {
5540 if (size == 0) {
5541 gen_helper_recps_f32(tmp, tmp, tmp2, cpu_env);
5542 } else {
5543 gen_helper_rsqrts_f32(tmp, tmp, tmp2, cpu_env);
5546 break;
5547 case NEON_3R_VFM:
5549 /* VFMA, VFMS: fused multiply-add */
5550 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
5551 TCGv_i32 tmp3 = neon_load_reg(rd, pass);
5552 if (size) {
5553 /* VFMS */
5554 gen_helper_vfp_negs(tmp, tmp);
5556 gen_helper_vfp_muladds(tmp, tmp, tmp2, tmp3, fpstatus);
5557 tcg_temp_free_i32(tmp3);
5558 tcg_temp_free_ptr(fpstatus);
5559 break;
5561 default:
5562 abort();
5564 tcg_temp_free_i32(tmp2);
5566 /* Save the result. For elementwise operations we can put it
5567 straight into the destination register. For pairwise operations
5568 we have to be careful to avoid clobbering the source operands. */
5569 if (pairwise && rd == rm) {
5570 neon_store_scratch(pass, tmp);
5571 } else {
5572 neon_store_reg(rd, pass, tmp);
5575 } /* for pass */
5576 if (pairwise && rd == rm) {
5577 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5578 tmp = neon_load_scratch(pass);
5579 neon_store_reg(rd, pass, tmp);
5582 /* End of 3 register same size operations. */
5583 } else if (insn & (1 << 4)) {
5584 if ((insn & 0x00380080) != 0) {
5585 /* Two registers and shift. */
5586 op = (insn >> 8) & 0xf;
5587 if (insn & (1 << 7)) {
5588 /* 64-bit shift. */
5589 if (op > 7) {
5590 return 1;
5592 size = 3;
5593 } else {
5594 size = 2;
5595 while ((insn & (1 << (size + 19))) == 0)
5596 size--;
5598 shift = (insn >> 16) & ((1 << (3 + size)) - 1);
5599 /* To avoid excessive duplication of ops we implement shift
5600 by immediate using the variable shift operations. */
5601 if (op < 8) {
5602 /* Shift by immediate:
5603 VSHR, VSRA, VRSHR, VRSRA, VSRI, VSHL, VQSHL, VQSHLU. */
5604 if (q && ((rd | rm) & 1)) {
5605 return 1;
5607 if (!u && (op == 4 || op == 6)) {
5608 return 1;
5610 /* Right shifts are encoded as N - shift, where N is the
5611 element size in bits. */
5612 if (op <= 4)
5613 shift = shift - (1 << (size + 3));
5614 if (size == 3) {
5615 count = q + 1;
5616 } else {
5617 count = q ? 4: 2;
5619 switch (size) {
5620 case 0:
5621 imm = (uint8_t) shift;
5622 imm |= imm << 8;
5623 imm |= imm << 16;
5624 break;
5625 case 1:
5626 imm = (uint16_t) shift;
5627 imm |= imm << 16;
5628 break;
5629 case 2:
5630 case 3:
5631 imm = shift;
5632 break;
5633 default:
5634 abort();
5637 for (pass = 0; pass < count; pass++) {
5638 if (size == 3) {
5639 neon_load_reg64(cpu_V0, rm + pass);
5640 tcg_gen_movi_i64(cpu_V1, imm);
5641 switch (op) {
5642 case 0: /* VSHR */
5643 case 1: /* VSRA */
5644 if (u)
5645 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5646 else
5647 gen_helper_neon_shl_s64(cpu_V0, cpu_V0, cpu_V1);
5648 break;
5649 case 2: /* VRSHR */
5650 case 3: /* VRSRA */
5651 if (u)
5652 gen_helper_neon_rshl_u64(cpu_V0, cpu_V0, cpu_V1);
5653 else
5654 gen_helper_neon_rshl_s64(cpu_V0, cpu_V0, cpu_V1);
5655 break;
5656 case 4: /* VSRI */
5657 case 5: /* VSHL, VSLI */
5658 gen_helper_neon_shl_u64(cpu_V0, cpu_V0, cpu_V1);
5659 break;
5660 case 6: /* VQSHLU */
5661 gen_helper_neon_qshlu_s64(cpu_V0, cpu_env,
5662 cpu_V0, cpu_V1);
5663 break;
5664 case 7: /* VQSHL */
5665 if (u) {
5666 gen_helper_neon_qshl_u64(cpu_V0, cpu_env,
5667 cpu_V0, cpu_V1);
5668 } else {
5669 gen_helper_neon_qshl_s64(cpu_V0, cpu_env,
5670 cpu_V0, cpu_V1);
5672 break;
5674 if (op == 1 || op == 3) {
5675 /* Accumulate. */
5676 neon_load_reg64(cpu_V1, rd + pass);
5677 tcg_gen_add_i64(cpu_V0, cpu_V0, cpu_V1);
5678 } else if (op == 4 || (op == 5 && u)) {
5679 /* Insert */
5680 neon_load_reg64(cpu_V1, rd + pass);
5681 uint64_t mask;
5682 if (shift < -63 || shift > 63) {
5683 mask = 0;
5684 } else {
5685 if (op == 4) {
5686 mask = 0xffffffffffffffffull >> -shift;
5687 } else {
5688 mask = 0xffffffffffffffffull << shift;
5691 tcg_gen_andi_i64(cpu_V1, cpu_V1, ~mask);
5692 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
5694 neon_store_reg64(cpu_V0, rd + pass);
5695 } else { /* size < 3 */
5696 /* Operands in T0 and T1. */
5697 tmp = neon_load_reg(rm, pass);
5698 tmp2 = tcg_temp_new_i32();
5699 tcg_gen_movi_i32(tmp2, imm);
5700 switch (op) {
5701 case 0: /* VSHR */
5702 case 1: /* VSRA */
5703 GEN_NEON_INTEGER_OP(shl);
5704 break;
5705 case 2: /* VRSHR */
5706 case 3: /* VRSRA */
5707 GEN_NEON_INTEGER_OP(rshl);
5708 break;
5709 case 4: /* VSRI */
5710 case 5: /* VSHL, VSLI */
5711 switch (size) {
5712 case 0: gen_helper_neon_shl_u8(tmp, tmp, tmp2); break;
5713 case 1: gen_helper_neon_shl_u16(tmp, tmp, tmp2); break;
5714 case 2: gen_helper_neon_shl_u32(tmp, tmp, tmp2); break;
5715 default: abort();
5717 break;
5718 case 6: /* VQSHLU */
5719 switch (size) {
5720 case 0:
5721 gen_helper_neon_qshlu_s8(tmp, cpu_env,
5722 tmp, tmp2);
5723 break;
5724 case 1:
5725 gen_helper_neon_qshlu_s16(tmp, cpu_env,
5726 tmp, tmp2);
5727 break;
5728 case 2:
5729 gen_helper_neon_qshlu_s32(tmp, cpu_env,
5730 tmp, tmp2);
5731 break;
5732 default:
5733 abort();
5735 break;
5736 case 7: /* VQSHL */
5737 GEN_NEON_INTEGER_OP_ENV(qshl);
5738 break;
5740 tcg_temp_free_i32(tmp2);
5742 if (op == 1 || op == 3) {
5743 /* Accumulate. */
5744 tmp2 = neon_load_reg(rd, pass);
5745 gen_neon_add(size, tmp, tmp2);
5746 tcg_temp_free_i32(tmp2);
5747 } else if (op == 4 || (op == 5 && u)) {
5748 /* Insert */
5749 switch (size) {
5750 case 0:
5751 if (op == 4)
5752 mask = 0xff >> -shift;
5753 else
5754 mask = (uint8_t)(0xff << shift);
5755 mask |= mask << 8;
5756 mask |= mask << 16;
5757 break;
5758 case 1:
5759 if (op == 4)
5760 mask = 0xffff >> -shift;
5761 else
5762 mask = (uint16_t)(0xffff << shift);
5763 mask |= mask << 16;
5764 break;
5765 case 2:
5766 if (shift < -31 || shift > 31) {
5767 mask = 0;
5768 } else {
5769 if (op == 4)
5770 mask = 0xffffffffu >> -shift;
5771 else
5772 mask = 0xffffffffu << shift;
5774 break;
5775 default:
5776 abort();
5778 tmp2 = neon_load_reg(rd, pass);
5779 tcg_gen_andi_i32(tmp, tmp, mask);
5780 tcg_gen_andi_i32(tmp2, tmp2, ~mask);
5781 tcg_gen_or_i32(tmp, tmp, tmp2);
5782 tcg_temp_free_i32(tmp2);
5784 neon_store_reg(rd, pass, tmp);
5786 } /* for pass */
5787 } else if (op < 10) {
5788 /* Shift by immediate and narrow:
5789 VSHRN, VRSHRN, VQSHRN, VQRSHRN. */
5790 int input_unsigned = (op == 8) ? !u : u;
5791 if (rm & 1) {
5792 return 1;
5794 shift = shift - (1 << (size + 3));
5795 size++;
5796 if (size == 3) {
5797 tmp64 = tcg_const_i64(shift);
5798 neon_load_reg64(cpu_V0, rm);
5799 neon_load_reg64(cpu_V1, rm + 1);
5800 for (pass = 0; pass < 2; pass++) {
5801 TCGv_i64 in;
5802 if (pass == 0) {
5803 in = cpu_V0;
5804 } else {
5805 in = cpu_V1;
5807 if (q) {
5808 if (input_unsigned) {
5809 gen_helper_neon_rshl_u64(cpu_V0, in, tmp64);
5810 } else {
5811 gen_helper_neon_rshl_s64(cpu_V0, in, tmp64);
5813 } else {
5814 if (input_unsigned) {
5815 gen_helper_neon_shl_u64(cpu_V0, in, tmp64);
5816 } else {
5817 gen_helper_neon_shl_s64(cpu_V0, in, tmp64);
5820 tmp = tcg_temp_new_i32();
5821 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5822 neon_store_reg(rd, pass, tmp);
5823 } /* for pass */
5824 tcg_temp_free_i64(tmp64);
5825 } else {
5826 if (size == 1) {
5827 imm = (uint16_t)shift;
5828 imm |= imm << 16;
5829 } else {
5830 /* size == 2 */
5831 imm = (uint32_t)shift;
5833 tmp2 = tcg_const_i32(imm);
5834 tmp4 = neon_load_reg(rm + 1, 0);
5835 tmp5 = neon_load_reg(rm + 1, 1);
5836 for (pass = 0; pass < 2; pass++) {
5837 if (pass == 0) {
5838 tmp = neon_load_reg(rm, 0);
5839 } else {
5840 tmp = tmp4;
5842 gen_neon_shift_narrow(size, tmp, tmp2, q,
5843 input_unsigned);
5844 if (pass == 0) {
5845 tmp3 = neon_load_reg(rm, 1);
5846 } else {
5847 tmp3 = tmp5;
5849 gen_neon_shift_narrow(size, tmp3, tmp2, q,
5850 input_unsigned);
5851 tcg_gen_concat_i32_i64(cpu_V0, tmp, tmp3);
5852 tcg_temp_free_i32(tmp);
5853 tcg_temp_free_i32(tmp3);
5854 tmp = tcg_temp_new_i32();
5855 gen_neon_narrow_op(op == 8, u, size - 1, tmp, cpu_V0);
5856 neon_store_reg(rd, pass, tmp);
5857 } /* for pass */
5858 tcg_temp_free_i32(tmp2);
5860 } else if (op == 10) {
5861 /* VSHLL, VMOVL */
5862 if (q || (rd & 1)) {
5863 return 1;
5865 tmp = neon_load_reg(rm, 0);
5866 tmp2 = neon_load_reg(rm, 1);
5867 for (pass = 0; pass < 2; pass++) {
5868 if (pass == 1)
5869 tmp = tmp2;
5871 gen_neon_widen(cpu_V0, tmp, size, u);
5873 if (shift != 0) {
5874 /* The shift is less than the width of the source
5875 type, so we can just shift the whole register. */
5876 tcg_gen_shli_i64(cpu_V0, cpu_V0, shift);
5877 /* Widen the result of shift: we need to clear
5878 * the potential overflow bits resulting from
5879 * left bits of the narrow input appearing as
5880 * right bits of left the neighbour narrow
5881 * input. */
5882 if (size < 2 || !u) {
5883 uint64_t imm64;
5884 if (size == 0) {
5885 imm = (0xffu >> (8 - shift));
5886 imm |= imm << 16;
5887 } else if (size == 1) {
5888 imm = 0xffff >> (16 - shift);
5889 } else {
5890 /* size == 2 */
5891 imm = 0xffffffff >> (32 - shift);
5893 if (size < 2) {
5894 imm64 = imm | (((uint64_t)imm) << 32);
5895 } else {
5896 imm64 = imm;
5898 tcg_gen_andi_i64(cpu_V0, cpu_V0, ~imm64);
5901 neon_store_reg64(cpu_V0, rd + pass);
5903 } else if (op >= 14) {
5904 /* VCVT fixed-point. */
5905 if (!(insn & (1 << 21)) || (q && ((rd | rm) & 1))) {
5906 return 1;
5908 /* We have already masked out the must-be-1 top bit of imm6,
5909 * hence this 32-shift where the ARM ARM has 64-imm6.
5911 shift = 32 - shift;
5912 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5913 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, pass));
5914 if (!(op & 1)) {
5915 if (u)
5916 gen_vfp_ulto(0, shift, 1);
5917 else
5918 gen_vfp_slto(0, shift, 1);
5919 } else {
5920 if (u)
5921 gen_vfp_toul(0, shift, 1);
5922 else
5923 gen_vfp_tosl(0, shift, 1);
5925 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, pass));
5927 } else {
5928 return 1;
5930 } else { /* (insn & 0x00380080) == 0 */
5931 int invert;
5932 if (q && (rd & 1)) {
5933 return 1;
5936 op = (insn >> 8) & 0xf;
5937 /* One register and immediate. */
5938 imm = (u << 7) | ((insn >> 12) & 0x70) | (insn & 0xf);
5939 invert = (insn & (1 << 5)) != 0;
5940 /* Note that op = 2,3,4,5,6,7,10,11,12,13 imm=0 is UNPREDICTABLE.
5941 * We choose to not special-case this and will behave as if a
5942 * valid constant encoding of 0 had been given.
5944 switch (op) {
5945 case 0: case 1:
5946 /* no-op */
5947 break;
5948 case 2: case 3:
5949 imm <<= 8;
5950 break;
5951 case 4: case 5:
5952 imm <<= 16;
5953 break;
5954 case 6: case 7:
5955 imm <<= 24;
5956 break;
5957 case 8: case 9:
5958 imm |= imm << 16;
5959 break;
5960 case 10: case 11:
5961 imm = (imm << 8) | (imm << 24);
5962 break;
5963 case 12:
5964 imm = (imm << 8) | 0xff;
5965 break;
5966 case 13:
5967 imm = (imm << 16) | 0xffff;
5968 break;
5969 case 14:
5970 imm |= (imm << 8) | (imm << 16) | (imm << 24);
5971 if (invert)
5972 imm = ~imm;
5973 break;
5974 case 15:
5975 if (invert) {
5976 return 1;
5978 imm = ((imm & 0x80) << 24) | ((imm & 0x3f) << 19)
5979 | ((imm & 0x40) ? (0x1f << 25) : (1 << 30));
5980 break;
5982 if (invert)
5983 imm = ~imm;
5985 for (pass = 0; pass < (q ? 4 : 2); pass++) {
5986 if (op & 1 && op < 12) {
5987 tmp = neon_load_reg(rd, pass);
5988 if (invert) {
5989 /* The immediate value has already been inverted, so
5990 BIC becomes AND. */
5991 tcg_gen_andi_i32(tmp, tmp, imm);
5992 } else {
5993 tcg_gen_ori_i32(tmp, tmp, imm);
5995 } else {
5996 /* VMOV, VMVN. */
5997 tmp = tcg_temp_new_i32();
5998 if (op == 14 && invert) {
5999 int n;
6000 uint32_t val;
6001 val = 0;
6002 for (n = 0; n < 4; n++) {
6003 if (imm & (1 << (n + (pass & 1) * 4)))
6004 val |= 0xff << (n * 8);
6006 tcg_gen_movi_i32(tmp, val);
6007 } else {
6008 tcg_gen_movi_i32(tmp, imm);
6011 neon_store_reg(rd, pass, tmp);
6014 } else { /* (insn & 0x00800010 == 0x00800000) */
6015 if (size != 3) {
6016 op = (insn >> 8) & 0xf;
6017 if ((insn & (1 << 6)) == 0) {
6018 /* Three registers of different lengths. */
6019 int src1_wide;
6020 int src2_wide;
6021 int prewiden;
6022 /* undefreq: bit 0 : UNDEF if size == 0
6023 * bit 1 : UNDEF if size == 1
6024 * bit 2 : UNDEF if size == 2
6025 * bit 3 : UNDEF if U == 1
6026 * Note that [2:0] set implies 'always UNDEF'
6028 int undefreq;
6029 /* prewiden, src1_wide, src2_wide, undefreq */
6030 static const int neon_3reg_wide[16][4] = {
6031 {1, 0, 0, 0}, /* VADDL */
6032 {1, 1, 0, 0}, /* VADDW */
6033 {1, 0, 0, 0}, /* VSUBL */
6034 {1, 1, 0, 0}, /* VSUBW */
6035 {0, 1, 1, 0}, /* VADDHN */
6036 {0, 0, 0, 0}, /* VABAL */
6037 {0, 1, 1, 0}, /* VSUBHN */
6038 {0, 0, 0, 0}, /* VABDL */
6039 {0, 0, 0, 0}, /* VMLAL */
6040 {0, 0, 0, 9}, /* VQDMLAL */
6041 {0, 0, 0, 0}, /* VMLSL */
6042 {0, 0, 0, 9}, /* VQDMLSL */
6043 {0, 0, 0, 0}, /* Integer VMULL */
6044 {0, 0, 0, 1}, /* VQDMULL */
6045 {0, 0, 0, 0xa}, /* Polynomial VMULL */
6046 {0, 0, 0, 7}, /* Reserved: always UNDEF */
6049 prewiden = neon_3reg_wide[op][0];
6050 src1_wide = neon_3reg_wide[op][1];
6051 src2_wide = neon_3reg_wide[op][2];
6052 undefreq = neon_3reg_wide[op][3];
6054 if ((undefreq & (1 << size)) ||
6055 ((undefreq & 8) && u)) {
6056 return 1;
6058 if ((src1_wide && (rn & 1)) ||
6059 (src2_wide && (rm & 1)) ||
6060 (!src2_wide && (rd & 1))) {
6061 return 1;
6064 /* Handle VMULL.P64 (Polynomial 64x64 to 128 bit multiply)
6065 * outside the loop below as it only performs a single pass.
6067 if (op == 14 && size == 2) {
6068 TCGv_i64 tcg_rn, tcg_rm, tcg_rd;
6070 if (!arm_feature(env, ARM_FEATURE_V8_PMULL)) {
6071 return 1;
6073 tcg_rn = tcg_temp_new_i64();
6074 tcg_rm = tcg_temp_new_i64();
6075 tcg_rd = tcg_temp_new_i64();
6076 neon_load_reg64(tcg_rn, rn);
6077 neon_load_reg64(tcg_rm, rm);
6078 gen_helper_neon_pmull_64_lo(tcg_rd, tcg_rn, tcg_rm);
6079 neon_store_reg64(tcg_rd, rd);
6080 gen_helper_neon_pmull_64_hi(tcg_rd, tcg_rn, tcg_rm);
6081 neon_store_reg64(tcg_rd, rd + 1);
6082 tcg_temp_free_i64(tcg_rn);
6083 tcg_temp_free_i64(tcg_rm);
6084 tcg_temp_free_i64(tcg_rd);
6085 return 0;
6088 /* Avoid overlapping operands. Wide source operands are
6089 always aligned so will never overlap with wide
6090 destinations in problematic ways. */
6091 if (rd == rm && !src2_wide) {
6092 tmp = neon_load_reg(rm, 1);
6093 neon_store_scratch(2, tmp);
6094 } else if (rd == rn && !src1_wide) {
6095 tmp = neon_load_reg(rn, 1);
6096 neon_store_scratch(2, tmp);
6098 TCGV_UNUSED_I32(tmp3);
6099 for (pass = 0; pass < 2; pass++) {
6100 if (src1_wide) {
6101 neon_load_reg64(cpu_V0, rn + pass);
6102 TCGV_UNUSED_I32(tmp);
6103 } else {
6104 if (pass == 1 && rd == rn) {
6105 tmp = neon_load_scratch(2);
6106 } else {
6107 tmp = neon_load_reg(rn, pass);
6109 if (prewiden) {
6110 gen_neon_widen(cpu_V0, tmp, size, u);
6113 if (src2_wide) {
6114 neon_load_reg64(cpu_V1, rm + pass);
6115 TCGV_UNUSED_I32(tmp2);
6116 } else {
6117 if (pass == 1 && rd == rm) {
6118 tmp2 = neon_load_scratch(2);
6119 } else {
6120 tmp2 = neon_load_reg(rm, pass);
6122 if (prewiden) {
6123 gen_neon_widen(cpu_V1, tmp2, size, u);
6126 switch (op) {
6127 case 0: case 1: case 4: /* VADDL, VADDW, VADDHN, VRADDHN */
6128 gen_neon_addl(size);
6129 break;
6130 case 2: case 3: case 6: /* VSUBL, VSUBW, VSUBHN, VRSUBHN */
6131 gen_neon_subl(size);
6132 break;
6133 case 5: case 7: /* VABAL, VABDL */
6134 switch ((size << 1) | u) {
6135 case 0:
6136 gen_helper_neon_abdl_s16(cpu_V0, tmp, tmp2);
6137 break;
6138 case 1:
6139 gen_helper_neon_abdl_u16(cpu_V0, tmp, tmp2);
6140 break;
6141 case 2:
6142 gen_helper_neon_abdl_s32(cpu_V0, tmp, tmp2);
6143 break;
6144 case 3:
6145 gen_helper_neon_abdl_u32(cpu_V0, tmp, tmp2);
6146 break;
6147 case 4:
6148 gen_helper_neon_abdl_s64(cpu_V0, tmp, tmp2);
6149 break;
6150 case 5:
6151 gen_helper_neon_abdl_u64(cpu_V0, tmp, tmp2);
6152 break;
6153 default: abort();
6155 tcg_temp_free_i32(tmp2);
6156 tcg_temp_free_i32(tmp);
6157 break;
6158 case 8: case 9: case 10: case 11: case 12: case 13:
6159 /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
6160 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6161 break;
6162 case 14: /* Polynomial VMULL */
6163 gen_helper_neon_mull_p8(cpu_V0, tmp, tmp2);
6164 tcg_temp_free_i32(tmp2);
6165 tcg_temp_free_i32(tmp);
6166 break;
6167 default: /* 15 is RESERVED: caught earlier */
6168 abort();
6170 if (op == 13) {
6171 /* VQDMULL */
6172 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6173 neon_store_reg64(cpu_V0, rd + pass);
6174 } else if (op == 5 || (op >= 8 && op <= 11)) {
6175 /* Accumulate. */
6176 neon_load_reg64(cpu_V1, rd + pass);
6177 switch (op) {
6178 case 10: /* VMLSL */
6179 gen_neon_negl(cpu_V0, size);
6180 /* Fall through */
6181 case 5: case 8: /* VABAL, VMLAL */
6182 gen_neon_addl(size);
6183 break;
6184 case 9: case 11: /* VQDMLAL, VQDMLSL */
6185 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6186 if (op == 11) {
6187 gen_neon_negl(cpu_V0, size);
6189 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6190 break;
6191 default:
6192 abort();
6194 neon_store_reg64(cpu_V0, rd + pass);
6195 } else if (op == 4 || op == 6) {
6196 /* Narrowing operation. */
6197 tmp = tcg_temp_new_i32();
6198 if (!u) {
6199 switch (size) {
6200 case 0:
6201 gen_helper_neon_narrow_high_u8(tmp, cpu_V0);
6202 break;
6203 case 1:
6204 gen_helper_neon_narrow_high_u16(tmp, cpu_V0);
6205 break;
6206 case 2:
6207 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6208 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
6209 break;
6210 default: abort();
6212 } else {
6213 switch (size) {
6214 case 0:
6215 gen_helper_neon_narrow_round_high_u8(tmp, cpu_V0);
6216 break;
6217 case 1:
6218 gen_helper_neon_narrow_round_high_u16(tmp, cpu_V0);
6219 break;
6220 case 2:
6221 tcg_gen_addi_i64(cpu_V0, cpu_V0, 1u << 31);
6222 tcg_gen_shri_i64(cpu_V0, cpu_V0, 32);
6223 tcg_gen_trunc_i64_i32(tmp, cpu_V0);
6224 break;
6225 default: abort();
6228 if (pass == 0) {
6229 tmp3 = tmp;
6230 } else {
6231 neon_store_reg(rd, 0, tmp3);
6232 neon_store_reg(rd, 1, tmp);
6234 } else {
6235 /* Write back the result. */
6236 neon_store_reg64(cpu_V0, rd + pass);
6239 } else {
6240 /* Two registers and a scalar. NB that for ops of this form
6241 * the ARM ARM labels bit 24 as Q, but it is in our variable
6242 * 'u', not 'q'.
6244 if (size == 0) {
6245 return 1;
6247 switch (op) {
6248 case 1: /* Float VMLA scalar */
6249 case 5: /* Floating point VMLS scalar */
6250 case 9: /* Floating point VMUL scalar */
6251 if (size == 1) {
6252 return 1;
6254 /* fall through */
6255 case 0: /* Integer VMLA scalar */
6256 case 4: /* Integer VMLS scalar */
6257 case 8: /* Integer VMUL scalar */
6258 case 12: /* VQDMULH scalar */
6259 case 13: /* VQRDMULH scalar */
6260 if (u && ((rd | rn) & 1)) {
6261 return 1;
6263 tmp = neon_get_scalar(size, rm);
6264 neon_store_scratch(0, tmp);
6265 for (pass = 0; pass < (u ? 4 : 2); pass++) {
6266 tmp = neon_load_scratch(0);
6267 tmp2 = neon_load_reg(rn, pass);
6268 if (op == 12) {
6269 if (size == 1) {
6270 gen_helper_neon_qdmulh_s16(tmp, cpu_env, tmp, tmp2);
6271 } else {
6272 gen_helper_neon_qdmulh_s32(tmp, cpu_env, tmp, tmp2);
6274 } else if (op == 13) {
6275 if (size == 1) {
6276 gen_helper_neon_qrdmulh_s16(tmp, cpu_env, tmp, tmp2);
6277 } else {
6278 gen_helper_neon_qrdmulh_s32(tmp, cpu_env, tmp, tmp2);
6280 } else if (op & 1) {
6281 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6282 gen_helper_vfp_muls(tmp, tmp, tmp2, fpstatus);
6283 tcg_temp_free_ptr(fpstatus);
6284 } else {
6285 switch (size) {
6286 case 0: gen_helper_neon_mul_u8(tmp, tmp, tmp2); break;
6287 case 1: gen_helper_neon_mul_u16(tmp, tmp, tmp2); break;
6288 case 2: tcg_gen_mul_i32(tmp, tmp, tmp2); break;
6289 default: abort();
6292 tcg_temp_free_i32(tmp2);
6293 if (op < 8) {
6294 /* Accumulate. */
6295 tmp2 = neon_load_reg(rd, pass);
6296 switch (op) {
6297 case 0:
6298 gen_neon_add(size, tmp, tmp2);
6299 break;
6300 case 1:
6302 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6303 gen_helper_vfp_adds(tmp, tmp, tmp2, fpstatus);
6304 tcg_temp_free_ptr(fpstatus);
6305 break;
6307 case 4:
6308 gen_neon_rsb(size, tmp, tmp2);
6309 break;
6310 case 5:
6312 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6313 gen_helper_vfp_subs(tmp, tmp2, tmp, fpstatus);
6314 tcg_temp_free_ptr(fpstatus);
6315 break;
6317 default:
6318 abort();
6320 tcg_temp_free_i32(tmp2);
6322 neon_store_reg(rd, pass, tmp);
6324 break;
6325 case 3: /* VQDMLAL scalar */
6326 case 7: /* VQDMLSL scalar */
6327 case 11: /* VQDMULL scalar */
6328 if (u == 1) {
6329 return 1;
6331 /* fall through */
6332 case 2: /* VMLAL sclar */
6333 case 6: /* VMLSL scalar */
6334 case 10: /* VMULL scalar */
6335 if (rd & 1) {
6336 return 1;
6338 tmp2 = neon_get_scalar(size, rm);
6339 /* We need a copy of tmp2 because gen_neon_mull
6340 * deletes it during pass 0. */
6341 tmp4 = tcg_temp_new_i32();
6342 tcg_gen_mov_i32(tmp4, tmp2);
6343 tmp3 = neon_load_reg(rn, 1);
6345 for (pass = 0; pass < 2; pass++) {
6346 if (pass == 0) {
6347 tmp = neon_load_reg(rn, 0);
6348 } else {
6349 tmp = tmp3;
6350 tmp2 = tmp4;
6352 gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
6353 if (op != 11) {
6354 neon_load_reg64(cpu_V1, rd + pass);
6356 switch (op) {
6357 case 6:
6358 gen_neon_negl(cpu_V0, size);
6359 /* Fall through */
6360 case 2:
6361 gen_neon_addl(size);
6362 break;
6363 case 3: case 7:
6364 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6365 if (op == 7) {
6366 gen_neon_negl(cpu_V0, size);
6368 gen_neon_addl_saturate(cpu_V0, cpu_V1, size);
6369 break;
6370 case 10:
6371 /* no-op */
6372 break;
6373 case 11:
6374 gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
6375 break;
6376 default:
6377 abort();
6379 neon_store_reg64(cpu_V0, rd + pass);
6383 break;
6384 default: /* 14 and 15 are RESERVED */
6385 return 1;
6388 } else { /* size == 3 */
6389 if (!u) {
6390 /* Extract. */
6391 imm = (insn >> 8) & 0xf;
6393 if (imm > 7 && !q)
6394 return 1;
6396 if (q && ((rd | rn | rm) & 1)) {
6397 return 1;
6400 if (imm == 0) {
6401 neon_load_reg64(cpu_V0, rn);
6402 if (q) {
6403 neon_load_reg64(cpu_V1, rn + 1);
6405 } else if (imm == 8) {
6406 neon_load_reg64(cpu_V0, rn + 1);
6407 if (q) {
6408 neon_load_reg64(cpu_V1, rm);
6410 } else if (q) {
6411 tmp64 = tcg_temp_new_i64();
6412 if (imm < 8) {
6413 neon_load_reg64(cpu_V0, rn);
6414 neon_load_reg64(tmp64, rn + 1);
6415 } else {
6416 neon_load_reg64(cpu_V0, rn + 1);
6417 neon_load_reg64(tmp64, rm);
6419 tcg_gen_shri_i64(cpu_V0, cpu_V0, (imm & 7) * 8);
6420 tcg_gen_shli_i64(cpu_V1, tmp64, 64 - ((imm & 7) * 8));
6421 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6422 if (imm < 8) {
6423 neon_load_reg64(cpu_V1, rm);
6424 } else {
6425 neon_load_reg64(cpu_V1, rm + 1);
6426 imm -= 8;
6428 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6429 tcg_gen_shri_i64(tmp64, tmp64, imm * 8);
6430 tcg_gen_or_i64(cpu_V1, cpu_V1, tmp64);
6431 tcg_temp_free_i64(tmp64);
6432 } else {
6433 /* BUGFIX */
6434 neon_load_reg64(cpu_V0, rn);
6435 tcg_gen_shri_i64(cpu_V0, cpu_V0, imm * 8);
6436 neon_load_reg64(cpu_V1, rm);
6437 tcg_gen_shli_i64(cpu_V1, cpu_V1, 64 - (imm * 8));
6438 tcg_gen_or_i64(cpu_V0, cpu_V0, cpu_V1);
6440 neon_store_reg64(cpu_V0, rd);
6441 if (q) {
6442 neon_store_reg64(cpu_V1, rd + 1);
6444 } else if ((insn & (1 << 11)) == 0) {
6445 /* Two register misc. */
6446 op = ((insn >> 12) & 0x30) | ((insn >> 7) & 0xf);
6447 size = (insn >> 18) & 3;
6448 /* UNDEF for unknown op values and bad op-size combinations */
6449 if ((neon_2rm_sizes[op] & (1 << size)) == 0) {
6450 return 1;
6452 if ((op != NEON_2RM_VMOVN && op != NEON_2RM_VQMOVN) &&
6453 q && ((rm | rd) & 1)) {
6454 return 1;
6456 switch (op) {
6457 case NEON_2RM_VREV64:
6458 for (pass = 0; pass < (q ? 2 : 1); pass++) {
6459 tmp = neon_load_reg(rm, pass * 2);
6460 tmp2 = neon_load_reg(rm, pass * 2 + 1);
6461 switch (size) {
6462 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6463 case 1: gen_swap_half(tmp); break;
6464 case 2: /* no-op */ break;
6465 default: abort();
6467 neon_store_reg(rd, pass * 2 + 1, tmp);
6468 if (size == 2) {
6469 neon_store_reg(rd, pass * 2, tmp2);
6470 } else {
6471 switch (size) {
6472 case 0: tcg_gen_bswap32_i32(tmp2, tmp2); break;
6473 case 1: gen_swap_half(tmp2); break;
6474 default: abort();
6476 neon_store_reg(rd, pass * 2, tmp2);
6479 break;
6480 case NEON_2RM_VPADDL: case NEON_2RM_VPADDL_U:
6481 case NEON_2RM_VPADAL: case NEON_2RM_VPADAL_U:
6482 for (pass = 0; pass < q + 1; pass++) {
6483 tmp = neon_load_reg(rm, pass * 2);
6484 gen_neon_widen(cpu_V0, tmp, size, op & 1);
6485 tmp = neon_load_reg(rm, pass * 2 + 1);
6486 gen_neon_widen(cpu_V1, tmp, size, op & 1);
6487 switch (size) {
6488 case 0: gen_helper_neon_paddl_u16(CPU_V001); break;
6489 case 1: gen_helper_neon_paddl_u32(CPU_V001); break;
6490 case 2: tcg_gen_add_i64(CPU_V001); break;
6491 default: abort();
6493 if (op >= NEON_2RM_VPADAL) {
6494 /* Accumulate. */
6495 neon_load_reg64(cpu_V1, rd + pass);
6496 gen_neon_addl(size);
6498 neon_store_reg64(cpu_V0, rd + pass);
6500 break;
6501 case NEON_2RM_VTRN:
6502 if (size == 2) {
6503 int n;
6504 for (n = 0; n < (q ? 4 : 2); n += 2) {
6505 tmp = neon_load_reg(rm, n);
6506 tmp2 = neon_load_reg(rd, n + 1);
6507 neon_store_reg(rm, n, tmp2);
6508 neon_store_reg(rd, n + 1, tmp);
6510 } else {
6511 goto elementwise;
6513 break;
6514 case NEON_2RM_VUZP:
6515 if (gen_neon_unzip(rd, rm, size, q)) {
6516 return 1;
6518 break;
6519 case NEON_2RM_VZIP:
6520 if (gen_neon_zip(rd, rm, size, q)) {
6521 return 1;
6523 break;
6524 case NEON_2RM_VMOVN: case NEON_2RM_VQMOVN:
6525 /* also VQMOVUN; op field and mnemonics don't line up */
6526 if (rm & 1) {
6527 return 1;
6529 TCGV_UNUSED_I32(tmp2);
6530 for (pass = 0; pass < 2; pass++) {
6531 neon_load_reg64(cpu_V0, rm + pass);
6532 tmp = tcg_temp_new_i32();
6533 gen_neon_narrow_op(op == NEON_2RM_VMOVN, q, size,
6534 tmp, cpu_V0);
6535 if (pass == 0) {
6536 tmp2 = tmp;
6537 } else {
6538 neon_store_reg(rd, 0, tmp2);
6539 neon_store_reg(rd, 1, tmp);
6542 break;
6543 case NEON_2RM_VSHLL:
6544 if (q || (rd & 1)) {
6545 return 1;
6547 tmp = neon_load_reg(rm, 0);
6548 tmp2 = neon_load_reg(rm, 1);
6549 for (pass = 0; pass < 2; pass++) {
6550 if (pass == 1)
6551 tmp = tmp2;
6552 gen_neon_widen(cpu_V0, tmp, size, 1);
6553 tcg_gen_shli_i64(cpu_V0, cpu_V0, 8 << size);
6554 neon_store_reg64(cpu_V0, rd + pass);
6556 break;
6557 case NEON_2RM_VCVT_F16_F32:
6558 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6559 q || (rm & 1)) {
6560 return 1;
6562 tmp = tcg_temp_new_i32();
6563 tmp2 = tcg_temp_new_i32();
6564 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 0));
6565 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6566 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 1));
6567 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6568 tcg_gen_shli_i32(tmp2, tmp2, 16);
6569 tcg_gen_or_i32(tmp2, tmp2, tmp);
6570 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 2));
6571 gen_helper_neon_fcvt_f32_to_f16(tmp, cpu_F0s, cpu_env);
6572 tcg_gen_ld_f32(cpu_F0s, cpu_env, neon_reg_offset(rm, 3));
6573 neon_store_reg(rd, 0, tmp2);
6574 tmp2 = tcg_temp_new_i32();
6575 gen_helper_neon_fcvt_f32_to_f16(tmp2, cpu_F0s, cpu_env);
6576 tcg_gen_shli_i32(tmp2, tmp2, 16);
6577 tcg_gen_or_i32(tmp2, tmp2, tmp);
6578 neon_store_reg(rd, 1, tmp2);
6579 tcg_temp_free_i32(tmp);
6580 break;
6581 case NEON_2RM_VCVT_F32_F16:
6582 if (!arm_feature(env, ARM_FEATURE_VFP_FP16) ||
6583 q || (rd & 1)) {
6584 return 1;
6586 tmp3 = tcg_temp_new_i32();
6587 tmp = neon_load_reg(rm, 0);
6588 tmp2 = neon_load_reg(rm, 1);
6589 tcg_gen_ext16u_i32(tmp3, tmp);
6590 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6591 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 0));
6592 tcg_gen_shri_i32(tmp3, tmp, 16);
6593 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6594 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 1));
6595 tcg_temp_free_i32(tmp);
6596 tcg_gen_ext16u_i32(tmp3, tmp2);
6597 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6598 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 2));
6599 tcg_gen_shri_i32(tmp3, tmp2, 16);
6600 gen_helper_neon_fcvt_f16_to_f32(cpu_F0s, tmp3, cpu_env);
6601 tcg_gen_st_f32(cpu_F0s, cpu_env, neon_reg_offset(rd, 3));
6602 tcg_temp_free_i32(tmp2);
6603 tcg_temp_free_i32(tmp3);
6604 break;
6605 case NEON_2RM_AESE: case NEON_2RM_AESMC:
6606 if (!arm_feature(env, ARM_FEATURE_V8_AES)
6607 || ((rm | rd) & 1)) {
6608 return 1;
6610 tmp = tcg_const_i32(rd);
6611 tmp2 = tcg_const_i32(rm);
6613 /* Bit 6 is the lowest opcode bit; it distinguishes between
6614 * encryption (AESE/AESMC) and decryption (AESD/AESIMC)
6616 tmp3 = tcg_const_i32(extract32(insn, 6, 1));
6618 if (op == NEON_2RM_AESE) {
6619 gen_helper_crypto_aese(cpu_env, tmp, tmp2, tmp3);
6620 } else {
6621 gen_helper_crypto_aesmc(cpu_env, tmp, tmp2, tmp3);
6623 tcg_temp_free_i32(tmp);
6624 tcg_temp_free_i32(tmp2);
6625 tcg_temp_free_i32(tmp3);
6626 break;
6627 case NEON_2RM_SHA1H:
6628 if (!arm_feature(env, ARM_FEATURE_V8_SHA1)
6629 || ((rm | rd) & 1)) {
6630 return 1;
6632 tmp = tcg_const_i32(rd);
6633 tmp2 = tcg_const_i32(rm);
6635 gen_helper_crypto_sha1h(cpu_env, tmp, tmp2);
6637 tcg_temp_free_i32(tmp);
6638 tcg_temp_free_i32(tmp2);
6639 break;
6640 case NEON_2RM_SHA1SU1:
6641 if ((rm | rd) & 1) {
6642 return 1;
6644 /* bit 6 (q): set -> SHA256SU0, cleared -> SHA1SU1 */
6645 if (q) {
6646 if (!arm_feature(env, ARM_FEATURE_V8_SHA256)) {
6647 return 1;
6649 } else if (!arm_feature(env, ARM_FEATURE_V8_SHA1)) {
6650 return 1;
6652 tmp = tcg_const_i32(rd);
6653 tmp2 = tcg_const_i32(rm);
6654 if (q) {
6655 gen_helper_crypto_sha256su0(cpu_env, tmp, tmp2);
6656 } else {
6657 gen_helper_crypto_sha1su1(cpu_env, tmp, tmp2);
6659 tcg_temp_free_i32(tmp);
6660 tcg_temp_free_i32(tmp2);
6661 break;
6662 default:
6663 elementwise:
6664 for (pass = 0; pass < (q ? 4 : 2); pass++) {
6665 if (neon_2rm_is_float_op(op)) {
6666 tcg_gen_ld_f32(cpu_F0s, cpu_env,
6667 neon_reg_offset(rm, pass));
6668 TCGV_UNUSED_I32(tmp);
6669 } else {
6670 tmp = neon_load_reg(rm, pass);
6672 switch (op) {
6673 case NEON_2RM_VREV32:
6674 switch (size) {
6675 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
6676 case 1: gen_swap_half(tmp); break;
6677 default: abort();
6679 break;
6680 case NEON_2RM_VREV16:
6681 gen_rev16(tmp);
6682 break;
6683 case NEON_2RM_VCLS:
6684 switch (size) {
6685 case 0: gen_helper_neon_cls_s8(tmp, tmp); break;
6686 case 1: gen_helper_neon_cls_s16(tmp, tmp); break;
6687 case 2: gen_helper_neon_cls_s32(tmp, tmp); break;
6688 default: abort();
6690 break;
6691 case NEON_2RM_VCLZ:
6692 switch (size) {
6693 case 0: gen_helper_neon_clz_u8(tmp, tmp); break;
6694 case 1: gen_helper_neon_clz_u16(tmp, tmp); break;
6695 case 2: gen_helper_clz(tmp, tmp); break;
6696 default: abort();
6698 break;
6699 case NEON_2RM_VCNT:
6700 gen_helper_neon_cnt_u8(tmp, tmp);
6701 break;
6702 case NEON_2RM_VMVN:
6703 tcg_gen_not_i32(tmp, tmp);
6704 break;
6705 case NEON_2RM_VQABS:
6706 switch (size) {
6707 case 0:
6708 gen_helper_neon_qabs_s8(tmp, cpu_env, tmp);
6709 break;
6710 case 1:
6711 gen_helper_neon_qabs_s16(tmp, cpu_env, tmp);
6712 break;
6713 case 2:
6714 gen_helper_neon_qabs_s32(tmp, cpu_env, tmp);
6715 break;
6716 default: abort();
6718 break;
6719 case NEON_2RM_VQNEG:
6720 switch (size) {
6721 case 0:
6722 gen_helper_neon_qneg_s8(tmp, cpu_env, tmp);
6723 break;
6724 case 1:
6725 gen_helper_neon_qneg_s16(tmp, cpu_env, tmp);
6726 break;
6727 case 2:
6728 gen_helper_neon_qneg_s32(tmp, cpu_env, tmp);
6729 break;
6730 default: abort();
6732 break;
6733 case NEON_2RM_VCGT0: case NEON_2RM_VCLE0:
6734 tmp2 = tcg_const_i32(0);
6735 switch(size) {
6736 case 0: gen_helper_neon_cgt_s8(tmp, tmp, tmp2); break;
6737 case 1: gen_helper_neon_cgt_s16(tmp, tmp, tmp2); break;
6738 case 2: gen_helper_neon_cgt_s32(tmp, tmp, tmp2); break;
6739 default: abort();
6741 tcg_temp_free_i32(tmp2);
6742 if (op == NEON_2RM_VCLE0) {
6743 tcg_gen_not_i32(tmp, tmp);
6745 break;
6746 case NEON_2RM_VCGE0: case NEON_2RM_VCLT0:
6747 tmp2 = tcg_const_i32(0);
6748 switch(size) {
6749 case 0: gen_helper_neon_cge_s8(tmp, tmp, tmp2); break;
6750 case 1: gen_helper_neon_cge_s16(tmp, tmp, tmp2); break;
6751 case 2: gen_helper_neon_cge_s32(tmp, tmp, tmp2); break;
6752 default: abort();
6754 tcg_temp_free_i32(tmp2);
6755 if (op == NEON_2RM_VCLT0) {
6756 tcg_gen_not_i32(tmp, tmp);
6758 break;
6759 case NEON_2RM_VCEQ0:
6760 tmp2 = tcg_const_i32(0);
6761 switch(size) {
6762 case 0: gen_helper_neon_ceq_u8(tmp, tmp, tmp2); break;
6763 case 1: gen_helper_neon_ceq_u16(tmp, tmp, tmp2); break;
6764 case 2: gen_helper_neon_ceq_u32(tmp, tmp, tmp2); break;
6765 default: abort();
6767 tcg_temp_free_i32(tmp2);
6768 break;
6769 case NEON_2RM_VABS:
6770 switch(size) {
6771 case 0: gen_helper_neon_abs_s8(tmp, tmp); break;
6772 case 1: gen_helper_neon_abs_s16(tmp, tmp); break;
6773 case 2: tcg_gen_abs_i32(tmp, tmp); break;
6774 default: abort();
6776 break;
6777 case NEON_2RM_VNEG:
6778 tmp2 = tcg_const_i32(0);
6779 gen_neon_rsb(size, tmp, tmp2);
6780 tcg_temp_free_i32(tmp2);
6781 break;
6782 case NEON_2RM_VCGT0_F:
6784 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6785 tmp2 = tcg_const_i32(0);
6786 gen_helper_neon_cgt_f32(tmp, tmp, tmp2, fpstatus);
6787 tcg_temp_free_i32(tmp2);
6788 tcg_temp_free_ptr(fpstatus);
6789 break;
6791 case NEON_2RM_VCGE0_F:
6793 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6794 tmp2 = tcg_const_i32(0);
6795 gen_helper_neon_cge_f32(tmp, tmp, tmp2, fpstatus);
6796 tcg_temp_free_i32(tmp2);
6797 tcg_temp_free_ptr(fpstatus);
6798 break;
6800 case NEON_2RM_VCEQ0_F:
6802 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6803 tmp2 = tcg_const_i32(0);
6804 gen_helper_neon_ceq_f32(tmp, tmp, tmp2, fpstatus);
6805 tcg_temp_free_i32(tmp2);
6806 tcg_temp_free_ptr(fpstatus);
6807 break;
6809 case NEON_2RM_VCLE0_F:
6811 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6812 tmp2 = tcg_const_i32(0);
6813 gen_helper_neon_cge_f32(tmp, tmp2, tmp, fpstatus);
6814 tcg_temp_free_i32(tmp2);
6815 tcg_temp_free_ptr(fpstatus);
6816 break;
6818 case NEON_2RM_VCLT0_F:
6820 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6821 tmp2 = tcg_const_i32(0);
6822 gen_helper_neon_cgt_f32(tmp, tmp2, tmp, fpstatus);
6823 tcg_temp_free_i32(tmp2);
6824 tcg_temp_free_ptr(fpstatus);
6825 break;
6827 case NEON_2RM_VABS_F:
6828 gen_vfp_abs(0);
6829 break;
6830 case NEON_2RM_VNEG_F:
6831 gen_vfp_neg(0);
6832 break;
6833 case NEON_2RM_VSWP:
6834 tmp2 = neon_load_reg(rd, pass);
6835 neon_store_reg(rm, pass, tmp2);
6836 break;
6837 case NEON_2RM_VTRN:
6838 tmp2 = neon_load_reg(rd, pass);
6839 switch (size) {
6840 case 0: gen_neon_trn_u8(tmp, tmp2); break;
6841 case 1: gen_neon_trn_u16(tmp, tmp2); break;
6842 default: abort();
6844 neon_store_reg(rm, pass, tmp2);
6845 break;
6846 case NEON_2RM_VRINTN:
6847 case NEON_2RM_VRINTA:
6848 case NEON_2RM_VRINTM:
6849 case NEON_2RM_VRINTP:
6850 case NEON_2RM_VRINTZ:
6852 TCGv_i32 tcg_rmode;
6853 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6854 int rmode;
6856 if (op == NEON_2RM_VRINTZ) {
6857 rmode = FPROUNDING_ZERO;
6858 } else {
6859 rmode = fp_decode_rm[((op & 0x6) >> 1) ^ 1];
6862 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6863 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6864 cpu_env);
6865 gen_helper_rints(cpu_F0s, cpu_F0s, fpstatus);
6866 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6867 cpu_env);
6868 tcg_temp_free_ptr(fpstatus);
6869 tcg_temp_free_i32(tcg_rmode);
6870 break;
6872 case NEON_2RM_VRINTX:
6874 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6875 gen_helper_rints_exact(cpu_F0s, cpu_F0s, fpstatus);
6876 tcg_temp_free_ptr(fpstatus);
6877 break;
6879 case NEON_2RM_VCVTAU:
6880 case NEON_2RM_VCVTAS:
6881 case NEON_2RM_VCVTNU:
6882 case NEON_2RM_VCVTNS:
6883 case NEON_2RM_VCVTPU:
6884 case NEON_2RM_VCVTPS:
6885 case NEON_2RM_VCVTMU:
6886 case NEON_2RM_VCVTMS:
6888 bool is_signed = !extract32(insn, 7, 1);
6889 TCGv_ptr fpst = get_fpstatus_ptr(1);
6890 TCGv_i32 tcg_rmode, tcg_shift;
6891 int rmode = fp_decode_rm[extract32(insn, 8, 2)];
6893 tcg_shift = tcg_const_i32(0);
6894 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6895 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6896 cpu_env);
6898 if (is_signed) {
6899 gen_helper_vfp_tosls(cpu_F0s, cpu_F0s,
6900 tcg_shift, fpst);
6901 } else {
6902 gen_helper_vfp_touls(cpu_F0s, cpu_F0s,
6903 tcg_shift, fpst);
6906 gen_helper_set_neon_rmode(tcg_rmode, tcg_rmode,
6907 cpu_env);
6908 tcg_temp_free_i32(tcg_rmode);
6909 tcg_temp_free_i32(tcg_shift);
6910 tcg_temp_free_ptr(fpst);
6911 break;
6913 case NEON_2RM_VRECPE:
6915 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6916 gen_helper_recpe_u32(tmp, tmp, fpstatus);
6917 tcg_temp_free_ptr(fpstatus);
6918 break;
6920 case NEON_2RM_VRSQRTE:
6922 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6923 gen_helper_rsqrte_u32(tmp, tmp, fpstatus);
6924 tcg_temp_free_ptr(fpstatus);
6925 break;
6927 case NEON_2RM_VRECPE_F:
6929 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6930 gen_helper_recpe_f32(cpu_F0s, cpu_F0s, fpstatus);
6931 tcg_temp_free_ptr(fpstatus);
6932 break;
6934 case NEON_2RM_VRSQRTE_F:
6936 TCGv_ptr fpstatus = get_fpstatus_ptr(1);
6937 gen_helper_rsqrte_f32(cpu_F0s, cpu_F0s, fpstatus);
6938 tcg_temp_free_ptr(fpstatus);
6939 break;
6941 case NEON_2RM_VCVT_FS: /* VCVT.F32.S32 */
6942 gen_vfp_sito(0, 1);
6943 break;
6944 case NEON_2RM_VCVT_FU: /* VCVT.F32.U32 */
6945 gen_vfp_uito(0, 1);
6946 break;
6947 case NEON_2RM_VCVT_SF: /* VCVT.S32.F32 */
6948 gen_vfp_tosiz(0, 1);
6949 break;
6950 case NEON_2RM_VCVT_UF: /* VCVT.U32.F32 */
6951 gen_vfp_touiz(0, 1);
6952 break;
6953 default:
6954 /* Reserved op values were caught by the
6955 * neon_2rm_sizes[] check earlier.
6957 abort();
6959 if (neon_2rm_is_float_op(op)) {
6960 tcg_gen_st_f32(cpu_F0s, cpu_env,
6961 neon_reg_offset(rd, pass));
6962 } else {
6963 neon_store_reg(rd, pass, tmp);
6966 break;
6968 } else if ((insn & (1 << 10)) == 0) {
6969 /* VTBL, VTBX. */
6970 int n = ((insn >> 8) & 3) + 1;
6971 if ((rn + n) > 32) {
6972 /* This is UNPREDICTABLE; we choose to UNDEF to avoid the
6973 * helper function running off the end of the register file.
6975 return 1;
6977 n <<= 3;
6978 if (insn & (1 << 6)) {
6979 tmp = neon_load_reg(rd, 0);
6980 } else {
6981 tmp = tcg_temp_new_i32();
6982 tcg_gen_movi_i32(tmp, 0);
6984 tmp2 = neon_load_reg(rm, 0);
6985 tmp4 = tcg_const_i32(rn);
6986 tmp5 = tcg_const_i32(n);
6987 gen_helper_neon_tbl(tmp2, cpu_env, tmp2, tmp, tmp4, tmp5);
6988 tcg_temp_free_i32(tmp);
6989 if (insn & (1 << 6)) {
6990 tmp = neon_load_reg(rd, 1);
6991 } else {
6992 tmp = tcg_temp_new_i32();
6993 tcg_gen_movi_i32(tmp, 0);
6995 tmp3 = neon_load_reg(rm, 1);
6996 gen_helper_neon_tbl(tmp3, cpu_env, tmp3, tmp, tmp4, tmp5);
6997 tcg_temp_free_i32(tmp5);
6998 tcg_temp_free_i32(tmp4);
6999 neon_store_reg(rd, 0, tmp2);
7000 neon_store_reg(rd, 1, tmp3);
7001 tcg_temp_free_i32(tmp);
7002 } else if ((insn & 0x380) == 0) {
7003 /* VDUP */
7004 if ((insn & (7 << 16)) == 0 || (q && (rd & 1))) {
7005 return 1;
7007 if (insn & (1 << 19)) {
7008 tmp = neon_load_reg(rm, 1);
7009 } else {
7010 tmp = neon_load_reg(rm, 0);
7012 if (insn & (1 << 16)) {
7013 gen_neon_dup_u8(tmp, ((insn >> 17) & 3) * 8);
7014 } else if (insn & (1 << 17)) {
7015 if ((insn >> 18) & 1)
7016 gen_neon_dup_high16(tmp);
7017 else
7018 gen_neon_dup_low16(tmp);
7020 for (pass = 0; pass < (q ? 4 : 2); pass++) {
7021 tmp2 = tcg_temp_new_i32();
7022 tcg_gen_mov_i32(tmp2, tmp);
7023 neon_store_reg(rd, pass, tmp2);
7025 tcg_temp_free_i32(tmp);
7026 } else {
7027 return 1;
7031 return 0;
7034 static int disas_coproc_insn(CPUARMState * env, DisasContext *s, uint32_t insn)
7036 int cpnum, is64, crn, crm, opc1, opc2, isread, rt, rt2;
7037 const ARMCPRegInfo *ri;
7039 cpnum = (insn >> 8) & 0xf;
7041 /* First check for coprocessor space used for XScale/iwMMXt insns */
7042 if (arm_feature(env, ARM_FEATURE_XSCALE) && (cpnum < 2)) {
7043 if (extract32(s->c15_cpar, cpnum, 1) == 0) {
7044 return 1;
7046 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7047 return disas_iwmmxt_insn(env, s, insn);
7048 } else if (arm_feature(env, ARM_FEATURE_XSCALE)) {
7049 return disas_dsp_insn(env, s, insn);
7051 return 1;
7054 /* Otherwise treat as a generic register access */
7055 is64 = (insn & (1 << 25)) == 0;
7056 if (!is64 && ((insn & (1 << 4)) == 0)) {
7057 /* cdp */
7058 return 1;
7061 crm = insn & 0xf;
7062 if (is64) {
7063 crn = 0;
7064 opc1 = (insn >> 4) & 0xf;
7065 opc2 = 0;
7066 rt2 = (insn >> 16) & 0xf;
7067 } else {
7068 crn = (insn >> 16) & 0xf;
7069 opc1 = (insn >> 21) & 7;
7070 opc2 = (insn >> 5) & 7;
7071 rt2 = 0;
7073 isread = (insn >> 20) & 1;
7074 rt = (insn >> 12) & 0xf;
7076 ri = get_arm_cp_reginfo(s->cp_regs,
7077 ENCODE_CP_REG(cpnum, is64, crn, crm, opc1, opc2));
7078 if (ri) {
7079 /* Check access permissions */
7080 if (!cp_access_ok(s->current_el, ri, isread)) {
7081 return 1;
7084 if (ri->accessfn ||
7085 (arm_feature(env, ARM_FEATURE_XSCALE) && cpnum < 14)) {
7086 /* Emit code to perform further access permissions checks at
7087 * runtime; this may result in an exception.
7088 * Note that on XScale all cp0..c13 registers do an access check
7089 * call in order to handle c15_cpar.
7091 TCGv_ptr tmpptr;
7092 TCGv_i32 tcg_syn;
7093 uint32_t syndrome;
7095 /* Note that since we are an implementation which takes an
7096 * exception on a trapped conditional instruction only if the
7097 * instruction passes its condition code check, we can take
7098 * advantage of the clause in the ARM ARM that allows us to set
7099 * the COND field in the instruction to 0xE in all cases.
7100 * We could fish the actual condition out of the insn (ARM)
7101 * or the condexec bits (Thumb) but it isn't necessary.
7103 switch (cpnum) {
7104 case 14:
7105 if (is64) {
7106 syndrome = syn_cp14_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7107 isread, s->thumb);
7108 } else {
7109 syndrome = syn_cp14_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7110 rt, isread, s->thumb);
7112 break;
7113 case 15:
7114 if (is64) {
7115 syndrome = syn_cp15_rrt_trap(1, 0xe, opc1, crm, rt, rt2,
7116 isread, s->thumb);
7117 } else {
7118 syndrome = syn_cp15_rt_trap(1, 0xe, opc1, opc2, crn, crm,
7119 rt, isread, s->thumb);
7121 break;
7122 default:
7123 /* ARMv8 defines that only coprocessors 14 and 15 exist,
7124 * so this can only happen if this is an ARMv7 or earlier CPU,
7125 * in which case the syndrome information won't actually be
7126 * guest visible.
7128 assert(!arm_feature(env, ARM_FEATURE_V8));
7129 syndrome = syn_uncategorized();
7130 break;
7133 gen_set_pc_im(s, s->pc);
7134 tmpptr = tcg_const_ptr(ri);
7135 tcg_syn = tcg_const_i32(syndrome);
7136 gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
7137 tcg_temp_free_ptr(tmpptr);
7138 tcg_temp_free_i32(tcg_syn);
7141 /* Handle special cases first */
7142 switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
7143 case ARM_CP_NOP:
7144 return 0;
7145 case ARM_CP_WFI:
7146 if (isread) {
7147 return 1;
7149 gen_set_pc_im(s, s->pc);
7150 s->is_jmp = DISAS_WFI;
7151 return 0;
7152 default:
7153 break;
7156 if (use_icount && (ri->type & ARM_CP_IO)) {
7157 gen_io_start();
7160 if (isread) {
7161 /* Read */
7162 if (is64) {
7163 TCGv_i64 tmp64;
7164 TCGv_i32 tmp;
7165 if (ri->type & ARM_CP_CONST) {
7166 tmp64 = tcg_const_i64(ri->resetvalue);
7167 } else if (ri->readfn) {
7168 TCGv_ptr tmpptr;
7169 tmp64 = tcg_temp_new_i64();
7170 tmpptr = tcg_const_ptr(ri);
7171 gen_helper_get_cp_reg64(tmp64, cpu_env, tmpptr);
7172 tcg_temp_free_ptr(tmpptr);
7173 } else {
7174 tmp64 = tcg_temp_new_i64();
7175 tcg_gen_ld_i64(tmp64, cpu_env, ri->fieldoffset);
7177 tmp = tcg_temp_new_i32();
7178 tcg_gen_trunc_i64_i32(tmp, tmp64);
7179 store_reg(s, rt, tmp);
7180 tcg_gen_shri_i64(tmp64, tmp64, 32);
7181 tmp = tcg_temp_new_i32();
7182 tcg_gen_trunc_i64_i32(tmp, tmp64);
7183 tcg_temp_free_i64(tmp64);
7184 store_reg(s, rt2, tmp);
7185 } else {
7186 TCGv_i32 tmp;
7187 if (ri->type & ARM_CP_CONST) {
7188 tmp = tcg_const_i32(ri->resetvalue);
7189 } else if (ri->readfn) {
7190 TCGv_ptr tmpptr;
7191 tmp = tcg_temp_new_i32();
7192 tmpptr = tcg_const_ptr(ri);
7193 gen_helper_get_cp_reg(tmp, cpu_env, tmpptr);
7194 tcg_temp_free_ptr(tmpptr);
7195 } else {
7196 tmp = load_cpu_offset(ri->fieldoffset);
7198 if (rt == 15) {
7199 /* Destination register of r15 for 32 bit loads sets
7200 * the condition codes from the high 4 bits of the value
7202 gen_set_nzcv(tmp);
7203 tcg_temp_free_i32(tmp);
7204 } else {
7205 store_reg(s, rt, tmp);
7208 } else {
7209 /* Write */
7210 if (ri->type & ARM_CP_CONST) {
7211 /* If not forbidden by access permissions, treat as WI */
7212 return 0;
7215 if (is64) {
7216 TCGv_i32 tmplo, tmphi;
7217 TCGv_i64 tmp64 = tcg_temp_new_i64();
7218 tmplo = load_reg(s, rt);
7219 tmphi = load_reg(s, rt2);
7220 tcg_gen_concat_i32_i64(tmp64, tmplo, tmphi);
7221 tcg_temp_free_i32(tmplo);
7222 tcg_temp_free_i32(tmphi);
7223 if (ri->writefn) {
7224 TCGv_ptr tmpptr = tcg_const_ptr(ri);
7225 gen_helper_set_cp_reg64(cpu_env, tmpptr, tmp64);
7226 tcg_temp_free_ptr(tmpptr);
7227 } else {
7228 tcg_gen_st_i64(tmp64, cpu_env, ri->fieldoffset);
7230 tcg_temp_free_i64(tmp64);
7231 } else {
7232 if (ri->writefn) {
7233 TCGv_i32 tmp;
7234 TCGv_ptr tmpptr;
7235 tmp = load_reg(s, rt);
7236 tmpptr = tcg_const_ptr(ri);
7237 gen_helper_set_cp_reg(cpu_env, tmpptr, tmp);
7238 tcg_temp_free_ptr(tmpptr);
7239 tcg_temp_free_i32(tmp);
7240 } else {
7241 TCGv_i32 tmp = load_reg(s, rt);
7242 store_cpu_offset(tmp, ri->fieldoffset);
7247 if (use_icount && (ri->type & ARM_CP_IO)) {
7248 /* I/O operations must end the TB here (whether read or write) */
7249 gen_io_end();
7250 gen_lookup_tb(s);
7251 } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
7252 /* We default to ending the TB on a coprocessor register write,
7253 * but allow this to be suppressed by the register definition
7254 * (usually only necessary to work around guest bugs).
7256 gen_lookup_tb(s);
7259 return 0;
7262 /* Unknown register; this might be a guest error or a QEMU
7263 * unimplemented feature.
7265 if (is64) {
7266 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7267 "64 bit system register cp:%d opc1: %d crm:%d\n",
7268 isread ? "read" : "write", cpnum, opc1, crm);
7269 } else {
7270 qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch32 "
7271 "system register cp:%d opc1:%d crn:%d crm:%d opc2:%d\n",
7272 isread ? "read" : "write", cpnum, opc1, crn, crm, opc2);
7275 return 1;
7279 /* Store a 64-bit value to a register pair. Clobbers val. */
7280 static void gen_storeq_reg(DisasContext *s, int rlow, int rhigh, TCGv_i64 val)
7282 TCGv_i32 tmp;
7283 tmp = tcg_temp_new_i32();
7284 tcg_gen_trunc_i64_i32(tmp, val);
7285 store_reg(s, rlow, tmp);
7286 tmp = tcg_temp_new_i32();
7287 tcg_gen_shri_i64(val, val, 32);
7288 tcg_gen_trunc_i64_i32(tmp, val);
7289 store_reg(s, rhigh, tmp);
7292 /* load a 32-bit value from a register and perform a 64-bit accumulate. */
7293 static void gen_addq_lo(DisasContext *s, TCGv_i64 val, int rlow)
7295 TCGv_i64 tmp;
7296 TCGv_i32 tmp2;
7298 /* Load value and extend to 64 bits. */
7299 tmp = tcg_temp_new_i64();
7300 tmp2 = load_reg(s, rlow);
7301 tcg_gen_extu_i32_i64(tmp, tmp2);
7302 tcg_temp_free_i32(tmp2);
7303 tcg_gen_add_i64(val, val, tmp);
7304 tcg_temp_free_i64(tmp);
7307 /* load and add a 64-bit value from a register pair. */
7308 static void gen_addq(DisasContext *s, TCGv_i64 val, int rlow, int rhigh)
7310 TCGv_i64 tmp;
7311 TCGv_i32 tmpl;
7312 TCGv_i32 tmph;
7314 /* Load 64-bit value rd:rn. */
7315 tmpl = load_reg(s, rlow);
7316 tmph = load_reg(s, rhigh);
7317 tmp = tcg_temp_new_i64();
7318 tcg_gen_concat_i32_i64(tmp, tmpl, tmph);
7319 tcg_temp_free_i32(tmpl);
7320 tcg_temp_free_i32(tmph);
7321 tcg_gen_add_i64(val, val, tmp);
7322 tcg_temp_free_i64(tmp);
7325 /* Set N and Z flags from hi|lo. */
7326 static void gen_logicq_cc(TCGv_i32 lo, TCGv_i32 hi)
7328 tcg_gen_mov_i32(cpu_NF, hi);
7329 tcg_gen_or_i32(cpu_ZF, lo, hi);
7332 /* Load/Store exclusive instructions are implemented by remembering
7333 the value/address loaded, and seeing if these are the same
7334 when the store is performed. This should be sufficient to implement
7335 the architecturally mandated semantics, and avoids having to monitor
7336 regular stores.
7338 In system emulation mode only one CPU will be running at once, so
7339 this sequence is effectively atomic. In user emulation mode we
7340 throw an exception and handle the atomic operation elsewhere. */
7341 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
7342 TCGv_i32 addr, int size)
7344 TCGv_i32 tmp = tcg_temp_new_i32();
7346 s->is_ldex = true;
7348 switch (size) {
7349 case 0:
7350 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
7351 break;
7352 case 1:
7353 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
7354 break;
7355 case 2:
7356 case 3:
7357 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7358 break;
7359 default:
7360 abort();
7363 if (size == 3) {
7364 TCGv_i32 tmp2 = tcg_temp_new_i32();
7365 TCGv_i32 tmp3 = tcg_temp_new_i32();
7367 tcg_gen_addi_i32(tmp2, addr, 4);
7368 gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
7369 tcg_temp_free_i32(tmp2);
7370 tcg_gen_concat_i32_i64(cpu_exclusive_val, tmp, tmp3);
7371 store_reg(s, rt2, tmp3);
7372 } else {
7373 tcg_gen_extu_i32_i64(cpu_exclusive_val, tmp);
7376 store_reg(s, rt, tmp);
7377 tcg_gen_extu_i32_i64(cpu_exclusive_addr, addr);
7380 static void gen_clrex(DisasContext *s)
7382 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7385 #ifdef CONFIG_USER_ONLY
7386 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7387 TCGv_i32 addr, int size)
7389 tcg_gen_extu_i32_i64(cpu_exclusive_test, addr);
7390 tcg_gen_movi_i32(cpu_exclusive_info,
7391 size | (rd << 4) | (rt << 8) | (rt2 << 12));
7392 gen_exception_internal_insn(s, 4, EXCP_STREX);
7394 #else
7395 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
7396 TCGv_i32 addr, int size)
7398 TCGv_i32 tmp;
7399 TCGv_i64 val64, extaddr;
7400 int done_label;
7401 int fail_label;
7403 /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]) {
7404 [addr] = {Rt};
7405 {Rd} = 0;
7406 } else {
7407 {Rd} = 1;
7408 } */
7409 fail_label = gen_new_label();
7410 done_label = gen_new_label();
7411 extaddr = tcg_temp_new_i64();
7412 tcg_gen_extu_i32_i64(extaddr, addr);
7413 tcg_gen_brcond_i64(TCG_COND_NE, extaddr, cpu_exclusive_addr, fail_label);
7414 tcg_temp_free_i64(extaddr);
7416 tmp = tcg_temp_new_i32();
7417 switch (size) {
7418 case 0:
7419 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
7420 break;
7421 case 1:
7422 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
7423 break;
7424 case 2:
7425 case 3:
7426 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7427 break;
7428 default:
7429 abort();
7432 val64 = tcg_temp_new_i64();
7433 if (size == 3) {
7434 TCGv_i32 tmp2 = tcg_temp_new_i32();
7435 TCGv_i32 tmp3 = tcg_temp_new_i32();
7436 tcg_gen_addi_i32(tmp2, addr, 4);
7437 gen_aa32_ld32u(tmp3, tmp2, get_mem_index(s));
7438 tcg_temp_free_i32(tmp2);
7439 tcg_gen_concat_i32_i64(val64, tmp, tmp3);
7440 tcg_temp_free_i32(tmp3);
7441 } else {
7442 tcg_gen_extu_i32_i64(val64, tmp);
7444 tcg_temp_free_i32(tmp);
7446 tcg_gen_brcond_i64(TCG_COND_NE, val64, cpu_exclusive_val, fail_label);
7447 tcg_temp_free_i64(val64);
7449 tmp = load_reg(s, rt);
7450 switch (size) {
7451 case 0:
7452 gen_aa32_st8(tmp, addr, get_mem_index(s));
7453 break;
7454 case 1:
7455 gen_aa32_st16(tmp, addr, get_mem_index(s));
7456 break;
7457 case 2:
7458 case 3:
7459 gen_aa32_st32(tmp, addr, get_mem_index(s));
7460 break;
7461 default:
7462 abort();
7464 tcg_temp_free_i32(tmp);
7465 if (size == 3) {
7466 tcg_gen_addi_i32(addr, addr, 4);
7467 tmp = load_reg(s, rt2);
7468 gen_aa32_st32(tmp, addr, get_mem_index(s));
7469 tcg_temp_free_i32(tmp);
7471 tcg_gen_movi_i32(cpu_R[rd], 0);
7472 tcg_gen_br(done_label);
7473 gen_set_label(fail_label);
7474 tcg_gen_movi_i32(cpu_R[rd], 1);
7475 gen_set_label(done_label);
7476 tcg_gen_movi_i64(cpu_exclusive_addr, -1);
7478 #endif
7480 /* gen_srs:
7481 * @env: CPUARMState
7482 * @s: DisasContext
7483 * @mode: mode field from insn (which stack to store to)
7484 * @amode: addressing mode (DA/IA/DB/IB), encoded as per P,U bits in ARM insn
7485 * @writeback: true if writeback bit set
7487 * Generate code for the SRS (Store Return State) insn.
7489 static void gen_srs(DisasContext *s,
7490 uint32_t mode, uint32_t amode, bool writeback)
7492 int32_t offset;
7493 TCGv_i32 addr = tcg_temp_new_i32();
7494 TCGv_i32 tmp = tcg_const_i32(mode);
7495 gen_helper_get_r13_banked(addr, cpu_env, tmp);
7496 tcg_temp_free_i32(tmp);
7497 switch (amode) {
7498 case 0: /* DA */
7499 offset = -4;
7500 break;
7501 case 1: /* IA */
7502 offset = 0;
7503 break;
7504 case 2: /* DB */
7505 offset = -8;
7506 break;
7507 case 3: /* IB */
7508 offset = 4;
7509 break;
7510 default:
7511 abort();
7513 tcg_gen_addi_i32(addr, addr, offset);
7514 tmp = load_reg(s, 14);
7515 gen_aa32_st32(tmp, addr, get_mem_index(s));
7516 tcg_temp_free_i32(tmp);
7517 tmp = load_cpu_field(spsr);
7518 tcg_gen_addi_i32(addr, addr, 4);
7519 gen_aa32_st32(tmp, addr, get_mem_index(s));
7520 tcg_temp_free_i32(tmp);
7521 if (writeback) {
7522 switch (amode) {
7523 case 0:
7524 offset = -8;
7525 break;
7526 case 1:
7527 offset = 4;
7528 break;
7529 case 2:
7530 offset = -4;
7531 break;
7532 case 3:
7533 offset = 0;
7534 break;
7535 default:
7536 abort();
7538 tcg_gen_addi_i32(addr, addr, offset);
7539 tmp = tcg_const_i32(mode);
7540 gen_helper_set_r13_banked(cpu_env, tmp, addr);
7541 tcg_temp_free_i32(tmp);
7543 tcg_temp_free_i32(addr);
7546 static void disas_arm_insn(CPUARMState * env, DisasContext *s)
7548 unsigned int cond, insn, val, op1, i, shift, rm, rs, rn, rd, sh;
7549 TCGv_i32 tmp;
7550 TCGv_i32 tmp2;
7551 TCGv_i32 tmp3;
7552 TCGv_i32 addr;
7553 TCGv_i64 tmp64;
7555 insn = arm_ldl_code(env, s->pc, s->bswap_code);
7556 s->pc += 4;
7558 /* M variants do not implement ARM mode. */
7559 if (IS_M(env))
7560 goto illegal_op;
7561 cond = insn >> 28;
7562 if (cond == 0xf){
7563 /* In ARMv3 and v4 the NV condition is UNPREDICTABLE; we
7564 * choose to UNDEF. In ARMv5 and above the space is used
7565 * for miscellaneous unconditional instructions.
7567 ARCH(5);
7569 /* Unconditional instructions. */
7570 if (((insn >> 25) & 7) == 1) {
7571 /* NEON Data processing. */
7572 if (!arm_feature(env, ARM_FEATURE_NEON))
7573 goto illegal_op;
7575 if (disas_neon_data_insn(env, s, insn))
7576 goto illegal_op;
7577 return;
7579 if ((insn & 0x0f100000) == 0x04000000) {
7580 /* NEON load/store. */
7581 if (!arm_feature(env, ARM_FEATURE_NEON))
7582 goto illegal_op;
7584 if (disas_neon_ls_insn(env, s, insn))
7585 goto illegal_op;
7586 return;
7588 if ((insn & 0x0f000e10) == 0x0e000a00) {
7589 /* VFP. */
7590 if (disas_vfp_insn(env, s, insn)) {
7591 goto illegal_op;
7593 return;
7595 if (((insn & 0x0f30f000) == 0x0510f000) ||
7596 ((insn & 0x0f30f010) == 0x0710f000)) {
7597 if ((insn & (1 << 22)) == 0) {
7598 /* PLDW; v7MP */
7599 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7600 goto illegal_op;
7603 /* Otherwise PLD; v5TE+ */
7604 ARCH(5TE);
7605 return;
7607 if (((insn & 0x0f70f000) == 0x0450f000) ||
7608 ((insn & 0x0f70f010) == 0x0650f000)) {
7609 ARCH(7);
7610 return; /* PLI; V7 */
7612 if (((insn & 0x0f700000) == 0x04100000) ||
7613 ((insn & 0x0f700010) == 0x06100000)) {
7614 if (!arm_feature(env, ARM_FEATURE_V7MP)) {
7615 goto illegal_op;
7617 return; /* v7MP: Unallocated memory hint: must NOP */
7620 if ((insn & 0x0ffffdff) == 0x01010000) {
7621 ARCH(6);
7622 /* setend */
7623 if (((insn >> 9) & 1) != s->bswap_code) {
7624 /* Dynamic endianness switching not implemented. */
7625 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
7626 goto illegal_op;
7628 return;
7629 } else if ((insn & 0x0fffff00) == 0x057ff000) {
7630 switch ((insn >> 4) & 0xf) {
7631 case 1: /* clrex */
7632 ARCH(6K);
7633 gen_clrex(s);
7634 return;
7635 case 4: /* dsb */
7636 case 5: /* dmb */
7637 case 6: /* isb */
7638 ARCH(7);
7639 /* We don't emulate caches so these are a no-op. */
7640 return;
7641 default:
7642 goto illegal_op;
7644 } else if ((insn & 0x0e5fffe0) == 0x084d0500) {
7645 /* srs */
7646 if (IS_USER(s)) {
7647 goto illegal_op;
7649 ARCH(6);
7650 gen_srs(s, (insn & 0x1f), (insn >> 23) & 3, insn & (1 << 21));
7651 return;
7652 } else if ((insn & 0x0e50ffe0) == 0x08100a00) {
7653 /* rfe */
7654 int32_t offset;
7655 if (IS_USER(s))
7656 goto illegal_op;
7657 ARCH(6);
7658 rn = (insn >> 16) & 0xf;
7659 addr = load_reg(s, rn);
7660 i = (insn >> 23) & 3;
7661 switch (i) {
7662 case 0: offset = -4; break; /* DA */
7663 case 1: offset = 0; break; /* IA */
7664 case 2: offset = -8; break; /* DB */
7665 case 3: offset = 4; break; /* IB */
7666 default: abort();
7668 if (offset)
7669 tcg_gen_addi_i32(addr, addr, offset);
7670 /* Load PC into tmp and CPSR into tmp2. */
7671 tmp = tcg_temp_new_i32();
7672 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
7673 tcg_gen_addi_i32(addr, addr, 4);
7674 tmp2 = tcg_temp_new_i32();
7675 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
7676 if (insn & (1 << 21)) {
7677 /* Base writeback. */
7678 switch (i) {
7679 case 0: offset = -8; break;
7680 case 1: offset = 4; break;
7681 case 2: offset = -4; break;
7682 case 3: offset = 0; break;
7683 default: abort();
7685 if (offset)
7686 tcg_gen_addi_i32(addr, addr, offset);
7687 store_reg(s, rn, addr);
7688 } else {
7689 tcg_temp_free_i32(addr);
7691 gen_rfe(s, tmp, tmp2);
7692 return;
7693 } else if ((insn & 0x0e000000) == 0x0a000000) {
7694 /* branch link and change to thumb (blx <offset>) */
7695 int32_t offset;
7697 val = (uint32_t)s->pc;
7698 tmp = tcg_temp_new_i32();
7699 tcg_gen_movi_i32(tmp, val);
7700 store_reg(s, 14, tmp);
7701 /* Sign-extend the 24-bit offset */
7702 offset = (((int32_t)insn) << 8) >> 8;
7703 /* offset * 4 + bit24 * 2 + (thumb bit) */
7704 val += (offset << 2) | ((insn >> 23) & 2) | 1;
7705 /* pipeline offset */
7706 val += 4;
7707 /* protected by ARCH(5); above, near the start of uncond block */
7708 gen_bx_im(s, val);
7709 return;
7710 } else if ((insn & 0x0e000f00) == 0x0c000100) {
7711 if (arm_feature(env, ARM_FEATURE_IWMMXT)) {
7712 /* iWMMXt register transfer. */
7713 if (extract32(s->c15_cpar, 1, 1)) {
7714 if (!disas_iwmmxt_insn(env, s, insn)) {
7715 return;
7719 } else if ((insn & 0x0fe00000) == 0x0c400000) {
7720 /* Coprocessor double register transfer. */
7721 ARCH(5TE);
7722 } else if ((insn & 0x0f000010) == 0x0e000010) {
7723 /* Additional coprocessor register transfer. */
7724 } else if ((insn & 0x0ff10020) == 0x01000000) {
7725 uint32_t mask;
7726 uint32_t val;
7727 /* cps (privileged) */
7728 if (IS_USER(s))
7729 return;
7730 mask = val = 0;
7731 if (insn & (1 << 19)) {
7732 if (insn & (1 << 8))
7733 mask |= CPSR_A;
7734 if (insn & (1 << 7))
7735 mask |= CPSR_I;
7736 if (insn & (1 << 6))
7737 mask |= CPSR_F;
7738 if (insn & (1 << 18))
7739 val |= mask;
7741 if (insn & (1 << 17)) {
7742 mask |= CPSR_M;
7743 val |= (insn & 0x1f);
7745 if (mask) {
7746 gen_set_psr_im(s, mask, 0, val);
7748 return;
7750 goto illegal_op;
7752 if (cond != 0xe) {
7753 /* if not always execute, we generate a conditional jump to
7754 next instruction */
7755 s->condlabel = gen_new_label();
7756 arm_gen_test_cc(cond ^ 1, s->condlabel);
7757 s->condjmp = 1;
7759 if ((insn & 0x0f900000) == 0x03000000) {
7760 if ((insn & (1 << 21)) == 0) {
7761 ARCH(6T2);
7762 rd = (insn >> 12) & 0xf;
7763 val = ((insn >> 4) & 0xf000) | (insn & 0xfff);
7764 if ((insn & (1 << 22)) == 0) {
7765 /* MOVW */
7766 tmp = tcg_temp_new_i32();
7767 tcg_gen_movi_i32(tmp, val);
7768 } else {
7769 /* MOVT */
7770 tmp = load_reg(s, rd);
7771 tcg_gen_ext16u_i32(tmp, tmp);
7772 tcg_gen_ori_i32(tmp, tmp, val << 16);
7774 store_reg(s, rd, tmp);
7775 } else {
7776 if (((insn >> 12) & 0xf) != 0xf)
7777 goto illegal_op;
7778 if (((insn >> 16) & 0xf) == 0) {
7779 gen_nop_hint(s, insn & 0xff);
7780 } else {
7781 /* CPSR = immediate */
7782 val = insn & 0xff;
7783 shift = ((insn >> 8) & 0xf) * 2;
7784 if (shift)
7785 val = (val >> shift) | (val << (32 - shift));
7786 i = ((insn & (1 << 22)) != 0);
7787 if (gen_set_psr_im(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, val))
7788 goto illegal_op;
7791 } else if ((insn & 0x0f900000) == 0x01000000
7792 && (insn & 0x00000090) != 0x00000090) {
7793 /* miscellaneous instructions */
7794 op1 = (insn >> 21) & 3;
7795 sh = (insn >> 4) & 0xf;
7796 rm = insn & 0xf;
7797 switch (sh) {
7798 case 0x0: /* move program status register */
7799 if (op1 & 1) {
7800 /* PSR = reg */
7801 tmp = load_reg(s, rm);
7802 i = ((op1 & 2) != 0);
7803 if (gen_set_psr(s, msr_mask(env, s, (insn >> 16) & 0xf, i), i, tmp))
7804 goto illegal_op;
7805 } else {
7806 /* reg = PSR */
7807 rd = (insn >> 12) & 0xf;
7808 if (op1 & 2) {
7809 if (IS_USER(s))
7810 goto illegal_op;
7811 tmp = load_cpu_field(spsr);
7812 } else {
7813 tmp = tcg_temp_new_i32();
7814 gen_helper_cpsr_read(tmp, cpu_env);
7816 store_reg(s, rd, tmp);
7818 break;
7819 case 0x1:
7820 if (op1 == 1) {
7821 /* branch/exchange thumb (bx). */
7822 ARCH(4T);
7823 tmp = load_reg(s, rm);
7824 gen_bx(s, tmp);
7825 } else if (op1 == 3) {
7826 /* clz */
7827 ARCH(5);
7828 rd = (insn >> 12) & 0xf;
7829 tmp = load_reg(s, rm);
7830 gen_helper_clz(tmp, tmp);
7831 store_reg(s, rd, tmp);
7832 } else {
7833 goto illegal_op;
7835 break;
7836 case 0x2:
7837 if (op1 == 1) {
7838 ARCH(5J); /* bxj */
7839 /* Trivial implementation equivalent to bx. */
7840 tmp = load_reg(s, rm);
7841 gen_bx(s, tmp);
7842 } else {
7843 goto illegal_op;
7845 break;
7846 case 0x3:
7847 if (op1 != 1)
7848 goto illegal_op;
7850 ARCH(5);
7851 /* branch link/exchange thumb (blx) */
7852 tmp = load_reg(s, rm);
7853 tmp2 = tcg_temp_new_i32();
7854 tcg_gen_movi_i32(tmp2, s->pc);
7855 store_reg(s, 14, tmp2);
7856 gen_bx(s, tmp);
7857 break;
7858 case 0x4:
7860 /* crc32/crc32c */
7861 uint32_t c = extract32(insn, 8, 4);
7863 /* Check this CPU supports ARMv8 CRC instructions.
7864 * op1 == 3 is UNPREDICTABLE but handle as UNDEFINED.
7865 * Bits 8, 10 and 11 should be zero.
7867 if (!arm_feature(env, ARM_FEATURE_CRC) || op1 == 0x3 ||
7868 (c & 0xd) != 0) {
7869 goto illegal_op;
7872 rn = extract32(insn, 16, 4);
7873 rd = extract32(insn, 12, 4);
7875 tmp = load_reg(s, rn);
7876 tmp2 = load_reg(s, rm);
7877 if (op1 == 0) {
7878 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
7879 } else if (op1 == 1) {
7880 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
7882 tmp3 = tcg_const_i32(1 << op1);
7883 if (c & 0x2) {
7884 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
7885 } else {
7886 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
7888 tcg_temp_free_i32(tmp2);
7889 tcg_temp_free_i32(tmp3);
7890 store_reg(s, rd, tmp);
7891 break;
7893 case 0x5: /* saturating add/subtract */
7894 ARCH(5TE);
7895 rd = (insn >> 12) & 0xf;
7896 rn = (insn >> 16) & 0xf;
7897 tmp = load_reg(s, rm);
7898 tmp2 = load_reg(s, rn);
7899 if (op1 & 2)
7900 gen_helper_double_saturate(tmp2, cpu_env, tmp2);
7901 if (op1 & 1)
7902 gen_helper_sub_saturate(tmp, cpu_env, tmp, tmp2);
7903 else
7904 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
7905 tcg_temp_free_i32(tmp2);
7906 store_reg(s, rd, tmp);
7907 break;
7908 case 7:
7910 int imm16 = extract32(insn, 0, 4) | (extract32(insn, 8, 12) << 4);
7911 switch (op1) {
7912 case 1:
7913 /* bkpt */
7914 ARCH(5);
7915 gen_exception_insn(s, 4, EXCP_BKPT,
7916 syn_aa32_bkpt(imm16, false));
7917 break;
7918 case 2:
7919 /* Hypervisor call (v7) */
7920 ARCH(7);
7921 if (IS_USER(s)) {
7922 goto illegal_op;
7924 gen_hvc(s, imm16);
7925 break;
7926 case 3:
7927 /* Secure monitor call (v6+) */
7928 ARCH(6K);
7929 if (IS_USER(s)) {
7930 goto illegal_op;
7932 gen_smc(s);
7933 break;
7934 default:
7935 goto illegal_op;
7937 break;
7939 case 0x8: /* signed multiply */
7940 case 0xa:
7941 case 0xc:
7942 case 0xe:
7943 ARCH(5TE);
7944 rs = (insn >> 8) & 0xf;
7945 rn = (insn >> 12) & 0xf;
7946 rd = (insn >> 16) & 0xf;
7947 if (op1 == 1) {
7948 /* (32 * 16) >> 16 */
7949 tmp = load_reg(s, rm);
7950 tmp2 = load_reg(s, rs);
7951 if (sh & 4)
7952 tcg_gen_sari_i32(tmp2, tmp2, 16);
7953 else
7954 gen_sxth(tmp2);
7955 tmp64 = gen_muls_i64_i32(tmp, tmp2);
7956 tcg_gen_shri_i64(tmp64, tmp64, 16);
7957 tmp = tcg_temp_new_i32();
7958 tcg_gen_trunc_i64_i32(tmp, tmp64);
7959 tcg_temp_free_i64(tmp64);
7960 if ((sh & 2) == 0) {
7961 tmp2 = load_reg(s, rn);
7962 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7963 tcg_temp_free_i32(tmp2);
7965 store_reg(s, rd, tmp);
7966 } else {
7967 /* 16 * 16 */
7968 tmp = load_reg(s, rm);
7969 tmp2 = load_reg(s, rs);
7970 gen_mulxy(tmp, tmp2, sh & 2, sh & 4);
7971 tcg_temp_free_i32(tmp2);
7972 if (op1 == 2) {
7973 tmp64 = tcg_temp_new_i64();
7974 tcg_gen_ext_i32_i64(tmp64, tmp);
7975 tcg_temp_free_i32(tmp);
7976 gen_addq(s, tmp64, rn, rd);
7977 gen_storeq_reg(s, rn, rd, tmp64);
7978 tcg_temp_free_i64(tmp64);
7979 } else {
7980 if (op1 == 0) {
7981 tmp2 = load_reg(s, rn);
7982 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
7983 tcg_temp_free_i32(tmp2);
7985 store_reg(s, rd, tmp);
7988 break;
7989 default:
7990 goto illegal_op;
7992 } else if (((insn & 0x0e000000) == 0 &&
7993 (insn & 0x00000090) != 0x90) ||
7994 ((insn & 0x0e000000) == (1 << 25))) {
7995 int set_cc, logic_cc, shiftop;
7997 op1 = (insn >> 21) & 0xf;
7998 set_cc = (insn >> 20) & 1;
7999 logic_cc = table_logic_cc[op1] & set_cc;
8001 /* data processing instruction */
8002 if (insn & (1 << 25)) {
8003 /* immediate operand */
8004 val = insn & 0xff;
8005 shift = ((insn >> 8) & 0xf) * 2;
8006 if (shift) {
8007 val = (val >> shift) | (val << (32 - shift));
8009 tmp2 = tcg_temp_new_i32();
8010 tcg_gen_movi_i32(tmp2, val);
8011 if (logic_cc && shift) {
8012 gen_set_CF_bit31(tmp2);
8014 } else {
8015 /* register */
8016 rm = (insn) & 0xf;
8017 tmp2 = load_reg(s, rm);
8018 shiftop = (insn >> 5) & 3;
8019 if (!(insn & (1 << 4))) {
8020 shift = (insn >> 7) & 0x1f;
8021 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
8022 } else {
8023 rs = (insn >> 8) & 0xf;
8024 tmp = load_reg(s, rs);
8025 gen_arm_shift_reg(tmp2, shiftop, tmp, logic_cc);
8028 if (op1 != 0x0f && op1 != 0x0d) {
8029 rn = (insn >> 16) & 0xf;
8030 tmp = load_reg(s, rn);
8031 } else {
8032 TCGV_UNUSED_I32(tmp);
8034 rd = (insn >> 12) & 0xf;
8035 switch(op1) {
8036 case 0x00:
8037 tcg_gen_and_i32(tmp, tmp, tmp2);
8038 if (logic_cc) {
8039 gen_logic_CC(tmp);
8041 store_reg_bx(env, s, rd, tmp);
8042 break;
8043 case 0x01:
8044 tcg_gen_xor_i32(tmp, tmp, tmp2);
8045 if (logic_cc) {
8046 gen_logic_CC(tmp);
8048 store_reg_bx(env, s, rd, tmp);
8049 break;
8050 case 0x02:
8051 if (set_cc && rd == 15) {
8052 /* SUBS r15, ... is used for exception return. */
8053 if (IS_USER(s)) {
8054 goto illegal_op;
8056 gen_sub_CC(tmp, tmp, tmp2);
8057 gen_exception_return(s, tmp);
8058 } else {
8059 if (set_cc) {
8060 gen_sub_CC(tmp, tmp, tmp2);
8061 } else {
8062 tcg_gen_sub_i32(tmp, tmp, tmp2);
8064 store_reg_bx(env, s, rd, tmp);
8066 break;
8067 case 0x03:
8068 if (set_cc) {
8069 gen_sub_CC(tmp, tmp2, tmp);
8070 } else {
8071 tcg_gen_sub_i32(tmp, tmp2, tmp);
8073 store_reg_bx(env, s, rd, tmp);
8074 break;
8075 case 0x04:
8076 if (set_cc) {
8077 gen_add_CC(tmp, tmp, tmp2);
8078 } else {
8079 tcg_gen_add_i32(tmp, tmp, tmp2);
8081 store_reg_bx(env, s, rd, tmp);
8082 break;
8083 case 0x05:
8084 if (set_cc) {
8085 gen_adc_CC(tmp, tmp, tmp2);
8086 } else {
8087 gen_add_carry(tmp, tmp, tmp2);
8089 store_reg_bx(env, s, rd, tmp);
8090 break;
8091 case 0x06:
8092 if (set_cc) {
8093 gen_sbc_CC(tmp, tmp, tmp2);
8094 } else {
8095 gen_sub_carry(tmp, tmp, tmp2);
8097 store_reg_bx(env, s, rd, tmp);
8098 break;
8099 case 0x07:
8100 if (set_cc) {
8101 gen_sbc_CC(tmp, tmp2, tmp);
8102 } else {
8103 gen_sub_carry(tmp, tmp2, tmp);
8105 store_reg_bx(env, s, rd, tmp);
8106 break;
8107 case 0x08:
8108 if (set_cc) {
8109 tcg_gen_and_i32(tmp, tmp, tmp2);
8110 gen_logic_CC(tmp);
8112 tcg_temp_free_i32(tmp);
8113 break;
8114 case 0x09:
8115 if (set_cc) {
8116 tcg_gen_xor_i32(tmp, tmp, tmp2);
8117 gen_logic_CC(tmp);
8119 tcg_temp_free_i32(tmp);
8120 break;
8121 case 0x0a:
8122 if (set_cc) {
8123 gen_sub_CC(tmp, tmp, tmp2);
8125 tcg_temp_free_i32(tmp);
8126 break;
8127 case 0x0b:
8128 if (set_cc) {
8129 gen_add_CC(tmp, tmp, tmp2);
8131 tcg_temp_free_i32(tmp);
8132 break;
8133 case 0x0c:
8134 tcg_gen_or_i32(tmp, tmp, tmp2);
8135 if (logic_cc) {
8136 gen_logic_CC(tmp);
8138 store_reg_bx(env, s, rd, tmp);
8139 break;
8140 case 0x0d:
8141 if (logic_cc && rd == 15) {
8142 /* MOVS r15, ... is used for exception return. */
8143 if (IS_USER(s)) {
8144 goto illegal_op;
8146 gen_exception_return(s, tmp2);
8147 } else {
8148 if (logic_cc) {
8149 gen_logic_CC(tmp2);
8151 store_reg_bx(env, s, rd, tmp2);
8153 break;
8154 case 0x0e:
8155 tcg_gen_andc_i32(tmp, tmp, tmp2);
8156 if (logic_cc) {
8157 gen_logic_CC(tmp);
8159 store_reg_bx(env, s, rd, tmp);
8160 break;
8161 default:
8162 case 0x0f:
8163 tcg_gen_not_i32(tmp2, tmp2);
8164 if (logic_cc) {
8165 gen_logic_CC(tmp2);
8167 store_reg_bx(env, s, rd, tmp2);
8168 break;
8170 if (op1 != 0x0f && op1 != 0x0d) {
8171 tcg_temp_free_i32(tmp2);
8173 } else {
8174 /* other instructions */
8175 op1 = (insn >> 24) & 0xf;
8176 switch(op1) {
8177 case 0x0:
8178 case 0x1:
8179 /* multiplies, extra load/stores */
8180 sh = (insn >> 5) & 3;
8181 if (sh == 0) {
8182 if (op1 == 0x0) {
8183 rd = (insn >> 16) & 0xf;
8184 rn = (insn >> 12) & 0xf;
8185 rs = (insn >> 8) & 0xf;
8186 rm = (insn) & 0xf;
8187 op1 = (insn >> 20) & 0xf;
8188 switch (op1) {
8189 case 0: case 1: case 2: case 3: case 6:
8190 /* 32 bit mul */
8191 tmp = load_reg(s, rs);
8192 tmp2 = load_reg(s, rm);
8193 tcg_gen_mul_i32(tmp, tmp, tmp2);
8194 tcg_temp_free_i32(tmp2);
8195 if (insn & (1 << 22)) {
8196 /* Subtract (mls) */
8197 ARCH(6T2);
8198 tmp2 = load_reg(s, rn);
8199 tcg_gen_sub_i32(tmp, tmp2, tmp);
8200 tcg_temp_free_i32(tmp2);
8201 } else if (insn & (1 << 21)) {
8202 /* Add */
8203 tmp2 = load_reg(s, rn);
8204 tcg_gen_add_i32(tmp, tmp, tmp2);
8205 tcg_temp_free_i32(tmp2);
8207 if (insn & (1 << 20))
8208 gen_logic_CC(tmp);
8209 store_reg(s, rd, tmp);
8210 break;
8211 case 4:
8212 /* 64 bit mul double accumulate (UMAAL) */
8213 ARCH(6);
8214 tmp = load_reg(s, rs);
8215 tmp2 = load_reg(s, rm);
8216 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
8217 gen_addq_lo(s, tmp64, rn);
8218 gen_addq_lo(s, tmp64, rd);
8219 gen_storeq_reg(s, rn, rd, tmp64);
8220 tcg_temp_free_i64(tmp64);
8221 break;
8222 case 8: case 9: case 10: case 11:
8223 case 12: case 13: case 14: case 15:
8224 /* 64 bit mul: UMULL, UMLAL, SMULL, SMLAL. */
8225 tmp = load_reg(s, rs);
8226 tmp2 = load_reg(s, rm);
8227 if (insn & (1 << 22)) {
8228 tcg_gen_muls2_i32(tmp, tmp2, tmp, tmp2);
8229 } else {
8230 tcg_gen_mulu2_i32(tmp, tmp2, tmp, tmp2);
8232 if (insn & (1 << 21)) { /* mult accumulate */
8233 TCGv_i32 al = load_reg(s, rn);
8234 TCGv_i32 ah = load_reg(s, rd);
8235 tcg_gen_add2_i32(tmp, tmp2, tmp, tmp2, al, ah);
8236 tcg_temp_free_i32(al);
8237 tcg_temp_free_i32(ah);
8239 if (insn & (1 << 20)) {
8240 gen_logicq_cc(tmp, tmp2);
8242 store_reg(s, rn, tmp);
8243 store_reg(s, rd, tmp2);
8244 break;
8245 default:
8246 goto illegal_op;
8248 } else {
8249 rn = (insn >> 16) & 0xf;
8250 rd = (insn >> 12) & 0xf;
8251 if (insn & (1 << 23)) {
8252 /* load/store exclusive */
8253 int op2 = (insn >> 8) & 3;
8254 op1 = (insn >> 21) & 0x3;
8256 switch (op2) {
8257 case 0: /* lda/stl */
8258 if (op1 == 1) {
8259 goto illegal_op;
8261 ARCH(8);
8262 break;
8263 case 1: /* reserved */
8264 goto illegal_op;
8265 case 2: /* ldaex/stlex */
8266 ARCH(8);
8267 break;
8268 case 3: /* ldrex/strex */
8269 if (op1) {
8270 ARCH(6K);
8271 } else {
8272 ARCH(6);
8274 break;
8277 addr = tcg_temp_local_new_i32();
8278 load_reg_var(s, addr, rn);
8280 /* Since the emulation does not have barriers,
8281 the acquire/release semantics need no special
8282 handling */
8283 if (op2 == 0) {
8284 if (insn & (1 << 20)) {
8285 tmp = tcg_temp_new_i32();
8286 switch (op1) {
8287 case 0: /* lda */
8288 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8289 break;
8290 case 2: /* ldab */
8291 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
8292 break;
8293 case 3: /* ldah */
8294 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
8295 break;
8296 default:
8297 abort();
8299 store_reg(s, rd, tmp);
8300 } else {
8301 rm = insn & 0xf;
8302 tmp = load_reg(s, rm);
8303 switch (op1) {
8304 case 0: /* stl */
8305 gen_aa32_st32(tmp, addr, get_mem_index(s));
8306 break;
8307 case 2: /* stlb */
8308 gen_aa32_st8(tmp, addr, get_mem_index(s));
8309 break;
8310 case 3: /* stlh */
8311 gen_aa32_st16(tmp, addr, get_mem_index(s));
8312 break;
8313 default:
8314 abort();
8316 tcg_temp_free_i32(tmp);
8318 } else if (insn & (1 << 20)) {
8319 switch (op1) {
8320 case 0: /* ldrex */
8321 gen_load_exclusive(s, rd, 15, addr, 2);
8322 break;
8323 case 1: /* ldrexd */
8324 gen_load_exclusive(s, rd, rd + 1, addr, 3);
8325 break;
8326 case 2: /* ldrexb */
8327 gen_load_exclusive(s, rd, 15, addr, 0);
8328 break;
8329 case 3: /* ldrexh */
8330 gen_load_exclusive(s, rd, 15, addr, 1);
8331 break;
8332 default:
8333 abort();
8335 } else {
8336 rm = insn & 0xf;
8337 switch (op1) {
8338 case 0: /* strex */
8339 gen_store_exclusive(s, rd, rm, 15, addr, 2);
8340 break;
8341 case 1: /* strexd */
8342 gen_store_exclusive(s, rd, rm, rm + 1, addr, 3);
8343 break;
8344 case 2: /* strexb */
8345 gen_store_exclusive(s, rd, rm, 15, addr, 0);
8346 break;
8347 case 3: /* strexh */
8348 gen_store_exclusive(s, rd, rm, 15, addr, 1);
8349 break;
8350 default:
8351 abort();
8354 tcg_temp_free_i32(addr);
8355 } else {
8356 /* SWP instruction */
8357 rm = (insn) & 0xf;
8359 /* ??? This is not really atomic. However we know
8360 we never have multiple CPUs running in parallel,
8361 so it is good enough. */
8362 addr = load_reg(s, rn);
8363 tmp = load_reg(s, rm);
8364 tmp2 = tcg_temp_new_i32();
8365 if (insn & (1 << 22)) {
8366 gen_aa32_ld8u(tmp2, addr, get_mem_index(s));
8367 gen_aa32_st8(tmp, addr, get_mem_index(s));
8368 } else {
8369 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
8370 gen_aa32_st32(tmp, addr, get_mem_index(s));
8372 tcg_temp_free_i32(tmp);
8373 tcg_temp_free_i32(addr);
8374 store_reg(s, rd, tmp2);
8377 } else {
8378 int address_offset;
8379 int load;
8380 /* Misc load/store */
8381 rn = (insn >> 16) & 0xf;
8382 rd = (insn >> 12) & 0xf;
8383 addr = load_reg(s, rn);
8384 if (insn & (1 << 24))
8385 gen_add_datah_offset(s, insn, 0, addr);
8386 address_offset = 0;
8387 if (insn & (1 << 20)) {
8388 /* load */
8389 tmp = tcg_temp_new_i32();
8390 switch(sh) {
8391 case 1:
8392 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
8393 break;
8394 case 2:
8395 gen_aa32_ld8s(tmp, addr, get_mem_index(s));
8396 break;
8397 default:
8398 case 3:
8399 gen_aa32_ld16s(tmp, addr, get_mem_index(s));
8400 break;
8402 load = 1;
8403 } else if (sh & 2) {
8404 ARCH(5TE);
8405 /* doubleword */
8406 if (sh & 1) {
8407 /* store */
8408 tmp = load_reg(s, rd);
8409 gen_aa32_st32(tmp, addr, get_mem_index(s));
8410 tcg_temp_free_i32(tmp);
8411 tcg_gen_addi_i32(addr, addr, 4);
8412 tmp = load_reg(s, rd + 1);
8413 gen_aa32_st32(tmp, addr, get_mem_index(s));
8414 tcg_temp_free_i32(tmp);
8415 load = 0;
8416 } else {
8417 /* load */
8418 tmp = tcg_temp_new_i32();
8419 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8420 store_reg(s, rd, tmp);
8421 tcg_gen_addi_i32(addr, addr, 4);
8422 tmp = tcg_temp_new_i32();
8423 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8424 rd++;
8425 load = 1;
8427 address_offset = -4;
8428 } else {
8429 /* store */
8430 tmp = load_reg(s, rd);
8431 gen_aa32_st16(tmp, addr, get_mem_index(s));
8432 tcg_temp_free_i32(tmp);
8433 load = 0;
8435 /* Perform base writeback before the loaded value to
8436 ensure correct behavior with overlapping index registers.
8437 ldrd with base writeback is is undefined if the
8438 destination and index registers overlap. */
8439 if (!(insn & (1 << 24))) {
8440 gen_add_datah_offset(s, insn, address_offset, addr);
8441 store_reg(s, rn, addr);
8442 } else if (insn & (1 << 21)) {
8443 if (address_offset)
8444 tcg_gen_addi_i32(addr, addr, address_offset);
8445 store_reg(s, rn, addr);
8446 } else {
8447 tcg_temp_free_i32(addr);
8449 if (load) {
8450 /* Complete the load. */
8451 store_reg(s, rd, tmp);
8454 break;
8455 case 0x4:
8456 case 0x5:
8457 goto do_ldst;
8458 case 0x6:
8459 case 0x7:
8460 if (insn & (1 << 4)) {
8461 ARCH(6);
8462 /* Armv6 Media instructions. */
8463 rm = insn & 0xf;
8464 rn = (insn >> 16) & 0xf;
8465 rd = (insn >> 12) & 0xf;
8466 rs = (insn >> 8) & 0xf;
8467 switch ((insn >> 23) & 3) {
8468 case 0: /* Parallel add/subtract. */
8469 op1 = (insn >> 20) & 7;
8470 tmp = load_reg(s, rn);
8471 tmp2 = load_reg(s, rm);
8472 sh = (insn >> 5) & 7;
8473 if ((op1 & 3) == 0 || sh == 5 || sh == 6)
8474 goto illegal_op;
8475 gen_arm_parallel_addsub(op1, sh, tmp, tmp2);
8476 tcg_temp_free_i32(tmp2);
8477 store_reg(s, rd, tmp);
8478 break;
8479 case 1:
8480 if ((insn & 0x00700020) == 0) {
8481 /* Halfword pack. */
8482 tmp = load_reg(s, rn);
8483 tmp2 = load_reg(s, rm);
8484 shift = (insn >> 7) & 0x1f;
8485 if (insn & (1 << 6)) {
8486 /* pkhtb */
8487 if (shift == 0)
8488 shift = 31;
8489 tcg_gen_sari_i32(tmp2, tmp2, shift);
8490 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
8491 tcg_gen_ext16u_i32(tmp2, tmp2);
8492 } else {
8493 /* pkhbt */
8494 if (shift)
8495 tcg_gen_shli_i32(tmp2, tmp2, shift);
8496 tcg_gen_ext16u_i32(tmp, tmp);
8497 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
8499 tcg_gen_or_i32(tmp, tmp, tmp2);
8500 tcg_temp_free_i32(tmp2);
8501 store_reg(s, rd, tmp);
8502 } else if ((insn & 0x00200020) == 0x00200000) {
8503 /* [us]sat */
8504 tmp = load_reg(s, rm);
8505 shift = (insn >> 7) & 0x1f;
8506 if (insn & (1 << 6)) {
8507 if (shift == 0)
8508 shift = 31;
8509 tcg_gen_sari_i32(tmp, tmp, shift);
8510 } else {
8511 tcg_gen_shli_i32(tmp, tmp, shift);
8513 sh = (insn >> 16) & 0x1f;
8514 tmp2 = tcg_const_i32(sh);
8515 if (insn & (1 << 22))
8516 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
8517 else
8518 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
8519 tcg_temp_free_i32(tmp2);
8520 store_reg(s, rd, tmp);
8521 } else if ((insn & 0x00300fe0) == 0x00200f20) {
8522 /* [us]sat16 */
8523 tmp = load_reg(s, rm);
8524 sh = (insn >> 16) & 0x1f;
8525 tmp2 = tcg_const_i32(sh);
8526 if (insn & (1 << 22))
8527 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
8528 else
8529 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
8530 tcg_temp_free_i32(tmp2);
8531 store_reg(s, rd, tmp);
8532 } else if ((insn & 0x00700fe0) == 0x00000fa0) {
8533 /* Select bytes. */
8534 tmp = load_reg(s, rn);
8535 tmp2 = load_reg(s, rm);
8536 tmp3 = tcg_temp_new_i32();
8537 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
8538 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
8539 tcg_temp_free_i32(tmp3);
8540 tcg_temp_free_i32(tmp2);
8541 store_reg(s, rd, tmp);
8542 } else if ((insn & 0x000003e0) == 0x00000060) {
8543 tmp = load_reg(s, rm);
8544 shift = (insn >> 10) & 3;
8545 /* ??? In many cases it's not necessary to do a
8546 rotate, a shift is sufficient. */
8547 if (shift != 0)
8548 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
8549 op1 = (insn >> 20) & 7;
8550 switch (op1) {
8551 case 0: gen_sxtb16(tmp); break;
8552 case 2: gen_sxtb(tmp); break;
8553 case 3: gen_sxth(tmp); break;
8554 case 4: gen_uxtb16(tmp); break;
8555 case 6: gen_uxtb(tmp); break;
8556 case 7: gen_uxth(tmp); break;
8557 default: goto illegal_op;
8559 if (rn != 15) {
8560 tmp2 = load_reg(s, rn);
8561 if ((op1 & 3) == 0) {
8562 gen_add16(tmp, tmp2);
8563 } else {
8564 tcg_gen_add_i32(tmp, tmp, tmp2);
8565 tcg_temp_free_i32(tmp2);
8568 store_reg(s, rd, tmp);
8569 } else if ((insn & 0x003f0f60) == 0x003f0f20) {
8570 /* rev */
8571 tmp = load_reg(s, rm);
8572 if (insn & (1 << 22)) {
8573 if (insn & (1 << 7)) {
8574 gen_revsh(tmp);
8575 } else {
8576 ARCH(6T2);
8577 gen_helper_rbit(tmp, tmp);
8579 } else {
8580 if (insn & (1 << 7))
8581 gen_rev16(tmp);
8582 else
8583 tcg_gen_bswap32_i32(tmp, tmp);
8585 store_reg(s, rd, tmp);
8586 } else {
8587 goto illegal_op;
8589 break;
8590 case 2: /* Multiplies (Type 3). */
8591 switch ((insn >> 20) & 0x7) {
8592 case 5:
8593 if (((insn >> 6) ^ (insn >> 7)) & 1) {
8594 /* op2 not 00x or 11x : UNDEF */
8595 goto illegal_op;
8597 /* Signed multiply most significant [accumulate].
8598 (SMMUL, SMMLA, SMMLS) */
8599 tmp = load_reg(s, rm);
8600 tmp2 = load_reg(s, rs);
8601 tmp64 = gen_muls_i64_i32(tmp, tmp2);
8603 if (rd != 15) {
8604 tmp = load_reg(s, rd);
8605 if (insn & (1 << 6)) {
8606 tmp64 = gen_subq_msw(tmp64, tmp);
8607 } else {
8608 tmp64 = gen_addq_msw(tmp64, tmp);
8611 if (insn & (1 << 5)) {
8612 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
8614 tcg_gen_shri_i64(tmp64, tmp64, 32);
8615 tmp = tcg_temp_new_i32();
8616 tcg_gen_trunc_i64_i32(tmp, tmp64);
8617 tcg_temp_free_i64(tmp64);
8618 store_reg(s, rn, tmp);
8619 break;
8620 case 0:
8621 case 4:
8622 /* SMLAD, SMUAD, SMLSD, SMUSD, SMLALD, SMLSLD */
8623 if (insn & (1 << 7)) {
8624 goto illegal_op;
8626 tmp = load_reg(s, rm);
8627 tmp2 = load_reg(s, rs);
8628 if (insn & (1 << 5))
8629 gen_swap_half(tmp2);
8630 gen_smul_dual(tmp, tmp2);
8631 if (insn & (1 << 22)) {
8632 /* smlald, smlsld */
8633 TCGv_i64 tmp64_2;
8635 tmp64 = tcg_temp_new_i64();
8636 tmp64_2 = tcg_temp_new_i64();
8637 tcg_gen_ext_i32_i64(tmp64, tmp);
8638 tcg_gen_ext_i32_i64(tmp64_2, tmp2);
8639 tcg_temp_free_i32(tmp);
8640 tcg_temp_free_i32(tmp2);
8641 if (insn & (1 << 6)) {
8642 tcg_gen_sub_i64(tmp64, tmp64, tmp64_2);
8643 } else {
8644 tcg_gen_add_i64(tmp64, tmp64, tmp64_2);
8646 tcg_temp_free_i64(tmp64_2);
8647 gen_addq(s, tmp64, rd, rn);
8648 gen_storeq_reg(s, rd, rn, tmp64);
8649 tcg_temp_free_i64(tmp64);
8650 } else {
8651 /* smuad, smusd, smlad, smlsd */
8652 if (insn & (1 << 6)) {
8653 /* This subtraction cannot overflow. */
8654 tcg_gen_sub_i32(tmp, tmp, tmp2);
8655 } else {
8656 /* This addition cannot overflow 32 bits;
8657 * however it may overflow considered as a
8658 * signed operation, in which case we must set
8659 * the Q flag.
8661 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8663 tcg_temp_free_i32(tmp2);
8664 if (rd != 15)
8666 tmp2 = load_reg(s, rd);
8667 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
8668 tcg_temp_free_i32(tmp2);
8670 store_reg(s, rn, tmp);
8672 break;
8673 case 1:
8674 case 3:
8675 /* SDIV, UDIV */
8676 if (!arm_feature(env, ARM_FEATURE_ARM_DIV)) {
8677 goto illegal_op;
8679 if (((insn >> 5) & 7) || (rd != 15)) {
8680 goto illegal_op;
8682 tmp = load_reg(s, rm);
8683 tmp2 = load_reg(s, rs);
8684 if (insn & (1 << 21)) {
8685 gen_helper_udiv(tmp, tmp, tmp2);
8686 } else {
8687 gen_helper_sdiv(tmp, tmp, tmp2);
8689 tcg_temp_free_i32(tmp2);
8690 store_reg(s, rn, tmp);
8691 break;
8692 default:
8693 goto illegal_op;
8695 break;
8696 case 3:
8697 op1 = ((insn >> 17) & 0x38) | ((insn >> 5) & 7);
8698 switch (op1) {
8699 case 0: /* Unsigned sum of absolute differences. */
8700 ARCH(6);
8701 tmp = load_reg(s, rm);
8702 tmp2 = load_reg(s, rs);
8703 gen_helper_usad8(tmp, tmp, tmp2);
8704 tcg_temp_free_i32(tmp2);
8705 if (rd != 15) {
8706 tmp2 = load_reg(s, rd);
8707 tcg_gen_add_i32(tmp, tmp, tmp2);
8708 tcg_temp_free_i32(tmp2);
8710 store_reg(s, rn, tmp);
8711 break;
8712 case 0x20: case 0x24: case 0x28: case 0x2c:
8713 /* Bitfield insert/clear. */
8714 ARCH(6T2);
8715 shift = (insn >> 7) & 0x1f;
8716 i = (insn >> 16) & 0x1f;
8717 i = i + 1 - shift;
8718 if (rm == 15) {
8719 tmp = tcg_temp_new_i32();
8720 tcg_gen_movi_i32(tmp, 0);
8721 } else {
8722 tmp = load_reg(s, rm);
8724 if (i != 32) {
8725 tmp2 = load_reg(s, rd);
8726 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, i);
8727 tcg_temp_free_i32(tmp2);
8729 store_reg(s, rd, tmp);
8730 break;
8731 case 0x12: case 0x16: case 0x1a: case 0x1e: /* sbfx */
8732 case 0x32: case 0x36: case 0x3a: case 0x3e: /* ubfx */
8733 ARCH(6T2);
8734 tmp = load_reg(s, rm);
8735 shift = (insn >> 7) & 0x1f;
8736 i = ((insn >> 16) & 0x1f) + 1;
8737 if (shift + i > 32)
8738 goto illegal_op;
8739 if (i < 32) {
8740 if (op1 & 0x20) {
8741 gen_ubfx(tmp, shift, (1u << i) - 1);
8742 } else {
8743 gen_sbfx(tmp, shift, i);
8746 store_reg(s, rd, tmp);
8747 break;
8748 default:
8749 goto illegal_op;
8751 break;
8753 break;
8755 do_ldst:
8756 /* Check for undefined extension instructions
8757 * per the ARM Bible IE:
8758 * xxxx 0111 1111 xxxx xxxx xxxx 1111 xxxx
8760 sh = (0xf << 20) | (0xf << 4);
8761 if (op1 == 0x7 && ((insn & sh) == sh))
8763 goto illegal_op;
8765 /* load/store byte/word */
8766 rn = (insn >> 16) & 0xf;
8767 rd = (insn >> 12) & 0xf;
8768 tmp2 = load_reg(s, rn);
8769 if ((insn & 0x01200000) == 0x00200000) {
8770 /* ldrt/strt */
8771 i = MMU_USER_IDX;
8772 } else {
8773 i = get_mem_index(s);
8775 if (insn & (1 << 24))
8776 gen_add_data_offset(s, insn, tmp2);
8777 if (insn & (1 << 20)) {
8778 /* load */
8779 tmp = tcg_temp_new_i32();
8780 if (insn & (1 << 22)) {
8781 gen_aa32_ld8u(tmp, tmp2, i);
8782 } else {
8783 gen_aa32_ld32u(tmp, tmp2, i);
8785 } else {
8786 /* store */
8787 tmp = load_reg(s, rd);
8788 if (insn & (1 << 22)) {
8789 gen_aa32_st8(tmp, tmp2, i);
8790 } else {
8791 gen_aa32_st32(tmp, tmp2, i);
8793 tcg_temp_free_i32(tmp);
8795 if (!(insn & (1 << 24))) {
8796 gen_add_data_offset(s, insn, tmp2);
8797 store_reg(s, rn, tmp2);
8798 } else if (insn & (1 << 21)) {
8799 store_reg(s, rn, tmp2);
8800 } else {
8801 tcg_temp_free_i32(tmp2);
8803 if (insn & (1 << 20)) {
8804 /* Complete the load. */
8805 store_reg_from_load(env, s, rd, tmp);
8807 break;
8808 case 0x08:
8809 case 0x09:
8811 int j, n, user, loaded_base;
8812 TCGv_i32 loaded_var;
8813 /* load/store multiple words */
8814 /* XXX: store correct base if write back */
8815 user = 0;
8816 if (insn & (1 << 22)) {
8817 if (IS_USER(s))
8818 goto illegal_op; /* only usable in supervisor mode */
8820 if ((insn & (1 << 15)) == 0)
8821 user = 1;
8823 rn = (insn >> 16) & 0xf;
8824 addr = load_reg(s, rn);
8826 /* compute total size */
8827 loaded_base = 0;
8828 TCGV_UNUSED_I32(loaded_var);
8829 n = 0;
8830 for(i=0;i<16;i++) {
8831 if (insn & (1 << i))
8832 n++;
8834 /* XXX: test invalid n == 0 case ? */
8835 if (insn & (1 << 23)) {
8836 if (insn & (1 << 24)) {
8837 /* pre increment */
8838 tcg_gen_addi_i32(addr, addr, 4);
8839 } else {
8840 /* post increment */
8842 } else {
8843 if (insn & (1 << 24)) {
8844 /* pre decrement */
8845 tcg_gen_addi_i32(addr, addr, -(n * 4));
8846 } else {
8847 /* post decrement */
8848 if (n != 1)
8849 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8852 j = 0;
8853 for(i=0;i<16;i++) {
8854 if (insn & (1 << i)) {
8855 if (insn & (1 << 20)) {
8856 /* load */
8857 tmp = tcg_temp_new_i32();
8858 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
8859 if (user) {
8860 tmp2 = tcg_const_i32(i);
8861 gen_helper_set_user_reg(cpu_env, tmp2, tmp);
8862 tcg_temp_free_i32(tmp2);
8863 tcg_temp_free_i32(tmp);
8864 } else if (i == rn) {
8865 loaded_var = tmp;
8866 loaded_base = 1;
8867 } else {
8868 store_reg_from_load(env, s, i, tmp);
8870 } else {
8871 /* store */
8872 if (i == 15) {
8873 /* special case: r15 = PC + 8 */
8874 val = (long)s->pc + 4;
8875 tmp = tcg_temp_new_i32();
8876 tcg_gen_movi_i32(tmp, val);
8877 } else if (user) {
8878 tmp = tcg_temp_new_i32();
8879 tmp2 = tcg_const_i32(i);
8880 gen_helper_get_user_reg(tmp, cpu_env, tmp2);
8881 tcg_temp_free_i32(tmp2);
8882 } else {
8883 tmp = load_reg(s, i);
8885 gen_aa32_st32(tmp, addr, get_mem_index(s));
8886 tcg_temp_free_i32(tmp);
8888 j++;
8889 /* no need to add after the last transfer */
8890 if (j != n)
8891 tcg_gen_addi_i32(addr, addr, 4);
8894 if (insn & (1 << 21)) {
8895 /* write back */
8896 if (insn & (1 << 23)) {
8897 if (insn & (1 << 24)) {
8898 /* pre increment */
8899 } else {
8900 /* post increment */
8901 tcg_gen_addi_i32(addr, addr, 4);
8903 } else {
8904 if (insn & (1 << 24)) {
8905 /* pre decrement */
8906 if (n != 1)
8907 tcg_gen_addi_i32(addr, addr, -((n - 1) * 4));
8908 } else {
8909 /* post decrement */
8910 tcg_gen_addi_i32(addr, addr, -(n * 4));
8913 store_reg(s, rn, addr);
8914 } else {
8915 tcg_temp_free_i32(addr);
8917 if (loaded_base) {
8918 store_reg(s, rn, loaded_var);
8920 if ((insn & (1 << 22)) && !user) {
8921 /* Restore CPSR from SPSR. */
8922 tmp = load_cpu_field(spsr);
8923 gen_set_cpsr(tmp, CPSR_ERET_MASK);
8924 tcg_temp_free_i32(tmp);
8925 s->is_jmp = DISAS_UPDATE;
8928 break;
8929 case 0xa:
8930 case 0xb:
8932 int32_t offset;
8934 /* branch (and link) */
8935 val = (int32_t)s->pc;
8936 if (insn & (1 << 24)) {
8937 tmp = tcg_temp_new_i32();
8938 tcg_gen_movi_i32(tmp, val);
8939 store_reg(s, 14, tmp);
8941 offset = sextract32(insn << 2, 0, 26);
8942 val += offset + 4;
8943 gen_jmp(s, val);
8945 break;
8946 case 0xc:
8947 case 0xd:
8948 case 0xe:
8949 if (((insn >> 8) & 0xe) == 10) {
8950 /* VFP. */
8951 if (disas_vfp_insn(env, s, insn)) {
8952 goto illegal_op;
8954 } else if (disas_coproc_insn(env, s, insn)) {
8955 /* Coprocessor. */
8956 goto illegal_op;
8958 break;
8959 case 0xf:
8960 /* swi */
8961 gen_set_pc_im(s, s->pc);
8962 s->svc_imm = extract32(insn, 0, 24);
8963 s->is_jmp = DISAS_SWI;
8964 break;
8965 default:
8966 illegal_op:
8967 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
8968 break;
8973 /* Return true if this is a Thumb-2 logical op. */
8974 static int
8975 thumb2_logic_op(int op)
8977 return (op < 8);
8980 /* Generate code for a Thumb-2 data processing operation. If CONDS is nonzero
8981 then set condition code flags based on the result of the operation.
8982 If SHIFTER_OUT is nonzero then set the carry flag for logical operations
8983 to the high bit of T1.
8984 Returns zero if the opcode is valid. */
8986 static int
8987 gen_thumb2_data_op(DisasContext *s, int op, int conds, uint32_t shifter_out,
8988 TCGv_i32 t0, TCGv_i32 t1)
8990 int logic_cc;
8992 logic_cc = 0;
8993 switch (op) {
8994 case 0: /* and */
8995 tcg_gen_and_i32(t0, t0, t1);
8996 logic_cc = conds;
8997 break;
8998 case 1: /* bic */
8999 tcg_gen_andc_i32(t0, t0, t1);
9000 logic_cc = conds;
9001 break;
9002 case 2: /* orr */
9003 tcg_gen_or_i32(t0, t0, t1);
9004 logic_cc = conds;
9005 break;
9006 case 3: /* orn */
9007 tcg_gen_orc_i32(t0, t0, t1);
9008 logic_cc = conds;
9009 break;
9010 case 4: /* eor */
9011 tcg_gen_xor_i32(t0, t0, t1);
9012 logic_cc = conds;
9013 break;
9014 case 8: /* add */
9015 if (conds)
9016 gen_add_CC(t0, t0, t1);
9017 else
9018 tcg_gen_add_i32(t0, t0, t1);
9019 break;
9020 case 10: /* adc */
9021 if (conds)
9022 gen_adc_CC(t0, t0, t1);
9023 else
9024 gen_adc(t0, t1);
9025 break;
9026 case 11: /* sbc */
9027 if (conds) {
9028 gen_sbc_CC(t0, t0, t1);
9029 } else {
9030 gen_sub_carry(t0, t0, t1);
9032 break;
9033 case 13: /* sub */
9034 if (conds)
9035 gen_sub_CC(t0, t0, t1);
9036 else
9037 tcg_gen_sub_i32(t0, t0, t1);
9038 break;
9039 case 14: /* rsb */
9040 if (conds)
9041 gen_sub_CC(t0, t1, t0);
9042 else
9043 tcg_gen_sub_i32(t0, t1, t0);
9044 break;
9045 default: /* 5, 6, 7, 9, 12, 15. */
9046 return 1;
9048 if (logic_cc) {
9049 gen_logic_CC(t0);
9050 if (shifter_out)
9051 gen_set_CF_bit31(t1);
9053 return 0;
9056 /* Translate a 32-bit thumb instruction. Returns nonzero if the instruction
9057 is not legal. */
9058 static int disas_thumb2_insn(CPUARMState *env, DisasContext *s, uint16_t insn_hw1)
9060 uint32_t insn, imm, shift, offset;
9061 uint32_t rd, rn, rm, rs;
9062 TCGv_i32 tmp;
9063 TCGv_i32 tmp2;
9064 TCGv_i32 tmp3;
9065 TCGv_i32 addr;
9066 TCGv_i64 tmp64;
9067 int op;
9068 int shiftop;
9069 int conds;
9070 int logic_cc;
9072 if (!(arm_feature(env, ARM_FEATURE_THUMB2)
9073 || arm_feature (env, ARM_FEATURE_M))) {
9074 /* Thumb-1 cores may need to treat bl and blx as a pair of
9075 16-bit instructions to get correct prefetch abort behavior. */
9076 insn = insn_hw1;
9077 if ((insn & (1 << 12)) == 0) {
9078 ARCH(5);
9079 /* Second half of blx. */
9080 offset = ((insn & 0x7ff) << 1);
9081 tmp = load_reg(s, 14);
9082 tcg_gen_addi_i32(tmp, tmp, offset);
9083 tcg_gen_andi_i32(tmp, tmp, 0xfffffffc);
9085 tmp2 = tcg_temp_new_i32();
9086 tcg_gen_movi_i32(tmp2, s->pc | 1);
9087 store_reg(s, 14, tmp2);
9088 gen_bx(s, tmp);
9089 return 0;
9091 if (insn & (1 << 11)) {
9092 /* Second half of bl. */
9093 offset = ((insn & 0x7ff) << 1) | 1;
9094 tmp = load_reg(s, 14);
9095 tcg_gen_addi_i32(tmp, tmp, offset);
9097 tmp2 = tcg_temp_new_i32();
9098 tcg_gen_movi_i32(tmp2, s->pc | 1);
9099 store_reg(s, 14, tmp2);
9100 gen_bx(s, tmp);
9101 return 0;
9103 if ((s->pc & ~TARGET_PAGE_MASK) == 0) {
9104 /* Instruction spans a page boundary. Implement it as two
9105 16-bit instructions in case the second half causes an
9106 prefetch abort. */
9107 offset = ((int32_t)insn << 21) >> 9;
9108 tcg_gen_movi_i32(cpu_R[14], s->pc + 2 + offset);
9109 return 0;
9111 /* Fall through to 32-bit decode. */
9114 insn = arm_lduw_code(env, s->pc, s->bswap_code);
9115 s->pc += 2;
9116 insn |= (uint32_t)insn_hw1 << 16;
9118 if ((insn & 0xf800e800) != 0xf000e800) {
9119 ARCH(6T2);
9122 rn = (insn >> 16) & 0xf;
9123 rs = (insn >> 12) & 0xf;
9124 rd = (insn >> 8) & 0xf;
9125 rm = insn & 0xf;
9126 switch ((insn >> 25) & 0xf) {
9127 case 0: case 1: case 2: case 3:
9128 /* 16-bit instructions. Should never happen. */
9129 abort();
9130 case 4:
9131 if (insn & (1 << 22)) {
9132 /* Other load/store, table branch. */
9133 if (insn & 0x01200000) {
9134 /* Load/store doubleword. */
9135 if (rn == 15) {
9136 addr = tcg_temp_new_i32();
9137 tcg_gen_movi_i32(addr, s->pc & ~3);
9138 } else {
9139 addr = load_reg(s, rn);
9141 offset = (insn & 0xff) * 4;
9142 if ((insn & (1 << 23)) == 0)
9143 offset = -offset;
9144 if (insn & (1 << 24)) {
9145 tcg_gen_addi_i32(addr, addr, offset);
9146 offset = 0;
9148 if (insn & (1 << 20)) {
9149 /* ldrd */
9150 tmp = tcg_temp_new_i32();
9151 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9152 store_reg(s, rs, tmp);
9153 tcg_gen_addi_i32(addr, addr, 4);
9154 tmp = tcg_temp_new_i32();
9155 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9156 store_reg(s, rd, tmp);
9157 } else {
9158 /* strd */
9159 tmp = load_reg(s, rs);
9160 gen_aa32_st32(tmp, addr, get_mem_index(s));
9161 tcg_temp_free_i32(tmp);
9162 tcg_gen_addi_i32(addr, addr, 4);
9163 tmp = load_reg(s, rd);
9164 gen_aa32_st32(tmp, addr, get_mem_index(s));
9165 tcg_temp_free_i32(tmp);
9167 if (insn & (1 << 21)) {
9168 /* Base writeback. */
9169 if (rn == 15)
9170 goto illegal_op;
9171 tcg_gen_addi_i32(addr, addr, offset - 4);
9172 store_reg(s, rn, addr);
9173 } else {
9174 tcg_temp_free_i32(addr);
9176 } else if ((insn & (1 << 23)) == 0) {
9177 /* Load/store exclusive word. */
9178 addr = tcg_temp_local_new_i32();
9179 load_reg_var(s, addr, rn);
9180 tcg_gen_addi_i32(addr, addr, (insn & 0xff) << 2);
9181 if (insn & (1 << 20)) {
9182 gen_load_exclusive(s, rs, 15, addr, 2);
9183 } else {
9184 gen_store_exclusive(s, rd, rs, 15, addr, 2);
9186 tcg_temp_free_i32(addr);
9187 } else if ((insn & (7 << 5)) == 0) {
9188 /* Table Branch. */
9189 if (rn == 15) {
9190 addr = tcg_temp_new_i32();
9191 tcg_gen_movi_i32(addr, s->pc);
9192 } else {
9193 addr = load_reg(s, rn);
9195 tmp = load_reg(s, rm);
9196 tcg_gen_add_i32(addr, addr, tmp);
9197 if (insn & (1 << 4)) {
9198 /* tbh */
9199 tcg_gen_add_i32(addr, addr, tmp);
9200 tcg_temp_free_i32(tmp);
9201 tmp = tcg_temp_new_i32();
9202 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
9203 } else { /* tbb */
9204 tcg_temp_free_i32(tmp);
9205 tmp = tcg_temp_new_i32();
9206 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
9208 tcg_temp_free_i32(addr);
9209 tcg_gen_shli_i32(tmp, tmp, 1);
9210 tcg_gen_addi_i32(tmp, tmp, s->pc);
9211 store_reg(s, 15, tmp);
9212 } else {
9213 int op2 = (insn >> 6) & 0x3;
9214 op = (insn >> 4) & 0x3;
9215 switch (op2) {
9216 case 0:
9217 goto illegal_op;
9218 case 1:
9219 /* Load/store exclusive byte/halfword/doubleword */
9220 if (op == 2) {
9221 goto illegal_op;
9223 ARCH(7);
9224 break;
9225 case 2:
9226 /* Load-acquire/store-release */
9227 if (op == 3) {
9228 goto illegal_op;
9230 /* Fall through */
9231 case 3:
9232 /* Load-acquire/store-release exclusive */
9233 ARCH(8);
9234 break;
9236 addr = tcg_temp_local_new_i32();
9237 load_reg_var(s, addr, rn);
9238 if (!(op2 & 1)) {
9239 if (insn & (1 << 20)) {
9240 tmp = tcg_temp_new_i32();
9241 switch (op) {
9242 case 0: /* ldab */
9243 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
9244 break;
9245 case 1: /* ldah */
9246 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
9247 break;
9248 case 2: /* lda */
9249 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9250 break;
9251 default:
9252 abort();
9254 store_reg(s, rs, tmp);
9255 } else {
9256 tmp = load_reg(s, rs);
9257 switch (op) {
9258 case 0: /* stlb */
9259 gen_aa32_st8(tmp, addr, get_mem_index(s));
9260 break;
9261 case 1: /* stlh */
9262 gen_aa32_st16(tmp, addr, get_mem_index(s));
9263 break;
9264 case 2: /* stl */
9265 gen_aa32_st32(tmp, addr, get_mem_index(s));
9266 break;
9267 default:
9268 abort();
9270 tcg_temp_free_i32(tmp);
9272 } else if (insn & (1 << 20)) {
9273 gen_load_exclusive(s, rs, rd, addr, op);
9274 } else {
9275 gen_store_exclusive(s, rm, rs, rd, addr, op);
9277 tcg_temp_free_i32(addr);
9279 } else {
9280 /* Load/store multiple, RFE, SRS. */
9281 if (((insn >> 23) & 1) == ((insn >> 24) & 1)) {
9282 /* RFE, SRS: not available in user mode or on M profile */
9283 if (IS_USER(s) || IS_M(env)) {
9284 goto illegal_op;
9286 if (insn & (1 << 20)) {
9287 /* rfe */
9288 addr = load_reg(s, rn);
9289 if ((insn & (1 << 24)) == 0)
9290 tcg_gen_addi_i32(addr, addr, -8);
9291 /* Load PC into tmp and CPSR into tmp2. */
9292 tmp = tcg_temp_new_i32();
9293 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9294 tcg_gen_addi_i32(addr, addr, 4);
9295 tmp2 = tcg_temp_new_i32();
9296 gen_aa32_ld32u(tmp2, addr, get_mem_index(s));
9297 if (insn & (1 << 21)) {
9298 /* Base writeback. */
9299 if (insn & (1 << 24)) {
9300 tcg_gen_addi_i32(addr, addr, 4);
9301 } else {
9302 tcg_gen_addi_i32(addr, addr, -4);
9304 store_reg(s, rn, addr);
9305 } else {
9306 tcg_temp_free_i32(addr);
9308 gen_rfe(s, tmp, tmp2);
9309 } else {
9310 /* srs */
9311 gen_srs(s, (insn & 0x1f), (insn & (1 << 24)) ? 1 : 2,
9312 insn & (1 << 21));
9314 } else {
9315 int i, loaded_base = 0;
9316 TCGv_i32 loaded_var;
9317 /* Load/store multiple. */
9318 addr = load_reg(s, rn);
9319 offset = 0;
9320 for (i = 0; i < 16; i++) {
9321 if (insn & (1 << i))
9322 offset += 4;
9324 if (insn & (1 << 24)) {
9325 tcg_gen_addi_i32(addr, addr, -offset);
9328 TCGV_UNUSED_I32(loaded_var);
9329 for (i = 0; i < 16; i++) {
9330 if ((insn & (1 << i)) == 0)
9331 continue;
9332 if (insn & (1 << 20)) {
9333 /* Load. */
9334 tmp = tcg_temp_new_i32();
9335 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
9336 if (i == 15) {
9337 gen_bx(s, tmp);
9338 } else if (i == rn) {
9339 loaded_var = tmp;
9340 loaded_base = 1;
9341 } else {
9342 store_reg(s, i, tmp);
9344 } else {
9345 /* Store. */
9346 tmp = load_reg(s, i);
9347 gen_aa32_st32(tmp, addr, get_mem_index(s));
9348 tcg_temp_free_i32(tmp);
9350 tcg_gen_addi_i32(addr, addr, 4);
9352 if (loaded_base) {
9353 store_reg(s, rn, loaded_var);
9355 if (insn & (1 << 21)) {
9356 /* Base register writeback. */
9357 if (insn & (1 << 24)) {
9358 tcg_gen_addi_i32(addr, addr, -offset);
9360 /* Fault if writeback register is in register list. */
9361 if (insn & (1 << rn))
9362 goto illegal_op;
9363 store_reg(s, rn, addr);
9364 } else {
9365 tcg_temp_free_i32(addr);
9369 break;
9370 case 5:
9372 op = (insn >> 21) & 0xf;
9373 if (op == 6) {
9374 /* Halfword pack. */
9375 tmp = load_reg(s, rn);
9376 tmp2 = load_reg(s, rm);
9377 shift = ((insn >> 10) & 0x1c) | ((insn >> 6) & 0x3);
9378 if (insn & (1 << 5)) {
9379 /* pkhtb */
9380 if (shift == 0)
9381 shift = 31;
9382 tcg_gen_sari_i32(tmp2, tmp2, shift);
9383 tcg_gen_andi_i32(tmp, tmp, 0xffff0000);
9384 tcg_gen_ext16u_i32(tmp2, tmp2);
9385 } else {
9386 /* pkhbt */
9387 if (shift)
9388 tcg_gen_shli_i32(tmp2, tmp2, shift);
9389 tcg_gen_ext16u_i32(tmp, tmp);
9390 tcg_gen_andi_i32(tmp2, tmp2, 0xffff0000);
9392 tcg_gen_or_i32(tmp, tmp, tmp2);
9393 tcg_temp_free_i32(tmp2);
9394 store_reg(s, rd, tmp);
9395 } else {
9396 /* Data processing register constant shift. */
9397 if (rn == 15) {
9398 tmp = tcg_temp_new_i32();
9399 tcg_gen_movi_i32(tmp, 0);
9400 } else {
9401 tmp = load_reg(s, rn);
9403 tmp2 = load_reg(s, rm);
9405 shiftop = (insn >> 4) & 3;
9406 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9407 conds = (insn & (1 << 20)) != 0;
9408 logic_cc = (conds && thumb2_logic_op(op));
9409 gen_arm_shift_im(tmp2, shiftop, shift, logic_cc);
9410 if (gen_thumb2_data_op(s, op, conds, 0, tmp, tmp2))
9411 goto illegal_op;
9412 tcg_temp_free_i32(tmp2);
9413 if (rd != 15) {
9414 store_reg(s, rd, tmp);
9415 } else {
9416 tcg_temp_free_i32(tmp);
9419 break;
9420 case 13: /* Misc data processing. */
9421 op = ((insn >> 22) & 6) | ((insn >> 7) & 1);
9422 if (op < 4 && (insn & 0xf000) != 0xf000)
9423 goto illegal_op;
9424 switch (op) {
9425 case 0: /* Register controlled shift. */
9426 tmp = load_reg(s, rn);
9427 tmp2 = load_reg(s, rm);
9428 if ((insn & 0x70) != 0)
9429 goto illegal_op;
9430 op = (insn >> 21) & 3;
9431 logic_cc = (insn & (1 << 20)) != 0;
9432 gen_arm_shift_reg(tmp, op, tmp2, logic_cc);
9433 if (logic_cc)
9434 gen_logic_CC(tmp);
9435 store_reg_bx(env, s, rd, tmp);
9436 break;
9437 case 1: /* Sign/zero extend. */
9438 tmp = load_reg(s, rm);
9439 shift = (insn >> 4) & 3;
9440 /* ??? In many cases it's not necessary to do a
9441 rotate, a shift is sufficient. */
9442 if (shift != 0)
9443 tcg_gen_rotri_i32(tmp, tmp, shift * 8);
9444 op = (insn >> 20) & 7;
9445 switch (op) {
9446 case 0: gen_sxth(tmp); break;
9447 case 1: gen_uxth(tmp); break;
9448 case 2: gen_sxtb16(tmp); break;
9449 case 3: gen_uxtb16(tmp); break;
9450 case 4: gen_sxtb(tmp); break;
9451 case 5: gen_uxtb(tmp); break;
9452 default: goto illegal_op;
9454 if (rn != 15) {
9455 tmp2 = load_reg(s, rn);
9456 if ((op >> 1) == 1) {
9457 gen_add16(tmp, tmp2);
9458 } else {
9459 tcg_gen_add_i32(tmp, tmp, tmp2);
9460 tcg_temp_free_i32(tmp2);
9463 store_reg(s, rd, tmp);
9464 break;
9465 case 2: /* SIMD add/subtract. */
9466 op = (insn >> 20) & 7;
9467 shift = (insn >> 4) & 7;
9468 if ((op & 3) == 3 || (shift & 3) == 3)
9469 goto illegal_op;
9470 tmp = load_reg(s, rn);
9471 tmp2 = load_reg(s, rm);
9472 gen_thumb2_parallel_addsub(op, shift, tmp, tmp2);
9473 tcg_temp_free_i32(tmp2);
9474 store_reg(s, rd, tmp);
9475 break;
9476 case 3: /* Other data processing. */
9477 op = ((insn >> 17) & 0x38) | ((insn >> 4) & 7);
9478 if (op < 4) {
9479 /* Saturating add/subtract. */
9480 tmp = load_reg(s, rn);
9481 tmp2 = load_reg(s, rm);
9482 if (op & 1)
9483 gen_helper_double_saturate(tmp, cpu_env, tmp);
9484 if (op & 2)
9485 gen_helper_sub_saturate(tmp, cpu_env, tmp2, tmp);
9486 else
9487 gen_helper_add_saturate(tmp, cpu_env, tmp, tmp2);
9488 tcg_temp_free_i32(tmp2);
9489 } else {
9490 tmp = load_reg(s, rn);
9491 switch (op) {
9492 case 0x0a: /* rbit */
9493 gen_helper_rbit(tmp, tmp);
9494 break;
9495 case 0x08: /* rev */
9496 tcg_gen_bswap32_i32(tmp, tmp);
9497 break;
9498 case 0x09: /* rev16 */
9499 gen_rev16(tmp);
9500 break;
9501 case 0x0b: /* revsh */
9502 gen_revsh(tmp);
9503 break;
9504 case 0x10: /* sel */
9505 tmp2 = load_reg(s, rm);
9506 tmp3 = tcg_temp_new_i32();
9507 tcg_gen_ld_i32(tmp3, cpu_env, offsetof(CPUARMState, GE));
9508 gen_helper_sel_flags(tmp, tmp3, tmp, tmp2);
9509 tcg_temp_free_i32(tmp3);
9510 tcg_temp_free_i32(tmp2);
9511 break;
9512 case 0x18: /* clz */
9513 gen_helper_clz(tmp, tmp);
9514 break;
9515 case 0x20:
9516 case 0x21:
9517 case 0x22:
9518 case 0x28:
9519 case 0x29:
9520 case 0x2a:
9522 /* crc32/crc32c */
9523 uint32_t sz = op & 0x3;
9524 uint32_t c = op & 0x8;
9526 if (!arm_feature(env, ARM_FEATURE_CRC)) {
9527 goto illegal_op;
9530 tmp2 = load_reg(s, rm);
9531 if (sz == 0) {
9532 tcg_gen_andi_i32(tmp2, tmp2, 0xff);
9533 } else if (sz == 1) {
9534 tcg_gen_andi_i32(tmp2, tmp2, 0xffff);
9536 tmp3 = tcg_const_i32(1 << sz);
9537 if (c) {
9538 gen_helper_crc32c(tmp, tmp, tmp2, tmp3);
9539 } else {
9540 gen_helper_crc32(tmp, tmp, tmp2, tmp3);
9542 tcg_temp_free_i32(tmp2);
9543 tcg_temp_free_i32(tmp3);
9544 break;
9546 default:
9547 goto illegal_op;
9550 store_reg(s, rd, tmp);
9551 break;
9552 case 4: case 5: /* 32-bit multiply. Sum of absolute differences. */
9553 op = (insn >> 4) & 0xf;
9554 tmp = load_reg(s, rn);
9555 tmp2 = load_reg(s, rm);
9556 switch ((insn >> 20) & 7) {
9557 case 0: /* 32 x 32 -> 32 */
9558 tcg_gen_mul_i32(tmp, tmp, tmp2);
9559 tcg_temp_free_i32(tmp2);
9560 if (rs != 15) {
9561 tmp2 = load_reg(s, rs);
9562 if (op)
9563 tcg_gen_sub_i32(tmp, tmp2, tmp);
9564 else
9565 tcg_gen_add_i32(tmp, tmp, tmp2);
9566 tcg_temp_free_i32(tmp2);
9568 break;
9569 case 1: /* 16 x 16 -> 32 */
9570 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9571 tcg_temp_free_i32(tmp2);
9572 if (rs != 15) {
9573 tmp2 = load_reg(s, rs);
9574 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9575 tcg_temp_free_i32(tmp2);
9577 break;
9578 case 2: /* Dual multiply add. */
9579 case 4: /* Dual multiply subtract. */
9580 if (op)
9581 gen_swap_half(tmp2);
9582 gen_smul_dual(tmp, tmp2);
9583 if (insn & (1 << 22)) {
9584 /* This subtraction cannot overflow. */
9585 tcg_gen_sub_i32(tmp, tmp, tmp2);
9586 } else {
9587 /* This addition cannot overflow 32 bits;
9588 * however it may overflow considered as a signed
9589 * operation, in which case we must set the Q flag.
9591 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9593 tcg_temp_free_i32(tmp2);
9594 if (rs != 15)
9596 tmp2 = load_reg(s, rs);
9597 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9598 tcg_temp_free_i32(tmp2);
9600 break;
9601 case 3: /* 32 * 16 -> 32msb */
9602 if (op)
9603 tcg_gen_sari_i32(tmp2, tmp2, 16);
9604 else
9605 gen_sxth(tmp2);
9606 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9607 tcg_gen_shri_i64(tmp64, tmp64, 16);
9608 tmp = tcg_temp_new_i32();
9609 tcg_gen_trunc_i64_i32(tmp, tmp64);
9610 tcg_temp_free_i64(tmp64);
9611 if (rs != 15)
9613 tmp2 = load_reg(s, rs);
9614 gen_helper_add_setq(tmp, cpu_env, tmp, tmp2);
9615 tcg_temp_free_i32(tmp2);
9617 break;
9618 case 5: case 6: /* 32 * 32 -> 32msb (SMMUL, SMMLA, SMMLS) */
9619 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9620 if (rs != 15) {
9621 tmp = load_reg(s, rs);
9622 if (insn & (1 << 20)) {
9623 tmp64 = gen_addq_msw(tmp64, tmp);
9624 } else {
9625 tmp64 = gen_subq_msw(tmp64, tmp);
9628 if (insn & (1 << 4)) {
9629 tcg_gen_addi_i64(tmp64, tmp64, 0x80000000u);
9631 tcg_gen_shri_i64(tmp64, tmp64, 32);
9632 tmp = tcg_temp_new_i32();
9633 tcg_gen_trunc_i64_i32(tmp, tmp64);
9634 tcg_temp_free_i64(tmp64);
9635 break;
9636 case 7: /* Unsigned sum of absolute differences. */
9637 gen_helper_usad8(tmp, tmp, tmp2);
9638 tcg_temp_free_i32(tmp2);
9639 if (rs != 15) {
9640 tmp2 = load_reg(s, rs);
9641 tcg_gen_add_i32(tmp, tmp, tmp2);
9642 tcg_temp_free_i32(tmp2);
9644 break;
9646 store_reg(s, rd, tmp);
9647 break;
9648 case 6: case 7: /* 64-bit multiply, Divide. */
9649 op = ((insn >> 4) & 0xf) | ((insn >> 16) & 0x70);
9650 tmp = load_reg(s, rn);
9651 tmp2 = load_reg(s, rm);
9652 if ((op & 0x50) == 0x10) {
9653 /* sdiv, udiv */
9654 if (!arm_feature(env, ARM_FEATURE_THUMB_DIV)) {
9655 goto illegal_op;
9657 if (op & 0x20)
9658 gen_helper_udiv(tmp, tmp, tmp2);
9659 else
9660 gen_helper_sdiv(tmp, tmp, tmp2);
9661 tcg_temp_free_i32(tmp2);
9662 store_reg(s, rd, tmp);
9663 } else if ((op & 0xe) == 0xc) {
9664 /* Dual multiply accumulate long. */
9665 if (op & 1)
9666 gen_swap_half(tmp2);
9667 gen_smul_dual(tmp, tmp2);
9668 if (op & 0x10) {
9669 tcg_gen_sub_i32(tmp, tmp, tmp2);
9670 } else {
9671 tcg_gen_add_i32(tmp, tmp, tmp2);
9673 tcg_temp_free_i32(tmp2);
9674 /* BUGFIX */
9675 tmp64 = tcg_temp_new_i64();
9676 tcg_gen_ext_i32_i64(tmp64, tmp);
9677 tcg_temp_free_i32(tmp);
9678 gen_addq(s, tmp64, rs, rd);
9679 gen_storeq_reg(s, rs, rd, tmp64);
9680 tcg_temp_free_i64(tmp64);
9681 } else {
9682 if (op & 0x20) {
9683 /* Unsigned 64-bit multiply */
9684 tmp64 = gen_mulu_i64_i32(tmp, tmp2);
9685 } else {
9686 if (op & 8) {
9687 /* smlalxy */
9688 gen_mulxy(tmp, tmp2, op & 2, op & 1);
9689 tcg_temp_free_i32(tmp2);
9690 tmp64 = tcg_temp_new_i64();
9691 tcg_gen_ext_i32_i64(tmp64, tmp);
9692 tcg_temp_free_i32(tmp);
9693 } else {
9694 /* Signed 64-bit multiply */
9695 tmp64 = gen_muls_i64_i32(tmp, tmp2);
9698 if (op & 4) {
9699 /* umaal */
9700 gen_addq_lo(s, tmp64, rs);
9701 gen_addq_lo(s, tmp64, rd);
9702 } else if (op & 0x40) {
9703 /* 64-bit accumulate. */
9704 gen_addq(s, tmp64, rs, rd);
9706 gen_storeq_reg(s, rs, rd, tmp64);
9707 tcg_temp_free_i64(tmp64);
9709 break;
9711 break;
9712 case 6: case 7: case 14: case 15:
9713 /* Coprocessor. */
9714 if (((insn >> 24) & 3) == 3) {
9715 /* Translate into the equivalent ARM encoding. */
9716 insn = (insn & 0xe2ffffff) | ((insn & (1 << 28)) >> 4) | (1 << 28);
9717 if (disas_neon_data_insn(env, s, insn))
9718 goto illegal_op;
9719 } else if (((insn >> 8) & 0xe) == 10) {
9720 if (disas_vfp_insn(env, s, insn)) {
9721 goto illegal_op;
9723 } else {
9724 if (insn & (1 << 28))
9725 goto illegal_op;
9726 if (disas_coproc_insn (env, s, insn))
9727 goto illegal_op;
9729 break;
9730 case 8: case 9: case 10: case 11:
9731 if (insn & (1 << 15)) {
9732 /* Branches, misc control. */
9733 if (insn & 0x5000) {
9734 /* Unconditional branch. */
9735 /* signextend(hw1[10:0]) -> offset[:12]. */
9736 offset = ((int32_t)insn << 5) >> 9 & ~(int32_t)0xfff;
9737 /* hw1[10:0] -> offset[11:1]. */
9738 offset |= (insn & 0x7ff) << 1;
9739 /* (~hw2[13, 11] ^ offset[24]) -> offset[23,22]
9740 offset[24:22] already have the same value because of the
9741 sign extension above. */
9742 offset ^= ((~insn) & (1 << 13)) << 10;
9743 offset ^= ((~insn) & (1 << 11)) << 11;
9745 if (insn & (1 << 14)) {
9746 /* Branch and link. */
9747 tcg_gen_movi_i32(cpu_R[14], s->pc | 1);
9750 offset += s->pc;
9751 if (insn & (1 << 12)) {
9752 /* b/bl */
9753 gen_jmp(s, offset);
9754 } else {
9755 /* blx */
9756 offset &= ~(uint32_t)2;
9757 /* thumb2 bx, no need to check */
9758 gen_bx_im(s, offset);
9760 } else if (((insn >> 23) & 7) == 7) {
9761 /* Misc control */
9762 if (insn & (1 << 13))
9763 goto illegal_op;
9765 if (insn & (1 << 26)) {
9766 if (!(insn & (1 << 20))) {
9767 /* Hypervisor call (v7) */
9768 int imm16 = extract32(insn, 16, 4) << 12
9769 | extract32(insn, 0, 12);
9770 ARCH(7);
9771 if (IS_USER(s)) {
9772 goto illegal_op;
9774 gen_hvc(s, imm16);
9775 } else {
9776 /* Secure monitor call (v6+) */
9777 ARCH(6K);
9778 if (IS_USER(s)) {
9779 goto illegal_op;
9781 gen_smc(s);
9783 } else {
9784 op = (insn >> 20) & 7;
9785 switch (op) {
9786 case 0: /* msr cpsr. */
9787 if (IS_M(env)) {
9788 tmp = load_reg(s, rn);
9789 addr = tcg_const_i32(insn & 0xff);
9790 gen_helper_v7m_msr(cpu_env, addr, tmp);
9791 tcg_temp_free_i32(addr);
9792 tcg_temp_free_i32(tmp);
9793 gen_lookup_tb(s);
9794 break;
9796 /* fall through */
9797 case 1: /* msr spsr. */
9798 if (IS_M(env))
9799 goto illegal_op;
9800 tmp = load_reg(s, rn);
9801 if (gen_set_psr(s,
9802 msr_mask(env, s, (insn >> 8) & 0xf, op == 1),
9803 op == 1, tmp))
9804 goto illegal_op;
9805 break;
9806 case 2: /* cps, nop-hint. */
9807 if (((insn >> 8) & 7) == 0) {
9808 gen_nop_hint(s, insn & 0xff);
9810 /* Implemented as NOP in user mode. */
9811 if (IS_USER(s))
9812 break;
9813 offset = 0;
9814 imm = 0;
9815 if (insn & (1 << 10)) {
9816 if (insn & (1 << 7))
9817 offset |= CPSR_A;
9818 if (insn & (1 << 6))
9819 offset |= CPSR_I;
9820 if (insn & (1 << 5))
9821 offset |= CPSR_F;
9822 if (insn & (1 << 9))
9823 imm = CPSR_A | CPSR_I | CPSR_F;
9825 if (insn & (1 << 8)) {
9826 offset |= 0x1f;
9827 imm |= (insn & 0x1f);
9829 if (offset) {
9830 gen_set_psr_im(s, offset, 0, imm);
9832 break;
9833 case 3: /* Special control operations. */
9834 ARCH(7);
9835 op = (insn >> 4) & 0xf;
9836 switch (op) {
9837 case 2: /* clrex */
9838 gen_clrex(s);
9839 break;
9840 case 4: /* dsb */
9841 case 5: /* dmb */
9842 case 6: /* isb */
9843 /* These execute as NOPs. */
9844 break;
9845 default:
9846 goto illegal_op;
9848 break;
9849 case 4: /* bxj */
9850 /* Trivial implementation equivalent to bx. */
9851 tmp = load_reg(s, rn);
9852 gen_bx(s, tmp);
9853 break;
9854 case 5: /* Exception return. */
9855 if (IS_USER(s)) {
9856 goto illegal_op;
9858 if (rn != 14 || rd != 15) {
9859 goto illegal_op;
9861 tmp = load_reg(s, rn);
9862 tcg_gen_subi_i32(tmp, tmp, insn & 0xff);
9863 gen_exception_return(s, tmp);
9864 break;
9865 case 6: /* mrs cpsr. */
9866 tmp = tcg_temp_new_i32();
9867 if (IS_M(env)) {
9868 addr = tcg_const_i32(insn & 0xff);
9869 gen_helper_v7m_mrs(tmp, cpu_env, addr);
9870 tcg_temp_free_i32(addr);
9871 } else {
9872 gen_helper_cpsr_read(tmp, cpu_env);
9874 store_reg(s, rd, tmp);
9875 break;
9876 case 7: /* mrs spsr. */
9877 /* Not accessible in user mode. */
9878 if (IS_USER(s) || IS_M(env))
9879 goto illegal_op;
9880 tmp = load_cpu_field(spsr);
9881 store_reg(s, rd, tmp);
9882 break;
9885 } else {
9886 /* Conditional branch. */
9887 op = (insn >> 22) & 0xf;
9888 /* Generate a conditional jump to next instruction. */
9889 s->condlabel = gen_new_label();
9890 arm_gen_test_cc(op ^ 1, s->condlabel);
9891 s->condjmp = 1;
9893 /* offset[11:1] = insn[10:0] */
9894 offset = (insn & 0x7ff) << 1;
9895 /* offset[17:12] = insn[21:16]. */
9896 offset |= (insn & 0x003f0000) >> 4;
9897 /* offset[31:20] = insn[26]. */
9898 offset |= ((int32_t)((insn << 5) & 0x80000000)) >> 11;
9899 /* offset[18] = insn[13]. */
9900 offset |= (insn & (1 << 13)) << 5;
9901 /* offset[19] = insn[11]. */
9902 offset |= (insn & (1 << 11)) << 8;
9904 /* jump to the offset */
9905 gen_jmp(s, s->pc + offset);
9907 } else {
9908 /* Data processing immediate. */
9909 if (insn & (1 << 25)) {
9910 if (insn & (1 << 24)) {
9911 if (insn & (1 << 20))
9912 goto illegal_op;
9913 /* Bitfield/Saturate. */
9914 op = (insn >> 21) & 7;
9915 imm = insn & 0x1f;
9916 shift = ((insn >> 6) & 3) | ((insn >> 10) & 0x1c);
9917 if (rn == 15) {
9918 tmp = tcg_temp_new_i32();
9919 tcg_gen_movi_i32(tmp, 0);
9920 } else {
9921 tmp = load_reg(s, rn);
9923 switch (op) {
9924 case 2: /* Signed bitfield extract. */
9925 imm++;
9926 if (shift + imm > 32)
9927 goto illegal_op;
9928 if (imm < 32)
9929 gen_sbfx(tmp, shift, imm);
9930 break;
9931 case 6: /* Unsigned bitfield extract. */
9932 imm++;
9933 if (shift + imm > 32)
9934 goto illegal_op;
9935 if (imm < 32)
9936 gen_ubfx(tmp, shift, (1u << imm) - 1);
9937 break;
9938 case 3: /* Bitfield insert/clear. */
9939 if (imm < shift)
9940 goto illegal_op;
9941 imm = imm + 1 - shift;
9942 if (imm != 32) {
9943 tmp2 = load_reg(s, rd);
9944 tcg_gen_deposit_i32(tmp, tmp2, tmp, shift, imm);
9945 tcg_temp_free_i32(tmp2);
9947 break;
9948 case 7:
9949 goto illegal_op;
9950 default: /* Saturate. */
9951 if (shift) {
9952 if (op & 1)
9953 tcg_gen_sari_i32(tmp, tmp, shift);
9954 else
9955 tcg_gen_shli_i32(tmp, tmp, shift);
9957 tmp2 = tcg_const_i32(imm);
9958 if (op & 4) {
9959 /* Unsigned. */
9960 if ((op & 1) && shift == 0)
9961 gen_helper_usat16(tmp, cpu_env, tmp, tmp2);
9962 else
9963 gen_helper_usat(tmp, cpu_env, tmp, tmp2);
9964 } else {
9965 /* Signed. */
9966 if ((op & 1) && shift == 0)
9967 gen_helper_ssat16(tmp, cpu_env, tmp, tmp2);
9968 else
9969 gen_helper_ssat(tmp, cpu_env, tmp, tmp2);
9971 tcg_temp_free_i32(tmp2);
9972 break;
9974 store_reg(s, rd, tmp);
9975 } else {
9976 imm = ((insn & 0x04000000) >> 15)
9977 | ((insn & 0x7000) >> 4) | (insn & 0xff);
9978 if (insn & (1 << 22)) {
9979 /* 16-bit immediate. */
9980 imm |= (insn >> 4) & 0xf000;
9981 if (insn & (1 << 23)) {
9982 /* movt */
9983 tmp = load_reg(s, rd);
9984 tcg_gen_ext16u_i32(tmp, tmp);
9985 tcg_gen_ori_i32(tmp, tmp, imm << 16);
9986 } else {
9987 /* movw */
9988 tmp = tcg_temp_new_i32();
9989 tcg_gen_movi_i32(tmp, imm);
9991 } else {
9992 /* Add/sub 12-bit immediate. */
9993 if (rn == 15) {
9994 offset = s->pc & ~(uint32_t)3;
9995 if (insn & (1 << 23))
9996 offset -= imm;
9997 else
9998 offset += imm;
9999 tmp = tcg_temp_new_i32();
10000 tcg_gen_movi_i32(tmp, offset);
10001 } else {
10002 tmp = load_reg(s, rn);
10003 if (insn & (1 << 23))
10004 tcg_gen_subi_i32(tmp, tmp, imm);
10005 else
10006 tcg_gen_addi_i32(tmp, tmp, imm);
10009 store_reg(s, rd, tmp);
10011 } else {
10012 int shifter_out = 0;
10013 /* modified 12-bit immediate. */
10014 shift = ((insn & 0x04000000) >> 23) | ((insn & 0x7000) >> 12);
10015 imm = (insn & 0xff);
10016 switch (shift) {
10017 case 0: /* XY */
10018 /* Nothing to do. */
10019 break;
10020 case 1: /* 00XY00XY */
10021 imm |= imm << 16;
10022 break;
10023 case 2: /* XY00XY00 */
10024 imm |= imm << 16;
10025 imm <<= 8;
10026 break;
10027 case 3: /* XYXYXYXY */
10028 imm |= imm << 16;
10029 imm |= imm << 8;
10030 break;
10031 default: /* Rotated constant. */
10032 shift = (shift << 1) | (imm >> 7);
10033 imm |= 0x80;
10034 imm = imm << (32 - shift);
10035 shifter_out = 1;
10036 break;
10038 tmp2 = tcg_temp_new_i32();
10039 tcg_gen_movi_i32(tmp2, imm);
10040 rn = (insn >> 16) & 0xf;
10041 if (rn == 15) {
10042 tmp = tcg_temp_new_i32();
10043 tcg_gen_movi_i32(tmp, 0);
10044 } else {
10045 tmp = load_reg(s, rn);
10047 op = (insn >> 21) & 0xf;
10048 if (gen_thumb2_data_op(s, op, (insn & (1 << 20)) != 0,
10049 shifter_out, tmp, tmp2))
10050 goto illegal_op;
10051 tcg_temp_free_i32(tmp2);
10052 rd = (insn >> 8) & 0xf;
10053 if (rd != 15) {
10054 store_reg(s, rd, tmp);
10055 } else {
10056 tcg_temp_free_i32(tmp);
10060 break;
10061 case 12: /* Load/store single data item. */
10063 int postinc = 0;
10064 int writeback = 0;
10065 int memidx;
10066 if ((insn & 0x01100000) == 0x01000000) {
10067 if (disas_neon_ls_insn(env, s, insn))
10068 goto illegal_op;
10069 break;
10071 op = ((insn >> 21) & 3) | ((insn >> 22) & 4);
10072 if (rs == 15) {
10073 if (!(insn & (1 << 20))) {
10074 goto illegal_op;
10076 if (op != 2) {
10077 /* Byte or halfword load space with dest == r15 : memory hints.
10078 * Catch them early so we don't emit pointless addressing code.
10079 * This space is a mix of:
10080 * PLD/PLDW/PLI, which we implement as NOPs (note that unlike
10081 * the ARM encodings, PLDW space doesn't UNDEF for non-v7MP
10082 * cores)
10083 * unallocated hints, which must be treated as NOPs
10084 * UNPREDICTABLE space, which we NOP or UNDEF depending on
10085 * which is easiest for the decoding logic
10086 * Some space which must UNDEF
10088 int op1 = (insn >> 23) & 3;
10089 int op2 = (insn >> 6) & 0x3f;
10090 if (op & 2) {
10091 goto illegal_op;
10093 if (rn == 15) {
10094 /* UNPREDICTABLE, unallocated hint or
10095 * PLD/PLDW/PLI (literal)
10097 return 0;
10099 if (op1 & 1) {
10100 return 0; /* PLD/PLDW/PLI or unallocated hint */
10102 if ((op2 == 0) || ((op2 & 0x3c) == 0x30)) {
10103 return 0; /* PLD/PLDW/PLI or unallocated hint */
10105 /* UNDEF space, or an UNPREDICTABLE */
10106 return 1;
10109 memidx = get_mem_index(s);
10110 if (rn == 15) {
10111 addr = tcg_temp_new_i32();
10112 /* PC relative. */
10113 /* s->pc has already been incremented by 4. */
10114 imm = s->pc & 0xfffffffc;
10115 if (insn & (1 << 23))
10116 imm += insn & 0xfff;
10117 else
10118 imm -= insn & 0xfff;
10119 tcg_gen_movi_i32(addr, imm);
10120 } else {
10121 addr = load_reg(s, rn);
10122 if (insn & (1 << 23)) {
10123 /* Positive offset. */
10124 imm = insn & 0xfff;
10125 tcg_gen_addi_i32(addr, addr, imm);
10126 } else {
10127 imm = insn & 0xff;
10128 switch ((insn >> 8) & 0xf) {
10129 case 0x0: /* Shifted Register. */
10130 shift = (insn >> 4) & 0xf;
10131 if (shift > 3) {
10132 tcg_temp_free_i32(addr);
10133 goto illegal_op;
10135 tmp = load_reg(s, rm);
10136 if (shift)
10137 tcg_gen_shli_i32(tmp, tmp, shift);
10138 tcg_gen_add_i32(addr, addr, tmp);
10139 tcg_temp_free_i32(tmp);
10140 break;
10141 case 0xc: /* Negative offset. */
10142 tcg_gen_addi_i32(addr, addr, -imm);
10143 break;
10144 case 0xe: /* User privilege. */
10145 tcg_gen_addi_i32(addr, addr, imm);
10146 memidx = MMU_USER_IDX;
10147 break;
10148 case 0x9: /* Post-decrement. */
10149 imm = -imm;
10150 /* Fall through. */
10151 case 0xb: /* Post-increment. */
10152 postinc = 1;
10153 writeback = 1;
10154 break;
10155 case 0xd: /* Pre-decrement. */
10156 imm = -imm;
10157 /* Fall through. */
10158 case 0xf: /* Pre-increment. */
10159 tcg_gen_addi_i32(addr, addr, imm);
10160 writeback = 1;
10161 break;
10162 default:
10163 tcg_temp_free_i32(addr);
10164 goto illegal_op;
10168 if (insn & (1 << 20)) {
10169 /* Load. */
10170 tmp = tcg_temp_new_i32();
10171 switch (op) {
10172 case 0:
10173 gen_aa32_ld8u(tmp, addr, memidx);
10174 break;
10175 case 4:
10176 gen_aa32_ld8s(tmp, addr, memidx);
10177 break;
10178 case 1:
10179 gen_aa32_ld16u(tmp, addr, memidx);
10180 break;
10181 case 5:
10182 gen_aa32_ld16s(tmp, addr, memidx);
10183 break;
10184 case 2:
10185 gen_aa32_ld32u(tmp, addr, memidx);
10186 break;
10187 default:
10188 tcg_temp_free_i32(tmp);
10189 tcg_temp_free_i32(addr);
10190 goto illegal_op;
10192 if (rs == 15) {
10193 gen_bx(s, tmp);
10194 } else {
10195 store_reg(s, rs, tmp);
10197 } else {
10198 /* Store. */
10199 tmp = load_reg(s, rs);
10200 switch (op) {
10201 case 0:
10202 gen_aa32_st8(tmp, addr, memidx);
10203 break;
10204 case 1:
10205 gen_aa32_st16(tmp, addr, memidx);
10206 break;
10207 case 2:
10208 gen_aa32_st32(tmp, addr, memidx);
10209 break;
10210 default:
10211 tcg_temp_free_i32(tmp);
10212 tcg_temp_free_i32(addr);
10213 goto illegal_op;
10215 tcg_temp_free_i32(tmp);
10217 if (postinc)
10218 tcg_gen_addi_i32(addr, addr, imm);
10219 if (writeback) {
10220 store_reg(s, rn, addr);
10221 } else {
10222 tcg_temp_free_i32(addr);
10225 break;
10226 default:
10227 goto illegal_op;
10229 return 0;
10230 illegal_op:
10231 return 1;
10234 static void disas_thumb_insn(CPUARMState *env, DisasContext *s)
10236 uint32_t val, insn, op, rm, rn, rd, shift, cond;
10237 int32_t offset;
10238 int i;
10239 TCGv_i32 tmp;
10240 TCGv_i32 tmp2;
10241 TCGv_i32 addr;
10243 if (s->condexec_mask) {
10244 cond = s->condexec_cond;
10245 if (cond != 0x0e) { /* Skip conditional when condition is AL. */
10246 s->condlabel = gen_new_label();
10247 arm_gen_test_cc(cond ^ 1, s->condlabel);
10248 s->condjmp = 1;
10252 insn = arm_lduw_code(env, s->pc, s->bswap_code);
10253 s->pc += 2;
10255 switch (insn >> 12) {
10256 case 0: case 1:
10258 rd = insn & 7;
10259 op = (insn >> 11) & 3;
10260 if (op == 3) {
10261 /* add/subtract */
10262 rn = (insn >> 3) & 7;
10263 tmp = load_reg(s, rn);
10264 if (insn & (1 << 10)) {
10265 /* immediate */
10266 tmp2 = tcg_temp_new_i32();
10267 tcg_gen_movi_i32(tmp2, (insn >> 6) & 7);
10268 } else {
10269 /* reg */
10270 rm = (insn >> 6) & 7;
10271 tmp2 = load_reg(s, rm);
10273 if (insn & (1 << 9)) {
10274 if (s->condexec_mask)
10275 tcg_gen_sub_i32(tmp, tmp, tmp2);
10276 else
10277 gen_sub_CC(tmp, tmp, tmp2);
10278 } else {
10279 if (s->condexec_mask)
10280 tcg_gen_add_i32(tmp, tmp, tmp2);
10281 else
10282 gen_add_CC(tmp, tmp, tmp2);
10284 tcg_temp_free_i32(tmp2);
10285 store_reg(s, rd, tmp);
10286 } else {
10287 /* shift immediate */
10288 rm = (insn >> 3) & 7;
10289 shift = (insn >> 6) & 0x1f;
10290 tmp = load_reg(s, rm);
10291 gen_arm_shift_im(tmp, op, shift, s->condexec_mask == 0);
10292 if (!s->condexec_mask)
10293 gen_logic_CC(tmp);
10294 store_reg(s, rd, tmp);
10296 break;
10297 case 2: case 3:
10298 /* arithmetic large immediate */
10299 op = (insn >> 11) & 3;
10300 rd = (insn >> 8) & 0x7;
10301 if (op == 0) { /* mov */
10302 tmp = tcg_temp_new_i32();
10303 tcg_gen_movi_i32(tmp, insn & 0xff);
10304 if (!s->condexec_mask)
10305 gen_logic_CC(tmp);
10306 store_reg(s, rd, tmp);
10307 } else {
10308 tmp = load_reg(s, rd);
10309 tmp2 = tcg_temp_new_i32();
10310 tcg_gen_movi_i32(tmp2, insn & 0xff);
10311 switch (op) {
10312 case 1: /* cmp */
10313 gen_sub_CC(tmp, tmp, tmp2);
10314 tcg_temp_free_i32(tmp);
10315 tcg_temp_free_i32(tmp2);
10316 break;
10317 case 2: /* add */
10318 if (s->condexec_mask)
10319 tcg_gen_add_i32(tmp, tmp, tmp2);
10320 else
10321 gen_add_CC(tmp, tmp, tmp2);
10322 tcg_temp_free_i32(tmp2);
10323 store_reg(s, rd, tmp);
10324 break;
10325 case 3: /* sub */
10326 if (s->condexec_mask)
10327 tcg_gen_sub_i32(tmp, tmp, tmp2);
10328 else
10329 gen_sub_CC(tmp, tmp, tmp2);
10330 tcg_temp_free_i32(tmp2);
10331 store_reg(s, rd, tmp);
10332 break;
10335 break;
10336 case 4:
10337 if (insn & (1 << 11)) {
10338 rd = (insn >> 8) & 7;
10339 /* load pc-relative. Bit 1 of PC is ignored. */
10340 val = s->pc + 2 + ((insn & 0xff) * 4);
10341 val &= ~(uint32_t)2;
10342 addr = tcg_temp_new_i32();
10343 tcg_gen_movi_i32(addr, val);
10344 tmp = tcg_temp_new_i32();
10345 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10346 tcg_temp_free_i32(addr);
10347 store_reg(s, rd, tmp);
10348 break;
10350 if (insn & (1 << 10)) {
10351 /* data processing extended or blx */
10352 rd = (insn & 7) | ((insn >> 4) & 8);
10353 rm = (insn >> 3) & 0xf;
10354 op = (insn >> 8) & 3;
10355 switch (op) {
10356 case 0: /* add */
10357 tmp = load_reg(s, rd);
10358 tmp2 = load_reg(s, rm);
10359 tcg_gen_add_i32(tmp, tmp, tmp2);
10360 tcg_temp_free_i32(tmp2);
10361 store_reg(s, rd, tmp);
10362 break;
10363 case 1: /* cmp */
10364 tmp = load_reg(s, rd);
10365 tmp2 = load_reg(s, rm);
10366 gen_sub_CC(tmp, tmp, tmp2);
10367 tcg_temp_free_i32(tmp2);
10368 tcg_temp_free_i32(tmp);
10369 break;
10370 case 2: /* mov/cpy */
10371 tmp = load_reg(s, rm);
10372 store_reg(s, rd, tmp);
10373 break;
10374 case 3:/* branch [and link] exchange thumb register */
10375 tmp = load_reg(s, rm);
10376 if (insn & (1 << 7)) {
10377 ARCH(5);
10378 val = (uint32_t)s->pc | 1;
10379 tmp2 = tcg_temp_new_i32();
10380 tcg_gen_movi_i32(tmp2, val);
10381 store_reg(s, 14, tmp2);
10383 /* already thumb, no need to check */
10384 gen_bx(s, tmp);
10385 break;
10387 break;
10390 /* data processing register */
10391 rd = insn & 7;
10392 rm = (insn >> 3) & 7;
10393 op = (insn >> 6) & 0xf;
10394 if (op == 2 || op == 3 || op == 4 || op == 7) {
10395 /* the shift/rotate ops want the operands backwards */
10396 val = rm;
10397 rm = rd;
10398 rd = val;
10399 val = 1;
10400 } else {
10401 val = 0;
10404 if (op == 9) { /* neg */
10405 tmp = tcg_temp_new_i32();
10406 tcg_gen_movi_i32(tmp, 0);
10407 } else if (op != 0xf) { /* mvn doesn't read its first operand */
10408 tmp = load_reg(s, rd);
10409 } else {
10410 TCGV_UNUSED_I32(tmp);
10413 tmp2 = load_reg(s, rm);
10414 switch (op) {
10415 case 0x0: /* and */
10416 tcg_gen_and_i32(tmp, tmp, tmp2);
10417 if (!s->condexec_mask)
10418 gen_logic_CC(tmp);
10419 break;
10420 case 0x1: /* eor */
10421 tcg_gen_xor_i32(tmp, tmp, tmp2);
10422 if (!s->condexec_mask)
10423 gen_logic_CC(tmp);
10424 break;
10425 case 0x2: /* lsl */
10426 if (s->condexec_mask) {
10427 gen_shl(tmp2, tmp2, tmp);
10428 } else {
10429 gen_helper_shl_cc(tmp2, cpu_env, tmp2, tmp);
10430 gen_logic_CC(tmp2);
10432 break;
10433 case 0x3: /* lsr */
10434 if (s->condexec_mask) {
10435 gen_shr(tmp2, tmp2, tmp);
10436 } else {
10437 gen_helper_shr_cc(tmp2, cpu_env, tmp2, tmp);
10438 gen_logic_CC(tmp2);
10440 break;
10441 case 0x4: /* asr */
10442 if (s->condexec_mask) {
10443 gen_sar(tmp2, tmp2, tmp);
10444 } else {
10445 gen_helper_sar_cc(tmp2, cpu_env, tmp2, tmp);
10446 gen_logic_CC(tmp2);
10448 break;
10449 case 0x5: /* adc */
10450 if (s->condexec_mask) {
10451 gen_adc(tmp, tmp2);
10452 } else {
10453 gen_adc_CC(tmp, tmp, tmp2);
10455 break;
10456 case 0x6: /* sbc */
10457 if (s->condexec_mask) {
10458 gen_sub_carry(tmp, tmp, tmp2);
10459 } else {
10460 gen_sbc_CC(tmp, tmp, tmp2);
10462 break;
10463 case 0x7: /* ror */
10464 if (s->condexec_mask) {
10465 tcg_gen_andi_i32(tmp, tmp, 0x1f);
10466 tcg_gen_rotr_i32(tmp2, tmp2, tmp);
10467 } else {
10468 gen_helper_ror_cc(tmp2, cpu_env, tmp2, tmp);
10469 gen_logic_CC(tmp2);
10471 break;
10472 case 0x8: /* tst */
10473 tcg_gen_and_i32(tmp, tmp, tmp2);
10474 gen_logic_CC(tmp);
10475 rd = 16;
10476 break;
10477 case 0x9: /* neg */
10478 if (s->condexec_mask)
10479 tcg_gen_neg_i32(tmp, tmp2);
10480 else
10481 gen_sub_CC(tmp, tmp, tmp2);
10482 break;
10483 case 0xa: /* cmp */
10484 gen_sub_CC(tmp, tmp, tmp2);
10485 rd = 16;
10486 break;
10487 case 0xb: /* cmn */
10488 gen_add_CC(tmp, tmp, tmp2);
10489 rd = 16;
10490 break;
10491 case 0xc: /* orr */
10492 tcg_gen_or_i32(tmp, tmp, tmp2);
10493 if (!s->condexec_mask)
10494 gen_logic_CC(tmp);
10495 break;
10496 case 0xd: /* mul */
10497 tcg_gen_mul_i32(tmp, tmp, tmp2);
10498 if (!s->condexec_mask)
10499 gen_logic_CC(tmp);
10500 break;
10501 case 0xe: /* bic */
10502 tcg_gen_andc_i32(tmp, tmp, tmp2);
10503 if (!s->condexec_mask)
10504 gen_logic_CC(tmp);
10505 break;
10506 case 0xf: /* mvn */
10507 tcg_gen_not_i32(tmp2, tmp2);
10508 if (!s->condexec_mask)
10509 gen_logic_CC(tmp2);
10510 val = 1;
10511 rm = rd;
10512 break;
10514 if (rd != 16) {
10515 if (val) {
10516 store_reg(s, rm, tmp2);
10517 if (op != 0xf)
10518 tcg_temp_free_i32(tmp);
10519 } else {
10520 store_reg(s, rd, tmp);
10521 tcg_temp_free_i32(tmp2);
10523 } else {
10524 tcg_temp_free_i32(tmp);
10525 tcg_temp_free_i32(tmp2);
10527 break;
10529 case 5:
10530 /* load/store register offset. */
10531 rd = insn & 7;
10532 rn = (insn >> 3) & 7;
10533 rm = (insn >> 6) & 7;
10534 op = (insn >> 9) & 7;
10535 addr = load_reg(s, rn);
10536 tmp = load_reg(s, rm);
10537 tcg_gen_add_i32(addr, addr, tmp);
10538 tcg_temp_free_i32(tmp);
10540 if (op < 3) { /* store */
10541 tmp = load_reg(s, rd);
10542 } else {
10543 tmp = tcg_temp_new_i32();
10546 switch (op) {
10547 case 0: /* str */
10548 gen_aa32_st32(tmp, addr, get_mem_index(s));
10549 break;
10550 case 1: /* strh */
10551 gen_aa32_st16(tmp, addr, get_mem_index(s));
10552 break;
10553 case 2: /* strb */
10554 gen_aa32_st8(tmp, addr, get_mem_index(s));
10555 break;
10556 case 3: /* ldrsb */
10557 gen_aa32_ld8s(tmp, addr, get_mem_index(s));
10558 break;
10559 case 4: /* ldr */
10560 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10561 break;
10562 case 5: /* ldrh */
10563 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
10564 break;
10565 case 6: /* ldrb */
10566 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
10567 break;
10568 case 7: /* ldrsh */
10569 gen_aa32_ld16s(tmp, addr, get_mem_index(s));
10570 break;
10572 if (op >= 3) { /* load */
10573 store_reg(s, rd, tmp);
10574 } else {
10575 tcg_temp_free_i32(tmp);
10577 tcg_temp_free_i32(addr);
10578 break;
10580 case 6:
10581 /* load/store word immediate offset */
10582 rd = insn & 7;
10583 rn = (insn >> 3) & 7;
10584 addr = load_reg(s, rn);
10585 val = (insn >> 4) & 0x7c;
10586 tcg_gen_addi_i32(addr, addr, val);
10588 if (insn & (1 << 11)) {
10589 /* load */
10590 tmp = tcg_temp_new_i32();
10591 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10592 store_reg(s, rd, tmp);
10593 } else {
10594 /* store */
10595 tmp = load_reg(s, rd);
10596 gen_aa32_st32(tmp, addr, get_mem_index(s));
10597 tcg_temp_free_i32(tmp);
10599 tcg_temp_free_i32(addr);
10600 break;
10602 case 7:
10603 /* load/store byte immediate offset */
10604 rd = insn & 7;
10605 rn = (insn >> 3) & 7;
10606 addr = load_reg(s, rn);
10607 val = (insn >> 6) & 0x1f;
10608 tcg_gen_addi_i32(addr, addr, val);
10610 if (insn & (1 << 11)) {
10611 /* load */
10612 tmp = tcg_temp_new_i32();
10613 gen_aa32_ld8u(tmp, addr, get_mem_index(s));
10614 store_reg(s, rd, tmp);
10615 } else {
10616 /* store */
10617 tmp = load_reg(s, rd);
10618 gen_aa32_st8(tmp, addr, get_mem_index(s));
10619 tcg_temp_free_i32(tmp);
10621 tcg_temp_free_i32(addr);
10622 break;
10624 case 8:
10625 /* load/store halfword immediate offset */
10626 rd = insn & 7;
10627 rn = (insn >> 3) & 7;
10628 addr = load_reg(s, rn);
10629 val = (insn >> 5) & 0x3e;
10630 tcg_gen_addi_i32(addr, addr, val);
10632 if (insn & (1 << 11)) {
10633 /* load */
10634 tmp = tcg_temp_new_i32();
10635 gen_aa32_ld16u(tmp, addr, get_mem_index(s));
10636 store_reg(s, rd, tmp);
10637 } else {
10638 /* store */
10639 tmp = load_reg(s, rd);
10640 gen_aa32_st16(tmp, addr, get_mem_index(s));
10641 tcg_temp_free_i32(tmp);
10643 tcg_temp_free_i32(addr);
10644 break;
10646 case 9:
10647 /* load/store from stack */
10648 rd = (insn >> 8) & 7;
10649 addr = load_reg(s, 13);
10650 val = (insn & 0xff) * 4;
10651 tcg_gen_addi_i32(addr, addr, val);
10653 if (insn & (1 << 11)) {
10654 /* load */
10655 tmp = tcg_temp_new_i32();
10656 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10657 store_reg(s, rd, tmp);
10658 } else {
10659 /* store */
10660 tmp = load_reg(s, rd);
10661 gen_aa32_st32(tmp, addr, get_mem_index(s));
10662 tcg_temp_free_i32(tmp);
10664 tcg_temp_free_i32(addr);
10665 break;
10667 case 10:
10668 /* add to high reg */
10669 rd = (insn >> 8) & 7;
10670 if (insn & (1 << 11)) {
10671 /* SP */
10672 tmp = load_reg(s, 13);
10673 } else {
10674 /* PC. bit 1 is ignored. */
10675 tmp = tcg_temp_new_i32();
10676 tcg_gen_movi_i32(tmp, (s->pc + 2) & ~(uint32_t)2);
10678 val = (insn & 0xff) * 4;
10679 tcg_gen_addi_i32(tmp, tmp, val);
10680 store_reg(s, rd, tmp);
10681 break;
10683 case 11:
10684 /* misc */
10685 op = (insn >> 8) & 0xf;
10686 switch (op) {
10687 case 0:
10688 /* adjust stack pointer */
10689 tmp = load_reg(s, 13);
10690 val = (insn & 0x7f) * 4;
10691 if (insn & (1 << 7))
10692 val = -(int32_t)val;
10693 tcg_gen_addi_i32(tmp, tmp, val);
10694 store_reg(s, 13, tmp);
10695 break;
10697 case 2: /* sign/zero extend. */
10698 ARCH(6);
10699 rd = insn & 7;
10700 rm = (insn >> 3) & 7;
10701 tmp = load_reg(s, rm);
10702 switch ((insn >> 6) & 3) {
10703 case 0: gen_sxth(tmp); break;
10704 case 1: gen_sxtb(tmp); break;
10705 case 2: gen_uxth(tmp); break;
10706 case 3: gen_uxtb(tmp); break;
10708 store_reg(s, rd, tmp);
10709 break;
10710 case 4: case 5: case 0xc: case 0xd:
10711 /* push/pop */
10712 addr = load_reg(s, 13);
10713 if (insn & (1 << 8))
10714 offset = 4;
10715 else
10716 offset = 0;
10717 for (i = 0; i < 8; i++) {
10718 if (insn & (1 << i))
10719 offset += 4;
10721 if ((insn & (1 << 11)) == 0) {
10722 tcg_gen_addi_i32(addr, addr, -offset);
10724 for (i = 0; i < 8; i++) {
10725 if (insn & (1 << i)) {
10726 if (insn & (1 << 11)) {
10727 /* pop */
10728 tmp = tcg_temp_new_i32();
10729 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10730 store_reg(s, i, tmp);
10731 } else {
10732 /* push */
10733 tmp = load_reg(s, i);
10734 gen_aa32_st32(tmp, addr, get_mem_index(s));
10735 tcg_temp_free_i32(tmp);
10737 /* advance to the next address. */
10738 tcg_gen_addi_i32(addr, addr, 4);
10741 TCGV_UNUSED_I32(tmp);
10742 if (insn & (1 << 8)) {
10743 if (insn & (1 << 11)) {
10744 /* pop pc */
10745 tmp = tcg_temp_new_i32();
10746 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10747 /* don't set the pc until the rest of the instruction
10748 has completed */
10749 } else {
10750 /* push lr */
10751 tmp = load_reg(s, 14);
10752 gen_aa32_st32(tmp, addr, get_mem_index(s));
10753 tcg_temp_free_i32(tmp);
10755 tcg_gen_addi_i32(addr, addr, 4);
10757 if ((insn & (1 << 11)) == 0) {
10758 tcg_gen_addi_i32(addr, addr, -offset);
10760 /* write back the new stack pointer */
10761 store_reg(s, 13, addr);
10762 /* set the new PC value */
10763 if ((insn & 0x0900) == 0x0900) {
10764 store_reg_from_load(env, s, 15, tmp);
10766 break;
10768 case 1: case 3: case 9: case 11: /* czb */
10769 rm = insn & 7;
10770 tmp = load_reg(s, rm);
10771 s->condlabel = gen_new_label();
10772 s->condjmp = 1;
10773 if (insn & (1 << 11))
10774 tcg_gen_brcondi_i32(TCG_COND_EQ, tmp, 0, s->condlabel);
10775 else
10776 tcg_gen_brcondi_i32(TCG_COND_NE, tmp, 0, s->condlabel);
10777 tcg_temp_free_i32(tmp);
10778 offset = ((insn & 0xf8) >> 2) | (insn & 0x200) >> 3;
10779 val = (uint32_t)s->pc + 2;
10780 val += offset;
10781 gen_jmp(s, val);
10782 break;
10784 case 15: /* IT, nop-hint. */
10785 if ((insn & 0xf) == 0) {
10786 gen_nop_hint(s, (insn >> 4) & 0xf);
10787 break;
10789 /* If Then. */
10790 s->condexec_cond = (insn >> 4) & 0xe;
10791 s->condexec_mask = insn & 0x1f;
10792 /* No actual code generated for this insn, just setup state. */
10793 break;
10795 case 0xe: /* bkpt */
10797 int imm8 = extract32(insn, 0, 8);
10798 ARCH(5);
10799 gen_exception_insn(s, 2, EXCP_BKPT, syn_aa32_bkpt(imm8, true));
10800 break;
10803 case 0xa: /* rev */
10804 ARCH(6);
10805 rn = (insn >> 3) & 0x7;
10806 rd = insn & 0x7;
10807 tmp = load_reg(s, rn);
10808 switch ((insn >> 6) & 3) {
10809 case 0: tcg_gen_bswap32_i32(tmp, tmp); break;
10810 case 1: gen_rev16(tmp); break;
10811 case 3: gen_revsh(tmp); break;
10812 default: goto illegal_op;
10814 store_reg(s, rd, tmp);
10815 break;
10817 case 6:
10818 switch ((insn >> 5) & 7) {
10819 case 2:
10820 /* setend */
10821 ARCH(6);
10822 if (((insn >> 3) & 1) != s->bswap_code) {
10823 /* Dynamic endianness switching not implemented. */
10824 qemu_log_mask(LOG_UNIMP, "arm: unimplemented setend\n");
10825 goto illegal_op;
10827 break;
10828 case 3:
10829 /* cps */
10830 ARCH(6);
10831 if (IS_USER(s)) {
10832 break;
10834 if (IS_M(env)) {
10835 tmp = tcg_const_i32((insn & (1 << 4)) != 0);
10836 /* FAULTMASK */
10837 if (insn & 1) {
10838 addr = tcg_const_i32(19);
10839 gen_helper_v7m_msr(cpu_env, addr, tmp);
10840 tcg_temp_free_i32(addr);
10842 /* PRIMASK */
10843 if (insn & 2) {
10844 addr = tcg_const_i32(16);
10845 gen_helper_v7m_msr(cpu_env, addr, tmp);
10846 tcg_temp_free_i32(addr);
10848 tcg_temp_free_i32(tmp);
10849 gen_lookup_tb(s);
10850 } else {
10851 if (insn & (1 << 4)) {
10852 shift = CPSR_A | CPSR_I | CPSR_F;
10853 } else {
10854 shift = 0;
10856 gen_set_psr_im(s, ((insn & 7) << 6), 0, shift);
10858 break;
10859 default:
10860 goto undef;
10862 break;
10864 default:
10865 goto undef;
10867 break;
10869 case 12:
10871 /* load/store multiple */
10872 TCGv_i32 loaded_var;
10873 TCGV_UNUSED_I32(loaded_var);
10874 rn = (insn >> 8) & 0x7;
10875 addr = load_reg(s, rn);
10876 for (i = 0; i < 8; i++) {
10877 if (insn & (1 << i)) {
10878 if (insn & (1 << 11)) {
10879 /* load */
10880 tmp = tcg_temp_new_i32();
10881 gen_aa32_ld32u(tmp, addr, get_mem_index(s));
10882 if (i == rn) {
10883 loaded_var = tmp;
10884 } else {
10885 store_reg(s, i, tmp);
10887 } else {
10888 /* store */
10889 tmp = load_reg(s, i);
10890 gen_aa32_st32(tmp, addr, get_mem_index(s));
10891 tcg_temp_free_i32(tmp);
10893 /* advance to the next address */
10894 tcg_gen_addi_i32(addr, addr, 4);
10897 if ((insn & (1 << rn)) == 0) {
10898 /* base reg not in list: base register writeback */
10899 store_reg(s, rn, addr);
10900 } else {
10901 /* base reg in list: if load, complete it now */
10902 if (insn & (1 << 11)) {
10903 store_reg(s, rn, loaded_var);
10905 tcg_temp_free_i32(addr);
10907 break;
10909 case 13:
10910 /* conditional branch or swi */
10911 cond = (insn >> 8) & 0xf;
10912 if (cond == 0xe)
10913 goto undef;
10915 if (cond == 0xf) {
10916 /* swi */
10917 gen_set_pc_im(s, s->pc);
10918 s->svc_imm = extract32(insn, 0, 8);
10919 s->is_jmp = DISAS_SWI;
10920 break;
10922 /* generate a conditional jump to next instruction */
10923 s->condlabel = gen_new_label();
10924 arm_gen_test_cc(cond ^ 1, s->condlabel);
10925 s->condjmp = 1;
10927 /* jump to the offset */
10928 val = (uint32_t)s->pc + 2;
10929 offset = ((int32_t)insn << 24) >> 24;
10930 val += offset << 1;
10931 gen_jmp(s, val);
10932 break;
10934 case 14:
10935 if (insn & (1 << 11)) {
10936 if (disas_thumb2_insn(env, s, insn))
10937 goto undef32;
10938 break;
10940 /* unconditional branch */
10941 val = (uint32_t)s->pc;
10942 offset = ((int32_t)insn << 21) >> 21;
10943 val += (offset << 1) + 2;
10944 gen_jmp(s, val);
10945 break;
10947 case 15:
10948 if (disas_thumb2_insn(env, s, insn))
10949 goto undef32;
10950 break;
10952 return;
10953 undef32:
10954 gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
10955 return;
10956 illegal_op:
10957 undef:
10958 gen_exception_insn(s, 2, EXCP_UDEF, syn_uncategorized());
10961 /* generate intermediate code in gen_opc_buf and gen_opparam_buf for
10962 basic block 'tb'. If search_pc is TRUE, also generate PC
10963 information for each intermediate instruction. */
10964 static inline void gen_intermediate_code_internal(ARMCPU *cpu,
10965 TranslationBlock *tb,
10966 bool search_pc)
10968 CPUState *cs = CPU(cpu);
10969 CPUARMState *env = &cpu->env;
10970 DisasContext dc1, *dc = &dc1;
10971 CPUBreakpoint *bp;
10972 uint16_t *gen_opc_end;
10973 int j, lj;
10974 target_ulong pc_start;
10975 target_ulong next_page_start;
10976 int num_insns;
10977 int max_insns;
10979 /* generate intermediate code */
10981 /* The A64 decoder has its own top level loop, because it doesn't need
10982 * the A32/T32 complexity to do with conditional execution/IT blocks/etc.
10984 if (ARM_TBFLAG_AARCH64_STATE(tb->flags)) {
10985 gen_intermediate_code_internal_a64(cpu, tb, search_pc);
10986 return;
10989 pc_start = tb->pc;
10991 dc->tb = tb;
10993 gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
10995 dc->is_jmp = DISAS_NEXT;
10996 dc->pc = pc_start;
10997 dc->singlestep_enabled = cs->singlestep_enabled;
10998 dc->condjmp = 0;
11000 dc->aarch64 = 0;
11001 dc->thumb = ARM_TBFLAG_THUMB(tb->flags);
11002 dc->bswap_code = ARM_TBFLAG_BSWAP_CODE(tb->flags);
11003 dc->condexec_mask = (ARM_TBFLAG_CONDEXEC(tb->flags) & 0xf) << 1;
11004 dc->condexec_cond = ARM_TBFLAG_CONDEXEC(tb->flags) >> 4;
11005 #if !defined(CONFIG_USER_ONLY)
11006 dc->user = (ARM_TBFLAG_PRIV(tb->flags) == 0);
11007 #endif
11008 dc->cpacr_fpen = ARM_TBFLAG_CPACR_FPEN(tb->flags);
11009 dc->vfp_enabled = ARM_TBFLAG_VFPEN(tb->flags);
11010 dc->vec_len = ARM_TBFLAG_VECLEN(tb->flags);
11011 dc->vec_stride = ARM_TBFLAG_VECSTRIDE(tb->flags);
11012 dc->c15_cpar = ARM_TBFLAG_XSCALE_CPAR(tb->flags);
11013 dc->cp_regs = cpu->cp_regs;
11014 dc->current_el = arm_current_el(env);
11015 dc->features = env->features;
11017 /* Single step state. The code-generation logic here is:
11018 * SS_ACTIVE == 0:
11019 * generate code with no special handling for single-stepping (except
11020 * that anything that can make us go to SS_ACTIVE == 1 must end the TB;
11021 * this happens anyway because those changes are all system register or
11022 * PSTATE writes).
11023 * SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
11024 * emit code for one insn
11025 * emit code to clear PSTATE.SS
11026 * emit code to generate software step exception for completed step
11027 * end TB (as usual for having generated an exception)
11028 * SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
11029 * emit code to generate a software step exception
11030 * end the TB
11032 dc->ss_active = ARM_TBFLAG_SS_ACTIVE(tb->flags);
11033 dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(tb->flags);
11034 dc->is_ldex = false;
11035 dc->ss_same_el = false; /* Can't be true since EL_d must be AArch64 */
11037 cpu_F0s = tcg_temp_new_i32();
11038 cpu_F1s = tcg_temp_new_i32();
11039 cpu_F0d = tcg_temp_new_i64();
11040 cpu_F1d = tcg_temp_new_i64();
11041 cpu_V0 = cpu_F0d;
11042 cpu_V1 = cpu_F1d;
11043 /* FIXME: cpu_M0 can probably be the same as cpu_V0. */
11044 cpu_M0 = tcg_temp_new_i64();
11045 next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
11046 lj = -1;
11047 num_insns = 0;
11048 max_insns = tb->cflags & CF_COUNT_MASK;
11049 if (max_insns == 0)
11050 max_insns = CF_COUNT_MASK;
11052 gen_tb_start();
11054 tcg_clear_temp_count();
11056 /* A note on handling of the condexec (IT) bits:
11058 * We want to avoid the overhead of having to write the updated condexec
11059 * bits back to the CPUARMState for every instruction in an IT block. So:
11060 * (1) if the condexec bits are not already zero then we write
11061 * zero back into the CPUARMState now. This avoids complications trying
11062 * to do it at the end of the block. (For example if we don't do this
11063 * it's hard to identify whether we can safely skip writing condexec
11064 * at the end of the TB, which we definitely want to do for the case
11065 * where a TB doesn't do anything with the IT state at all.)
11066 * (2) if we are going to leave the TB then we call gen_set_condexec()
11067 * which will write the correct value into CPUARMState if zero is wrong.
11068 * This is done both for leaving the TB at the end, and for leaving
11069 * it because of an exception we know will happen, which is done in
11070 * gen_exception_insn(). The latter is necessary because we need to
11071 * leave the TB with the PC/IT state just prior to execution of the
11072 * instruction which caused the exception.
11073 * (3) if we leave the TB unexpectedly (eg a data abort on a load)
11074 * then the CPUARMState will be wrong and we need to reset it.
11075 * This is handled in the same way as restoration of the
11076 * PC in these situations: we will be called again with search_pc=1
11077 * and generate a mapping of the condexec bits for each PC in
11078 * gen_opc_condexec_bits[]. restore_state_to_opc() then uses
11079 * this to restore the condexec bits.
11081 * Note that there are no instructions which can read the condexec
11082 * bits, and none which can write non-static values to them, so
11083 * we don't need to care about whether CPUARMState is correct in the
11084 * middle of a TB.
11087 /* Reset the conditional execution bits immediately. This avoids
11088 complications trying to do it at the end of the block. */
11089 if (dc->condexec_mask || dc->condexec_cond)
11091 TCGv_i32 tmp = tcg_temp_new_i32();
11092 tcg_gen_movi_i32(tmp, 0);
11093 store_cpu_field(tmp, condexec_bits);
11095 do {
11096 #ifdef CONFIG_USER_ONLY
11097 /* Intercept jump to the magic kernel page. */
11098 if (dc->pc >= 0xffff0000) {
11099 /* We always get here via a jump, so know we are not in a
11100 conditional execution block. */
11101 gen_exception_internal(EXCP_KERNEL_TRAP);
11102 dc->is_jmp = DISAS_UPDATE;
11103 break;
11105 #else
11106 if (dc->pc >= 0xfffffff0 && IS_M(env)) {
11107 /* We always get here via a jump, so know we are not in a
11108 conditional execution block. */
11109 gen_exception_internal(EXCP_EXCEPTION_EXIT);
11110 dc->is_jmp = DISAS_UPDATE;
11111 break;
11113 #endif
11115 if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
11116 QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
11117 if (bp->pc == dc->pc) {
11118 gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
11119 /* Advance PC so that clearing the breakpoint will
11120 invalidate this TB. */
11121 dc->pc += 2;
11122 goto done_generating;
11126 if (search_pc) {
11127 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
11128 if (lj < j) {
11129 lj++;
11130 while (lj < j)
11131 tcg_ctx.gen_opc_instr_start[lj++] = 0;
11133 tcg_ctx.gen_opc_pc[lj] = dc->pc;
11134 gen_opc_condexec_bits[lj] = (dc->condexec_cond << 4) | (dc->condexec_mask >> 1);
11135 tcg_ctx.gen_opc_instr_start[lj] = 1;
11136 tcg_ctx.gen_opc_icount[lj] = num_insns;
11139 if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO))
11140 gen_io_start();
11142 if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
11143 tcg_gen_debug_insn_start(dc->pc);
11146 if (dc->ss_active && !dc->pstate_ss) {
11147 /* Singlestep state is Active-pending.
11148 * If we're in this state at the start of a TB then either
11149 * a) we just took an exception to an EL which is being debugged
11150 * and this is the first insn in the exception handler
11151 * b) debug exceptions were masked and we just unmasked them
11152 * without changing EL (eg by clearing PSTATE.D)
11153 * In either case we're going to take a swstep exception in the
11154 * "did not step an insn" case, and so the syndrome ISV and EX
11155 * bits should be zero.
11157 assert(num_insns == 0);
11158 gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0));
11159 goto done_generating;
11162 if (dc->thumb) {
11163 disas_thumb_insn(env, dc);
11164 if (dc->condexec_mask) {
11165 dc->condexec_cond = (dc->condexec_cond & 0xe)
11166 | ((dc->condexec_mask >> 4) & 1);
11167 dc->condexec_mask = (dc->condexec_mask << 1) & 0x1f;
11168 if (dc->condexec_mask == 0) {
11169 dc->condexec_cond = 0;
11172 } else {
11173 disas_arm_insn(env, dc);
11176 if (dc->condjmp && !dc->is_jmp) {
11177 gen_set_label(dc->condlabel);
11178 dc->condjmp = 0;
11181 if (tcg_check_temp_count()) {
11182 fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
11183 dc->pc);
11186 /* Translation stops when a conditional branch is encountered.
11187 * Otherwise the subsequent code could get translated several times.
11188 * Also stop translation when a page boundary is reached. This
11189 * ensures prefetch aborts occur at the right place. */
11190 num_insns ++;
11191 } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
11192 !cs->singlestep_enabled &&
11193 !singlestep &&
11194 !dc->ss_active &&
11195 dc->pc < next_page_start &&
11196 num_insns < max_insns);
11198 if (tb->cflags & CF_LAST_IO) {
11199 if (dc->condjmp) {
11200 /* FIXME: This can theoretically happen with self-modifying
11201 code. */
11202 cpu_abort(cs, "IO on conditional branch instruction");
11204 gen_io_end();
11207 /* At this stage dc->condjmp will only be set when the skipped
11208 instruction was a conditional branch or trap, and the PC has
11209 already been written. */
11210 if (unlikely(cs->singlestep_enabled || dc->ss_active)) {
11211 /* Make sure the pc is updated, and raise a debug exception. */
11212 if (dc->condjmp) {
11213 gen_set_condexec(dc);
11214 if (dc->is_jmp == DISAS_SWI) {
11215 gen_ss_advance(dc);
11216 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
11217 } else if (dc->is_jmp == DISAS_HVC) {
11218 gen_ss_advance(dc);
11219 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm));
11220 } else if (dc->is_jmp == DISAS_SMC) {
11221 gen_ss_advance(dc);
11222 gen_exception(EXCP_SMC, syn_aa32_smc());
11223 } else if (dc->ss_active) {
11224 gen_step_complete_exception(dc);
11225 } else {
11226 gen_exception_internal(EXCP_DEBUG);
11228 gen_set_label(dc->condlabel);
11230 if (dc->condjmp || !dc->is_jmp) {
11231 gen_set_pc_im(dc, dc->pc);
11232 dc->condjmp = 0;
11234 gen_set_condexec(dc);
11235 if (dc->is_jmp == DISAS_SWI && !dc->condjmp) {
11236 gen_ss_advance(dc);
11237 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
11238 } else if (dc->is_jmp == DISAS_HVC && !dc->condjmp) {
11239 gen_ss_advance(dc);
11240 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm));
11241 } else if (dc->is_jmp == DISAS_SMC && !dc->condjmp) {
11242 gen_ss_advance(dc);
11243 gen_exception(EXCP_SMC, syn_aa32_smc());
11244 } else if (dc->ss_active) {
11245 gen_step_complete_exception(dc);
11246 } else {
11247 /* FIXME: Single stepping a WFI insn will not halt
11248 the CPU. */
11249 gen_exception_internal(EXCP_DEBUG);
11251 } else {
11252 /* While branches must always occur at the end of an IT block,
11253 there are a few other things that can cause us to terminate
11254 the TB in the middle of an IT block:
11255 - Exception generating instructions (bkpt, swi, undefined).
11256 - Page boundaries.
11257 - Hardware watchpoints.
11258 Hardware breakpoints have already been handled and skip this code.
11260 gen_set_condexec(dc);
11261 switch(dc->is_jmp) {
11262 case DISAS_NEXT:
11263 gen_goto_tb(dc, 1, dc->pc);
11264 break;
11265 default:
11266 case DISAS_JUMP:
11267 case DISAS_UPDATE:
11268 /* indicate that the hash table must be used to find the next TB */
11269 tcg_gen_exit_tb(0);
11270 break;
11271 case DISAS_TB_JUMP:
11272 /* nothing more to generate */
11273 break;
11274 case DISAS_WFI:
11275 gen_helper_wfi(cpu_env);
11276 break;
11277 case DISAS_WFE:
11278 gen_helper_wfe(cpu_env);
11279 break;
11280 case DISAS_SWI:
11281 gen_exception(EXCP_SWI, syn_aa32_svc(dc->svc_imm, dc->thumb));
11282 break;
11283 case DISAS_HVC:
11284 gen_exception(EXCP_HVC, syn_aa32_hvc(dc->svc_imm));
11285 break;
11286 case DISAS_SMC:
11287 gen_exception(EXCP_SMC, syn_aa32_smc());
11288 break;
11290 if (dc->condjmp) {
11291 gen_set_label(dc->condlabel);
11292 gen_set_condexec(dc);
11293 gen_goto_tb(dc, 1, dc->pc);
11294 dc->condjmp = 0;
11298 done_generating:
11299 gen_tb_end(tb, num_insns);
11300 *tcg_ctx.gen_opc_ptr = INDEX_op_end;
11302 #ifdef DEBUG_DISAS
11303 if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
11304 qemu_log("----------------\n");
11305 qemu_log("IN: %s\n", lookup_symbol(pc_start));
11306 log_target_disas(env, pc_start, dc->pc - pc_start,
11307 dc->thumb | (dc->bswap_code << 1));
11308 qemu_log("\n");
11310 #endif
11311 if (search_pc) {
11312 j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
11313 lj++;
11314 while (lj <= j)
11315 tcg_ctx.gen_opc_instr_start[lj++] = 0;
11316 } else {
11317 tb->size = dc->pc - pc_start;
11318 tb->icount = num_insns;
11322 void gen_intermediate_code(CPUARMState *env, TranslationBlock *tb)
11324 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, false);
11327 void gen_intermediate_code_pc(CPUARMState *env, TranslationBlock *tb)
11329 gen_intermediate_code_internal(arm_env_get_cpu(env), tb, true);
11332 static const char *cpu_mode_names[16] = {
11333 "usr", "fiq", "irq", "svc", "???", "???", "mon", "abt",
11334 "???", "???", "hyp", "und", "???", "???", "???", "sys"
11337 void arm_cpu_dump_state(CPUState *cs, FILE *f, fprintf_function cpu_fprintf,
11338 int flags)
11340 ARMCPU *cpu = ARM_CPU(cs);
11341 CPUARMState *env = &cpu->env;
11342 int i;
11343 uint32_t psr;
11345 if (is_a64(env)) {
11346 aarch64_cpu_dump_state(cs, f, cpu_fprintf, flags);
11347 return;
11350 for(i=0;i<16;i++) {
11351 cpu_fprintf(f, "R%02d=%08x", i, env->regs[i]);
11352 if ((i % 4) == 3)
11353 cpu_fprintf(f, "\n");
11354 else
11355 cpu_fprintf(f, " ");
11357 psr = cpsr_read(env);
11358 cpu_fprintf(f, "PSR=%08x %c%c%c%c %c %s%d\n",
11359 psr,
11360 psr & (1 << 31) ? 'N' : '-',
11361 psr & (1 << 30) ? 'Z' : '-',
11362 psr & (1 << 29) ? 'C' : '-',
11363 psr & (1 << 28) ? 'V' : '-',
11364 psr & CPSR_T ? 'T' : 'A',
11365 cpu_mode_names[psr & 0xf], (psr & 0x10) ? 32 : 26);
11367 if (flags & CPU_DUMP_FPU) {
11368 int numvfpregs = 0;
11369 if (arm_feature(env, ARM_FEATURE_VFP)) {
11370 numvfpregs += 16;
11372 if (arm_feature(env, ARM_FEATURE_VFP3)) {
11373 numvfpregs += 16;
11375 for (i = 0; i < numvfpregs; i++) {
11376 uint64_t v = float64_val(env->vfp.regs[i]);
11377 cpu_fprintf(f, "s%02d=%08x s%02d=%08x d%02d=%016" PRIx64 "\n",
11378 i * 2, (uint32_t)v,
11379 i * 2 + 1, (uint32_t)(v >> 32),
11380 i, v);
11382 cpu_fprintf(f, "FPSCR: %08x\n", (int)env->vfp.xregs[ARM_VFP_FPSCR]);
11386 void restore_state_to_opc(CPUARMState *env, TranslationBlock *tb, int pc_pos)
11388 if (is_a64(env)) {
11389 env->pc = tcg_ctx.gen_opc_pc[pc_pos];
11390 env->condexec_bits = 0;
11391 } else {
11392 env->regs[15] = tcg_ctx.gen_opc_pc[pc_pos];
11393 env->condexec_bits = gen_opc_condexec_bits[pc_pos];