]> Git Repo - qemu.git/blob - target-arm/translate-a64.c
target-arm: Implement CBAR for Cortex-A57
[qemu.git] / target-arm / translate-a64.c
1 /*
2  *  AArch64 translation
3  *
4  *  Copyright (c) 2013 Alexander Graf <[email protected]>
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
18  */
19 #include <stdarg.h>
20 #include <stdlib.h>
21 #include <stdio.h>
22 #include <string.h>
23 #include <inttypes.h>
24
25 #include "cpu.h"
26 #include "tcg-op.h"
27 #include "qemu/log.h"
28 #include "translate.h"
29 #include "internals.h"
30 #include "qemu/host-utils.h"
31
32 #include "exec/gen-icount.h"
33
34 #include "helper.h"
35 #define GEN_HELPER 1
36 #include "helper.h"
37
38 static TCGv_i64 cpu_X[32];
39 static TCGv_i64 cpu_pc;
40 static TCGv_i32 cpu_NF, cpu_ZF, cpu_CF, cpu_VF;
41
42 /* Load/store exclusive handling */
43 static TCGv_i64 cpu_exclusive_addr;
44 static TCGv_i64 cpu_exclusive_val;
45 static TCGv_i64 cpu_exclusive_high;
46 #ifdef CONFIG_USER_ONLY
47 static TCGv_i64 cpu_exclusive_test;
48 static TCGv_i32 cpu_exclusive_info;
49 #endif
50
51 static const char *regnames[] = {
52     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
53     "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
54     "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
55     "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
56 };
57
58 enum a64_shift_type {
59     A64_SHIFT_TYPE_LSL = 0,
60     A64_SHIFT_TYPE_LSR = 1,
61     A64_SHIFT_TYPE_ASR = 2,
62     A64_SHIFT_TYPE_ROR = 3
63 };
64
65 /* Table based decoder typedefs - used when the relevant bits for decode
66  * are too awkwardly scattered across the instruction (eg SIMD).
67  */
68 typedef void AArch64DecodeFn(DisasContext *s, uint32_t insn);
69
70 typedef struct AArch64DecodeTable {
71     uint32_t pattern;
72     uint32_t mask;
73     AArch64DecodeFn *disas_fn;
74 } AArch64DecodeTable;
75
76 /* Function prototype for gen_ functions for calling Neon helpers */
77 typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
78 typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
79 typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
80 typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
81 typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
82 typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
83 typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
84 typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
85 typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
86 typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
87 typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
88
89 /* initialize TCG globals.  */
90 void a64_translate_init(void)
91 {
92     int i;
93
94     cpu_pc = tcg_global_mem_new_i64(TCG_AREG0,
95                                     offsetof(CPUARMState, pc),
96                                     "pc");
97     for (i = 0; i < 32; i++) {
98         cpu_X[i] = tcg_global_mem_new_i64(TCG_AREG0,
99                                           offsetof(CPUARMState, xregs[i]),
100                                           regnames[i]);
101     }
102
103     cpu_NF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, NF), "NF");
104     cpu_ZF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, ZF), "ZF");
105     cpu_CF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, CF), "CF");
106     cpu_VF = tcg_global_mem_new_i32(TCG_AREG0, offsetof(CPUARMState, VF), "VF");
107
108     cpu_exclusive_addr = tcg_global_mem_new_i64(TCG_AREG0,
109         offsetof(CPUARMState, exclusive_addr), "exclusive_addr");
110     cpu_exclusive_val = tcg_global_mem_new_i64(TCG_AREG0,
111         offsetof(CPUARMState, exclusive_val), "exclusive_val");
112     cpu_exclusive_high = tcg_global_mem_new_i64(TCG_AREG0,
113         offsetof(CPUARMState, exclusive_high), "exclusive_high");
114 #ifdef CONFIG_USER_ONLY
115     cpu_exclusive_test = tcg_global_mem_new_i64(TCG_AREG0,
116         offsetof(CPUARMState, exclusive_test), "exclusive_test");
117     cpu_exclusive_info = tcg_global_mem_new_i32(TCG_AREG0,
118         offsetof(CPUARMState, exclusive_info), "exclusive_info");
119 #endif
120 }
121
122 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
123                             fprintf_function cpu_fprintf, int flags)
124 {
125     ARMCPU *cpu = ARM_CPU(cs);
126     CPUARMState *env = &cpu->env;
127     uint32_t psr = pstate_read(env);
128     int i;
129
130     cpu_fprintf(f, "PC=%016"PRIx64"  SP=%016"PRIx64"\n",
131             env->pc, env->xregs[31]);
132     for (i = 0; i < 31; i++) {
133         cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
134         if ((i % 4) == 3) {
135             cpu_fprintf(f, "\n");
136         } else {
137             cpu_fprintf(f, " ");
138         }
139     }
140     cpu_fprintf(f, "PSTATE=%08x (flags %c%c%c%c)\n",
141                 psr,
142                 psr & PSTATE_N ? 'N' : '-',
143                 psr & PSTATE_Z ? 'Z' : '-',
144                 psr & PSTATE_C ? 'C' : '-',
145                 psr & PSTATE_V ? 'V' : '-');
146     cpu_fprintf(f, "\n");
147
148     if (flags & CPU_DUMP_FPU) {
149         int numvfpregs = 32;
150         for (i = 0; i < numvfpregs; i += 2) {
151             uint64_t vlo = float64_val(env->vfp.regs[i * 2]);
152             uint64_t vhi = float64_val(env->vfp.regs[(i * 2) + 1]);
153             cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 " ",
154                         i, vhi, vlo);
155             vlo = float64_val(env->vfp.regs[(i + 1) * 2]);
156             vhi = float64_val(env->vfp.regs[((i + 1) * 2) + 1]);
157             cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "\n",
158                         i + 1, vhi, vlo);
159         }
160         cpu_fprintf(f, "FPCR: %08x  FPSR: %08x\n",
161                     vfp_get_fpcr(env), vfp_get_fpsr(env));
162     }
163 }
164
165 static int get_mem_index(DisasContext *s)
166 {
167 #ifdef CONFIG_USER_ONLY
168     return 1;
169 #else
170     return s->user;
171 #endif
172 }
173
174 void gen_a64_set_pc_im(uint64_t val)
175 {
176     tcg_gen_movi_i64(cpu_pc, val);
177 }
178
179 static void gen_exception_internal(int excp)
180 {
181     TCGv_i32 tcg_excp = tcg_const_i32(excp);
182
183     assert(excp_is_internal(excp));
184     gen_helper_exception_internal(cpu_env, tcg_excp);
185     tcg_temp_free_i32(tcg_excp);
186 }
187
188 static void gen_exception(int excp, uint32_t syndrome)
189 {
190     TCGv_i32 tcg_excp = tcg_const_i32(excp);
191     TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
192
193     gen_helper_exception_with_syndrome(cpu_env, tcg_excp, tcg_syn);
194     tcg_temp_free_i32(tcg_syn);
195     tcg_temp_free_i32(tcg_excp);
196 }
197
198 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
199 {
200     gen_a64_set_pc_im(s->pc - offset);
201     gen_exception_internal(excp);
202     s->is_jmp = DISAS_EXC;
203 }
204
205 static void gen_exception_insn(DisasContext *s, int offset, int excp,
206                                uint32_t syndrome)
207 {
208     gen_a64_set_pc_im(s->pc - offset);
209     gen_exception(excp, syndrome);
210     s->is_jmp = DISAS_EXC;
211 }
212
213 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
214 {
215     /* No direct tb linking with singlestep or deterministic io */
216     if (s->singlestep_enabled || (s->tb->cflags & CF_LAST_IO)) {
217         return false;
218     }
219
220     /* Only link tbs from inside the same guest page */
221     if ((s->tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
222         return false;
223     }
224
225     return true;
226 }
227
228 static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
229 {
230     TranslationBlock *tb;
231
232     tb = s->tb;
233     if (use_goto_tb(s, n, dest)) {
234         tcg_gen_goto_tb(n);
235         gen_a64_set_pc_im(dest);
236         tcg_gen_exit_tb((intptr_t)tb + n);
237         s->is_jmp = DISAS_TB_JUMP;
238     } else {
239         gen_a64_set_pc_im(dest);
240         if (s->singlestep_enabled) {
241             gen_exception_internal(EXCP_DEBUG);
242         }
243         tcg_gen_exit_tb(0);
244         s->is_jmp = DISAS_JUMP;
245     }
246 }
247
248 static void unallocated_encoding(DisasContext *s)
249 {
250     /* Unallocated and reserved encodings are uncategorized */
251     gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized());
252 }
253
254 #define unsupported_encoding(s, insn)                                    \
255     do {                                                                 \
256         qemu_log_mask(LOG_UNIMP,                                         \
257                       "%s:%d: unsupported instruction encoding 0x%08x "  \
258                       "at pc=%016" PRIx64 "\n",                          \
259                       __FILE__, __LINE__, insn, s->pc - 4);              \
260         unallocated_encoding(s);                                         \
261     } while (0);
262
263 static void init_tmp_a64_array(DisasContext *s)
264 {
265 #ifdef CONFIG_DEBUG_TCG
266     int i;
267     for (i = 0; i < ARRAY_SIZE(s->tmp_a64); i++) {
268         TCGV_UNUSED_I64(s->tmp_a64[i]);
269     }
270 #endif
271     s->tmp_a64_count = 0;
272 }
273
274 static void free_tmp_a64(DisasContext *s)
275 {
276     int i;
277     for (i = 0; i < s->tmp_a64_count; i++) {
278         tcg_temp_free_i64(s->tmp_a64[i]);
279     }
280     init_tmp_a64_array(s);
281 }
282
283 static TCGv_i64 new_tmp_a64(DisasContext *s)
284 {
285     assert(s->tmp_a64_count < TMP_A64_MAX);
286     return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
287 }
288
289 static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
290 {
291     TCGv_i64 t = new_tmp_a64(s);
292     tcg_gen_movi_i64(t, 0);
293     return t;
294 }
295
296 /*
297  * Register access functions
298  *
299  * These functions are used for directly accessing a register in where
300  * changes to the final register value are likely to be made. If you
301  * need to use a register for temporary calculation (e.g. index type
302  * operations) use the read_* form.
303  *
304  * B1.2.1 Register mappings
305  *
306  * In instruction register encoding 31 can refer to ZR (zero register) or
307  * the SP (stack pointer) depending on context. In QEMU's case we map SP
308  * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
309  * This is the point of the _sp forms.
310  */
311 static TCGv_i64 cpu_reg(DisasContext *s, int reg)
312 {
313     if (reg == 31) {
314         return new_tmp_a64_zero(s);
315     } else {
316         return cpu_X[reg];
317     }
318 }
319
320 /* register access for when 31 == SP */
321 static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
322 {
323     return cpu_X[reg];
324 }
325
326 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
327  * representing the register contents. This TCGv is an auto-freed
328  * temporary so it need not be explicitly freed, and may be modified.
329  */
330 static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
331 {
332     TCGv_i64 v = new_tmp_a64(s);
333     if (reg != 31) {
334         if (sf) {
335             tcg_gen_mov_i64(v, cpu_X[reg]);
336         } else {
337             tcg_gen_ext32u_i64(v, cpu_X[reg]);
338         }
339     } else {
340         tcg_gen_movi_i64(v, 0);
341     }
342     return v;
343 }
344
345 static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
346 {
347     TCGv_i64 v = new_tmp_a64(s);
348     if (sf) {
349         tcg_gen_mov_i64(v, cpu_X[reg]);
350     } else {
351         tcg_gen_ext32u_i64(v, cpu_X[reg]);
352     }
353     return v;
354 }
355
356 /* We should have at some point before trying to access an FP register
357  * done the necessary access check, so assert that
358  * (a) we did the check and
359  * (b) we didn't then just plough ahead anyway if it failed.
360  * Print the instruction pattern in the abort message so we can figure
361  * out what we need to fix if a user encounters this problem in the wild.
362  */
363 static inline void assert_fp_access_checked(DisasContext *s)
364 {
365 #ifdef CONFIG_DEBUG_TCG
366     if (unlikely(!s->fp_access_checked || !s->cpacr_fpen)) {
367         fprintf(stderr, "target-arm: FP access check missing for "
368                 "instruction 0x%08x\n", s->insn);
369         abort();
370     }
371 #endif
372 }
373
374 /* Return the offset into CPUARMState of an element of specified
375  * size, 'element' places in from the least significant end of
376  * the FP/vector register Qn.
377  */
378 static inline int vec_reg_offset(DisasContext *s, int regno,
379                                  int element, TCGMemOp size)
380 {
381     int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
382 #ifdef HOST_WORDS_BIGENDIAN
383     /* This is complicated slightly because vfp.regs[2n] is
384      * still the low half and  vfp.regs[2n+1] the high half
385      * of the 128 bit vector, even on big endian systems.
386      * Calculate the offset assuming a fully bigendian 128 bits,
387      * then XOR to account for the order of the two 64 bit halves.
388      */
389     offs += (16 - ((element + 1) * (1 << size)));
390     offs ^= 8;
391 #else
392     offs += element * (1 << size);
393 #endif
394     assert_fp_access_checked(s);
395     return offs;
396 }
397
398 /* Return the offset into CPUARMState of a slice (from
399  * the least significant end) of FP register Qn (ie
400  * Dn, Sn, Hn or Bn).
401  * (Note that this is not the same mapping as for A32; see cpu.h)
402  */
403 static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size)
404 {
405     int offs = offsetof(CPUARMState, vfp.regs[regno * 2]);
406 #ifdef HOST_WORDS_BIGENDIAN
407     offs += (8 - (1 << size));
408 #endif
409     assert_fp_access_checked(s);
410     return offs;
411 }
412
413 /* Offset of the high half of the 128 bit vector Qn */
414 static inline int fp_reg_hi_offset(DisasContext *s, int regno)
415 {
416     assert_fp_access_checked(s);
417     return offsetof(CPUARMState, vfp.regs[regno * 2 + 1]);
418 }
419
420 /* Convenience accessors for reading and writing single and double
421  * FP registers. Writing clears the upper parts of the associated
422  * 128 bit vector register, as required by the architecture.
423  * Note that unlike the GP register accessors, the values returned
424  * by the read functions must be manually freed.
425  */
426 static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
427 {
428     TCGv_i64 v = tcg_temp_new_i64();
429
430     tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
431     return v;
432 }
433
434 static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
435 {
436     TCGv_i32 v = tcg_temp_new_i32();
437
438     tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(s, reg, MO_32));
439     return v;
440 }
441
442 static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
443 {
444     TCGv_i64 tcg_zero = tcg_const_i64(0);
445
446     tcg_gen_st_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
447     tcg_gen_st_i64(tcg_zero, cpu_env, fp_reg_hi_offset(s, reg));
448     tcg_temp_free_i64(tcg_zero);
449 }
450
451 static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
452 {
453     TCGv_i64 tmp = tcg_temp_new_i64();
454
455     tcg_gen_extu_i32_i64(tmp, v);
456     write_fp_dreg(s, reg, tmp);
457     tcg_temp_free_i64(tmp);
458 }
459
460 static TCGv_ptr get_fpstatus_ptr(void)
461 {
462     TCGv_ptr statusptr = tcg_temp_new_ptr();
463     int offset;
464
465     /* In A64 all instructions (both FP and Neon) use the FPCR;
466      * there is no equivalent of the A32 Neon "standard FPSCR value"
467      * and all operations use vfp.fp_status.
468      */
469     offset = offsetof(CPUARMState, vfp.fp_status);
470     tcg_gen_addi_ptr(statusptr, cpu_env, offset);
471     return statusptr;
472 }
473
474 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
475  * than the 32 bit equivalent.
476  */
477 static inline void gen_set_NZ64(TCGv_i64 result)
478 {
479     TCGv_i64 flag = tcg_temp_new_i64();
480
481     tcg_gen_setcondi_i64(TCG_COND_NE, flag, result, 0);
482     tcg_gen_trunc_i64_i32(cpu_ZF, flag);
483     tcg_gen_shri_i64(flag, result, 32);
484     tcg_gen_trunc_i64_i32(cpu_NF, flag);
485     tcg_temp_free_i64(flag);
486 }
487
488 /* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
489 static inline void gen_logic_CC(int sf, TCGv_i64 result)
490 {
491     if (sf) {
492         gen_set_NZ64(result);
493     } else {
494         tcg_gen_trunc_i64_i32(cpu_ZF, result);
495         tcg_gen_trunc_i64_i32(cpu_NF, result);
496     }
497     tcg_gen_movi_i32(cpu_CF, 0);
498     tcg_gen_movi_i32(cpu_VF, 0);
499 }
500
501 /* dest = T0 + T1; compute C, N, V and Z flags */
502 static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
503 {
504     if (sf) {
505         TCGv_i64 result, flag, tmp;
506         result = tcg_temp_new_i64();
507         flag = tcg_temp_new_i64();
508         tmp = tcg_temp_new_i64();
509
510         tcg_gen_movi_i64(tmp, 0);
511         tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
512
513         tcg_gen_trunc_i64_i32(cpu_CF, flag);
514
515         gen_set_NZ64(result);
516
517         tcg_gen_xor_i64(flag, result, t0);
518         tcg_gen_xor_i64(tmp, t0, t1);
519         tcg_gen_andc_i64(flag, flag, tmp);
520         tcg_temp_free_i64(tmp);
521         tcg_gen_shri_i64(flag, flag, 32);
522         tcg_gen_trunc_i64_i32(cpu_VF, flag);
523
524         tcg_gen_mov_i64(dest, result);
525         tcg_temp_free_i64(result);
526         tcg_temp_free_i64(flag);
527     } else {
528         /* 32 bit arithmetic */
529         TCGv_i32 t0_32 = tcg_temp_new_i32();
530         TCGv_i32 t1_32 = tcg_temp_new_i32();
531         TCGv_i32 tmp = tcg_temp_new_i32();
532
533         tcg_gen_movi_i32(tmp, 0);
534         tcg_gen_trunc_i64_i32(t0_32, t0);
535         tcg_gen_trunc_i64_i32(t1_32, t1);
536         tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
537         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
538         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
539         tcg_gen_xor_i32(tmp, t0_32, t1_32);
540         tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
541         tcg_gen_extu_i32_i64(dest, cpu_NF);
542
543         tcg_temp_free_i32(tmp);
544         tcg_temp_free_i32(t0_32);
545         tcg_temp_free_i32(t1_32);
546     }
547 }
548
549 /* dest = T0 - T1; compute C, N, V and Z flags */
550 static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
551 {
552     if (sf) {
553         /* 64 bit arithmetic */
554         TCGv_i64 result, flag, tmp;
555
556         result = tcg_temp_new_i64();
557         flag = tcg_temp_new_i64();
558         tcg_gen_sub_i64(result, t0, t1);
559
560         gen_set_NZ64(result);
561
562         tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
563         tcg_gen_trunc_i64_i32(cpu_CF, flag);
564
565         tcg_gen_xor_i64(flag, result, t0);
566         tmp = tcg_temp_new_i64();
567         tcg_gen_xor_i64(tmp, t0, t1);
568         tcg_gen_and_i64(flag, flag, tmp);
569         tcg_temp_free_i64(tmp);
570         tcg_gen_shri_i64(flag, flag, 32);
571         tcg_gen_trunc_i64_i32(cpu_VF, flag);
572         tcg_gen_mov_i64(dest, result);
573         tcg_temp_free_i64(flag);
574         tcg_temp_free_i64(result);
575     } else {
576         /* 32 bit arithmetic */
577         TCGv_i32 t0_32 = tcg_temp_new_i32();
578         TCGv_i32 t1_32 = tcg_temp_new_i32();
579         TCGv_i32 tmp;
580
581         tcg_gen_trunc_i64_i32(t0_32, t0);
582         tcg_gen_trunc_i64_i32(t1_32, t1);
583         tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
584         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
585         tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
586         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
587         tmp = tcg_temp_new_i32();
588         tcg_gen_xor_i32(tmp, t0_32, t1_32);
589         tcg_temp_free_i32(t0_32);
590         tcg_temp_free_i32(t1_32);
591         tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
592         tcg_temp_free_i32(tmp);
593         tcg_gen_extu_i32_i64(dest, cpu_NF);
594     }
595 }
596
597 /* dest = T0 + T1 + CF; do not compute flags. */
598 static void gen_adc(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
599 {
600     TCGv_i64 flag = tcg_temp_new_i64();
601     tcg_gen_extu_i32_i64(flag, cpu_CF);
602     tcg_gen_add_i64(dest, t0, t1);
603     tcg_gen_add_i64(dest, dest, flag);
604     tcg_temp_free_i64(flag);
605
606     if (!sf) {
607         tcg_gen_ext32u_i64(dest, dest);
608     }
609 }
610
611 /* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
612 static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
613 {
614     if (sf) {
615         TCGv_i64 result, cf_64, vf_64, tmp;
616         result = tcg_temp_new_i64();
617         cf_64 = tcg_temp_new_i64();
618         vf_64 = tcg_temp_new_i64();
619         tmp = tcg_const_i64(0);
620
621         tcg_gen_extu_i32_i64(cf_64, cpu_CF);
622         tcg_gen_add2_i64(result, cf_64, t0, tmp, cf_64, tmp);
623         tcg_gen_add2_i64(result, cf_64, result, cf_64, t1, tmp);
624         tcg_gen_trunc_i64_i32(cpu_CF, cf_64);
625         gen_set_NZ64(result);
626
627         tcg_gen_xor_i64(vf_64, result, t0);
628         tcg_gen_xor_i64(tmp, t0, t1);
629         tcg_gen_andc_i64(vf_64, vf_64, tmp);
630         tcg_gen_shri_i64(vf_64, vf_64, 32);
631         tcg_gen_trunc_i64_i32(cpu_VF, vf_64);
632
633         tcg_gen_mov_i64(dest, result);
634
635         tcg_temp_free_i64(tmp);
636         tcg_temp_free_i64(vf_64);
637         tcg_temp_free_i64(cf_64);
638         tcg_temp_free_i64(result);
639     } else {
640         TCGv_i32 t0_32, t1_32, tmp;
641         t0_32 = tcg_temp_new_i32();
642         t1_32 = tcg_temp_new_i32();
643         tmp = tcg_const_i32(0);
644
645         tcg_gen_trunc_i64_i32(t0_32, t0);
646         tcg_gen_trunc_i64_i32(t1_32, t1);
647         tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, cpu_CF, tmp);
648         tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1_32, tmp);
649
650         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
651         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
652         tcg_gen_xor_i32(tmp, t0_32, t1_32);
653         tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
654         tcg_gen_extu_i32_i64(dest, cpu_NF);
655
656         tcg_temp_free_i32(tmp);
657         tcg_temp_free_i32(t1_32);
658         tcg_temp_free_i32(t0_32);
659     }
660 }
661
662 /*
663  * Load/Store generators
664  */
665
666 /*
667  * Store from GPR register to memory.
668  */
669 static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
670                              TCGv_i64 tcg_addr, int size, int memidx)
671 {
672     g_assert(size <= 3);
673     tcg_gen_qemu_st_i64(source, tcg_addr, memidx, MO_TE + size);
674 }
675
676 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
677                       TCGv_i64 tcg_addr, int size)
678 {
679     do_gpr_st_memidx(s, source, tcg_addr, size, get_mem_index(s));
680 }
681
682 /*
683  * Load from memory to GPR register
684  */
685 static void do_gpr_ld_memidx(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
686                              int size, bool is_signed, bool extend, int memidx)
687 {
688     TCGMemOp memop = MO_TE + size;
689
690     g_assert(size <= 3);
691
692     if (is_signed) {
693         memop += MO_SIGN;
694     }
695
696     tcg_gen_qemu_ld_i64(dest, tcg_addr, memidx, memop);
697
698     if (extend && is_signed) {
699         g_assert(size < 3);
700         tcg_gen_ext32u_i64(dest, dest);
701     }
702 }
703
704 static void do_gpr_ld(DisasContext *s, TCGv_i64 dest, TCGv_i64 tcg_addr,
705                       int size, bool is_signed, bool extend)
706 {
707     do_gpr_ld_memidx(s, dest, tcg_addr, size, is_signed, extend,
708                      get_mem_index(s));
709 }
710
711 /*
712  * Store from FP register to memory
713  */
714 static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
715 {
716     /* This writes the bottom N bits of a 128 bit wide vector to memory */
717     TCGv_i64 tmp = tcg_temp_new_i64();
718     tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
719     if (size < 4) {
720         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TE + size);
721     } else {
722         TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
723         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s), MO_TEQ);
724         tcg_gen_qemu_st64(tmp, tcg_addr, get_mem_index(s));
725         tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
726         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
727         tcg_gen_qemu_st_i64(tmp, tcg_hiaddr, get_mem_index(s), MO_TEQ);
728         tcg_temp_free_i64(tcg_hiaddr);
729     }
730
731     tcg_temp_free_i64(tmp);
732 }
733
734 /*
735  * Load from memory to FP register
736  */
737 static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
738 {
739     /* This always zero-extends and writes to a full 128 bit wide vector */
740     TCGv_i64 tmplo = tcg_temp_new_i64();
741     TCGv_i64 tmphi;
742
743     if (size < 4) {
744         TCGMemOp memop = MO_TE + size;
745         tmphi = tcg_const_i64(0);
746         tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
747     } else {
748         TCGv_i64 tcg_hiaddr;
749         tmphi = tcg_temp_new_i64();
750         tcg_hiaddr = tcg_temp_new_i64();
751
752         tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), MO_TEQ);
753         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
754         tcg_gen_qemu_ld_i64(tmphi, tcg_hiaddr, get_mem_index(s), MO_TEQ);
755         tcg_temp_free_i64(tcg_hiaddr);
756     }
757
758     tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
759     tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
760
761     tcg_temp_free_i64(tmplo);
762     tcg_temp_free_i64(tmphi);
763 }
764
765 /*
766  * Vector load/store helpers.
767  *
768  * The principal difference between this and a FP load is that we don't
769  * zero extend as we are filling a partial chunk of the vector register.
770  * These functions don't support 128 bit loads/stores, which would be
771  * normal load/store operations.
772  *
773  * The _i32 versions are useful when operating on 32 bit quantities
774  * (eg for floating point single or using Neon helper functions).
775  */
776
777 /* Get value of an element within a vector register */
778 static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
779                              int element, TCGMemOp memop)
780 {
781     int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
782     switch (memop) {
783     case MO_8:
784         tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
785         break;
786     case MO_16:
787         tcg_gen_ld16u_i64(tcg_dest, cpu_env, vect_off);
788         break;
789     case MO_32:
790         tcg_gen_ld32u_i64(tcg_dest, cpu_env, vect_off);
791         break;
792     case MO_8|MO_SIGN:
793         tcg_gen_ld8s_i64(tcg_dest, cpu_env, vect_off);
794         break;
795     case MO_16|MO_SIGN:
796         tcg_gen_ld16s_i64(tcg_dest, cpu_env, vect_off);
797         break;
798     case MO_32|MO_SIGN:
799         tcg_gen_ld32s_i64(tcg_dest, cpu_env, vect_off);
800         break;
801     case MO_64:
802     case MO_64|MO_SIGN:
803         tcg_gen_ld_i64(tcg_dest, cpu_env, vect_off);
804         break;
805     default:
806         g_assert_not_reached();
807     }
808 }
809
810 static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
811                                  int element, TCGMemOp memop)
812 {
813     int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
814     switch (memop) {
815     case MO_8:
816         tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off);
817         break;
818     case MO_16:
819         tcg_gen_ld16u_i32(tcg_dest, cpu_env, vect_off);
820         break;
821     case MO_8|MO_SIGN:
822         tcg_gen_ld8s_i32(tcg_dest, cpu_env, vect_off);
823         break;
824     case MO_16|MO_SIGN:
825         tcg_gen_ld16s_i32(tcg_dest, cpu_env, vect_off);
826         break;
827     case MO_32:
828     case MO_32|MO_SIGN:
829         tcg_gen_ld_i32(tcg_dest, cpu_env, vect_off);
830         break;
831     default:
832         g_assert_not_reached();
833     }
834 }
835
836 /* Set value of an element within a vector register */
837 static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
838                               int element, TCGMemOp memop)
839 {
840     int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
841     switch (memop) {
842     case MO_8:
843         tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
844         break;
845     case MO_16:
846         tcg_gen_st16_i64(tcg_src, cpu_env, vect_off);
847         break;
848     case MO_32:
849         tcg_gen_st32_i64(tcg_src, cpu_env, vect_off);
850         break;
851     case MO_64:
852         tcg_gen_st_i64(tcg_src, cpu_env, vect_off);
853         break;
854     default:
855         g_assert_not_reached();
856     }
857 }
858
859 static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
860                                   int destidx, int element, TCGMemOp memop)
861 {
862     int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
863     switch (memop) {
864     case MO_8:
865         tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
866         break;
867     case MO_16:
868         tcg_gen_st16_i32(tcg_src, cpu_env, vect_off);
869         break;
870     case MO_32:
871         tcg_gen_st_i32(tcg_src, cpu_env, vect_off);
872         break;
873     default:
874         g_assert_not_reached();
875     }
876 }
877
878 /* Clear the high 64 bits of a 128 bit vector (in general non-quad
879  * vector ops all need to do this).
880  */
881 static void clear_vec_high(DisasContext *s, int rd)
882 {
883     TCGv_i64 tcg_zero = tcg_const_i64(0);
884
885     write_vec_element(s, tcg_zero, rd, 1, MO_64);
886     tcg_temp_free_i64(tcg_zero);
887 }
888
889 /* Store from vector register to memory */
890 static void do_vec_st(DisasContext *s, int srcidx, int element,
891                       TCGv_i64 tcg_addr, int size)
892 {
893     TCGMemOp memop = MO_TE + size;
894     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
895
896     read_vec_element(s, tcg_tmp, srcidx, element, size);
897     tcg_gen_qemu_st_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
898
899     tcg_temp_free_i64(tcg_tmp);
900 }
901
902 /* Load from memory to vector register */
903 static void do_vec_ld(DisasContext *s, int destidx, int element,
904                       TCGv_i64 tcg_addr, int size)
905 {
906     TCGMemOp memop = MO_TE + size;
907     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
908
909     tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
910     write_vec_element(s, tcg_tmp, destidx, element, size);
911
912     tcg_temp_free_i64(tcg_tmp);
913 }
914
915 /* Check that FP/Neon access is enabled. If it is, return
916  * true. If not, emit code to generate an appropriate exception,
917  * and return false; the caller should not emit any code for
918  * the instruction. Note that this check must happen after all
919  * unallocated-encoding checks (otherwise the syndrome information
920  * for the resulting exception will be incorrect).
921  */
922 static inline bool fp_access_check(DisasContext *s)
923 {
924     assert(!s->fp_access_checked);
925     s->fp_access_checked = true;
926
927     if (s->cpacr_fpen) {
928         return true;
929     }
930
931     gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, false));
932     return false;
933 }
934
935 /*
936  * This utility function is for doing register extension with an
937  * optional shift. You will likely want to pass a temporary for the
938  * destination register. See DecodeRegExtend() in the ARM ARM.
939  */
940 static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
941                               int option, unsigned int shift)
942 {
943     int extsize = extract32(option, 0, 2);
944     bool is_signed = extract32(option, 2, 1);
945
946     if (is_signed) {
947         switch (extsize) {
948         case 0:
949             tcg_gen_ext8s_i64(tcg_out, tcg_in);
950             break;
951         case 1:
952             tcg_gen_ext16s_i64(tcg_out, tcg_in);
953             break;
954         case 2:
955             tcg_gen_ext32s_i64(tcg_out, tcg_in);
956             break;
957         case 3:
958             tcg_gen_mov_i64(tcg_out, tcg_in);
959             break;
960         }
961     } else {
962         switch (extsize) {
963         case 0:
964             tcg_gen_ext8u_i64(tcg_out, tcg_in);
965             break;
966         case 1:
967             tcg_gen_ext16u_i64(tcg_out, tcg_in);
968             break;
969         case 2:
970             tcg_gen_ext32u_i64(tcg_out, tcg_in);
971             break;
972         case 3:
973             tcg_gen_mov_i64(tcg_out, tcg_in);
974             break;
975         }
976     }
977
978     if (shift) {
979         tcg_gen_shli_i64(tcg_out, tcg_out, shift);
980     }
981 }
982
983 static inline void gen_check_sp_alignment(DisasContext *s)
984 {
985     /* The AArch64 architecture mandates that (if enabled via PSTATE
986      * or SCTLR bits) there is a check that SP is 16-aligned on every
987      * SP-relative load or store (with an exception generated if it is not).
988      * In line with general QEMU practice regarding misaligned accesses,
989      * we omit these checks for the sake of guest program performance.
990      * This function is provided as a hook so we can more easily add these
991      * checks in future (possibly as a "favour catching guest program bugs
992      * over speed" user selectable option).
993      */
994 }
995
996 /*
997  * This provides a simple table based table lookup decoder. It is
998  * intended to be used when the relevant bits for decode are too
999  * awkwardly placed and switch/if based logic would be confusing and
1000  * deeply nested. Since it's a linear search through the table, tables
1001  * should be kept small.
1002  *
1003  * It returns the first handler where insn & mask == pattern, or
1004  * NULL if there is no match.
1005  * The table is terminated by an empty mask (i.e. 0)
1006  */
1007 static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
1008                                                uint32_t insn)
1009 {
1010     const AArch64DecodeTable *tptr = table;
1011
1012     while (tptr->mask) {
1013         if ((insn & tptr->mask) == tptr->pattern) {
1014             return tptr->disas_fn;
1015         }
1016         tptr++;
1017     }
1018     return NULL;
1019 }
1020
1021 /*
1022  * the instruction disassembly implemented here matches
1023  * the instruction encoding classifications in chapter 3 (C3)
1024  * of the ARM Architecture Reference Manual (DDI0487A_a)
1025  */
1026
1027 /* C3.2.7 Unconditional branch (immediate)
1028  *   31  30       26 25                                  0
1029  * +----+-----------+-------------------------------------+
1030  * | op | 0 0 1 0 1 |                 imm26               |
1031  * +----+-----------+-------------------------------------+
1032  */
1033 static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
1034 {
1035     uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
1036
1037     if (insn & (1 << 31)) {
1038         /* C5.6.26 BL Branch with link */
1039         tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1040     }
1041
1042     /* C5.6.20 B Branch / C5.6.26 BL Branch with link */
1043     gen_goto_tb(s, 0, addr);
1044 }
1045
1046 /* C3.2.1 Compare & branch (immediate)
1047  *   31  30         25  24  23                  5 4      0
1048  * +----+-------------+----+---------------------+--------+
1049  * | sf | 0 1 1 0 1 0 | op |         imm19       |   Rt   |
1050  * +----+-------------+----+---------------------+--------+
1051  */
1052 static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
1053 {
1054     unsigned int sf, op, rt;
1055     uint64_t addr;
1056     int label_match;
1057     TCGv_i64 tcg_cmp;
1058
1059     sf = extract32(insn, 31, 1);
1060     op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
1061     rt = extract32(insn, 0, 5);
1062     addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
1063
1064     tcg_cmp = read_cpu_reg(s, rt, sf);
1065     label_match = gen_new_label();
1066
1067     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1068                         tcg_cmp, 0, label_match);
1069
1070     gen_goto_tb(s, 0, s->pc);
1071     gen_set_label(label_match);
1072     gen_goto_tb(s, 1, addr);
1073 }
1074
1075 /* C3.2.5 Test & branch (immediate)
1076  *   31  30         25  24  23   19 18          5 4    0
1077  * +----+-------------+----+-------+-------------+------+
1078  * | b5 | 0 1 1 0 1 1 | op |  b40  |    imm14    |  Rt  |
1079  * +----+-------------+----+-------+-------------+------+
1080  */
1081 static void disas_test_b_imm(DisasContext *s, uint32_t insn)
1082 {
1083     unsigned int bit_pos, op, rt;
1084     uint64_t addr;
1085     int label_match;
1086     TCGv_i64 tcg_cmp;
1087
1088     bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
1089     op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
1090     addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
1091     rt = extract32(insn, 0, 5);
1092
1093     tcg_cmp = tcg_temp_new_i64();
1094     tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
1095     label_match = gen_new_label();
1096     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1097                         tcg_cmp, 0, label_match);
1098     tcg_temp_free_i64(tcg_cmp);
1099     gen_goto_tb(s, 0, s->pc);
1100     gen_set_label(label_match);
1101     gen_goto_tb(s, 1, addr);
1102 }
1103
1104 /* C3.2.2 / C5.6.19 Conditional branch (immediate)
1105  *  31           25  24  23                  5   4  3    0
1106  * +---------------+----+---------------------+----+------+
1107  * | 0 1 0 1 0 1 0 | o1 |         imm19       | o0 | cond |
1108  * +---------------+----+---------------------+----+------+
1109  */
1110 static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
1111 {
1112     unsigned int cond;
1113     uint64_t addr;
1114
1115     if ((insn & (1 << 4)) || (insn & (1 << 24))) {
1116         unallocated_encoding(s);
1117         return;
1118     }
1119     addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
1120     cond = extract32(insn, 0, 4);
1121
1122     if (cond < 0x0e) {
1123         /* genuinely conditional branches */
1124         int label_match = gen_new_label();
1125         arm_gen_test_cc(cond, label_match);
1126         gen_goto_tb(s, 0, s->pc);
1127         gen_set_label(label_match);
1128         gen_goto_tb(s, 1, addr);
1129     } else {
1130         /* 0xe and 0xf are both "always" conditions */
1131         gen_goto_tb(s, 0, addr);
1132     }
1133 }
1134
1135 /* C5.6.68 HINT */
1136 static void handle_hint(DisasContext *s, uint32_t insn,
1137                         unsigned int op1, unsigned int op2, unsigned int crm)
1138 {
1139     unsigned int selector = crm << 3 | op2;
1140
1141     if (op1 != 3) {
1142         unallocated_encoding(s);
1143         return;
1144     }
1145
1146     switch (selector) {
1147     case 0: /* NOP */
1148         return;
1149     case 3: /* WFI */
1150         s->is_jmp = DISAS_WFI;
1151         return;
1152     case 1: /* YIELD */
1153     case 2: /* WFE */
1154     case 4: /* SEV */
1155     case 5: /* SEVL */
1156         /* we treat all as NOP at least for now */
1157         return;
1158     default:
1159         /* default specified as NOP equivalent */
1160         return;
1161     }
1162 }
1163
1164 static void gen_clrex(DisasContext *s, uint32_t insn)
1165 {
1166     tcg_gen_movi_i64(cpu_exclusive_addr, -1);
1167 }
1168
1169 /* CLREX, DSB, DMB, ISB */
1170 static void handle_sync(DisasContext *s, uint32_t insn,
1171                         unsigned int op1, unsigned int op2, unsigned int crm)
1172 {
1173     if (op1 != 3) {
1174         unallocated_encoding(s);
1175         return;
1176     }
1177
1178     switch (op2) {
1179     case 2: /* CLREX */
1180         gen_clrex(s, insn);
1181         return;
1182     case 4: /* DSB */
1183     case 5: /* DMB */
1184     case 6: /* ISB */
1185         /* We don't emulate caches so barriers are no-ops */
1186         return;
1187     default:
1188         unallocated_encoding(s);
1189         return;
1190     }
1191 }
1192
1193 /* C5.6.130 MSR (immediate) - move immediate to processor state field */
1194 static void handle_msr_i(DisasContext *s, uint32_t insn,
1195                          unsigned int op1, unsigned int op2, unsigned int crm)
1196 {
1197     int op = op1 << 3 | op2;
1198     switch (op) {
1199     case 0x05: /* SPSel */
1200         if (s->current_pl == 0) {
1201             unallocated_encoding(s);
1202             return;
1203         }
1204         /* fall through */
1205     case 0x1e: /* DAIFSet */
1206     case 0x1f: /* DAIFClear */
1207     {
1208         TCGv_i32 tcg_imm = tcg_const_i32(crm);
1209         TCGv_i32 tcg_op = tcg_const_i32(op);
1210         gen_a64_set_pc_im(s->pc - 4);
1211         gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
1212         tcg_temp_free_i32(tcg_imm);
1213         tcg_temp_free_i32(tcg_op);
1214         s->is_jmp = DISAS_UPDATE;
1215         break;
1216     }
1217     default:
1218         unallocated_encoding(s);
1219         return;
1220     }
1221 }
1222
1223 static void gen_get_nzcv(TCGv_i64 tcg_rt)
1224 {
1225     TCGv_i32 tmp = tcg_temp_new_i32();
1226     TCGv_i32 nzcv = tcg_temp_new_i32();
1227
1228     /* build bit 31, N */
1229     tcg_gen_andi_i32(nzcv, cpu_NF, (1 << 31));
1230     /* build bit 30, Z */
1231     tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
1232     tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
1233     /* build bit 29, C */
1234     tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
1235     /* build bit 28, V */
1236     tcg_gen_shri_i32(tmp, cpu_VF, 31);
1237     tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
1238     /* generate result */
1239     tcg_gen_extu_i32_i64(tcg_rt, nzcv);
1240
1241     tcg_temp_free_i32(nzcv);
1242     tcg_temp_free_i32(tmp);
1243 }
1244
1245 static void gen_set_nzcv(TCGv_i64 tcg_rt)
1246
1247 {
1248     TCGv_i32 nzcv = tcg_temp_new_i32();
1249
1250     /* take NZCV from R[t] */
1251     tcg_gen_trunc_i64_i32(nzcv, tcg_rt);
1252
1253     /* bit 31, N */
1254     tcg_gen_andi_i32(cpu_NF, nzcv, (1 << 31));
1255     /* bit 30, Z */
1256     tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
1257     tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
1258     /* bit 29, C */
1259     tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
1260     tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
1261     /* bit 28, V */
1262     tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
1263     tcg_gen_shli_i32(cpu_VF, cpu_VF, 3);
1264     tcg_temp_free_i32(nzcv);
1265 }
1266
1267 /* C5.6.129 MRS - move from system register
1268  * C5.6.131 MSR (register) - move to system register
1269  * C5.6.204 SYS
1270  * C5.6.205 SYSL
1271  * These are all essentially the same insn in 'read' and 'write'
1272  * versions, with varying op0 fields.
1273  */
1274 static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
1275                        unsigned int op0, unsigned int op1, unsigned int op2,
1276                        unsigned int crn, unsigned int crm, unsigned int rt)
1277 {
1278     const ARMCPRegInfo *ri;
1279     TCGv_i64 tcg_rt;
1280
1281     ri = get_arm_cp_reginfo(s->cp_regs,
1282                             ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
1283                                                crn, crm, op0, op1, op2));
1284
1285     if (!ri) {
1286         /* Unknown register; this might be a guest error or a QEMU
1287          * unimplemented feature.
1288          */
1289         qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch64 "
1290                       "system register op0:%d op1:%d crn:%d crm:%d op2:%d\n",
1291                       isread ? "read" : "write", op0, op1, crn, crm, op2);
1292         unallocated_encoding(s);
1293         return;
1294     }
1295
1296     /* Check access permissions */
1297     if (!cp_access_ok(s->current_pl, ri, isread)) {
1298         unallocated_encoding(s);
1299         return;
1300     }
1301
1302     if (ri->accessfn) {
1303         /* Emit code to perform further access permissions checks at
1304          * runtime; this may result in an exception.
1305          */
1306         TCGv_ptr tmpptr;
1307         TCGv_i32 tcg_syn;
1308         uint32_t syndrome;
1309
1310         gen_a64_set_pc_im(s->pc - 4);
1311         tmpptr = tcg_const_ptr(ri);
1312         syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
1313         tcg_syn = tcg_const_i32(syndrome);
1314         gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn);
1315         tcg_temp_free_ptr(tmpptr);
1316         tcg_temp_free_i32(tcg_syn);
1317     }
1318
1319     /* Handle special cases first */
1320     switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
1321     case ARM_CP_NOP:
1322         return;
1323     case ARM_CP_NZCV:
1324         tcg_rt = cpu_reg(s, rt);
1325         if (isread) {
1326             gen_get_nzcv(tcg_rt);
1327         } else {
1328             gen_set_nzcv(tcg_rt);
1329         }
1330         return;
1331     case ARM_CP_CURRENTEL:
1332         /* Reads as current EL value from pstate, which is
1333          * guaranteed to be constant by the tb flags.
1334          */
1335         tcg_rt = cpu_reg(s, rt);
1336         tcg_gen_movi_i64(tcg_rt, s->current_pl << 2);
1337         return;
1338     case ARM_CP_DC_ZVA:
1339         /* Writes clear the aligned block of memory which rt points into. */
1340         tcg_rt = cpu_reg(s, rt);
1341         gen_helper_dc_zva(cpu_env, tcg_rt);
1342         return;
1343     default:
1344         break;
1345     }
1346
1347     if (use_icount && (ri->type & ARM_CP_IO)) {
1348         gen_io_start();
1349     }
1350
1351     tcg_rt = cpu_reg(s, rt);
1352
1353     if (isread) {
1354         if (ri->type & ARM_CP_CONST) {
1355             tcg_gen_movi_i64(tcg_rt, ri->resetvalue);
1356         } else if (ri->readfn) {
1357             TCGv_ptr tmpptr;
1358             tmpptr = tcg_const_ptr(ri);
1359             gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr);
1360             tcg_temp_free_ptr(tmpptr);
1361         } else {
1362             tcg_gen_ld_i64(tcg_rt, cpu_env, ri->fieldoffset);
1363         }
1364     } else {
1365         if (ri->type & ARM_CP_CONST) {
1366             /* If not forbidden by access permissions, treat as WI */
1367             return;
1368         } else if (ri->writefn) {
1369             TCGv_ptr tmpptr;
1370             tmpptr = tcg_const_ptr(ri);
1371             gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt);
1372             tcg_temp_free_ptr(tmpptr);
1373         } else {
1374             tcg_gen_st_i64(tcg_rt, cpu_env, ri->fieldoffset);
1375         }
1376     }
1377
1378     if (use_icount && (ri->type & ARM_CP_IO)) {
1379         /* I/O operations must end the TB here (whether read or write) */
1380         gen_io_end();
1381         s->is_jmp = DISAS_UPDATE;
1382     } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
1383         /* We default to ending the TB on a coprocessor register write,
1384          * but allow this to be suppressed by the register definition
1385          * (usually only necessary to work around guest bugs).
1386          */
1387         s->is_jmp = DISAS_UPDATE;
1388     }
1389 }
1390
1391 /* C3.2.4 System
1392  *  31                 22 21  20 19 18 16 15   12 11    8 7   5 4    0
1393  * +---------------------+---+-----+-----+-------+-------+-----+------+
1394  * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 |  CRn  |  CRm  | op2 |  Rt  |
1395  * +---------------------+---+-----+-----+-------+-------+-----+------+
1396  */
1397 static void disas_system(DisasContext *s, uint32_t insn)
1398 {
1399     unsigned int l, op0, op1, crn, crm, op2, rt;
1400     l = extract32(insn, 21, 1);
1401     op0 = extract32(insn, 19, 2);
1402     op1 = extract32(insn, 16, 3);
1403     crn = extract32(insn, 12, 4);
1404     crm = extract32(insn, 8, 4);
1405     op2 = extract32(insn, 5, 3);
1406     rt = extract32(insn, 0, 5);
1407
1408     if (op0 == 0) {
1409         if (l || rt != 31) {
1410             unallocated_encoding(s);
1411             return;
1412         }
1413         switch (crn) {
1414         case 2: /* C5.6.68 HINT */
1415             handle_hint(s, insn, op1, op2, crm);
1416             break;
1417         case 3: /* CLREX, DSB, DMB, ISB */
1418             handle_sync(s, insn, op1, op2, crm);
1419             break;
1420         case 4: /* C5.6.130 MSR (immediate) */
1421             handle_msr_i(s, insn, op1, op2, crm);
1422             break;
1423         default:
1424             unallocated_encoding(s);
1425             break;
1426         }
1427         return;
1428     }
1429     handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
1430 }
1431
1432 /* C3.2.3 Exception generation
1433  *
1434  *  31             24 23 21 20                     5 4   2 1  0
1435  * +-----------------+-----+------------------------+-----+----+
1436  * | 1 1 0 1 0 1 0 0 | opc |          imm16         | op2 | LL |
1437  * +-----------------------+------------------------+----------+
1438  */
1439 static void disas_exc(DisasContext *s, uint32_t insn)
1440 {
1441     int opc = extract32(insn, 21, 3);
1442     int op2_ll = extract32(insn, 0, 5);
1443     int imm16 = extract32(insn, 5, 16);
1444
1445     switch (opc) {
1446     case 0:
1447         /* SVC, HVC, SMC; since we don't support the Virtualization
1448          * or TrustZone extensions these all UNDEF except SVC.
1449          */
1450         if (op2_ll != 1) {
1451             unallocated_encoding(s);
1452             break;
1453         }
1454         gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16));
1455         break;
1456     case 1:
1457         if (op2_ll != 0) {
1458             unallocated_encoding(s);
1459             break;
1460         }
1461         /* BRK */
1462         gen_exception_insn(s, 0, EXCP_BKPT, syn_aa64_bkpt(imm16));
1463         break;
1464     case 2:
1465         if (op2_ll != 0) {
1466             unallocated_encoding(s);
1467             break;
1468         }
1469         /* HLT */
1470         unsupported_encoding(s, insn);
1471         break;
1472     case 5:
1473         if (op2_ll < 1 || op2_ll > 3) {
1474             unallocated_encoding(s);
1475             break;
1476         }
1477         /* DCPS1, DCPS2, DCPS3 */
1478         unsupported_encoding(s, insn);
1479         break;
1480     default:
1481         unallocated_encoding(s);
1482         break;
1483     }
1484 }
1485
1486 /* C3.2.7 Unconditional branch (register)
1487  *  31           25 24   21 20   16 15   10 9    5 4     0
1488  * +---------------+-------+-------+-------+------+-------+
1489  * | 1 1 0 1 0 1 1 |  opc  |  op2  |  op3  |  Rn  |  op4  |
1490  * +---------------+-------+-------+-------+------+-------+
1491  */
1492 static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
1493 {
1494     unsigned int opc, op2, op3, rn, op4;
1495
1496     opc = extract32(insn, 21, 4);
1497     op2 = extract32(insn, 16, 5);
1498     op3 = extract32(insn, 10, 6);
1499     rn = extract32(insn, 5, 5);
1500     op4 = extract32(insn, 0, 5);
1501
1502     if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
1503         unallocated_encoding(s);
1504         return;
1505     }
1506
1507     switch (opc) {
1508     case 0: /* BR */
1509     case 2: /* RET */
1510         break;
1511     case 1: /* BLR */
1512         tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1513         break;
1514     case 4: /* ERET */
1515         gen_helper_exception_return(cpu_env);
1516         s->is_jmp = DISAS_JUMP;
1517         return;
1518     case 5: /* DRPS */
1519         if (rn != 0x1f) {
1520             unallocated_encoding(s);
1521         } else {
1522             unsupported_encoding(s, insn);
1523         }
1524         return;
1525     default:
1526         unallocated_encoding(s);
1527         return;
1528     }
1529
1530     tcg_gen_mov_i64(cpu_pc, cpu_reg(s, rn));
1531     s->is_jmp = DISAS_JUMP;
1532 }
1533
1534 /* C3.2 Branches, exception generating and system instructions */
1535 static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
1536 {
1537     switch (extract32(insn, 25, 7)) {
1538     case 0x0a: case 0x0b:
1539     case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
1540         disas_uncond_b_imm(s, insn);
1541         break;
1542     case 0x1a: case 0x5a: /* Compare & branch (immediate) */
1543         disas_comp_b_imm(s, insn);
1544         break;
1545     case 0x1b: case 0x5b: /* Test & branch (immediate) */
1546         disas_test_b_imm(s, insn);
1547         break;
1548     case 0x2a: /* Conditional branch (immediate) */
1549         disas_cond_b_imm(s, insn);
1550         break;
1551     case 0x6a: /* Exception generation / System */
1552         if (insn & (1 << 24)) {
1553             disas_system(s, insn);
1554         } else {
1555             disas_exc(s, insn);
1556         }
1557         break;
1558     case 0x6b: /* Unconditional branch (register) */
1559         disas_uncond_b_reg(s, insn);
1560         break;
1561     default:
1562         unallocated_encoding(s);
1563         break;
1564     }
1565 }
1566
1567 /*
1568  * Load/Store exclusive instructions are implemented by remembering
1569  * the value/address loaded, and seeing if these are the same
1570  * when the store is performed. This is not actually the architecturally
1571  * mandated semantics, but it works for typical guest code sequences
1572  * and avoids having to monitor regular stores.
1573  *
1574  * In system emulation mode only one CPU will be running at once, so
1575  * this sequence is effectively atomic.  In user emulation mode we
1576  * throw an exception and handle the atomic operation elsewhere.
1577  */
1578 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
1579                                TCGv_i64 addr, int size, bool is_pair)
1580 {
1581     TCGv_i64 tmp = tcg_temp_new_i64();
1582     TCGMemOp memop = MO_TE + size;
1583
1584     g_assert(size <= 3);
1585     tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), memop);
1586
1587     if (is_pair) {
1588         TCGv_i64 addr2 = tcg_temp_new_i64();
1589         TCGv_i64 hitmp = tcg_temp_new_i64();
1590
1591         g_assert(size >= 2);
1592         tcg_gen_addi_i64(addr2, addr, 1 << size);
1593         tcg_gen_qemu_ld_i64(hitmp, addr2, get_mem_index(s), memop);
1594         tcg_temp_free_i64(addr2);
1595         tcg_gen_mov_i64(cpu_exclusive_high, hitmp);
1596         tcg_gen_mov_i64(cpu_reg(s, rt2), hitmp);
1597         tcg_temp_free_i64(hitmp);
1598     }
1599
1600     tcg_gen_mov_i64(cpu_exclusive_val, tmp);
1601     tcg_gen_mov_i64(cpu_reg(s, rt), tmp);
1602
1603     tcg_temp_free_i64(tmp);
1604     tcg_gen_mov_i64(cpu_exclusive_addr, addr);
1605 }
1606
1607 #ifdef CONFIG_USER_ONLY
1608 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
1609                                 TCGv_i64 addr, int size, int is_pair)
1610 {
1611     tcg_gen_mov_i64(cpu_exclusive_test, addr);
1612     tcg_gen_movi_i32(cpu_exclusive_info,
1613                      size | is_pair << 2 | (rd << 4) | (rt << 9) | (rt2 << 14));
1614     gen_exception_internal_insn(s, 4, EXCP_STREX);
1615 }
1616 #else
1617 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
1618                                 TCGv_i64 inaddr, int size, int is_pair)
1619 {
1620     /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]
1621      *     && (!is_pair || env->exclusive_high == [addr + datasize])) {
1622      *     [addr] = {Rt};
1623      *     if (is_pair) {
1624      *         [addr + datasize] = {Rt2};
1625      *     }
1626      *     {Rd} = 0;
1627      * } else {
1628      *     {Rd} = 1;
1629      * }
1630      * env->exclusive_addr = -1;
1631      */
1632     int fail_label = gen_new_label();
1633     int done_label = gen_new_label();
1634     TCGv_i64 addr = tcg_temp_local_new_i64();
1635     TCGv_i64 tmp;
1636
1637     /* Copy input into a local temp so it is not trashed when the
1638      * basic block ends at the branch insn.
1639      */
1640     tcg_gen_mov_i64(addr, inaddr);
1641     tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
1642
1643     tmp = tcg_temp_new_i64();
1644     tcg_gen_qemu_ld_i64(tmp, addr, get_mem_index(s), MO_TE + size);
1645     tcg_gen_brcond_i64(TCG_COND_NE, tmp, cpu_exclusive_val, fail_label);
1646     tcg_temp_free_i64(tmp);
1647
1648     if (is_pair) {
1649         TCGv_i64 addrhi = tcg_temp_new_i64();
1650         TCGv_i64 tmphi = tcg_temp_new_i64();
1651
1652         tcg_gen_addi_i64(addrhi, addr, 1 << size);
1653         tcg_gen_qemu_ld_i64(tmphi, addrhi, get_mem_index(s), MO_TE + size);
1654         tcg_gen_brcond_i64(TCG_COND_NE, tmphi, cpu_exclusive_high, fail_label);
1655
1656         tcg_temp_free_i64(tmphi);
1657         tcg_temp_free_i64(addrhi);
1658     }
1659
1660     /* We seem to still have the exclusive monitor, so do the store */
1661     tcg_gen_qemu_st_i64(cpu_reg(s, rt), addr, get_mem_index(s), MO_TE + size);
1662     if (is_pair) {
1663         TCGv_i64 addrhi = tcg_temp_new_i64();
1664
1665         tcg_gen_addi_i64(addrhi, addr, 1 << size);
1666         tcg_gen_qemu_st_i64(cpu_reg(s, rt2), addrhi,
1667                             get_mem_index(s), MO_TE + size);
1668         tcg_temp_free_i64(addrhi);
1669     }
1670
1671     tcg_temp_free_i64(addr);
1672
1673     tcg_gen_movi_i64(cpu_reg(s, rd), 0);
1674     tcg_gen_br(done_label);
1675     gen_set_label(fail_label);
1676     tcg_gen_movi_i64(cpu_reg(s, rd), 1);
1677     gen_set_label(done_label);
1678     tcg_gen_movi_i64(cpu_exclusive_addr, -1);
1679
1680 }
1681 #endif
1682
1683 /* C3.3.6 Load/store exclusive
1684  *
1685  *  31 30 29         24  23  22   21  20  16  15  14   10 9    5 4    0
1686  * +-----+-------------+----+---+----+------+----+-------+------+------+
1687  * | sz  | 0 0 1 0 0 0 | o2 | L | o1 |  Rs  | o0 |  Rt2  |  Rn  | Rt   |
1688  * +-----+-------------+----+---+----+------+----+-------+------+------+
1689  *
1690  *  sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
1691  *   L: 0 -> store, 1 -> load
1692  *  o2: 0 -> exclusive, 1 -> not
1693  *  o1: 0 -> single register, 1 -> register pair
1694  *  o0: 1 -> load-acquire/store-release, 0 -> not
1695  *
1696  *  o0 == 0 AND o2 == 1 is un-allocated
1697  *  o1 == 1 is un-allocated except for 32 and 64 bit sizes
1698  */
1699 static void disas_ldst_excl(DisasContext *s, uint32_t insn)
1700 {
1701     int rt = extract32(insn, 0, 5);
1702     int rn = extract32(insn, 5, 5);
1703     int rt2 = extract32(insn, 10, 5);
1704     int is_lasr = extract32(insn, 15, 1);
1705     int rs = extract32(insn, 16, 5);
1706     int is_pair = extract32(insn, 21, 1);
1707     int is_store = !extract32(insn, 22, 1);
1708     int is_excl = !extract32(insn, 23, 1);
1709     int size = extract32(insn, 30, 2);
1710     TCGv_i64 tcg_addr;
1711
1712     if ((!is_excl && !is_lasr) ||
1713         (is_pair && size < 2)) {
1714         unallocated_encoding(s);
1715         return;
1716     }
1717
1718     if (rn == 31) {
1719         gen_check_sp_alignment(s);
1720     }
1721     tcg_addr = read_cpu_reg_sp(s, rn, 1);
1722
1723     /* Note that since TCG is single threaded load-acquire/store-release
1724      * semantics require no extra if (is_lasr) { ... } handling.
1725      */
1726
1727     if (is_excl) {
1728         if (!is_store) {
1729             gen_load_exclusive(s, rt, rt2, tcg_addr, size, is_pair);
1730         } else {
1731             gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, is_pair);
1732         }
1733     } else {
1734         TCGv_i64 tcg_rt = cpu_reg(s, rt);
1735         if (is_store) {
1736             do_gpr_st(s, tcg_rt, tcg_addr, size);
1737         } else {
1738             do_gpr_ld(s, tcg_rt, tcg_addr, size, false, false);
1739         }
1740         if (is_pair) {
1741             TCGv_i64 tcg_rt2 = cpu_reg(s, rt);
1742             tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
1743             if (is_store) {
1744                 do_gpr_st(s, tcg_rt2, tcg_addr, size);
1745             } else {
1746                 do_gpr_ld(s, tcg_rt2, tcg_addr, size, false, false);
1747             }
1748         }
1749     }
1750 }
1751
1752 /*
1753  * C3.3.5 Load register (literal)
1754  *
1755  *  31 30 29   27  26 25 24 23                5 4     0
1756  * +-----+-------+---+-----+-------------------+-------+
1757  * | opc | 0 1 1 | V | 0 0 |     imm19         |  Rt   |
1758  * +-----+-------+---+-----+-------------------+-------+
1759  *
1760  * V: 1 -> vector (simd/fp)
1761  * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
1762  *                   10-> 32 bit signed, 11 -> prefetch
1763  * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
1764  */
1765 static void disas_ld_lit(DisasContext *s, uint32_t insn)
1766 {
1767     int rt = extract32(insn, 0, 5);
1768     int64_t imm = sextract32(insn, 5, 19) << 2;
1769     bool is_vector = extract32(insn, 26, 1);
1770     int opc = extract32(insn, 30, 2);
1771     bool is_signed = false;
1772     int size = 2;
1773     TCGv_i64 tcg_rt, tcg_addr;
1774
1775     if (is_vector) {
1776         if (opc == 3) {
1777             unallocated_encoding(s);
1778             return;
1779         }
1780         size = 2 + opc;
1781         if (!fp_access_check(s)) {
1782             return;
1783         }
1784     } else {
1785         if (opc == 3) {
1786             /* PRFM (literal) : prefetch */
1787             return;
1788         }
1789         size = 2 + extract32(opc, 0, 1);
1790         is_signed = extract32(opc, 1, 1);
1791     }
1792
1793     tcg_rt = cpu_reg(s, rt);
1794
1795     tcg_addr = tcg_const_i64((s->pc - 4) + imm);
1796     if (is_vector) {
1797         do_fp_ld(s, rt, tcg_addr, size);
1798     } else {
1799         do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
1800     }
1801     tcg_temp_free_i64(tcg_addr);
1802 }
1803
1804 /*
1805  * C5.6.80 LDNP (Load Pair - non-temporal hint)
1806  * C5.6.81 LDP (Load Pair - non vector)
1807  * C5.6.82 LDPSW (Load Pair Signed Word - non vector)
1808  * C5.6.176 STNP (Store Pair - non-temporal hint)
1809  * C5.6.177 STP (Store Pair - non vector)
1810  * C6.3.165 LDNP (Load Pair of SIMD&FP - non-temporal hint)
1811  * C6.3.165 LDP (Load Pair of SIMD&FP)
1812  * C6.3.284 STNP (Store Pair of SIMD&FP - non-temporal hint)
1813  * C6.3.284 STP (Store Pair of SIMD&FP)
1814  *
1815  *  31 30 29   27  26  25 24   23  22 21   15 14   10 9    5 4    0
1816  * +-----+-------+---+---+-------+---+-----------------------------+
1817  * | opc | 1 0 1 | V | 0 | index | L |  imm7 |  Rt2  |  Rn  | Rt   |
1818  * +-----+-------+---+---+-------+---+-------+-------+------+------+
1819  *
1820  * opc: LDP/STP/LDNP/STNP        00 -> 32 bit, 10 -> 64 bit
1821  *      LDPSW                    01
1822  *      LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
1823  *   V: 0 -> GPR, 1 -> Vector
1824  * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
1825  *      10 -> signed offset, 11 -> pre-index
1826  *   L: 0 -> Store 1 -> Load
1827  *
1828  * Rt, Rt2 = GPR or SIMD registers to be stored
1829  * Rn = general purpose register containing address
1830  * imm7 = signed offset (multiple of 4 or 8 depending on size)
1831  */
1832 static void disas_ldst_pair(DisasContext *s, uint32_t insn)
1833 {
1834     int rt = extract32(insn, 0, 5);
1835     int rn = extract32(insn, 5, 5);
1836     int rt2 = extract32(insn, 10, 5);
1837     int64_t offset = sextract32(insn, 15, 7);
1838     int index = extract32(insn, 23, 2);
1839     bool is_vector = extract32(insn, 26, 1);
1840     bool is_load = extract32(insn, 22, 1);
1841     int opc = extract32(insn, 30, 2);
1842
1843     bool is_signed = false;
1844     bool postindex = false;
1845     bool wback = false;
1846
1847     TCGv_i64 tcg_addr; /* calculated address */
1848     int size;
1849
1850     if (opc == 3) {
1851         unallocated_encoding(s);
1852         return;
1853     }
1854
1855     if (is_vector) {
1856         size = 2 + opc;
1857     } else {
1858         size = 2 + extract32(opc, 1, 1);
1859         is_signed = extract32(opc, 0, 1);
1860         if (!is_load && is_signed) {
1861             unallocated_encoding(s);
1862             return;
1863         }
1864     }
1865
1866     switch (index) {
1867     case 1: /* post-index */
1868         postindex = true;
1869         wback = true;
1870         break;
1871     case 0:
1872         /* signed offset with "non-temporal" hint. Since we don't emulate
1873          * caches we don't care about hints to the cache system about
1874          * data access patterns, and handle this identically to plain
1875          * signed offset.
1876          */
1877         if (is_signed) {
1878             /* There is no non-temporal-hint version of LDPSW */
1879             unallocated_encoding(s);
1880             return;
1881         }
1882         postindex = false;
1883         break;
1884     case 2: /* signed offset, rn not updated */
1885         postindex = false;
1886         break;
1887     case 3: /* pre-index */
1888         postindex = false;
1889         wback = true;
1890         break;
1891     }
1892
1893     if (is_vector && !fp_access_check(s)) {
1894         return;
1895     }
1896
1897     offset <<= size;
1898
1899     if (rn == 31) {
1900         gen_check_sp_alignment(s);
1901     }
1902
1903     tcg_addr = read_cpu_reg_sp(s, rn, 1);
1904
1905     if (!postindex) {
1906         tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
1907     }
1908
1909     if (is_vector) {
1910         if (is_load) {
1911             do_fp_ld(s, rt, tcg_addr, size);
1912         } else {
1913             do_fp_st(s, rt, tcg_addr, size);
1914         }
1915     } else {
1916         TCGv_i64 tcg_rt = cpu_reg(s, rt);
1917         if (is_load) {
1918             do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false);
1919         } else {
1920             do_gpr_st(s, tcg_rt, tcg_addr, size);
1921         }
1922     }
1923     tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
1924     if (is_vector) {
1925         if (is_load) {
1926             do_fp_ld(s, rt2, tcg_addr, size);
1927         } else {
1928             do_fp_st(s, rt2, tcg_addr, size);
1929         }
1930     } else {
1931         TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
1932         if (is_load) {
1933             do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false);
1934         } else {
1935             do_gpr_st(s, tcg_rt2, tcg_addr, size);
1936         }
1937     }
1938
1939     if (wback) {
1940         if (postindex) {
1941             tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
1942         } else {
1943             tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
1944         }
1945         tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
1946     }
1947 }
1948
1949 /*
1950  * C3.3.8 Load/store (immediate post-indexed)
1951  * C3.3.9 Load/store (immediate pre-indexed)
1952  * C3.3.12 Load/store (unscaled immediate)
1953  *
1954  * 31 30 29   27  26 25 24 23 22 21  20    12 11 10 9    5 4    0
1955  * +----+-------+---+-----+-----+---+--------+-----+------+------+
1956  * |size| 1 1 1 | V | 0 0 | opc | 0 |  imm9  | idx |  Rn  |  Rt  |
1957  * +----+-------+---+-----+-----+---+--------+-----+------+------+
1958  *
1959  * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
1960          10 -> unprivileged
1961  * V = 0 -> non-vector
1962  * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
1963  * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
1964  */
1965 static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn)
1966 {
1967     int rt = extract32(insn, 0, 5);
1968     int rn = extract32(insn, 5, 5);
1969     int imm9 = sextract32(insn, 12, 9);
1970     int opc = extract32(insn, 22, 2);
1971     int size = extract32(insn, 30, 2);
1972     int idx = extract32(insn, 10, 2);
1973     bool is_signed = false;
1974     bool is_store = false;
1975     bool is_extended = false;
1976     bool is_unpriv = (idx == 2);
1977     bool is_vector = extract32(insn, 26, 1);
1978     bool post_index;
1979     bool writeback;
1980
1981     TCGv_i64 tcg_addr;
1982
1983     if (is_vector) {
1984         size |= (opc & 2) << 1;
1985         if (size > 4 || is_unpriv) {
1986             unallocated_encoding(s);
1987             return;
1988         }
1989         is_store = ((opc & 1) == 0);
1990         if (!fp_access_check(s)) {
1991             return;
1992         }
1993     } else {
1994         if (size == 3 && opc == 2) {
1995             /* PRFM - prefetch */
1996             if (is_unpriv) {
1997                 unallocated_encoding(s);
1998                 return;
1999             }
2000             return;
2001         }
2002         if (opc == 3 && size > 1) {
2003             unallocated_encoding(s);
2004             return;
2005         }
2006         is_store = (opc == 0);
2007         is_signed = opc & (1<<1);
2008         is_extended = (size < 3) && (opc & 1);
2009     }
2010
2011     switch (idx) {
2012     case 0:
2013     case 2:
2014         post_index = false;
2015         writeback = false;
2016         break;
2017     case 1:
2018         post_index = true;
2019         writeback = true;
2020         break;
2021     case 3:
2022         post_index = false;
2023         writeback = true;
2024         break;
2025     }
2026
2027     if (rn == 31) {
2028         gen_check_sp_alignment(s);
2029     }
2030     tcg_addr = read_cpu_reg_sp(s, rn, 1);
2031
2032     if (!post_index) {
2033         tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
2034     }
2035
2036     if (is_vector) {
2037         if (is_store) {
2038             do_fp_st(s, rt, tcg_addr, size);
2039         } else {
2040             do_fp_ld(s, rt, tcg_addr, size);
2041         }
2042     } else {
2043         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2044         int memidx = is_unpriv ? 1 : get_mem_index(s);
2045
2046         if (is_store) {
2047             do_gpr_st_memidx(s, tcg_rt, tcg_addr, size, memidx);
2048         } else {
2049             do_gpr_ld_memidx(s, tcg_rt, tcg_addr, size,
2050                              is_signed, is_extended, memidx);
2051         }
2052     }
2053
2054     if (writeback) {
2055         TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
2056         if (post_index) {
2057             tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
2058         }
2059         tcg_gen_mov_i64(tcg_rn, tcg_addr);
2060     }
2061 }
2062
2063 /*
2064  * C3.3.10 Load/store (register offset)
2065  *
2066  * 31 30 29   27  26 25 24 23 22 21  20  16 15 13 12 11 10 9  5 4  0
2067  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2068  * |size| 1 1 1 | V | 0 0 | opc | 1 |  Rm  | opt | S| 1 0 | Rn | Rt |
2069  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2070  *
2071  * For non-vector:
2072  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
2073  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2074  * For vector:
2075  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
2076  *   opc<0>: 0 -> store, 1 -> load
2077  * V: 1 -> vector/simd
2078  * opt: extend encoding (see DecodeRegExtend)
2079  * S: if S=1 then scale (essentially index by sizeof(size))
2080  * Rt: register to transfer into/out of
2081  * Rn: address register or SP for base
2082  * Rm: offset register or ZR for offset
2083  */
2084 static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn)
2085 {
2086     int rt = extract32(insn, 0, 5);
2087     int rn = extract32(insn, 5, 5);
2088     int shift = extract32(insn, 12, 1);
2089     int rm = extract32(insn, 16, 5);
2090     int opc = extract32(insn, 22, 2);
2091     int opt = extract32(insn, 13, 3);
2092     int size = extract32(insn, 30, 2);
2093     bool is_signed = false;
2094     bool is_store = false;
2095     bool is_extended = false;
2096     bool is_vector = extract32(insn, 26, 1);
2097
2098     TCGv_i64 tcg_rm;
2099     TCGv_i64 tcg_addr;
2100
2101     if (extract32(opt, 1, 1) == 0) {
2102         unallocated_encoding(s);
2103         return;
2104     }
2105
2106     if (is_vector) {
2107         size |= (opc & 2) << 1;
2108         if (size > 4) {
2109             unallocated_encoding(s);
2110             return;
2111         }
2112         is_store = !extract32(opc, 0, 1);
2113         if (!fp_access_check(s)) {
2114             return;
2115         }
2116     } else {
2117         if (size == 3 && opc == 2) {
2118             /* PRFM - prefetch */
2119             return;
2120         }
2121         if (opc == 3 && size > 1) {
2122             unallocated_encoding(s);
2123             return;
2124         }
2125         is_store = (opc == 0);
2126         is_signed = extract32(opc, 1, 1);
2127         is_extended = (size < 3) && extract32(opc, 0, 1);
2128     }
2129
2130     if (rn == 31) {
2131         gen_check_sp_alignment(s);
2132     }
2133     tcg_addr = read_cpu_reg_sp(s, rn, 1);
2134
2135     tcg_rm = read_cpu_reg(s, rm, 1);
2136     ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
2137
2138     tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
2139
2140     if (is_vector) {
2141         if (is_store) {
2142             do_fp_st(s, rt, tcg_addr, size);
2143         } else {
2144             do_fp_ld(s, rt, tcg_addr, size);
2145         }
2146     } else {
2147         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2148         if (is_store) {
2149             do_gpr_st(s, tcg_rt, tcg_addr, size);
2150         } else {
2151             do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
2152         }
2153     }
2154 }
2155
2156 /*
2157  * C3.3.13 Load/store (unsigned immediate)
2158  *
2159  * 31 30 29   27  26 25 24 23 22 21        10 9     5
2160  * +----+-------+---+-----+-----+------------+-------+------+
2161  * |size| 1 1 1 | V | 0 1 | opc |   imm12    |  Rn   |  Rt  |
2162  * +----+-------+---+-----+-----+------------+-------+------+
2163  *
2164  * For non-vector:
2165  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
2166  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2167  * For vector:
2168  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
2169  *   opc<0>: 0 -> store, 1 -> load
2170  * Rn: base address register (inc SP)
2171  * Rt: target register
2172  */
2173 static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn)
2174 {
2175     int rt = extract32(insn, 0, 5);
2176     int rn = extract32(insn, 5, 5);
2177     unsigned int imm12 = extract32(insn, 10, 12);
2178     bool is_vector = extract32(insn, 26, 1);
2179     int size = extract32(insn, 30, 2);
2180     int opc = extract32(insn, 22, 2);
2181     unsigned int offset;
2182
2183     TCGv_i64 tcg_addr;
2184
2185     bool is_store;
2186     bool is_signed = false;
2187     bool is_extended = false;
2188
2189     if (is_vector) {
2190         size |= (opc & 2) << 1;
2191         if (size > 4) {
2192             unallocated_encoding(s);
2193             return;
2194         }
2195         is_store = !extract32(opc, 0, 1);
2196         if (!fp_access_check(s)) {
2197             return;
2198         }
2199     } else {
2200         if (size == 3 && opc == 2) {
2201             /* PRFM - prefetch */
2202             return;
2203         }
2204         if (opc == 3 && size > 1) {
2205             unallocated_encoding(s);
2206             return;
2207         }
2208         is_store = (opc == 0);
2209         is_signed = extract32(opc, 1, 1);
2210         is_extended = (size < 3) && extract32(opc, 0, 1);
2211     }
2212
2213     if (rn == 31) {
2214         gen_check_sp_alignment(s);
2215     }
2216     tcg_addr = read_cpu_reg_sp(s, rn, 1);
2217     offset = imm12 << size;
2218     tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
2219
2220     if (is_vector) {
2221         if (is_store) {
2222             do_fp_st(s, rt, tcg_addr, size);
2223         } else {
2224             do_fp_ld(s, rt, tcg_addr, size);
2225         }
2226     } else {
2227         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2228         if (is_store) {
2229             do_gpr_st(s, tcg_rt, tcg_addr, size);
2230         } else {
2231             do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended);
2232         }
2233     }
2234 }
2235
2236 /* Load/store register (all forms) */
2237 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
2238 {
2239     switch (extract32(insn, 24, 2)) {
2240     case 0:
2241         if (extract32(insn, 21, 1) == 1 && extract32(insn, 10, 2) == 2) {
2242             disas_ldst_reg_roffset(s, insn);
2243         } else {
2244             /* Load/store register (unscaled immediate)
2245              * Load/store immediate pre/post-indexed
2246              * Load/store register unprivileged
2247              */
2248             disas_ldst_reg_imm9(s, insn);
2249         }
2250         break;
2251     case 1:
2252         disas_ldst_reg_unsigned_imm(s, insn);
2253         break;
2254     default:
2255         unallocated_encoding(s);
2256         break;
2257     }
2258 }
2259
2260 /* C3.3.1 AdvSIMD load/store multiple structures
2261  *
2262  *  31  30  29           23 22  21         16 15    12 11  10 9    5 4    0
2263  * +---+---+---------------+---+-------------+--------+------+------+------+
2264  * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size |  Rn  |  Rt  |
2265  * +---+---+---------------+---+-------------+--------+------+------+------+
2266  *
2267  * C3.3.2 AdvSIMD load/store multiple structures (post-indexed)
2268  *
2269  *  31  30  29           23 22  21  20     16 15    12 11  10 9    5 4    0
2270  * +---+---+---------------+---+---+---------+--------+------+------+------+
2271  * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 |   Rm    | opcode | size |  Rn  |  Rt  |
2272  * +---+---+---------------+---+---+---------+--------+------+------+------+
2273  *
2274  * Rt: first (or only) SIMD&FP register to be transferred
2275  * Rn: base address or SP
2276  * Rm (post-index only): post-index register (when !31) or size dependent #imm
2277  */
2278 static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
2279 {
2280     int rt = extract32(insn, 0, 5);
2281     int rn = extract32(insn, 5, 5);
2282     int size = extract32(insn, 10, 2);
2283     int opcode = extract32(insn, 12, 4);
2284     bool is_store = !extract32(insn, 22, 1);
2285     bool is_postidx = extract32(insn, 23, 1);
2286     bool is_q = extract32(insn, 30, 1);
2287     TCGv_i64 tcg_addr, tcg_rn;
2288
2289     int ebytes = 1 << size;
2290     int elements = (is_q ? 128 : 64) / (8 << size);
2291     int rpt;    /* num iterations */
2292     int selem;  /* structure elements */
2293     int r;
2294
2295     if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
2296         unallocated_encoding(s);
2297         return;
2298     }
2299
2300     /* From the shared decode logic */
2301     switch (opcode) {
2302     case 0x0:
2303         rpt = 1;
2304         selem = 4;
2305         break;
2306     case 0x2:
2307         rpt = 4;
2308         selem = 1;
2309         break;
2310     case 0x4:
2311         rpt = 1;
2312         selem = 3;
2313         break;
2314     case 0x6:
2315         rpt = 3;
2316         selem = 1;
2317         break;
2318     case 0x7:
2319         rpt = 1;
2320         selem = 1;
2321         break;
2322     case 0x8:
2323         rpt = 1;
2324         selem = 2;
2325         break;
2326     case 0xa:
2327         rpt = 2;
2328         selem = 1;
2329         break;
2330     default:
2331         unallocated_encoding(s);
2332         return;
2333     }
2334
2335     if (size == 3 && !is_q && selem != 1) {
2336         /* reserved */
2337         unallocated_encoding(s);
2338         return;
2339     }
2340
2341     if (!fp_access_check(s)) {
2342         return;
2343     }
2344
2345     if (rn == 31) {
2346         gen_check_sp_alignment(s);
2347     }
2348
2349     tcg_rn = cpu_reg_sp(s, rn);
2350     tcg_addr = tcg_temp_new_i64();
2351     tcg_gen_mov_i64(tcg_addr, tcg_rn);
2352
2353     for (r = 0; r < rpt; r++) {
2354         int e;
2355         for (e = 0; e < elements; e++) {
2356             int tt = (rt + r) % 32;
2357             int xs;
2358             for (xs = 0; xs < selem; xs++) {
2359                 if (is_store) {
2360                     do_vec_st(s, tt, e, tcg_addr, size);
2361                 } else {
2362                     do_vec_ld(s, tt, e, tcg_addr, size);
2363
2364                     /* For non-quad operations, setting a slice of the low
2365                      * 64 bits of the register clears the high 64 bits (in
2366                      * the ARM ARM pseudocode this is implicit in the fact
2367                      * that 'rval' is a 64 bit wide variable). We optimize
2368                      * by noticing that we only need to do this the first
2369                      * time we touch a register.
2370                      */
2371                     if (!is_q && e == 0 && (r == 0 || xs == selem - 1)) {
2372                         clear_vec_high(s, tt);
2373                     }
2374                 }
2375                 tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
2376                 tt = (tt + 1) % 32;
2377             }
2378         }
2379     }
2380
2381     if (is_postidx) {
2382         int rm = extract32(insn, 16, 5);
2383         if (rm == 31) {
2384             tcg_gen_mov_i64(tcg_rn, tcg_addr);
2385         } else {
2386             tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
2387         }
2388     }
2389     tcg_temp_free_i64(tcg_addr);
2390 }
2391
2392 /* C3.3.3 AdvSIMD load/store single structure
2393  *
2394  *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
2395  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2396  * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size |  Rn  |  Rt  |
2397  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2398  *
2399  * C3.3.4 AdvSIMD load/store single structure (post-indexed)
2400  *
2401  *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
2402  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2403  * | 0 | Q | 0 0 1 1 0 1 1 | L R |     Rm    | opc | S | size |  Rn  |  Rt  |
2404  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
2405  *
2406  * Rt: first (or only) SIMD&FP register to be transferred
2407  * Rn: base address or SP
2408  * Rm (post-index only): post-index register (when !31) or size dependent #imm
2409  * index = encoded in Q:S:size dependent on size
2410  *
2411  * lane_size = encoded in R, opc
2412  * transfer width = encoded in opc, S, size
2413  */
2414 static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
2415 {
2416     int rt = extract32(insn, 0, 5);
2417     int rn = extract32(insn, 5, 5);
2418     int size = extract32(insn, 10, 2);
2419     int S = extract32(insn, 12, 1);
2420     int opc = extract32(insn, 13, 3);
2421     int R = extract32(insn, 21, 1);
2422     int is_load = extract32(insn, 22, 1);
2423     int is_postidx = extract32(insn, 23, 1);
2424     int is_q = extract32(insn, 30, 1);
2425
2426     int scale = extract32(opc, 1, 2);
2427     int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
2428     bool replicate = false;
2429     int index = is_q << 3 | S << 2 | size;
2430     int ebytes, xs;
2431     TCGv_i64 tcg_addr, tcg_rn;
2432
2433     switch (scale) {
2434     case 3:
2435         if (!is_load || S) {
2436             unallocated_encoding(s);
2437             return;
2438         }
2439         scale = size;
2440         replicate = true;
2441         break;
2442     case 0:
2443         break;
2444     case 1:
2445         if (extract32(size, 0, 1)) {
2446             unallocated_encoding(s);
2447             return;
2448         }
2449         index >>= 1;
2450         break;
2451     case 2:
2452         if (extract32(size, 1, 1)) {
2453             unallocated_encoding(s);
2454             return;
2455         }
2456         if (!extract32(size, 0, 1)) {
2457             index >>= 2;
2458         } else {
2459             if (S) {
2460                 unallocated_encoding(s);
2461                 return;
2462             }
2463             index >>= 3;
2464             scale = 3;
2465         }
2466         break;
2467     default:
2468         g_assert_not_reached();
2469     }
2470
2471     if (!fp_access_check(s)) {
2472         return;
2473     }
2474
2475     ebytes = 1 << scale;
2476
2477     if (rn == 31) {
2478         gen_check_sp_alignment(s);
2479     }
2480
2481     tcg_rn = cpu_reg_sp(s, rn);
2482     tcg_addr = tcg_temp_new_i64();
2483     tcg_gen_mov_i64(tcg_addr, tcg_rn);
2484
2485     for (xs = 0; xs < selem; xs++) {
2486         if (replicate) {
2487             /* Load and replicate to all elements */
2488             uint64_t mulconst;
2489             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
2490
2491             tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
2492                                 get_mem_index(s), MO_TE + scale);
2493             switch (scale) {
2494             case 0:
2495                 mulconst = 0x0101010101010101ULL;
2496                 break;
2497             case 1:
2498                 mulconst = 0x0001000100010001ULL;
2499                 break;
2500             case 2:
2501                 mulconst = 0x0000000100000001ULL;
2502                 break;
2503             case 3:
2504                 mulconst = 0;
2505                 break;
2506             default:
2507                 g_assert_not_reached();
2508             }
2509             if (mulconst) {
2510                 tcg_gen_muli_i64(tcg_tmp, tcg_tmp, mulconst);
2511             }
2512             write_vec_element(s, tcg_tmp, rt, 0, MO_64);
2513             if (is_q) {
2514                 write_vec_element(s, tcg_tmp, rt, 1, MO_64);
2515             } else {
2516                 clear_vec_high(s, rt);
2517             }
2518             tcg_temp_free_i64(tcg_tmp);
2519         } else {
2520             /* Load/store one element per register */
2521             if (is_load) {
2522                 do_vec_ld(s, rt, index, tcg_addr, MO_TE + scale);
2523             } else {
2524                 do_vec_st(s, rt, index, tcg_addr, MO_TE + scale);
2525             }
2526         }
2527         tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
2528         rt = (rt + 1) % 32;
2529     }
2530
2531     if (is_postidx) {
2532         int rm = extract32(insn, 16, 5);
2533         if (rm == 31) {
2534             tcg_gen_mov_i64(tcg_rn, tcg_addr);
2535         } else {
2536             tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
2537         }
2538     }
2539     tcg_temp_free_i64(tcg_addr);
2540 }
2541
2542 /* C3.3 Loads and stores */
2543 static void disas_ldst(DisasContext *s, uint32_t insn)
2544 {
2545     switch (extract32(insn, 24, 6)) {
2546     case 0x08: /* Load/store exclusive */
2547         disas_ldst_excl(s, insn);
2548         break;
2549     case 0x18: case 0x1c: /* Load register (literal) */
2550         disas_ld_lit(s, insn);
2551         break;
2552     case 0x28: case 0x29:
2553     case 0x2c: case 0x2d: /* Load/store pair (all forms) */
2554         disas_ldst_pair(s, insn);
2555         break;
2556     case 0x38: case 0x39:
2557     case 0x3c: case 0x3d: /* Load/store register (all forms) */
2558         disas_ldst_reg(s, insn);
2559         break;
2560     case 0x0c: /* AdvSIMD load/store multiple structures */
2561         disas_ldst_multiple_struct(s, insn);
2562         break;
2563     case 0x0d: /* AdvSIMD load/store single structure */
2564         disas_ldst_single_struct(s, insn);
2565         break;
2566     default:
2567         unallocated_encoding(s);
2568         break;
2569     }
2570 }
2571
2572 /* C3.4.6 PC-rel. addressing
2573  *   31  30   29 28       24 23                5 4    0
2574  * +----+-------+-----------+-------------------+------+
2575  * | op | immlo | 1 0 0 0 0 |       immhi       |  Rd  |
2576  * +----+-------+-----------+-------------------+------+
2577  */
2578 static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
2579 {
2580     unsigned int page, rd;
2581     uint64_t base;
2582     int64_t offset;
2583
2584     page = extract32(insn, 31, 1);
2585     /* SignExtend(immhi:immlo) -> offset */
2586     offset = ((int64_t)sextract32(insn, 5, 19) << 2) | extract32(insn, 29, 2);
2587     rd = extract32(insn, 0, 5);
2588     base = s->pc - 4;
2589
2590     if (page) {
2591         /* ADRP (page based) */
2592         base &= ~0xfff;
2593         offset <<= 12;
2594     }
2595
2596     tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
2597 }
2598
2599 /*
2600  * C3.4.1 Add/subtract (immediate)
2601  *
2602  *  31 30 29 28       24 23 22 21         10 9   5 4   0
2603  * +--+--+--+-----------+-----+-------------+-----+-----+
2604  * |sf|op| S| 1 0 0 0 1 |shift|    imm12    |  Rn | Rd  |
2605  * +--+--+--+-----------+-----+-------------+-----+-----+
2606  *
2607  *    sf: 0 -> 32bit, 1 -> 64bit
2608  *    op: 0 -> add  , 1 -> sub
2609  *     S: 1 -> set flags
2610  * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
2611  */
2612 static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
2613 {
2614     int rd = extract32(insn, 0, 5);
2615     int rn = extract32(insn, 5, 5);
2616     uint64_t imm = extract32(insn, 10, 12);
2617     int shift = extract32(insn, 22, 2);
2618     bool setflags = extract32(insn, 29, 1);
2619     bool sub_op = extract32(insn, 30, 1);
2620     bool is_64bit = extract32(insn, 31, 1);
2621
2622     TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
2623     TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
2624     TCGv_i64 tcg_result;
2625
2626     switch (shift) {
2627     case 0x0:
2628         break;
2629     case 0x1:
2630         imm <<= 12;
2631         break;
2632     default:
2633         unallocated_encoding(s);
2634         return;
2635     }
2636
2637     tcg_result = tcg_temp_new_i64();
2638     if (!setflags) {
2639         if (sub_op) {
2640             tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
2641         } else {
2642             tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
2643         }
2644     } else {
2645         TCGv_i64 tcg_imm = tcg_const_i64(imm);
2646         if (sub_op) {
2647             gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
2648         } else {
2649             gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
2650         }
2651         tcg_temp_free_i64(tcg_imm);
2652     }
2653
2654     if (is_64bit) {
2655         tcg_gen_mov_i64(tcg_rd, tcg_result);
2656     } else {
2657         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
2658     }
2659
2660     tcg_temp_free_i64(tcg_result);
2661 }
2662
2663 /* The input should be a value in the bottom e bits (with higher
2664  * bits zero); returns that value replicated into every element
2665  * of size e in a 64 bit integer.
2666  */
2667 static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
2668 {
2669     assert(e != 0);
2670     while (e < 64) {
2671         mask |= mask << e;
2672         e *= 2;
2673     }
2674     return mask;
2675 }
2676
2677 /* Return a value with the bottom len bits set (where 0 < len <= 64) */
2678 static inline uint64_t bitmask64(unsigned int length)
2679 {
2680     assert(length > 0 && length <= 64);
2681     return ~0ULL >> (64 - length);
2682 }
2683
2684 /* Simplified variant of pseudocode DecodeBitMasks() for the case where we
2685  * only require the wmask. Returns false if the imms/immr/immn are a reserved
2686  * value (ie should cause a guest UNDEF exception), and true if they are
2687  * valid, in which case the decoded bit pattern is written to result.
2688  */
2689 static bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
2690                                    unsigned int imms, unsigned int immr)
2691 {
2692     uint64_t mask;
2693     unsigned e, levels, s, r;
2694     int len;
2695
2696     assert(immn < 2 && imms < 64 && immr < 64);
2697
2698     /* The bit patterns we create here are 64 bit patterns which
2699      * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
2700      * 64 bits each. Each element contains the same value: a run
2701      * of between 1 and e-1 non-zero bits, rotated within the
2702      * element by between 0 and e-1 bits.
2703      *
2704      * The element size and run length are encoded into immn (1 bit)
2705      * and imms (6 bits) as follows:
2706      * 64 bit elements: immn = 1, imms = <length of run - 1>
2707      * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
2708      * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
2709      *  8 bit elements: immn = 0, imms = 110 : <length of run - 1>
2710      *  4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
2711      *  2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
2712      * Notice that immn = 0, imms = 11111x is the only combination
2713      * not covered by one of the above options; this is reserved.
2714      * Further, <length of run - 1> all-ones is a reserved pattern.
2715      *
2716      * In all cases the rotation is by immr % e (and immr is 6 bits).
2717      */
2718
2719     /* First determine the element size */
2720     len = 31 - clz32((immn << 6) | (~imms & 0x3f));
2721     if (len < 1) {
2722         /* This is the immn == 0, imms == 0x11111x case */
2723         return false;
2724     }
2725     e = 1 << len;
2726
2727     levels = e - 1;
2728     s = imms & levels;
2729     r = immr & levels;
2730
2731     if (s == levels) {
2732         /* <length of run - 1> mustn't be all-ones. */
2733         return false;
2734     }
2735
2736     /* Create the value of one element: s+1 set bits rotated
2737      * by r within the element (which is e bits wide)...
2738      */
2739     mask = bitmask64(s + 1);
2740     mask = (mask >> r) | (mask << (e - r));
2741     /* ...then replicate the element over the whole 64 bit value */
2742     mask = bitfield_replicate(mask, e);
2743     *result = mask;
2744     return true;
2745 }
2746
2747 /* C3.4.4 Logical (immediate)
2748  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
2749  * +----+-----+-------------+---+------+------+------+------+
2750  * | sf | opc | 1 0 0 1 0 0 | N | immr | imms |  Rn  |  Rd  |
2751  * +----+-----+-------------+---+------+------+------+------+
2752  */
2753 static void disas_logic_imm(DisasContext *s, uint32_t insn)
2754 {
2755     unsigned int sf, opc, is_n, immr, imms, rn, rd;
2756     TCGv_i64 tcg_rd, tcg_rn;
2757     uint64_t wmask;
2758     bool is_and = false;
2759
2760     sf = extract32(insn, 31, 1);
2761     opc = extract32(insn, 29, 2);
2762     is_n = extract32(insn, 22, 1);
2763     immr = extract32(insn, 16, 6);
2764     imms = extract32(insn, 10, 6);
2765     rn = extract32(insn, 5, 5);
2766     rd = extract32(insn, 0, 5);
2767
2768     if (!sf && is_n) {
2769         unallocated_encoding(s);
2770         return;
2771     }
2772
2773     if (opc == 0x3) { /* ANDS */
2774         tcg_rd = cpu_reg(s, rd);
2775     } else {
2776         tcg_rd = cpu_reg_sp(s, rd);
2777     }
2778     tcg_rn = cpu_reg(s, rn);
2779
2780     if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
2781         /* some immediate field values are reserved */
2782         unallocated_encoding(s);
2783         return;
2784     }
2785
2786     if (!sf) {
2787         wmask &= 0xffffffff;
2788     }
2789
2790     switch (opc) {
2791     case 0x3: /* ANDS */
2792     case 0x0: /* AND */
2793         tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
2794         is_and = true;
2795         break;
2796     case 0x1: /* ORR */
2797         tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
2798         break;
2799     case 0x2: /* EOR */
2800         tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
2801         break;
2802     default:
2803         assert(FALSE); /* must handle all above */
2804         break;
2805     }
2806
2807     if (!sf && !is_and) {
2808         /* zero extend final result; we know we can skip this for AND
2809          * since the immediate had the high 32 bits clear.
2810          */
2811         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2812     }
2813
2814     if (opc == 3) { /* ANDS */
2815         gen_logic_CC(sf, tcg_rd);
2816     }
2817 }
2818
2819 /*
2820  * C3.4.5 Move wide (immediate)
2821  *
2822  *  31 30 29 28         23 22 21 20             5 4    0
2823  * +--+-----+-------------+-----+----------------+------+
2824  * |sf| opc | 1 0 0 1 0 1 |  hw |  imm16         |  Rd  |
2825  * +--+-----+-------------+-----+----------------+------+
2826  *
2827  * sf: 0 -> 32 bit, 1 -> 64 bit
2828  * opc: 00 -> N, 10 -> Z, 11 -> K
2829  * hw: shift/16 (0,16, and sf only 32, 48)
2830  */
2831 static void disas_movw_imm(DisasContext *s, uint32_t insn)
2832 {
2833     int rd = extract32(insn, 0, 5);
2834     uint64_t imm = extract32(insn, 5, 16);
2835     int sf = extract32(insn, 31, 1);
2836     int opc = extract32(insn, 29, 2);
2837     int pos = extract32(insn, 21, 2) << 4;
2838     TCGv_i64 tcg_rd = cpu_reg(s, rd);
2839     TCGv_i64 tcg_imm;
2840
2841     if (!sf && (pos >= 32)) {
2842         unallocated_encoding(s);
2843         return;
2844     }
2845
2846     switch (opc) {
2847     case 0: /* MOVN */
2848     case 2: /* MOVZ */
2849         imm <<= pos;
2850         if (opc == 0) {
2851             imm = ~imm;
2852         }
2853         if (!sf) {
2854             imm &= 0xffffffffu;
2855         }
2856         tcg_gen_movi_i64(tcg_rd, imm);
2857         break;
2858     case 3: /* MOVK */
2859         tcg_imm = tcg_const_i64(imm);
2860         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_imm, pos, 16);
2861         tcg_temp_free_i64(tcg_imm);
2862         if (!sf) {
2863             tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2864         }
2865         break;
2866     default:
2867         unallocated_encoding(s);
2868         break;
2869     }
2870 }
2871
2872 /* C3.4.2 Bitfield
2873  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
2874  * +----+-----+-------------+---+------+------+------+------+
2875  * | sf | opc | 1 0 0 1 1 0 | N | immr | imms |  Rn  |  Rd  |
2876  * +----+-----+-------------+---+------+------+------+------+
2877  */
2878 static void disas_bitfield(DisasContext *s, uint32_t insn)
2879 {
2880     unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
2881     TCGv_i64 tcg_rd, tcg_tmp;
2882
2883     sf = extract32(insn, 31, 1);
2884     opc = extract32(insn, 29, 2);
2885     n = extract32(insn, 22, 1);
2886     ri = extract32(insn, 16, 6);
2887     si = extract32(insn, 10, 6);
2888     rn = extract32(insn, 5, 5);
2889     rd = extract32(insn, 0, 5);
2890     bitsize = sf ? 64 : 32;
2891
2892     if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
2893         unallocated_encoding(s);
2894         return;
2895     }
2896
2897     tcg_rd = cpu_reg(s, rd);
2898     tcg_tmp = read_cpu_reg(s, rn, sf);
2899
2900     /* OPTME: probably worth recognizing common cases of ext{8,16,32}{u,s} */
2901
2902     if (opc != 1) { /* SBFM or UBFM */
2903         tcg_gen_movi_i64(tcg_rd, 0);
2904     }
2905
2906     /* do the bit move operation */
2907     if (si >= ri) {
2908         /* Wd<s-r:0> = Wn<s:r> */
2909         tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
2910         pos = 0;
2911         len = (si - ri) + 1;
2912     } else {
2913         /* Wd<32+s-r,32-r> = Wn<s:0> */
2914         pos = bitsize - ri;
2915         len = si + 1;
2916     }
2917
2918     tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
2919
2920     if (opc == 0) { /* SBFM - sign extend the destination field */
2921         tcg_gen_shli_i64(tcg_rd, tcg_rd, 64 - (pos + len));
2922         tcg_gen_sari_i64(tcg_rd, tcg_rd, 64 - (pos + len));
2923     }
2924
2925     if (!sf) { /* zero extend final result */
2926         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2927     }
2928 }
2929
2930 /* C3.4.3 Extract
2931  *   31  30  29 28         23 22   21  20  16 15    10 9    5 4    0
2932  * +----+------+-------------+---+----+------+--------+------+------+
2933  * | sf | op21 | 1 0 0 1 1 1 | N | o0 |  Rm  |  imms  |  Rn  |  Rd  |
2934  * +----+------+-------------+---+----+------+--------+------+------+
2935  */
2936 static void disas_extract(DisasContext *s, uint32_t insn)
2937 {
2938     unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
2939
2940     sf = extract32(insn, 31, 1);
2941     n = extract32(insn, 22, 1);
2942     rm = extract32(insn, 16, 5);
2943     imm = extract32(insn, 10, 6);
2944     rn = extract32(insn, 5, 5);
2945     rd = extract32(insn, 0, 5);
2946     op21 = extract32(insn, 29, 2);
2947     op0 = extract32(insn, 21, 1);
2948     bitsize = sf ? 64 : 32;
2949
2950     if (sf != n || op21 || op0 || imm >= bitsize) {
2951         unallocated_encoding(s);
2952     } else {
2953         TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
2954
2955         tcg_rd = cpu_reg(s, rd);
2956
2957         if (imm) {
2958             /* OPTME: we can special case rm==rn as a rotate */
2959             tcg_rm = read_cpu_reg(s, rm, sf);
2960             tcg_rn = read_cpu_reg(s, rn, sf);
2961             tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
2962             tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
2963             tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
2964             if (!sf) {
2965                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
2966             }
2967         } else {
2968             /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
2969              * so an extract from bit 0 is a special case.
2970              */
2971             if (sf) {
2972                 tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
2973             } else {
2974                 tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
2975             }
2976         }
2977
2978     }
2979 }
2980
2981 /* C3.4 Data processing - immediate */
2982 static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
2983 {
2984     switch (extract32(insn, 23, 6)) {
2985     case 0x20: case 0x21: /* PC-rel. addressing */
2986         disas_pc_rel_adr(s, insn);
2987         break;
2988     case 0x22: case 0x23: /* Add/subtract (immediate) */
2989         disas_add_sub_imm(s, insn);
2990         break;
2991     case 0x24: /* Logical (immediate) */
2992         disas_logic_imm(s, insn);
2993         break;
2994     case 0x25: /* Move wide (immediate) */
2995         disas_movw_imm(s, insn);
2996         break;
2997     case 0x26: /* Bitfield */
2998         disas_bitfield(s, insn);
2999         break;
3000     case 0x27: /* Extract */
3001         disas_extract(s, insn);
3002         break;
3003     default:
3004         unallocated_encoding(s);
3005         break;
3006     }
3007 }
3008
3009 /* Shift a TCGv src by TCGv shift_amount, put result in dst.
3010  * Note that it is the caller's responsibility to ensure that the
3011  * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
3012  * mandated semantics for out of range shifts.
3013  */
3014 static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
3015                       enum a64_shift_type shift_type, TCGv_i64 shift_amount)
3016 {
3017     switch (shift_type) {
3018     case A64_SHIFT_TYPE_LSL:
3019         tcg_gen_shl_i64(dst, src, shift_amount);
3020         break;
3021     case A64_SHIFT_TYPE_LSR:
3022         tcg_gen_shr_i64(dst, src, shift_amount);
3023         break;
3024     case A64_SHIFT_TYPE_ASR:
3025         if (!sf) {
3026             tcg_gen_ext32s_i64(dst, src);
3027         }
3028         tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
3029         break;
3030     case A64_SHIFT_TYPE_ROR:
3031         if (sf) {
3032             tcg_gen_rotr_i64(dst, src, shift_amount);
3033         } else {
3034             TCGv_i32 t0, t1;
3035             t0 = tcg_temp_new_i32();
3036             t1 = tcg_temp_new_i32();
3037             tcg_gen_trunc_i64_i32(t0, src);
3038             tcg_gen_trunc_i64_i32(t1, shift_amount);
3039             tcg_gen_rotr_i32(t0, t0, t1);
3040             tcg_gen_extu_i32_i64(dst, t0);
3041             tcg_temp_free_i32(t0);
3042             tcg_temp_free_i32(t1);
3043         }
3044         break;
3045     default:
3046         assert(FALSE); /* all shift types should be handled */
3047         break;
3048     }
3049
3050     if (!sf) { /* zero extend final result */
3051         tcg_gen_ext32u_i64(dst, dst);
3052     }
3053 }
3054
3055 /* Shift a TCGv src by immediate, put result in dst.
3056  * The shift amount must be in range (this should always be true as the
3057  * relevant instructions will UNDEF on bad shift immediates).
3058  */
3059 static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
3060                           enum a64_shift_type shift_type, unsigned int shift_i)
3061 {
3062     assert(shift_i < (sf ? 64 : 32));
3063
3064     if (shift_i == 0) {
3065         tcg_gen_mov_i64(dst, src);
3066     } else {
3067         TCGv_i64 shift_const;
3068
3069         shift_const = tcg_const_i64(shift_i);
3070         shift_reg(dst, src, sf, shift_type, shift_const);
3071         tcg_temp_free_i64(shift_const);
3072     }
3073 }
3074
3075 /* C3.5.10 Logical (shifted register)
3076  *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
3077  * +----+-----+-----------+-------+---+------+--------+------+------+
3078  * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
3079  * +----+-----+-----------+-------+---+------+--------+------+------+
3080  */
3081 static void disas_logic_reg(DisasContext *s, uint32_t insn)
3082 {
3083     TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
3084     unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
3085
3086     sf = extract32(insn, 31, 1);
3087     opc = extract32(insn, 29, 2);
3088     shift_type = extract32(insn, 22, 2);
3089     invert = extract32(insn, 21, 1);
3090     rm = extract32(insn, 16, 5);
3091     shift_amount = extract32(insn, 10, 6);
3092     rn = extract32(insn, 5, 5);
3093     rd = extract32(insn, 0, 5);
3094
3095     if (!sf && (shift_amount & (1 << 5))) {
3096         unallocated_encoding(s);
3097         return;
3098     }
3099
3100     tcg_rd = cpu_reg(s, rd);
3101
3102     if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
3103         /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
3104          * register-register MOV and MVN, so it is worth special casing.
3105          */
3106         tcg_rm = cpu_reg(s, rm);
3107         if (invert) {
3108             tcg_gen_not_i64(tcg_rd, tcg_rm);
3109             if (!sf) {
3110                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3111             }
3112         } else {
3113             if (sf) {
3114                 tcg_gen_mov_i64(tcg_rd, tcg_rm);
3115             } else {
3116                 tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
3117             }
3118         }
3119         return;
3120     }
3121
3122     tcg_rm = read_cpu_reg(s, rm, sf);
3123
3124     if (shift_amount) {
3125         shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
3126     }
3127
3128     tcg_rn = cpu_reg(s, rn);
3129
3130     switch (opc | (invert << 2)) {
3131     case 0: /* AND */
3132     case 3: /* ANDS */
3133         tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
3134         break;
3135     case 1: /* ORR */
3136         tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
3137         break;
3138     case 2: /* EOR */
3139         tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
3140         break;
3141     case 4: /* BIC */
3142     case 7: /* BICS */
3143         tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
3144         break;
3145     case 5: /* ORN */
3146         tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
3147         break;
3148     case 6: /* EON */
3149         tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
3150         break;
3151     default:
3152         assert(FALSE);
3153         break;
3154     }
3155
3156     if (!sf) {
3157         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3158     }
3159
3160     if (opc == 3) {
3161         gen_logic_CC(sf, tcg_rd);
3162     }
3163 }
3164
3165 /*
3166  * C3.5.1 Add/subtract (extended register)
3167  *
3168  *  31|30|29|28       24|23 22|21|20   16|15  13|12  10|9  5|4  0|
3169  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
3170  * |sf|op| S| 0 1 0 1 1 | opt | 1|  Rm   |option| imm3 | Rn | Rd |
3171  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
3172  *
3173  *  sf: 0 -> 32bit, 1 -> 64bit
3174  *  op: 0 -> add  , 1 -> sub
3175  *   S: 1 -> set flags
3176  * opt: 00
3177  * option: extension type (see DecodeRegExtend)
3178  * imm3: optional shift to Rm
3179  *
3180  * Rd = Rn + LSL(extend(Rm), amount)
3181  */
3182 static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
3183 {
3184     int rd = extract32(insn, 0, 5);
3185     int rn = extract32(insn, 5, 5);
3186     int imm3 = extract32(insn, 10, 3);
3187     int option = extract32(insn, 13, 3);
3188     int rm = extract32(insn, 16, 5);
3189     bool setflags = extract32(insn, 29, 1);
3190     bool sub_op = extract32(insn, 30, 1);
3191     bool sf = extract32(insn, 31, 1);
3192
3193     TCGv_i64 tcg_rm, tcg_rn; /* temps */
3194     TCGv_i64 tcg_rd;
3195     TCGv_i64 tcg_result;
3196
3197     if (imm3 > 4) {
3198         unallocated_encoding(s);
3199         return;
3200     }
3201
3202     /* non-flag setting ops may use SP */
3203     if (!setflags) {
3204         tcg_rd = cpu_reg_sp(s, rd);
3205     } else {
3206         tcg_rd = cpu_reg(s, rd);
3207     }
3208     tcg_rn = read_cpu_reg_sp(s, rn, sf);
3209
3210     tcg_rm = read_cpu_reg(s, rm, sf);
3211     ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
3212
3213     tcg_result = tcg_temp_new_i64();
3214
3215     if (!setflags) {
3216         if (sub_op) {
3217             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
3218         } else {
3219             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
3220         }
3221     } else {
3222         if (sub_op) {
3223             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
3224         } else {
3225             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
3226         }
3227     }
3228
3229     if (sf) {
3230         tcg_gen_mov_i64(tcg_rd, tcg_result);
3231     } else {
3232         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
3233     }
3234
3235     tcg_temp_free_i64(tcg_result);
3236 }
3237
3238 /*
3239  * C3.5.2 Add/subtract (shifted register)
3240  *
3241  *  31 30 29 28       24 23 22 21 20   16 15     10 9    5 4    0
3242  * +--+--+--+-----------+-----+--+-------+---------+------+------+
3243  * |sf|op| S| 0 1 0 1 1 |shift| 0|  Rm   |  imm6   |  Rn  |  Rd  |
3244  * +--+--+--+-----------+-----+--+-------+---------+------+------+
3245  *
3246  *    sf: 0 -> 32bit, 1 -> 64bit
3247  *    op: 0 -> add  , 1 -> sub
3248  *     S: 1 -> set flags
3249  * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
3250  *  imm6: Shift amount to apply to Rm before the add/sub
3251  */
3252 static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
3253 {
3254     int rd = extract32(insn, 0, 5);
3255     int rn = extract32(insn, 5, 5);
3256     int imm6 = extract32(insn, 10, 6);
3257     int rm = extract32(insn, 16, 5);
3258     int shift_type = extract32(insn, 22, 2);
3259     bool setflags = extract32(insn, 29, 1);
3260     bool sub_op = extract32(insn, 30, 1);
3261     bool sf = extract32(insn, 31, 1);
3262
3263     TCGv_i64 tcg_rd = cpu_reg(s, rd);
3264     TCGv_i64 tcg_rn, tcg_rm;
3265     TCGv_i64 tcg_result;
3266
3267     if ((shift_type == 3) || (!sf && (imm6 > 31))) {
3268         unallocated_encoding(s);
3269         return;
3270     }
3271
3272     tcg_rn = read_cpu_reg(s, rn, sf);
3273     tcg_rm = read_cpu_reg(s, rm, sf);
3274
3275     shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
3276
3277     tcg_result = tcg_temp_new_i64();
3278
3279     if (!setflags) {
3280         if (sub_op) {
3281             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
3282         } else {
3283             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
3284         }
3285     } else {
3286         if (sub_op) {
3287             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
3288         } else {
3289             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
3290         }
3291     }
3292
3293     if (sf) {
3294         tcg_gen_mov_i64(tcg_rd, tcg_result);
3295     } else {
3296         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
3297     }
3298
3299     tcg_temp_free_i64(tcg_result);
3300 }
3301
3302 /* C3.5.9 Data-processing (3 source)
3303
3304    31 30  29 28       24 23 21  20  16  15  14  10 9    5 4    0
3305   +--+------+-----------+------+------+----+------+------+------+
3306   |sf| op54 | 1 1 0 1 1 | op31 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
3307   +--+------+-----------+------+------+----+------+------+------+
3308
3309  */
3310 static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
3311 {
3312     int rd = extract32(insn, 0, 5);
3313     int rn = extract32(insn, 5, 5);
3314     int ra = extract32(insn, 10, 5);
3315     int rm = extract32(insn, 16, 5);
3316     int op_id = (extract32(insn, 29, 3) << 4) |
3317         (extract32(insn, 21, 3) << 1) |
3318         extract32(insn, 15, 1);
3319     bool sf = extract32(insn, 31, 1);
3320     bool is_sub = extract32(op_id, 0, 1);
3321     bool is_high = extract32(op_id, 2, 1);
3322     bool is_signed = false;
3323     TCGv_i64 tcg_op1;
3324     TCGv_i64 tcg_op2;
3325     TCGv_i64 tcg_tmp;
3326
3327     /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
3328     switch (op_id) {
3329     case 0x42: /* SMADDL */
3330     case 0x43: /* SMSUBL */
3331     case 0x44: /* SMULH */
3332         is_signed = true;
3333         break;
3334     case 0x0: /* MADD (32bit) */
3335     case 0x1: /* MSUB (32bit) */
3336     case 0x40: /* MADD (64bit) */
3337     case 0x41: /* MSUB (64bit) */
3338     case 0x4a: /* UMADDL */
3339     case 0x4b: /* UMSUBL */
3340     case 0x4c: /* UMULH */
3341         break;
3342     default:
3343         unallocated_encoding(s);
3344         return;
3345     }
3346
3347     if (is_high) {
3348         TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
3349         TCGv_i64 tcg_rd = cpu_reg(s, rd);
3350         TCGv_i64 tcg_rn = cpu_reg(s, rn);
3351         TCGv_i64 tcg_rm = cpu_reg(s, rm);
3352
3353         if (is_signed) {
3354             tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
3355         } else {
3356             tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
3357         }
3358
3359         tcg_temp_free_i64(low_bits);
3360         return;
3361     }
3362
3363     tcg_op1 = tcg_temp_new_i64();
3364     tcg_op2 = tcg_temp_new_i64();
3365     tcg_tmp = tcg_temp_new_i64();
3366
3367     if (op_id < 0x42) {
3368         tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
3369         tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
3370     } else {
3371         if (is_signed) {
3372             tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
3373             tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
3374         } else {
3375             tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
3376             tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
3377         }
3378     }
3379
3380     if (ra == 31 && !is_sub) {
3381         /* Special-case MADD with rA == XZR; it is the standard MUL alias */
3382         tcg_gen_mul_i64(cpu_reg(s, rd), tcg_op1, tcg_op2);
3383     } else {
3384         tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
3385         if (is_sub) {
3386             tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
3387         } else {
3388             tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
3389         }
3390     }
3391
3392     if (!sf) {
3393         tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
3394     }
3395
3396     tcg_temp_free_i64(tcg_op1);
3397     tcg_temp_free_i64(tcg_op2);
3398     tcg_temp_free_i64(tcg_tmp);
3399 }
3400
3401 /* C3.5.3 - Add/subtract (with carry)
3402  *  31 30 29 28 27 26 25 24 23 22 21  20  16  15   10  9    5 4   0
3403  * +--+--+--+------------------------+------+---------+------+-----+
3404  * |sf|op| S| 1  1  0  1  0  0  0  0 |  rm  | opcode2 |  Rn  |  Rd |
3405  * +--+--+--+------------------------+------+---------+------+-----+
3406  *                                            [000000]
3407  */
3408
3409 static void disas_adc_sbc(DisasContext *s, uint32_t insn)
3410 {
3411     unsigned int sf, op, setflags, rm, rn, rd;
3412     TCGv_i64 tcg_y, tcg_rn, tcg_rd;
3413
3414     if (extract32(insn, 10, 6) != 0) {
3415         unallocated_encoding(s);
3416         return;
3417     }
3418
3419     sf = extract32(insn, 31, 1);
3420     op = extract32(insn, 30, 1);
3421     setflags = extract32(insn, 29, 1);
3422     rm = extract32(insn, 16, 5);
3423     rn = extract32(insn, 5, 5);
3424     rd = extract32(insn, 0, 5);
3425
3426     tcg_rd = cpu_reg(s, rd);
3427     tcg_rn = cpu_reg(s, rn);
3428
3429     if (op) {
3430         tcg_y = new_tmp_a64(s);
3431         tcg_gen_not_i64(tcg_y, cpu_reg(s, rm));
3432     } else {
3433         tcg_y = cpu_reg(s, rm);
3434     }
3435
3436     if (setflags) {
3437         gen_adc_CC(sf, tcg_rd, tcg_rn, tcg_y);
3438     } else {
3439         gen_adc(sf, tcg_rd, tcg_rn, tcg_y);
3440     }
3441 }
3442
3443 /* C3.5.4 - C3.5.5 Conditional compare (immediate / register)
3444  *  31 30 29 28 27 26 25 24 23 22 21  20    16 15  12  11  10  9   5  4 3   0
3445  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3446  * |sf|op| S| 1  1  0  1  0  0  1  0 |imm5/rm | cond |i/r |o2|  Rn  |o3|nzcv |
3447  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
3448  *        [1]                             y                [0]       [0]
3449  */
3450 static void disas_cc(DisasContext *s, uint32_t insn)
3451 {
3452     unsigned int sf, op, y, cond, rn, nzcv, is_imm;
3453     int label_continue = -1;
3454     TCGv_i64 tcg_tmp, tcg_y, tcg_rn;
3455
3456     if (!extract32(insn, 29, 1)) {
3457         unallocated_encoding(s);
3458         return;
3459     }
3460     if (insn & (1 << 10 | 1 << 4)) {
3461         unallocated_encoding(s);
3462         return;
3463     }
3464     sf = extract32(insn, 31, 1);
3465     op = extract32(insn, 30, 1);
3466     is_imm = extract32(insn, 11, 1);
3467     y = extract32(insn, 16, 5); /* y = rm (reg) or imm5 (imm) */
3468     cond = extract32(insn, 12, 4);
3469     rn = extract32(insn, 5, 5);
3470     nzcv = extract32(insn, 0, 4);
3471
3472     if (cond < 0x0e) { /* not always */
3473         int label_match = gen_new_label();
3474         label_continue = gen_new_label();
3475         arm_gen_test_cc(cond, label_match);
3476         /* nomatch: */
3477         tcg_tmp = tcg_temp_new_i64();
3478         tcg_gen_movi_i64(tcg_tmp, nzcv << 28);
3479         gen_set_nzcv(tcg_tmp);
3480         tcg_temp_free_i64(tcg_tmp);
3481         tcg_gen_br(label_continue);
3482         gen_set_label(label_match);
3483     }
3484     /* match, or condition is always */
3485     if (is_imm) {
3486         tcg_y = new_tmp_a64(s);
3487         tcg_gen_movi_i64(tcg_y, y);
3488     } else {
3489         tcg_y = cpu_reg(s, y);
3490     }
3491     tcg_rn = cpu_reg(s, rn);
3492
3493     tcg_tmp = tcg_temp_new_i64();
3494     if (op) {
3495         gen_sub_CC(sf, tcg_tmp, tcg_rn, tcg_y);
3496     } else {
3497         gen_add_CC(sf, tcg_tmp, tcg_rn, tcg_y);
3498     }
3499     tcg_temp_free_i64(tcg_tmp);
3500
3501     if (cond < 0x0e) { /* continue */
3502         gen_set_label(label_continue);
3503     }
3504 }
3505
3506 /* C3.5.6 Conditional select
3507  *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
3508  * +----+----+---+-----------------+------+------+-----+------+------+
3509  * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
3510  * +----+----+---+-----------------+------+------+-----+------+------+
3511  */
3512 static void disas_cond_select(DisasContext *s, uint32_t insn)
3513 {
3514     unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
3515     TCGv_i64 tcg_rd, tcg_src;
3516
3517     if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
3518         /* S == 1 or op2<1> == 1 */
3519         unallocated_encoding(s);
3520         return;
3521     }
3522     sf = extract32(insn, 31, 1);
3523     else_inv = extract32(insn, 30, 1);
3524     rm = extract32(insn, 16, 5);
3525     cond = extract32(insn, 12, 4);
3526     else_inc = extract32(insn, 10, 1);
3527     rn = extract32(insn, 5, 5);
3528     rd = extract32(insn, 0, 5);
3529
3530     if (rd == 31) {
3531         /* silly no-op write; until we use movcond we must special-case
3532          * this to avoid a dead temporary across basic blocks.
3533          */
3534         return;
3535     }
3536
3537     tcg_rd = cpu_reg(s, rd);
3538
3539     if (cond >= 0x0e) { /* condition "always" */
3540         tcg_src = read_cpu_reg(s, rn, sf);
3541         tcg_gen_mov_i64(tcg_rd, tcg_src);
3542     } else {
3543         /* OPTME: we could use movcond here, at the cost of duplicating
3544          * a lot of the arm_gen_test_cc() logic.
3545          */
3546         int label_match = gen_new_label();
3547         int label_continue = gen_new_label();
3548
3549         arm_gen_test_cc(cond, label_match);
3550         /* nomatch: */
3551         tcg_src = cpu_reg(s, rm);
3552
3553         if (else_inv && else_inc) {
3554             tcg_gen_neg_i64(tcg_rd, tcg_src);
3555         } else if (else_inv) {
3556             tcg_gen_not_i64(tcg_rd, tcg_src);
3557         } else if (else_inc) {
3558             tcg_gen_addi_i64(tcg_rd, tcg_src, 1);
3559         } else {
3560             tcg_gen_mov_i64(tcg_rd, tcg_src);
3561         }
3562         if (!sf) {
3563             tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3564         }
3565         tcg_gen_br(label_continue);
3566         /* match: */
3567         gen_set_label(label_match);
3568         tcg_src = read_cpu_reg(s, rn, sf);
3569         tcg_gen_mov_i64(tcg_rd, tcg_src);
3570         /* continue: */
3571         gen_set_label(label_continue);
3572     }
3573 }
3574
3575 static void handle_clz(DisasContext *s, unsigned int sf,
3576                        unsigned int rn, unsigned int rd)
3577 {
3578     TCGv_i64 tcg_rd, tcg_rn;
3579     tcg_rd = cpu_reg(s, rd);
3580     tcg_rn = cpu_reg(s, rn);
3581
3582     if (sf) {
3583         gen_helper_clz64(tcg_rd, tcg_rn);
3584     } else {
3585         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3586         tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3587         gen_helper_clz(tcg_tmp32, tcg_tmp32);
3588         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3589         tcg_temp_free_i32(tcg_tmp32);
3590     }
3591 }
3592
3593 static void handle_cls(DisasContext *s, unsigned int sf,
3594                        unsigned int rn, unsigned int rd)
3595 {
3596     TCGv_i64 tcg_rd, tcg_rn;
3597     tcg_rd = cpu_reg(s, rd);
3598     tcg_rn = cpu_reg(s, rn);
3599
3600     if (sf) {
3601         gen_helper_cls64(tcg_rd, tcg_rn);
3602     } else {
3603         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3604         tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3605         gen_helper_cls32(tcg_tmp32, tcg_tmp32);
3606         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3607         tcg_temp_free_i32(tcg_tmp32);
3608     }
3609 }
3610
3611 static void handle_rbit(DisasContext *s, unsigned int sf,
3612                         unsigned int rn, unsigned int rd)
3613 {
3614     TCGv_i64 tcg_rd, tcg_rn;
3615     tcg_rd = cpu_reg(s, rd);
3616     tcg_rn = cpu_reg(s, rn);
3617
3618     if (sf) {
3619         gen_helper_rbit64(tcg_rd, tcg_rn);
3620     } else {
3621         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
3622         tcg_gen_trunc_i64_i32(tcg_tmp32, tcg_rn);
3623         gen_helper_rbit(tcg_tmp32, tcg_tmp32);
3624         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
3625         tcg_temp_free_i32(tcg_tmp32);
3626     }
3627 }
3628
3629 /* C5.6.149 REV with sf==1, opcode==3 ("REV64") */
3630 static void handle_rev64(DisasContext *s, unsigned int sf,
3631                          unsigned int rn, unsigned int rd)
3632 {
3633     if (!sf) {
3634         unallocated_encoding(s);
3635         return;
3636     }
3637     tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
3638 }
3639
3640 /* C5.6.149 REV with sf==0, opcode==2
3641  * C5.6.151 REV32 (sf==1, opcode==2)
3642  */
3643 static void handle_rev32(DisasContext *s, unsigned int sf,
3644                          unsigned int rn, unsigned int rd)
3645 {
3646     TCGv_i64 tcg_rd = cpu_reg(s, rd);
3647
3648     if (sf) {
3649         TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3650         TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3651
3652         /* bswap32_i64 requires zero high word */
3653         tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
3654         tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
3655         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
3656         tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
3657         tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
3658
3659         tcg_temp_free_i64(tcg_tmp);
3660     } else {
3661         tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
3662         tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
3663     }
3664 }
3665
3666 /* C5.6.150 REV16 (opcode==1) */
3667 static void handle_rev16(DisasContext *s, unsigned int sf,
3668                          unsigned int rn, unsigned int rd)
3669 {
3670     TCGv_i64 tcg_rd = cpu_reg(s, rd);
3671     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3672     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3673
3674     tcg_gen_andi_i64(tcg_tmp, tcg_rn, 0xffff);
3675     tcg_gen_bswap16_i64(tcg_rd, tcg_tmp);
3676
3677     tcg_gen_shri_i64(tcg_tmp, tcg_rn, 16);
3678     tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
3679     tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3680     tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 16, 16);
3681
3682     if (sf) {
3683         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
3684         tcg_gen_andi_i64(tcg_tmp, tcg_tmp, 0xffff);
3685         tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3686         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 32, 16);
3687
3688         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 48);
3689         tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
3690         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, 48, 16);
3691     }
3692
3693     tcg_temp_free_i64(tcg_tmp);
3694 }
3695
3696 /* C3.5.7 Data-processing (1 source)
3697  *   31  30  29  28             21 20     16 15    10 9    5 4    0
3698  * +----+---+---+-----------------+---------+--------+------+------+
3699  * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
3700  * +----+---+---+-----------------+---------+--------+------+------+
3701  */
3702 static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
3703 {
3704     unsigned int sf, opcode, rn, rd;
3705
3706     if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
3707         unallocated_encoding(s);
3708         return;
3709     }
3710
3711     sf = extract32(insn, 31, 1);
3712     opcode = extract32(insn, 10, 6);
3713     rn = extract32(insn, 5, 5);
3714     rd = extract32(insn, 0, 5);
3715
3716     switch (opcode) {
3717     case 0: /* RBIT */
3718         handle_rbit(s, sf, rn, rd);
3719         break;
3720     case 1: /* REV16 */
3721         handle_rev16(s, sf, rn, rd);
3722         break;
3723     case 2: /* REV32 */
3724         handle_rev32(s, sf, rn, rd);
3725         break;
3726     case 3: /* REV64 */
3727         handle_rev64(s, sf, rn, rd);
3728         break;
3729     case 4: /* CLZ */
3730         handle_clz(s, sf, rn, rd);
3731         break;
3732     case 5: /* CLS */
3733         handle_cls(s, sf, rn, rd);
3734         break;
3735     }
3736 }
3737
3738 static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
3739                        unsigned int rm, unsigned int rn, unsigned int rd)
3740 {
3741     TCGv_i64 tcg_n, tcg_m, tcg_rd;
3742     tcg_rd = cpu_reg(s, rd);
3743
3744     if (!sf && is_signed) {
3745         tcg_n = new_tmp_a64(s);
3746         tcg_m = new_tmp_a64(s);
3747         tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
3748         tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
3749     } else {
3750         tcg_n = read_cpu_reg(s, rn, sf);
3751         tcg_m = read_cpu_reg(s, rm, sf);
3752     }
3753
3754     if (is_signed) {
3755         gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
3756     } else {
3757         gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
3758     }
3759
3760     if (!sf) { /* zero extend final result */
3761         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3762     }
3763 }
3764
3765 /* C5.6.115 LSLV, C5.6.118 LSRV, C5.6.17 ASRV, C5.6.154 RORV */
3766 static void handle_shift_reg(DisasContext *s,
3767                              enum a64_shift_type shift_type, unsigned int sf,
3768                              unsigned int rm, unsigned int rn, unsigned int rd)
3769 {
3770     TCGv_i64 tcg_shift = tcg_temp_new_i64();
3771     TCGv_i64 tcg_rd = cpu_reg(s, rd);
3772     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
3773
3774     tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
3775     shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
3776     tcg_temp_free_i64(tcg_shift);
3777 }
3778
3779 /* C3.5.8 Data-processing (2 source)
3780  *   31   30  29 28             21 20  16 15    10 9    5 4    0
3781  * +----+---+---+-----------------+------+--------+------+------+
3782  * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
3783  * +----+---+---+-----------------+------+--------+------+------+
3784  */
3785 static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
3786 {
3787     unsigned int sf, rm, opcode, rn, rd;
3788     sf = extract32(insn, 31, 1);
3789     rm = extract32(insn, 16, 5);
3790     opcode = extract32(insn, 10, 6);
3791     rn = extract32(insn, 5, 5);
3792     rd = extract32(insn, 0, 5);
3793
3794     if (extract32(insn, 29, 1)) {
3795         unallocated_encoding(s);
3796         return;
3797     }
3798
3799     switch (opcode) {
3800     case 2: /* UDIV */
3801         handle_div(s, false, sf, rm, rn, rd);
3802         break;
3803     case 3: /* SDIV */
3804         handle_div(s, true, sf, rm, rn, rd);
3805         break;
3806     case 8: /* LSLV */
3807         handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
3808         break;
3809     case 9: /* LSRV */
3810         handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
3811         break;
3812     case 10: /* ASRV */
3813         handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
3814         break;
3815     case 11: /* RORV */
3816         handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
3817         break;
3818     case 16:
3819     case 17:
3820     case 18:
3821     case 19:
3822     case 20:
3823     case 21:
3824     case 22:
3825     case 23: /* CRC32 */
3826         unsupported_encoding(s, insn);
3827         break;
3828     default:
3829         unallocated_encoding(s);
3830         break;
3831     }
3832 }
3833
3834 /* C3.5 Data processing - register */
3835 static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
3836 {
3837     switch (extract32(insn, 24, 5)) {
3838     case 0x0a: /* Logical (shifted register) */
3839         disas_logic_reg(s, insn);
3840         break;
3841     case 0x0b: /* Add/subtract */
3842         if (insn & (1 << 21)) { /* (extended register) */
3843             disas_add_sub_ext_reg(s, insn);
3844         } else {
3845             disas_add_sub_reg(s, insn);
3846         }
3847         break;
3848     case 0x1b: /* Data-processing (3 source) */
3849         disas_data_proc_3src(s, insn);
3850         break;
3851     case 0x1a:
3852         switch (extract32(insn, 21, 3)) {
3853         case 0x0: /* Add/subtract (with carry) */
3854             disas_adc_sbc(s, insn);
3855             break;
3856         case 0x2: /* Conditional compare */
3857             disas_cc(s, insn); /* both imm and reg forms */
3858             break;
3859         case 0x4: /* Conditional select */
3860             disas_cond_select(s, insn);
3861             break;
3862         case 0x6: /* Data-processing */
3863             if (insn & (1 << 30)) { /* (1 source) */
3864                 disas_data_proc_1src(s, insn);
3865             } else {            /* (2 source) */
3866                 disas_data_proc_2src(s, insn);
3867             }
3868             break;
3869         default:
3870             unallocated_encoding(s);
3871             break;
3872         }
3873         break;
3874     default:
3875         unallocated_encoding(s);
3876         break;
3877     }
3878 }
3879
3880 static void handle_fp_compare(DisasContext *s, bool is_double,
3881                               unsigned int rn, unsigned int rm,
3882                               bool cmp_with_zero, bool signal_all_nans)
3883 {
3884     TCGv_i64 tcg_flags = tcg_temp_new_i64();
3885     TCGv_ptr fpst = get_fpstatus_ptr();
3886
3887     if (is_double) {
3888         TCGv_i64 tcg_vn, tcg_vm;
3889
3890         tcg_vn = read_fp_dreg(s, rn);
3891         if (cmp_with_zero) {
3892             tcg_vm = tcg_const_i64(0);
3893         } else {
3894             tcg_vm = read_fp_dreg(s, rm);
3895         }
3896         if (signal_all_nans) {
3897             gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3898         } else {
3899             gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3900         }
3901         tcg_temp_free_i64(tcg_vn);
3902         tcg_temp_free_i64(tcg_vm);
3903     } else {
3904         TCGv_i32 tcg_vn, tcg_vm;
3905
3906         tcg_vn = read_fp_sreg(s, rn);
3907         if (cmp_with_zero) {
3908             tcg_vm = tcg_const_i32(0);
3909         } else {
3910             tcg_vm = read_fp_sreg(s, rm);
3911         }
3912         if (signal_all_nans) {
3913             gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3914         } else {
3915             gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
3916         }
3917         tcg_temp_free_i32(tcg_vn);
3918         tcg_temp_free_i32(tcg_vm);
3919     }
3920
3921     tcg_temp_free_ptr(fpst);
3922
3923     gen_set_nzcv(tcg_flags);
3924
3925     tcg_temp_free_i64(tcg_flags);
3926 }
3927
3928 /* C3.6.22 Floating point compare
3929  *   31  30  29 28       24 23  22  21 20  16 15 14 13  10    9    5 4     0
3930  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3931  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | op  | 1 0 0 0 |  Rn  |  op2  |
3932  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
3933  */
3934 static void disas_fp_compare(DisasContext *s, uint32_t insn)
3935 {
3936     unsigned int mos, type, rm, op, rn, opc, op2r;
3937
3938     mos = extract32(insn, 29, 3);
3939     type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3940     rm = extract32(insn, 16, 5);
3941     op = extract32(insn, 14, 2);
3942     rn = extract32(insn, 5, 5);
3943     opc = extract32(insn, 3, 2);
3944     op2r = extract32(insn, 0, 3);
3945
3946     if (mos || op || op2r || type > 1) {
3947         unallocated_encoding(s);
3948         return;
3949     }
3950
3951     if (!fp_access_check(s)) {
3952         return;
3953     }
3954
3955     handle_fp_compare(s, type, rn, rm, opc & 1, opc & 2);
3956 }
3957
3958 /* C3.6.23 Floating point conditional compare
3959  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5  4   3    0
3960  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3961  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 0 1 |  Rn  | op | nzcv |
3962  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
3963  */
3964 static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
3965 {
3966     unsigned int mos, type, rm, cond, rn, op, nzcv;
3967     TCGv_i64 tcg_flags;
3968     int label_continue = -1;
3969
3970     mos = extract32(insn, 29, 3);
3971     type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
3972     rm = extract32(insn, 16, 5);
3973     cond = extract32(insn, 12, 4);
3974     rn = extract32(insn, 5, 5);
3975     op = extract32(insn, 4, 1);
3976     nzcv = extract32(insn, 0, 4);
3977
3978     if (mos || type > 1) {
3979         unallocated_encoding(s);
3980         return;
3981     }
3982
3983     if (!fp_access_check(s)) {
3984         return;
3985     }
3986
3987     if (cond < 0x0e) { /* not always */
3988         int label_match = gen_new_label();
3989         label_continue = gen_new_label();
3990         arm_gen_test_cc(cond, label_match);
3991         /* nomatch: */
3992         tcg_flags = tcg_const_i64(nzcv << 28);
3993         gen_set_nzcv(tcg_flags);
3994         tcg_temp_free_i64(tcg_flags);
3995         tcg_gen_br(label_continue);
3996         gen_set_label(label_match);
3997     }
3998
3999     handle_fp_compare(s, type, rn, rm, false, op);
4000
4001     if (cond < 0x0e) {
4002         gen_set_label(label_continue);
4003     }
4004 }
4005
4006 /* copy src FP register to dst FP register; type specifies single or double */
4007 static void gen_mov_fp2fp(DisasContext *s, int type, int dst, int src)
4008 {
4009     if (type) {
4010         TCGv_i64 v = read_fp_dreg(s, src);
4011         write_fp_dreg(s, dst, v);
4012         tcg_temp_free_i64(v);
4013     } else {
4014         TCGv_i32 v = read_fp_sreg(s, src);
4015         write_fp_sreg(s, dst, v);
4016         tcg_temp_free_i32(v);
4017     }
4018 }
4019
4020 /* C3.6.24 Floating point conditional select
4021  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5 4    0
4022  * +---+---+---+-----------+------+---+------+------+-----+------+------+
4023  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 1 1 |  Rn  |  Rd  |
4024  * +---+---+---+-----------+------+---+------+------+-----+------+------+
4025  */
4026 static void disas_fp_csel(DisasContext *s, uint32_t insn)
4027 {
4028     unsigned int mos, type, rm, cond, rn, rd;
4029     int label_continue = -1;
4030
4031     mos = extract32(insn, 29, 3);
4032     type = extract32(insn, 22, 2); /* 0 = single, 1 = double */
4033     rm = extract32(insn, 16, 5);
4034     cond = extract32(insn, 12, 4);
4035     rn = extract32(insn, 5, 5);
4036     rd = extract32(insn, 0, 5);
4037
4038     if (mos || type > 1) {
4039         unallocated_encoding(s);
4040         return;
4041     }
4042
4043     if (!fp_access_check(s)) {
4044         return;
4045     }
4046
4047     if (cond < 0x0e) { /* not always */
4048         int label_match = gen_new_label();
4049         label_continue = gen_new_label();
4050         arm_gen_test_cc(cond, label_match);
4051         /* nomatch: */
4052         gen_mov_fp2fp(s, type, rd, rm);
4053         tcg_gen_br(label_continue);
4054         gen_set_label(label_match);
4055     }
4056
4057     gen_mov_fp2fp(s, type, rd, rn);
4058
4059     if (cond < 0x0e) { /* continue */
4060         gen_set_label(label_continue);
4061     }
4062 }
4063
4064 /* C3.6.25 Floating-point data-processing (1 source) - single precision */
4065 static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
4066 {
4067     TCGv_ptr fpst;
4068     TCGv_i32 tcg_op;
4069     TCGv_i32 tcg_res;
4070
4071     fpst = get_fpstatus_ptr();
4072     tcg_op = read_fp_sreg(s, rn);
4073     tcg_res = tcg_temp_new_i32();
4074
4075     switch (opcode) {
4076     case 0x0: /* FMOV */
4077         tcg_gen_mov_i32(tcg_res, tcg_op);
4078         break;
4079     case 0x1: /* FABS */
4080         gen_helper_vfp_abss(tcg_res, tcg_op);
4081         break;
4082     case 0x2: /* FNEG */
4083         gen_helper_vfp_negs(tcg_res, tcg_op);
4084         break;
4085     case 0x3: /* FSQRT */
4086         gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
4087         break;
4088     case 0x8: /* FRINTN */
4089     case 0x9: /* FRINTP */
4090     case 0xa: /* FRINTM */
4091     case 0xb: /* FRINTZ */
4092     case 0xc: /* FRINTA */
4093     {
4094         TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
4095
4096         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4097         gen_helper_rints(tcg_res, tcg_op, fpst);
4098
4099         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4100         tcg_temp_free_i32(tcg_rmode);
4101         break;
4102     }
4103     case 0xe: /* FRINTX */
4104         gen_helper_rints_exact(tcg_res, tcg_op, fpst);
4105         break;
4106     case 0xf: /* FRINTI */
4107         gen_helper_rints(tcg_res, tcg_op, fpst);
4108         break;
4109     default:
4110         abort();
4111     }
4112
4113     write_fp_sreg(s, rd, tcg_res);
4114
4115     tcg_temp_free_ptr(fpst);
4116     tcg_temp_free_i32(tcg_op);
4117     tcg_temp_free_i32(tcg_res);
4118 }
4119
4120 /* C3.6.25 Floating-point data-processing (1 source) - double precision */
4121 static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
4122 {
4123     TCGv_ptr fpst;
4124     TCGv_i64 tcg_op;
4125     TCGv_i64 tcg_res;
4126
4127     fpst = get_fpstatus_ptr();
4128     tcg_op = read_fp_dreg(s, rn);
4129     tcg_res = tcg_temp_new_i64();
4130
4131     switch (opcode) {
4132     case 0x0: /* FMOV */
4133         tcg_gen_mov_i64(tcg_res, tcg_op);
4134         break;
4135     case 0x1: /* FABS */
4136         gen_helper_vfp_absd(tcg_res, tcg_op);
4137         break;
4138     case 0x2: /* FNEG */
4139         gen_helper_vfp_negd(tcg_res, tcg_op);
4140         break;
4141     case 0x3: /* FSQRT */
4142         gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
4143         break;
4144     case 0x8: /* FRINTN */
4145     case 0x9: /* FRINTP */
4146     case 0xa: /* FRINTM */
4147     case 0xb: /* FRINTZ */
4148     case 0xc: /* FRINTA */
4149     {
4150         TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
4151
4152         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4153         gen_helper_rintd(tcg_res, tcg_op, fpst);
4154
4155         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4156         tcg_temp_free_i32(tcg_rmode);
4157         break;
4158     }
4159     case 0xe: /* FRINTX */
4160         gen_helper_rintd_exact(tcg_res, tcg_op, fpst);
4161         break;
4162     case 0xf: /* FRINTI */
4163         gen_helper_rintd(tcg_res, tcg_op, fpst);
4164         break;
4165     default:
4166         abort();
4167     }
4168
4169     write_fp_dreg(s, rd, tcg_res);
4170
4171     tcg_temp_free_ptr(fpst);
4172     tcg_temp_free_i64(tcg_op);
4173     tcg_temp_free_i64(tcg_res);
4174 }
4175
4176 static void handle_fp_fcvt(DisasContext *s, int opcode,
4177                            int rd, int rn, int dtype, int ntype)
4178 {
4179     switch (ntype) {
4180     case 0x0:
4181     {
4182         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
4183         if (dtype == 1) {
4184             /* Single to double */
4185             TCGv_i64 tcg_rd = tcg_temp_new_i64();
4186             gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
4187             write_fp_dreg(s, rd, tcg_rd);
4188             tcg_temp_free_i64(tcg_rd);
4189         } else {
4190             /* Single to half */
4191             TCGv_i32 tcg_rd = tcg_temp_new_i32();
4192             gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, cpu_env);
4193             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
4194             write_fp_sreg(s, rd, tcg_rd);
4195             tcg_temp_free_i32(tcg_rd);
4196         }
4197         tcg_temp_free_i32(tcg_rn);
4198         break;
4199     }
4200     case 0x1:
4201     {
4202         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
4203         TCGv_i32 tcg_rd = tcg_temp_new_i32();
4204         if (dtype == 0) {
4205             /* Double to single */
4206             gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
4207         } else {
4208             /* Double to half */
4209             gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, cpu_env);
4210             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
4211         }
4212         write_fp_sreg(s, rd, tcg_rd);
4213         tcg_temp_free_i32(tcg_rd);
4214         tcg_temp_free_i64(tcg_rn);
4215         break;
4216     }
4217     case 0x3:
4218     {
4219         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
4220         tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
4221         if (dtype == 0) {
4222             /* Half to single */
4223             TCGv_i32 tcg_rd = tcg_temp_new_i32();
4224             gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, cpu_env);
4225             write_fp_sreg(s, rd, tcg_rd);
4226             tcg_temp_free_i32(tcg_rd);
4227         } else {
4228             /* Half to double */
4229             TCGv_i64 tcg_rd = tcg_temp_new_i64();
4230             gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, cpu_env);
4231             write_fp_dreg(s, rd, tcg_rd);
4232             tcg_temp_free_i64(tcg_rd);
4233         }
4234         tcg_temp_free_i32(tcg_rn);
4235         break;
4236     }
4237     default:
4238         abort();
4239     }
4240 }
4241
4242 /* C3.6.25 Floating point data-processing (1 source)
4243  *   31  30  29 28       24 23  22  21 20    15 14       10 9    5 4    0
4244  * +---+---+---+-----------+------+---+--------+-----------+------+------+
4245  * | M | 0 | S | 1 1 1 1 0 | type | 1 | opcode | 1 0 0 0 0 |  Rn  |  Rd  |
4246  * +---+---+---+-----------+------+---+--------+-----------+------+------+
4247  */
4248 static void disas_fp_1src(DisasContext *s, uint32_t insn)
4249 {
4250     int type = extract32(insn, 22, 2);
4251     int opcode = extract32(insn, 15, 6);
4252     int rn = extract32(insn, 5, 5);
4253     int rd = extract32(insn, 0, 5);
4254
4255     switch (opcode) {
4256     case 0x4: case 0x5: case 0x7:
4257     {
4258         /* FCVT between half, single and double precision */
4259         int dtype = extract32(opcode, 0, 2);
4260         if (type == 2 || dtype == type) {
4261             unallocated_encoding(s);
4262             return;
4263         }
4264         if (!fp_access_check(s)) {
4265             return;
4266         }
4267
4268         handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
4269         break;
4270     }
4271     case 0x0 ... 0x3:
4272     case 0x8 ... 0xc:
4273     case 0xe ... 0xf:
4274         /* 32-to-32 and 64-to-64 ops */
4275         switch (type) {
4276         case 0:
4277             if (!fp_access_check(s)) {
4278                 return;
4279             }
4280
4281             handle_fp_1src_single(s, opcode, rd, rn);
4282             break;
4283         case 1:
4284             if (!fp_access_check(s)) {
4285                 return;
4286             }
4287
4288             handle_fp_1src_double(s, opcode, rd, rn);
4289             break;
4290         default:
4291             unallocated_encoding(s);
4292         }
4293         break;
4294     default:
4295         unallocated_encoding(s);
4296         break;
4297     }
4298 }
4299
4300 /* C3.6.26 Floating-point data-processing (2 source) - single precision */
4301 static void handle_fp_2src_single(DisasContext *s, int opcode,
4302                                   int rd, int rn, int rm)
4303 {
4304     TCGv_i32 tcg_op1;
4305     TCGv_i32 tcg_op2;
4306     TCGv_i32 tcg_res;
4307     TCGv_ptr fpst;
4308
4309     tcg_res = tcg_temp_new_i32();
4310     fpst = get_fpstatus_ptr();
4311     tcg_op1 = read_fp_sreg(s, rn);
4312     tcg_op2 = read_fp_sreg(s, rm);
4313
4314     switch (opcode) {
4315     case 0x0: /* FMUL */
4316         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
4317         break;
4318     case 0x1: /* FDIV */
4319         gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
4320         break;
4321     case 0x2: /* FADD */
4322         gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
4323         break;
4324     case 0x3: /* FSUB */
4325         gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
4326         break;
4327     case 0x4: /* FMAX */
4328         gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
4329         break;
4330     case 0x5: /* FMIN */
4331         gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
4332         break;
4333     case 0x6: /* FMAXNM */
4334         gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
4335         break;
4336     case 0x7: /* FMINNM */
4337         gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
4338         break;
4339     case 0x8: /* FNMUL */
4340         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
4341         gen_helper_vfp_negs(tcg_res, tcg_res);
4342         break;
4343     }
4344
4345     write_fp_sreg(s, rd, tcg_res);
4346
4347     tcg_temp_free_ptr(fpst);
4348     tcg_temp_free_i32(tcg_op1);
4349     tcg_temp_free_i32(tcg_op2);
4350     tcg_temp_free_i32(tcg_res);
4351 }
4352
4353 /* C3.6.26 Floating-point data-processing (2 source) - double precision */
4354 static void handle_fp_2src_double(DisasContext *s, int opcode,
4355                                   int rd, int rn, int rm)
4356 {
4357     TCGv_i64 tcg_op1;
4358     TCGv_i64 tcg_op2;
4359     TCGv_i64 tcg_res;
4360     TCGv_ptr fpst;
4361
4362     tcg_res = tcg_temp_new_i64();
4363     fpst = get_fpstatus_ptr();
4364     tcg_op1 = read_fp_dreg(s, rn);
4365     tcg_op2 = read_fp_dreg(s, rm);
4366
4367     switch (opcode) {
4368     case 0x0: /* FMUL */
4369         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
4370         break;
4371     case 0x1: /* FDIV */
4372         gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
4373         break;
4374     case 0x2: /* FADD */
4375         gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
4376         break;
4377     case 0x3: /* FSUB */
4378         gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
4379         break;
4380     case 0x4: /* FMAX */
4381         gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
4382         break;
4383     case 0x5: /* FMIN */
4384         gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
4385         break;
4386     case 0x6: /* FMAXNM */
4387         gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
4388         break;
4389     case 0x7: /* FMINNM */
4390         gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
4391         break;
4392     case 0x8: /* FNMUL */
4393         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
4394         gen_helper_vfp_negd(tcg_res, tcg_res);
4395         break;
4396     }
4397
4398     write_fp_dreg(s, rd, tcg_res);
4399
4400     tcg_temp_free_ptr(fpst);
4401     tcg_temp_free_i64(tcg_op1);
4402     tcg_temp_free_i64(tcg_op2);
4403     tcg_temp_free_i64(tcg_res);
4404 }
4405
4406 /* C3.6.26 Floating point data-processing (2 source)
4407  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
4408  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
4409  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | opcode | 1 0 |  Rn  |  Rd  |
4410  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
4411  */
4412 static void disas_fp_2src(DisasContext *s, uint32_t insn)
4413 {
4414     int type = extract32(insn, 22, 2);
4415     int rd = extract32(insn, 0, 5);
4416     int rn = extract32(insn, 5, 5);
4417     int rm = extract32(insn, 16, 5);
4418     int opcode = extract32(insn, 12, 4);
4419
4420     if (opcode > 8) {
4421         unallocated_encoding(s);
4422         return;
4423     }
4424
4425     switch (type) {
4426     case 0:
4427         if (!fp_access_check(s)) {
4428             return;
4429         }
4430         handle_fp_2src_single(s, opcode, rd, rn, rm);
4431         break;
4432     case 1:
4433         if (!fp_access_check(s)) {
4434             return;
4435         }
4436         handle_fp_2src_double(s, opcode, rd, rn, rm);
4437         break;
4438     default:
4439         unallocated_encoding(s);
4440     }
4441 }
4442
4443 /* C3.6.27 Floating-point data-processing (3 source) - single precision */
4444 static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
4445                                   int rd, int rn, int rm, int ra)
4446 {
4447     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
4448     TCGv_i32 tcg_res = tcg_temp_new_i32();
4449     TCGv_ptr fpst = get_fpstatus_ptr();
4450
4451     tcg_op1 = read_fp_sreg(s, rn);
4452     tcg_op2 = read_fp_sreg(s, rm);
4453     tcg_op3 = read_fp_sreg(s, ra);
4454
4455     /* These are fused multiply-add, and must be done as one
4456      * floating point operation with no rounding between the
4457      * multiplication and addition steps.
4458      * NB that doing the negations here as separate steps is
4459      * correct : an input NaN should come out with its sign bit
4460      * flipped if it is a negated-input.
4461      */
4462     if (o1 == true) {
4463         gen_helper_vfp_negs(tcg_op3, tcg_op3);
4464     }
4465
4466     if (o0 != o1) {
4467         gen_helper_vfp_negs(tcg_op1, tcg_op1);
4468     }
4469
4470     gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
4471
4472     write_fp_sreg(s, rd, tcg_res);
4473
4474     tcg_temp_free_ptr(fpst);
4475     tcg_temp_free_i32(tcg_op1);
4476     tcg_temp_free_i32(tcg_op2);
4477     tcg_temp_free_i32(tcg_op3);
4478     tcg_temp_free_i32(tcg_res);
4479 }
4480
4481 /* C3.6.27 Floating-point data-processing (3 source) - double precision */
4482 static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
4483                                   int rd, int rn, int rm, int ra)
4484 {
4485     TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
4486     TCGv_i64 tcg_res = tcg_temp_new_i64();
4487     TCGv_ptr fpst = get_fpstatus_ptr();
4488
4489     tcg_op1 = read_fp_dreg(s, rn);
4490     tcg_op2 = read_fp_dreg(s, rm);
4491     tcg_op3 = read_fp_dreg(s, ra);
4492
4493     /* These are fused multiply-add, and must be done as one
4494      * floating point operation with no rounding between the
4495      * multiplication and addition steps.
4496      * NB that doing the negations here as separate steps is
4497      * correct : an input NaN should come out with its sign bit
4498      * flipped if it is a negated-input.
4499      */
4500     if (o1 == true) {
4501         gen_helper_vfp_negd(tcg_op3, tcg_op3);
4502     }
4503
4504     if (o0 != o1) {
4505         gen_helper_vfp_negd(tcg_op1, tcg_op1);
4506     }
4507
4508     gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
4509
4510     write_fp_dreg(s, rd, tcg_res);
4511
4512     tcg_temp_free_ptr(fpst);
4513     tcg_temp_free_i64(tcg_op1);
4514     tcg_temp_free_i64(tcg_op2);
4515     tcg_temp_free_i64(tcg_op3);
4516     tcg_temp_free_i64(tcg_res);
4517 }
4518
4519 /* C3.6.27 Floating point data-processing (3 source)
4520  *   31  30  29 28       24 23  22  21  20  16  15  14  10 9    5 4    0
4521  * +---+---+---+-----------+------+----+------+----+------+------+------+
4522  * | M | 0 | S | 1 1 1 1 1 | type | o1 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
4523  * +---+---+---+-----------+------+----+------+----+------+------+------+
4524  */
4525 static void disas_fp_3src(DisasContext *s, uint32_t insn)
4526 {
4527     int type = extract32(insn, 22, 2);
4528     int rd = extract32(insn, 0, 5);
4529     int rn = extract32(insn, 5, 5);
4530     int ra = extract32(insn, 10, 5);
4531     int rm = extract32(insn, 16, 5);
4532     bool o0 = extract32(insn, 15, 1);
4533     bool o1 = extract32(insn, 21, 1);
4534
4535     switch (type) {
4536     case 0:
4537         if (!fp_access_check(s)) {
4538             return;
4539         }
4540         handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
4541         break;
4542     case 1:
4543         if (!fp_access_check(s)) {
4544             return;
4545         }
4546         handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
4547         break;
4548     default:
4549         unallocated_encoding(s);
4550     }
4551 }
4552
4553 /* C3.6.28 Floating point immediate
4554  *   31  30  29 28       24 23  22  21 20        13 12   10 9    5 4    0
4555  * +---+---+---+-----------+------+---+------------+-------+------+------+
4556  * | M | 0 | S | 1 1 1 1 0 | type | 1 |    imm8    | 1 0 0 | imm5 |  Rd  |
4557  * +---+---+---+-----------+------+---+------------+-------+------+------+
4558  */
4559 static void disas_fp_imm(DisasContext *s, uint32_t insn)
4560 {
4561     int rd = extract32(insn, 0, 5);
4562     int imm8 = extract32(insn, 13, 8);
4563     int is_double = extract32(insn, 22, 2);
4564     uint64_t imm;
4565     TCGv_i64 tcg_res;
4566
4567     if (is_double > 1) {
4568         unallocated_encoding(s);
4569         return;
4570     }
4571
4572     if (!fp_access_check(s)) {
4573         return;
4574     }
4575
4576     /* The imm8 encodes the sign bit, enough bits to represent
4577      * an exponent in the range 01....1xx to 10....0xx,
4578      * and the most significant 4 bits of the mantissa; see
4579      * VFPExpandImm() in the v8 ARM ARM.
4580      */
4581     if (is_double) {
4582         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
4583             (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
4584             extract32(imm8, 0, 6);
4585         imm <<= 48;
4586     } else {
4587         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
4588             (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
4589             (extract32(imm8, 0, 6) << 3);
4590         imm <<= 16;
4591     }
4592
4593     tcg_res = tcg_const_i64(imm);
4594     write_fp_dreg(s, rd, tcg_res);
4595     tcg_temp_free_i64(tcg_res);
4596 }
4597
4598 /* Handle floating point <=> fixed point conversions. Note that we can
4599  * also deal with fp <=> integer conversions as a special case (scale == 64)
4600  * OPTME: consider handling that special case specially or at least skipping
4601  * the call to scalbn in the helpers for zero shifts.
4602  */
4603 static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
4604                            bool itof, int rmode, int scale, int sf, int type)
4605 {
4606     bool is_signed = !(opcode & 1);
4607     bool is_double = type;
4608     TCGv_ptr tcg_fpstatus;
4609     TCGv_i32 tcg_shift;
4610
4611     tcg_fpstatus = get_fpstatus_ptr();
4612
4613     tcg_shift = tcg_const_i32(64 - scale);
4614
4615     if (itof) {
4616         TCGv_i64 tcg_int = cpu_reg(s, rn);
4617         if (!sf) {
4618             TCGv_i64 tcg_extend = new_tmp_a64(s);
4619
4620             if (is_signed) {
4621                 tcg_gen_ext32s_i64(tcg_extend, tcg_int);
4622             } else {
4623                 tcg_gen_ext32u_i64(tcg_extend, tcg_int);
4624             }
4625
4626             tcg_int = tcg_extend;
4627         }
4628
4629         if (is_double) {
4630             TCGv_i64 tcg_double = tcg_temp_new_i64();
4631             if (is_signed) {
4632                 gen_helper_vfp_sqtod(tcg_double, tcg_int,
4633                                      tcg_shift, tcg_fpstatus);
4634             } else {
4635                 gen_helper_vfp_uqtod(tcg_double, tcg_int,
4636                                      tcg_shift, tcg_fpstatus);
4637             }
4638             write_fp_dreg(s, rd, tcg_double);
4639             tcg_temp_free_i64(tcg_double);
4640         } else {
4641             TCGv_i32 tcg_single = tcg_temp_new_i32();
4642             if (is_signed) {
4643                 gen_helper_vfp_sqtos(tcg_single, tcg_int,
4644                                      tcg_shift, tcg_fpstatus);
4645             } else {
4646                 gen_helper_vfp_uqtos(tcg_single, tcg_int,
4647                                      tcg_shift, tcg_fpstatus);
4648             }
4649             write_fp_sreg(s, rd, tcg_single);
4650             tcg_temp_free_i32(tcg_single);
4651         }
4652     } else {
4653         TCGv_i64 tcg_int = cpu_reg(s, rd);
4654         TCGv_i32 tcg_rmode;
4655
4656         if (extract32(opcode, 2, 1)) {
4657             /* There are too many rounding modes to all fit into rmode,
4658              * so FCVTA[US] is a special case.
4659              */
4660             rmode = FPROUNDING_TIEAWAY;
4661         }
4662
4663         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
4664
4665         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4666
4667         if (is_double) {
4668             TCGv_i64 tcg_double = read_fp_dreg(s, rn);
4669             if (is_signed) {
4670                 if (!sf) {
4671                     gen_helper_vfp_tosld(tcg_int, tcg_double,
4672                                          tcg_shift, tcg_fpstatus);
4673                 } else {
4674                     gen_helper_vfp_tosqd(tcg_int, tcg_double,
4675                                          tcg_shift, tcg_fpstatus);
4676                 }
4677             } else {
4678                 if (!sf) {
4679                     gen_helper_vfp_tould(tcg_int, tcg_double,
4680                                          tcg_shift, tcg_fpstatus);
4681                 } else {
4682                     gen_helper_vfp_touqd(tcg_int, tcg_double,
4683                                          tcg_shift, tcg_fpstatus);
4684                 }
4685             }
4686             tcg_temp_free_i64(tcg_double);
4687         } else {
4688             TCGv_i32 tcg_single = read_fp_sreg(s, rn);
4689             if (sf) {
4690                 if (is_signed) {
4691                     gen_helper_vfp_tosqs(tcg_int, tcg_single,
4692                                          tcg_shift, tcg_fpstatus);
4693                 } else {
4694                     gen_helper_vfp_touqs(tcg_int, tcg_single,
4695                                          tcg_shift, tcg_fpstatus);
4696                 }
4697             } else {
4698                 TCGv_i32 tcg_dest = tcg_temp_new_i32();
4699                 if (is_signed) {
4700                     gen_helper_vfp_tosls(tcg_dest, tcg_single,
4701                                          tcg_shift, tcg_fpstatus);
4702                 } else {
4703                     gen_helper_vfp_touls(tcg_dest, tcg_single,
4704                                          tcg_shift, tcg_fpstatus);
4705                 }
4706                 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
4707                 tcg_temp_free_i32(tcg_dest);
4708             }
4709             tcg_temp_free_i32(tcg_single);
4710         }
4711
4712         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
4713         tcg_temp_free_i32(tcg_rmode);
4714
4715         if (!sf) {
4716             tcg_gen_ext32u_i64(tcg_int, tcg_int);
4717         }
4718     }
4719
4720     tcg_temp_free_ptr(tcg_fpstatus);
4721     tcg_temp_free_i32(tcg_shift);
4722 }
4723
4724 /* C3.6.29 Floating point <-> fixed point conversions
4725  *   31   30  29 28       24 23  22  21 20   19 18    16 15   10 9    5 4    0
4726  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4727  * | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opcode | scale |  Rn  |  Rd  |
4728  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
4729  */
4730 static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
4731 {
4732     int rd = extract32(insn, 0, 5);
4733     int rn = extract32(insn, 5, 5);
4734     int scale = extract32(insn, 10, 6);
4735     int opcode = extract32(insn, 16, 3);
4736     int rmode = extract32(insn, 19, 2);
4737     int type = extract32(insn, 22, 2);
4738     bool sbit = extract32(insn, 29, 1);
4739     bool sf = extract32(insn, 31, 1);
4740     bool itof;
4741
4742     if (sbit || (type > 1)
4743         || (!sf && scale < 32)) {
4744         unallocated_encoding(s);
4745         return;
4746     }
4747
4748     switch ((rmode << 3) | opcode) {
4749     case 0x2: /* SCVTF */
4750     case 0x3: /* UCVTF */
4751         itof = true;
4752         break;
4753     case 0x18: /* FCVTZS */
4754     case 0x19: /* FCVTZU */
4755         itof = false;
4756         break;
4757     default:
4758         unallocated_encoding(s);
4759         return;
4760     }
4761
4762     if (!fp_access_check(s)) {
4763         return;
4764     }
4765
4766     handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
4767 }
4768
4769 static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
4770 {
4771     /* FMOV: gpr to or from float, double, or top half of quad fp reg,
4772      * without conversion.
4773      */
4774
4775     if (itof) {
4776         TCGv_i64 tcg_rn = cpu_reg(s, rn);
4777
4778         switch (type) {
4779         case 0:
4780         {
4781             /* 32 bit */
4782             TCGv_i64 tmp = tcg_temp_new_i64();
4783             tcg_gen_ext32u_i64(tmp, tcg_rn);
4784             tcg_gen_st_i64(tmp, cpu_env, fp_reg_offset(s, rd, MO_64));
4785             tcg_gen_movi_i64(tmp, 0);
4786             tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd));
4787             tcg_temp_free_i64(tmp);
4788             break;
4789         }
4790         case 1:
4791         {
4792             /* 64 bit */
4793             TCGv_i64 tmp = tcg_const_i64(0);
4794             tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_offset(s, rd, MO_64));
4795             tcg_gen_st_i64(tmp, cpu_env, fp_reg_hi_offset(s, rd));
4796             tcg_temp_free_i64(tmp);
4797             break;
4798         }
4799         case 2:
4800             /* 64 bit to top half. */
4801             tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd));
4802             break;
4803         }
4804     } else {
4805         TCGv_i64 tcg_rd = cpu_reg(s, rd);
4806
4807         switch (type) {
4808         case 0:
4809             /* 32 bit */
4810             tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_32));
4811             break;
4812         case 1:
4813             /* 64 bit */
4814             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_64));
4815             break;
4816         case 2:
4817             /* 64 bits from top half */
4818             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(s, rn));
4819             break;
4820         }
4821     }
4822 }
4823
4824 /* C3.6.30 Floating point <-> integer conversions
4825  *   31   30  29 28       24 23  22  21 20   19 18 16 15         10 9  5 4  0
4826  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4827  * | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
4828  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
4829  */
4830 static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
4831 {
4832     int rd = extract32(insn, 0, 5);
4833     int rn = extract32(insn, 5, 5);
4834     int opcode = extract32(insn, 16, 3);
4835     int rmode = extract32(insn, 19, 2);
4836     int type = extract32(insn, 22, 2);
4837     bool sbit = extract32(insn, 29, 1);
4838     bool sf = extract32(insn, 31, 1);
4839
4840     if (sbit) {
4841         unallocated_encoding(s);
4842         return;
4843     }
4844
4845     if (opcode > 5) {
4846         /* FMOV */
4847         bool itof = opcode & 1;
4848
4849         if (rmode >= 2) {
4850             unallocated_encoding(s);
4851             return;
4852         }
4853
4854         switch (sf << 3 | type << 1 | rmode) {
4855         case 0x0: /* 32 bit */
4856         case 0xa: /* 64 bit */
4857         case 0xd: /* 64 bit to top half of quad */
4858             break;
4859         default:
4860             /* all other sf/type/rmode combinations are invalid */
4861             unallocated_encoding(s);
4862             break;
4863         }
4864
4865         if (!fp_access_check(s)) {
4866             return;
4867         }
4868         handle_fmov(s, rd, rn, type, itof);
4869     } else {
4870         /* actual FP conversions */
4871         bool itof = extract32(opcode, 1, 1);
4872
4873         if (type > 1 || (rmode != 0 && opcode > 1)) {
4874             unallocated_encoding(s);
4875             return;
4876         }
4877
4878         if (!fp_access_check(s)) {
4879             return;
4880         }
4881         handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
4882     }
4883 }
4884
4885 /* FP-specific subcases of table C3-6 (SIMD and FP data processing)
4886  *   31  30  29 28     25 24                          0
4887  * +---+---+---+---------+-----------------------------+
4888  * |   | 0 |   | 1 1 1 1 |                             |
4889  * +---+---+---+---------+-----------------------------+
4890  */
4891 static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
4892 {
4893     if (extract32(insn, 24, 1)) {
4894         /* Floating point data-processing (3 source) */
4895         disas_fp_3src(s, insn);
4896     } else if (extract32(insn, 21, 1) == 0) {
4897         /* Floating point to fixed point conversions */
4898         disas_fp_fixed_conv(s, insn);
4899     } else {
4900         switch (extract32(insn, 10, 2)) {
4901         case 1:
4902             /* Floating point conditional compare */
4903             disas_fp_ccomp(s, insn);
4904             break;
4905         case 2:
4906             /* Floating point data-processing (2 source) */
4907             disas_fp_2src(s, insn);
4908             break;
4909         case 3:
4910             /* Floating point conditional select */
4911             disas_fp_csel(s, insn);
4912             break;
4913         case 0:
4914             switch (ctz32(extract32(insn, 12, 4))) {
4915             case 0: /* [15:12] == xxx1 */
4916                 /* Floating point immediate */
4917                 disas_fp_imm(s, insn);
4918                 break;
4919             case 1: /* [15:12] == xx10 */
4920                 /* Floating point compare */
4921                 disas_fp_compare(s, insn);
4922                 break;
4923             case 2: /* [15:12] == x100 */
4924                 /* Floating point data-processing (1 source) */
4925                 disas_fp_1src(s, insn);
4926                 break;
4927             case 3: /* [15:12] == 1000 */
4928                 unallocated_encoding(s);
4929                 break;
4930             default: /* [15:12] == 0000 */
4931                 /* Floating point <-> integer conversions */
4932                 disas_fp_int_conv(s, insn);
4933                 break;
4934             }
4935             break;
4936         }
4937     }
4938 }
4939
4940 static void do_ext64(DisasContext *s, TCGv_i64 tcg_left, TCGv_i64 tcg_right,
4941                      int pos)
4942 {
4943     /* Extract 64 bits from the middle of two concatenated 64 bit
4944      * vector register slices left:right. The extracted bits start
4945      * at 'pos' bits into the right (least significant) side.
4946      * We return the result in tcg_right, and guarantee not to
4947      * trash tcg_left.
4948      */
4949     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4950     assert(pos > 0 && pos < 64);
4951
4952     tcg_gen_shri_i64(tcg_right, tcg_right, pos);
4953     tcg_gen_shli_i64(tcg_tmp, tcg_left, 64 - pos);
4954     tcg_gen_or_i64(tcg_right, tcg_right, tcg_tmp);
4955
4956     tcg_temp_free_i64(tcg_tmp);
4957 }
4958
4959 /* C3.6.1 EXT
4960  *   31  30 29         24 23 22  21 20  16 15  14  11 10  9    5 4    0
4961  * +---+---+-------------+-----+---+------+---+------+---+------+------+
4962  * | 0 | Q | 1 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | imm4 | 0 |  Rn  |  Rd  |
4963  * +---+---+-------------+-----+---+------+---+------+---+------+------+
4964  */
4965 static void disas_simd_ext(DisasContext *s, uint32_t insn)
4966 {
4967     int is_q = extract32(insn, 30, 1);
4968     int op2 = extract32(insn, 22, 2);
4969     int imm4 = extract32(insn, 11, 4);
4970     int rm = extract32(insn, 16, 5);
4971     int rn = extract32(insn, 5, 5);
4972     int rd = extract32(insn, 0, 5);
4973     int pos = imm4 << 3;
4974     TCGv_i64 tcg_resl, tcg_resh;
4975
4976     if (op2 != 0 || (!is_q && extract32(imm4, 3, 1))) {
4977         unallocated_encoding(s);
4978         return;
4979     }
4980
4981     if (!fp_access_check(s)) {
4982         return;
4983     }
4984
4985     tcg_resh = tcg_temp_new_i64();
4986     tcg_resl = tcg_temp_new_i64();
4987
4988     /* Vd gets bits starting at pos bits into Vm:Vn. This is
4989      * either extracting 128 bits from a 128:128 concatenation, or
4990      * extracting 64 bits from a 64:64 concatenation.
4991      */
4992     if (!is_q) {
4993         read_vec_element(s, tcg_resl, rn, 0, MO_64);
4994         if (pos != 0) {
4995             read_vec_element(s, tcg_resh, rm, 0, MO_64);
4996             do_ext64(s, tcg_resh, tcg_resl, pos);
4997         }
4998         tcg_gen_movi_i64(tcg_resh, 0);
4999     } else {
5000         TCGv_i64 tcg_hh;
5001         typedef struct {
5002             int reg;
5003             int elt;
5004         } EltPosns;
5005         EltPosns eltposns[] = { {rn, 0}, {rn, 1}, {rm, 0}, {rm, 1} };
5006         EltPosns *elt = eltposns;
5007
5008         if (pos >= 64) {
5009             elt++;
5010             pos -= 64;
5011         }
5012
5013         read_vec_element(s, tcg_resl, elt->reg, elt->elt, MO_64);
5014         elt++;
5015         read_vec_element(s, tcg_resh, elt->reg, elt->elt, MO_64);
5016         elt++;
5017         if (pos != 0) {
5018             do_ext64(s, tcg_resh, tcg_resl, pos);
5019             tcg_hh = tcg_temp_new_i64();
5020             read_vec_element(s, tcg_hh, elt->reg, elt->elt, MO_64);
5021             do_ext64(s, tcg_hh, tcg_resh, pos);
5022             tcg_temp_free_i64(tcg_hh);
5023         }
5024     }
5025
5026     write_vec_element(s, tcg_resl, rd, 0, MO_64);
5027     tcg_temp_free_i64(tcg_resl);
5028     write_vec_element(s, tcg_resh, rd, 1, MO_64);
5029     tcg_temp_free_i64(tcg_resh);
5030 }
5031
5032 /* C3.6.2 TBL/TBX
5033  *   31  30 29         24 23 22  21 20  16 15  14 13  12  11 10 9    5 4    0
5034  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
5035  * | 0 | Q | 0 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | len | op | 0 0 |  Rn  |  Rd  |
5036  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
5037  */
5038 static void disas_simd_tb(DisasContext *s, uint32_t insn)
5039 {
5040     int op2 = extract32(insn, 22, 2);
5041     int is_q = extract32(insn, 30, 1);
5042     int rm = extract32(insn, 16, 5);
5043     int rn = extract32(insn, 5, 5);
5044     int rd = extract32(insn, 0, 5);
5045     int is_tblx = extract32(insn, 12, 1);
5046     int len = extract32(insn, 13, 2);
5047     TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
5048     TCGv_i32 tcg_regno, tcg_numregs;
5049
5050     if (op2 != 0) {
5051         unallocated_encoding(s);
5052         return;
5053     }
5054
5055     if (!fp_access_check(s)) {
5056         return;
5057     }
5058
5059     /* This does a table lookup: for every byte element in the input
5060      * we index into a table formed from up to four vector registers,
5061      * and then the output is the result of the lookups. Our helper
5062      * function does the lookup operation for a single 64 bit part of
5063      * the input.
5064      */
5065     tcg_resl = tcg_temp_new_i64();
5066     tcg_resh = tcg_temp_new_i64();
5067
5068     if (is_tblx) {
5069         read_vec_element(s, tcg_resl, rd, 0, MO_64);
5070     } else {
5071         tcg_gen_movi_i64(tcg_resl, 0);
5072     }
5073     if (is_tblx && is_q) {
5074         read_vec_element(s, tcg_resh, rd, 1, MO_64);
5075     } else {
5076         tcg_gen_movi_i64(tcg_resh, 0);
5077     }
5078
5079     tcg_idx = tcg_temp_new_i64();
5080     tcg_regno = tcg_const_i32(rn);
5081     tcg_numregs = tcg_const_i32(len + 1);
5082     read_vec_element(s, tcg_idx, rm, 0, MO_64);
5083     gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
5084                         tcg_regno, tcg_numregs);
5085     if (is_q) {
5086         read_vec_element(s, tcg_idx, rm, 1, MO_64);
5087         gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
5088                             tcg_regno, tcg_numregs);
5089     }
5090     tcg_temp_free_i64(tcg_idx);
5091     tcg_temp_free_i32(tcg_regno);
5092     tcg_temp_free_i32(tcg_numregs);
5093
5094     write_vec_element(s, tcg_resl, rd, 0, MO_64);
5095     tcg_temp_free_i64(tcg_resl);
5096     write_vec_element(s, tcg_resh, rd, 1, MO_64);
5097     tcg_temp_free_i64(tcg_resh);
5098 }
5099
5100 /* C3.6.3 ZIP/UZP/TRN
5101  *   31  30 29         24 23  22  21 20   16 15 14 12 11 10 9    5 4    0
5102  * +---+---+-------------+------+---+------+---+------------------+------+
5103  * | 0 | Q | 0 0 1 1 1 0 | size | 0 |  Rm  | 0 | opc | 1 0 |  Rn  |  Rd  |
5104  * +---+---+-------------+------+---+------+---+------------------+------+
5105  */
5106 static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
5107 {
5108     int rd = extract32(insn, 0, 5);
5109     int rn = extract32(insn, 5, 5);
5110     int rm = extract32(insn, 16, 5);
5111     int size = extract32(insn, 22, 2);
5112     /* opc field bits [1:0] indicate ZIP/UZP/TRN;
5113      * bit 2 indicates 1 vs 2 variant of the insn.
5114      */
5115     int opcode = extract32(insn, 12, 2);
5116     bool part = extract32(insn, 14, 1);
5117     bool is_q = extract32(insn, 30, 1);
5118     int esize = 8 << size;
5119     int i, ofs;
5120     int datasize = is_q ? 128 : 64;
5121     int elements = datasize / esize;
5122     TCGv_i64 tcg_res, tcg_resl, tcg_resh;
5123
5124     if (opcode == 0 || (size == 3 && !is_q)) {
5125         unallocated_encoding(s);
5126         return;
5127     }
5128
5129     if (!fp_access_check(s)) {
5130         return;
5131     }
5132
5133     tcg_resl = tcg_const_i64(0);
5134     tcg_resh = tcg_const_i64(0);
5135     tcg_res = tcg_temp_new_i64();
5136
5137     for (i = 0; i < elements; i++) {
5138         switch (opcode) {
5139         case 1: /* UZP1/2 */
5140         {
5141             int midpoint = elements / 2;
5142             if (i < midpoint) {
5143                 read_vec_element(s, tcg_res, rn, 2 * i + part, size);
5144             } else {
5145                 read_vec_element(s, tcg_res, rm,
5146                                  2 * (i - midpoint) + part, size);
5147             }
5148             break;
5149         }
5150         case 2: /* TRN1/2 */
5151             if (i & 1) {
5152                 read_vec_element(s, tcg_res, rm, (i & ~1) + part, size);
5153             } else {
5154                 read_vec_element(s, tcg_res, rn, (i & ~1) + part, size);
5155             }
5156             break;
5157         case 3: /* ZIP1/2 */
5158         {
5159             int base = part * elements / 2;
5160             if (i & 1) {
5161                 read_vec_element(s, tcg_res, rm, base + (i >> 1), size);
5162             } else {
5163                 read_vec_element(s, tcg_res, rn, base + (i >> 1), size);
5164             }
5165             break;
5166         }
5167         default:
5168             g_assert_not_reached();
5169         }
5170
5171         ofs = i * esize;
5172         if (ofs < 64) {
5173             tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
5174             tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
5175         } else {
5176             tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
5177             tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
5178         }
5179     }
5180
5181     tcg_temp_free_i64(tcg_res);
5182
5183     write_vec_element(s, tcg_resl, rd, 0, MO_64);
5184     tcg_temp_free_i64(tcg_resl);
5185     write_vec_element(s, tcg_resh, rd, 1, MO_64);
5186     tcg_temp_free_i64(tcg_resh);
5187 }
5188
5189 static void do_minmaxop(DisasContext *s, TCGv_i32 tcg_elt1, TCGv_i32 tcg_elt2,
5190                         int opc, bool is_min, TCGv_ptr fpst)
5191 {
5192     /* Helper function for disas_simd_across_lanes: do a single precision
5193      * min/max operation on the specified two inputs,
5194      * and return the result in tcg_elt1.
5195      */
5196     if (opc == 0xc) {
5197         if (is_min) {
5198             gen_helper_vfp_minnums(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
5199         } else {
5200             gen_helper_vfp_maxnums(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
5201         }
5202     } else {
5203         assert(opc == 0xf);
5204         if (is_min) {
5205             gen_helper_vfp_mins(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
5206         } else {
5207             gen_helper_vfp_maxs(tcg_elt1, tcg_elt1, tcg_elt2, fpst);
5208         }
5209     }
5210 }
5211
5212 /* C3.6.4 AdvSIMD across lanes
5213  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
5214  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
5215  * | 0 | Q | U | 0 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
5216  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
5217  */
5218 static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
5219 {
5220     int rd = extract32(insn, 0, 5);
5221     int rn = extract32(insn, 5, 5);
5222     int size = extract32(insn, 22, 2);
5223     int opcode = extract32(insn, 12, 5);
5224     bool is_q = extract32(insn, 30, 1);
5225     bool is_u = extract32(insn, 29, 1);
5226     bool is_fp = false;
5227     bool is_min = false;
5228     int esize;
5229     int elements;
5230     int i;
5231     TCGv_i64 tcg_res, tcg_elt;
5232
5233     switch (opcode) {
5234     case 0x1b: /* ADDV */
5235         if (is_u) {
5236             unallocated_encoding(s);
5237             return;
5238         }
5239         /* fall through */
5240     case 0x3: /* SADDLV, UADDLV */
5241     case 0xa: /* SMAXV, UMAXV */
5242     case 0x1a: /* SMINV, UMINV */
5243         if (size == 3 || (size == 2 && !is_q)) {
5244             unallocated_encoding(s);
5245             return;
5246         }
5247         break;
5248     case 0xc: /* FMAXNMV, FMINNMV */
5249     case 0xf: /* FMAXV, FMINV */
5250         if (!is_u || !is_q || extract32(size, 0, 1)) {
5251             unallocated_encoding(s);
5252             return;
5253         }
5254         /* Bit 1 of size field encodes min vs max, and actual size is always
5255          * 32 bits: adjust the size variable so following code can rely on it
5256          */
5257         is_min = extract32(size, 1, 1);
5258         is_fp = true;
5259         size = 2;
5260         break;
5261     default:
5262         unallocated_encoding(s);
5263         return;
5264     }
5265
5266     if (!fp_access_check(s)) {
5267         return;
5268     }
5269
5270     esize = 8 << size;
5271     elements = (is_q ? 128 : 64) / esize;
5272
5273     tcg_res = tcg_temp_new_i64();
5274     tcg_elt = tcg_temp_new_i64();
5275
5276     /* These instructions operate across all lanes of a vector
5277      * to produce a single result. We can guarantee that a 64
5278      * bit intermediate is sufficient:
5279      *  + for [US]ADDLV the maximum element size is 32 bits, and
5280      *    the result type is 64 bits
5281      *  + for FMAX*V, FMIN*V, ADDV the intermediate type is the
5282      *    same as the element size, which is 32 bits at most
5283      * For the integer operations we can choose to work at 64
5284      * or 32 bits and truncate at the end; for simplicity
5285      * we use 64 bits always. The floating point
5286      * ops do require 32 bit intermediates, though.
5287      */
5288     if (!is_fp) {
5289         read_vec_element(s, tcg_res, rn, 0, size | (is_u ? 0 : MO_SIGN));
5290
5291         for (i = 1; i < elements; i++) {
5292             read_vec_element(s, tcg_elt, rn, i, size | (is_u ? 0 : MO_SIGN));
5293
5294             switch (opcode) {
5295             case 0x03: /* SADDLV / UADDLV */
5296             case 0x1b: /* ADDV */
5297                 tcg_gen_add_i64(tcg_res, tcg_res, tcg_elt);
5298                 break;
5299             case 0x0a: /* SMAXV / UMAXV */
5300                 tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
5301                                     tcg_res,
5302                                     tcg_res, tcg_elt, tcg_res, tcg_elt);
5303                 break;
5304             case 0x1a: /* SMINV / UMINV */
5305                 tcg_gen_movcond_i64(is_u ? TCG_COND_LEU : TCG_COND_LE,
5306                                     tcg_res,
5307                                     tcg_res, tcg_elt, tcg_res, tcg_elt);
5308                 break;
5309                 break;
5310             default:
5311                 g_assert_not_reached();
5312             }
5313
5314         }
5315     } else {
5316         /* Floating point ops which work on 32 bit (single) intermediates.
5317          * Note that correct NaN propagation requires that we do these
5318          * operations in exactly the order specified by the pseudocode.
5319          */
5320         TCGv_i32 tcg_elt1 = tcg_temp_new_i32();
5321         TCGv_i32 tcg_elt2 = tcg_temp_new_i32();
5322         TCGv_i32 tcg_elt3 = tcg_temp_new_i32();
5323         TCGv_ptr fpst = get_fpstatus_ptr();
5324
5325         assert(esize == 32);
5326         assert(elements == 4);
5327
5328         read_vec_element(s, tcg_elt, rn, 0, MO_32);
5329         tcg_gen_trunc_i64_i32(tcg_elt1, tcg_elt);
5330         read_vec_element(s, tcg_elt, rn, 1, MO_32);
5331         tcg_gen_trunc_i64_i32(tcg_elt2, tcg_elt);
5332
5333         do_minmaxop(s, tcg_elt1, tcg_elt2, opcode, is_min, fpst);
5334
5335         read_vec_element(s, tcg_elt, rn, 2, MO_32);
5336         tcg_gen_trunc_i64_i32(tcg_elt2, tcg_elt);
5337         read_vec_element(s, tcg_elt, rn, 3, MO_32);
5338         tcg_gen_trunc_i64_i32(tcg_elt3, tcg_elt);
5339
5340         do_minmaxop(s, tcg_elt2, tcg_elt3, opcode, is_min, fpst);
5341
5342         do_minmaxop(s, tcg_elt1, tcg_elt2, opcode, is_min, fpst);
5343
5344         tcg_gen_extu_i32_i64(tcg_res, tcg_elt1);
5345         tcg_temp_free_i32(tcg_elt1);
5346         tcg_temp_free_i32(tcg_elt2);
5347         tcg_temp_free_i32(tcg_elt3);
5348         tcg_temp_free_ptr(fpst);
5349     }
5350
5351     tcg_temp_free_i64(tcg_elt);
5352
5353     /* Now truncate the result to the width required for the final output */
5354     if (opcode == 0x03) {
5355         /* SADDLV, UADDLV: result is 2*esize */
5356         size++;
5357     }
5358
5359     switch (size) {
5360     case 0:
5361         tcg_gen_ext8u_i64(tcg_res, tcg_res);
5362         break;
5363     case 1:
5364         tcg_gen_ext16u_i64(tcg_res, tcg_res);
5365         break;
5366     case 2:
5367         tcg_gen_ext32u_i64(tcg_res, tcg_res);
5368         break;
5369     case 3:
5370         break;
5371     default:
5372         g_assert_not_reached();
5373     }
5374
5375     write_fp_dreg(s, rd, tcg_res);
5376     tcg_temp_free_i64(tcg_res);
5377 }
5378
5379 /* C6.3.31 DUP (Element, Vector)
5380  *
5381  *  31  30   29              21 20    16 15        10  9    5 4    0
5382  * +---+---+-------------------+--------+-------------+------+------+
5383  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
5384  * +---+---+-------------------+--------+-------------+------+------+
5385  *
5386  * size: encoded in imm5 (see ARM ARM LowestSetBit())
5387  */
5388 static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
5389                              int imm5)
5390 {
5391     int size = ctz32(imm5);
5392     int esize = 8 << size;
5393     int elements = (is_q ? 128 : 64) / esize;
5394     int index, i;
5395     TCGv_i64 tmp;
5396
5397     if (size > 3 || (size == 3 && !is_q)) {
5398         unallocated_encoding(s);
5399         return;
5400     }
5401
5402     if (!fp_access_check(s)) {
5403         return;
5404     }
5405
5406     index = imm5 >> (size + 1);
5407
5408     tmp = tcg_temp_new_i64();
5409     read_vec_element(s, tmp, rn, index, size);
5410
5411     for (i = 0; i < elements; i++) {
5412         write_vec_element(s, tmp, rd, i, size);
5413     }
5414
5415     if (!is_q) {
5416         clear_vec_high(s, rd);
5417     }
5418
5419     tcg_temp_free_i64(tmp);
5420 }
5421
5422 /* C6.3.31 DUP (element, scalar)
5423  *  31                   21 20    16 15        10  9    5 4    0
5424  * +-----------------------+--------+-------------+------+------+
5425  * | 0 1 0 1 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
5426  * +-----------------------+--------+-------------+------+------+
5427  */
5428 static void handle_simd_dupes(DisasContext *s, int rd, int rn,
5429                               int imm5)
5430 {
5431     int size = ctz32(imm5);
5432     int index;
5433     TCGv_i64 tmp;
5434
5435     if (size > 3) {
5436         unallocated_encoding(s);
5437         return;
5438     }
5439
5440     if (!fp_access_check(s)) {
5441         return;
5442     }
5443
5444     index = imm5 >> (size + 1);
5445
5446     /* This instruction just extracts the specified element and
5447      * zero-extends it into the bottom of the destination register.
5448      */
5449     tmp = tcg_temp_new_i64();
5450     read_vec_element(s, tmp, rn, index, size);
5451     write_fp_dreg(s, rd, tmp);
5452     tcg_temp_free_i64(tmp);
5453 }
5454
5455 /* C6.3.32 DUP (General)
5456  *
5457  *  31  30   29              21 20    16 15        10  9    5 4    0
5458  * +---+---+-------------------+--------+-------------+------+------+
5459  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 1 1 |  Rn  |  Rd  |
5460  * +---+---+-------------------+--------+-------------+------+------+
5461  *
5462  * size: encoded in imm5 (see ARM ARM LowestSetBit())
5463  */
5464 static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn,
5465                              int imm5)
5466 {
5467     int size = ctz32(imm5);
5468     int esize = 8 << size;
5469     int elements = (is_q ? 128 : 64)/esize;
5470     int i = 0;
5471
5472     if (size > 3 || ((size == 3) && !is_q)) {
5473         unallocated_encoding(s);
5474         return;
5475     }
5476
5477     if (!fp_access_check(s)) {
5478         return;
5479     }
5480
5481     for (i = 0; i < elements; i++) {
5482         write_vec_element(s, cpu_reg(s, rn), rd, i, size);
5483     }
5484     if (!is_q) {
5485         clear_vec_high(s, rd);
5486     }
5487 }
5488
5489 /* C6.3.150 INS (Element)
5490  *
5491  *  31                   21 20    16 15  14    11  10 9    5 4    0
5492  * +-----------------------+--------+------------+---+------+------+
5493  * | 0 1 1 0 1 1 1 0 0 0 0 |  imm5  | 0 |  imm4  | 1 |  Rn  |  Rd  |
5494  * +-----------------------+--------+------------+---+------+------+
5495  *
5496  * size: encoded in imm5 (see ARM ARM LowestSetBit())
5497  * index: encoded in imm5<4:size+1>
5498  */
5499 static void handle_simd_inse(DisasContext *s, int rd, int rn,
5500                              int imm4, int imm5)
5501 {
5502     int size = ctz32(imm5);
5503     int src_index, dst_index;
5504     TCGv_i64 tmp;
5505
5506     if (size > 3) {
5507         unallocated_encoding(s);
5508         return;
5509     }
5510
5511     if (!fp_access_check(s)) {
5512         return;
5513     }
5514
5515     dst_index = extract32(imm5, 1+size, 5);
5516     src_index = extract32(imm4, size, 4);
5517
5518     tmp = tcg_temp_new_i64();
5519
5520     read_vec_element(s, tmp, rn, src_index, size);
5521     write_vec_element(s, tmp, rd, dst_index, size);
5522
5523     tcg_temp_free_i64(tmp);
5524 }
5525
5526
5527 /* C6.3.151 INS (General)
5528  *
5529  *  31                   21 20    16 15        10  9    5 4    0
5530  * +-----------------------+--------+-------------+------+------+
5531  * | 0 1 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 1 1 1 |  Rn  |  Rd  |
5532  * +-----------------------+--------+-------------+------+------+
5533  *
5534  * size: encoded in imm5 (see ARM ARM LowestSetBit())
5535  * index: encoded in imm5<4:size+1>
5536  */
5537 static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
5538 {
5539     int size = ctz32(imm5);
5540     int idx;
5541
5542     if (size > 3) {
5543         unallocated_encoding(s);
5544         return;
5545     }
5546
5547     if (!fp_access_check(s)) {
5548         return;
5549     }
5550
5551     idx = extract32(imm5, 1 + size, 4 - size);
5552     write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
5553 }
5554
5555 /*
5556  * C6.3.321 UMOV (General)
5557  * C6.3.237 SMOV (General)
5558  *
5559  *  31  30   29              21 20    16 15    12   10 9    5 4    0
5560  * +---+---+-------------------+--------+-------------+------+------+
5561  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 1 U 1 1 |  Rn  |  Rd  |
5562  * +---+---+-------------------+--------+-------------+------+------+
5563  *
5564  * U: unsigned when set
5565  * size: encoded in imm5 (see ARM ARM LowestSetBit())
5566  */
5567 static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed,
5568                                   int rn, int rd, int imm5)
5569 {
5570     int size = ctz32(imm5);
5571     int element;
5572     TCGv_i64 tcg_rd;
5573
5574     /* Check for UnallocatedEncodings */
5575     if (is_signed) {
5576         if (size > 2 || (size == 2 && !is_q)) {
5577             unallocated_encoding(s);
5578             return;
5579         }
5580     } else {
5581         if (size > 3
5582             || (size < 3 && is_q)
5583             || (size == 3 && !is_q)) {
5584             unallocated_encoding(s);
5585             return;
5586         }
5587     }
5588
5589     if (!fp_access_check(s)) {
5590         return;
5591     }
5592
5593     element = extract32(imm5, 1+size, 4);
5594
5595     tcg_rd = cpu_reg(s, rd);
5596     read_vec_element(s, tcg_rd, rn, element, size | (is_signed ? MO_SIGN : 0));
5597     if (is_signed && !is_q) {
5598         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
5599     }
5600 }
5601
5602 /* C3.6.5 AdvSIMD copy
5603  *   31  30  29  28             21 20  16 15  14  11 10  9    5 4    0
5604  * +---+---+----+-----------------+------+---+------+---+------+------+
5605  * | 0 | Q | op | 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
5606  * +---+---+----+-----------------+------+---+------+---+------+------+
5607  */
5608 static void disas_simd_copy(DisasContext *s, uint32_t insn)
5609 {
5610     int rd = extract32(insn, 0, 5);
5611     int rn = extract32(insn, 5, 5);
5612     int imm4 = extract32(insn, 11, 4);
5613     int op = extract32(insn, 29, 1);
5614     int is_q = extract32(insn, 30, 1);
5615     int imm5 = extract32(insn, 16, 5);
5616
5617     if (op) {
5618         if (is_q) {
5619             /* INS (element) */
5620             handle_simd_inse(s, rd, rn, imm4, imm5);
5621         } else {
5622             unallocated_encoding(s);
5623         }
5624     } else {
5625         switch (imm4) {
5626         case 0:
5627             /* DUP (element - vector) */
5628             handle_simd_dupe(s, is_q, rd, rn, imm5);
5629             break;
5630         case 1:
5631             /* DUP (general) */
5632             handle_simd_dupg(s, is_q, rd, rn, imm5);
5633             break;
5634         case 3:
5635             if (is_q) {
5636                 /* INS (general) */
5637                 handle_simd_insg(s, rd, rn, imm5);
5638             } else {
5639                 unallocated_encoding(s);
5640             }
5641             break;
5642         case 5:
5643         case 7:
5644             /* UMOV/SMOV (is_q indicates 32/64; imm4 indicates signedness) */
5645             handle_simd_umov_smov(s, is_q, (imm4 == 5), rn, rd, imm5);
5646             break;
5647         default:
5648             unallocated_encoding(s);
5649             break;
5650         }
5651     }
5652 }
5653
5654 /* C3.6.6 AdvSIMD modified immediate
5655  *  31  30   29  28                 19 18 16 15   12  11  10  9     5 4    0
5656  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
5657  * | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh |  Rd  |
5658  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
5659  *
5660  * There are a number of operations that can be carried out here:
5661  *   MOVI - move (shifted) imm into register
5662  *   MVNI - move inverted (shifted) imm into register
5663  *   ORR  - bitwise OR of (shifted) imm with register
5664  *   BIC  - bitwise clear of (shifted) imm with register
5665  */
5666 static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
5667 {
5668     int rd = extract32(insn, 0, 5);
5669     int cmode = extract32(insn, 12, 4);
5670     int cmode_3_1 = extract32(cmode, 1, 3);
5671     int cmode_0 = extract32(cmode, 0, 1);
5672     int o2 = extract32(insn, 11, 1);
5673     uint64_t abcdefgh = extract32(insn, 5, 5) | (extract32(insn, 16, 3) << 5);
5674     bool is_neg = extract32(insn, 29, 1);
5675     bool is_q = extract32(insn, 30, 1);
5676     uint64_t imm = 0;
5677     TCGv_i64 tcg_rd, tcg_imm;
5678     int i;
5679
5680     if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {
5681         unallocated_encoding(s);
5682         return;
5683     }
5684
5685     if (!fp_access_check(s)) {
5686         return;
5687     }
5688
5689     /* See AdvSIMDExpandImm() in ARM ARM */
5690     switch (cmode_3_1) {
5691     case 0: /* Replicate(Zeros(24):imm8, 2) */
5692     case 1: /* Replicate(Zeros(16):imm8:Zeros(8), 2) */
5693     case 2: /* Replicate(Zeros(8):imm8:Zeros(16), 2) */
5694     case 3: /* Replicate(imm8:Zeros(24), 2) */
5695     {
5696         int shift = cmode_3_1 * 8;
5697         imm = bitfield_replicate(abcdefgh << shift, 32);
5698         break;
5699     }
5700     case 4: /* Replicate(Zeros(8):imm8, 4) */
5701     case 5: /* Replicate(imm8:Zeros(8), 4) */
5702     {
5703         int shift = (cmode_3_1 & 0x1) * 8;
5704         imm = bitfield_replicate(abcdefgh << shift, 16);
5705         break;
5706     }
5707     case 6:
5708         if (cmode_0) {
5709             /* Replicate(Zeros(8):imm8:Ones(16), 2) */
5710             imm = (abcdefgh << 16) | 0xffff;
5711         } else {
5712             /* Replicate(Zeros(16):imm8:Ones(8), 2) */
5713             imm = (abcdefgh << 8) | 0xff;
5714         }
5715         imm = bitfield_replicate(imm, 32);
5716         break;
5717     case 7:
5718         if (!cmode_0 && !is_neg) {
5719             imm = bitfield_replicate(abcdefgh, 8);
5720         } else if (!cmode_0 && is_neg) {
5721             int i;
5722             imm = 0;
5723             for (i = 0; i < 8; i++) {
5724                 if ((abcdefgh) & (1 << i)) {
5725                     imm |= 0xffULL << (i * 8);
5726                 }
5727             }
5728         } else if (cmode_0) {
5729             if (is_neg) {
5730                 imm = (abcdefgh & 0x3f) << 48;
5731                 if (abcdefgh & 0x80) {
5732                     imm |= 0x8000000000000000ULL;
5733                 }
5734                 if (abcdefgh & 0x40) {
5735                     imm |= 0x3fc0000000000000ULL;
5736                 } else {
5737                     imm |= 0x4000000000000000ULL;
5738                 }
5739             } else {
5740                 imm = (abcdefgh & 0x3f) << 19;
5741                 if (abcdefgh & 0x80) {
5742                     imm |= 0x80000000;
5743                 }
5744                 if (abcdefgh & 0x40) {
5745                     imm |= 0x3e000000;
5746                 } else {
5747                     imm |= 0x40000000;
5748                 }
5749                 imm |= (imm << 32);
5750             }
5751         }
5752         break;
5753     }
5754
5755     if (cmode_3_1 != 7 && is_neg) {
5756         imm = ~imm;
5757     }
5758
5759     tcg_imm = tcg_const_i64(imm);
5760     tcg_rd = new_tmp_a64(s);
5761
5762     for (i = 0; i < 2; i++) {
5763         int foffs = i ? fp_reg_hi_offset(s, rd) : fp_reg_offset(s, rd, MO_64);
5764
5765         if (i == 1 && !is_q) {
5766             /* non-quad ops clear high half of vector */
5767             tcg_gen_movi_i64(tcg_rd, 0);
5768         } else if ((cmode & 0x9) == 0x1 || (cmode & 0xd) == 0x9) {
5769             tcg_gen_ld_i64(tcg_rd, cpu_env, foffs);
5770             if (is_neg) {
5771                 /* AND (BIC) */
5772                 tcg_gen_and_i64(tcg_rd, tcg_rd, tcg_imm);
5773             } else {
5774                 /* ORR */
5775                 tcg_gen_or_i64(tcg_rd, tcg_rd, tcg_imm);
5776             }
5777         } else {
5778             /* MOVI */
5779             tcg_gen_mov_i64(tcg_rd, tcg_imm);
5780         }
5781         tcg_gen_st_i64(tcg_rd, cpu_env, foffs);
5782     }
5783
5784     tcg_temp_free_i64(tcg_imm);
5785 }
5786
5787 /* C3.6.7 AdvSIMD scalar copy
5788  *  31 30  29  28             21 20  16 15  14  11 10  9    5 4    0
5789  * +-----+----+-----------------+------+---+------+---+------+------+
5790  * | 0 1 | op | 1 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
5791  * +-----+----+-----------------+------+---+------+---+------+------+
5792  */
5793 static void disas_simd_scalar_copy(DisasContext *s, uint32_t insn)
5794 {
5795     int rd = extract32(insn, 0, 5);
5796     int rn = extract32(insn, 5, 5);
5797     int imm4 = extract32(insn, 11, 4);
5798     int imm5 = extract32(insn, 16, 5);
5799     int op = extract32(insn, 29, 1);
5800
5801     if (op != 0 || imm4 != 0) {
5802         unallocated_encoding(s);
5803         return;
5804     }
5805
5806     /* DUP (element, scalar) */
5807     handle_simd_dupes(s, rd, rn, imm5);
5808 }
5809
5810 /* C3.6.8 AdvSIMD scalar pairwise
5811  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
5812  * +-----+---+-----------+------+-----------+--------+-----+------+------+
5813  * | 0 1 | U | 1 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
5814  * +-----+---+-----------+------+-----------+--------+-----+------+------+
5815  */
5816 static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
5817 {
5818     int u = extract32(insn, 29, 1);
5819     int size = extract32(insn, 22, 2);
5820     int opcode = extract32(insn, 12, 5);
5821     int rn = extract32(insn, 5, 5);
5822     int rd = extract32(insn, 0, 5);
5823     TCGv_ptr fpst;
5824
5825     /* For some ops (the FP ones), size[1] is part of the encoding.
5826      * For ADDP strictly it is not but size[1] is always 1 for valid
5827      * encodings.
5828      */
5829     opcode |= (extract32(size, 1, 1) << 5);
5830
5831     switch (opcode) {
5832     case 0x3b: /* ADDP */
5833         if (u || size != 3) {
5834             unallocated_encoding(s);
5835             return;
5836         }
5837         if (!fp_access_check(s)) {
5838             return;
5839         }
5840
5841         TCGV_UNUSED_PTR(fpst);
5842         break;
5843     case 0xc: /* FMAXNMP */
5844     case 0xd: /* FADDP */
5845     case 0xf: /* FMAXP */
5846     case 0x2c: /* FMINNMP */
5847     case 0x2f: /* FMINP */
5848         /* FP op, size[0] is 32 or 64 bit */
5849         if (!u) {
5850             unallocated_encoding(s);
5851             return;
5852         }
5853         if (!fp_access_check(s)) {
5854             return;
5855         }
5856
5857         size = extract32(size, 0, 1) ? 3 : 2;
5858         fpst = get_fpstatus_ptr();
5859         break;
5860     default:
5861         unallocated_encoding(s);
5862         return;
5863     }
5864
5865     if (size == 3) {
5866         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
5867         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
5868         TCGv_i64 tcg_res = tcg_temp_new_i64();
5869
5870         read_vec_element(s, tcg_op1, rn, 0, MO_64);
5871         read_vec_element(s, tcg_op2, rn, 1, MO_64);
5872
5873         switch (opcode) {
5874         case 0x3b: /* ADDP */
5875             tcg_gen_add_i64(tcg_res, tcg_op1, tcg_op2);
5876             break;
5877         case 0xc: /* FMAXNMP */
5878             gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
5879             break;
5880         case 0xd: /* FADDP */
5881             gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
5882             break;
5883         case 0xf: /* FMAXP */
5884             gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
5885             break;
5886         case 0x2c: /* FMINNMP */
5887             gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
5888             break;
5889         case 0x2f: /* FMINP */
5890             gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
5891             break;
5892         default:
5893             g_assert_not_reached();
5894         }
5895
5896         write_fp_dreg(s, rd, tcg_res);
5897
5898         tcg_temp_free_i64(tcg_op1);
5899         tcg_temp_free_i64(tcg_op2);
5900         tcg_temp_free_i64(tcg_res);
5901     } else {
5902         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
5903         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
5904         TCGv_i32 tcg_res = tcg_temp_new_i32();
5905
5906         read_vec_element_i32(s, tcg_op1, rn, 0, MO_32);
5907         read_vec_element_i32(s, tcg_op2, rn, 1, MO_32);
5908
5909         switch (opcode) {
5910         case 0xc: /* FMAXNMP */
5911             gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
5912             break;
5913         case 0xd: /* FADDP */
5914             gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
5915             break;
5916         case 0xf: /* FMAXP */
5917             gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
5918             break;
5919         case 0x2c: /* FMINNMP */
5920             gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
5921             break;
5922         case 0x2f: /* FMINP */
5923             gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
5924             break;
5925         default:
5926             g_assert_not_reached();
5927         }
5928
5929         write_fp_sreg(s, rd, tcg_res);
5930
5931         tcg_temp_free_i32(tcg_op1);
5932         tcg_temp_free_i32(tcg_op2);
5933         tcg_temp_free_i32(tcg_res);
5934     }
5935
5936     if (!TCGV_IS_UNUSED_PTR(fpst)) {
5937         tcg_temp_free_ptr(fpst);
5938     }
5939 }
5940
5941 /*
5942  * Common SSHR[RA]/USHR[RA] - Shift right (optional rounding/accumulate)
5943  *
5944  * This code is handles the common shifting code and is used by both
5945  * the vector and scalar code.
5946  */
5947 static void handle_shri_with_rndacc(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
5948                                     TCGv_i64 tcg_rnd, bool accumulate,
5949                                     bool is_u, int size, int shift)
5950 {
5951     bool extended_result = false;
5952     bool round = !TCGV_IS_UNUSED_I64(tcg_rnd);
5953     int ext_lshift = 0;
5954     TCGv_i64 tcg_src_hi;
5955
5956     if (round && size == 3) {
5957         extended_result = true;
5958         ext_lshift = 64 - shift;
5959         tcg_src_hi = tcg_temp_new_i64();
5960     } else if (shift == 64) {
5961         if (!accumulate && is_u) {
5962             /* result is zero */
5963             tcg_gen_movi_i64(tcg_res, 0);
5964             return;
5965         }
5966     }
5967
5968     /* Deal with the rounding step */
5969     if (round) {
5970         if (extended_result) {
5971             TCGv_i64 tcg_zero = tcg_const_i64(0);
5972             if (!is_u) {
5973                 /* take care of sign extending tcg_res */
5974                 tcg_gen_sari_i64(tcg_src_hi, tcg_src, 63);
5975                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
5976                                  tcg_src, tcg_src_hi,
5977                                  tcg_rnd, tcg_zero);
5978             } else {
5979                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
5980                                  tcg_src, tcg_zero,
5981                                  tcg_rnd, tcg_zero);
5982             }
5983             tcg_temp_free_i64(tcg_zero);
5984         } else {
5985             tcg_gen_add_i64(tcg_src, tcg_src, tcg_rnd);
5986         }
5987     }
5988
5989     /* Now do the shift right */
5990     if (round && extended_result) {
5991         /* extended case, >64 bit precision required */
5992         if (ext_lshift == 0) {
5993             /* special case, only high bits matter */
5994             tcg_gen_mov_i64(tcg_src, tcg_src_hi);
5995         } else {
5996             tcg_gen_shri_i64(tcg_src, tcg_src, shift);
5997             tcg_gen_shli_i64(tcg_src_hi, tcg_src_hi, ext_lshift);
5998             tcg_gen_or_i64(tcg_src, tcg_src, tcg_src_hi);
5999         }
6000     } else {
6001         if (is_u) {
6002             if (shift == 64) {
6003                 /* essentially shifting in 64 zeros */
6004                 tcg_gen_movi_i64(tcg_src, 0);
6005             } else {
6006                 tcg_gen_shri_i64(tcg_src, tcg_src, shift);
6007             }
6008         } else {
6009             if (shift == 64) {
6010                 /* effectively extending the sign-bit */
6011                 tcg_gen_sari_i64(tcg_src, tcg_src, 63);
6012             } else {
6013                 tcg_gen_sari_i64(tcg_src, tcg_src, shift);
6014             }
6015         }
6016     }
6017
6018     if (accumulate) {
6019         tcg_gen_add_i64(tcg_res, tcg_res, tcg_src);
6020     } else {
6021         tcg_gen_mov_i64(tcg_res, tcg_src);
6022     }
6023
6024     if (extended_result) {
6025         tcg_temp_free_i64(tcg_src_hi);
6026     }
6027 }
6028
6029 /* Common SHL/SLI - Shift left with an optional insert */
6030 static void handle_shli_with_ins(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
6031                                  bool insert, int shift)
6032 {
6033     if (insert) { /* SLI */
6034         tcg_gen_deposit_i64(tcg_res, tcg_res, tcg_src, shift, 64 - shift);
6035     } else { /* SHL */
6036         tcg_gen_shli_i64(tcg_res, tcg_src, shift);
6037     }
6038 }
6039
6040 /* SRI: shift right with insert */
6041 static void handle_shri_with_ins(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
6042                                  int size, int shift)
6043 {
6044     int esize = 8 << size;
6045
6046     /* shift count same as element size is valid but does nothing;
6047      * special case to avoid potential shift by 64.
6048      */
6049     if (shift != esize) {
6050         tcg_gen_shri_i64(tcg_src, tcg_src, shift);
6051         tcg_gen_deposit_i64(tcg_res, tcg_res, tcg_src, 0, esize - shift);
6052     }
6053 }
6054
6055 /* SSHR[RA]/USHR[RA] - Scalar shift right (optional rounding/accumulate) */
6056 static void handle_scalar_simd_shri(DisasContext *s,
6057                                     bool is_u, int immh, int immb,
6058                                     int opcode, int rn, int rd)
6059 {
6060     const int size = 3;
6061     int immhb = immh << 3 | immb;
6062     int shift = 2 * (8 << size) - immhb;
6063     bool accumulate = false;
6064     bool round = false;
6065     bool insert = false;
6066     TCGv_i64 tcg_rn;
6067     TCGv_i64 tcg_rd;
6068     TCGv_i64 tcg_round;
6069
6070     if (!extract32(immh, 3, 1)) {
6071         unallocated_encoding(s);
6072         return;
6073     }
6074
6075     if (!fp_access_check(s)) {
6076         return;
6077     }
6078
6079     switch (opcode) {
6080     case 0x02: /* SSRA / USRA (accumulate) */
6081         accumulate = true;
6082         break;
6083     case 0x04: /* SRSHR / URSHR (rounding) */
6084         round = true;
6085         break;
6086     case 0x06: /* SRSRA / URSRA (accum + rounding) */
6087         accumulate = round = true;
6088         break;
6089     case 0x08: /* SRI */
6090         insert = true;
6091         break;
6092     }
6093
6094     if (round) {
6095         uint64_t round_const = 1ULL << (shift - 1);
6096         tcg_round = tcg_const_i64(round_const);
6097     } else {
6098         TCGV_UNUSED_I64(tcg_round);
6099     }
6100
6101     tcg_rn = read_fp_dreg(s, rn);
6102     tcg_rd = (accumulate || insert) ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
6103
6104     if (insert) {
6105         handle_shri_with_ins(tcg_rd, tcg_rn, size, shift);
6106     } else {
6107         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
6108                                 accumulate, is_u, size, shift);
6109     }
6110
6111     write_fp_dreg(s, rd, tcg_rd);
6112
6113     tcg_temp_free_i64(tcg_rn);
6114     tcg_temp_free_i64(tcg_rd);
6115     if (round) {
6116         tcg_temp_free_i64(tcg_round);
6117     }
6118 }
6119
6120 /* SHL/SLI - Scalar shift left */
6121 static void handle_scalar_simd_shli(DisasContext *s, bool insert,
6122                                     int immh, int immb, int opcode,
6123                                     int rn, int rd)
6124 {
6125     int size = 32 - clz32(immh) - 1;
6126     int immhb = immh << 3 | immb;
6127     int shift = immhb - (8 << size);
6128     TCGv_i64 tcg_rn = new_tmp_a64(s);
6129     TCGv_i64 tcg_rd = new_tmp_a64(s);
6130
6131     if (!extract32(immh, 3, 1)) {
6132         unallocated_encoding(s);
6133         return;
6134     }
6135
6136     if (!fp_access_check(s)) {
6137         return;
6138     }
6139
6140     tcg_rn = read_fp_dreg(s, rn);
6141     tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
6142
6143     handle_shli_with_ins(tcg_rd, tcg_rn, insert, shift);
6144
6145     write_fp_dreg(s, rd, tcg_rd);
6146
6147     tcg_temp_free_i64(tcg_rn);
6148     tcg_temp_free_i64(tcg_rd);
6149 }
6150
6151 /* SQSHRN/SQSHRUN - Saturating (signed/unsigned) shift right with
6152  * (signed/unsigned) narrowing */
6153 static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
6154                                    bool is_u_shift, bool is_u_narrow,
6155                                    int immh, int immb, int opcode,
6156                                    int rn, int rd)
6157 {
6158     int immhb = immh << 3 | immb;
6159     int size = 32 - clz32(immh) - 1;
6160     int esize = 8 << size;
6161     int shift = (2 * esize) - immhb;
6162     int elements = is_scalar ? 1 : (64 / esize);
6163     bool round = extract32(opcode, 0, 1);
6164     TCGMemOp ldop = (size + 1) | (is_u_shift ? 0 : MO_SIGN);
6165     TCGv_i64 tcg_rn, tcg_rd, tcg_round;
6166     TCGv_i32 tcg_rd_narrowed;
6167     TCGv_i64 tcg_final;
6168
6169     static NeonGenNarrowEnvFn * const signed_narrow_fns[4][2] = {
6170         { gen_helper_neon_narrow_sat_s8,
6171           gen_helper_neon_unarrow_sat8 },
6172         { gen_helper_neon_narrow_sat_s16,
6173           gen_helper_neon_unarrow_sat16 },
6174         { gen_helper_neon_narrow_sat_s32,
6175           gen_helper_neon_unarrow_sat32 },
6176         { NULL, NULL },
6177     };
6178     static NeonGenNarrowEnvFn * const unsigned_narrow_fns[4] = {
6179         gen_helper_neon_narrow_sat_u8,
6180         gen_helper_neon_narrow_sat_u16,
6181         gen_helper_neon_narrow_sat_u32,
6182         NULL
6183     };
6184     NeonGenNarrowEnvFn *narrowfn;
6185
6186     int i;
6187
6188     assert(size < 4);
6189
6190     if (extract32(immh, 3, 1)) {
6191         unallocated_encoding(s);
6192         return;
6193     }
6194
6195     if (!fp_access_check(s)) {
6196         return;
6197     }
6198
6199     if (is_u_shift) {
6200         narrowfn = unsigned_narrow_fns[size];
6201     } else {
6202         narrowfn = signed_narrow_fns[size][is_u_narrow ? 1 : 0];
6203     }
6204
6205     tcg_rn = tcg_temp_new_i64();
6206     tcg_rd = tcg_temp_new_i64();
6207     tcg_rd_narrowed = tcg_temp_new_i32();
6208     tcg_final = tcg_const_i64(0);
6209
6210     if (round) {
6211         uint64_t round_const = 1ULL << (shift - 1);
6212         tcg_round = tcg_const_i64(round_const);
6213     } else {
6214         TCGV_UNUSED_I64(tcg_round);
6215     }
6216
6217     for (i = 0; i < elements; i++) {
6218         read_vec_element(s, tcg_rn, rn, i, ldop);
6219         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
6220                                 false, is_u_shift, size+1, shift);
6221         narrowfn(tcg_rd_narrowed, cpu_env, tcg_rd);
6222         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd_narrowed);
6223         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
6224     }
6225
6226     if (!is_q) {
6227         clear_vec_high(s, rd);
6228         write_vec_element(s, tcg_final, rd, 0, MO_64);
6229     } else {
6230         write_vec_element(s, tcg_final, rd, 1, MO_64);
6231     }
6232
6233     if (round) {
6234         tcg_temp_free_i64(tcg_round);
6235     }
6236     tcg_temp_free_i64(tcg_rn);
6237     tcg_temp_free_i64(tcg_rd);
6238     tcg_temp_free_i32(tcg_rd_narrowed);
6239     tcg_temp_free_i64(tcg_final);
6240     return;
6241 }
6242
6243 /* SQSHLU, UQSHL, SQSHL: saturating left shifts */
6244 static void handle_simd_qshl(DisasContext *s, bool scalar, bool is_q,
6245                              bool src_unsigned, bool dst_unsigned,
6246                              int immh, int immb, int rn, int rd)
6247 {
6248     int immhb = immh << 3 | immb;
6249     int size = 32 - clz32(immh) - 1;
6250     int shift = immhb - (8 << size);
6251     int pass;
6252
6253     assert(immh != 0);
6254     assert(!(scalar && is_q));
6255
6256     if (!scalar) {
6257         if (!is_q && extract32(immh, 3, 1)) {
6258             unallocated_encoding(s);
6259             return;
6260         }
6261
6262         /* Since we use the variable-shift helpers we must
6263          * replicate the shift count into each element of
6264          * the tcg_shift value.
6265          */
6266         switch (size) {
6267         case 0:
6268             shift |= shift << 8;
6269             /* fall through */
6270         case 1:
6271             shift |= shift << 16;
6272             break;
6273         case 2:
6274         case 3:
6275             break;
6276         default:
6277             g_assert_not_reached();
6278         }
6279     }
6280
6281     if (!fp_access_check(s)) {
6282         return;
6283     }
6284
6285     if (size == 3) {
6286         TCGv_i64 tcg_shift = tcg_const_i64(shift);
6287         static NeonGenTwo64OpEnvFn * const fns[2][2] = {
6288             { gen_helper_neon_qshl_s64, gen_helper_neon_qshlu_s64 },
6289             { NULL, gen_helper_neon_qshl_u64 },
6290         };
6291         NeonGenTwo64OpEnvFn *genfn = fns[src_unsigned][dst_unsigned];
6292         int maxpass = is_q ? 2 : 1;
6293
6294         for (pass = 0; pass < maxpass; pass++) {
6295             TCGv_i64 tcg_op = tcg_temp_new_i64();
6296
6297             read_vec_element(s, tcg_op, rn, pass, MO_64);
6298             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
6299             write_vec_element(s, tcg_op, rd, pass, MO_64);
6300
6301             tcg_temp_free_i64(tcg_op);
6302         }
6303         tcg_temp_free_i64(tcg_shift);
6304
6305         if (!is_q) {
6306             clear_vec_high(s, rd);
6307         }
6308     } else {
6309         TCGv_i32 tcg_shift = tcg_const_i32(shift);
6310         static NeonGenTwoOpEnvFn * const fns[2][2][3] = {
6311             {
6312                 { gen_helper_neon_qshl_s8,
6313                   gen_helper_neon_qshl_s16,
6314                   gen_helper_neon_qshl_s32 },
6315                 { gen_helper_neon_qshlu_s8,
6316                   gen_helper_neon_qshlu_s16,
6317                   gen_helper_neon_qshlu_s32 }
6318             }, {
6319                 { NULL, NULL, NULL },
6320                 { gen_helper_neon_qshl_u8,
6321                   gen_helper_neon_qshl_u16,
6322                   gen_helper_neon_qshl_u32 }
6323             }
6324         };
6325         NeonGenTwoOpEnvFn *genfn = fns[src_unsigned][dst_unsigned][size];
6326         TCGMemOp memop = scalar ? size : MO_32;
6327         int maxpass = scalar ? 1 : is_q ? 4 : 2;
6328
6329         for (pass = 0; pass < maxpass; pass++) {
6330             TCGv_i32 tcg_op = tcg_temp_new_i32();
6331
6332             read_vec_element_i32(s, tcg_op, rn, pass, memop);
6333             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
6334             if (scalar) {
6335                 switch (size) {
6336                 case 0:
6337                     tcg_gen_ext8u_i32(tcg_op, tcg_op);
6338                     break;
6339                 case 1:
6340                     tcg_gen_ext16u_i32(tcg_op, tcg_op);
6341                     break;
6342                 case 2:
6343                     break;
6344                 default:
6345                     g_assert_not_reached();
6346                 }
6347                 write_fp_sreg(s, rd, tcg_op);
6348             } else {
6349                 write_vec_element_i32(s, tcg_op, rd, pass, MO_32);
6350             }
6351
6352             tcg_temp_free_i32(tcg_op);
6353         }
6354         tcg_temp_free_i32(tcg_shift);
6355
6356         if (!is_q && !scalar) {
6357             clear_vec_high(s, rd);
6358         }
6359     }
6360 }
6361
6362 /* Common vector code for handling integer to FP conversion */
6363 static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
6364                                    int elements, int is_signed,
6365                                    int fracbits, int size)
6366 {
6367     bool is_double = size == 3 ? true : false;
6368     TCGv_ptr tcg_fpst = get_fpstatus_ptr();
6369     TCGv_i32 tcg_shift = tcg_const_i32(fracbits);
6370     TCGv_i64 tcg_int = tcg_temp_new_i64();
6371     TCGMemOp mop = size | (is_signed ? MO_SIGN : 0);
6372     int pass;
6373
6374     for (pass = 0; pass < elements; pass++) {
6375         read_vec_element(s, tcg_int, rn, pass, mop);
6376
6377         if (is_double) {
6378             TCGv_i64 tcg_double = tcg_temp_new_i64();
6379             if (is_signed) {
6380                 gen_helper_vfp_sqtod(tcg_double, tcg_int,
6381                                      tcg_shift, tcg_fpst);
6382             } else {
6383                 gen_helper_vfp_uqtod(tcg_double, tcg_int,
6384                                      tcg_shift, tcg_fpst);
6385             }
6386             if (elements == 1) {
6387                 write_fp_dreg(s, rd, tcg_double);
6388             } else {
6389                 write_vec_element(s, tcg_double, rd, pass, MO_64);
6390             }
6391             tcg_temp_free_i64(tcg_double);
6392         } else {
6393             TCGv_i32 tcg_single = tcg_temp_new_i32();
6394             if (is_signed) {
6395                 gen_helper_vfp_sqtos(tcg_single, tcg_int,
6396                                      tcg_shift, tcg_fpst);
6397             } else {
6398                 gen_helper_vfp_uqtos(tcg_single, tcg_int,
6399                                      tcg_shift, tcg_fpst);
6400             }
6401             if (elements == 1) {
6402                 write_fp_sreg(s, rd, tcg_single);
6403             } else {
6404                 write_vec_element_i32(s, tcg_single, rd, pass, MO_32);
6405             }
6406             tcg_temp_free_i32(tcg_single);
6407         }
6408     }
6409
6410     if (!is_double && elements == 2) {
6411         clear_vec_high(s, rd);
6412     }
6413
6414     tcg_temp_free_i64(tcg_int);
6415     tcg_temp_free_ptr(tcg_fpst);
6416     tcg_temp_free_i32(tcg_shift);
6417 }
6418
6419 /* UCVTF/SCVTF - Integer to FP conversion */
6420 static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
6421                                          bool is_q, bool is_u,
6422                                          int immh, int immb, int opcode,
6423                                          int rn, int rd)
6424 {
6425     bool is_double = extract32(immh, 3, 1);
6426     int size = is_double ? MO_64 : MO_32;
6427     int elements;
6428     int immhb = immh << 3 | immb;
6429     int fracbits = (is_double ? 128 : 64) - immhb;
6430
6431     if (!extract32(immh, 2, 2)) {
6432         unallocated_encoding(s);
6433         return;
6434     }
6435
6436     if (is_scalar) {
6437         elements = 1;
6438     } else {
6439         elements = is_double ? 2 : is_q ? 4 : 2;
6440         if (is_double && !is_q) {
6441             unallocated_encoding(s);
6442             return;
6443         }
6444     }
6445
6446     if (!fp_access_check(s)) {
6447         return;
6448     }
6449
6450     /* immh == 0 would be a failure of the decode logic */
6451     g_assert(immh);
6452
6453     handle_simd_intfp_conv(s, rd, rn, elements, !is_u, fracbits, size);
6454 }
6455
6456 /* FCVTZS, FVCVTZU - FP to fixedpoint conversion */
6457 static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
6458                                          bool is_q, bool is_u,
6459                                          int immh, int immb, int rn, int rd)
6460 {
6461     bool is_double = extract32(immh, 3, 1);
6462     int immhb = immh << 3 | immb;
6463     int fracbits = (is_double ? 128 : 64) - immhb;
6464     int pass;
6465     TCGv_ptr tcg_fpstatus;
6466     TCGv_i32 tcg_rmode, tcg_shift;
6467
6468     if (!extract32(immh, 2, 2)) {
6469         unallocated_encoding(s);
6470         return;
6471     }
6472
6473     if (!is_scalar && !is_q && is_double) {
6474         unallocated_encoding(s);
6475         return;
6476     }
6477
6478     if (!fp_access_check(s)) {
6479         return;
6480     }
6481
6482     assert(!(is_scalar && is_q));
6483
6484     tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
6485     gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
6486     tcg_fpstatus = get_fpstatus_ptr();
6487     tcg_shift = tcg_const_i32(fracbits);
6488
6489     if (is_double) {
6490         int maxpass = is_scalar ? 1 : is_q ? 2 : 1;
6491
6492         for (pass = 0; pass < maxpass; pass++) {
6493             TCGv_i64 tcg_op = tcg_temp_new_i64();
6494
6495             read_vec_element(s, tcg_op, rn, pass, MO_64);
6496             if (is_u) {
6497                 gen_helper_vfp_touqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
6498             } else {
6499                 gen_helper_vfp_tosqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
6500             }
6501             write_vec_element(s, tcg_op, rd, pass, MO_64);
6502             tcg_temp_free_i64(tcg_op);
6503         }
6504         if (!is_q) {
6505             clear_vec_high(s, rd);
6506         }
6507     } else {
6508         int maxpass = is_scalar ? 1 : is_q ? 4 : 2;
6509         for (pass = 0; pass < maxpass; pass++) {
6510             TCGv_i32 tcg_op = tcg_temp_new_i32();
6511
6512             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
6513             if (is_u) {
6514                 gen_helper_vfp_touls(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
6515             } else {
6516                 gen_helper_vfp_tosls(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
6517             }
6518             if (is_scalar) {
6519                 write_fp_sreg(s, rd, tcg_op);
6520             } else {
6521                 write_vec_element_i32(s, tcg_op, rd, pass, MO_32);
6522             }
6523             tcg_temp_free_i32(tcg_op);
6524         }
6525         if (!is_q && !is_scalar) {
6526             clear_vec_high(s, rd);
6527         }
6528     }
6529
6530     tcg_temp_free_ptr(tcg_fpstatus);
6531     tcg_temp_free_i32(tcg_shift);
6532     gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
6533     tcg_temp_free_i32(tcg_rmode);
6534 }
6535
6536 /* C3.6.9 AdvSIMD scalar shift by immediate
6537  *  31 30  29 28         23 22  19 18  16 15    11  10 9    5 4    0
6538  * +-----+---+-------------+------+------+--------+---+------+------+
6539  * | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
6540  * +-----+---+-------------+------+------+--------+---+------+------+
6541  *
6542  * This is the scalar version so it works on a fixed sized registers
6543  */
6544 static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn)
6545 {
6546     int rd = extract32(insn, 0, 5);
6547     int rn = extract32(insn, 5, 5);
6548     int opcode = extract32(insn, 11, 5);
6549     int immb = extract32(insn, 16, 3);
6550     int immh = extract32(insn, 19, 4);
6551     bool is_u = extract32(insn, 29, 1);
6552
6553     if (immh == 0) {
6554         unallocated_encoding(s);
6555         return;
6556     }
6557
6558     switch (opcode) {
6559     case 0x08: /* SRI */
6560         if (!is_u) {
6561             unallocated_encoding(s);
6562             return;
6563         }
6564         /* fall through */
6565     case 0x00: /* SSHR / USHR */
6566     case 0x02: /* SSRA / USRA */
6567     case 0x04: /* SRSHR / URSHR */
6568     case 0x06: /* SRSRA / URSRA */
6569         handle_scalar_simd_shri(s, is_u, immh, immb, opcode, rn, rd);
6570         break;
6571     case 0x0a: /* SHL / SLI */
6572         handle_scalar_simd_shli(s, is_u, immh, immb, opcode, rn, rd);
6573         break;
6574     case 0x1c: /* SCVTF, UCVTF */
6575         handle_simd_shift_intfp_conv(s, true, false, is_u, immh, immb,
6576                                      opcode, rn, rd);
6577         break;
6578     case 0x10: /* SQSHRUN, SQSHRUN2 */
6579     case 0x11: /* SQRSHRUN, SQRSHRUN2 */
6580         if (!is_u) {
6581             unallocated_encoding(s);
6582             return;
6583         }
6584         handle_vec_simd_sqshrn(s, true, false, false, true,
6585                                immh, immb, opcode, rn, rd);
6586         break;
6587     case 0x12: /* SQSHRN, SQSHRN2, UQSHRN */
6588     case 0x13: /* SQRSHRN, SQRSHRN2, UQRSHRN, UQRSHRN2 */
6589         handle_vec_simd_sqshrn(s, true, false, is_u, is_u,
6590                                immh, immb, opcode, rn, rd);
6591         break;
6592     case 0xc: /* SQSHLU */
6593         if (!is_u) {
6594             unallocated_encoding(s);
6595             return;
6596         }
6597         handle_simd_qshl(s, true, false, false, true, immh, immb, rn, rd);
6598         break;
6599     case 0xe: /* SQSHL, UQSHL */
6600         handle_simd_qshl(s, true, false, is_u, is_u, immh, immb, rn, rd);
6601         break;
6602     case 0x1f: /* FCVTZS, FCVTZU */
6603         handle_simd_shift_fpint_conv(s, true, false, is_u, immh, immb, rn, rd);
6604         break;
6605     default:
6606         unallocated_encoding(s);
6607         break;
6608     }
6609 }
6610
6611 /* C3.6.10 AdvSIMD scalar three different
6612  *  31 30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
6613  * +-----+---+-----------+------+---+------+--------+-----+------+------+
6614  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
6615  * +-----+---+-----------+------+---+------+--------+-----+------+------+
6616  */
6617 static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
6618 {
6619     bool is_u = extract32(insn, 29, 1);
6620     int size = extract32(insn, 22, 2);
6621     int opcode = extract32(insn, 12, 4);
6622     int rm = extract32(insn, 16, 5);
6623     int rn = extract32(insn, 5, 5);
6624     int rd = extract32(insn, 0, 5);
6625
6626     if (is_u) {
6627         unallocated_encoding(s);
6628         return;
6629     }
6630
6631     switch (opcode) {
6632     case 0x9: /* SQDMLAL, SQDMLAL2 */
6633     case 0xb: /* SQDMLSL, SQDMLSL2 */
6634     case 0xd: /* SQDMULL, SQDMULL2 */
6635         if (size == 0 || size == 3) {
6636             unallocated_encoding(s);
6637             return;
6638         }
6639         break;
6640     default:
6641         unallocated_encoding(s);
6642         return;
6643     }
6644
6645     if (!fp_access_check(s)) {
6646         return;
6647     }
6648
6649     if (size == 2) {
6650         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
6651         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
6652         TCGv_i64 tcg_res = tcg_temp_new_i64();
6653
6654         read_vec_element(s, tcg_op1, rn, 0, MO_32 | MO_SIGN);
6655         read_vec_element(s, tcg_op2, rm, 0, MO_32 | MO_SIGN);
6656
6657         tcg_gen_mul_i64(tcg_res, tcg_op1, tcg_op2);
6658         gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env, tcg_res, tcg_res);
6659
6660         switch (opcode) {
6661         case 0xd: /* SQDMULL, SQDMULL2 */
6662             break;
6663         case 0xb: /* SQDMLSL, SQDMLSL2 */
6664             tcg_gen_neg_i64(tcg_res, tcg_res);
6665             /* fall through */
6666         case 0x9: /* SQDMLAL, SQDMLAL2 */
6667             read_vec_element(s, tcg_op1, rd, 0, MO_64);
6668             gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env,
6669                                               tcg_res, tcg_op1);
6670             break;
6671         default:
6672             g_assert_not_reached();
6673         }
6674
6675         write_fp_dreg(s, rd, tcg_res);
6676
6677         tcg_temp_free_i64(tcg_op1);
6678         tcg_temp_free_i64(tcg_op2);
6679         tcg_temp_free_i64(tcg_res);
6680     } else {
6681         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
6682         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
6683         TCGv_i64 tcg_res = tcg_temp_new_i64();
6684
6685         read_vec_element_i32(s, tcg_op1, rn, 0, MO_16);
6686         read_vec_element_i32(s, tcg_op2, rm, 0, MO_16);
6687
6688         gen_helper_neon_mull_s16(tcg_res, tcg_op1, tcg_op2);
6689         gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env, tcg_res, tcg_res);
6690
6691         switch (opcode) {
6692         case 0xd: /* SQDMULL, SQDMULL2 */
6693             break;
6694         case 0xb: /* SQDMLSL, SQDMLSL2 */
6695             gen_helper_neon_negl_u32(tcg_res, tcg_res);
6696             /* fall through */
6697         case 0x9: /* SQDMLAL, SQDMLAL2 */
6698         {
6699             TCGv_i64 tcg_op3 = tcg_temp_new_i64();
6700             read_vec_element(s, tcg_op3, rd, 0, MO_32);
6701             gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env,
6702                                               tcg_res, tcg_op3);
6703             tcg_temp_free_i64(tcg_op3);
6704             break;
6705         }
6706         default:
6707             g_assert_not_reached();
6708         }
6709
6710         tcg_gen_ext32u_i64(tcg_res, tcg_res);
6711         write_fp_dreg(s, rd, tcg_res);
6712
6713         tcg_temp_free_i32(tcg_op1);
6714         tcg_temp_free_i32(tcg_op2);
6715         tcg_temp_free_i64(tcg_res);
6716     }
6717 }
6718
6719 static void handle_3same_64(DisasContext *s, int opcode, bool u,
6720                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn, TCGv_i64 tcg_rm)
6721 {
6722     /* Handle 64x64->64 opcodes which are shared between the scalar
6723      * and vector 3-same groups. We cover every opcode where size == 3
6724      * is valid in either the three-reg-same (integer, not pairwise)
6725      * or scalar-three-reg-same groups. (Some opcodes are not yet
6726      * implemented.)
6727      */
6728     TCGCond cond;
6729
6730     switch (opcode) {
6731     case 0x1: /* SQADD */
6732         if (u) {
6733             gen_helper_neon_qadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
6734         } else {
6735             gen_helper_neon_qadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
6736         }
6737         break;
6738     case 0x5: /* SQSUB */
6739         if (u) {
6740             gen_helper_neon_qsub_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
6741         } else {
6742             gen_helper_neon_qsub_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
6743         }
6744         break;
6745     case 0x6: /* CMGT, CMHI */
6746         /* 64 bit integer comparison, result = test ? (2^64 - 1) : 0.
6747          * We implement this using setcond (test) and then negating.
6748          */
6749         cond = u ? TCG_COND_GTU : TCG_COND_GT;
6750     do_cmop:
6751         tcg_gen_setcond_i64(cond, tcg_rd, tcg_rn, tcg_rm);
6752         tcg_gen_neg_i64(tcg_rd, tcg_rd);
6753         break;
6754     case 0x7: /* CMGE, CMHS */
6755         cond = u ? TCG_COND_GEU : TCG_COND_GE;
6756         goto do_cmop;
6757     case 0x11: /* CMTST, CMEQ */
6758         if (u) {
6759             cond = TCG_COND_EQ;
6760             goto do_cmop;
6761         }
6762         /* CMTST : test is "if (X & Y != 0)". */
6763         tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
6764         tcg_gen_setcondi_i64(TCG_COND_NE, tcg_rd, tcg_rd, 0);
6765         tcg_gen_neg_i64(tcg_rd, tcg_rd);
6766         break;
6767     case 0x8: /* SSHL, USHL */
6768         if (u) {
6769             gen_helper_neon_shl_u64(tcg_rd, tcg_rn, tcg_rm);
6770         } else {
6771             gen_helper_neon_shl_s64(tcg_rd, tcg_rn, tcg_rm);
6772         }
6773         break;
6774     case 0x9: /* SQSHL, UQSHL */
6775         if (u) {
6776             gen_helper_neon_qshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
6777         } else {
6778             gen_helper_neon_qshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
6779         }
6780         break;
6781     case 0xa: /* SRSHL, URSHL */
6782         if (u) {
6783             gen_helper_neon_rshl_u64(tcg_rd, tcg_rn, tcg_rm);
6784         } else {
6785             gen_helper_neon_rshl_s64(tcg_rd, tcg_rn, tcg_rm);
6786         }
6787         break;
6788     case 0xb: /* SQRSHL, UQRSHL */
6789         if (u) {
6790             gen_helper_neon_qrshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
6791         } else {
6792             gen_helper_neon_qrshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
6793         }
6794         break;
6795     case 0x10: /* ADD, SUB */
6796         if (u) {
6797             tcg_gen_sub_i64(tcg_rd, tcg_rn, tcg_rm);
6798         } else {
6799             tcg_gen_add_i64(tcg_rd, tcg_rn, tcg_rm);
6800         }
6801         break;
6802     default:
6803         g_assert_not_reached();
6804     }
6805 }
6806
6807 /* Handle the 3-same-operands float operations; shared by the scalar
6808  * and vector encodings. The caller must filter out any encodings
6809  * not allocated for the encoding it is dealing with.
6810  */
6811 static void handle_3same_float(DisasContext *s, int size, int elements,
6812                                int fpopcode, int rd, int rn, int rm)
6813 {
6814     int pass;
6815     TCGv_ptr fpst = get_fpstatus_ptr();
6816
6817     for (pass = 0; pass < elements; pass++) {
6818         if (size) {
6819             /* Double */
6820             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
6821             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
6822             TCGv_i64 tcg_res = tcg_temp_new_i64();
6823
6824             read_vec_element(s, tcg_op1, rn, pass, MO_64);
6825             read_vec_element(s, tcg_op2, rm, pass, MO_64);
6826
6827             switch (fpopcode) {
6828             case 0x39: /* FMLS */
6829                 /* As usual for ARM, separate negation for fused multiply-add */
6830                 gen_helper_vfp_negd(tcg_op1, tcg_op1);
6831                 /* fall through */
6832             case 0x19: /* FMLA */
6833                 read_vec_element(s, tcg_res, rd, pass, MO_64);
6834                 gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2,
6835                                        tcg_res, fpst);
6836                 break;
6837             case 0x18: /* FMAXNM */
6838                 gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
6839                 break;
6840             case 0x1a: /* FADD */
6841                 gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
6842                 break;
6843             case 0x1b: /* FMULX */
6844                 gen_helper_vfp_mulxd(tcg_res, tcg_op1, tcg_op2, fpst);
6845                 break;
6846             case 0x1c: /* FCMEQ */
6847                 gen_helper_neon_ceq_f64(tcg_res, tcg_op1, tcg_op2, fpst);
6848                 break;
6849             case 0x1e: /* FMAX */
6850                 gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
6851                 break;
6852             case 0x1f: /* FRECPS */
6853                 gen_helper_recpsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
6854                 break;
6855             case 0x38: /* FMINNM */
6856                 gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
6857                 break;
6858             case 0x3a: /* FSUB */
6859                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
6860                 break;
6861             case 0x3e: /* FMIN */
6862                 gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
6863                 break;
6864             case 0x3f: /* FRSQRTS */
6865                 gen_helper_rsqrtsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
6866                 break;
6867             case 0x5b: /* FMUL */
6868                 gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
6869                 break;
6870             case 0x5c: /* FCMGE */
6871                 gen_helper_neon_cge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
6872                 break;
6873             case 0x5d: /* FACGE */
6874                 gen_helper_neon_acge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
6875                 break;
6876             case 0x5f: /* FDIV */
6877                 gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
6878                 break;
6879             case 0x7a: /* FABD */
6880                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
6881                 gen_helper_vfp_absd(tcg_res, tcg_res);
6882                 break;
6883             case 0x7c: /* FCMGT */
6884                 gen_helper_neon_cgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
6885                 break;
6886             case 0x7d: /* FACGT */
6887                 gen_helper_neon_acgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
6888                 break;
6889             default:
6890                 g_assert_not_reached();
6891             }
6892
6893             write_vec_element(s, tcg_res, rd, pass, MO_64);
6894
6895             tcg_temp_free_i64(tcg_res);
6896             tcg_temp_free_i64(tcg_op1);
6897             tcg_temp_free_i64(tcg_op2);
6898         } else {
6899             /* Single */
6900             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
6901             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
6902             TCGv_i32 tcg_res = tcg_temp_new_i32();
6903
6904             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
6905             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
6906
6907             switch (fpopcode) {
6908             case 0x39: /* FMLS */
6909                 /* As usual for ARM, separate negation for fused multiply-add */
6910                 gen_helper_vfp_negs(tcg_op1, tcg_op1);
6911                 /* fall through */
6912             case 0x19: /* FMLA */
6913                 read_vec_element_i32(s, tcg_res, rd, pass, MO_32);
6914                 gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2,
6915                                        tcg_res, fpst);
6916                 break;
6917             case 0x1a: /* FADD */
6918                 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
6919                 break;
6920             case 0x1b: /* FMULX */
6921                 gen_helper_vfp_mulxs(tcg_res, tcg_op1, tcg_op2, fpst);
6922                 break;
6923             case 0x1c: /* FCMEQ */
6924                 gen_helper_neon_ceq_f32(tcg_res, tcg_op1, tcg_op2, fpst);
6925                 break;
6926             case 0x1e: /* FMAX */
6927                 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
6928                 break;
6929             case 0x1f: /* FRECPS */
6930                 gen_helper_recpsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
6931                 break;
6932             case 0x18: /* FMAXNM */
6933                 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
6934                 break;
6935             case 0x38: /* FMINNM */
6936                 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
6937                 break;
6938             case 0x3a: /* FSUB */
6939                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
6940                 break;
6941             case 0x3e: /* FMIN */
6942                 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
6943                 break;
6944             case 0x3f: /* FRSQRTS */
6945                 gen_helper_rsqrtsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
6946                 break;
6947             case 0x5b: /* FMUL */
6948                 gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
6949                 break;
6950             case 0x5c: /* FCMGE */
6951                 gen_helper_neon_cge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
6952                 break;
6953             case 0x5d: /* FACGE */
6954                 gen_helper_neon_acge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
6955                 break;
6956             case 0x5f: /* FDIV */
6957                 gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
6958                 break;
6959             case 0x7a: /* FABD */
6960                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
6961                 gen_helper_vfp_abss(tcg_res, tcg_res);
6962                 break;
6963             case 0x7c: /* FCMGT */
6964                 gen_helper_neon_cgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
6965                 break;
6966             case 0x7d: /* FACGT */
6967                 gen_helper_neon_acgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
6968                 break;
6969             default:
6970                 g_assert_not_reached();
6971             }
6972
6973             if (elements == 1) {
6974                 /* scalar single so clear high part */
6975                 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
6976
6977                 tcg_gen_extu_i32_i64(tcg_tmp, tcg_res);
6978                 write_vec_element(s, tcg_tmp, rd, pass, MO_64);
6979                 tcg_temp_free_i64(tcg_tmp);
6980             } else {
6981                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
6982             }
6983
6984             tcg_temp_free_i32(tcg_res);
6985             tcg_temp_free_i32(tcg_op1);
6986             tcg_temp_free_i32(tcg_op2);
6987         }
6988     }
6989
6990     tcg_temp_free_ptr(fpst);
6991
6992     if ((elements << size) < 4) {
6993         /* scalar, or non-quad vector op */
6994         clear_vec_high(s, rd);
6995     }
6996 }
6997
6998 /* C3.6.11 AdvSIMD scalar three same
6999  *  31 30  29 28       24 23  22  21 20  16 15    11  10 9    5 4    0
7000  * +-----+---+-----------+------+---+------+--------+---+------+------+
7001  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
7002  * +-----+---+-----------+------+---+------+--------+---+------+------+
7003  */
7004 static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
7005 {
7006     int rd = extract32(insn, 0, 5);
7007     int rn = extract32(insn, 5, 5);
7008     int opcode = extract32(insn, 11, 5);
7009     int rm = extract32(insn, 16, 5);
7010     int size = extract32(insn, 22, 2);
7011     bool u = extract32(insn, 29, 1);
7012     TCGv_i64 tcg_rd;
7013
7014     if (opcode >= 0x18) {
7015         /* Floating point: U, size[1] and opcode indicate operation */
7016         int fpopcode = opcode | (extract32(size, 1, 1) << 5) | (u << 6);
7017         switch (fpopcode) {
7018         case 0x1b: /* FMULX */
7019         case 0x1f: /* FRECPS */
7020         case 0x3f: /* FRSQRTS */
7021         case 0x5d: /* FACGE */
7022         case 0x7d: /* FACGT */
7023         case 0x1c: /* FCMEQ */
7024         case 0x5c: /* FCMGE */
7025         case 0x7c: /* FCMGT */
7026         case 0x7a: /* FABD */
7027             break;
7028         default:
7029             unallocated_encoding(s);
7030             return;
7031         }
7032
7033         if (!fp_access_check(s)) {
7034             return;
7035         }
7036
7037         handle_3same_float(s, extract32(size, 0, 1), 1, fpopcode, rd, rn, rm);
7038         return;
7039     }
7040
7041     switch (opcode) {
7042     case 0x1: /* SQADD, UQADD */
7043     case 0x5: /* SQSUB, UQSUB */
7044     case 0x9: /* SQSHL, UQSHL */
7045     case 0xb: /* SQRSHL, UQRSHL */
7046         break;
7047     case 0x8: /* SSHL, USHL */
7048     case 0xa: /* SRSHL, URSHL */
7049     case 0x6: /* CMGT, CMHI */
7050     case 0x7: /* CMGE, CMHS */
7051     case 0x11: /* CMTST, CMEQ */
7052     case 0x10: /* ADD, SUB (vector) */
7053         if (size != 3) {
7054             unallocated_encoding(s);
7055             return;
7056         }
7057         break;
7058     case 0x16: /* SQDMULH, SQRDMULH (vector) */
7059         if (size != 1 && size != 2) {
7060             unallocated_encoding(s);
7061             return;
7062         }
7063         break;
7064     default:
7065         unallocated_encoding(s);
7066         return;
7067     }
7068
7069     if (!fp_access_check(s)) {
7070         return;
7071     }
7072
7073     tcg_rd = tcg_temp_new_i64();
7074
7075     if (size == 3) {
7076         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
7077         TCGv_i64 tcg_rm = read_fp_dreg(s, rm);
7078
7079         handle_3same_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rm);
7080         tcg_temp_free_i64(tcg_rn);
7081         tcg_temp_free_i64(tcg_rm);
7082     } else {
7083         /* Do a single operation on the lowest element in the vector.
7084          * We use the standard Neon helpers and rely on 0 OP 0 == 0 with
7085          * no side effects for all these operations.
7086          * OPTME: special-purpose helpers would avoid doing some
7087          * unnecessary work in the helper for the 8 and 16 bit cases.
7088          */
7089         NeonGenTwoOpEnvFn *genenvfn;
7090         TCGv_i32 tcg_rn = tcg_temp_new_i32();
7091         TCGv_i32 tcg_rm = tcg_temp_new_i32();
7092         TCGv_i32 tcg_rd32 = tcg_temp_new_i32();
7093
7094         read_vec_element_i32(s, tcg_rn, rn, 0, size);
7095         read_vec_element_i32(s, tcg_rm, rm, 0, size);
7096
7097         switch (opcode) {
7098         case 0x1: /* SQADD, UQADD */
7099         {
7100             static NeonGenTwoOpEnvFn * const fns[3][2] = {
7101                 { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 },
7102                 { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 },
7103                 { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 },
7104             };
7105             genenvfn = fns[size][u];
7106             break;
7107         }
7108         case 0x5: /* SQSUB, UQSUB */
7109         {
7110             static NeonGenTwoOpEnvFn * const fns[3][2] = {
7111                 { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 },
7112                 { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 },
7113                 { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 },
7114             };
7115             genenvfn = fns[size][u];
7116             break;
7117         }
7118         case 0x9: /* SQSHL, UQSHL */
7119         {
7120             static NeonGenTwoOpEnvFn * const fns[3][2] = {
7121                 { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
7122                 { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
7123                 { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
7124             };
7125             genenvfn = fns[size][u];
7126             break;
7127         }
7128         case 0xb: /* SQRSHL, UQRSHL */
7129         {
7130             static NeonGenTwoOpEnvFn * const fns[3][2] = {
7131                 { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
7132                 { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
7133                 { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
7134             };
7135             genenvfn = fns[size][u];
7136             break;
7137         }
7138         case 0x16: /* SQDMULH, SQRDMULH */
7139         {
7140             static NeonGenTwoOpEnvFn * const fns[2][2] = {
7141                 { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
7142                 { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
7143             };
7144             assert(size == 1 || size == 2);
7145             genenvfn = fns[size - 1][u];
7146             break;
7147         }
7148         default:
7149             g_assert_not_reached();
7150         }
7151
7152         genenvfn(tcg_rd32, cpu_env, tcg_rn, tcg_rm);
7153         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd32);
7154         tcg_temp_free_i32(tcg_rd32);
7155         tcg_temp_free_i32(tcg_rn);
7156         tcg_temp_free_i32(tcg_rm);
7157     }
7158
7159     write_fp_dreg(s, rd, tcg_rd);
7160
7161     tcg_temp_free_i64(tcg_rd);
7162 }
7163
7164 static void handle_2misc_64(DisasContext *s, int opcode, bool u,
7165                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
7166                             TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
7167 {
7168     /* Handle 64->64 opcodes which are shared between the scalar and
7169      * vector 2-reg-misc groups. We cover every integer opcode where size == 3
7170      * is valid in either group and also the double-precision fp ops.
7171      * The caller only need provide tcg_rmode and tcg_fpstatus if the op
7172      * requires them.
7173      */
7174     TCGCond cond;
7175
7176     switch (opcode) {
7177     case 0x4: /* CLS, CLZ */
7178         if (u) {
7179             gen_helper_clz64(tcg_rd, tcg_rn);
7180         } else {
7181             gen_helper_cls64(tcg_rd, tcg_rn);
7182         }
7183         break;
7184     case 0x5: /* NOT */
7185         /* This opcode is shared with CNT and RBIT but we have earlier
7186          * enforced that size == 3 if and only if this is the NOT insn.
7187          */
7188         tcg_gen_not_i64(tcg_rd, tcg_rn);
7189         break;
7190     case 0x7: /* SQABS, SQNEG */
7191         if (u) {
7192             gen_helper_neon_qneg_s64(tcg_rd, cpu_env, tcg_rn);
7193         } else {
7194             gen_helper_neon_qabs_s64(tcg_rd, cpu_env, tcg_rn);
7195         }
7196         break;
7197     case 0xa: /* CMLT */
7198         /* 64 bit integer comparison against zero, result is
7199          * test ? (2^64 - 1) : 0. We implement via setcond(!test) and
7200          * subtracting 1.
7201          */
7202         cond = TCG_COND_LT;
7203     do_cmop:
7204         tcg_gen_setcondi_i64(cond, tcg_rd, tcg_rn, 0);
7205         tcg_gen_neg_i64(tcg_rd, tcg_rd);
7206         break;
7207     case 0x8: /* CMGT, CMGE */
7208         cond = u ? TCG_COND_GE : TCG_COND_GT;
7209         goto do_cmop;
7210     case 0x9: /* CMEQ, CMLE */
7211         cond = u ? TCG_COND_LE : TCG_COND_EQ;
7212         goto do_cmop;
7213     case 0xb: /* ABS, NEG */
7214         if (u) {
7215             tcg_gen_neg_i64(tcg_rd, tcg_rn);
7216         } else {
7217             TCGv_i64 tcg_zero = tcg_const_i64(0);
7218             tcg_gen_neg_i64(tcg_rd, tcg_rn);
7219             tcg_gen_movcond_i64(TCG_COND_GT, tcg_rd, tcg_rn, tcg_zero,
7220                                 tcg_rn, tcg_rd);
7221             tcg_temp_free_i64(tcg_zero);
7222         }
7223         break;
7224     case 0x2f: /* FABS */
7225         gen_helper_vfp_absd(tcg_rd, tcg_rn);
7226         break;
7227     case 0x6f: /* FNEG */
7228         gen_helper_vfp_negd(tcg_rd, tcg_rn);
7229         break;
7230     case 0x7f: /* FSQRT */
7231         gen_helper_vfp_sqrtd(tcg_rd, tcg_rn, cpu_env);
7232         break;
7233     case 0x1a: /* FCVTNS */
7234     case 0x1b: /* FCVTMS */
7235     case 0x1c: /* FCVTAS */
7236     case 0x3a: /* FCVTPS */
7237     case 0x3b: /* FCVTZS */
7238     {
7239         TCGv_i32 tcg_shift = tcg_const_i32(0);
7240         gen_helper_vfp_tosqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
7241         tcg_temp_free_i32(tcg_shift);
7242         break;
7243     }
7244     case 0x5a: /* FCVTNU */
7245     case 0x5b: /* FCVTMU */
7246     case 0x5c: /* FCVTAU */
7247     case 0x7a: /* FCVTPU */
7248     case 0x7b: /* FCVTZU */
7249     {
7250         TCGv_i32 tcg_shift = tcg_const_i32(0);
7251         gen_helper_vfp_touqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
7252         tcg_temp_free_i32(tcg_shift);
7253         break;
7254     }
7255     case 0x18: /* FRINTN */
7256     case 0x19: /* FRINTM */
7257     case 0x38: /* FRINTP */
7258     case 0x39: /* FRINTZ */
7259     case 0x58: /* FRINTA */
7260     case 0x79: /* FRINTI */
7261         gen_helper_rintd(tcg_rd, tcg_rn, tcg_fpstatus);
7262         break;
7263     case 0x59: /* FRINTX */
7264         gen_helper_rintd_exact(tcg_rd, tcg_rn, tcg_fpstatus);
7265         break;
7266     default:
7267         g_assert_not_reached();
7268     }
7269 }
7270
7271 static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
7272                                    bool is_scalar, bool is_u, bool is_q,
7273                                    int size, int rn, int rd)
7274 {
7275     bool is_double = (size == 3);
7276     TCGv_ptr fpst;
7277
7278     if (!fp_access_check(s)) {
7279         return;
7280     }
7281
7282     fpst = get_fpstatus_ptr();
7283
7284     if (is_double) {
7285         TCGv_i64 tcg_op = tcg_temp_new_i64();
7286         TCGv_i64 tcg_zero = tcg_const_i64(0);
7287         TCGv_i64 tcg_res = tcg_temp_new_i64();
7288         NeonGenTwoDoubleOPFn *genfn;
7289         bool swap = false;
7290         int pass;
7291
7292         switch (opcode) {
7293         case 0x2e: /* FCMLT (zero) */
7294             swap = true;
7295             /* fallthrough */
7296         case 0x2c: /* FCMGT (zero) */
7297             genfn = gen_helper_neon_cgt_f64;
7298             break;
7299         case 0x2d: /* FCMEQ (zero) */
7300             genfn = gen_helper_neon_ceq_f64;
7301             break;
7302         case 0x6d: /* FCMLE (zero) */
7303             swap = true;
7304             /* fall through */
7305         case 0x6c: /* FCMGE (zero) */
7306             genfn = gen_helper_neon_cge_f64;
7307             break;
7308         default:
7309             g_assert_not_reached();
7310         }
7311
7312         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
7313             read_vec_element(s, tcg_op, rn, pass, MO_64);
7314             if (swap) {
7315                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
7316             } else {
7317                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
7318             }
7319             write_vec_element(s, tcg_res, rd, pass, MO_64);
7320         }
7321         if (is_scalar) {
7322             clear_vec_high(s, rd);
7323         }
7324
7325         tcg_temp_free_i64(tcg_res);
7326         tcg_temp_free_i64(tcg_zero);
7327         tcg_temp_free_i64(tcg_op);
7328     } else {
7329         TCGv_i32 tcg_op = tcg_temp_new_i32();
7330         TCGv_i32 tcg_zero = tcg_const_i32(0);
7331         TCGv_i32 tcg_res = tcg_temp_new_i32();
7332         NeonGenTwoSingleOPFn *genfn;
7333         bool swap = false;
7334         int pass, maxpasses;
7335
7336         switch (opcode) {
7337         case 0x2e: /* FCMLT (zero) */
7338             swap = true;
7339             /* fall through */
7340         case 0x2c: /* FCMGT (zero) */
7341             genfn = gen_helper_neon_cgt_f32;
7342             break;
7343         case 0x2d: /* FCMEQ (zero) */
7344             genfn = gen_helper_neon_ceq_f32;
7345             break;
7346         case 0x6d: /* FCMLE (zero) */
7347             swap = true;
7348             /* fall through */
7349         case 0x6c: /* FCMGE (zero) */
7350             genfn = gen_helper_neon_cge_f32;
7351             break;
7352         default:
7353             g_assert_not_reached();
7354         }
7355
7356         if (is_scalar) {
7357             maxpasses = 1;
7358         } else {
7359             maxpasses = is_q ? 4 : 2;
7360         }
7361
7362         for (pass = 0; pass < maxpasses; pass++) {
7363             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
7364             if (swap) {
7365                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
7366             } else {
7367                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
7368             }
7369             if (is_scalar) {
7370                 write_fp_sreg(s, rd, tcg_res);
7371             } else {
7372                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
7373             }
7374         }
7375         tcg_temp_free_i32(tcg_res);
7376         tcg_temp_free_i32(tcg_zero);
7377         tcg_temp_free_i32(tcg_op);
7378         if (!is_q && !is_scalar) {
7379             clear_vec_high(s, rd);
7380         }
7381     }
7382
7383     tcg_temp_free_ptr(fpst);
7384 }
7385
7386 static void handle_2misc_reciprocal(DisasContext *s, int opcode,
7387                                     bool is_scalar, bool is_u, bool is_q,
7388                                     int size, int rn, int rd)
7389 {
7390     bool is_double = (size == 3);
7391     TCGv_ptr fpst = get_fpstatus_ptr();
7392
7393     if (is_double) {
7394         TCGv_i64 tcg_op = tcg_temp_new_i64();
7395         TCGv_i64 tcg_res = tcg_temp_new_i64();
7396         int pass;
7397
7398         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
7399             read_vec_element(s, tcg_op, rn, pass, MO_64);
7400             switch (opcode) {
7401             case 0x3d: /* FRECPE */
7402                 gen_helper_recpe_f64(tcg_res, tcg_op, fpst);
7403                 break;
7404             case 0x3f: /* FRECPX */
7405                 gen_helper_frecpx_f64(tcg_res, tcg_op, fpst);
7406                 break;
7407             case 0x7d: /* FRSQRTE */
7408                 gen_helper_rsqrte_f64(tcg_res, tcg_op, fpst);
7409                 break;
7410             default:
7411                 g_assert_not_reached();
7412             }
7413             write_vec_element(s, tcg_res, rd, pass, MO_64);
7414         }
7415         if (is_scalar) {
7416             clear_vec_high(s, rd);
7417         }
7418
7419         tcg_temp_free_i64(tcg_res);
7420         tcg_temp_free_i64(tcg_op);
7421     } else {
7422         TCGv_i32 tcg_op = tcg_temp_new_i32();
7423         TCGv_i32 tcg_res = tcg_temp_new_i32();
7424         int pass, maxpasses;
7425
7426         if (is_scalar) {
7427             maxpasses = 1;
7428         } else {
7429             maxpasses = is_q ? 4 : 2;
7430         }
7431
7432         for (pass = 0; pass < maxpasses; pass++) {
7433             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
7434
7435             switch (opcode) {
7436             case 0x3c: /* URECPE */
7437                 gen_helper_recpe_u32(tcg_res, tcg_op, fpst);
7438                 break;
7439             case 0x3d: /* FRECPE */
7440                 gen_helper_recpe_f32(tcg_res, tcg_op, fpst);
7441                 break;
7442             case 0x3f: /* FRECPX */
7443                 gen_helper_frecpx_f32(tcg_res, tcg_op, fpst);
7444                 break;
7445             case 0x7d: /* FRSQRTE */
7446                 gen_helper_rsqrte_f32(tcg_res, tcg_op, fpst);
7447                 break;
7448             default:
7449                 g_assert_not_reached();
7450             }
7451
7452             if (is_scalar) {
7453                 write_fp_sreg(s, rd, tcg_res);
7454             } else {
7455                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
7456             }
7457         }
7458         tcg_temp_free_i32(tcg_res);
7459         tcg_temp_free_i32(tcg_op);
7460         if (!is_q && !is_scalar) {
7461             clear_vec_high(s, rd);
7462         }
7463     }
7464     tcg_temp_free_ptr(fpst);
7465 }
7466
7467 static void handle_2misc_narrow(DisasContext *s, bool scalar,
7468                                 int opcode, bool u, bool is_q,
7469                                 int size, int rn, int rd)
7470 {
7471     /* Handle 2-reg-misc ops which are narrowing (so each 2*size element
7472      * in the source becomes a size element in the destination).
7473      */
7474     int pass;
7475     TCGv_i32 tcg_res[2];
7476     int destelt = is_q ? 2 : 0;
7477     int passes = scalar ? 1 : 2;
7478
7479     if (scalar) {
7480         tcg_res[1] = tcg_const_i32(0);
7481     }
7482
7483     for (pass = 0; pass < passes; pass++) {
7484         TCGv_i64 tcg_op = tcg_temp_new_i64();
7485         NeonGenNarrowFn *genfn = NULL;
7486         NeonGenNarrowEnvFn *genenvfn = NULL;
7487
7488         if (scalar) {
7489             read_vec_element(s, tcg_op, rn, pass, size + 1);
7490         } else {
7491             read_vec_element(s, tcg_op, rn, pass, MO_64);
7492         }
7493         tcg_res[pass] = tcg_temp_new_i32();
7494
7495         switch (opcode) {
7496         case 0x12: /* XTN, SQXTUN */
7497         {
7498             static NeonGenNarrowFn * const xtnfns[3] = {
7499                 gen_helper_neon_narrow_u8,
7500                 gen_helper_neon_narrow_u16,
7501                 tcg_gen_trunc_i64_i32,
7502             };
7503             static NeonGenNarrowEnvFn * const sqxtunfns[3] = {
7504                 gen_helper_neon_unarrow_sat8,
7505                 gen_helper_neon_unarrow_sat16,
7506                 gen_helper_neon_unarrow_sat32,
7507             };
7508             if (u) {
7509                 genenvfn = sqxtunfns[size];
7510             } else {
7511                 genfn = xtnfns[size];
7512             }
7513             break;
7514         }
7515         case 0x14: /* SQXTN, UQXTN */
7516         {
7517             static NeonGenNarrowEnvFn * const fns[3][2] = {
7518                 { gen_helper_neon_narrow_sat_s8,
7519                   gen_helper_neon_narrow_sat_u8 },
7520                 { gen_helper_neon_narrow_sat_s16,
7521                   gen_helper_neon_narrow_sat_u16 },
7522                 { gen_helper_neon_narrow_sat_s32,
7523                   gen_helper_neon_narrow_sat_u32 },
7524             };
7525             genenvfn = fns[size][u];
7526             break;
7527         }
7528         case 0x16: /* FCVTN, FCVTN2 */
7529             /* 32 bit to 16 bit or 64 bit to 32 bit float conversion */
7530             if (size == 2) {
7531                 gen_helper_vfp_fcvtsd(tcg_res[pass], tcg_op, cpu_env);
7532             } else {
7533                 TCGv_i32 tcg_lo = tcg_temp_new_i32();
7534                 TCGv_i32 tcg_hi = tcg_temp_new_i32();
7535                 tcg_gen_trunc_i64_i32(tcg_lo, tcg_op);
7536                 gen_helper_vfp_fcvt_f32_to_f16(tcg_lo, tcg_lo, cpu_env);
7537                 tcg_gen_shri_i64(tcg_op, tcg_op, 32);
7538                 tcg_gen_trunc_i64_i32(tcg_hi, tcg_op);
7539                 gen_helper_vfp_fcvt_f32_to_f16(tcg_hi, tcg_hi, cpu_env);
7540                 tcg_gen_deposit_i32(tcg_res[pass], tcg_lo, tcg_hi, 16, 16);
7541                 tcg_temp_free_i32(tcg_lo);
7542                 tcg_temp_free_i32(tcg_hi);
7543             }
7544             break;
7545         case 0x56:  /* FCVTXN, FCVTXN2 */
7546             /* 64 bit to 32 bit float conversion
7547              * with von Neumann rounding (round to odd)
7548              */
7549             assert(size == 2);
7550             gen_helper_fcvtx_f64_to_f32(tcg_res[pass], tcg_op, cpu_env);
7551             break;
7552         default:
7553             g_assert_not_reached();
7554         }
7555
7556         if (genfn) {
7557             genfn(tcg_res[pass], tcg_op);
7558         } else if (genenvfn) {
7559             genenvfn(tcg_res[pass], cpu_env, tcg_op);
7560         }
7561
7562         tcg_temp_free_i64(tcg_op);
7563     }
7564
7565     for (pass = 0; pass < 2; pass++) {
7566         write_vec_element_i32(s, tcg_res[pass], rd, destelt + pass, MO_32);
7567         tcg_temp_free_i32(tcg_res[pass]);
7568     }
7569     if (!is_q) {
7570         clear_vec_high(s, rd);
7571     }
7572 }
7573
7574 /* Remaining saturating accumulating ops */
7575 static void handle_2misc_satacc(DisasContext *s, bool is_scalar, bool is_u,
7576                                 bool is_q, int size, int rn, int rd)
7577 {
7578     bool is_double = (size == 3);
7579
7580     if (is_double) {
7581         TCGv_i64 tcg_rn = tcg_temp_new_i64();
7582         TCGv_i64 tcg_rd = tcg_temp_new_i64();
7583         int pass;
7584
7585         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
7586             read_vec_element(s, tcg_rn, rn, pass, MO_64);
7587             read_vec_element(s, tcg_rd, rd, pass, MO_64);
7588
7589             if (is_u) { /* USQADD */
7590                 gen_helper_neon_uqadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
7591             } else { /* SUQADD */
7592                 gen_helper_neon_sqadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
7593             }
7594             write_vec_element(s, tcg_rd, rd, pass, MO_64);
7595         }
7596         if (is_scalar) {
7597             clear_vec_high(s, rd);
7598         }
7599
7600         tcg_temp_free_i64(tcg_rd);
7601         tcg_temp_free_i64(tcg_rn);
7602     } else {
7603         TCGv_i32 tcg_rn = tcg_temp_new_i32();
7604         TCGv_i32 tcg_rd = tcg_temp_new_i32();
7605         int pass, maxpasses;
7606
7607         if (is_scalar) {
7608             maxpasses = 1;
7609         } else {
7610             maxpasses = is_q ? 4 : 2;
7611         }
7612
7613         for (pass = 0; pass < maxpasses; pass++) {
7614             if (is_scalar) {
7615                 read_vec_element_i32(s, tcg_rn, rn, pass, size);
7616                 read_vec_element_i32(s, tcg_rd, rd, pass, size);
7617             } else {
7618                 read_vec_element_i32(s, tcg_rn, rn, pass, MO_32);
7619                 read_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
7620             }
7621
7622             if (is_u) { /* USQADD */
7623                 switch (size) {
7624                 case 0:
7625                     gen_helper_neon_uqadd_s8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
7626                     break;
7627                 case 1:
7628                     gen_helper_neon_uqadd_s16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
7629                     break;
7630                 case 2:
7631                     gen_helper_neon_uqadd_s32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
7632                     break;
7633                 default:
7634                     g_assert_not_reached();
7635                 }
7636             } else { /* SUQADD */
7637                 switch (size) {
7638                 case 0:
7639                     gen_helper_neon_sqadd_u8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
7640                     break;
7641                 case 1:
7642                     gen_helper_neon_sqadd_u16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
7643                     break;
7644                 case 2:
7645                     gen_helper_neon_sqadd_u32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
7646                     break;
7647                 default:
7648                     g_assert_not_reached();
7649                 }
7650             }
7651
7652             if (is_scalar) {
7653                 TCGv_i64 tcg_zero = tcg_const_i64(0);
7654                 write_vec_element(s, tcg_zero, rd, 0, MO_64);
7655                 tcg_temp_free_i64(tcg_zero);
7656             }
7657             write_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
7658         }
7659
7660         if (!is_q) {
7661             clear_vec_high(s, rd);
7662         }
7663
7664         tcg_temp_free_i32(tcg_rd);
7665         tcg_temp_free_i32(tcg_rn);
7666     }
7667 }
7668
7669 /* C3.6.12 AdvSIMD scalar two reg misc
7670  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
7671  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7672  * | 0 1 | U | 1 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
7673  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7674  */
7675 static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
7676 {
7677     int rd = extract32(insn, 0, 5);
7678     int rn = extract32(insn, 5, 5);
7679     int opcode = extract32(insn, 12, 5);
7680     int size = extract32(insn, 22, 2);
7681     bool u = extract32(insn, 29, 1);
7682     bool is_fcvt = false;
7683     int rmode;
7684     TCGv_i32 tcg_rmode;
7685     TCGv_ptr tcg_fpstatus;
7686
7687     switch (opcode) {
7688     case 0x3: /* USQADD / SUQADD*/
7689         if (!fp_access_check(s)) {
7690             return;
7691         }
7692         handle_2misc_satacc(s, true, u, false, size, rn, rd);
7693         return;
7694     case 0x7: /* SQABS / SQNEG */
7695         break;
7696     case 0xa: /* CMLT */
7697         if (u) {
7698             unallocated_encoding(s);
7699             return;
7700         }
7701         /* fall through */
7702     case 0x8: /* CMGT, CMGE */
7703     case 0x9: /* CMEQ, CMLE */
7704     case 0xb: /* ABS, NEG */
7705         if (size != 3) {
7706             unallocated_encoding(s);
7707             return;
7708         }
7709         break;
7710     case 0x12: /* SQXTUN */
7711         if (u) {
7712             unallocated_encoding(s);
7713             return;
7714         }
7715         /* fall through */
7716     case 0x14: /* SQXTN, UQXTN */
7717         if (size == 3) {
7718             unallocated_encoding(s);
7719             return;
7720         }
7721         if (!fp_access_check(s)) {
7722             return;
7723         }
7724         handle_2misc_narrow(s, true, opcode, u, false, size, rn, rd);
7725         return;
7726     case 0xc ... 0xf:
7727     case 0x16 ... 0x1d:
7728     case 0x1f:
7729         /* Floating point: U, size[1] and opcode indicate operation;
7730          * size[0] indicates single or double precision.
7731          */
7732         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
7733         size = extract32(size, 0, 1) ? 3 : 2;
7734         switch (opcode) {
7735         case 0x2c: /* FCMGT (zero) */
7736         case 0x2d: /* FCMEQ (zero) */
7737         case 0x2e: /* FCMLT (zero) */
7738         case 0x6c: /* FCMGE (zero) */
7739         case 0x6d: /* FCMLE (zero) */
7740             handle_2misc_fcmp_zero(s, opcode, true, u, true, size, rn, rd);
7741             return;
7742         case 0x1d: /* SCVTF */
7743         case 0x5d: /* UCVTF */
7744         {
7745             bool is_signed = (opcode == 0x1d);
7746             if (!fp_access_check(s)) {
7747                 return;
7748             }
7749             handle_simd_intfp_conv(s, rd, rn, 1, is_signed, 0, size);
7750             return;
7751         }
7752         case 0x3d: /* FRECPE */
7753         case 0x3f: /* FRECPX */
7754         case 0x7d: /* FRSQRTE */
7755             if (!fp_access_check(s)) {
7756                 return;
7757             }
7758             handle_2misc_reciprocal(s, opcode, true, u, true, size, rn, rd);
7759             return;
7760         case 0x1a: /* FCVTNS */
7761         case 0x1b: /* FCVTMS */
7762         case 0x3a: /* FCVTPS */
7763         case 0x3b: /* FCVTZS */
7764         case 0x5a: /* FCVTNU */
7765         case 0x5b: /* FCVTMU */
7766         case 0x7a: /* FCVTPU */
7767         case 0x7b: /* FCVTZU */
7768             is_fcvt = true;
7769             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
7770             break;
7771         case 0x1c: /* FCVTAS */
7772         case 0x5c: /* FCVTAU */
7773             /* TIEAWAY doesn't fit in the usual rounding mode encoding */
7774             is_fcvt = true;
7775             rmode = FPROUNDING_TIEAWAY;
7776             break;
7777         case 0x56: /* FCVTXN, FCVTXN2 */
7778             if (size == 2) {
7779                 unallocated_encoding(s);
7780                 return;
7781             }
7782             if (!fp_access_check(s)) {
7783                 return;
7784             }
7785             handle_2misc_narrow(s, true, opcode, u, false, size - 1, rn, rd);
7786             return;
7787         default:
7788             unallocated_encoding(s);
7789             return;
7790         }
7791         break;
7792     default:
7793         unallocated_encoding(s);
7794         return;
7795     }
7796
7797     if (!fp_access_check(s)) {
7798         return;
7799     }
7800
7801     if (is_fcvt) {
7802         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
7803         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
7804         tcg_fpstatus = get_fpstatus_ptr();
7805     } else {
7806         TCGV_UNUSED_I32(tcg_rmode);
7807         TCGV_UNUSED_PTR(tcg_fpstatus);
7808     }
7809
7810     if (size == 3) {
7811         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
7812         TCGv_i64 tcg_rd = tcg_temp_new_i64();
7813
7814         handle_2misc_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rmode, tcg_fpstatus);
7815         write_fp_dreg(s, rd, tcg_rd);
7816         tcg_temp_free_i64(tcg_rd);
7817         tcg_temp_free_i64(tcg_rn);
7818     } else {
7819         TCGv_i32 tcg_rn = tcg_temp_new_i32();
7820         TCGv_i32 tcg_rd = tcg_temp_new_i32();
7821
7822         read_vec_element_i32(s, tcg_rn, rn, 0, size);
7823
7824         switch (opcode) {
7825         case 0x7: /* SQABS, SQNEG */
7826         {
7827             NeonGenOneOpEnvFn *genfn;
7828             static NeonGenOneOpEnvFn * const fns[3][2] = {
7829                 { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
7830                 { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
7831                 { gen_helper_neon_qabs_s32, gen_helper_neon_qneg_s32 },
7832             };
7833             genfn = fns[size][u];
7834             genfn(tcg_rd, cpu_env, tcg_rn);
7835             break;
7836         }
7837         case 0x1a: /* FCVTNS */
7838         case 0x1b: /* FCVTMS */
7839         case 0x1c: /* FCVTAS */
7840         case 0x3a: /* FCVTPS */
7841         case 0x3b: /* FCVTZS */
7842         {
7843             TCGv_i32 tcg_shift = tcg_const_i32(0);
7844             gen_helper_vfp_tosls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
7845             tcg_temp_free_i32(tcg_shift);
7846             break;
7847         }
7848         case 0x5a: /* FCVTNU */
7849         case 0x5b: /* FCVTMU */
7850         case 0x5c: /* FCVTAU */
7851         case 0x7a: /* FCVTPU */
7852         case 0x7b: /* FCVTZU */
7853         {
7854             TCGv_i32 tcg_shift = tcg_const_i32(0);
7855             gen_helper_vfp_touls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
7856             tcg_temp_free_i32(tcg_shift);
7857             break;
7858         }
7859         default:
7860             g_assert_not_reached();
7861         }
7862
7863         write_fp_sreg(s, rd, tcg_rd);
7864         tcg_temp_free_i32(tcg_rd);
7865         tcg_temp_free_i32(tcg_rn);
7866     }
7867
7868     if (is_fcvt) {
7869         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
7870         tcg_temp_free_i32(tcg_rmode);
7871         tcg_temp_free_ptr(tcg_fpstatus);
7872     }
7873 }
7874
7875 /* SSHR[RA]/USHR[RA] - Vector shift right (optional rounding/accumulate) */
7876 static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
7877                                  int immh, int immb, int opcode, int rn, int rd)
7878 {
7879     int size = 32 - clz32(immh) - 1;
7880     int immhb = immh << 3 | immb;
7881     int shift = 2 * (8 << size) - immhb;
7882     bool accumulate = false;
7883     bool round = false;
7884     bool insert = false;
7885     int dsize = is_q ? 128 : 64;
7886     int esize = 8 << size;
7887     int elements = dsize/esize;
7888     TCGMemOp memop = size | (is_u ? 0 : MO_SIGN);
7889     TCGv_i64 tcg_rn = new_tmp_a64(s);
7890     TCGv_i64 tcg_rd = new_tmp_a64(s);
7891     TCGv_i64 tcg_round;
7892     int i;
7893
7894     if (extract32(immh, 3, 1) && !is_q) {
7895         unallocated_encoding(s);
7896         return;
7897     }
7898
7899     if (size > 3 && !is_q) {
7900         unallocated_encoding(s);
7901         return;
7902     }
7903
7904     if (!fp_access_check(s)) {
7905         return;
7906     }
7907
7908     switch (opcode) {
7909     case 0x02: /* SSRA / USRA (accumulate) */
7910         accumulate = true;
7911         break;
7912     case 0x04: /* SRSHR / URSHR (rounding) */
7913         round = true;
7914         break;
7915     case 0x06: /* SRSRA / URSRA (accum + rounding) */
7916         accumulate = round = true;
7917         break;
7918     case 0x08: /* SRI */
7919         insert = true;
7920         break;
7921     }
7922
7923     if (round) {
7924         uint64_t round_const = 1ULL << (shift - 1);
7925         tcg_round = tcg_const_i64(round_const);
7926     } else {
7927         TCGV_UNUSED_I64(tcg_round);
7928     }
7929
7930     for (i = 0; i < elements; i++) {
7931         read_vec_element(s, tcg_rn, rn, i, memop);
7932         if (accumulate || insert) {
7933             read_vec_element(s, tcg_rd, rd, i, memop);
7934         }
7935
7936         if (insert) {
7937             handle_shri_with_ins(tcg_rd, tcg_rn, size, shift);
7938         } else {
7939             handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
7940                                     accumulate, is_u, size, shift);
7941         }
7942
7943         write_vec_element(s, tcg_rd, rd, i, size);
7944     }
7945
7946     if (!is_q) {
7947         clear_vec_high(s, rd);
7948     }
7949
7950     if (round) {
7951         tcg_temp_free_i64(tcg_round);
7952     }
7953 }
7954
7955 /* SHL/SLI - Vector shift left */
7956 static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
7957                                 int immh, int immb, int opcode, int rn, int rd)
7958 {
7959     int size = 32 - clz32(immh) - 1;
7960     int immhb = immh << 3 | immb;
7961     int shift = immhb - (8 << size);
7962     int dsize = is_q ? 128 : 64;
7963     int esize = 8 << size;
7964     int elements = dsize/esize;
7965     TCGv_i64 tcg_rn = new_tmp_a64(s);
7966     TCGv_i64 tcg_rd = new_tmp_a64(s);
7967     int i;
7968
7969     if (extract32(immh, 3, 1) && !is_q) {
7970         unallocated_encoding(s);
7971         return;
7972     }
7973
7974     if (size > 3 && !is_q) {
7975         unallocated_encoding(s);
7976         return;
7977     }
7978
7979     if (!fp_access_check(s)) {
7980         return;
7981     }
7982
7983     for (i = 0; i < elements; i++) {
7984         read_vec_element(s, tcg_rn, rn, i, size);
7985         if (insert) {
7986             read_vec_element(s, tcg_rd, rd, i, size);
7987         }
7988
7989         handle_shli_with_ins(tcg_rd, tcg_rn, insert, shift);
7990
7991         write_vec_element(s, tcg_rd, rd, i, size);
7992     }
7993
7994     if (!is_q) {
7995         clear_vec_high(s, rd);
7996     }
7997 }
7998
7999 /* USHLL/SHLL - Vector shift left with widening */
8000 static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u,
8001                                  int immh, int immb, int opcode, int rn, int rd)
8002 {
8003     int size = 32 - clz32(immh) - 1;
8004     int immhb = immh << 3 | immb;
8005     int shift = immhb - (8 << size);
8006     int dsize = 64;
8007     int esize = 8 << size;
8008     int elements = dsize/esize;
8009     TCGv_i64 tcg_rn = new_tmp_a64(s);
8010     TCGv_i64 tcg_rd = new_tmp_a64(s);
8011     int i;
8012
8013     if (size >= 3) {
8014         unallocated_encoding(s);
8015         return;
8016     }
8017
8018     if (!fp_access_check(s)) {
8019         return;
8020     }
8021
8022     /* For the LL variants the store is larger than the load,
8023      * so if rd == rn we would overwrite parts of our input.
8024      * So load everything right now and use shifts in the main loop.
8025      */
8026     read_vec_element(s, tcg_rn, rn, is_q ? 1 : 0, MO_64);
8027
8028     for (i = 0; i < elements; i++) {
8029         tcg_gen_shri_i64(tcg_rd, tcg_rn, i * esize);
8030         ext_and_shift_reg(tcg_rd, tcg_rd, size | (!is_u << 2), 0);
8031         tcg_gen_shli_i64(tcg_rd, tcg_rd, shift);
8032         write_vec_element(s, tcg_rd, rd, i, size + 1);
8033     }
8034 }
8035
8036 /* SHRN/RSHRN - Shift right with narrowing (and potential rounding) */
8037 static void handle_vec_simd_shrn(DisasContext *s, bool is_q,
8038                                  int immh, int immb, int opcode, int rn, int rd)
8039 {
8040     int immhb = immh << 3 | immb;
8041     int size = 32 - clz32(immh) - 1;
8042     int dsize = 64;
8043     int esize = 8 << size;
8044     int elements = dsize/esize;
8045     int shift = (2 * esize) - immhb;
8046     bool round = extract32(opcode, 0, 1);
8047     TCGv_i64 tcg_rn, tcg_rd, tcg_final;
8048     TCGv_i64 tcg_round;
8049     int i;
8050
8051     if (extract32(immh, 3, 1)) {
8052         unallocated_encoding(s);
8053         return;
8054     }
8055
8056     if (!fp_access_check(s)) {
8057         return;
8058     }
8059
8060     tcg_rn = tcg_temp_new_i64();
8061     tcg_rd = tcg_temp_new_i64();
8062     tcg_final = tcg_temp_new_i64();
8063     read_vec_element(s, tcg_final, rd, is_q ? 1 : 0, MO_64);
8064
8065     if (round) {
8066         uint64_t round_const = 1ULL << (shift - 1);
8067         tcg_round = tcg_const_i64(round_const);
8068     } else {
8069         TCGV_UNUSED_I64(tcg_round);
8070     }
8071
8072     for (i = 0; i < elements; i++) {
8073         read_vec_element(s, tcg_rn, rn, i, size+1);
8074         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
8075                                 false, true, size+1, shift);
8076
8077         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
8078     }
8079
8080     if (!is_q) {
8081         clear_vec_high(s, rd);
8082         write_vec_element(s, tcg_final, rd, 0, MO_64);
8083     } else {
8084         write_vec_element(s, tcg_final, rd, 1, MO_64);
8085     }
8086
8087     if (round) {
8088         tcg_temp_free_i64(tcg_round);
8089     }
8090     tcg_temp_free_i64(tcg_rn);
8091     tcg_temp_free_i64(tcg_rd);
8092     tcg_temp_free_i64(tcg_final);
8093     return;
8094 }
8095
8096
8097 /* C3.6.14 AdvSIMD shift by immediate
8098  *  31  30   29 28         23 22  19 18  16 15    11  10 9    5 4    0
8099  * +---+---+---+-------------+------+------+--------+---+------+------+
8100  * | 0 | Q | U | 0 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
8101  * +---+---+---+-------------+------+------+--------+---+------+------+
8102  */
8103 static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
8104 {
8105     int rd = extract32(insn, 0, 5);
8106     int rn = extract32(insn, 5, 5);
8107     int opcode = extract32(insn, 11, 5);
8108     int immb = extract32(insn, 16, 3);
8109     int immh = extract32(insn, 19, 4);
8110     bool is_u = extract32(insn, 29, 1);
8111     bool is_q = extract32(insn, 30, 1);
8112
8113     switch (opcode) {
8114     case 0x08: /* SRI */
8115         if (!is_u) {
8116             unallocated_encoding(s);
8117             return;
8118         }
8119         /* fall through */
8120     case 0x00: /* SSHR / USHR */
8121     case 0x02: /* SSRA / USRA (accumulate) */
8122     case 0x04: /* SRSHR / URSHR (rounding) */
8123     case 0x06: /* SRSRA / URSRA (accum + rounding) */
8124         handle_vec_simd_shri(s, is_q, is_u, immh, immb, opcode, rn, rd);
8125         break;
8126     case 0x0a: /* SHL / SLI */
8127         handle_vec_simd_shli(s, is_q, is_u, immh, immb, opcode, rn, rd);
8128         break;
8129     case 0x10: /* SHRN */
8130     case 0x11: /* RSHRN / SQRSHRUN */
8131         if (is_u) {
8132             handle_vec_simd_sqshrn(s, false, is_q, false, true, immh, immb,
8133                                    opcode, rn, rd);
8134         } else {
8135             handle_vec_simd_shrn(s, is_q, immh, immb, opcode, rn, rd);
8136         }
8137         break;
8138     case 0x12: /* SQSHRN / UQSHRN */
8139     case 0x13: /* SQRSHRN / UQRSHRN */
8140         handle_vec_simd_sqshrn(s, false, is_q, is_u, is_u, immh, immb,
8141                                opcode, rn, rd);
8142         break;
8143     case 0x14: /* SSHLL / USHLL */
8144         handle_vec_simd_wshli(s, is_q, is_u, immh, immb, opcode, rn, rd);
8145         break;
8146     case 0x1c: /* SCVTF / UCVTF */
8147         handle_simd_shift_intfp_conv(s, false, is_q, is_u, immh, immb,
8148                                      opcode, rn, rd);
8149         break;
8150     case 0xc: /* SQSHLU */
8151         if (!is_u) {
8152             unallocated_encoding(s);
8153             return;
8154         }
8155         handle_simd_qshl(s, false, is_q, false, true, immh, immb, rn, rd);
8156         break;
8157     case 0xe: /* SQSHL, UQSHL */
8158         handle_simd_qshl(s, false, is_q, is_u, is_u, immh, immb, rn, rd);
8159         break;
8160     case 0x1f: /* FCVTZS/ FCVTZU */
8161         handle_simd_shift_fpint_conv(s, false, is_q, is_u, immh, immb, rn, rd);
8162         return;
8163     default:
8164         unallocated_encoding(s);
8165         return;
8166     }
8167 }
8168
8169 /* Generate code to do a "long" addition or subtraction, ie one done in
8170  * TCGv_i64 on vector lanes twice the width specified by size.
8171  */
8172 static void gen_neon_addl(int size, bool is_sub, TCGv_i64 tcg_res,
8173                           TCGv_i64 tcg_op1, TCGv_i64 tcg_op2)
8174 {
8175     static NeonGenTwo64OpFn * const fns[3][2] = {
8176         { gen_helper_neon_addl_u16, gen_helper_neon_subl_u16 },
8177         { gen_helper_neon_addl_u32, gen_helper_neon_subl_u32 },
8178         { tcg_gen_add_i64, tcg_gen_sub_i64 },
8179     };
8180     NeonGenTwo64OpFn *genfn;
8181     assert(size < 3);
8182
8183     genfn = fns[size][is_sub];
8184     genfn(tcg_res, tcg_op1, tcg_op2);
8185 }
8186
8187 static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
8188                                 int opcode, int rd, int rn, int rm)
8189 {
8190     /* 3-reg-different widening insns: 64 x 64 -> 128 */
8191     TCGv_i64 tcg_res[2];
8192     int pass, accop;
8193
8194     tcg_res[0] = tcg_temp_new_i64();
8195     tcg_res[1] = tcg_temp_new_i64();
8196
8197     /* Does this op do an adding accumulate, a subtracting accumulate,
8198      * or no accumulate at all?
8199      */
8200     switch (opcode) {
8201     case 5:
8202     case 8:
8203     case 9:
8204         accop = 1;
8205         break;
8206     case 10:
8207     case 11:
8208         accop = -1;
8209         break;
8210     default:
8211         accop = 0;
8212         break;
8213     }
8214
8215     if (accop != 0) {
8216         read_vec_element(s, tcg_res[0], rd, 0, MO_64);
8217         read_vec_element(s, tcg_res[1], rd, 1, MO_64);
8218     }
8219
8220     /* size == 2 means two 32x32->64 operations; this is worth special
8221      * casing because we can generally handle it inline.
8222      */
8223     if (size == 2) {
8224         for (pass = 0; pass < 2; pass++) {
8225             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8226             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8227             TCGv_i64 tcg_passres;
8228             TCGMemOp memop = MO_32 | (is_u ? 0 : MO_SIGN);
8229
8230             int elt = pass + is_q * 2;
8231
8232             read_vec_element(s, tcg_op1, rn, elt, memop);
8233             read_vec_element(s, tcg_op2, rm, elt, memop);
8234
8235             if (accop == 0) {
8236                 tcg_passres = tcg_res[pass];
8237             } else {
8238                 tcg_passres = tcg_temp_new_i64();
8239             }
8240
8241             switch (opcode) {
8242             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
8243                 tcg_gen_add_i64(tcg_passres, tcg_op1, tcg_op2);
8244                 break;
8245             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
8246                 tcg_gen_sub_i64(tcg_passres, tcg_op1, tcg_op2);
8247                 break;
8248             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
8249             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
8250             {
8251                 TCGv_i64 tcg_tmp1 = tcg_temp_new_i64();
8252                 TCGv_i64 tcg_tmp2 = tcg_temp_new_i64();
8253
8254                 tcg_gen_sub_i64(tcg_tmp1, tcg_op1, tcg_op2);
8255                 tcg_gen_sub_i64(tcg_tmp2, tcg_op2, tcg_op1);
8256                 tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
8257                                     tcg_passres,
8258                                     tcg_op1, tcg_op2, tcg_tmp1, tcg_tmp2);
8259                 tcg_temp_free_i64(tcg_tmp1);
8260                 tcg_temp_free_i64(tcg_tmp2);
8261                 break;
8262             }
8263             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
8264             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
8265             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
8266                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
8267                 break;
8268             case 9: /* SQDMLAL, SQDMLAL2 */
8269             case 11: /* SQDMLSL, SQDMLSL2 */
8270             case 13: /* SQDMULL, SQDMULL2 */
8271                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
8272                 gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
8273                                                   tcg_passres, tcg_passres);
8274                 break;
8275             default:
8276                 g_assert_not_reached();
8277             }
8278
8279             if (opcode == 9 || opcode == 11) {
8280                 /* saturating accumulate ops */
8281                 if (accop < 0) {
8282                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
8283                 }
8284                 gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
8285                                                   tcg_res[pass], tcg_passres);
8286             } else if (accop > 0) {
8287                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
8288             } else if (accop < 0) {
8289                 tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
8290             }
8291
8292             if (accop != 0) {
8293                 tcg_temp_free_i64(tcg_passres);
8294             }
8295
8296             tcg_temp_free_i64(tcg_op1);
8297             tcg_temp_free_i64(tcg_op2);
8298         }
8299     } else {
8300         /* size 0 or 1, generally helper functions */
8301         for (pass = 0; pass < 2; pass++) {
8302             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
8303             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
8304             TCGv_i64 tcg_passres;
8305             int elt = pass + is_q * 2;
8306
8307             read_vec_element_i32(s, tcg_op1, rn, elt, MO_32);
8308             read_vec_element_i32(s, tcg_op2, rm, elt, MO_32);
8309
8310             if (accop == 0) {
8311                 tcg_passres = tcg_res[pass];
8312             } else {
8313                 tcg_passres = tcg_temp_new_i64();
8314             }
8315
8316             switch (opcode) {
8317             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
8318             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
8319             {
8320                 TCGv_i64 tcg_op2_64 = tcg_temp_new_i64();
8321                 static NeonGenWidenFn * const widenfns[2][2] = {
8322                     { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
8323                     { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
8324                 };
8325                 NeonGenWidenFn *widenfn = widenfns[size][is_u];
8326
8327                 widenfn(tcg_op2_64, tcg_op2);
8328                 widenfn(tcg_passres, tcg_op1);
8329                 gen_neon_addl(size, (opcode == 2), tcg_passres,
8330                               tcg_passres, tcg_op2_64);
8331                 tcg_temp_free_i64(tcg_op2_64);
8332                 break;
8333             }
8334             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
8335             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
8336                 if (size == 0) {
8337                     if (is_u) {
8338                         gen_helper_neon_abdl_u16(tcg_passres, tcg_op1, tcg_op2);
8339                     } else {
8340                         gen_helper_neon_abdl_s16(tcg_passres, tcg_op1, tcg_op2);
8341                     }
8342                 } else {
8343                     if (is_u) {
8344                         gen_helper_neon_abdl_u32(tcg_passres, tcg_op1, tcg_op2);
8345                     } else {
8346                         gen_helper_neon_abdl_s32(tcg_passres, tcg_op1, tcg_op2);
8347                     }
8348                 }
8349                 break;
8350             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
8351             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
8352             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
8353                 if (size == 0) {
8354                     if (is_u) {
8355                         gen_helper_neon_mull_u8(tcg_passres, tcg_op1, tcg_op2);
8356                     } else {
8357                         gen_helper_neon_mull_s8(tcg_passres, tcg_op1, tcg_op2);
8358                     }
8359                 } else {
8360                     if (is_u) {
8361                         gen_helper_neon_mull_u16(tcg_passres, tcg_op1, tcg_op2);
8362                     } else {
8363                         gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
8364                     }
8365                 }
8366                 break;
8367             case 9: /* SQDMLAL, SQDMLAL2 */
8368             case 11: /* SQDMLSL, SQDMLSL2 */
8369             case 13: /* SQDMULL, SQDMULL2 */
8370                 assert(size == 1);
8371                 gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
8372                 gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
8373                                                   tcg_passres, tcg_passres);
8374                 break;
8375             case 14: /* PMULL */
8376                 assert(size == 0);
8377                 gen_helper_neon_mull_p8(tcg_passres, tcg_op1, tcg_op2);
8378                 break;
8379             default:
8380                 g_assert_not_reached();
8381             }
8382             tcg_temp_free_i32(tcg_op1);
8383             tcg_temp_free_i32(tcg_op2);
8384
8385             if (accop != 0) {
8386                 if (opcode == 9 || opcode == 11) {
8387                     /* saturating accumulate ops */
8388                     if (accop < 0) {
8389                         gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
8390                     }
8391                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
8392                                                       tcg_res[pass],
8393                                                       tcg_passres);
8394                 } else {
8395                     gen_neon_addl(size, (accop < 0), tcg_res[pass],
8396                                   tcg_res[pass], tcg_passres);
8397                 }
8398                 tcg_temp_free_i64(tcg_passres);
8399             }
8400         }
8401     }
8402
8403     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
8404     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
8405     tcg_temp_free_i64(tcg_res[0]);
8406     tcg_temp_free_i64(tcg_res[1]);
8407 }
8408
8409 static void handle_3rd_wide(DisasContext *s, int is_q, int is_u, int size,
8410                             int opcode, int rd, int rn, int rm)
8411 {
8412     TCGv_i64 tcg_res[2];
8413     int part = is_q ? 2 : 0;
8414     int pass;
8415
8416     for (pass = 0; pass < 2; pass++) {
8417         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8418         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
8419         TCGv_i64 tcg_op2_wide = tcg_temp_new_i64();
8420         static NeonGenWidenFn * const widenfns[3][2] = {
8421             { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
8422             { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
8423             { tcg_gen_ext_i32_i64, tcg_gen_extu_i32_i64 },
8424         };
8425         NeonGenWidenFn *widenfn = widenfns[size][is_u];
8426
8427         read_vec_element(s, tcg_op1, rn, pass, MO_64);
8428         read_vec_element_i32(s, tcg_op2, rm, part + pass, MO_32);
8429         widenfn(tcg_op2_wide, tcg_op2);
8430         tcg_temp_free_i32(tcg_op2);
8431         tcg_res[pass] = tcg_temp_new_i64();
8432         gen_neon_addl(size, (opcode == 3),
8433                       tcg_res[pass], tcg_op1, tcg_op2_wide);
8434         tcg_temp_free_i64(tcg_op1);
8435         tcg_temp_free_i64(tcg_op2_wide);
8436     }
8437
8438     for (pass = 0; pass < 2; pass++) {
8439         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
8440         tcg_temp_free_i64(tcg_res[pass]);
8441     }
8442 }
8443
8444 static void do_narrow_high_u32(TCGv_i32 res, TCGv_i64 in)
8445 {
8446     tcg_gen_shri_i64(in, in, 32);
8447     tcg_gen_trunc_i64_i32(res, in);
8448 }
8449
8450 static void do_narrow_round_high_u32(TCGv_i32 res, TCGv_i64 in)
8451 {
8452     tcg_gen_addi_i64(in, in, 1U << 31);
8453     do_narrow_high_u32(res, in);
8454 }
8455
8456 static void handle_3rd_narrowing(DisasContext *s, int is_q, int is_u, int size,
8457                                  int opcode, int rd, int rn, int rm)
8458 {
8459     TCGv_i32 tcg_res[2];
8460     int part = is_q ? 2 : 0;
8461     int pass;
8462
8463     for (pass = 0; pass < 2; pass++) {
8464         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8465         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8466         TCGv_i64 tcg_wideres = tcg_temp_new_i64();
8467         static NeonGenNarrowFn * const narrowfns[3][2] = {
8468             { gen_helper_neon_narrow_high_u8,
8469               gen_helper_neon_narrow_round_high_u8 },
8470             { gen_helper_neon_narrow_high_u16,
8471               gen_helper_neon_narrow_round_high_u16 },
8472             { do_narrow_high_u32, do_narrow_round_high_u32 },
8473         };
8474         NeonGenNarrowFn *gennarrow = narrowfns[size][is_u];
8475
8476         read_vec_element(s, tcg_op1, rn, pass, MO_64);
8477         read_vec_element(s, tcg_op2, rm, pass, MO_64);
8478
8479         gen_neon_addl(size, (opcode == 6), tcg_wideres, tcg_op1, tcg_op2);
8480
8481         tcg_temp_free_i64(tcg_op1);
8482         tcg_temp_free_i64(tcg_op2);
8483
8484         tcg_res[pass] = tcg_temp_new_i32();
8485         gennarrow(tcg_res[pass], tcg_wideres);
8486         tcg_temp_free_i64(tcg_wideres);
8487     }
8488
8489     for (pass = 0; pass < 2; pass++) {
8490         write_vec_element_i32(s, tcg_res[pass], rd, pass + part, MO_32);
8491         tcg_temp_free_i32(tcg_res[pass]);
8492     }
8493     if (!is_q) {
8494         clear_vec_high(s, rd);
8495     }
8496 }
8497
8498 static void handle_pmull_64(DisasContext *s, int is_q, int rd, int rn, int rm)
8499 {
8500     /* PMULL of 64 x 64 -> 128 is an odd special case because it
8501      * is the only three-reg-diff instruction which produces a
8502      * 128-bit wide result from a single operation. However since
8503      * it's possible to calculate the two halves more or less
8504      * separately we just use two helper calls.
8505      */
8506     TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8507     TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8508     TCGv_i64 tcg_res = tcg_temp_new_i64();
8509
8510     read_vec_element(s, tcg_op1, rn, is_q, MO_64);
8511     read_vec_element(s, tcg_op2, rm, is_q, MO_64);
8512     gen_helper_neon_pmull_64_lo(tcg_res, tcg_op1, tcg_op2);
8513     write_vec_element(s, tcg_res, rd, 0, MO_64);
8514     gen_helper_neon_pmull_64_hi(tcg_res, tcg_op1, tcg_op2);
8515     write_vec_element(s, tcg_res, rd, 1, MO_64);
8516
8517     tcg_temp_free_i64(tcg_op1);
8518     tcg_temp_free_i64(tcg_op2);
8519     tcg_temp_free_i64(tcg_res);
8520 }
8521
8522 /* C3.6.15 AdvSIMD three different
8523  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
8524  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
8525  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
8526  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
8527  */
8528 static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
8529 {
8530     /* Instructions in this group fall into three basic classes
8531      * (in each case with the operation working on each element in
8532      * the input vectors):
8533      * (1) widening 64 x 64 -> 128 (with possibly Vd as an extra
8534      *     128 bit input)
8535      * (2) wide 64 x 128 -> 128
8536      * (3) narrowing 128 x 128 -> 64
8537      * Here we do initial decode, catch unallocated cases and
8538      * dispatch to separate functions for each class.
8539      */
8540     int is_q = extract32(insn, 30, 1);
8541     int is_u = extract32(insn, 29, 1);
8542     int size = extract32(insn, 22, 2);
8543     int opcode = extract32(insn, 12, 4);
8544     int rm = extract32(insn, 16, 5);
8545     int rn = extract32(insn, 5, 5);
8546     int rd = extract32(insn, 0, 5);
8547
8548     switch (opcode) {
8549     case 1: /* SADDW, SADDW2, UADDW, UADDW2 */
8550     case 3: /* SSUBW, SSUBW2, USUBW, USUBW2 */
8551         /* 64 x 128 -> 128 */
8552         if (size == 3) {
8553             unallocated_encoding(s);
8554             return;
8555         }
8556         if (!fp_access_check(s)) {
8557             return;
8558         }
8559         handle_3rd_wide(s, is_q, is_u, size, opcode, rd, rn, rm);
8560         break;
8561     case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */
8562     case 6: /* SUBHN, SUBHN2, RSUBHN, RSUBHN2 */
8563         /* 128 x 128 -> 64 */
8564         if (size == 3) {
8565             unallocated_encoding(s);
8566             return;
8567         }
8568         if (!fp_access_check(s)) {
8569             return;
8570         }
8571         handle_3rd_narrowing(s, is_q, is_u, size, opcode, rd, rn, rm);
8572         break;
8573     case 14: /* PMULL, PMULL2 */
8574         if (is_u || size == 1 || size == 2) {
8575             unallocated_encoding(s);
8576             return;
8577         }
8578         if (size == 3) {
8579             if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)) {
8580                 unallocated_encoding(s);
8581                 return;
8582             }
8583             if (!fp_access_check(s)) {
8584                 return;
8585             }
8586             handle_pmull_64(s, is_q, rd, rn, rm);
8587             return;
8588         }
8589         goto is_widening;
8590     case 9: /* SQDMLAL, SQDMLAL2 */
8591     case 11: /* SQDMLSL, SQDMLSL2 */
8592     case 13: /* SQDMULL, SQDMULL2 */
8593         if (is_u || size == 0) {
8594             unallocated_encoding(s);
8595             return;
8596         }
8597         /* fall through */
8598     case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
8599     case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
8600     case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
8601     case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
8602     case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
8603     case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
8604     case 12: /* SMULL, SMULL2, UMULL, UMULL2 */
8605         /* 64 x 64 -> 128 */
8606         if (size == 3) {
8607             unallocated_encoding(s);
8608             return;
8609         }
8610     is_widening:
8611         if (!fp_access_check(s)) {
8612             return;
8613         }
8614
8615         handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm);
8616         break;
8617     default:
8618         /* opcode 15 not allocated */
8619         unallocated_encoding(s);
8620         break;
8621     }
8622 }
8623
8624 /* Logic op (opcode == 3) subgroup of C3.6.16. */
8625 static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
8626 {
8627     int rd = extract32(insn, 0, 5);
8628     int rn = extract32(insn, 5, 5);
8629     int rm = extract32(insn, 16, 5);
8630     int size = extract32(insn, 22, 2);
8631     bool is_u = extract32(insn, 29, 1);
8632     bool is_q = extract32(insn, 30, 1);
8633     TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
8634     int pass;
8635
8636     if (!fp_access_check(s)) {
8637         return;
8638     }
8639
8640     tcg_op1 = tcg_temp_new_i64();
8641     tcg_op2 = tcg_temp_new_i64();
8642     tcg_res[0] = tcg_temp_new_i64();
8643     tcg_res[1] = tcg_temp_new_i64();
8644
8645     for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
8646         read_vec_element(s, tcg_op1, rn, pass, MO_64);
8647         read_vec_element(s, tcg_op2, rm, pass, MO_64);
8648
8649         if (!is_u) {
8650             switch (size) {
8651             case 0: /* AND */
8652                 tcg_gen_and_i64(tcg_res[pass], tcg_op1, tcg_op2);
8653                 break;
8654             case 1: /* BIC */
8655                 tcg_gen_andc_i64(tcg_res[pass], tcg_op1, tcg_op2);
8656                 break;
8657             case 2: /* ORR */
8658                 tcg_gen_or_i64(tcg_res[pass], tcg_op1, tcg_op2);
8659                 break;
8660             case 3: /* ORN */
8661                 tcg_gen_orc_i64(tcg_res[pass], tcg_op1, tcg_op2);
8662                 break;
8663             }
8664         } else {
8665             if (size != 0) {
8666                 /* B* ops need res loaded to operate on */
8667                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
8668             }
8669
8670             switch (size) {
8671             case 0: /* EOR */
8672                 tcg_gen_xor_i64(tcg_res[pass], tcg_op1, tcg_op2);
8673                 break;
8674             case 1: /* BSL bitwise select */
8675                 tcg_gen_xor_i64(tcg_op1, tcg_op1, tcg_op2);
8676                 tcg_gen_and_i64(tcg_op1, tcg_op1, tcg_res[pass]);
8677                 tcg_gen_xor_i64(tcg_res[pass], tcg_op2, tcg_op1);
8678                 break;
8679             case 2: /* BIT, bitwise insert if true */
8680                 tcg_gen_xor_i64(tcg_op1, tcg_op1, tcg_res[pass]);
8681                 tcg_gen_and_i64(tcg_op1, tcg_op1, tcg_op2);
8682                 tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
8683                 break;
8684             case 3: /* BIF, bitwise insert if false */
8685                 tcg_gen_xor_i64(tcg_op1, tcg_op1, tcg_res[pass]);
8686                 tcg_gen_andc_i64(tcg_op1, tcg_op1, tcg_op2);
8687                 tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
8688                 break;
8689             }
8690         }
8691     }
8692
8693     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
8694     if (!is_q) {
8695         tcg_gen_movi_i64(tcg_res[1], 0);
8696     }
8697     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
8698
8699     tcg_temp_free_i64(tcg_op1);
8700     tcg_temp_free_i64(tcg_op2);
8701     tcg_temp_free_i64(tcg_res[0]);
8702     tcg_temp_free_i64(tcg_res[1]);
8703 }
8704
8705 /* Helper functions for 32 bit comparisons */
8706 static void gen_max_s32(TCGv_i32 res, TCGv_i32 op1, TCGv_i32 op2)
8707 {
8708     tcg_gen_movcond_i32(TCG_COND_GE, res, op1, op2, op1, op2);
8709 }
8710
8711 static void gen_max_u32(TCGv_i32 res, TCGv_i32 op1, TCGv_i32 op2)
8712 {
8713     tcg_gen_movcond_i32(TCG_COND_GEU, res, op1, op2, op1, op2);
8714 }
8715
8716 static void gen_min_s32(TCGv_i32 res, TCGv_i32 op1, TCGv_i32 op2)
8717 {
8718     tcg_gen_movcond_i32(TCG_COND_LE, res, op1, op2, op1, op2);
8719 }
8720
8721 static void gen_min_u32(TCGv_i32 res, TCGv_i32 op1, TCGv_i32 op2)
8722 {
8723     tcg_gen_movcond_i32(TCG_COND_LEU, res, op1, op2, op1, op2);
8724 }
8725
8726 /* Pairwise op subgroup of C3.6.16.
8727  *
8728  * This is called directly or via the handle_3same_float for float pairwise
8729  * operations where the opcode and size are calculated differently.
8730  */
8731 static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
8732                                    int size, int rn, int rm, int rd)
8733 {
8734     TCGv_ptr fpst;
8735     int pass;
8736
8737     /* Floating point operations need fpst */
8738     if (opcode >= 0x58) {
8739         fpst = get_fpstatus_ptr();
8740     } else {
8741         TCGV_UNUSED_PTR(fpst);
8742     }
8743
8744     if (!fp_access_check(s)) {
8745         return;
8746     }
8747
8748     /* These operations work on the concatenated rm:rn, with each pair of
8749      * adjacent elements being operated on to produce an element in the result.
8750      */
8751     if (size == 3) {
8752         TCGv_i64 tcg_res[2];
8753
8754         for (pass = 0; pass < 2; pass++) {
8755             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8756             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8757             int passreg = (pass == 0) ? rn : rm;
8758
8759             read_vec_element(s, tcg_op1, passreg, 0, MO_64);
8760             read_vec_element(s, tcg_op2, passreg, 1, MO_64);
8761             tcg_res[pass] = tcg_temp_new_i64();
8762
8763             switch (opcode) {
8764             case 0x17: /* ADDP */
8765                 tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
8766                 break;
8767             case 0x58: /* FMAXNMP */
8768                 gen_helper_vfp_maxnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8769                 break;
8770             case 0x5a: /* FADDP */
8771                 gen_helper_vfp_addd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8772                 break;
8773             case 0x5e: /* FMAXP */
8774                 gen_helper_vfp_maxd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8775                 break;
8776             case 0x78: /* FMINNMP */
8777                 gen_helper_vfp_minnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8778                 break;
8779             case 0x7e: /* FMINP */
8780                 gen_helper_vfp_mind(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8781                 break;
8782             default:
8783                 g_assert_not_reached();
8784             }
8785
8786             tcg_temp_free_i64(tcg_op1);
8787             tcg_temp_free_i64(tcg_op2);
8788         }
8789
8790         for (pass = 0; pass < 2; pass++) {
8791             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
8792             tcg_temp_free_i64(tcg_res[pass]);
8793         }
8794     } else {
8795         int maxpass = is_q ? 4 : 2;
8796         TCGv_i32 tcg_res[4];
8797
8798         for (pass = 0; pass < maxpass; pass++) {
8799             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
8800             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
8801             NeonGenTwoOpFn *genfn = NULL;
8802             int passreg = pass < (maxpass / 2) ? rn : rm;
8803             int passelt = (is_q && (pass & 1)) ? 2 : 0;
8804
8805             read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_32);
8806             read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_32);
8807             tcg_res[pass] = tcg_temp_new_i32();
8808
8809             switch (opcode) {
8810             case 0x17: /* ADDP */
8811             {
8812                 static NeonGenTwoOpFn * const fns[3] = {
8813                     gen_helper_neon_padd_u8,
8814                     gen_helper_neon_padd_u16,
8815                     tcg_gen_add_i32,
8816                 };
8817                 genfn = fns[size];
8818                 break;
8819             }
8820             case 0x14: /* SMAXP, UMAXP */
8821             {
8822                 static NeonGenTwoOpFn * const fns[3][2] = {
8823                     { gen_helper_neon_pmax_s8, gen_helper_neon_pmax_u8 },
8824                     { gen_helper_neon_pmax_s16, gen_helper_neon_pmax_u16 },
8825                     { gen_max_s32, gen_max_u32 },
8826                 };
8827                 genfn = fns[size][u];
8828                 break;
8829             }
8830             case 0x15: /* SMINP, UMINP */
8831             {
8832                 static NeonGenTwoOpFn * const fns[3][2] = {
8833                     { gen_helper_neon_pmin_s8, gen_helper_neon_pmin_u8 },
8834                     { gen_helper_neon_pmin_s16, gen_helper_neon_pmin_u16 },
8835                     { gen_min_s32, gen_min_u32 },
8836                 };
8837                 genfn = fns[size][u];
8838                 break;
8839             }
8840             /* The FP operations are all on single floats (32 bit) */
8841             case 0x58: /* FMAXNMP */
8842                 gen_helper_vfp_maxnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8843                 break;
8844             case 0x5a: /* FADDP */
8845                 gen_helper_vfp_adds(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8846                 break;
8847             case 0x5e: /* FMAXP */
8848                 gen_helper_vfp_maxs(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8849                 break;
8850             case 0x78: /* FMINNMP */
8851                 gen_helper_vfp_minnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8852                 break;
8853             case 0x7e: /* FMINP */
8854                 gen_helper_vfp_mins(tcg_res[pass], tcg_op1, tcg_op2, fpst);
8855                 break;
8856             default:
8857                 g_assert_not_reached();
8858             }
8859
8860             /* FP ops called directly, otherwise call now */
8861             if (genfn) {
8862                 genfn(tcg_res[pass], tcg_op1, tcg_op2);
8863             }
8864
8865             tcg_temp_free_i32(tcg_op1);
8866             tcg_temp_free_i32(tcg_op2);
8867         }
8868
8869         for (pass = 0; pass < maxpass; pass++) {
8870             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
8871             tcg_temp_free_i32(tcg_res[pass]);
8872         }
8873         if (!is_q) {
8874             clear_vec_high(s, rd);
8875         }
8876     }
8877
8878     if (!TCGV_IS_UNUSED_PTR(fpst)) {
8879         tcg_temp_free_ptr(fpst);
8880     }
8881 }
8882
8883 /* Floating point op subgroup of C3.6.16. */
8884 static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
8885 {
8886     /* For floating point ops, the U, size[1] and opcode bits
8887      * together indicate the operation. size[0] indicates single
8888      * or double.
8889      */
8890     int fpopcode = extract32(insn, 11, 5)
8891         | (extract32(insn, 23, 1) << 5)
8892         | (extract32(insn, 29, 1) << 6);
8893     int is_q = extract32(insn, 30, 1);
8894     int size = extract32(insn, 22, 1);
8895     int rm = extract32(insn, 16, 5);
8896     int rn = extract32(insn, 5, 5);
8897     int rd = extract32(insn, 0, 5);
8898
8899     int datasize = is_q ? 128 : 64;
8900     int esize = 32 << size;
8901     int elements = datasize / esize;
8902
8903     if (size == 1 && !is_q) {
8904         unallocated_encoding(s);
8905         return;
8906     }
8907
8908     switch (fpopcode) {
8909     case 0x58: /* FMAXNMP */
8910     case 0x5a: /* FADDP */
8911     case 0x5e: /* FMAXP */
8912     case 0x78: /* FMINNMP */
8913     case 0x7e: /* FMINP */
8914         if (size && !is_q) {
8915             unallocated_encoding(s);
8916             return;
8917         }
8918         handle_simd_3same_pair(s, is_q, 0, fpopcode, size ? MO_64 : MO_32,
8919                                rn, rm, rd);
8920         return;
8921     case 0x1b: /* FMULX */
8922     case 0x1f: /* FRECPS */
8923     case 0x3f: /* FRSQRTS */
8924     case 0x5d: /* FACGE */
8925     case 0x7d: /* FACGT */
8926     case 0x19: /* FMLA */
8927     case 0x39: /* FMLS */
8928     case 0x18: /* FMAXNM */
8929     case 0x1a: /* FADD */
8930     case 0x1c: /* FCMEQ */
8931     case 0x1e: /* FMAX */
8932     case 0x38: /* FMINNM */
8933     case 0x3a: /* FSUB */
8934     case 0x3e: /* FMIN */
8935     case 0x5b: /* FMUL */
8936     case 0x5c: /* FCMGE */
8937     case 0x5f: /* FDIV */
8938     case 0x7a: /* FABD */
8939     case 0x7c: /* FCMGT */
8940         if (!fp_access_check(s)) {
8941             return;
8942         }
8943
8944         handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
8945         return;
8946     default:
8947         unallocated_encoding(s);
8948         return;
8949     }
8950 }
8951
8952 /* Integer op subgroup of C3.6.16. */
8953 static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
8954 {
8955     int is_q = extract32(insn, 30, 1);
8956     int u = extract32(insn, 29, 1);
8957     int size = extract32(insn, 22, 2);
8958     int opcode = extract32(insn, 11, 5);
8959     int rm = extract32(insn, 16, 5);
8960     int rn = extract32(insn, 5, 5);
8961     int rd = extract32(insn, 0, 5);
8962     int pass;
8963
8964     switch (opcode) {
8965     case 0x13: /* MUL, PMUL */
8966         if (u && size != 0) {
8967             unallocated_encoding(s);
8968             return;
8969         }
8970         /* fall through */
8971     case 0x0: /* SHADD, UHADD */
8972     case 0x2: /* SRHADD, URHADD */
8973     case 0x4: /* SHSUB, UHSUB */
8974     case 0xc: /* SMAX, UMAX */
8975     case 0xd: /* SMIN, UMIN */
8976     case 0xe: /* SABD, UABD */
8977     case 0xf: /* SABA, UABA */
8978     case 0x12: /* MLA, MLS */
8979         if (size == 3) {
8980             unallocated_encoding(s);
8981             return;
8982         }
8983         break;
8984     case 0x16: /* SQDMULH, SQRDMULH */
8985         if (size == 0 || size == 3) {
8986             unallocated_encoding(s);
8987             return;
8988         }
8989         break;
8990     default:
8991         if (size == 3 && !is_q) {
8992             unallocated_encoding(s);
8993             return;
8994         }
8995         break;
8996     }
8997
8998     if (!fp_access_check(s)) {
8999         return;
9000     }
9001
9002     if (size == 3) {
9003         for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
9004             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
9005             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
9006             TCGv_i64 tcg_res = tcg_temp_new_i64();
9007
9008             read_vec_element(s, tcg_op1, rn, pass, MO_64);
9009             read_vec_element(s, tcg_op2, rm, pass, MO_64);
9010
9011             handle_3same_64(s, opcode, u, tcg_res, tcg_op1, tcg_op2);
9012
9013             write_vec_element(s, tcg_res, rd, pass, MO_64);
9014
9015             tcg_temp_free_i64(tcg_res);
9016             tcg_temp_free_i64(tcg_op1);
9017             tcg_temp_free_i64(tcg_op2);
9018         }
9019     } else {
9020         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
9021             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
9022             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
9023             TCGv_i32 tcg_res = tcg_temp_new_i32();
9024             NeonGenTwoOpFn *genfn = NULL;
9025             NeonGenTwoOpEnvFn *genenvfn = NULL;
9026
9027             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
9028             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
9029
9030             switch (opcode) {
9031             case 0x0: /* SHADD, UHADD */
9032             {
9033                 static NeonGenTwoOpFn * const fns[3][2] = {
9034                     { gen_helper_neon_hadd_s8, gen_helper_neon_hadd_u8 },
9035                     { gen_helper_neon_hadd_s16, gen_helper_neon_hadd_u16 },
9036                     { gen_helper_neon_hadd_s32, gen_helper_neon_hadd_u32 },
9037                 };
9038                 genfn = fns[size][u];
9039                 break;
9040             }
9041             case 0x1: /* SQADD, UQADD */
9042             {
9043                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
9044                     { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 },
9045                     { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 },
9046                     { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 },
9047                 };
9048                 genenvfn = fns[size][u];
9049                 break;
9050             }
9051             case 0x2: /* SRHADD, URHADD */
9052             {
9053                 static NeonGenTwoOpFn * const fns[3][2] = {
9054                     { gen_helper_neon_rhadd_s8, gen_helper_neon_rhadd_u8 },
9055                     { gen_helper_neon_rhadd_s16, gen_helper_neon_rhadd_u16 },
9056                     { gen_helper_neon_rhadd_s32, gen_helper_neon_rhadd_u32 },
9057                 };
9058                 genfn = fns[size][u];
9059                 break;
9060             }
9061             case 0x4: /* SHSUB, UHSUB */
9062             {
9063                 static NeonGenTwoOpFn * const fns[3][2] = {
9064                     { gen_helper_neon_hsub_s8, gen_helper_neon_hsub_u8 },
9065                     { gen_helper_neon_hsub_s16, gen_helper_neon_hsub_u16 },
9066                     { gen_helper_neon_hsub_s32, gen_helper_neon_hsub_u32 },
9067                 };
9068                 genfn = fns[size][u];
9069                 break;
9070             }
9071             case 0x5: /* SQSUB, UQSUB */
9072             {
9073                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
9074                     { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 },
9075                     { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 },
9076                     { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 },
9077                 };
9078                 genenvfn = fns[size][u];
9079                 break;
9080             }
9081             case 0x6: /* CMGT, CMHI */
9082             {
9083                 static NeonGenTwoOpFn * const fns[3][2] = {
9084                     { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_u8 },
9085                     { gen_helper_neon_cgt_s16, gen_helper_neon_cgt_u16 },
9086                     { gen_helper_neon_cgt_s32, gen_helper_neon_cgt_u32 },
9087                 };
9088                 genfn = fns[size][u];
9089                 break;
9090             }
9091             case 0x7: /* CMGE, CMHS */
9092             {
9093                 static NeonGenTwoOpFn * const fns[3][2] = {
9094                     { gen_helper_neon_cge_s8, gen_helper_neon_cge_u8 },
9095                     { gen_helper_neon_cge_s16, gen_helper_neon_cge_u16 },
9096                     { gen_helper_neon_cge_s32, gen_helper_neon_cge_u32 },
9097                 };
9098                 genfn = fns[size][u];
9099                 break;
9100             }
9101             case 0x8: /* SSHL, USHL */
9102             {
9103                 static NeonGenTwoOpFn * const fns[3][2] = {
9104                     { gen_helper_neon_shl_s8, gen_helper_neon_shl_u8 },
9105                     { gen_helper_neon_shl_s16, gen_helper_neon_shl_u16 },
9106                     { gen_helper_neon_shl_s32, gen_helper_neon_shl_u32 },
9107                 };
9108                 genfn = fns[size][u];
9109                 break;
9110             }
9111             case 0x9: /* SQSHL, UQSHL */
9112             {
9113                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
9114                     { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
9115                     { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
9116                     { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
9117                 };
9118                 genenvfn = fns[size][u];
9119                 break;
9120             }
9121             case 0xa: /* SRSHL, URSHL */
9122             {
9123                 static NeonGenTwoOpFn * const fns[3][2] = {
9124                     { gen_helper_neon_rshl_s8, gen_helper_neon_rshl_u8 },
9125                     { gen_helper_neon_rshl_s16, gen_helper_neon_rshl_u16 },
9126                     { gen_helper_neon_rshl_s32, gen_helper_neon_rshl_u32 },
9127                 };
9128                 genfn = fns[size][u];
9129                 break;
9130             }
9131             case 0xb: /* SQRSHL, UQRSHL */
9132             {
9133                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
9134                     { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
9135                     { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
9136                     { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
9137                 };
9138                 genenvfn = fns[size][u];
9139                 break;
9140             }
9141             case 0xc: /* SMAX, UMAX */
9142             {
9143                 static NeonGenTwoOpFn * const fns[3][2] = {
9144                     { gen_helper_neon_max_s8, gen_helper_neon_max_u8 },
9145                     { gen_helper_neon_max_s16, gen_helper_neon_max_u16 },
9146                     { gen_max_s32, gen_max_u32 },
9147                 };
9148                 genfn = fns[size][u];
9149                 break;
9150             }
9151
9152             case 0xd: /* SMIN, UMIN */
9153             {
9154                 static NeonGenTwoOpFn * const fns[3][2] = {
9155                     { gen_helper_neon_min_s8, gen_helper_neon_min_u8 },
9156                     { gen_helper_neon_min_s16, gen_helper_neon_min_u16 },
9157                     { gen_min_s32, gen_min_u32 },
9158                 };
9159                 genfn = fns[size][u];
9160                 break;
9161             }
9162             case 0xe: /* SABD, UABD */
9163             case 0xf: /* SABA, UABA */
9164             {
9165                 static NeonGenTwoOpFn * const fns[3][2] = {
9166                     { gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 },
9167                     { gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 },
9168                     { gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 },
9169                 };
9170                 genfn = fns[size][u];
9171                 break;
9172             }
9173             case 0x10: /* ADD, SUB */
9174             {
9175                 static NeonGenTwoOpFn * const fns[3][2] = {
9176                     { gen_helper_neon_add_u8, gen_helper_neon_sub_u8 },
9177                     { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
9178                     { tcg_gen_add_i32, tcg_gen_sub_i32 },
9179                 };
9180                 genfn = fns[size][u];
9181                 break;
9182             }
9183             case 0x11: /* CMTST, CMEQ */
9184             {
9185                 static NeonGenTwoOpFn * const fns[3][2] = {
9186                     { gen_helper_neon_tst_u8, gen_helper_neon_ceq_u8 },
9187                     { gen_helper_neon_tst_u16, gen_helper_neon_ceq_u16 },
9188                     { gen_helper_neon_tst_u32, gen_helper_neon_ceq_u32 },
9189                 };
9190                 genfn = fns[size][u];
9191                 break;
9192             }
9193             case 0x13: /* MUL, PMUL */
9194                 if (u) {
9195                     /* PMUL */
9196                     assert(size == 0);
9197                     genfn = gen_helper_neon_mul_p8;
9198                     break;
9199                 }
9200                 /* fall through : MUL */
9201             case 0x12: /* MLA, MLS */
9202             {
9203                 static NeonGenTwoOpFn * const fns[3] = {
9204                     gen_helper_neon_mul_u8,
9205                     gen_helper_neon_mul_u16,
9206                     tcg_gen_mul_i32,
9207                 };
9208                 genfn = fns[size];
9209                 break;
9210             }
9211             case 0x16: /* SQDMULH, SQRDMULH */
9212             {
9213                 static NeonGenTwoOpEnvFn * const fns[2][2] = {
9214                     { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
9215                     { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
9216                 };
9217                 assert(size == 1 || size == 2);
9218                 genenvfn = fns[size - 1][u];
9219                 break;
9220             }
9221             default:
9222                 g_assert_not_reached();
9223             }
9224
9225             if (genenvfn) {
9226                 genenvfn(tcg_res, cpu_env, tcg_op1, tcg_op2);
9227             } else {
9228                 genfn(tcg_res, tcg_op1, tcg_op2);
9229             }
9230
9231             if (opcode == 0xf || opcode == 0x12) {
9232                 /* SABA, UABA, MLA, MLS: accumulating ops */
9233                 static NeonGenTwoOpFn * const fns[3][2] = {
9234                     { gen_helper_neon_add_u8, gen_helper_neon_sub_u8 },
9235                     { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
9236                     { tcg_gen_add_i32, tcg_gen_sub_i32 },
9237                 };
9238                 bool is_sub = (opcode == 0x12 && u); /* MLS */
9239
9240                 genfn = fns[size][is_sub];
9241                 read_vec_element_i32(s, tcg_op1, rd, pass, MO_32);
9242                 genfn(tcg_res, tcg_op1, tcg_res);
9243             }
9244
9245             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
9246
9247             tcg_temp_free_i32(tcg_res);
9248             tcg_temp_free_i32(tcg_op1);
9249             tcg_temp_free_i32(tcg_op2);
9250         }
9251     }
9252
9253     if (!is_q) {
9254         clear_vec_high(s, rd);
9255     }
9256 }
9257
9258 /* C3.6.16 AdvSIMD three same
9259  *  31  30  29  28       24 23  22  21 20  16 15    11  10 9    5 4    0
9260  * +---+---+---+-----------+------+---+------+--------+---+------+------+
9261  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
9262  * +---+---+---+-----------+------+---+------+--------+---+------+------+
9263  */
9264 static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
9265 {
9266     int opcode = extract32(insn, 11, 5);
9267
9268     switch (opcode) {
9269     case 0x3: /* logic ops */
9270         disas_simd_3same_logic(s, insn);
9271         break;
9272     case 0x17: /* ADDP */
9273     case 0x14: /* SMAXP, UMAXP */
9274     case 0x15: /* SMINP, UMINP */
9275     {
9276         /* Pairwise operations */
9277         int is_q = extract32(insn, 30, 1);
9278         int u = extract32(insn, 29, 1);
9279         int size = extract32(insn, 22, 2);
9280         int rm = extract32(insn, 16, 5);
9281         int rn = extract32(insn, 5, 5);
9282         int rd = extract32(insn, 0, 5);
9283         if (opcode == 0x17) {
9284             if (u || (size == 3 && !is_q)) {
9285                 unallocated_encoding(s);
9286                 return;
9287             }
9288         } else {
9289             if (size == 3) {
9290                 unallocated_encoding(s);
9291                 return;
9292             }
9293         }
9294         handle_simd_3same_pair(s, is_q, u, opcode, size, rn, rm, rd);
9295         break;
9296     }
9297     case 0x18 ... 0x31:
9298         /* floating point ops, sz[1] and U are part of opcode */
9299         disas_simd_3same_float(s, insn);
9300         break;
9301     default:
9302         disas_simd_3same_int(s, insn);
9303         break;
9304     }
9305 }
9306
9307 static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
9308                                   int size, int rn, int rd)
9309 {
9310     /* Handle 2-reg-misc ops which are widening (so each size element
9311      * in the source becomes a 2*size element in the destination.
9312      * The only instruction like this is FCVTL.
9313      */
9314     int pass;
9315
9316     if (size == 3) {
9317         /* 32 -> 64 bit fp conversion */
9318         TCGv_i64 tcg_res[2];
9319         int srcelt = is_q ? 2 : 0;
9320
9321         for (pass = 0; pass < 2; pass++) {
9322             TCGv_i32 tcg_op = tcg_temp_new_i32();
9323             tcg_res[pass] = tcg_temp_new_i64();
9324
9325             read_vec_element_i32(s, tcg_op, rn, srcelt + pass, MO_32);
9326             gen_helper_vfp_fcvtds(tcg_res[pass], tcg_op, cpu_env);
9327             tcg_temp_free_i32(tcg_op);
9328         }
9329         for (pass = 0; pass < 2; pass++) {
9330             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
9331             tcg_temp_free_i64(tcg_res[pass]);
9332         }
9333     } else {
9334         /* 16 -> 32 bit fp conversion */
9335         int srcelt = is_q ? 4 : 0;
9336         TCGv_i32 tcg_res[4];
9337
9338         for (pass = 0; pass < 4; pass++) {
9339             tcg_res[pass] = tcg_temp_new_i32();
9340
9341             read_vec_element_i32(s, tcg_res[pass], rn, srcelt + pass, MO_16);
9342             gen_helper_vfp_fcvt_f16_to_f32(tcg_res[pass], tcg_res[pass],
9343                                            cpu_env);
9344         }
9345         for (pass = 0; pass < 4; pass++) {
9346             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
9347             tcg_temp_free_i32(tcg_res[pass]);
9348         }
9349     }
9350 }
9351
9352 static void handle_rev(DisasContext *s, int opcode, bool u,
9353                        bool is_q, int size, int rn, int rd)
9354 {
9355     int op = (opcode << 1) | u;
9356     int opsz = op + size;
9357     int grp_size = 3 - opsz;
9358     int dsize = is_q ? 128 : 64;
9359     int i;
9360
9361     if (opsz >= 3) {
9362         unallocated_encoding(s);
9363         return;
9364     }
9365
9366     if (!fp_access_check(s)) {
9367         return;
9368     }
9369
9370     if (size == 0) {
9371         /* Special case bytes, use bswap op on each group of elements */
9372         int groups = dsize / (8 << grp_size);
9373
9374         for (i = 0; i < groups; i++) {
9375             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
9376
9377             read_vec_element(s, tcg_tmp, rn, i, grp_size);
9378             switch (grp_size) {
9379             case MO_16:
9380                 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
9381                 break;
9382             case MO_32:
9383                 tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
9384                 break;
9385             case MO_64:
9386                 tcg_gen_bswap64_i64(tcg_tmp, tcg_tmp);
9387                 break;
9388             default:
9389                 g_assert_not_reached();
9390             }
9391             write_vec_element(s, tcg_tmp, rd, i, grp_size);
9392             tcg_temp_free_i64(tcg_tmp);
9393         }
9394         if (!is_q) {
9395             clear_vec_high(s, rd);
9396         }
9397     } else {
9398         int revmask = (1 << grp_size) - 1;
9399         int esize = 8 << size;
9400         int elements = dsize / esize;
9401         TCGv_i64 tcg_rn = tcg_temp_new_i64();
9402         TCGv_i64 tcg_rd = tcg_const_i64(0);
9403         TCGv_i64 tcg_rd_hi = tcg_const_i64(0);
9404
9405         for (i = 0; i < elements; i++) {
9406             int e_rev = (i & 0xf) ^ revmask;
9407             int off = e_rev * esize;
9408             read_vec_element(s, tcg_rn, rn, i, size);
9409             if (off >= 64) {
9410                 tcg_gen_deposit_i64(tcg_rd_hi, tcg_rd_hi,
9411                                     tcg_rn, off - 64, esize);
9412             } else {
9413                 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, off, esize);
9414             }
9415         }
9416         write_vec_element(s, tcg_rd, rd, 0, MO_64);
9417         write_vec_element(s, tcg_rd_hi, rd, 1, MO_64);
9418
9419         tcg_temp_free_i64(tcg_rd_hi);
9420         tcg_temp_free_i64(tcg_rd);
9421         tcg_temp_free_i64(tcg_rn);
9422     }
9423 }
9424
9425 static void handle_2misc_pairwise(DisasContext *s, int opcode, bool u,
9426                                   bool is_q, int size, int rn, int rd)
9427 {
9428     /* Implement the pairwise operations from 2-misc:
9429      * SADDLP, UADDLP, SADALP, UADALP.
9430      * These all add pairs of elements in the input to produce a
9431      * double-width result element in the output (possibly accumulating).
9432      */
9433     bool accum = (opcode == 0x6);
9434     int maxpass = is_q ? 2 : 1;
9435     int pass;
9436     TCGv_i64 tcg_res[2];
9437
9438     if (size == 2) {
9439         /* 32 + 32 -> 64 op */
9440         TCGMemOp memop = size + (u ? 0 : MO_SIGN);
9441
9442         for (pass = 0; pass < maxpass; pass++) {
9443             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
9444             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
9445
9446             tcg_res[pass] = tcg_temp_new_i64();
9447
9448             read_vec_element(s, tcg_op1, rn, pass * 2, memop);
9449             read_vec_element(s, tcg_op2, rn, pass * 2 + 1, memop);
9450             tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
9451             if (accum) {
9452                 read_vec_element(s, tcg_op1, rd, pass, MO_64);
9453                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
9454             }
9455
9456             tcg_temp_free_i64(tcg_op1);
9457             tcg_temp_free_i64(tcg_op2);
9458         }
9459     } else {
9460         for (pass = 0; pass < maxpass; pass++) {
9461             TCGv_i64 tcg_op = tcg_temp_new_i64();
9462             NeonGenOneOpFn *genfn;
9463             static NeonGenOneOpFn * const fns[2][2] = {
9464                 { gen_helper_neon_addlp_s8,  gen_helper_neon_addlp_u8 },
9465                 { gen_helper_neon_addlp_s16,  gen_helper_neon_addlp_u16 },
9466             };
9467
9468             genfn = fns[size][u];
9469
9470             tcg_res[pass] = tcg_temp_new_i64();
9471
9472             read_vec_element(s, tcg_op, rn, pass, MO_64);
9473             genfn(tcg_res[pass], tcg_op);
9474
9475             if (accum) {
9476                 read_vec_element(s, tcg_op, rd, pass, MO_64);
9477                 if (size == 0) {
9478                     gen_helper_neon_addl_u16(tcg_res[pass],
9479                                              tcg_res[pass], tcg_op);
9480                 } else {
9481                     gen_helper_neon_addl_u32(tcg_res[pass],
9482                                              tcg_res[pass], tcg_op);
9483                 }
9484             }
9485             tcg_temp_free_i64(tcg_op);
9486         }
9487     }
9488     if (!is_q) {
9489         tcg_res[1] = tcg_const_i64(0);
9490     }
9491     for (pass = 0; pass < 2; pass++) {
9492         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
9493         tcg_temp_free_i64(tcg_res[pass]);
9494     }
9495 }
9496
9497 static void handle_shll(DisasContext *s, bool is_q, int size, int rn, int rd)
9498 {
9499     /* Implement SHLL and SHLL2 */
9500     int pass;
9501     int part = is_q ? 2 : 0;
9502     TCGv_i64 tcg_res[2];
9503
9504     for (pass = 0; pass < 2; pass++) {
9505         static NeonGenWidenFn * const widenfns[3] = {
9506             gen_helper_neon_widen_u8,
9507             gen_helper_neon_widen_u16,
9508             tcg_gen_extu_i32_i64,
9509         };
9510         NeonGenWidenFn *widenfn = widenfns[size];
9511         TCGv_i32 tcg_op = tcg_temp_new_i32();
9512
9513         read_vec_element_i32(s, tcg_op, rn, part + pass, MO_32);
9514         tcg_res[pass] = tcg_temp_new_i64();
9515         widenfn(tcg_res[pass], tcg_op);
9516         tcg_gen_shli_i64(tcg_res[pass], tcg_res[pass], 8 << size);
9517
9518         tcg_temp_free_i32(tcg_op);
9519     }
9520
9521     for (pass = 0; pass < 2; pass++) {
9522         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
9523         tcg_temp_free_i64(tcg_res[pass]);
9524     }
9525 }
9526
9527 /* C3.6.17 AdvSIMD two reg misc
9528  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
9529  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
9530  * | 0 | Q | U | 0 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
9531  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
9532  */
9533 static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
9534 {
9535     int size = extract32(insn, 22, 2);
9536     int opcode = extract32(insn, 12, 5);
9537     bool u = extract32(insn, 29, 1);
9538     bool is_q = extract32(insn, 30, 1);
9539     int rn = extract32(insn, 5, 5);
9540     int rd = extract32(insn, 0, 5);
9541     bool need_fpstatus = false;
9542     bool need_rmode = false;
9543     int rmode = -1;
9544     TCGv_i32 tcg_rmode;
9545     TCGv_ptr tcg_fpstatus;
9546
9547     switch (opcode) {
9548     case 0x0: /* REV64, REV32 */
9549     case 0x1: /* REV16 */
9550         handle_rev(s, opcode, u, is_q, size, rn, rd);
9551         return;
9552     case 0x5: /* CNT, NOT, RBIT */
9553         if (u && size == 0) {
9554             /* NOT: adjust size so we can use the 64-bits-at-a-time loop. */
9555             size = 3;
9556             break;
9557         } else if (u && size == 1) {
9558             /* RBIT */
9559             break;
9560         } else if (!u && size == 0) {
9561             /* CNT */
9562             break;
9563         }
9564         unallocated_encoding(s);
9565         return;
9566     case 0x12: /* XTN, XTN2, SQXTUN, SQXTUN2 */
9567     case 0x14: /* SQXTN, SQXTN2, UQXTN, UQXTN2 */
9568         if (size == 3) {
9569             unallocated_encoding(s);
9570             return;
9571         }
9572         if (!fp_access_check(s)) {
9573             return;
9574         }
9575
9576         handle_2misc_narrow(s, false, opcode, u, is_q, size, rn, rd);
9577         return;
9578     case 0x4: /* CLS, CLZ */
9579         if (size == 3) {
9580             unallocated_encoding(s);
9581             return;
9582         }
9583         break;
9584     case 0x2: /* SADDLP, UADDLP */
9585     case 0x6: /* SADALP, UADALP */
9586         if (size == 3) {
9587             unallocated_encoding(s);
9588             return;
9589         }
9590         if (!fp_access_check(s)) {
9591             return;
9592         }
9593         handle_2misc_pairwise(s, opcode, u, is_q, size, rn, rd);
9594         return;
9595     case 0x13: /* SHLL, SHLL2 */
9596         if (u == 0 || size == 3) {
9597             unallocated_encoding(s);
9598             return;
9599         }
9600         if (!fp_access_check(s)) {
9601             return;
9602         }
9603         handle_shll(s, is_q, size, rn, rd);
9604         return;
9605     case 0xa: /* CMLT */
9606         if (u == 1) {
9607             unallocated_encoding(s);
9608             return;
9609         }
9610         /* fall through */
9611     case 0x8: /* CMGT, CMGE */
9612     case 0x9: /* CMEQ, CMLE */
9613     case 0xb: /* ABS, NEG */
9614         if (size == 3 && !is_q) {
9615             unallocated_encoding(s);
9616             return;
9617         }
9618         break;
9619     case 0x3: /* SUQADD, USQADD */
9620         if (size == 3 && !is_q) {
9621             unallocated_encoding(s);
9622             return;
9623         }
9624         if (!fp_access_check(s)) {
9625             return;
9626         }
9627         handle_2misc_satacc(s, false, u, is_q, size, rn, rd);
9628         return;
9629     case 0x7: /* SQABS, SQNEG */
9630         if (size == 3 && !is_q) {
9631             unallocated_encoding(s);
9632             return;
9633         }
9634         break;
9635     case 0xc ... 0xf:
9636     case 0x16 ... 0x1d:
9637     case 0x1f:
9638     {
9639         /* Floating point: U, size[1] and opcode indicate operation;
9640          * size[0] indicates single or double precision.
9641          */
9642         int is_double = extract32(size, 0, 1);
9643         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
9644         size = is_double ? 3 : 2;
9645         switch (opcode) {
9646         case 0x2f: /* FABS */
9647         case 0x6f: /* FNEG */
9648             if (size == 3 && !is_q) {
9649                 unallocated_encoding(s);
9650                 return;
9651             }
9652             break;
9653         case 0x1d: /* SCVTF */
9654         case 0x5d: /* UCVTF */
9655         {
9656             bool is_signed = (opcode == 0x1d) ? true : false;
9657             int elements = is_double ? 2 : is_q ? 4 : 2;
9658             if (is_double && !is_q) {
9659                 unallocated_encoding(s);
9660                 return;
9661             }
9662             if (!fp_access_check(s)) {
9663                 return;
9664             }
9665             handle_simd_intfp_conv(s, rd, rn, elements, is_signed, 0, size);
9666             return;
9667         }
9668         case 0x2c: /* FCMGT (zero) */
9669         case 0x2d: /* FCMEQ (zero) */
9670         case 0x2e: /* FCMLT (zero) */
9671         case 0x6c: /* FCMGE (zero) */
9672         case 0x6d: /* FCMLE (zero) */
9673             if (size == 3 && !is_q) {
9674                 unallocated_encoding(s);
9675                 return;
9676             }
9677             handle_2misc_fcmp_zero(s, opcode, false, u, is_q, size, rn, rd);
9678             return;
9679         case 0x7f: /* FSQRT */
9680             if (size == 3 && !is_q) {
9681                 unallocated_encoding(s);
9682                 return;
9683             }
9684             break;
9685         case 0x1a: /* FCVTNS */
9686         case 0x1b: /* FCVTMS */
9687         case 0x3a: /* FCVTPS */
9688         case 0x3b: /* FCVTZS */
9689         case 0x5a: /* FCVTNU */
9690         case 0x5b: /* FCVTMU */
9691         case 0x7a: /* FCVTPU */
9692         case 0x7b: /* FCVTZU */
9693             need_fpstatus = true;
9694             need_rmode = true;
9695             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
9696             if (size == 3 && !is_q) {
9697                 unallocated_encoding(s);
9698                 return;
9699             }
9700             break;
9701         case 0x5c: /* FCVTAU */
9702         case 0x1c: /* FCVTAS */
9703             need_fpstatus = true;
9704             need_rmode = true;
9705             rmode = FPROUNDING_TIEAWAY;
9706             if (size == 3 && !is_q) {
9707                 unallocated_encoding(s);
9708                 return;
9709             }
9710             break;
9711         case 0x3c: /* URECPE */
9712             if (size == 3) {
9713                 unallocated_encoding(s);
9714                 return;
9715             }
9716             /* fall through */
9717         case 0x3d: /* FRECPE */
9718         case 0x7d: /* FRSQRTE */
9719             if (size == 3 && !is_q) {
9720                 unallocated_encoding(s);
9721                 return;
9722             }
9723             if (!fp_access_check(s)) {
9724                 return;
9725             }
9726             handle_2misc_reciprocal(s, opcode, false, u, is_q, size, rn, rd);
9727             return;
9728         case 0x56: /* FCVTXN, FCVTXN2 */
9729             if (size == 2) {
9730                 unallocated_encoding(s);
9731                 return;
9732             }
9733             /* fall through */
9734         case 0x16: /* FCVTN, FCVTN2 */
9735             /* handle_2misc_narrow does a 2*size -> size operation, but these
9736              * instructions encode the source size rather than dest size.
9737              */
9738             if (!fp_access_check(s)) {
9739                 return;
9740             }
9741             handle_2misc_narrow(s, false, opcode, 0, is_q, size - 1, rn, rd);
9742             return;
9743         case 0x17: /* FCVTL, FCVTL2 */
9744             if (!fp_access_check(s)) {
9745                 return;
9746             }
9747             handle_2misc_widening(s, opcode, is_q, size, rn, rd);
9748             return;
9749         case 0x18: /* FRINTN */
9750         case 0x19: /* FRINTM */
9751         case 0x38: /* FRINTP */
9752         case 0x39: /* FRINTZ */
9753             need_rmode = true;
9754             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
9755             /* fall through */
9756         case 0x59: /* FRINTX */
9757         case 0x79: /* FRINTI */
9758             need_fpstatus = true;
9759             if (size == 3 && !is_q) {
9760                 unallocated_encoding(s);
9761                 return;
9762             }
9763             break;
9764         case 0x58: /* FRINTA */
9765             need_rmode = true;
9766             rmode = FPROUNDING_TIEAWAY;
9767             need_fpstatus = true;
9768             if (size == 3 && !is_q) {
9769                 unallocated_encoding(s);
9770                 return;
9771             }
9772             break;
9773         case 0x7c: /* URSQRTE */
9774             if (size == 3) {
9775                 unallocated_encoding(s);
9776                 return;
9777             }
9778             need_fpstatus = true;
9779             break;
9780         default:
9781             unallocated_encoding(s);
9782             return;
9783         }
9784         break;
9785     }
9786     default:
9787         unallocated_encoding(s);
9788         return;
9789     }
9790
9791     if (!fp_access_check(s)) {
9792         return;
9793     }
9794
9795     if (need_fpstatus) {
9796         tcg_fpstatus = get_fpstatus_ptr();
9797     } else {
9798         TCGV_UNUSED_PTR(tcg_fpstatus);
9799     }
9800     if (need_rmode) {
9801         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
9802         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
9803     } else {
9804         TCGV_UNUSED_I32(tcg_rmode);
9805     }
9806
9807     if (size == 3) {
9808         /* All 64-bit element operations can be shared with scalar 2misc */
9809         int pass;
9810
9811         for (pass = 0; pass < (is_q ? 2 : 1); pass++) {
9812             TCGv_i64 tcg_op = tcg_temp_new_i64();
9813             TCGv_i64 tcg_res = tcg_temp_new_i64();
9814
9815             read_vec_element(s, tcg_op, rn, pass, MO_64);
9816
9817             handle_2misc_64(s, opcode, u, tcg_res, tcg_op,
9818                             tcg_rmode, tcg_fpstatus);
9819
9820             write_vec_element(s, tcg_res, rd, pass, MO_64);
9821
9822             tcg_temp_free_i64(tcg_res);
9823             tcg_temp_free_i64(tcg_op);
9824         }
9825     } else {
9826         int pass;
9827
9828         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
9829             TCGv_i32 tcg_op = tcg_temp_new_i32();
9830             TCGv_i32 tcg_res = tcg_temp_new_i32();
9831             TCGCond cond;
9832
9833             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
9834
9835             if (size == 2) {
9836                 /* Special cases for 32 bit elements */
9837                 switch (opcode) {
9838                 case 0xa: /* CMLT */
9839                     /* 32 bit integer comparison against zero, result is
9840                      * test ? (2^32 - 1) : 0. We implement via setcond(test)
9841                      * and inverting.
9842                      */
9843                     cond = TCG_COND_LT;
9844                 do_cmop:
9845                     tcg_gen_setcondi_i32(cond, tcg_res, tcg_op, 0);
9846                     tcg_gen_neg_i32(tcg_res, tcg_res);
9847                     break;
9848                 case 0x8: /* CMGT, CMGE */
9849                     cond = u ? TCG_COND_GE : TCG_COND_GT;
9850                     goto do_cmop;
9851                 case 0x9: /* CMEQ, CMLE */
9852                     cond = u ? TCG_COND_LE : TCG_COND_EQ;
9853                     goto do_cmop;
9854                 case 0x4: /* CLS */
9855                     if (u) {
9856                         gen_helper_clz32(tcg_res, tcg_op);
9857                     } else {
9858                         gen_helper_cls32(tcg_res, tcg_op);
9859                     }
9860                     break;
9861                 case 0x7: /* SQABS, SQNEG */
9862                     if (u) {
9863                         gen_helper_neon_qneg_s32(tcg_res, cpu_env, tcg_op);
9864                     } else {
9865                         gen_helper_neon_qabs_s32(tcg_res, cpu_env, tcg_op);
9866                     }
9867                     break;
9868                 case 0xb: /* ABS, NEG */
9869                     if (u) {
9870                         tcg_gen_neg_i32(tcg_res, tcg_op);
9871                     } else {
9872                         TCGv_i32 tcg_zero = tcg_const_i32(0);
9873                         tcg_gen_neg_i32(tcg_res, tcg_op);
9874                         tcg_gen_movcond_i32(TCG_COND_GT, tcg_res, tcg_op,
9875                                             tcg_zero, tcg_op, tcg_res);
9876                         tcg_temp_free_i32(tcg_zero);
9877                     }
9878                     break;
9879                 case 0x2f: /* FABS */
9880                     gen_helper_vfp_abss(tcg_res, tcg_op);
9881                     break;
9882                 case 0x6f: /* FNEG */
9883                     gen_helper_vfp_negs(tcg_res, tcg_op);
9884                     break;
9885                 case 0x7f: /* FSQRT */
9886                     gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
9887                     break;
9888                 case 0x1a: /* FCVTNS */
9889                 case 0x1b: /* FCVTMS */
9890                 case 0x1c: /* FCVTAS */
9891                 case 0x3a: /* FCVTPS */
9892                 case 0x3b: /* FCVTZS */
9893                 {
9894                     TCGv_i32 tcg_shift = tcg_const_i32(0);
9895                     gen_helper_vfp_tosls(tcg_res, tcg_op,
9896                                          tcg_shift, tcg_fpstatus);
9897                     tcg_temp_free_i32(tcg_shift);
9898                     break;
9899                 }
9900                 case 0x5a: /* FCVTNU */
9901                 case 0x5b: /* FCVTMU */
9902                 case 0x5c: /* FCVTAU */
9903                 case 0x7a: /* FCVTPU */
9904                 case 0x7b: /* FCVTZU */
9905                 {
9906                     TCGv_i32 tcg_shift = tcg_const_i32(0);
9907                     gen_helper_vfp_touls(tcg_res, tcg_op,
9908                                          tcg_shift, tcg_fpstatus);
9909                     tcg_temp_free_i32(tcg_shift);
9910                     break;
9911                 }
9912                 case 0x18: /* FRINTN */
9913                 case 0x19: /* FRINTM */
9914                 case 0x38: /* FRINTP */
9915                 case 0x39: /* FRINTZ */
9916                 case 0x58: /* FRINTA */
9917                 case 0x79: /* FRINTI */
9918                     gen_helper_rints(tcg_res, tcg_op, tcg_fpstatus);
9919                     break;
9920                 case 0x59: /* FRINTX */
9921                     gen_helper_rints_exact(tcg_res, tcg_op, tcg_fpstatus);
9922                     break;
9923                 case 0x7c: /* URSQRTE */
9924                     gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
9925                     break;
9926                 default:
9927                     g_assert_not_reached();
9928                 }
9929             } else {
9930                 /* Use helpers for 8 and 16 bit elements */
9931                 switch (opcode) {
9932                 case 0x5: /* CNT, RBIT */
9933                     /* For these two insns size is part of the opcode specifier
9934                      * (handled earlier); they always operate on byte elements.
9935                      */
9936                     if (u) {
9937                         gen_helper_neon_rbit_u8(tcg_res, tcg_op);
9938                     } else {
9939                         gen_helper_neon_cnt_u8(tcg_res, tcg_op);
9940                     }
9941                     break;
9942                 case 0x7: /* SQABS, SQNEG */
9943                 {
9944                     NeonGenOneOpEnvFn *genfn;
9945                     static NeonGenOneOpEnvFn * const fns[2][2] = {
9946                         { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
9947                         { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
9948                     };
9949                     genfn = fns[size][u];
9950                     genfn(tcg_res, cpu_env, tcg_op);
9951                     break;
9952                 }
9953                 case 0x8: /* CMGT, CMGE */
9954                 case 0x9: /* CMEQ, CMLE */
9955                 case 0xa: /* CMLT */
9956                 {
9957                     static NeonGenTwoOpFn * const fns[3][2] = {
9958                         { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_s16 },
9959                         { gen_helper_neon_cge_s8, gen_helper_neon_cge_s16 },
9960                         { gen_helper_neon_ceq_u8, gen_helper_neon_ceq_u16 },
9961                     };
9962                     NeonGenTwoOpFn *genfn;
9963                     int comp;
9964                     bool reverse;
9965                     TCGv_i32 tcg_zero = tcg_const_i32(0);
9966
9967                     /* comp = index into [CMGT, CMGE, CMEQ, CMLE, CMLT] */
9968                     comp = (opcode - 0x8) * 2 + u;
9969                     /* ...but LE, LT are implemented as reverse GE, GT */
9970                     reverse = (comp > 2);
9971                     if (reverse) {
9972                         comp = 4 - comp;
9973                     }
9974                     genfn = fns[comp][size];
9975                     if (reverse) {
9976                         genfn(tcg_res, tcg_zero, tcg_op);
9977                     } else {
9978                         genfn(tcg_res, tcg_op, tcg_zero);
9979                     }
9980                     tcg_temp_free_i32(tcg_zero);
9981                     break;
9982                 }
9983                 case 0xb: /* ABS, NEG */
9984                     if (u) {
9985                         TCGv_i32 tcg_zero = tcg_const_i32(0);
9986                         if (size) {
9987                             gen_helper_neon_sub_u16(tcg_res, tcg_zero, tcg_op);
9988                         } else {
9989                             gen_helper_neon_sub_u8(tcg_res, tcg_zero, tcg_op);
9990                         }
9991                         tcg_temp_free_i32(tcg_zero);
9992                     } else {
9993                         if (size) {
9994                             gen_helper_neon_abs_s16(tcg_res, tcg_op);
9995                         } else {
9996                             gen_helper_neon_abs_s8(tcg_res, tcg_op);
9997                         }
9998                     }
9999                     break;
10000                 case 0x4: /* CLS, CLZ */
10001                     if (u) {
10002                         if (size == 0) {
10003                             gen_helper_neon_clz_u8(tcg_res, tcg_op);
10004                         } else {
10005                             gen_helper_neon_clz_u16(tcg_res, tcg_op);
10006                         }
10007                     } else {
10008                         if (size == 0) {
10009                             gen_helper_neon_cls_s8(tcg_res, tcg_op);
10010                         } else {
10011                             gen_helper_neon_cls_s16(tcg_res, tcg_op);
10012                         }
10013                     }
10014                     break;
10015                 default:
10016                     g_assert_not_reached();
10017                 }
10018             }
10019
10020             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
10021
10022             tcg_temp_free_i32(tcg_res);
10023             tcg_temp_free_i32(tcg_op);
10024         }
10025     }
10026     if (!is_q) {
10027         clear_vec_high(s, rd);
10028     }
10029
10030     if (need_rmode) {
10031         gen_helper_set_rmode(tcg_rmode, tcg_rmode, cpu_env);
10032         tcg_temp_free_i32(tcg_rmode);
10033     }
10034     if (need_fpstatus) {
10035         tcg_temp_free_ptr(tcg_fpstatus);
10036     }
10037 }
10038
10039 /* C3.6.13 AdvSIMD scalar x indexed element
10040  *  31 30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
10041  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
10042  * | 0 1 | U | 1 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
10043  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
10044  * C3.6.18 AdvSIMD vector x indexed element
10045  *   31  30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
10046  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
10047  * | 0 | Q | U | 0 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
10048  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
10049  */
10050 static void disas_simd_indexed(DisasContext *s, uint32_t insn)
10051 {
10052     /* This encoding has two kinds of instruction:
10053      *  normal, where we perform elt x idxelt => elt for each
10054      *     element in the vector
10055      *  long, where we perform elt x idxelt and generate a result of
10056      *     double the width of the input element
10057      * The long ops have a 'part' specifier (ie come in INSN, INSN2 pairs).
10058      */
10059     bool is_scalar = extract32(insn, 28, 1);
10060     bool is_q = extract32(insn, 30, 1);
10061     bool u = extract32(insn, 29, 1);
10062     int size = extract32(insn, 22, 2);
10063     int l = extract32(insn, 21, 1);
10064     int m = extract32(insn, 20, 1);
10065     /* Note that the Rm field here is only 4 bits, not 5 as it usually is */
10066     int rm = extract32(insn, 16, 4);
10067     int opcode = extract32(insn, 12, 4);
10068     int h = extract32(insn, 11, 1);
10069     int rn = extract32(insn, 5, 5);
10070     int rd = extract32(insn, 0, 5);
10071     bool is_long = false;
10072     bool is_fp = false;
10073     int index;
10074     TCGv_ptr fpst;
10075
10076     switch (opcode) {
10077     case 0x0: /* MLA */
10078     case 0x4: /* MLS */
10079         if (!u || is_scalar) {
10080             unallocated_encoding(s);
10081             return;
10082         }
10083         break;
10084     case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10085     case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10086     case 0xa: /* SMULL, SMULL2, UMULL, UMULL2 */
10087         if (is_scalar) {
10088             unallocated_encoding(s);
10089             return;
10090         }
10091         is_long = true;
10092         break;
10093     case 0x3: /* SQDMLAL, SQDMLAL2 */
10094     case 0x7: /* SQDMLSL, SQDMLSL2 */
10095     case 0xb: /* SQDMULL, SQDMULL2 */
10096         is_long = true;
10097         /* fall through */
10098     case 0xc: /* SQDMULH */
10099     case 0xd: /* SQRDMULH */
10100         if (u) {
10101             unallocated_encoding(s);
10102             return;
10103         }
10104         break;
10105     case 0x8: /* MUL */
10106         if (u || is_scalar) {
10107             unallocated_encoding(s);
10108             return;
10109         }
10110         break;
10111     case 0x1: /* FMLA */
10112     case 0x5: /* FMLS */
10113         if (u) {
10114             unallocated_encoding(s);
10115             return;
10116         }
10117         /* fall through */
10118     case 0x9: /* FMUL, FMULX */
10119         if (!extract32(size, 1, 1)) {
10120             unallocated_encoding(s);
10121             return;
10122         }
10123         is_fp = true;
10124         break;
10125     default:
10126         unallocated_encoding(s);
10127         return;
10128     }
10129
10130     if (is_fp) {
10131         /* low bit of size indicates single/double */
10132         size = extract32(size, 0, 1) ? 3 : 2;
10133         if (size == 2) {
10134             index = h << 1 | l;
10135         } else {
10136             if (l || !is_q) {
10137                 unallocated_encoding(s);
10138                 return;
10139             }
10140             index = h;
10141         }
10142         rm |= (m << 4);
10143     } else {
10144         switch (size) {
10145         case 1:
10146             index = h << 2 | l << 1 | m;
10147             break;
10148         case 2:
10149             index = h << 1 | l;
10150             rm |= (m << 4);
10151             break;
10152         default:
10153             unallocated_encoding(s);
10154             return;
10155         }
10156     }
10157
10158     if (!fp_access_check(s)) {
10159         return;
10160     }
10161
10162     if (is_fp) {
10163         fpst = get_fpstatus_ptr();
10164     } else {
10165         TCGV_UNUSED_PTR(fpst);
10166     }
10167
10168     if (size == 3) {
10169         TCGv_i64 tcg_idx = tcg_temp_new_i64();
10170         int pass;
10171
10172         assert(is_fp && is_q && !is_long);
10173
10174         read_vec_element(s, tcg_idx, rm, index, MO_64);
10175
10176         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
10177             TCGv_i64 tcg_op = tcg_temp_new_i64();
10178             TCGv_i64 tcg_res = tcg_temp_new_i64();
10179
10180             read_vec_element(s, tcg_op, rn, pass, MO_64);
10181
10182             switch (opcode) {
10183             case 0x5: /* FMLS */
10184                 /* As usual for ARM, separate negation for fused multiply-add */
10185                 gen_helper_vfp_negd(tcg_op, tcg_op);
10186                 /* fall through */
10187             case 0x1: /* FMLA */
10188                 read_vec_element(s, tcg_res, rd, pass, MO_64);
10189                 gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
10190                 break;
10191             case 0x9: /* FMUL, FMULX */
10192                 if (u) {
10193                     gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
10194                 } else {
10195                     gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
10196                 }
10197                 break;
10198             default:
10199                 g_assert_not_reached();
10200             }
10201
10202             write_vec_element(s, tcg_res, rd, pass, MO_64);
10203             tcg_temp_free_i64(tcg_op);
10204             tcg_temp_free_i64(tcg_res);
10205         }
10206
10207         if (is_scalar) {
10208             clear_vec_high(s, rd);
10209         }
10210
10211         tcg_temp_free_i64(tcg_idx);
10212     } else if (!is_long) {
10213         /* 32 bit floating point, or 16 or 32 bit integer.
10214          * For the 16 bit scalar case we use the usual Neon helpers and
10215          * rely on the fact that 0 op 0 == 0 with no side effects.
10216          */
10217         TCGv_i32 tcg_idx = tcg_temp_new_i32();
10218         int pass, maxpasses;
10219
10220         if (is_scalar) {
10221             maxpasses = 1;
10222         } else {
10223             maxpasses = is_q ? 4 : 2;
10224         }
10225
10226         read_vec_element_i32(s, tcg_idx, rm, index, size);
10227
10228         if (size == 1 && !is_scalar) {
10229             /* The simplest way to handle the 16x16 indexed ops is to duplicate
10230              * the index into both halves of the 32 bit tcg_idx and then use
10231              * the usual Neon helpers.
10232              */
10233             tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
10234         }
10235
10236         for (pass = 0; pass < maxpasses; pass++) {
10237             TCGv_i32 tcg_op = tcg_temp_new_i32();
10238             TCGv_i32 tcg_res = tcg_temp_new_i32();
10239
10240             read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
10241
10242             switch (opcode) {
10243             case 0x0: /* MLA */
10244             case 0x4: /* MLS */
10245             case 0x8: /* MUL */
10246             {
10247                 static NeonGenTwoOpFn * const fns[2][2] = {
10248                     { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
10249                     { tcg_gen_add_i32, tcg_gen_sub_i32 },
10250                 };
10251                 NeonGenTwoOpFn *genfn;
10252                 bool is_sub = opcode == 0x4;
10253
10254                 if (size == 1) {
10255                     gen_helper_neon_mul_u16(tcg_res, tcg_op, tcg_idx);
10256                 } else {
10257                     tcg_gen_mul_i32(tcg_res, tcg_op, tcg_idx);
10258                 }
10259                 if (opcode == 0x8) {
10260                     break;
10261                 }
10262                 read_vec_element_i32(s, tcg_op, rd, pass, MO_32);
10263                 genfn = fns[size - 1][is_sub];
10264                 genfn(tcg_res, tcg_op, tcg_res);
10265                 break;
10266             }
10267             case 0x5: /* FMLS */
10268                 /* As usual for ARM, separate negation for fused multiply-add */
10269                 gen_helper_vfp_negs(tcg_op, tcg_op);
10270                 /* fall through */
10271             case 0x1: /* FMLA */
10272                 read_vec_element_i32(s, tcg_res, rd, pass, MO_32);
10273                 gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
10274                 break;
10275             case 0x9: /* FMUL, FMULX */
10276                 if (u) {
10277                     gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
10278                 } else {
10279                     gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
10280                 }
10281                 break;
10282             case 0xc: /* SQDMULH */
10283                 if (size == 1) {
10284                     gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
10285                                                tcg_op, tcg_idx);
10286                 } else {
10287                     gen_helper_neon_qdmulh_s32(tcg_res, cpu_env,
10288                                                tcg_op, tcg_idx);
10289                 }
10290                 break;
10291             case 0xd: /* SQRDMULH */
10292                 if (size == 1) {
10293                     gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
10294                                                 tcg_op, tcg_idx);
10295                 } else {
10296                     gen_helper_neon_qrdmulh_s32(tcg_res, cpu_env,
10297                                                 tcg_op, tcg_idx);
10298                 }
10299                 break;
10300             default:
10301                 g_assert_not_reached();
10302             }
10303
10304             if (is_scalar) {
10305                 write_fp_sreg(s, rd, tcg_res);
10306             } else {
10307                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
10308             }
10309
10310             tcg_temp_free_i32(tcg_op);
10311             tcg_temp_free_i32(tcg_res);
10312         }
10313
10314         tcg_temp_free_i32(tcg_idx);
10315
10316         if (!is_q) {
10317             clear_vec_high(s, rd);
10318         }
10319     } else {
10320         /* long ops: 16x16->32 or 32x32->64 */
10321         TCGv_i64 tcg_res[2];
10322         int pass;
10323         bool satop = extract32(opcode, 0, 1);
10324         TCGMemOp memop = MO_32;
10325
10326         if (satop || !u) {
10327             memop |= MO_SIGN;
10328         }
10329
10330         if (size == 2) {
10331             TCGv_i64 tcg_idx = tcg_temp_new_i64();
10332
10333             read_vec_element(s, tcg_idx, rm, index, memop);
10334
10335             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
10336                 TCGv_i64 tcg_op = tcg_temp_new_i64();
10337                 TCGv_i64 tcg_passres;
10338                 int passelt;
10339
10340                 if (is_scalar) {
10341                     passelt = 0;
10342                 } else {
10343                     passelt = pass + (is_q * 2);
10344                 }
10345
10346                 read_vec_element(s, tcg_op, rn, passelt, memop);
10347
10348                 tcg_res[pass] = tcg_temp_new_i64();
10349
10350                 if (opcode == 0xa || opcode == 0xb) {
10351                     /* Non-accumulating ops */
10352                     tcg_passres = tcg_res[pass];
10353                 } else {
10354                     tcg_passres = tcg_temp_new_i64();
10355                 }
10356
10357                 tcg_gen_mul_i64(tcg_passres, tcg_op, tcg_idx);
10358                 tcg_temp_free_i64(tcg_op);
10359
10360                 if (satop) {
10361                     /* saturating, doubling */
10362                     gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
10363                                                       tcg_passres, tcg_passres);
10364                 }
10365
10366                 if (opcode == 0xa || opcode == 0xb) {
10367                     continue;
10368                 }
10369
10370                 /* Accumulating op: handle accumulate step */
10371                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
10372
10373                 switch (opcode) {
10374                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10375                     tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10376                     break;
10377                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10378                     tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10379                     break;
10380                 case 0x7: /* SQDMLSL, SQDMLSL2 */
10381                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
10382                     /* fall through */
10383                 case 0x3: /* SQDMLAL, SQDMLAL2 */
10384                     gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
10385                                                       tcg_res[pass],
10386                                                       tcg_passres);
10387                     break;
10388                 default:
10389                     g_assert_not_reached();
10390                 }
10391                 tcg_temp_free_i64(tcg_passres);
10392             }
10393             tcg_temp_free_i64(tcg_idx);
10394
10395             if (is_scalar) {
10396                 clear_vec_high(s, rd);
10397             }
10398         } else {
10399             TCGv_i32 tcg_idx = tcg_temp_new_i32();
10400
10401             assert(size == 1);
10402             read_vec_element_i32(s, tcg_idx, rm, index, size);
10403
10404             if (!is_scalar) {
10405                 /* The simplest way to handle the 16x16 indexed ops is to
10406                  * duplicate the index into both halves of the 32 bit tcg_idx
10407                  * and then use the usual Neon helpers.
10408                  */
10409                 tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
10410             }
10411
10412             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
10413                 TCGv_i32 tcg_op = tcg_temp_new_i32();
10414                 TCGv_i64 tcg_passres;
10415
10416                 if (is_scalar) {
10417                     read_vec_element_i32(s, tcg_op, rn, pass, size);
10418                 } else {
10419                     read_vec_element_i32(s, tcg_op, rn,
10420                                          pass + (is_q * 2), MO_32);
10421                 }
10422
10423                 tcg_res[pass] = tcg_temp_new_i64();
10424
10425                 if (opcode == 0xa || opcode == 0xb) {
10426                     /* Non-accumulating ops */
10427                     tcg_passres = tcg_res[pass];
10428                 } else {
10429                     tcg_passres = tcg_temp_new_i64();
10430                 }
10431
10432                 if (memop & MO_SIGN) {
10433                     gen_helper_neon_mull_s16(tcg_passres, tcg_op, tcg_idx);
10434                 } else {
10435                     gen_helper_neon_mull_u16(tcg_passres, tcg_op, tcg_idx);
10436                 }
10437                 if (satop) {
10438                     gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
10439                                                       tcg_passres, tcg_passres);
10440                 }
10441                 tcg_temp_free_i32(tcg_op);
10442
10443                 if (opcode == 0xa || opcode == 0xb) {
10444                     continue;
10445                 }
10446
10447                 /* Accumulating op: handle accumulate step */
10448                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
10449
10450                 switch (opcode) {
10451                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10452                     gen_helper_neon_addl_u32(tcg_res[pass], tcg_res[pass],
10453                                              tcg_passres);
10454                     break;
10455                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10456                     gen_helper_neon_subl_u32(tcg_res[pass], tcg_res[pass],
10457                                              tcg_passres);
10458                     break;
10459                 case 0x7: /* SQDMLSL, SQDMLSL2 */
10460                     gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
10461                     /* fall through */
10462                 case 0x3: /* SQDMLAL, SQDMLAL2 */
10463                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
10464                                                       tcg_res[pass],
10465                                                       tcg_passres);
10466                     break;
10467                 default:
10468                     g_assert_not_reached();
10469                 }
10470                 tcg_temp_free_i64(tcg_passres);
10471             }
10472             tcg_temp_free_i32(tcg_idx);
10473
10474             if (is_scalar) {
10475                 tcg_gen_ext32u_i64(tcg_res[0], tcg_res[0]);
10476             }
10477         }
10478
10479         if (is_scalar) {
10480             tcg_res[1] = tcg_const_i64(0);
10481         }
10482
10483         for (pass = 0; pass < 2; pass++) {
10484             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
10485             tcg_temp_free_i64(tcg_res[pass]);
10486         }
10487     }
10488
10489     if (!TCGV_IS_UNUSED_PTR(fpst)) {
10490         tcg_temp_free_ptr(fpst);
10491     }
10492 }
10493
10494 /* C3.6.19 Crypto AES
10495  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
10496  * +-----------------+------+-----------+--------+-----+------+------+
10497  * | 0 1 0 0 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
10498  * +-----------------+------+-----------+--------+-----+------+------+
10499  */
10500 static void disas_crypto_aes(DisasContext *s, uint32_t insn)
10501 {
10502     unsupported_encoding(s, insn);
10503 }
10504
10505 /* C3.6.20 Crypto three-reg SHA
10506  *  31             24 23  22  21 20  16  15 14    12 11 10 9    5 4    0
10507  * +-----------------+------+---+------+---+--------+-----+------+------+
10508  * | 0 1 0 1 1 1 1 0 | size | 0 |  Rm  | 0 | opcode | 0 0 |  Rn  |  Rd  |
10509  * +-----------------+------+---+------+---+--------+-----+------+------+
10510  */
10511 static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
10512 {
10513     unsupported_encoding(s, insn);
10514 }
10515
10516 /* C3.6.21 Crypto two-reg SHA
10517  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
10518  * +-----------------+------+-----------+--------+-----+------+------+
10519  * | 0 1 0 1 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
10520  * +-----------------+------+-----------+--------+-----+------+------+
10521  */
10522 static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
10523 {
10524     unsupported_encoding(s, insn);
10525 }
10526
10527 /* C3.6 Data processing - SIMD, inc Crypto
10528  *
10529  * As the decode gets a little complex we are using a table based
10530  * approach for this part of the decode.
10531  */
10532 static const AArch64DecodeTable data_proc_simd[] = {
10533     /* pattern  ,  mask     ,  fn                        */
10534     { 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
10535     { 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
10536     { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
10537     { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
10538     { 0x0e000400, 0x9fe08400, disas_simd_copy },
10539     { 0x0f000000, 0x9f000400, disas_simd_indexed }, /* vector indexed */
10540     /* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */
10541     { 0x0f000400, 0x9ff80400, disas_simd_mod_imm },
10542     { 0x0f000400, 0x9f800400, disas_simd_shift_imm },
10543     { 0x0e000000, 0xbf208c00, disas_simd_tb },
10544     { 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
10545     { 0x2e000000, 0xbf208400, disas_simd_ext },
10546     { 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
10547     { 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
10548     { 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
10549     { 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
10550     { 0x5e000400, 0xdfe08400, disas_simd_scalar_copy },
10551     { 0x5f000000, 0xdf000400, disas_simd_indexed }, /* scalar indexed */
10552     { 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm },
10553     { 0x4e280800, 0xff3e0c00, disas_crypto_aes },
10554     { 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
10555     { 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
10556     { 0x00000000, 0x00000000, NULL }
10557 };
10558
10559 static void disas_data_proc_simd(DisasContext *s, uint32_t insn)
10560 {
10561     /* Note that this is called with all non-FP cases from
10562      * table C3-6 so it must UNDEF for entries not specifically
10563      * allocated to instructions in that table.
10564      */
10565     AArch64DecodeFn *fn = lookup_disas_fn(&data_proc_simd[0], insn);
10566     if (fn) {
10567         fn(s, insn);
10568     } else {
10569         unallocated_encoding(s);
10570     }
10571 }
10572
10573 /* C3.6 Data processing - SIMD and floating point */
10574 static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
10575 {
10576     if (extract32(insn, 28, 1) == 1 && extract32(insn, 30, 1) == 0) {
10577         disas_data_proc_fp(s, insn);
10578     } else {
10579         /* SIMD, including crypto */
10580         disas_data_proc_simd(s, insn);
10581     }
10582 }
10583
10584 /* C3.1 A64 instruction index by encoding */
10585 static void disas_a64_insn(CPUARMState *env, DisasContext *s)
10586 {
10587     uint32_t insn;
10588
10589     insn = arm_ldl_code(env, s->pc, s->bswap_code);
10590     s->insn = insn;
10591     s->pc += 4;
10592
10593     s->fp_access_checked = false;
10594
10595     switch (extract32(insn, 25, 4)) {
10596     case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
10597         unallocated_encoding(s);
10598         break;
10599     case 0x8: case 0x9: /* Data processing - immediate */
10600         disas_data_proc_imm(s, insn);
10601         break;
10602     case 0xa: case 0xb: /* Branch, exception generation and system insns */
10603         disas_b_exc_sys(s, insn);
10604         break;
10605     case 0x4:
10606     case 0x6:
10607     case 0xc:
10608     case 0xe:      /* Loads and stores */
10609         disas_ldst(s, insn);
10610         break;
10611     case 0x5:
10612     case 0xd:      /* Data processing - register */
10613         disas_data_proc_reg(s, insn);
10614         break;
10615     case 0x7:
10616     case 0xf:      /* Data processing - SIMD and floating point */
10617         disas_data_proc_simd_fp(s, insn);
10618         break;
10619     default:
10620         assert(FALSE); /* all 15 cases should be handled above */
10621         break;
10622     }
10623
10624     /* if we allocated any temporaries, free them here */
10625     free_tmp_a64(s);
10626 }
10627
10628 void gen_intermediate_code_internal_a64(ARMCPU *cpu,
10629                                         TranslationBlock *tb,
10630                                         bool search_pc)
10631 {
10632     CPUState *cs = CPU(cpu);
10633     CPUARMState *env = &cpu->env;
10634     DisasContext dc1, *dc = &dc1;
10635     CPUBreakpoint *bp;
10636     uint16_t *gen_opc_end;
10637     int j, lj;
10638     target_ulong pc_start;
10639     target_ulong next_page_start;
10640     int num_insns;
10641     int max_insns;
10642
10643     pc_start = tb->pc;
10644
10645     dc->tb = tb;
10646
10647     gen_opc_end = tcg_ctx.gen_opc_buf + OPC_MAX_SIZE;
10648
10649     dc->is_jmp = DISAS_NEXT;
10650     dc->pc = pc_start;
10651     dc->singlestep_enabled = cs->singlestep_enabled;
10652     dc->condjmp = 0;
10653
10654     dc->aarch64 = 1;
10655     dc->thumb = 0;
10656     dc->bswap_code = 0;
10657     dc->condexec_mask = 0;
10658     dc->condexec_cond = 0;
10659 #if !defined(CONFIG_USER_ONLY)
10660     dc->user = (ARM_TBFLAG_AA64_EL(tb->flags) == 0);
10661 #endif
10662     dc->cpacr_fpen = ARM_TBFLAG_AA64_FPEN(tb->flags);
10663     dc->vec_len = 0;
10664     dc->vec_stride = 0;
10665     dc->cp_regs = cpu->cp_regs;
10666     dc->current_pl = arm_current_pl(env);
10667     dc->features = env->features;
10668
10669     init_tmp_a64_array(dc);
10670
10671     next_page_start = (pc_start & TARGET_PAGE_MASK) + TARGET_PAGE_SIZE;
10672     lj = -1;
10673     num_insns = 0;
10674     max_insns = tb->cflags & CF_COUNT_MASK;
10675     if (max_insns == 0) {
10676         max_insns = CF_COUNT_MASK;
10677     }
10678
10679     gen_tb_start();
10680
10681     tcg_clear_temp_count();
10682
10683     do {
10684         if (unlikely(!QTAILQ_EMPTY(&cs->breakpoints))) {
10685             QTAILQ_FOREACH(bp, &cs->breakpoints, entry) {
10686                 if (bp->pc == dc->pc) {
10687                     gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
10688                     /* Advance PC so that clearing the breakpoint will
10689                        invalidate this TB.  */
10690                     dc->pc += 2;
10691                     goto done_generating;
10692                 }
10693             }
10694         }
10695
10696         if (search_pc) {
10697             j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10698             if (lj < j) {
10699                 lj++;
10700                 while (lj < j) {
10701                     tcg_ctx.gen_opc_instr_start[lj++] = 0;
10702                 }
10703             }
10704             tcg_ctx.gen_opc_pc[lj] = dc->pc;
10705             tcg_ctx.gen_opc_instr_start[lj] = 1;
10706             tcg_ctx.gen_opc_icount[lj] = num_insns;
10707         }
10708
10709         if (num_insns + 1 == max_insns && (tb->cflags & CF_LAST_IO)) {
10710             gen_io_start();
10711         }
10712
10713         if (unlikely(qemu_loglevel_mask(CPU_LOG_TB_OP | CPU_LOG_TB_OP_OPT))) {
10714             tcg_gen_debug_insn_start(dc->pc);
10715         }
10716
10717         disas_a64_insn(env, dc);
10718
10719         if (tcg_check_temp_count()) {
10720             fprintf(stderr, "TCG temporary leak before "TARGET_FMT_lx"\n",
10721                     dc->pc);
10722         }
10723
10724         /* Translation stops when a conditional branch is encountered.
10725          * Otherwise the subsequent code could get translated several times.
10726          * Also stop translation when a page boundary is reached.  This
10727          * ensures prefetch aborts occur at the right place.
10728          */
10729         num_insns++;
10730     } while (!dc->is_jmp && tcg_ctx.gen_opc_ptr < gen_opc_end &&
10731              !cs->singlestep_enabled &&
10732              !singlestep &&
10733              dc->pc < next_page_start &&
10734              num_insns < max_insns);
10735
10736     if (tb->cflags & CF_LAST_IO) {
10737         gen_io_end();
10738     }
10739
10740     if (unlikely(cs->singlestep_enabled) && dc->is_jmp != DISAS_EXC) {
10741         /* Note that this means single stepping WFI doesn't halt the CPU.
10742          * For conditional branch insns this is harmless unreachable code as
10743          * gen_goto_tb() has already handled emitting the debug exception
10744          * (and thus a tb-jump is not possible when singlestepping).
10745          */
10746         assert(dc->is_jmp != DISAS_TB_JUMP);
10747         if (dc->is_jmp != DISAS_JUMP) {
10748             gen_a64_set_pc_im(dc->pc);
10749         }
10750         gen_exception_internal(EXCP_DEBUG);
10751     } else {
10752         switch (dc->is_jmp) {
10753         case DISAS_NEXT:
10754             gen_goto_tb(dc, 1, dc->pc);
10755             break;
10756         default:
10757         case DISAS_UPDATE:
10758             gen_a64_set_pc_im(dc->pc);
10759             /* fall through */
10760         case DISAS_JUMP:
10761             /* indicate that the hash table must be used to find the next TB */
10762             tcg_gen_exit_tb(0);
10763             break;
10764         case DISAS_TB_JUMP:
10765         case DISAS_EXC:
10766         case DISAS_SWI:
10767             break;
10768         case DISAS_WFI:
10769             /* This is a special case because we don't want to just halt the CPU
10770              * if trying to debug across a WFI.
10771              */
10772             gen_a64_set_pc_im(dc->pc);
10773             gen_helper_wfi(cpu_env);
10774             break;
10775         }
10776     }
10777
10778 done_generating:
10779     gen_tb_end(tb, num_insns);
10780     *tcg_ctx.gen_opc_ptr = INDEX_op_end;
10781
10782 #ifdef DEBUG_DISAS
10783     if (qemu_loglevel_mask(CPU_LOG_TB_IN_ASM)) {
10784         qemu_log("----------------\n");
10785         qemu_log("IN: %s\n", lookup_symbol(pc_start));
10786         log_target_disas(env, pc_start, dc->pc - pc_start,
10787                          4 | (dc->bswap_code << 1));
10788         qemu_log("\n");
10789     }
10790 #endif
10791     if (search_pc) {
10792         j = tcg_ctx.gen_opc_ptr - tcg_ctx.gen_opc_buf;
10793         lj++;
10794         while (lj <= j) {
10795             tcg_ctx.gen_opc_instr_start[lj++] = 0;
10796         }
10797     } else {
10798         tb->size = dc->pc - pc_start;
10799         tb->icount = num_insns;
10800     }
10801 }
This page took 0.613514 seconds and 4 git commands to generate.