]> Git Repo - qemu.git/blob - target/arm/translate-a64.c
target/arm: Implement FCSEL for fp16
[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 "qemu/osdep.h"
20
21 #include "cpu.h"
22 #include "exec/exec-all.h"
23 #include "tcg-op.h"
24 #include "tcg-op-gvec.h"
25 #include "qemu/log.h"
26 #include "arm_ldst.h"
27 #include "translate.h"
28 #include "internals.h"
29 #include "qemu/host-utils.h"
30
31 #include "exec/semihost.h"
32 #include "exec/gen-icount.h"
33
34 #include "exec/helper-proto.h"
35 #include "exec/helper-gen.h"
36 #include "exec/log.h"
37
38 #include "trace-tcg.h"
39
40 static TCGv_i64 cpu_X[32];
41 static TCGv_i64 cpu_pc;
42
43 /* Load/store exclusive handling */
44 static TCGv_i64 cpu_exclusive_high;
45 static TCGv_i64 cpu_reg(DisasContext *s, int reg);
46
47 static const char *regnames[] = {
48     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
49     "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
50     "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
51     "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
52 };
53
54 enum a64_shift_type {
55     A64_SHIFT_TYPE_LSL = 0,
56     A64_SHIFT_TYPE_LSR = 1,
57     A64_SHIFT_TYPE_ASR = 2,
58     A64_SHIFT_TYPE_ROR = 3
59 };
60
61 /* Table based decoder typedefs - used when the relevant bits for decode
62  * are too awkwardly scattered across the instruction (eg SIMD).
63  */
64 typedef void AArch64DecodeFn(DisasContext *s, uint32_t insn);
65
66 typedef struct AArch64DecodeTable {
67     uint32_t pattern;
68     uint32_t mask;
69     AArch64DecodeFn *disas_fn;
70 } AArch64DecodeTable;
71
72 /* Function prototype for gen_ functions for calling Neon helpers */
73 typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
74 typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
75 typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
76 typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
77 typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
78 typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
79 typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
80 typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
81 typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
82 typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
83 typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
84 typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
85 typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
86 typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
87 typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, TCGMemOp);
88
89 /* Note that the gvec expanders operate on offsets + sizes.  */
90 typedef void GVecGen2Fn(unsigned, uint32_t, uint32_t, uint32_t, uint32_t);
91 typedef void GVecGen2iFn(unsigned, uint32_t, uint32_t, int64_t,
92                          uint32_t, uint32_t);
93 typedef void GVecGen3Fn(unsigned, uint32_t, uint32_t,
94                         uint32_t, uint32_t, uint32_t);
95
96 /* initialize TCG globals.  */
97 void a64_translate_init(void)
98 {
99     int i;
100
101     cpu_pc = tcg_global_mem_new_i64(cpu_env,
102                                     offsetof(CPUARMState, pc),
103                                     "pc");
104     for (i = 0; i < 32; i++) {
105         cpu_X[i] = tcg_global_mem_new_i64(cpu_env,
106                                           offsetof(CPUARMState, xregs[i]),
107                                           regnames[i]);
108     }
109
110     cpu_exclusive_high = tcg_global_mem_new_i64(cpu_env,
111         offsetof(CPUARMState, exclusive_high), "exclusive_high");
112 }
113
114 static inline int get_a64_user_mem_index(DisasContext *s)
115 {
116     /* Return the core mmu_idx to use for A64 "unprivileged load/store" insns:
117      *  if EL1, access as if EL0; otherwise access at current EL
118      */
119     ARMMMUIdx useridx;
120
121     switch (s->mmu_idx) {
122     case ARMMMUIdx_S12NSE1:
123         useridx = ARMMMUIdx_S12NSE0;
124         break;
125     case ARMMMUIdx_S1SE1:
126         useridx = ARMMMUIdx_S1SE0;
127         break;
128     case ARMMMUIdx_S2NS:
129         g_assert_not_reached();
130     default:
131         useridx = s->mmu_idx;
132         break;
133     }
134     return arm_to_core_mmu_idx(useridx);
135 }
136
137 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
138                             fprintf_function cpu_fprintf, int flags)
139 {
140     ARMCPU *cpu = ARM_CPU(cs);
141     CPUARMState *env = &cpu->env;
142     uint32_t psr = pstate_read(env);
143     int i;
144     int el = arm_current_el(env);
145     const char *ns_status;
146
147     cpu_fprintf(f, "PC=%016"PRIx64"  SP=%016"PRIx64"\n",
148             env->pc, env->xregs[31]);
149     for (i = 0; i < 31; i++) {
150         cpu_fprintf(f, "X%02d=%016"PRIx64, i, env->xregs[i]);
151         if ((i % 4) == 3) {
152             cpu_fprintf(f, "\n");
153         } else {
154             cpu_fprintf(f, " ");
155         }
156     }
157
158     if (arm_feature(env, ARM_FEATURE_EL3) && el != 3) {
159         ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
160     } else {
161         ns_status = "";
162     }
163
164     cpu_fprintf(f, "\nPSTATE=%08x %c%c%c%c %sEL%d%c\n",
165                 psr,
166                 psr & PSTATE_N ? 'N' : '-',
167                 psr & PSTATE_Z ? 'Z' : '-',
168                 psr & PSTATE_C ? 'C' : '-',
169                 psr & PSTATE_V ? 'V' : '-',
170                 ns_status,
171                 el,
172                 psr & PSTATE_SP ? 'h' : 't');
173
174     if (flags & CPU_DUMP_FPU) {
175         int numvfpregs = 32;
176         for (i = 0; i < numvfpregs; i++) {
177             uint64_t *q = aa64_vfp_qreg(env, i);
178             uint64_t vlo = q[0];
179             uint64_t vhi = q[1];
180             cpu_fprintf(f, "q%02d=%016" PRIx64 ":%016" PRIx64 "%c",
181                         i, vhi, vlo, (i & 1 ? '\n' : ' '));
182         }
183         cpu_fprintf(f, "FPCR: %08x  FPSR: %08x\n",
184                     vfp_get_fpcr(env), vfp_get_fpsr(env));
185     }
186 }
187
188 void gen_a64_set_pc_im(uint64_t val)
189 {
190     tcg_gen_movi_i64(cpu_pc, val);
191 }
192
193 /* Load the PC from a generic TCG variable.
194  *
195  * If address tagging is enabled via the TCR TBI bits, then loading
196  * an address into the PC will clear out any tag in the it:
197  *  + for EL2 and EL3 there is only one TBI bit, and if it is set
198  *    then the address is zero-extended, clearing bits [63:56]
199  *  + for EL0 and EL1, TBI0 controls addresses with bit 55 == 0
200  *    and TBI1 controls addressses with bit 55 == 1.
201  *    If the appropriate TBI bit is set for the address then
202  *    the address is sign-extended from bit 55 into bits [63:56]
203  *
204  * We can avoid doing this for relative-branches, because the
205  * PC + offset can never overflow into the tag bits (assuming
206  * that virtual addresses are less than 56 bits wide, as they
207  * are currently), but we must handle it for branch-to-register.
208  */
209 static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
210 {
211
212     if (s->current_el <= 1) {
213         /* Test if NEITHER or BOTH TBI values are set.  If so, no need to
214          * examine bit 55 of address, can just generate code.
215          * If mixed, then test via generated code
216          */
217         if (s->tbi0 && s->tbi1) {
218             TCGv_i64 tmp_reg = tcg_temp_new_i64();
219             /* Both bits set, sign extension from bit 55 into [63:56] will
220              * cover both cases
221              */
222             tcg_gen_shli_i64(tmp_reg, src, 8);
223             tcg_gen_sari_i64(cpu_pc, tmp_reg, 8);
224             tcg_temp_free_i64(tmp_reg);
225         } else if (!s->tbi0 && !s->tbi1) {
226             /* Neither bit set, just load it as-is */
227             tcg_gen_mov_i64(cpu_pc, src);
228         } else {
229             TCGv_i64 tcg_tmpval = tcg_temp_new_i64();
230             TCGv_i64 tcg_bit55  = tcg_temp_new_i64();
231             TCGv_i64 tcg_zero   = tcg_const_i64(0);
232
233             tcg_gen_andi_i64(tcg_bit55, src, (1ull << 55));
234
235             if (s->tbi0) {
236                 /* tbi0==1, tbi1==0, so 0-fill upper byte if bit 55 = 0 */
237                 tcg_gen_andi_i64(tcg_tmpval, src,
238                                  0x00FFFFFFFFFFFFFFull);
239                 tcg_gen_movcond_i64(TCG_COND_EQ, cpu_pc, tcg_bit55, tcg_zero,
240                                     tcg_tmpval, src);
241             } else {
242                 /* tbi0==0, tbi1==1, so 1-fill upper byte if bit 55 = 1 */
243                 tcg_gen_ori_i64(tcg_tmpval, src,
244                                 0xFF00000000000000ull);
245                 tcg_gen_movcond_i64(TCG_COND_NE, cpu_pc, tcg_bit55, tcg_zero,
246                                     tcg_tmpval, src);
247             }
248             tcg_temp_free_i64(tcg_zero);
249             tcg_temp_free_i64(tcg_bit55);
250             tcg_temp_free_i64(tcg_tmpval);
251         }
252     } else {  /* EL > 1 */
253         if (s->tbi0) {
254             /* Force tag byte to all zero */
255             tcg_gen_andi_i64(cpu_pc, src, 0x00FFFFFFFFFFFFFFull);
256         } else {
257             /* Load unmodified address */
258             tcg_gen_mov_i64(cpu_pc, src);
259         }
260     }
261 }
262
263 typedef struct DisasCompare64 {
264     TCGCond cond;
265     TCGv_i64 value;
266 } DisasCompare64;
267
268 static void a64_test_cc(DisasCompare64 *c64, int cc)
269 {
270     DisasCompare c32;
271
272     arm_test_cc(&c32, cc);
273
274     /* Sign-extend the 32-bit value so that the GE/LT comparisons work
275        * properly.  The NE/EQ comparisons are also fine with this choice.  */
276     c64->cond = c32.cond;
277     c64->value = tcg_temp_new_i64();
278     tcg_gen_ext_i32_i64(c64->value, c32.value);
279
280     arm_free_cc(&c32);
281 }
282
283 static void a64_free_cc(DisasCompare64 *c64)
284 {
285     tcg_temp_free_i64(c64->value);
286 }
287
288 static void gen_exception_internal(int excp)
289 {
290     TCGv_i32 tcg_excp = tcg_const_i32(excp);
291
292     assert(excp_is_internal(excp));
293     gen_helper_exception_internal(cpu_env, tcg_excp);
294     tcg_temp_free_i32(tcg_excp);
295 }
296
297 static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
298 {
299     TCGv_i32 tcg_excp = tcg_const_i32(excp);
300     TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
301     TCGv_i32 tcg_el = tcg_const_i32(target_el);
302
303     gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
304                                        tcg_syn, tcg_el);
305     tcg_temp_free_i32(tcg_el);
306     tcg_temp_free_i32(tcg_syn);
307     tcg_temp_free_i32(tcg_excp);
308 }
309
310 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
311 {
312     gen_a64_set_pc_im(s->pc - offset);
313     gen_exception_internal(excp);
314     s->base.is_jmp = DISAS_NORETURN;
315 }
316
317 static void gen_exception_insn(DisasContext *s, int offset, int excp,
318                                uint32_t syndrome, uint32_t target_el)
319 {
320     gen_a64_set_pc_im(s->pc - offset);
321     gen_exception(excp, syndrome, target_el);
322     s->base.is_jmp = DISAS_NORETURN;
323 }
324
325 static void gen_exception_bkpt_insn(DisasContext *s, int offset,
326                                     uint32_t syndrome)
327 {
328     TCGv_i32 tcg_syn;
329
330     gen_a64_set_pc_im(s->pc - offset);
331     tcg_syn = tcg_const_i32(syndrome);
332     gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
333     tcg_temp_free_i32(tcg_syn);
334     s->base.is_jmp = DISAS_NORETURN;
335 }
336
337 static void gen_ss_advance(DisasContext *s)
338 {
339     /* If the singlestep state is Active-not-pending, advance to
340      * Active-pending.
341      */
342     if (s->ss_active) {
343         s->pstate_ss = 0;
344         gen_helper_clear_pstate_ss(cpu_env);
345     }
346 }
347
348 static void gen_step_complete_exception(DisasContext *s)
349 {
350     /* We just completed step of an insn. Move from Active-not-pending
351      * to Active-pending, and then also take the swstep exception.
352      * This corresponds to making the (IMPDEF) choice to prioritize
353      * swstep exceptions over asynchronous exceptions taken to an exception
354      * level where debug is disabled. This choice has the advantage that
355      * we do not need to maintain internal state corresponding to the
356      * ISV/EX syndrome bits between completion of the step and generation
357      * of the exception, and our syndrome information is always correct.
358      */
359     gen_ss_advance(s);
360     gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
361                   default_exception_el(s));
362     s->base.is_jmp = DISAS_NORETURN;
363 }
364
365 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
366 {
367     /* No direct tb linking with singlestep (either QEMU's or the ARM
368      * debug architecture kind) or deterministic io
369      */
370     if (s->base.singlestep_enabled || s->ss_active ||
371         (tb_cflags(s->base.tb) & CF_LAST_IO)) {
372         return false;
373     }
374
375 #ifndef CONFIG_USER_ONLY
376     /* Only link tbs from inside the same guest page */
377     if ((s->base.tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
378         return false;
379     }
380 #endif
381
382     return true;
383 }
384
385 static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
386 {
387     TranslationBlock *tb;
388
389     tb = s->base.tb;
390     if (use_goto_tb(s, n, dest)) {
391         tcg_gen_goto_tb(n);
392         gen_a64_set_pc_im(dest);
393         tcg_gen_exit_tb((intptr_t)tb + n);
394         s->base.is_jmp = DISAS_NORETURN;
395     } else {
396         gen_a64_set_pc_im(dest);
397         if (s->ss_active) {
398             gen_step_complete_exception(s);
399         } else if (s->base.singlestep_enabled) {
400             gen_exception_internal(EXCP_DEBUG);
401         } else {
402             tcg_gen_lookup_and_goto_ptr();
403             s->base.is_jmp = DISAS_NORETURN;
404         }
405     }
406 }
407
408 static void unallocated_encoding(DisasContext *s)
409 {
410     /* Unallocated and reserved encodings are uncategorized */
411     gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
412                        default_exception_el(s));
413 }
414
415 #define unsupported_encoding(s, insn)                                    \
416     do {                                                                 \
417         qemu_log_mask(LOG_UNIMP,                                         \
418                       "%s:%d: unsupported instruction encoding 0x%08x "  \
419                       "at pc=%016" PRIx64 "\n",                          \
420                       __FILE__, __LINE__, insn, s->pc - 4);              \
421         unallocated_encoding(s);                                         \
422     } while (0)
423
424 static void init_tmp_a64_array(DisasContext *s)
425 {
426 #ifdef CONFIG_DEBUG_TCG
427     memset(s->tmp_a64, 0, sizeof(s->tmp_a64));
428 #endif
429     s->tmp_a64_count = 0;
430 }
431
432 static void free_tmp_a64(DisasContext *s)
433 {
434     int i;
435     for (i = 0; i < s->tmp_a64_count; i++) {
436         tcg_temp_free_i64(s->tmp_a64[i]);
437     }
438     init_tmp_a64_array(s);
439 }
440
441 static TCGv_i64 new_tmp_a64(DisasContext *s)
442 {
443     assert(s->tmp_a64_count < TMP_A64_MAX);
444     return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
445 }
446
447 static TCGv_i64 new_tmp_a64_zero(DisasContext *s)
448 {
449     TCGv_i64 t = new_tmp_a64(s);
450     tcg_gen_movi_i64(t, 0);
451     return t;
452 }
453
454 /*
455  * Register access functions
456  *
457  * These functions are used for directly accessing a register in where
458  * changes to the final register value are likely to be made. If you
459  * need to use a register for temporary calculation (e.g. index type
460  * operations) use the read_* form.
461  *
462  * B1.2.1 Register mappings
463  *
464  * In instruction register encoding 31 can refer to ZR (zero register) or
465  * the SP (stack pointer) depending on context. In QEMU's case we map SP
466  * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
467  * This is the point of the _sp forms.
468  */
469 static TCGv_i64 cpu_reg(DisasContext *s, int reg)
470 {
471     if (reg == 31) {
472         return new_tmp_a64_zero(s);
473     } else {
474         return cpu_X[reg];
475     }
476 }
477
478 /* register access for when 31 == SP */
479 static TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
480 {
481     return cpu_X[reg];
482 }
483
484 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
485  * representing the register contents. This TCGv is an auto-freed
486  * temporary so it need not be explicitly freed, and may be modified.
487  */
488 static TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
489 {
490     TCGv_i64 v = new_tmp_a64(s);
491     if (reg != 31) {
492         if (sf) {
493             tcg_gen_mov_i64(v, cpu_X[reg]);
494         } else {
495             tcg_gen_ext32u_i64(v, cpu_X[reg]);
496         }
497     } else {
498         tcg_gen_movi_i64(v, 0);
499     }
500     return v;
501 }
502
503 static TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
504 {
505     TCGv_i64 v = new_tmp_a64(s);
506     if (sf) {
507         tcg_gen_mov_i64(v, cpu_X[reg]);
508     } else {
509         tcg_gen_ext32u_i64(v, cpu_X[reg]);
510     }
511     return v;
512 }
513
514 /* We should have at some point before trying to access an FP register
515  * done the necessary access check, so assert that
516  * (a) we did the check and
517  * (b) we didn't then just plough ahead anyway if it failed.
518  * Print the instruction pattern in the abort message so we can figure
519  * out what we need to fix if a user encounters this problem in the wild.
520  */
521 static inline void assert_fp_access_checked(DisasContext *s)
522 {
523 #ifdef CONFIG_DEBUG_TCG
524     if (unlikely(!s->fp_access_checked || s->fp_excp_el)) {
525         fprintf(stderr, "target-arm: FP access check missing for "
526                 "instruction 0x%08x\n", s->insn);
527         abort();
528     }
529 #endif
530 }
531
532 /* Return the offset into CPUARMState of an element of specified
533  * size, 'element' places in from the least significant end of
534  * the FP/vector register Qn.
535  */
536 static inline int vec_reg_offset(DisasContext *s, int regno,
537                                  int element, TCGMemOp size)
538 {
539     int offs = 0;
540 #ifdef HOST_WORDS_BIGENDIAN
541     /* This is complicated slightly because vfp.zregs[n].d[0] is
542      * still the low half and vfp.zregs[n].d[1] the high half
543      * of the 128 bit vector, even on big endian systems.
544      * Calculate the offset assuming a fully bigendian 128 bits,
545      * then XOR to account for the order of the two 64 bit halves.
546      */
547     offs += (16 - ((element + 1) * (1 << size)));
548     offs ^= 8;
549 #else
550     offs += element * (1 << size);
551 #endif
552     offs += offsetof(CPUARMState, vfp.zregs[regno]);
553     assert_fp_access_checked(s);
554     return offs;
555 }
556
557 /* Return the offset info CPUARMState of the "whole" vector register Qn.  */
558 static inline int vec_full_reg_offset(DisasContext *s, int regno)
559 {
560     assert_fp_access_checked(s);
561     return offsetof(CPUARMState, vfp.zregs[regno]);
562 }
563
564 /* Return a newly allocated pointer to the vector register.  */
565 static TCGv_ptr vec_full_reg_ptr(DisasContext *s, int regno)
566 {
567     TCGv_ptr ret = tcg_temp_new_ptr();
568     tcg_gen_addi_ptr(ret, cpu_env, vec_full_reg_offset(s, regno));
569     return ret;
570 }
571
572 /* Return the byte size of the "whole" vector register, VL / 8.  */
573 static inline int vec_full_reg_size(DisasContext *s)
574 {
575     /* FIXME SVE: We should put the composite ZCR_EL* value into tb->flags.
576        In the meantime this is just the AdvSIMD length of 128.  */
577     return 128 / 8;
578 }
579
580 /* Return the offset into CPUARMState of a slice (from
581  * the least significant end) of FP register Qn (ie
582  * Dn, Sn, Hn or Bn).
583  * (Note that this is not the same mapping as for A32; see cpu.h)
584  */
585 static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size)
586 {
587     return vec_reg_offset(s, regno, 0, size);
588 }
589
590 /* Offset of the high half of the 128 bit vector Qn */
591 static inline int fp_reg_hi_offset(DisasContext *s, int regno)
592 {
593     return vec_reg_offset(s, regno, 1, MO_64);
594 }
595
596 /* Convenience accessors for reading and writing single and double
597  * FP registers. Writing clears the upper parts of the associated
598  * 128 bit vector register, as required by the architecture.
599  * Note that unlike the GP register accessors, the values returned
600  * by the read functions must be manually freed.
601  */
602 static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
603 {
604     TCGv_i64 v = tcg_temp_new_i64();
605
606     tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
607     return v;
608 }
609
610 static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
611 {
612     TCGv_i32 v = tcg_temp_new_i32();
613
614     tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(s, reg, MO_32));
615     return v;
616 }
617
618 static TCGv_i32 read_fp_hreg(DisasContext *s, int reg)
619 {
620     TCGv_i32 v = tcg_temp_new_i32();
621
622     tcg_gen_ld16u_i32(v, cpu_env, fp_reg_offset(s, reg, MO_16));
623     return v;
624 }
625
626 /* Clear the bits above an N-bit vector, for N = (is_q ? 128 : 64).
627  * If SVE is not enabled, then there are only 128 bits in the vector.
628  */
629 static void clear_vec_high(DisasContext *s, bool is_q, int rd)
630 {
631     unsigned ofs = fp_reg_offset(s, rd, MO_64);
632     unsigned vsz = vec_full_reg_size(s);
633
634     if (!is_q) {
635         TCGv_i64 tcg_zero = tcg_const_i64(0);
636         tcg_gen_st_i64(tcg_zero, cpu_env, ofs + 8);
637         tcg_temp_free_i64(tcg_zero);
638     }
639     if (vsz > 16) {
640         tcg_gen_gvec_dup8i(ofs + 16, vsz - 16, vsz - 16, 0);
641     }
642 }
643
644 static void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
645 {
646     unsigned ofs = fp_reg_offset(s, reg, MO_64);
647
648     tcg_gen_st_i64(v, cpu_env, ofs);
649     clear_vec_high(s, false, reg);
650 }
651
652 static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
653 {
654     TCGv_i64 tmp = tcg_temp_new_i64();
655
656     tcg_gen_extu_i32_i64(tmp, v);
657     write_fp_dreg(s, reg, tmp);
658     tcg_temp_free_i64(tmp);
659 }
660
661 static TCGv_ptr get_fpstatus_ptr(bool is_f16)
662 {
663     TCGv_ptr statusptr = tcg_temp_new_ptr();
664     int offset;
665
666     /* In A64 all instructions (both FP and Neon) use the FPCR; there
667      * is no equivalent of the A32 Neon "standard FPSCR value".
668      * However half-precision operations operate under a different
669      * FZ16 flag and use vfp.fp_status_f16 instead of vfp.fp_status.
670      */
671     if (is_f16) {
672         offset = offsetof(CPUARMState, vfp.fp_status_f16);
673     } else {
674         offset = offsetof(CPUARMState, vfp.fp_status);
675     }
676     tcg_gen_addi_ptr(statusptr, cpu_env, offset);
677     return statusptr;
678 }
679
680 /* Expand a 2-operand AdvSIMD vector operation using an expander function.  */
681 static void gen_gvec_fn2(DisasContext *s, bool is_q, int rd, int rn,
682                          GVecGen2Fn *gvec_fn, int vece)
683 {
684     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
685             is_q ? 16 : 8, vec_full_reg_size(s));
686 }
687
688 /* Expand a 2-operand + immediate AdvSIMD vector operation using
689  * an expander function.
690  */
691 static void gen_gvec_fn2i(DisasContext *s, bool is_q, int rd, int rn,
692                           int64_t imm, GVecGen2iFn *gvec_fn, int vece)
693 {
694     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
695             imm, is_q ? 16 : 8, vec_full_reg_size(s));
696 }
697
698 /* Expand a 3-operand AdvSIMD vector operation using an expander function.  */
699 static void gen_gvec_fn3(DisasContext *s, bool is_q, int rd, int rn, int rm,
700                          GVecGen3Fn *gvec_fn, int vece)
701 {
702     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
703             vec_full_reg_offset(s, rm), is_q ? 16 : 8, vec_full_reg_size(s));
704 }
705
706 /* Expand a 2-operand + immediate AdvSIMD vector operation using
707  * an op descriptor.
708  */
709 static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd,
710                           int rn, int64_t imm, const GVecGen2i *gvec_op)
711 {
712     tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
713                     is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op);
714 }
715
716 /* Expand a 3-operand AdvSIMD vector operation using an op descriptor.  */
717 static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
718                          int rn, int rm, const GVecGen3 *gvec_op)
719 {
720     tcg_gen_gvec_3(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
721                    vec_full_reg_offset(s, rm), is_q ? 16 : 8,
722                    vec_full_reg_size(s), gvec_op);
723 }
724
725 /* Expand a 3-operand + env pointer operation using
726  * an out-of-line helper.
727  */
728 static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
729                              int rn, int rm, gen_helper_gvec_3_ptr *fn)
730 {
731     tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
732                        vec_full_reg_offset(s, rn),
733                        vec_full_reg_offset(s, rm), cpu_env,
734                        is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
735 }
736
737 /* Expand a 3-operand + fpstatus pointer + simd data value operation using
738  * an out-of-line helper.
739  */
740 static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
741                               int rm, bool is_fp16, int data,
742                               gen_helper_gvec_3_ptr *fn)
743 {
744     TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
745     tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
746                        vec_full_reg_offset(s, rn),
747                        vec_full_reg_offset(s, rm), fpst,
748                        is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
749     tcg_temp_free_ptr(fpst);
750 }
751
752 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
753  * than the 32 bit equivalent.
754  */
755 static inline void gen_set_NZ64(TCGv_i64 result)
756 {
757     tcg_gen_extr_i64_i32(cpu_ZF, cpu_NF, result);
758     tcg_gen_or_i32(cpu_ZF, cpu_ZF, cpu_NF);
759 }
760
761 /* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
762 static inline void gen_logic_CC(int sf, TCGv_i64 result)
763 {
764     if (sf) {
765         gen_set_NZ64(result);
766     } else {
767         tcg_gen_extrl_i64_i32(cpu_ZF, result);
768         tcg_gen_mov_i32(cpu_NF, cpu_ZF);
769     }
770     tcg_gen_movi_i32(cpu_CF, 0);
771     tcg_gen_movi_i32(cpu_VF, 0);
772 }
773
774 /* dest = T0 + T1; compute C, N, V and Z flags */
775 static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
776 {
777     if (sf) {
778         TCGv_i64 result, flag, tmp;
779         result = tcg_temp_new_i64();
780         flag = tcg_temp_new_i64();
781         tmp = tcg_temp_new_i64();
782
783         tcg_gen_movi_i64(tmp, 0);
784         tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
785
786         tcg_gen_extrl_i64_i32(cpu_CF, flag);
787
788         gen_set_NZ64(result);
789
790         tcg_gen_xor_i64(flag, result, t0);
791         tcg_gen_xor_i64(tmp, t0, t1);
792         tcg_gen_andc_i64(flag, flag, tmp);
793         tcg_temp_free_i64(tmp);
794         tcg_gen_extrh_i64_i32(cpu_VF, flag);
795
796         tcg_gen_mov_i64(dest, result);
797         tcg_temp_free_i64(result);
798         tcg_temp_free_i64(flag);
799     } else {
800         /* 32 bit arithmetic */
801         TCGv_i32 t0_32 = tcg_temp_new_i32();
802         TCGv_i32 t1_32 = tcg_temp_new_i32();
803         TCGv_i32 tmp = tcg_temp_new_i32();
804
805         tcg_gen_movi_i32(tmp, 0);
806         tcg_gen_extrl_i64_i32(t0_32, t0);
807         tcg_gen_extrl_i64_i32(t1_32, t1);
808         tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
809         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
810         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
811         tcg_gen_xor_i32(tmp, t0_32, t1_32);
812         tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
813         tcg_gen_extu_i32_i64(dest, cpu_NF);
814
815         tcg_temp_free_i32(tmp);
816         tcg_temp_free_i32(t0_32);
817         tcg_temp_free_i32(t1_32);
818     }
819 }
820
821 /* dest = T0 - T1; compute C, N, V and Z flags */
822 static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
823 {
824     if (sf) {
825         /* 64 bit arithmetic */
826         TCGv_i64 result, flag, tmp;
827
828         result = tcg_temp_new_i64();
829         flag = tcg_temp_new_i64();
830         tcg_gen_sub_i64(result, t0, t1);
831
832         gen_set_NZ64(result);
833
834         tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
835         tcg_gen_extrl_i64_i32(cpu_CF, flag);
836
837         tcg_gen_xor_i64(flag, result, t0);
838         tmp = tcg_temp_new_i64();
839         tcg_gen_xor_i64(tmp, t0, t1);
840         tcg_gen_and_i64(flag, flag, tmp);
841         tcg_temp_free_i64(tmp);
842         tcg_gen_extrh_i64_i32(cpu_VF, flag);
843         tcg_gen_mov_i64(dest, result);
844         tcg_temp_free_i64(flag);
845         tcg_temp_free_i64(result);
846     } else {
847         /* 32 bit arithmetic */
848         TCGv_i32 t0_32 = tcg_temp_new_i32();
849         TCGv_i32 t1_32 = tcg_temp_new_i32();
850         TCGv_i32 tmp;
851
852         tcg_gen_extrl_i64_i32(t0_32, t0);
853         tcg_gen_extrl_i64_i32(t1_32, t1);
854         tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
855         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
856         tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
857         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
858         tmp = tcg_temp_new_i32();
859         tcg_gen_xor_i32(tmp, t0_32, t1_32);
860         tcg_temp_free_i32(t0_32);
861         tcg_temp_free_i32(t1_32);
862         tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
863         tcg_temp_free_i32(tmp);
864         tcg_gen_extu_i32_i64(dest, cpu_NF);
865     }
866 }
867
868 /* dest = T0 + T1 + CF; do not compute flags. */
869 static void gen_adc(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
870 {
871     TCGv_i64 flag = tcg_temp_new_i64();
872     tcg_gen_extu_i32_i64(flag, cpu_CF);
873     tcg_gen_add_i64(dest, t0, t1);
874     tcg_gen_add_i64(dest, dest, flag);
875     tcg_temp_free_i64(flag);
876
877     if (!sf) {
878         tcg_gen_ext32u_i64(dest, dest);
879     }
880 }
881
882 /* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
883 static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
884 {
885     if (sf) {
886         TCGv_i64 result, cf_64, vf_64, tmp;
887         result = tcg_temp_new_i64();
888         cf_64 = tcg_temp_new_i64();
889         vf_64 = tcg_temp_new_i64();
890         tmp = tcg_const_i64(0);
891
892         tcg_gen_extu_i32_i64(cf_64, cpu_CF);
893         tcg_gen_add2_i64(result, cf_64, t0, tmp, cf_64, tmp);
894         tcg_gen_add2_i64(result, cf_64, result, cf_64, t1, tmp);
895         tcg_gen_extrl_i64_i32(cpu_CF, cf_64);
896         gen_set_NZ64(result);
897
898         tcg_gen_xor_i64(vf_64, result, t0);
899         tcg_gen_xor_i64(tmp, t0, t1);
900         tcg_gen_andc_i64(vf_64, vf_64, tmp);
901         tcg_gen_extrh_i64_i32(cpu_VF, vf_64);
902
903         tcg_gen_mov_i64(dest, result);
904
905         tcg_temp_free_i64(tmp);
906         tcg_temp_free_i64(vf_64);
907         tcg_temp_free_i64(cf_64);
908         tcg_temp_free_i64(result);
909     } else {
910         TCGv_i32 t0_32, t1_32, tmp;
911         t0_32 = tcg_temp_new_i32();
912         t1_32 = tcg_temp_new_i32();
913         tmp = tcg_const_i32(0);
914
915         tcg_gen_extrl_i64_i32(t0_32, t0);
916         tcg_gen_extrl_i64_i32(t1_32, t1);
917         tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, cpu_CF, tmp);
918         tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1_32, tmp);
919
920         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
921         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
922         tcg_gen_xor_i32(tmp, t0_32, t1_32);
923         tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
924         tcg_gen_extu_i32_i64(dest, cpu_NF);
925
926         tcg_temp_free_i32(tmp);
927         tcg_temp_free_i32(t1_32);
928         tcg_temp_free_i32(t0_32);
929     }
930 }
931
932 /*
933  * Load/Store generators
934  */
935
936 /*
937  * Store from GPR register to memory.
938  */
939 static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
940                              TCGv_i64 tcg_addr, int size, int memidx,
941                              bool iss_valid,
942                              unsigned int iss_srt,
943                              bool iss_sf, bool iss_ar)
944 {
945     g_assert(size <= 3);
946     tcg_gen_qemu_st_i64(source, tcg_addr, memidx, s->be_data + size);
947
948     if (iss_valid) {
949         uint32_t syn;
950
951         syn = syn_data_abort_with_iss(0,
952                                       size,
953                                       false,
954                                       iss_srt,
955                                       iss_sf,
956                                       iss_ar,
957                                       0, 0, 0, 0, 0, false);
958         disas_set_insn_syndrome(s, syn);
959     }
960 }
961
962 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
963                       TCGv_i64 tcg_addr, int size,
964                       bool iss_valid,
965                       unsigned int iss_srt,
966                       bool iss_sf, bool iss_ar)
967 {
968     do_gpr_st_memidx(s, source, tcg_addr, size, get_mem_index(s),
969                      iss_valid, iss_srt, iss_sf, iss_ar);
970 }
971
972 /*
973  * Load from memory to GPR register
974  */
975 static void do_gpr_ld_memidx(DisasContext *s,
976                              TCGv_i64 dest, TCGv_i64 tcg_addr,
977                              int size, bool is_signed,
978                              bool extend, int memidx,
979                              bool iss_valid, unsigned int iss_srt,
980                              bool iss_sf, bool iss_ar)
981 {
982     TCGMemOp memop = s->be_data + size;
983
984     g_assert(size <= 3);
985
986     if (is_signed) {
987         memop += MO_SIGN;
988     }
989
990     tcg_gen_qemu_ld_i64(dest, tcg_addr, memidx, memop);
991
992     if (extend && is_signed) {
993         g_assert(size < 3);
994         tcg_gen_ext32u_i64(dest, dest);
995     }
996
997     if (iss_valid) {
998         uint32_t syn;
999
1000         syn = syn_data_abort_with_iss(0,
1001                                       size,
1002                                       is_signed,
1003                                       iss_srt,
1004                                       iss_sf,
1005                                       iss_ar,
1006                                       0, 0, 0, 0, 0, false);
1007         disas_set_insn_syndrome(s, syn);
1008     }
1009 }
1010
1011 static void do_gpr_ld(DisasContext *s,
1012                       TCGv_i64 dest, TCGv_i64 tcg_addr,
1013                       int size, bool is_signed, bool extend,
1014                       bool iss_valid, unsigned int iss_srt,
1015                       bool iss_sf, bool iss_ar)
1016 {
1017     do_gpr_ld_memidx(s, dest, tcg_addr, size, is_signed, extend,
1018                      get_mem_index(s),
1019                      iss_valid, iss_srt, iss_sf, iss_ar);
1020 }
1021
1022 /*
1023  * Store from FP register to memory
1024  */
1025 static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
1026 {
1027     /* This writes the bottom N bits of a 128 bit wide vector to memory */
1028     TCGv_i64 tmp = tcg_temp_new_i64();
1029     tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
1030     if (size < 4) {
1031         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s),
1032                             s->be_data + size);
1033     } else {
1034         bool be = s->be_data == MO_BE;
1035         TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
1036
1037         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
1038         tcg_gen_qemu_st_i64(tmp, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
1039                             s->be_data | MO_Q);
1040         tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
1041         tcg_gen_qemu_st_i64(tmp, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
1042                             s->be_data | MO_Q);
1043         tcg_temp_free_i64(tcg_hiaddr);
1044     }
1045
1046     tcg_temp_free_i64(tmp);
1047 }
1048
1049 /*
1050  * Load from memory to FP register
1051  */
1052 static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
1053 {
1054     /* This always zero-extends and writes to a full 128 bit wide vector */
1055     TCGv_i64 tmplo = tcg_temp_new_i64();
1056     TCGv_i64 tmphi;
1057
1058     if (size < 4) {
1059         TCGMemOp memop = s->be_data + size;
1060         tmphi = tcg_const_i64(0);
1061         tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
1062     } else {
1063         bool be = s->be_data == MO_BE;
1064         TCGv_i64 tcg_hiaddr;
1065
1066         tmphi = tcg_temp_new_i64();
1067         tcg_hiaddr = tcg_temp_new_i64();
1068
1069         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
1070         tcg_gen_qemu_ld_i64(tmplo, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
1071                             s->be_data | MO_Q);
1072         tcg_gen_qemu_ld_i64(tmphi, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
1073                             s->be_data | MO_Q);
1074         tcg_temp_free_i64(tcg_hiaddr);
1075     }
1076
1077     tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
1078     tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
1079
1080     tcg_temp_free_i64(tmplo);
1081     tcg_temp_free_i64(tmphi);
1082
1083     clear_vec_high(s, true, destidx);
1084 }
1085
1086 /*
1087  * Vector load/store helpers.
1088  *
1089  * The principal difference between this and a FP load is that we don't
1090  * zero extend as we are filling a partial chunk of the vector register.
1091  * These functions don't support 128 bit loads/stores, which would be
1092  * normal load/store operations.
1093  *
1094  * The _i32 versions are useful when operating on 32 bit quantities
1095  * (eg for floating point single or using Neon helper functions).
1096  */
1097
1098 /* Get value of an element within a vector register */
1099 static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
1100                              int element, TCGMemOp memop)
1101 {
1102     int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
1103     switch (memop) {
1104     case MO_8:
1105         tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
1106         break;
1107     case MO_16:
1108         tcg_gen_ld16u_i64(tcg_dest, cpu_env, vect_off);
1109         break;
1110     case MO_32:
1111         tcg_gen_ld32u_i64(tcg_dest, cpu_env, vect_off);
1112         break;
1113     case MO_8|MO_SIGN:
1114         tcg_gen_ld8s_i64(tcg_dest, cpu_env, vect_off);
1115         break;
1116     case MO_16|MO_SIGN:
1117         tcg_gen_ld16s_i64(tcg_dest, cpu_env, vect_off);
1118         break;
1119     case MO_32|MO_SIGN:
1120         tcg_gen_ld32s_i64(tcg_dest, cpu_env, vect_off);
1121         break;
1122     case MO_64:
1123     case MO_64|MO_SIGN:
1124         tcg_gen_ld_i64(tcg_dest, cpu_env, vect_off);
1125         break;
1126     default:
1127         g_assert_not_reached();
1128     }
1129 }
1130
1131 static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
1132                                  int element, TCGMemOp memop)
1133 {
1134     int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
1135     switch (memop) {
1136     case MO_8:
1137         tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off);
1138         break;
1139     case MO_16:
1140         tcg_gen_ld16u_i32(tcg_dest, cpu_env, vect_off);
1141         break;
1142     case MO_8|MO_SIGN:
1143         tcg_gen_ld8s_i32(tcg_dest, cpu_env, vect_off);
1144         break;
1145     case MO_16|MO_SIGN:
1146         tcg_gen_ld16s_i32(tcg_dest, cpu_env, vect_off);
1147         break;
1148     case MO_32:
1149     case MO_32|MO_SIGN:
1150         tcg_gen_ld_i32(tcg_dest, cpu_env, vect_off);
1151         break;
1152     default:
1153         g_assert_not_reached();
1154     }
1155 }
1156
1157 /* Set value of an element within a vector register */
1158 static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
1159                               int element, TCGMemOp memop)
1160 {
1161     int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
1162     switch (memop) {
1163     case MO_8:
1164         tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
1165         break;
1166     case MO_16:
1167         tcg_gen_st16_i64(tcg_src, cpu_env, vect_off);
1168         break;
1169     case MO_32:
1170         tcg_gen_st32_i64(tcg_src, cpu_env, vect_off);
1171         break;
1172     case MO_64:
1173         tcg_gen_st_i64(tcg_src, cpu_env, vect_off);
1174         break;
1175     default:
1176         g_assert_not_reached();
1177     }
1178 }
1179
1180 static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
1181                                   int destidx, int element, TCGMemOp memop)
1182 {
1183     int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
1184     switch (memop) {
1185     case MO_8:
1186         tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
1187         break;
1188     case MO_16:
1189         tcg_gen_st16_i32(tcg_src, cpu_env, vect_off);
1190         break;
1191     case MO_32:
1192         tcg_gen_st_i32(tcg_src, cpu_env, vect_off);
1193         break;
1194     default:
1195         g_assert_not_reached();
1196     }
1197 }
1198
1199 /* Store from vector register to memory */
1200 static void do_vec_st(DisasContext *s, int srcidx, int element,
1201                       TCGv_i64 tcg_addr, int size)
1202 {
1203     TCGMemOp memop = s->be_data + size;
1204     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1205
1206     read_vec_element(s, tcg_tmp, srcidx, element, size);
1207     tcg_gen_qemu_st_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
1208
1209     tcg_temp_free_i64(tcg_tmp);
1210 }
1211
1212 /* Load from memory to vector register */
1213 static void do_vec_ld(DisasContext *s, int destidx, int element,
1214                       TCGv_i64 tcg_addr, int size)
1215 {
1216     TCGMemOp memop = s->be_data + size;
1217     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1218
1219     tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), memop);
1220     write_vec_element(s, tcg_tmp, destidx, element, size);
1221
1222     tcg_temp_free_i64(tcg_tmp);
1223 }
1224
1225 /* Check that FP/Neon access is enabled. If it is, return
1226  * true. If not, emit code to generate an appropriate exception,
1227  * and return false; the caller should not emit any code for
1228  * the instruction. Note that this check must happen after all
1229  * unallocated-encoding checks (otherwise the syndrome information
1230  * for the resulting exception will be incorrect).
1231  */
1232 static inline bool fp_access_check(DisasContext *s)
1233 {
1234     assert(!s->fp_access_checked);
1235     s->fp_access_checked = true;
1236
1237     if (!s->fp_excp_el) {
1238         return true;
1239     }
1240
1241     gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, false),
1242                        s->fp_excp_el);
1243     return false;
1244 }
1245
1246 /* Check that SVE access is enabled.  If it is, return true.
1247  * If not, emit code to generate an appropriate exception and return false.
1248  */
1249 static inline bool sve_access_check(DisasContext *s)
1250 {
1251     if (s->sve_excp_el) {
1252         gen_exception_insn(s, 4, EXCP_UDEF, syn_sve_access_trap(),
1253                            s->sve_excp_el);
1254         return false;
1255     }
1256     return true;
1257 }
1258
1259 /*
1260  * This utility function is for doing register extension with an
1261  * optional shift. You will likely want to pass a temporary for the
1262  * destination register. See DecodeRegExtend() in the ARM ARM.
1263  */
1264 static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
1265                               int option, unsigned int shift)
1266 {
1267     int extsize = extract32(option, 0, 2);
1268     bool is_signed = extract32(option, 2, 1);
1269
1270     if (is_signed) {
1271         switch (extsize) {
1272         case 0:
1273             tcg_gen_ext8s_i64(tcg_out, tcg_in);
1274             break;
1275         case 1:
1276             tcg_gen_ext16s_i64(tcg_out, tcg_in);
1277             break;
1278         case 2:
1279             tcg_gen_ext32s_i64(tcg_out, tcg_in);
1280             break;
1281         case 3:
1282             tcg_gen_mov_i64(tcg_out, tcg_in);
1283             break;
1284         }
1285     } else {
1286         switch (extsize) {
1287         case 0:
1288             tcg_gen_ext8u_i64(tcg_out, tcg_in);
1289             break;
1290         case 1:
1291             tcg_gen_ext16u_i64(tcg_out, tcg_in);
1292             break;
1293         case 2:
1294             tcg_gen_ext32u_i64(tcg_out, tcg_in);
1295             break;
1296         case 3:
1297             tcg_gen_mov_i64(tcg_out, tcg_in);
1298             break;
1299         }
1300     }
1301
1302     if (shift) {
1303         tcg_gen_shli_i64(tcg_out, tcg_out, shift);
1304     }
1305 }
1306
1307 static inline void gen_check_sp_alignment(DisasContext *s)
1308 {
1309     /* The AArch64 architecture mandates that (if enabled via PSTATE
1310      * or SCTLR bits) there is a check that SP is 16-aligned on every
1311      * SP-relative load or store (with an exception generated if it is not).
1312      * In line with general QEMU practice regarding misaligned accesses,
1313      * we omit these checks for the sake of guest program performance.
1314      * This function is provided as a hook so we can more easily add these
1315      * checks in future (possibly as a "favour catching guest program bugs
1316      * over speed" user selectable option).
1317      */
1318 }
1319
1320 /*
1321  * This provides a simple table based table lookup decoder. It is
1322  * intended to be used when the relevant bits for decode are too
1323  * awkwardly placed and switch/if based logic would be confusing and
1324  * deeply nested. Since it's a linear search through the table, tables
1325  * should be kept small.
1326  *
1327  * It returns the first handler where insn & mask == pattern, or
1328  * NULL if there is no match.
1329  * The table is terminated by an empty mask (i.e. 0)
1330  */
1331 static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
1332                                                uint32_t insn)
1333 {
1334     const AArch64DecodeTable *tptr = table;
1335
1336     while (tptr->mask) {
1337         if ((insn & tptr->mask) == tptr->pattern) {
1338             return tptr->disas_fn;
1339         }
1340         tptr++;
1341     }
1342     return NULL;
1343 }
1344
1345 /*
1346  * The instruction disassembly implemented here matches
1347  * the instruction encoding classifications in chapter C4
1348  * of the ARM Architecture Reference Manual (DDI0487B_a);
1349  * classification names and decode diagrams here should generally
1350  * match up with those in the manual.
1351  */
1352
1353 /* Unconditional branch (immediate)
1354  *   31  30       26 25                                  0
1355  * +----+-----------+-------------------------------------+
1356  * | op | 0 0 1 0 1 |                 imm26               |
1357  * +----+-----------+-------------------------------------+
1358  */
1359 static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
1360 {
1361     uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
1362
1363     if (insn & (1U << 31)) {
1364         /* BL Branch with link */
1365         tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1366     }
1367
1368     /* B Branch / BL Branch with link */
1369     gen_goto_tb(s, 0, addr);
1370 }
1371
1372 /* Compare and branch (immediate)
1373  *   31  30         25  24  23                  5 4      0
1374  * +----+-------------+----+---------------------+--------+
1375  * | sf | 0 1 1 0 1 0 | op |         imm19       |   Rt   |
1376  * +----+-------------+----+---------------------+--------+
1377  */
1378 static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
1379 {
1380     unsigned int sf, op, rt;
1381     uint64_t addr;
1382     TCGLabel *label_match;
1383     TCGv_i64 tcg_cmp;
1384
1385     sf = extract32(insn, 31, 1);
1386     op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
1387     rt = extract32(insn, 0, 5);
1388     addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
1389
1390     tcg_cmp = read_cpu_reg(s, rt, sf);
1391     label_match = gen_new_label();
1392
1393     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1394                         tcg_cmp, 0, label_match);
1395
1396     gen_goto_tb(s, 0, s->pc);
1397     gen_set_label(label_match);
1398     gen_goto_tb(s, 1, addr);
1399 }
1400
1401 /* Test and branch (immediate)
1402  *   31  30         25  24  23   19 18          5 4    0
1403  * +----+-------------+----+-------+-------------+------+
1404  * | b5 | 0 1 1 0 1 1 | op |  b40  |    imm14    |  Rt  |
1405  * +----+-------------+----+-------+-------------+------+
1406  */
1407 static void disas_test_b_imm(DisasContext *s, uint32_t insn)
1408 {
1409     unsigned int bit_pos, op, rt;
1410     uint64_t addr;
1411     TCGLabel *label_match;
1412     TCGv_i64 tcg_cmp;
1413
1414     bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
1415     op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
1416     addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
1417     rt = extract32(insn, 0, 5);
1418
1419     tcg_cmp = tcg_temp_new_i64();
1420     tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
1421     label_match = gen_new_label();
1422     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1423                         tcg_cmp, 0, label_match);
1424     tcg_temp_free_i64(tcg_cmp);
1425     gen_goto_tb(s, 0, s->pc);
1426     gen_set_label(label_match);
1427     gen_goto_tb(s, 1, addr);
1428 }
1429
1430 /* Conditional branch (immediate)
1431  *  31           25  24  23                  5   4  3    0
1432  * +---------------+----+---------------------+----+------+
1433  * | 0 1 0 1 0 1 0 | o1 |         imm19       | o0 | cond |
1434  * +---------------+----+---------------------+----+------+
1435  */
1436 static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
1437 {
1438     unsigned int cond;
1439     uint64_t addr;
1440
1441     if ((insn & (1 << 4)) || (insn & (1 << 24))) {
1442         unallocated_encoding(s);
1443         return;
1444     }
1445     addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
1446     cond = extract32(insn, 0, 4);
1447
1448     if (cond < 0x0e) {
1449         /* genuinely conditional branches */
1450         TCGLabel *label_match = gen_new_label();
1451         arm_gen_test_cc(cond, label_match);
1452         gen_goto_tb(s, 0, s->pc);
1453         gen_set_label(label_match);
1454         gen_goto_tb(s, 1, addr);
1455     } else {
1456         /* 0xe and 0xf are both "always" conditions */
1457         gen_goto_tb(s, 0, addr);
1458     }
1459 }
1460
1461 /* HINT instruction group, including various allocated HINTs */
1462 static void handle_hint(DisasContext *s, uint32_t insn,
1463                         unsigned int op1, unsigned int op2, unsigned int crm)
1464 {
1465     unsigned int selector = crm << 3 | op2;
1466
1467     if (op1 != 3) {
1468         unallocated_encoding(s);
1469         return;
1470     }
1471
1472     switch (selector) {
1473     case 0: /* NOP */
1474         return;
1475     case 3: /* WFI */
1476         s->base.is_jmp = DISAS_WFI;
1477         return;
1478         /* When running in MTTCG we don't generate jumps to the yield and
1479          * WFE helpers as it won't affect the scheduling of other vCPUs.
1480          * If we wanted to more completely model WFE/SEV so we don't busy
1481          * spin unnecessarily we would need to do something more involved.
1482          */
1483     case 1: /* YIELD */
1484         if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
1485             s->base.is_jmp = DISAS_YIELD;
1486         }
1487         return;
1488     case 2: /* WFE */
1489         if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
1490             s->base.is_jmp = DISAS_WFE;
1491         }
1492         return;
1493     case 4: /* SEV */
1494     case 5: /* SEVL */
1495         /* we treat all as NOP at least for now */
1496         return;
1497     default:
1498         /* default specified as NOP equivalent */
1499         return;
1500     }
1501 }
1502
1503 static void gen_clrex(DisasContext *s, uint32_t insn)
1504 {
1505     tcg_gen_movi_i64(cpu_exclusive_addr, -1);
1506 }
1507
1508 /* CLREX, DSB, DMB, ISB */
1509 static void handle_sync(DisasContext *s, uint32_t insn,
1510                         unsigned int op1, unsigned int op2, unsigned int crm)
1511 {
1512     TCGBar bar;
1513
1514     if (op1 != 3) {
1515         unallocated_encoding(s);
1516         return;
1517     }
1518
1519     switch (op2) {
1520     case 2: /* CLREX */
1521         gen_clrex(s, insn);
1522         return;
1523     case 4: /* DSB */
1524     case 5: /* DMB */
1525         switch (crm & 3) {
1526         case 1: /* MBReqTypes_Reads */
1527             bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
1528             break;
1529         case 2: /* MBReqTypes_Writes */
1530             bar = TCG_BAR_SC | TCG_MO_ST_ST;
1531             break;
1532         default: /* MBReqTypes_All */
1533             bar = TCG_BAR_SC | TCG_MO_ALL;
1534             break;
1535         }
1536         tcg_gen_mb(bar);
1537         return;
1538     case 6: /* ISB */
1539         /* We need to break the TB after this insn to execute
1540          * a self-modified code correctly and also to take
1541          * any pending interrupts immediately.
1542          */
1543         gen_goto_tb(s, 0, s->pc);
1544         return;
1545     default:
1546         unallocated_encoding(s);
1547         return;
1548     }
1549 }
1550
1551 /* MSR (immediate) - move immediate to processor state field */
1552 static void handle_msr_i(DisasContext *s, uint32_t insn,
1553                          unsigned int op1, unsigned int op2, unsigned int crm)
1554 {
1555     int op = op1 << 3 | op2;
1556     switch (op) {
1557     case 0x05: /* SPSel */
1558         if (s->current_el == 0) {
1559             unallocated_encoding(s);
1560             return;
1561         }
1562         /* fall through */
1563     case 0x1e: /* DAIFSet */
1564     case 0x1f: /* DAIFClear */
1565     {
1566         TCGv_i32 tcg_imm = tcg_const_i32(crm);
1567         TCGv_i32 tcg_op = tcg_const_i32(op);
1568         gen_a64_set_pc_im(s->pc - 4);
1569         gen_helper_msr_i_pstate(cpu_env, tcg_op, tcg_imm);
1570         tcg_temp_free_i32(tcg_imm);
1571         tcg_temp_free_i32(tcg_op);
1572         /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs.  */
1573         gen_a64_set_pc_im(s->pc);
1574         s->base.is_jmp = (op == 0x1f ? DISAS_EXIT : DISAS_JUMP);
1575         break;
1576     }
1577     default:
1578         unallocated_encoding(s);
1579         return;
1580     }
1581 }
1582
1583 static void gen_get_nzcv(TCGv_i64 tcg_rt)
1584 {
1585     TCGv_i32 tmp = tcg_temp_new_i32();
1586     TCGv_i32 nzcv = tcg_temp_new_i32();
1587
1588     /* build bit 31, N */
1589     tcg_gen_andi_i32(nzcv, cpu_NF, (1U << 31));
1590     /* build bit 30, Z */
1591     tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
1592     tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
1593     /* build bit 29, C */
1594     tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
1595     /* build bit 28, V */
1596     tcg_gen_shri_i32(tmp, cpu_VF, 31);
1597     tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
1598     /* generate result */
1599     tcg_gen_extu_i32_i64(tcg_rt, nzcv);
1600
1601     tcg_temp_free_i32(nzcv);
1602     tcg_temp_free_i32(tmp);
1603 }
1604
1605 static void gen_set_nzcv(TCGv_i64 tcg_rt)
1606
1607 {
1608     TCGv_i32 nzcv = tcg_temp_new_i32();
1609
1610     /* take NZCV from R[t] */
1611     tcg_gen_extrl_i64_i32(nzcv, tcg_rt);
1612
1613     /* bit 31, N */
1614     tcg_gen_andi_i32(cpu_NF, nzcv, (1U << 31));
1615     /* bit 30, Z */
1616     tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
1617     tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
1618     /* bit 29, C */
1619     tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
1620     tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
1621     /* bit 28, V */
1622     tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
1623     tcg_gen_shli_i32(cpu_VF, cpu_VF, 3);
1624     tcg_temp_free_i32(nzcv);
1625 }
1626
1627 /* MRS - move from system register
1628  * MSR (register) - move to system register
1629  * SYS
1630  * SYSL
1631  * These are all essentially the same insn in 'read' and 'write'
1632  * versions, with varying op0 fields.
1633  */
1634 static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
1635                        unsigned int op0, unsigned int op1, unsigned int op2,
1636                        unsigned int crn, unsigned int crm, unsigned int rt)
1637 {
1638     const ARMCPRegInfo *ri;
1639     TCGv_i64 tcg_rt;
1640
1641     ri = get_arm_cp_reginfo(s->cp_regs,
1642                             ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
1643                                                crn, crm, op0, op1, op2));
1644
1645     if (!ri) {
1646         /* Unknown register; this might be a guest error or a QEMU
1647          * unimplemented feature.
1648          */
1649         qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch64 "
1650                       "system register op0:%d op1:%d crn:%d crm:%d op2:%d\n",
1651                       isread ? "read" : "write", op0, op1, crn, crm, op2);
1652         unallocated_encoding(s);
1653         return;
1654     }
1655
1656     /* Check access permissions */
1657     if (!cp_access_ok(s->current_el, ri, isread)) {
1658         unallocated_encoding(s);
1659         return;
1660     }
1661
1662     if (ri->accessfn) {
1663         /* Emit code to perform further access permissions checks at
1664          * runtime; this may result in an exception.
1665          */
1666         TCGv_ptr tmpptr;
1667         TCGv_i32 tcg_syn, tcg_isread;
1668         uint32_t syndrome;
1669
1670         gen_a64_set_pc_im(s->pc - 4);
1671         tmpptr = tcg_const_ptr(ri);
1672         syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
1673         tcg_syn = tcg_const_i32(syndrome);
1674         tcg_isread = tcg_const_i32(isread);
1675         gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn, tcg_isread);
1676         tcg_temp_free_ptr(tmpptr);
1677         tcg_temp_free_i32(tcg_syn);
1678         tcg_temp_free_i32(tcg_isread);
1679     }
1680
1681     /* Handle special cases first */
1682     switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
1683     case ARM_CP_NOP:
1684         return;
1685     case ARM_CP_NZCV:
1686         tcg_rt = cpu_reg(s, rt);
1687         if (isread) {
1688             gen_get_nzcv(tcg_rt);
1689         } else {
1690             gen_set_nzcv(tcg_rt);
1691         }
1692         return;
1693     case ARM_CP_CURRENTEL:
1694         /* Reads as current EL value from pstate, which is
1695          * guaranteed to be constant by the tb flags.
1696          */
1697         tcg_rt = cpu_reg(s, rt);
1698         tcg_gen_movi_i64(tcg_rt, s->current_el << 2);
1699         return;
1700     case ARM_CP_DC_ZVA:
1701         /* Writes clear the aligned block of memory which rt points into. */
1702         tcg_rt = cpu_reg(s, rt);
1703         gen_helper_dc_zva(cpu_env, tcg_rt);
1704         return;
1705     default:
1706         break;
1707     }
1708     if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
1709         return;
1710     }
1711     if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
1712         return;
1713     }
1714
1715     if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
1716         gen_io_start();
1717     }
1718
1719     tcg_rt = cpu_reg(s, rt);
1720
1721     if (isread) {
1722         if (ri->type & ARM_CP_CONST) {
1723             tcg_gen_movi_i64(tcg_rt, ri->resetvalue);
1724         } else if (ri->readfn) {
1725             TCGv_ptr tmpptr;
1726             tmpptr = tcg_const_ptr(ri);
1727             gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr);
1728             tcg_temp_free_ptr(tmpptr);
1729         } else {
1730             tcg_gen_ld_i64(tcg_rt, cpu_env, ri->fieldoffset);
1731         }
1732     } else {
1733         if (ri->type & ARM_CP_CONST) {
1734             /* If not forbidden by access permissions, treat as WI */
1735             return;
1736         } else if (ri->writefn) {
1737             TCGv_ptr tmpptr;
1738             tmpptr = tcg_const_ptr(ri);
1739             gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt);
1740             tcg_temp_free_ptr(tmpptr);
1741         } else {
1742             tcg_gen_st_i64(tcg_rt, cpu_env, ri->fieldoffset);
1743         }
1744     }
1745
1746     if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
1747         /* I/O operations must end the TB here (whether read or write) */
1748         gen_io_end();
1749         s->base.is_jmp = DISAS_UPDATE;
1750     } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
1751         /* We default to ending the TB on a coprocessor register write,
1752          * but allow this to be suppressed by the register definition
1753          * (usually only necessary to work around guest bugs).
1754          */
1755         s->base.is_jmp = DISAS_UPDATE;
1756     }
1757 }
1758
1759 /* System
1760  *  31                 22 21  20 19 18 16 15   12 11    8 7   5 4    0
1761  * +---------------------+---+-----+-----+-------+-------+-----+------+
1762  * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 |  CRn  |  CRm  | op2 |  Rt  |
1763  * +---------------------+---+-----+-----+-------+-------+-----+------+
1764  */
1765 static void disas_system(DisasContext *s, uint32_t insn)
1766 {
1767     unsigned int l, op0, op1, crn, crm, op2, rt;
1768     l = extract32(insn, 21, 1);
1769     op0 = extract32(insn, 19, 2);
1770     op1 = extract32(insn, 16, 3);
1771     crn = extract32(insn, 12, 4);
1772     crm = extract32(insn, 8, 4);
1773     op2 = extract32(insn, 5, 3);
1774     rt = extract32(insn, 0, 5);
1775
1776     if (op0 == 0) {
1777         if (l || rt != 31) {
1778             unallocated_encoding(s);
1779             return;
1780         }
1781         switch (crn) {
1782         case 2: /* HINT (including allocated hints like NOP, YIELD, etc) */
1783             handle_hint(s, insn, op1, op2, crm);
1784             break;
1785         case 3: /* CLREX, DSB, DMB, ISB */
1786             handle_sync(s, insn, op1, op2, crm);
1787             break;
1788         case 4: /* MSR (immediate) */
1789             handle_msr_i(s, insn, op1, op2, crm);
1790             break;
1791         default:
1792             unallocated_encoding(s);
1793             break;
1794         }
1795         return;
1796     }
1797     handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
1798 }
1799
1800 /* Exception generation
1801  *
1802  *  31             24 23 21 20                     5 4   2 1  0
1803  * +-----------------+-----+------------------------+-----+----+
1804  * | 1 1 0 1 0 1 0 0 | opc |          imm16         | op2 | LL |
1805  * +-----------------------+------------------------+----------+
1806  */
1807 static void disas_exc(DisasContext *s, uint32_t insn)
1808 {
1809     int opc = extract32(insn, 21, 3);
1810     int op2_ll = extract32(insn, 0, 5);
1811     int imm16 = extract32(insn, 5, 16);
1812     TCGv_i32 tmp;
1813
1814     switch (opc) {
1815     case 0:
1816         /* For SVC, HVC and SMC we advance the single-step state
1817          * machine before taking the exception. This is architecturally
1818          * mandated, to ensure that single-stepping a system call
1819          * instruction works properly.
1820          */
1821         switch (op2_ll) {
1822         case 1:                                                     /* SVC */
1823             gen_ss_advance(s);
1824             gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16),
1825                                default_exception_el(s));
1826             break;
1827         case 2:                                                     /* HVC */
1828             if (s->current_el == 0) {
1829                 unallocated_encoding(s);
1830                 break;
1831             }
1832             /* The pre HVC helper handles cases when HVC gets trapped
1833              * as an undefined insn by runtime configuration.
1834              */
1835             gen_a64_set_pc_im(s->pc - 4);
1836             gen_helper_pre_hvc(cpu_env);
1837             gen_ss_advance(s);
1838             gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16), 2);
1839             break;
1840         case 3:                                                     /* SMC */
1841             if (s->current_el == 0) {
1842                 unallocated_encoding(s);
1843                 break;
1844             }
1845             gen_a64_set_pc_im(s->pc - 4);
1846             tmp = tcg_const_i32(syn_aa64_smc(imm16));
1847             gen_helper_pre_smc(cpu_env, tmp);
1848             tcg_temp_free_i32(tmp);
1849             gen_ss_advance(s);
1850             gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16), 3);
1851             break;
1852         default:
1853             unallocated_encoding(s);
1854             break;
1855         }
1856         break;
1857     case 1:
1858         if (op2_ll != 0) {
1859             unallocated_encoding(s);
1860             break;
1861         }
1862         /* BRK */
1863         gen_exception_bkpt_insn(s, 4, syn_aa64_bkpt(imm16));
1864         break;
1865     case 2:
1866         if (op2_ll != 0) {
1867             unallocated_encoding(s);
1868             break;
1869         }
1870         /* HLT. This has two purposes.
1871          * Architecturally, it is an external halting debug instruction.
1872          * Since QEMU doesn't implement external debug, we treat this as
1873          * it is required for halting debug disabled: it will UNDEF.
1874          * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
1875          */
1876         if (semihosting_enabled() && imm16 == 0xf000) {
1877 #ifndef CONFIG_USER_ONLY
1878             /* In system mode, don't allow userspace access to semihosting,
1879              * to provide some semblance of security (and for consistency
1880              * with our 32-bit semihosting).
1881              */
1882             if (s->current_el == 0) {
1883                 unsupported_encoding(s, insn);
1884                 break;
1885             }
1886 #endif
1887             gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
1888         } else {
1889             unsupported_encoding(s, insn);
1890         }
1891         break;
1892     case 5:
1893         if (op2_ll < 1 || op2_ll > 3) {
1894             unallocated_encoding(s);
1895             break;
1896         }
1897         /* DCPS1, DCPS2, DCPS3 */
1898         unsupported_encoding(s, insn);
1899         break;
1900     default:
1901         unallocated_encoding(s);
1902         break;
1903     }
1904 }
1905
1906 /* Unconditional branch (register)
1907  *  31           25 24   21 20   16 15   10 9    5 4     0
1908  * +---------------+-------+-------+-------+------+-------+
1909  * | 1 1 0 1 0 1 1 |  opc  |  op2  |  op3  |  Rn  |  op4  |
1910  * +---------------+-------+-------+-------+------+-------+
1911  */
1912 static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
1913 {
1914     unsigned int opc, op2, op3, rn, op4;
1915
1916     opc = extract32(insn, 21, 4);
1917     op2 = extract32(insn, 16, 5);
1918     op3 = extract32(insn, 10, 6);
1919     rn = extract32(insn, 5, 5);
1920     op4 = extract32(insn, 0, 5);
1921
1922     if (op4 != 0x0 || op3 != 0x0 || op2 != 0x1f) {
1923         unallocated_encoding(s);
1924         return;
1925     }
1926
1927     switch (opc) {
1928     case 0: /* BR */
1929     case 1: /* BLR */
1930     case 2: /* RET */
1931         gen_a64_set_pc(s, cpu_reg(s, rn));
1932         /* BLR also needs to load return address */
1933         if (opc == 1) {
1934             tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1935         }
1936         break;
1937     case 4: /* ERET */
1938         if (s->current_el == 0) {
1939             unallocated_encoding(s);
1940             return;
1941         }
1942         if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1943             gen_io_start();
1944         }
1945         gen_helper_exception_return(cpu_env);
1946         if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
1947             gen_io_end();
1948         }
1949         /* Must exit loop to check un-masked IRQs */
1950         s->base.is_jmp = DISAS_EXIT;
1951         return;
1952     case 5: /* DRPS */
1953         if (rn != 0x1f) {
1954             unallocated_encoding(s);
1955         } else {
1956             unsupported_encoding(s, insn);
1957         }
1958         return;
1959     default:
1960         unallocated_encoding(s);
1961         return;
1962     }
1963
1964     s->base.is_jmp = DISAS_JUMP;
1965 }
1966
1967 /* Branches, exception generating and system instructions */
1968 static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
1969 {
1970     switch (extract32(insn, 25, 7)) {
1971     case 0x0a: case 0x0b:
1972     case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
1973         disas_uncond_b_imm(s, insn);
1974         break;
1975     case 0x1a: case 0x5a: /* Compare & branch (immediate) */
1976         disas_comp_b_imm(s, insn);
1977         break;
1978     case 0x1b: case 0x5b: /* Test & branch (immediate) */
1979         disas_test_b_imm(s, insn);
1980         break;
1981     case 0x2a: /* Conditional branch (immediate) */
1982         disas_cond_b_imm(s, insn);
1983         break;
1984     case 0x6a: /* Exception generation / System */
1985         if (insn & (1 << 24)) {
1986             disas_system(s, insn);
1987         } else {
1988             disas_exc(s, insn);
1989         }
1990         break;
1991     case 0x6b: /* Unconditional branch (register) */
1992         disas_uncond_b_reg(s, insn);
1993         break;
1994     default:
1995         unallocated_encoding(s);
1996         break;
1997     }
1998 }
1999
2000 /*
2001  * Load/Store exclusive instructions are implemented by remembering
2002  * the value/address loaded, and seeing if these are the same
2003  * when the store is performed. This is not actually the architecturally
2004  * mandated semantics, but it works for typical guest code sequences
2005  * and avoids having to monitor regular stores.
2006  *
2007  * The store exclusive uses the atomic cmpxchg primitives to avoid
2008  * races in multi-threaded linux-user and when MTTCG softmmu is
2009  * enabled.
2010  */
2011 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
2012                                TCGv_i64 addr, int size, bool is_pair)
2013 {
2014     int idx = get_mem_index(s);
2015     TCGMemOp memop = s->be_data;
2016
2017     g_assert(size <= 3);
2018     if (is_pair) {
2019         g_assert(size >= 2);
2020         if (size == 2) {
2021             /* The pair must be single-copy atomic for the doubleword.  */
2022             memop |= MO_64 | MO_ALIGN;
2023             tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
2024             if (s->be_data == MO_LE) {
2025                 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
2026                 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 32, 32);
2027             } else {
2028                 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 32, 32);
2029                 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 0, 32);
2030             }
2031         } else {
2032             /* The pair must be single-copy atomic for *each* doubleword, not
2033                the entire quadword, however it must be quadword aligned.  */
2034             memop |= MO_64;
2035             tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx,
2036                                 memop | MO_ALIGN_16);
2037
2038             TCGv_i64 addr2 = tcg_temp_new_i64();
2039             tcg_gen_addi_i64(addr2, addr, 8);
2040             tcg_gen_qemu_ld_i64(cpu_exclusive_high, addr2, idx, memop);
2041             tcg_temp_free_i64(addr2);
2042
2043             tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
2044             tcg_gen_mov_i64(cpu_reg(s, rt2), cpu_exclusive_high);
2045         }
2046     } else {
2047         memop |= size | MO_ALIGN;
2048         tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
2049         tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
2050     }
2051     tcg_gen_mov_i64(cpu_exclusive_addr, addr);
2052 }
2053
2054 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
2055                                 TCGv_i64 addr, int size, int is_pair)
2056 {
2057     /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]
2058      *     && (!is_pair || env->exclusive_high == [addr + datasize])) {
2059      *     [addr] = {Rt};
2060      *     if (is_pair) {
2061      *         [addr + datasize] = {Rt2};
2062      *     }
2063      *     {Rd} = 0;
2064      * } else {
2065      *     {Rd} = 1;
2066      * }
2067      * env->exclusive_addr = -1;
2068      */
2069     TCGLabel *fail_label = gen_new_label();
2070     TCGLabel *done_label = gen_new_label();
2071     TCGv_i64 tmp;
2072
2073     tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
2074
2075     tmp = tcg_temp_new_i64();
2076     if (is_pair) {
2077         if (size == 2) {
2078             if (s->be_data == MO_LE) {
2079                 tcg_gen_concat32_i64(tmp, cpu_reg(s, rt), cpu_reg(s, rt2));
2080             } else {
2081                 tcg_gen_concat32_i64(tmp, cpu_reg(s, rt2), cpu_reg(s, rt));
2082             }
2083             tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr,
2084                                        cpu_exclusive_val, tmp,
2085                                        get_mem_index(s),
2086                                        MO_64 | MO_ALIGN | s->be_data);
2087             tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
2088         } else if (s->be_data == MO_LE) {
2089             if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2090                 gen_helper_paired_cmpxchg64_le_parallel(tmp, cpu_env,
2091                                                         cpu_exclusive_addr,
2092                                                         cpu_reg(s, rt),
2093                                                         cpu_reg(s, rt2));
2094             } else {
2095                 gen_helper_paired_cmpxchg64_le(tmp, cpu_env, cpu_exclusive_addr,
2096                                                cpu_reg(s, rt), cpu_reg(s, rt2));
2097             }
2098         } else {
2099             if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2100                 gen_helper_paired_cmpxchg64_be_parallel(tmp, cpu_env,
2101                                                         cpu_exclusive_addr,
2102                                                         cpu_reg(s, rt),
2103                                                         cpu_reg(s, rt2));
2104             } else {
2105                 gen_helper_paired_cmpxchg64_be(tmp, cpu_env, cpu_exclusive_addr,
2106                                                cpu_reg(s, rt), cpu_reg(s, rt2));
2107             }
2108         }
2109     } else {
2110         tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr, cpu_exclusive_val,
2111                                    cpu_reg(s, rt), get_mem_index(s),
2112                                    size | MO_ALIGN | s->be_data);
2113         tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
2114     }
2115     tcg_gen_mov_i64(cpu_reg(s, rd), tmp);
2116     tcg_temp_free_i64(tmp);
2117     tcg_gen_br(done_label);
2118
2119     gen_set_label(fail_label);
2120     tcg_gen_movi_i64(cpu_reg(s, rd), 1);
2121     gen_set_label(done_label);
2122     tcg_gen_movi_i64(cpu_exclusive_addr, -1);
2123 }
2124
2125 static void gen_compare_and_swap(DisasContext *s, int rs, int rt,
2126                                  int rn, int size)
2127 {
2128     TCGv_i64 tcg_rs = cpu_reg(s, rs);
2129     TCGv_i64 tcg_rt = cpu_reg(s, rt);
2130     int memidx = get_mem_index(s);
2131     TCGv_i64 addr = cpu_reg_sp(s, rn);
2132
2133     if (rn == 31) {
2134         gen_check_sp_alignment(s);
2135     }
2136     tcg_gen_atomic_cmpxchg_i64(tcg_rs, addr, tcg_rs, tcg_rt, memidx,
2137                                size | MO_ALIGN | s->be_data);
2138 }
2139
2140 static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
2141                                       int rn, int size)
2142 {
2143     TCGv_i64 s1 = cpu_reg(s, rs);
2144     TCGv_i64 s2 = cpu_reg(s, rs + 1);
2145     TCGv_i64 t1 = cpu_reg(s, rt);
2146     TCGv_i64 t2 = cpu_reg(s, rt + 1);
2147     TCGv_i64 addr = cpu_reg_sp(s, rn);
2148     int memidx = get_mem_index(s);
2149
2150     if (rn == 31) {
2151         gen_check_sp_alignment(s);
2152     }
2153
2154     if (size == 2) {
2155         TCGv_i64 cmp = tcg_temp_new_i64();
2156         TCGv_i64 val = tcg_temp_new_i64();
2157
2158         if (s->be_data == MO_LE) {
2159             tcg_gen_concat32_i64(val, t1, t2);
2160             tcg_gen_concat32_i64(cmp, s1, s2);
2161         } else {
2162             tcg_gen_concat32_i64(val, t2, t1);
2163             tcg_gen_concat32_i64(cmp, s2, s1);
2164         }
2165
2166         tcg_gen_atomic_cmpxchg_i64(cmp, addr, cmp, val, memidx,
2167                                    MO_64 | MO_ALIGN | s->be_data);
2168         tcg_temp_free_i64(val);
2169
2170         if (s->be_data == MO_LE) {
2171             tcg_gen_extr32_i64(s1, s2, cmp);
2172         } else {
2173             tcg_gen_extr32_i64(s2, s1, cmp);
2174         }
2175         tcg_temp_free_i64(cmp);
2176     } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2177         TCGv_i32 tcg_rs = tcg_const_i32(rs);
2178
2179         if (s->be_data == MO_LE) {
2180             gen_helper_casp_le_parallel(cpu_env, tcg_rs, addr, t1, t2);
2181         } else {
2182             gen_helper_casp_be_parallel(cpu_env, tcg_rs, addr, t1, t2);
2183         }
2184         tcg_temp_free_i32(tcg_rs);
2185     } else {
2186         TCGv_i64 d1 = tcg_temp_new_i64();
2187         TCGv_i64 d2 = tcg_temp_new_i64();
2188         TCGv_i64 a2 = tcg_temp_new_i64();
2189         TCGv_i64 c1 = tcg_temp_new_i64();
2190         TCGv_i64 c2 = tcg_temp_new_i64();
2191         TCGv_i64 zero = tcg_const_i64(0);
2192
2193         /* Load the two words, in memory order.  */
2194         tcg_gen_qemu_ld_i64(d1, addr, memidx,
2195                             MO_64 | MO_ALIGN_16 | s->be_data);
2196         tcg_gen_addi_i64(a2, addr, 8);
2197         tcg_gen_qemu_ld_i64(d2, addr, memidx, MO_64 | s->be_data);
2198
2199         /* Compare the two words, also in memory order.  */
2200         tcg_gen_setcond_i64(TCG_COND_EQ, c1, d1, s1);
2201         tcg_gen_setcond_i64(TCG_COND_EQ, c2, d2, s2);
2202         tcg_gen_and_i64(c2, c2, c1);
2203
2204         /* If compare equal, write back new data, else write back old data.  */
2205         tcg_gen_movcond_i64(TCG_COND_NE, c1, c2, zero, t1, d1);
2206         tcg_gen_movcond_i64(TCG_COND_NE, c2, c2, zero, t2, d2);
2207         tcg_gen_qemu_st_i64(c1, addr, memidx, MO_64 | s->be_data);
2208         tcg_gen_qemu_st_i64(c2, a2, memidx, MO_64 | s->be_data);
2209         tcg_temp_free_i64(a2);
2210         tcg_temp_free_i64(c1);
2211         tcg_temp_free_i64(c2);
2212         tcg_temp_free_i64(zero);
2213
2214         /* Write back the data from memory to Rs.  */
2215         tcg_gen_mov_i64(s1, d1);
2216         tcg_gen_mov_i64(s2, d2);
2217         tcg_temp_free_i64(d1);
2218         tcg_temp_free_i64(d2);
2219     }
2220 }
2221
2222 /* Update the Sixty-Four bit (SF) registersize. This logic is derived
2223  * from the ARMv8 specs for LDR (Shared decode for all encodings).
2224  */
2225 static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
2226 {
2227     int opc0 = extract32(opc, 0, 1);
2228     int regsize;
2229
2230     if (is_signed) {
2231         regsize = opc0 ? 32 : 64;
2232     } else {
2233         regsize = size == 3 ? 64 : 32;
2234     }
2235     return regsize == 64;
2236 }
2237
2238 /* Load/store exclusive
2239  *
2240  *  31 30 29         24  23  22   21  20  16  15  14   10 9    5 4    0
2241  * +-----+-------------+----+---+----+------+----+-------+------+------+
2242  * | sz  | 0 0 1 0 0 0 | o2 | L | o1 |  Rs  | o0 |  Rt2  |  Rn  | Rt   |
2243  * +-----+-------------+----+---+----+------+----+-------+------+------+
2244  *
2245  *  sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
2246  *   L: 0 -> store, 1 -> load
2247  *  o2: 0 -> exclusive, 1 -> not
2248  *  o1: 0 -> single register, 1 -> register pair
2249  *  o0: 1 -> load-acquire/store-release, 0 -> not
2250  */
2251 static void disas_ldst_excl(DisasContext *s, uint32_t insn)
2252 {
2253     int rt = extract32(insn, 0, 5);
2254     int rn = extract32(insn, 5, 5);
2255     int rt2 = extract32(insn, 10, 5);
2256     int rs = extract32(insn, 16, 5);
2257     int is_lasr = extract32(insn, 15, 1);
2258     int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
2259     int size = extract32(insn, 30, 2);
2260     TCGv_i64 tcg_addr;
2261
2262     switch (o2_L_o1_o0) {
2263     case 0x0: /* STXR */
2264     case 0x1: /* STLXR */
2265         if (rn == 31) {
2266             gen_check_sp_alignment(s);
2267         }
2268         if (is_lasr) {
2269             tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2270         }
2271         tcg_addr = read_cpu_reg_sp(s, rn, 1);
2272         gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, false);
2273         return;
2274
2275     case 0x4: /* LDXR */
2276     case 0x5: /* LDAXR */
2277         if (rn == 31) {
2278             gen_check_sp_alignment(s);
2279         }
2280         tcg_addr = read_cpu_reg_sp(s, rn, 1);
2281         s->is_ldex = true;
2282         gen_load_exclusive(s, rt, rt2, tcg_addr, size, false);
2283         if (is_lasr) {
2284             tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2285         }
2286         return;
2287
2288     case 0x9: /* STLR */
2289         /* Generate ISS for non-exclusive accesses including LASR.  */
2290         if (rn == 31) {
2291             gen_check_sp_alignment(s);
2292         }
2293         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2294         tcg_addr = read_cpu_reg_sp(s, rn, 1);
2295         do_gpr_st(s, cpu_reg(s, rt), tcg_addr, size, true, rt,
2296                   disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
2297         return;
2298
2299     case 0xd: /* LDAR */
2300         /* Generate ISS for non-exclusive accesses including LASR.  */
2301         if (rn == 31) {
2302             gen_check_sp_alignment(s);
2303         }
2304         tcg_addr = read_cpu_reg_sp(s, rn, 1);
2305         do_gpr_ld(s, cpu_reg(s, rt), tcg_addr, size, false, false, true, rt,
2306                   disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
2307         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2308         return;
2309
2310     case 0x2: case 0x3: /* CASP / STXP */
2311         if (size & 2) { /* STXP / STLXP */
2312             if (rn == 31) {
2313                 gen_check_sp_alignment(s);
2314             }
2315             if (is_lasr) {
2316                 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2317             }
2318             tcg_addr = read_cpu_reg_sp(s, rn, 1);
2319             gen_store_exclusive(s, rs, rt, rt2, tcg_addr, size, true);
2320             return;
2321         }
2322         if (rt2 == 31
2323             && ((rt | rs) & 1) == 0
2324             && arm_dc_feature(s, ARM_FEATURE_V8_ATOMICS)) {
2325             /* CASP / CASPL */
2326             gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
2327             return;
2328         }
2329         break;
2330
2331     case 0x6: case 0x7: /* CASPA / LDXP */
2332         if (size & 2) { /* LDXP / LDAXP */
2333             if (rn == 31) {
2334                 gen_check_sp_alignment(s);
2335             }
2336             tcg_addr = read_cpu_reg_sp(s, rn, 1);
2337             s->is_ldex = true;
2338             gen_load_exclusive(s, rt, rt2, tcg_addr, size, true);
2339             if (is_lasr) {
2340                 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2341             }
2342             return;
2343         }
2344         if (rt2 == 31
2345             && ((rt | rs) & 1) == 0
2346             && arm_dc_feature(s, ARM_FEATURE_V8_ATOMICS)) {
2347             /* CASPA / CASPAL */
2348             gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
2349             return;
2350         }
2351         break;
2352
2353     case 0xa: /* CAS */
2354     case 0xb: /* CASL */
2355     case 0xe: /* CASA */
2356     case 0xf: /* CASAL */
2357         if (rt2 == 31 && arm_dc_feature(s, ARM_FEATURE_V8_ATOMICS)) {
2358             gen_compare_and_swap(s, rs, rt, rn, size);
2359             return;
2360         }
2361         break;
2362     }
2363     unallocated_encoding(s);
2364 }
2365
2366 /*
2367  * Load register (literal)
2368  *
2369  *  31 30 29   27  26 25 24 23                5 4     0
2370  * +-----+-------+---+-----+-------------------+-------+
2371  * | opc | 0 1 1 | V | 0 0 |     imm19         |  Rt   |
2372  * +-----+-------+---+-----+-------------------+-------+
2373  *
2374  * V: 1 -> vector (simd/fp)
2375  * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
2376  *                   10-> 32 bit signed, 11 -> prefetch
2377  * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
2378  */
2379 static void disas_ld_lit(DisasContext *s, uint32_t insn)
2380 {
2381     int rt = extract32(insn, 0, 5);
2382     int64_t imm = sextract32(insn, 5, 19) << 2;
2383     bool is_vector = extract32(insn, 26, 1);
2384     int opc = extract32(insn, 30, 2);
2385     bool is_signed = false;
2386     int size = 2;
2387     TCGv_i64 tcg_rt, tcg_addr;
2388
2389     if (is_vector) {
2390         if (opc == 3) {
2391             unallocated_encoding(s);
2392             return;
2393         }
2394         size = 2 + opc;
2395         if (!fp_access_check(s)) {
2396             return;
2397         }
2398     } else {
2399         if (opc == 3) {
2400             /* PRFM (literal) : prefetch */
2401             return;
2402         }
2403         size = 2 + extract32(opc, 0, 1);
2404         is_signed = extract32(opc, 1, 1);
2405     }
2406
2407     tcg_rt = cpu_reg(s, rt);
2408
2409     tcg_addr = tcg_const_i64((s->pc - 4) + imm);
2410     if (is_vector) {
2411         do_fp_ld(s, rt, tcg_addr, size);
2412     } else {
2413         /* Only unsigned 32bit loads target 32bit registers.  */
2414         bool iss_sf = opc != 0;
2415
2416         do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, false,
2417                   true, rt, iss_sf, false);
2418     }
2419     tcg_temp_free_i64(tcg_addr);
2420 }
2421
2422 /*
2423  * LDNP (Load Pair - non-temporal hint)
2424  * LDP (Load Pair - non vector)
2425  * LDPSW (Load Pair Signed Word - non vector)
2426  * STNP (Store Pair - non-temporal hint)
2427  * STP (Store Pair - non vector)
2428  * LDNP (Load Pair of SIMD&FP - non-temporal hint)
2429  * LDP (Load Pair of SIMD&FP)
2430  * STNP (Store Pair of SIMD&FP - non-temporal hint)
2431  * STP (Store Pair of SIMD&FP)
2432  *
2433  *  31 30 29   27  26  25 24   23  22 21   15 14   10 9    5 4    0
2434  * +-----+-------+---+---+-------+---+-----------------------------+
2435  * | opc | 1 0 1 | V | 0 | index | L |  imm7 |  Rt2  |  Rn  | Rt   |
2436  * +-----+-------+---+---+-------+---+-------+-------+------+------+
2437  *
2438  * opc: LDP/STP/LDNP/STNP        00 -> 32 bit, 10 -> 64 bit
2439  *      LDPSW                    01
2440  *      LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
2441  *   V: 0 -> GPR, 1 -> Vector
2442  * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
2443  *      10 -> signed offset, 11 -> pre-index
2444  *   L: 0 -> Store 1 -> Load
2445  *
2446  * Rt, Rt2 = GPR or SIMD registers to be stored
2447  * Rn = general purpose register containing address
2448  * imm7 = signed offset (multiple of 4 or 8 depending on size)
2449  */
2450 static void disas_ldst_pair(DisasContext *s, uint32_t insn)
2451 {
2452     int rt = extract32(insn, 0, 5);
2453     int rn = extract32(insn, 5, 5);
2454     int rt2 = extract32(insn, 10, 5);
2455     uint64_t offset = sextract64(insn, 15, 7);
2456     int index = extract32(insn, 23, 2);
2457     bool is_vector = extract32(insn, 26, 1);
2458     bool is_load = extract32(insn, 22, 1);
2459     int opc = extract32(insn, 30, 2);
2460
2461     bool is_signed = false;
2462     bool postindex = false;
2463     bool wback = false;
2464
2465     TCGv_i64 tcg_addr; /* calculated address */
2466     int size;
2467
2468     if (opc == 3) {
2469         unallocated_encoding(s);
2470         return;
2471     }
2472
2473     if (is_vector) {
2474         size = 2 + opc;
2475     } else {
2476         size = 2 + extract32(opc, 1, 1);
2477         is_signed = extract32(opc, 0, 1);
2478         if (!is_load && is_signed) {
2479             unallocated_encoding(s);
2480             return;
2481         }
2482     }
2483
2484     switch (index) {
2485     case 1: /* post-index */
2486         postindex = true;
2487         wback = true;
2488         break;
2489     case 0:
2490         /* signed offset with "non-temporal" hint. Since we don't emulate
2491          * caches we don't care about hints to the cache system about
2492          * data access patterns, and handle this identically to plain
2493          * signed offset.
2494          */
2495         if (is_signed) {
2496             /* There is no non-temporal-hint version of LDPSW */
2497             unallocated_encoding(s);
2498             return;
2499         }
2500         postindex = false;
2501         break;
2502     case 2: /* signed offset, rn not updated */
2503         postindex = false;
2504         break;
2505     case 3: /* pre-index */
2506         postindex = false;
2507         wback = true;
2508         break;
2509     }
2510
2511     if (is_vector && !fp_access_check(s)) {
2512         return;
2513     }
2514
2515     offset <<= size;
2516
2517     if (rn == 31) {
2518         gen_check_sp_alignment(s);
2519     }
2520
2521     tcg_addr = read_cpu_reg_sp(s, rn, 1);
2522
2523     if (!postindex) {
2524         tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
2525     }
2526
2527     if (is_vector) {
2528         if (is_load) {
2529             do_fp_ld(s, rt, tcg_addr, size);
2530         } else {
2531             do_fp_st(s, rt, tcg_addr, size);
2532         }
2533         tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
2534         if (is_load) {
2535             do_fp_ld(s, rt2, tcg_addr, size);
2536         } else {
2537             do_fp_st(s, rt2, tcg_addr, size);
2538         }
2539     } else {
2540         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2541         TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
2542
2543         if (is_load) {
2544             TCGv_i64 tmp = tcg_temp_new_i64();
2545
2546             /* Do not modify tcg_rt before recognizing any exception
2547              * from the second load.
2548              */
2549             do_gpr_ld(s, tmp, tcg_addr, size, is_signed, false,
2550                       false, 0, false, false);
2551             tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
2552             do_gpr_ld(s, tcg_rt2, tcg_addr, size, is_signed, false,
2553                       false, 0, false, false);
2554
2555             tcg_gen_mov_i64(tcg_rt, tmp);
2556             tcg_temp_free_i64(tmp);
2557         } else {
2558             do_gpr_st(s, tcg_rt, tcg_addr, size,
2559                       false, 0, false, false);
2560             tcg_gen_addi_i64(tcg_addr, tcg_addr, 1 << size);
2561             do_gpr_st(s, tcg_rt2, tcg_addr, size,
2562                       false, 0, false, false);
2563         }
2564     }
2565
2566     if (wback) {
2567         if (postindex) {
2568             tcg_gen_addi_i64(tcg_addr, tcg_addr, offset - (1 << size));
2569         } else {
2570             tcg_gen_subi_i64(tcg_addr, tcg_addr, 1 << size);
2571         }
2572         tcg_gen_mov_i64(cpu_reg_sp(s, rn), tcg_addr);
2573     }
2574 }
2575
2576 /*
2577  * Load/store (immediate post-indexed)
2578  * Load/store (immediate pre-indexed)
2579  * Load/store (unscaled immediate)
2580  *
2581  * 31 30 29   27  26 25 24 23 22 21  20    12 11 10 9    5 4    0
2582  * +----+-------+---+-----+-----+---+--------+-----+------+------+
2583  * |size| 1 1 1 | V | 0 0 | opc | 0 |  imm9  | idx |  Rn  |  Rt  |
2584  * +----+-------+---+-----+-----+---+--------+-----+------+------+
2585  *
2586  * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
2587          10 -> unprivileged
2588  * V = 0 -> non-vector
2589  * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
2590  * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2591  */
2592 static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
2593                                 int opc,
2594                                 int size,
2595                                 int rt,
2596                                 bool is_vector)
2597 {
2598     int rn = extract32(insn, 5, 5);
2599     int imm9 = sextract32(insn, 12, 9);
2600     int idx = extract32(insn, 10, 2);
2601     bool is_signed = false;
2602     bool is_store = false;
2603     bool is_extended = false;
2604     bool is_unpriv = (idx == 2);
2605     bool iss_valid = !is_vector;
2606     bool post_index;
2607     bool writeback;
2608
2609     TCGv_i64 tcg_addr;
2610
2611     if (is_vector) {
2612         size |= (opc & 2) << 1;
2613         if (size > 4 || is_unpriv) {
2614             unallocated_encoding(s);
2615             return;
2616         }
2617         is_store = ((opc & 1) == 0);
2618         if (!fp_access_check(s)) {
2619             return;
2620         }
2621     } else {
2622         if (size == 3 && opc == 2) {
2623             /* PRFM - prefetch */
2624             if (is_unpriv) {
2625                 unallocated_encoding(s);
2626                 return;
2627             }
2628             return;
2629         }
2630         if (opc == 3 && size > 1) {
2631             unallocated_encoding(s);
2632             return;
2633         }
2634         is_store = (opc == 0);
2635         is_signed = extract32(opc, 1, 1);
2636         is_extended = (size < 3) && extract32(opc, 0, 1);
2637     }
2638
2639     switch (idx) {
2640     case 0:
2641     case 2:
2642         post_index = false;
2643         writeback = false;
2644         break;
2645     case 1:
2646         post_index = true;
2647         writeback = true;
2648         break;
2649     case 3:
2650         post_index = false;
2651         writeback = true;
2652         break;
2653     default:
2654         g_assert_not_reached();
2655     }
2656
2657     if (rn == 31) {
2658         gen_check_sp_alignment(s);
2659     }
2660     tcg_addr = read_cpu_reg_sp(s, rn, 1);
2661
2662     if (!post_index) {
2663         tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
2664     }
2665
2666     if (is_vector) {
2667         if (is_store) {
2668             do_fp_st(s, rt, tcg_addr, size);
2669         } else {
2670             do_fp_ld(s, rt, tcg_addr, size);
2671         }
2672     } else {
2673         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2674         int memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
2675         bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
2676
2677         if (is_store) {
2678             do_gpr_st_memidx(s, tcg_rt, tcg_addr, size, memidx,
2679                              iss_valid, rt, iss_sf, false);
2680         } else {
2681             do_gpr_ld_memidx(s, tcg_rt, tcg_addr, size,
2682                              is_signed, is_extended, memidx,
2683                              iss_valid, rt, iss_sf, false);
2684         }
2685     }
2686
2687     if (writeback) {
2688         TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
2689         if (post_index) {
2690             tcg_gen_addi_i64(tcg_addr, tcg_addr, imm9);
2691         }
2692         tcg_gen_mov_i64(tcg_rn, tcg_addr);
2693     }
2694 }
2695
2696 /*
2697  * Load/store (register offset)
2698  *
2699  * 31 30 29   27  26 25 24 23 22 21  20  16 15 13 12 11 10 9  5 4  0
2700  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2701  * |size| 1 1 1 | V | 0 0 | opc | 1 |  Rm  | opt | S| 1 0 | Rn | Rt |
2702  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2703  *
2704  * For non-vector:
2705  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
2706  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2707  * For vector:
2708  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
2709  *   opc<0>: 0 -> store, 1 -> load
2710  * V: 1 -> vector/simd
2711  * opt: extend encoding (see DecodeRegExtend)
2712  * S: if S=1 then scale (essentially index by sizeof(size))
2713  * Rt: register to transfer into/out of
2714  * Rn: address register or SP for base
2715  * Rm: offset register or ZR for offset
2716  */
2717 static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
2718                                    int opc,
2719                                    int size,
2720                                    int rt,
2721                                    bool is_vector)
2722 {
2723     int rn = extract32(insn, 5, 5);
2724     int shift = extract32(insn, 12, 1);
2725     int rm = extract32(insn, 16, 5);
2726     int opt = extract32(insn, 13, 3);
2727     bool is_signed = false;
2728     bool is_store = false;
2729     bool is_extended = false;
2730
2731     TCGv_i64 tcg_rm;
2732     TCGv_i64 tcg_addr;
2733
2734     if (extract32(opt, 1, 1) == 0) {
2735         unallocated_encoding(s);
2736         return;
2737     }
2738
2739     if (is_vector) {
2740         size |= (opc & 2) << 1;
2741         if (size > 4) {
2742             unallocated_encoding(s);
2743             return;
2744         }
2745         is_store = !extract32(opc, 0, 1);
2746         if (!fp_access_check(s)) {
2747             return;
2748         }
2749     } else {
2750         if (size == 3 && opc == 2) {
2751             /* PRFM - prefetch */
2752             return;
2753         }
2754         if (opc == 3 && size > 1) {
2755             unallocated_encoding(s);
2756             return;
2757         }
2758         is_store = (opc == 0);
2759         is_signed = extract32(opc, 1, 1);
2760         is_extended = (size < 3) && extract32(opc, 0, 1);
2761     }
2762
2763     if (rn == 31) {
2764         gen_check_sp_alignment(s);
2765     }
2766     tcg_addr = read_cpu_reg_sp(s, rn, 1);
2767
2768     tcg_rm = read_cpu_reg(s, rm, 1);
2769     ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
2770
2771     tcg_gen_add_i64(tcg_addr, tcg_addr, tcg_rm);
2772
2773     if (is_vector) {
2774         if (is_store) {
2775             do_fp_st(s, rt, tcg_addr, size);
2776         } else {
2777             do_fp_ld(s, rt, tcg_addr, size);
2778         }
2779     } else {
2780         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2781         bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
2782         if (is_store) {
2783             do_gpr_st(s, tcg_rt, tcg_addr, size,
2784                       true, rt, iss_sf, false);
2785         } else {
2786             do_gpr_ld(s, tcg_rt, tcg_addr, size,
2787                       is_signed, is_extended,
2788                       true, rt, iss_sf, false);
2789         }
2790     }
2791 }
2792
2793 /*
2794  * Load/store (unsigned immediate)
2795  *
2796  * 31 30 29   27  26 25 24 23 22 21        10 9     5
2797  * +----+-------+---+-----+-----+------------+-------+------+
2798  * |size| 1 1 1 | V | 0 1 | opc |   imm12    |  Rn   |  Rt  |
2799  * +----+-------+---+-----+-----+------------+-------+------+
2800  *
2801  * For non-vector:
2802  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
2803  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2804  * For vector:
2805  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
2806  *   opc<0>: 0 -> store, 1 -> load
2807  * Rn: base address register (inc SP)
2808  * Rt: target register
2809  */
2810 static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
2811                                         int opc,
2812                                         int size,
2813                                         int rt,
2814                                         bool is_vector)
2815 {
2816     int rn = extract32(insn, 5, 5);
2817     unsigned int imm12 = extract32(insn, 10, 12);
2818     unsigned int offset;
2819
2820     TCGv_i64 tcg_addr;
2821
2822     bool is_store;
2823     bool is_signed = false;
2824     bool is_extended = false;
2825
2826     if (is_vector) {
2827         size |= (opc & 2) << 1;
2828         if (size > 4) {
2829             unallocated_encoding(s);
2830             return;
2831         }
2832         is_store = !extract32(opc, 0, 1);
2833         if (!fp_access_check(s)) {
2834             return;
2835         }
2836     } else {
2837         if (size == 3 && opc == 2) {
2838             /* PRFM - prefetch */
2839             return;
2840         }
2841         if (opc == 3 && size > 1) {
2842             unallocated_encoding(s);
2843             return;
2844         }
2845         is_store = (opc == 0);
2846         is_signed = extract32(opc, 1, 1);
2847         is_extended = (size < 3) && extract32(opc, 0, 1);
2848     }
2849
2850     if (rn == 31) {
2851         gen_check_sp_alignment(s);
2852     }
2853     tcg_addr = read_cpu_reg_sp(s, rn, 1);
2854     offset = imm12 << size;
2855     tcg_gen_addi_i64(tcg_addr, tcg_addr, offset);
2856
2857     if (is_vector) {
2858         if (is_store) {
2859             do_fp_st(s, rt, tcg_addr, size);
2860         } else {
2861             do_fp_ld(s, rt, tcg_addr, size);
2862         }
2863     } else {
2864         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2865         bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
2866         if (is_store) {
2867             do_gpr_st(s, tcg_rt, tcg_addr, size,
2868                       true, rt, iss_sf, false);
2869         } else {
2870             do_gpr_ld(s, tcg_rt, tcg_addr, size, is_signed, is_extended,
2871                       true, rt, iss_sf, false);
2872         }
2873     }
2874 }
2875
2876 /* Atomic memory operations
2877  *
2878  *  31  30      27  26    24    22  21   16   15    12    10    5     0
2879  * +------+-------+---+-----+-----+---+----+----+-----+-----+----+-----+
2880  * | size | 1 1 1 | V | 0 0 | A R | 1 | Rs | o3 | opc | 0 0 | Rn |  Rt |
2881  * +------+-------+---+-----+-----+--------+----+-----+-----+----+-----+
2882  *
2883  * Rt: the result register
2884  * Rn: base address or SP
2885  * Rs: the source register for the operation
2886  * V: vector flag (always 0 as of v8.3)
2887  * A: acquire flag
2888  * R: release flag
2889  */
2890 static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
2891                               int size, int rt, bool is_vector)
2892 {
2893     int rs = extract32(insn, 16, 5);
2894     int rn = extract32(insn, 5, 5);
2895     int o3_opc = extract32(insn, 12, 4);
2896     int feature = ARM_FEATURE_V8_ATOMICS;
2897     TCGv_i64 tcg_rn, tcg_rs;
2898     AtomicThreeOpFn *fn;
2899
2900     if (is_vector) {
2901         unallocated_encoding(s);
2902         return;
2903     }
2904     switch (o3_opc) {
2905     case 000: /* LDADD */
2906         fn = tcg_gen_atomic_fetch_add_i64;
2907         break;
2908     case 001: /* LDCLR */
2909         fn = tcg_gen_atomic_fetch_and_i64;
2910         break;
2911     case 002: /* LDEOR */
2912         fn = tcg_gen_atomic_fetch_xor_i64;
2913         break;
2914     case 003: /* LDSET */
2915         fn = tcg_gen_atomic_fetch_or_i64;
2916         break;
2917     case 004: /* LDSMAX */
2918         fn = tcg_gen_atomic_fetch_smax_i64;
2919         break;
2920     case 005: /* LDSMIN */
2921         fn = tcg_gen_atomic_fetch_smin_i64;
2922         break;
2923     case 006: /* LDUMAX */
2924         fn = tcg_gen_atomic_fetch_umax_i64;
2925         break;
2926     case 007: /* LDUMIN */
2927         fn = tcg_gen_atomic_fetch_umin_i64;
2928         break;
2929     case 010: /* SWP */
2930         fn = tcg_gen_atomic_xchg_i64;
2931         break;
2932     default:
2933         unallocated_encoding(s);
2934         return;
2935     }
2936     if (!arm_dc_feature(s, feature)) {
2937         unallocated_encoding(s);
2938         return;
2939     }
2940
2941     if (rn == 31) {
2942         gen_check_sp_alignment(s);
2943     }
2944     tcg_rn = cpu_reg_sp(s, rn);
2945     tcg_rs = read_cpu_reg(s, rs, true);
2946
2947     if (o3_opc == 1) { /* LDCLR */
2948         tcg_gen_not_i64(tcg_rs, tcg_rs);
2949     }
2950
2951     /* The tcg atomic primitives are all full barriers.  Therefore we
2952      * can ignore the Acquire and Release bits of this instruction.
2953      */
2954     fn(cpu_reg(s, rt), tcg_rn, tcg_rs, get_mem_index(s),
2955        s->be_data | size | MO_ALIGN);
2956 }
2957
2958 /* Load/store register (all forms) */
2959 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
2960 {
2961     int rt = extract32(insn, 0, 5);
2962     int opc = extract32(insn, 22, 2);
2963     bool is_vector = extract32(insn, 26, 1);
2964     int size = extract32(insn, 30, 2);
2965
2966     switch (extract32(insn, 24, 2)) {
2967     case 0:
2968         if (extract32(insn, 21, 1) == 0) {
2969             /* Load/store register (unscaled immediate)
2970              * Load/store immediate pre/post-indexed
2971              * Load/store register unprivileged
2972              */
2973             disas_ldst_reg_imm9(s, insn, opc, size, rt, is_vector);
2974             return;
2975         }
2976         switch (extract32(insn, 10, 2)) {
2977         case 0:
2978             disas_ldst_atomic(s, insn, size, rt, is_vector);
2979             return;
2980         case 2:
2981             disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector);
2982             return;
2983         }
2984         break;
2985     case 1:
2986         disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector);
2987         return;
2988     }
2989     unallocated_encoding(s);
2990 }
2991
2992 /* AdvSIMD load/store multiple structures
2993  *
2994  *  31  30  29           23 22  21         16 15    12 11  10 9    5 4    0
2995  * +---+---+---------------+---+-------------+--------+------+------+------+
2996  * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size |  Rn  |  Rt  |
2997  * +---+---+---------------+---+-------------+--------+------+------+------+
2998  *
2999  * AdvSIMD load/store multiple structures (post-indexed)
3000  *
3001  *  31  30  29           23 22  21  20     16 15    12 11  10 9    5 4    0
3002  * +---+---+---------------+---+---+---------+--------+------+------+------+
3003  * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 |   Rm    | opcode | size |  Rn  |  Rt  |
3004  * +---+---+---------------+---+---+---------+--------+------+------+------+
3005  *
3006  * Rt: first (or only) SIMD&FP register to be transferred
3007  * Rn: base address or SP
3008  * Rm (post-index only): post-index register (when !31) or size dependent #imm
3009  */
3010 static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
3011 {
3012     int rt = extract32(insn, 0, 5);
3013     int rn = extract32(insn, 5, 5);
3014     int size = extract32(insn, 10, 2);
3015     int opcode = extract32(insn, 12, 4);
3016     bool is_store = !extract32(insn, 22, 1);
3017     bool is_postidx = extract32(insn, 23, 1);
3018     bool is_q = extract32(insn, 30, 1);
3019     TCGv_i64 tcg_addr, tcg_rn;
3020
3021     int ebytes = 1 << size;
3022     int elements = (is_q ? 128 : 64) / (8 << size);
3023     int rpt;    /* num iterations */
3024     int selem;  /* structure elements */
3025     int r;
3026
3027     if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
3028         unallocated_encoding(s);
3029         return;
3030     }
3031
3032     /* From the shared decode logic */
3033     switch (opcode) {
3034     case 0x0:
3035         rpt = 1;
3036         selem = 4;
3037         break;
3038     case 0x2:
3039         rpt = 4;
3040         selem = 1;
3041         break;
3042     case 0x4:
3043         rpt = 1;
3044         selem = 3;
3045         break;
3046     case 0x6:
3047         rpt = 3;
3048         selem = 1;
3049         break;
3050     case 0x7:
3051         rpt = 1;
3052         selem = 1;
3053         break;
3054     case 0x8:
3055         rpt = 1;
3056         selem = 2;
3057         break;
3058     case 0xa:
3059         rpt = 2;
3060         selem = 1;
3061         break;
3062     default:
3063         unallocated_encoding(s);
3064         return;
3065     }
3066
3067     if (size == 3 && !is_q && selem != 1) {
3068         /* reserved */
3069         unallocated_encoding(s);
3070         return;
3071     }
3072
3073     if (!fp_access_check(s)) {
3074         return;
3075     }
3076
3077     if (rn == 31) {
3078         gen_check_sp_alignment(s);
3079     }
3080
3081     tcg_rn = cpu_reg_sp(s, rn);
3082     tcg_addr = tcg_temp_new_i64();
3083     tcg_gen_mov_i64(tcg_addr, tcg_rn);
3084
3085     for (r = 0; r < rpt; r++) {
3086         int e;
3087         for (e = 0; e < elements; e++) {
3088             int tt = (rt + r) % 32;
3089             int xs;
3090             for (xs = 0; xs < selem; xs++) {
3091                 if (is_store) {
3092                     do_vec_st(s, tt, e, tcg_addr, size);
3093                 } else {
3094                     do_vec_ld(s, tt, e, tcg_addr, size);
3095
3096                     /* For non-quad operations, setting a slice of the low
3097                      * 64 bits of the register clears the high 64 bits (in
3098                      * the ARM ARM pseudocode this is implicit in the fact
3099                      * that 'rval' is a 64 bit wide variable).
3100                      * For quad operations, we might still need to zero the
3101                      * high bits of SVE.  We optimize by noticing that we only
3102                      * need to do this the first time we touch a register.
3103                      */
3104                     if (e == 0 && (r == 0 || xs == selem - 1)) {
3105                         clear_vec_high(s, is_q, tt);
3106                     }
3107                 }
3108                 tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
3109                 tt = (tt + 1) % 32;
3110             }
3111         }
3112     }
3113
3114     if (is_postidx) {
3115         int rm = extract32(insn, 16, 5);
3116         if (rm == 31) {
3117             tcg_gen_mov_i64(tcg_rn, tcg_addr);
3118         } else {
3119             tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
3120         }
3121     }
3122     tcg_temp_free_i64(tcg_addr);
3123 }
3124
3125 /* AdvSIMD load/store single structure
3126  *
3127  *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
3128  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3129  * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size |  Rn  |  Rt  |
3130  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3131  *
3132  * AdvSIMD load/store single structure (post-indexed)
3133  *
3134  *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
3135  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3136  * | 0 | Q | 0 0 1 1 0 1 1 | L R |     Rm    | opc | S | size |  Rn  |  Rt  |
3137  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3138  *
3139  * Rt: first (or only) SIMD&FP register to be transferred
3140  * Rn: base address or SP
3141  * Rm (post-index only): post-index register (when !31) or size dependent #imm
3142  * index = encoded in Q:S:size dependent on size
3143  *
3144  * lane_size = encoded in R, opc
3145  * transfer width = encoded in opc, S, size
3146  */
3147 static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
3148 {
3149     int rt = extract32(insn, 0, 5);
3150     int rn = extract32(insn, 5, 5);
3151     int size = extract32(insn, 10, 2);
3152     int S = extract32(insn, 12, 1);
3153     int opc = extract32(insn, 13, 3);
3154     int R = extract32(insn, 21, 1);
3155     int is_load = extract32(insn, 22, 1);
3156     int is_postidx = extract32(insn, 23, 1);
3157     int is_q = extract32(insn, 30, 1);
3158
3159     int scale = extract32(opc, 1, 2);
3160     int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
3161     bool replicate = false;
3162     int index = is_q << 3 | S << 2 | size;
3163     int ebytes, xs;
3164     TCGv_i64 tcg_addr, tcg_rn;
3165
3166     switch (scale) {
3167     case 3:
3168         if (!is_load || S) {
3169             unallocated_encoding(s);
3170             return;
3171         }
3172         scale = size;
3173         replicate = true;
3174         break;
3175     case 0:
3176         break;
3177     case 1:
3178         if (extract32(size, 0, 1)) {
3179             unallocated_encoding(s);
3180             return;
3181         }
3182         index >>= 1;
3183         break;
3184     case 2:
3185         if (extract32(size, 1, 1)) {
3186             unallocated_encoding(s);
3187             return;
3188         }
3189         if (!extract32(size, 0, 1)) {
3190             index >>= 2;
3191         } else {
3192             if (S) {
3193                 unallocated_encoding(s);
3194                 return;
3195             }
3196             index >>= 3;
3197             scale = 3;
3198         }
3199         break;
3200     default:
3201         g_assert_not_reached();
3202     }
3203
3204     if (!fp_access_check(s)) {
3205         return;
3206     }
3207
3208     ebytes = 1 << scale;
3209
3210     if (rn == 31) {
3211         gen_check_sp_alignment(s);
3212     }
3213
3214     tcg_rn = cpu_reg_sp(s, rn);
3215     tcg_addr = tcg_temp_new_i64();
3216     tcg_gen_mov_i64(tcg_addr, tcg_rn);
3217
3218     for (xs = 0; xs < selem; xs++) {
3219         if (replicate) {
3220             /* Load and replicate to all elements */
3221             uint64_t mulconst;
3222             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3223
3224             tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr,
3225                                 get_mem_index(s), s->be_data + scale);
3226             switch (scale) {
3227             case 0:
3228                 mulconst = 0x0101010101010101ULL;
3229                 break;
3230             case 1:
3231                 mulconst = 0x0001000100010001ULL;
3232                 break;
3233             case 2:
3234                 mulconst = 0x0000000100000001ULL;
3235                 break;
3236             case 3:
3237                 mulconst = 0;
3238                 break;
3239             default:
3240                 g_assert_not_reached();
3241             }
3242             if (mulconst) {
3243                 tcg_gen_muli_i64(tcg_tmp, tcg_tmp, mulconst);
3244             }
3245             write_vec_element(s, tcg_tmp, rt, 0, MO_64);
3246             if (is_q) {
3247                 write_vec_element(s, tcg_tmp, rt, 1, MO_64);
3248             }
3249             tcg_temp_free_i64(tcg_tmp);
3250             clear_vec_high(s, is_q, rt);
3251         } else {
3252             /* Load/store one element per register */
3253             if (is_load) {
3254                 do_vec_ld(s, rt, index, tcg_addr, scale);
3255             } else {
3256                 do_vec_st(s, rt, index, tcg_addr, scale);
3257             }
3258         }
3259         tcg_gen_addi_i64(tcg_addr, tcg_addr, ebytes);
3260         rt = (rt + 1) % 32;
3261     }
3262
3263     if (is_postidx) {
3264         int rm = extract32(insn, 16, 5);
3265         if (rm == 31) {
3266             tcg_gen_mov_i64(tcg_rn, tcg_addr);
3267         } else {
3268             tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
3269         }
3270     }
3271     tcg_temp_free_i64(tcg_addr);
3272 }
3273
3274 /* Loads and stores */
3275 static void disas_ldst(DisasContext *s, uint32_t insn)
3276 {
3277     switch (extract32(insn, 24, 6)) {
3278     case 0x08: /* Load/store exclusive */
3279         disas_ldst_excl(s, insn);
3280         break;
3281     case 0x18: case 0x1c: /* Load register (literal) */
3282         disas_ld_lit(s, insn);
3283         break;
3284     case 0x28: case 0x29:
3285     case 0x2c: case 0x2d: /* Load/store pair (all forms) */
3286         disas_ldst_pair(s, insn);
3287         break;
3288     case 0x38: case 0x39:
3289     case 0x3c: case 0x3d: /* Load/store register (all forms) */
3290         disas_ldst_reg(s, insn);
3291         break;
3292     case 0x0c: /* AdvSIMD load/store multiple structures */
3293         disas_ldst_multiple_struct(s, insn);
3294         break;
3295     case 0x0d: /* AdvSIMD load/store single structure */
3296         disas_ldst_single_struct(s, insn);
3297         break;
3298     default:
3299         unallocated_encoding(s);
3300         break;
3301     }
3302 }
3303
3304 /* PC-rel. addressing
3305  *   31  30   29 28       24 23                5 4    0
3306  * +----+-------+-----------+-------------------+------+
3307  * | op | immlo | 1 0 0 0 0 |       immhi       |  Rd  |
3308  * +----+-------+-----------+-------------------+------+
3309  */
3310 static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
3311 {
3312     unsigned int page, rd;
3313     uint64_t base;
3314     uint64_t offset;
3315
3316     page = extract32(insn, 31, 1);
3317     /* SignExtend(immhi:immlo) -> offset */
3318     offset = sextract64(insn, 5, 19);
3319     offset = offset << 2 | extract32(insn, 29, 2);
3320     rd = extract32(insn, 0, 5);
3321     base = s->pc - 4;
3322
3323     if (page) {
3324         /* ADRP (page based) */
3325         base &= ~0xfff;
3326         offset <<= 12;
3327     }
3328
3329     tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
3330 }
3331
3332 /*
3333  * Add/subtract (immediate)
3334  *
3335  *  31 30 29 28       24 23 22 21         10 9   5 4   0
3336  * +--+--+--+-----------+-----+-------------+-----+-----+
3337  * |sf|op| S| 1 0 0 0 1 |shift|    imm12    |  Rn | Rd  |
3338  * +--+--+--+-----------+-----+-------------+-----+-----+
3339  *
3340  *    sf: 0 -> 32bit, 1 -> 64bit
3341  *    op: 0 -> add  , 1 -> sub
3342  *     S: 1 -> set flags
3343  * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
3344  */
3345 static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
3346 {
3347     int rd = extract32(insn, 0, 5);
3348     int rn = extract32(insn, 5, 5);
3349     uint64_t imm = extract32(insn, 10, 12);
3350     int shift = extract32(insn, 22, 2);
3351     bool setflags = extract32(insn, 29, 1);
3352     bool sub_op = extract32(insn, 30, 1);
3353     bool is_64bit = extract32(insn, 31, 1);
3354
3355     TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
3356     TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
3357     TCGv_i64 tcg_result;
3358
3359     switch (shift) {
3360     case 0x0:
3361         break;
3362     case 0x1:
3363         imm <<= 12;
3364         break;
3365     default:
3366         unallocated_encoding(s);
3367         return;
3368     }
3369
3370     tcg_result = tcg_temp_new_i64();
3371     if (!setflags) {
3372         if (sub_op) {
3373             tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
3374         } else {
3375             tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
3376         }
3377     } else {
3378         TCGv_i64 tcg_imm = tcg_const_i64(imm);
3379         if (sub_op) {
3380             gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
3381         } else {
3382             gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
3383         }
3384         tcg_temp_free_i64(tcg_imm);
3385     }
3386
3387     if (is_64bit) {
3388         tcg_gen_mov_i64(tcg_rd, tcg_result);
3389     } else {
3390         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
3391     }
3392
3393     tcg_temp_free_i64(tcg_result);
3394 }
3395
3396 /* The input should be a value in the bottom e bits (with higher
3397  * bits zero); returns that value replicated into every element
3398  * of size e in a 64 bit integer.
3399  */
3400 static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
3401 {
3402     assert(e != 0);
3403     while (e < 64) {
3404         mask |= mask << e;
3405         e *= 2;
3406     }
3407     return mask;
3408 }
3409
3410 /* Return a value with the bottom len bits set (where 0 < len <= 64) */
3411 static inline uint64_t bitmask64(unsigned int length)
3412 {
3413     assert(length > 0 && length <= 64);
3414     return ~0ULL >> (64 - length);
3415 }
3416
3417 /* Simplified variant of pseudocode DecodeBitMasks() for the case where we
3418  * only require the wmask. Returns false if the imms/immr/immn are a reserved
3419  * value (ie should cause a guest UNDEF exception), and true if they are
3420  * valid, in which case the decoded bit pattern is written to result.
3421  */
3422 static bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
3423                                    unsigned int imms, unsigned int immr)
3424 {
3425     uint64_t mask;
3426     unsigned e, levels, s, r;
3427     int len;
3428
3429     assert(immn < 2 && imms < 64 && immr < 64);
3430
3431     /* The bit patterns we create here are 64 bit patterns which
3432      * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
3433      * 64 bits each. Each element contains the same value: a run
3434      * of between 1 and e-1 non-zero bits, rotated within the
3435      * element by between 0 and e-1 bits.
3436      *
3437      * The element size and run length are encoded into immn (1 bit)
3438      * and imms (6 bits) as follows:
3439      * 64 bit elements: immn = 1, imms = <length of run - 1>
3440      * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
3441      * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
3442      *  8 bit elements: immn = 0, imms = 110 : <length of run - 1>
3443      *  4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
3444      *  2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
3445      * Notice that immn = 0, imms = 11111x is the only combination
3446      * not covered by one of the above options; this is reserved.
3447      * Further, <length of run - 1> all-ones is a reserved pattern.
3448      *
3449      * In all cases the rotation is by immr % e (and immr is 6 bits).
3450      */
3451
3452     /* First determine the element size */
3453     len = 31 - clz32((immn << 6) | (~imms & 0x3f));
3454     if (len < 1) {
3455         /* This is the immn == 0, imms == 0x11111x case */
3456         return false;
3457     }
3458     e = 1 << len;
3459
3460     levels = e - 1;
3461     s = imms & levels;
3462     r = immr & levels;
3463
3464     if (s == levels) {
3465         /* <length of run - 1> mustn't be all-ones. */
3466         return false;
3467     }
3468
3469     /* Create the value of one element: s+1 set bits rotated
3470      * by r within the element (which is e bits wide)...
3471      */
3472     mask = bitmask64(s + 1);
3473     if (r) {
3474         mask = (mask >> r) | (mask << (e - r));
3475         mask &= bitmask64(e);
3476     }
3477     /* ...then replicate the element over the whole 64 bit value */
3478     mask = bitfield_replicate(mask, e);
3479     *result = mask;
3480     return true;
3481 }
3482
3483 /* Logical (immediate)
3484  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
3485  * +----+-----+-------------+---+------+------+------+------+
3486  * | sf | opc | 1 0 0 1 0 0 | N | immr | imms |  Rn  |  Rd  |
3487  * +----+-----+-------------+---+------+------+------+------+
3488  */
3489 static void disas_logic_imm(DisasContext *s, uint32_t insn)
3490 {
3491     unsigned int sf, opc, is_n, immr, imms, rn, rd;
3492     TCGv_i64 tcg_rd, tcg_rn;
3493     uint64_t wmask;
3494     bool is_and = false;
3495
3496     sf = extract32(insn, 31, 1);
3497     opc = extract32(insn, 29, 2);
3498     is_n = extract32(insn, 22, 1);
3499     immr = extract32(insn, 16, 6);
3500     imms = extract32(insn, 10, 6);
3501     rn = extract32(insn, 5, 5);
3502     rd = extract32(insn, 0, 5);
3503
3504     if (!sf && is_n) {
3505         unallocated_encoding(s);
3506         return;
3507     }
3508
3509     if (opc == 0x3) { /* ANDS */
3510         tcg_rd = cpu_reg(s, rd);
3511     } else {
3512         tcg_rd = cpu_reg_sp(s, rd);
3513     }
3514     tcg_rn = cpu_reg(s, rn);
3515
3516     if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
3517         /* some immediate field values are reserved */
3518         unallocated_encoding(s);
3519         return;
3520     }
3521
3522     if (!sf) {
3523         wmask &= 0xffffffff;
3524     }
3525
3526     switch (opc) {
3527     case 0x3: /* ANDS */
3528     case 0x0: /* AND */
3529         tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
3530         is_and = true;
3531         break;
3532     case 0x1: /* ORR */
3533         tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
3534         break;
3535     case 0x2: /* EOR */
3536         tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
3537         break;
3538     default:
3539         assert(FALSE); /* must handle all above */
3540         break;
3541     }
3542
3543     if (!sf && !is_and) {
3544         /* zero extend final result; we know we can skip this for AND
3545          * since the immediate had the high 32 bits clear.
3546          */
3547         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3548     }
3549
3550     if (opc == 3) { /* ANDS */
3551         gen_logic_CC(sf, tcg_rd);
3552     }
3553 }
3554
3555 /*
3556  * Move wide (immediate)
3557  *
3558  *  31 30 29 28         23 22 21 20             5 4    0
3559  * +--+-----+-------------+-----+----------------+------+
3560  * |sf| opc | 1 0 0 1 0 1 |  hw |  imm16         |  Rd  |
3561  * +--+-----+-------------+-----+----------------+------+
3562  *
3563  * sf: 0 -> 32 bit, 1 -> 64 bit
3564  * opc: 00 -> N, 10 -> Z, 11 -> K
3565  * hw: shift/16 (0,16, and sf only 32, 48)
3566  */
3567 static void disas_movw_imm(DisasContext *s, uint32_t insn)
3568 {
3569     int rd = extract32(insn, 0, 5);
3570     uint64_t imm = extract32(insn, 5, 16);
3571     int sf = extract32(insn, 31, 1);
3572     int opc = extract32(insn, 29, 2);
3573     int pos = extract32(insn, 21, 2) << 4;
3574     TCGv_i64 tcg_rd = cpu_reg(s, rd);
3575     TCGv_i64 tcg_imm;
3576
3577     if (!sf && (pos >= 32)) {
3578         unallocated_encoding(s);
3579         return;
3580     }
3581
3582     switch (opc) {
3583     case 0: /* MOVN */
3584     case 2: /* MOVZ */
3585         imm <<= pos;
3586         if (opc == 0) {
3587             imm = ~imm;
3588         }
3589         if (!sf) {
3590             imm &= 0xffffffffu;
3591         }
3592         tcg_gen_movi_i64(tcg_rd, imm);
3593         break;
3594     case 3: /* MOVK */
3595         tcg_imm = tcg_const_i64(imm);
3596         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_imm, pos, 16);
3597         tcg_temp_free_i64(tcg_imm);
3598         if (!sf) {
3599             tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3600         }
3601         break;
3602     default:
3603         unallocated_encoding(s);
3604         break;
3605     }
3606 }
3607
3608 /* Bitfield
3609  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
3610  * +----+-----+-------------+---+------+------+------+------+
3611  * | sf | opc | 1 0 0 1 1 0 | N | immr | imms |  Rn  |  Rd  |
3612  * +----+-----+-------------+---+------+------+------+------+
3613  */
3614 static void disas_bitfield(DisasContext *s, uint32_t insn)
3615 {
3616     unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
3617     TCGv_i64 tcg_rd, tcg_tmp;
3618
3619     sf = extract32(insn, 31, 1);
3620     opc = extract32(insn, 29, 2);
3621     n = extract32(insn, 22, 1);
3622     ri = extract32(insn, 16, 6);
3623     si = extract32(insn, 10, 6);
3624     rn = extract32(insn, 5, 5);
3625     rd = extract32(insn, 0, 5);
3626     bitsize = sf ? 64 : 32;
3627
3628     if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
3629         unallocated_encoding(s);
3630         return;
3631     }
3632
3633     tcg_rd = cpu_reg(s, rd);
3634
3635     /* Suppress the zero-extend for !sf.  Since RI and SI are constrained
3636        to be smaller than bitsize, we'll never reference data outside the
3637        low 32-bits anyway.  */
3638     tcg_tmp = read_cpu_reg(s, rn, 1);
3639
3640     /* Recognize simple(r) extractions.  */
3641     if (si >= ri) {
3642         /* Wd<s-r:0> = Wn<s:r> */
3643         len = (si - ri) + 1;
3644         if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
3645             tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
3646             goto done;
3647         } else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */
3648             tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
3649             return;
3650         }
3651         /* opc == 1, BXFIL fall through to deposit */
3652         tcg_gen_extract_i64(tcg_tmp, tcg_tmp, ri, len);
3653         pos = 0;
3654     } else {
3655         /* Handle the ri > si case with a deposit
3656          * Wd<32+s-r,32-r> = Wn<s:0>
3657          */
3658         len = si + 1;
3659         pos = (bitsize - ri) & (bitsize - 1);
3660     }
3661
3662     if (opc == 0 && len < ri) {
3663         /* SBFM: sign extend the destination field from len to fill
3664            the balance of the word.  Let the deposit below insert all
3665            of those sign bits.  */
3666         tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
3667         len = ri;
3668     }
3669
3670     if (opc == 1) { /* BFM, BXFIL */
3671         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
3672     } else {
3673         /* SBFM or UBFM: We start with zero, and we haven't modified
3674            any bits outside bitsize, therefore the zero-extension
3675            below is unneeded.  */
3676         tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
3677         return;
3678     }
3679
3680  done:
3681     if (!sf) { /* zero extend final result */
3682         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3683     }
3684 }
3685
3686 /* Extract
3687  *   31  30  29 28         23 22   21  20  16 15    10 9    5 4    0
3688  * +----+------+-------------+---+----+------+--------+------+------+
3689  * | sf | op21 | 1 0 0 1 1 1 | N | o0 |  Rm  |  imms  |  Rn  |  Rd  |
3690  * +----+------+-------------+---+----+------+--------+------+------+
3691  */
3692 static void disas_extract(DisasContext *s, uint32_t insn)
3693 {
3694     unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
3695
3696     sf = extract32(insn, 31, 1);
3697     n = extract32(insn, 22, 1);
3698     rm = extract32(insn, 16, 5);
3699     imm = extract32(insn, 10, 6);
3700     rn = extract32(insn, 5, 5);
3701     rd = extract32(insn, 0, 5);
3702     op21 = extract32(insn, 29, 2);
3703     op0 = extract32(insn, 21, 1);
3704     bitsize = sf ? 64 : 32;
3705
3706     if (sf != n || op21 || op0 || imm >= bitsize) {
3707         unallocated_encoding(s);
3708     } else {
3709         TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
3710
3711         tcg_rd = cpu_reg(s, rd);
3712
3713         if (unlikely(imm == 0)) {
3714             /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
3715              * so an extract from bit 0 is a special case.
3716              */
3717             if (sf) {
3718                 tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
3719             } else {
3720                 tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
3721             }
3722         } else if (rm == rn) { /* ROR */
3723             tcg_rm = cpu_reg(s, rm);
3724             if (sf) {
3725                 tcg_gen_rotri_i64(tcg_rd, tcg_rm, imm);
3726             } else {
3727                 TCGv_i32 tmp = tcg_temp_new_i32();
3728                 tcg_gen_extrl_i64_i32(tmp, tcg_rm);
3729                 tcg_gen_rotri_i32(tmp, tmp, imm);
3730                 tcg_gen_extu_i32_i64(tcg_rd, tmp);
3731                 tcg_temp_free_i32(tmp);
3732             }
3733         } else {
3734             tcg_rm = read_cpu_reg(s, rm, sf);
3735             tcg_rn = read_cpu_reg(s, rn, sf);
3736             tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
3737             tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
3738             tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
3739             if (!sf) {
3740                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3741             }
3742         }
3743     }
3744 }
3745
3746 /* Data processing - immediate */
3747 static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
3748 {
3749     switch (extract32(insn, 23, 6)) {
3750     case 0x20: case 0x21: /* PC-rel. addressing */
3751         disas_pc_rel_adr(s, insn);
3752         break;
3753     case 0x22: case 0x23: /* Add/subtract (immediate) */
3754         disas_add_sub_imm(s, insn);
3755         break;
3756     case 0x24: /* Logical (immediate) */
3757         disas_logic_imm(s, insn);
3758         break;
3759     case 0x25: /* Move wide (immediate) */
3760         disas_movw_imm(s, insn);
3761         break;
3762     case 0x26: /* Bitfield */
3763         disas_bitfield(s, insn);
3764         break;
3765     case 0x27: /* Extract */
3766         disas_extract(s, insn);
3767         break;
3768     default:
3769         unallocated_encoding(s);
3770         break;
3771     }
3772 }
3773
3774 /* Shift a TCGv src by TCGv shift_amount, put result in dst.
3775  * Note that it is the caller's responsibility to ensure that the
3776  * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
3777  * mandated semantics for out of range shifts.
3778  */
3779 static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
3780                       enum a64_shift_type shift_type, TCGv_i64 shift_amount)
3781 {
3782     switch (shift_type) {
3783     case A64_SHIFT_TYPE_LSL:
3784         tcg_gen_shl_i64(dst, src, shift_amount);
3785         break;
3786     case A64_SHIFT_TYPE_LSR:
3787         tcg_gen_shr_i64(dst, src, shift_amount);
3788         break;
3789     case A64_SHIFT_TYPE_ASR:
3790         if (!sf) {
3791             tcg_gen_ext32s_i64(dst, src);
3792         }
3793         tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
3794         break;
3795     case A64_SHIFT_TYPE_ROR:
3796         if (sf) {
3797             tcg_gen_rotr_i64(dst, src, shift_amount);
3798         } else {
3799             TCGv_i32 t0, t1;
3800             t0 = tcg_temp_new_i32();
3801             t1 = tcg_temp_new_i32();
3802             tcg_gen_extrl_i64_i32(t0, src);
3803             tcg_gen_extrl_i64_i32(t1, shift_amount);
3804             tcg_gen_rotr_i32(t0, t0, t1);
3805             tcg_gen_extu_i32_i64(dst, t0);
3806             tcg_temp_free_i32(t0);
3807             tcg_temp_free_i32(t1);
3808         }
3809         break;
3810     default:
3811         assert(FALSE); /* all shift types should be handled */
3812         break;
3813     }
3814
3815     if (!sf) { /* zero extend final result */
3816         tcg_gen_ext32u_i64(dst, dst);
3817     }
3818 }
3819
3820 /* Shift a TCGv src by immediate, put result in dst.
3821  * The shift amount must be in range (this should always be true as the
3822  * relevant instructions will UNDEF on bad shift immediates).
3823  */
3824 static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
3825                           enum a64_shift_type shift_type, unsigned int shift_i)
3826 {
3827     assert(shift_i < (sf ? 64 : 32));
3828
3829     if (shift_i == 0) {
3830         tcg_gen_mov_i64(dst, src);
3831     } else {
3832         TCGv_i64 shift_const;
3833
3834         shift_const = tcg_const_i64(shift_i);
3835         shift_reg(dst, src, sf, shift_type, shift_const);
3836         tcg_temp_free_i64(shift_const);
3837     }
3838 }
3839
3840 /* Logical (shifted register)
3841  *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
3842  * +----+-----+-----------+-------+---+------+--------+------+------+
3843  * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
3844  * +----+-----+-----------+-------+---+------+--------+------+------+
3845  */
3846 static void disas_logic_reg(DisasContext *s, uint32_t insn)
3847 {
3848     TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
3849     unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
3850
3851     sf = extract32(insn, 31, 1);
3852     opc = extract32(insn, 29, 2);
3853     shift_type = extract32(insn, 22, 2);
3854     invert = extract32(insn, 21, 1);
3855     rm = extract32(insn, 16, 5);
3856     shift_amount = extract32(insn, 10, 6);
3857     rn = extract32(insn, 5, 5);
3858     rd = extract32(insn, 0, 5);
3859
3860     if (!sf && (shift_amount & (1 << 5))) {
3861         unallocated_encoding(s);
3862         return;
3863     }
3864
3865     tcg_rd = cpu_reg(s, rd);
3866
3867     if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
3868         /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
3869          * register-register MOV and MVN, so it is worth special casing.
3870          */
3871         tcg_rm = cpu_reg(s, rm);
3872         if (invert) {
3873             tcg_gen_not_i64(tcg_rd, tcg_rm);
3874             if (!sf) {
3875                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3876             }
3877         } else {
3878             if (sf) {
3879                 tcg_gen_mov_i64(tcg_rd, tcg_rm);
3880             } else {
3881                 tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
3882             }
3883         }
3884         return;
3885     }
3886
3887     tcg_rm = read_cpu_reg(s, rm, sf);
3888
3889     if (shift_amount) {
3890         shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
3891     }
3892
3893     tcg_rn = cpu_reg(s, rn);
3894
3895     switch (opc | (invert << 2)) {
3896     case 0: /* AND */
3897     case 3: /* ANDS */
3898         tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
3899         break;
3900     case 1: /* ORR */
3901         tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
3902         break;
3903     case 2: /* EOR */
3904         tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
3905         break;
3906     case 4: /* BIC */
3907     case 7: /* BICS */
3908         tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
3909         break;
3910     case 5: /* ORN */
3911         tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
3912         break;
3913     case 6: /* EON */
3914         tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
3915         break;
3916     default:
3917         assert(FALSE);
3918         break;
3919     }
3920
3921     if (!sf) {
3922         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3923     }
3924
3925     if (opc == 3) {
3926         gen_logic_CC(sf, tcg_rd);
3927     }
3928 }
3929
3930 /*
3931  * Add/subtract (extended register)
3932  *
3933  *  31|30|29|28       24|23 22|21|20   16|15  13|12  10|9  5|4  0|
3934  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
3935  * |sf|op| S| 0 1 0 1 1 | opt | 1|  Rm   |option| imm3 | Rn | Rd |
3936  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
3937  *
3938  *  sf: 0 -> 32bit, 1 -> 64bit
3939  *  op: 0 -> add  , 1 -> sub
3940  *   S: 1 -> set flags
3941  * opt: 00
3942  * option: extension type (see DecodeRegExtend)
3943  * imm3: optional shift to Rm
3944  *
3945  * Rd = Rn + LSL(extend(Rm), amount)
3946  */
3947 static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
3948 {
3949     int rd = extract32(insn, 0, 5);
3950     int rn = extract32(insn, 5, 5);
3951     int imm3 = extract32(insn, 10, 3);
3952     int option = extract32(insn, 13, 3);
3953     int rm = extract32(insn, 16, 5);
3954     bool setflags = extract32(insn, 29, 1);
3955     bool sub_op = extract32(insn, 30, 1);
3956     bool sf = extract32(insn, 31, 1);
3957
3958     TCGv_i64 tcg_rm, tcg_rn; /* temps */
3959     TCGv_i64 tcg_rd;
3960     TCGv_i64 tcg_result;
3961
3962     if (imm3 > 4) {
3963         unallocated_encoding(s);
3964         return;
3965     }
3966
3967     /* non-flag setting ops may use SP */
3968     if (!setflags) {
3969         tcg_rd = cpu_reg_sp(s, rd);
3970     } else {
3971         tcg_rd = cpu_reg(s, rd);
3972     }
3973     tcg_rn = read_cpu_reg_sp(s, rn, sf);
3974
3975     tcg_rm = read_cpu_reg(s, rm, sf);
3976     ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
3977
3978     tcg_result = tcg_temp_new_i64();
3979
3980     if (!setflags) {
3981         if (sub_op) {
3982             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
3983         } else {
3984             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
3985         }
3986     } else {
3987         if (sub_op) {
3988             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
3989         } else {
3990             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
3991         }
3992     }
3993
3994     if (sf) {
3995         tcg_gen_mov_i64(tcg_rd, tcg_result);
3996     } else {
3997         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
3998     }
3999
4000     tcg_temp_free_i64(tcg_result);
4001 }
4002
4003 /*
4004  * Add/subtract (shifted register)
4005  *
4006  *  31 30 29 28       24 23 22 21 20   16 15     10 9    5 4    0
4007  * +--+--+--+-----------+-----+--+-------+---------+------+------+
4008  * |sf|op| S| 0 1 0 1 1 |shift| 0|  Rm   |  imm6   |  Rn  |  Rd  |
4009  * +--+--+--+-----------+-----+--+-------+---------+------+------+
4010  *
4011  *    sf: 0 -> 32bit, 1 -> 64bit
4012  *    op: 0 -> add  , 1 -> sub
4013  *     S: 1 -> set flags
4014  * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
4015  *  imm6: Shift amount to apply to Rm before the add/sub
4016  */
4017 static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
4018 {
4019     int rd = extract32(insn, 0, 5);
4020     int rn = extract32(insn, 5, 5);
4021     int imm6 = extract32(insn, 10, 6);
4022     int rm = extract32(insn, 16, 5);
4023     int shift_type = extract32(insn, 22, 2);
4024     bool setflags = extract32(insn, 29, 1);
4025     bool sub_op = extract32(insn, 30, 1);
4026     bool sf = extract32(insn, 31, 1);
4027
4028     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4029     TCGv_i64 tcg_rn, tcg_rm;
4030     TCGv_i64 tcg_result;
4031
4032     if ((shift_type == 3) || (!sf && (imm6 > 31))) {
4033         unallocated_encoding(s);
4034         return;
4035     }
4036
4037     tcg_rn = read_cpu_reg(s, rn, sf);
4038     tcg_rm = read_cpu_reg(s, rm, sf);
4039
4040     shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
4041
4042     tcg_result = tcg_temp_new_i64();
4043
4044     if (!setflags) {
4045         if (sub_op) {
4046             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
4047         } else {
4048             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
4049         }
4050     } else {
4051         if (sub_op) {
4052             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
4053         } else {
4054             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
4055         }
4056     }
4057
4058     if (sf) {
4059         tcg_gen_mov_i64(tcg_rd, tcg_result);
4060     } else {
4061         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
4062     }
4063
4064     tcg_temp_free_i64(tcg_result);
4065 }
4066
4067 /* Data-processing (3 source)
4068  *
4069  *    31 30  29 28       24 23 21  20  16  15  14  10 9    5 4    0
4070  *  +--+------+-----------+------+------+----+------+------+------+
4071  *  |sf| op54 | 1 1 0 1 1 | op31 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
4072  *  +--+------+-----------+------+------+----+------+------+------+
4073  */
4074 static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
4075 {
4076     int rd = extract32(insn, 0, 5);
4077     int rn = extract32(insn, 5, 5);
4078     int ra = extract32(insn, 10, 5);
4079     int rm = extract32(insn, 16, 5);
4080     int op_id = (extract32(insn, 29, 3) << 4) |
4081         (extract32(insn, 21, 3) << 1) |
4082         extract32(insn, 15, 1);
4083     bool sf = extract32(insn, 31, 1);
4084     bool is_sub = extract32(op_id, 0, 1);
4085     bool is_high = extract32(op_id, 2, 1);
4086     bool is_signed = false;
4087     TCGv_i64 tcg_op1;
4088     TCGv_i64 tcg_op2;
4089     TCGv_i64 tcg_tmp;
4090
4091     /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
4092     switch (op_id) {
4093     case 0x42: /* SMADDL */
4094     case 0x43: /* SMSUBL */
4095     case 0x44: /* SMULH */
4096         is_signed = true;
4097         break;
4098     case 0x0: /* MADD (32bit) */
4099     case 0x1: /* MSUB (32bit) */
4100     case 0x40: /* MADD (64bit) */
4101     case 0x41: /* MSUB (64bit) */
4102     case 0x4a: /* UMADDL */
4103     case 0x4b: /* UMSUBL */
4104     case 0x4c: /* UMULH */
4105         break;
4106     default:
4107         unallocated_encoding(s);
4108         return;
4109     }
4110
4111     if (is_high) {
4112         TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
4113         TCGv_i64 tcg_rd = cpu_reg(s, rd);
4114         TCGv_i64 tcg_rn = cpu_reg(s, rn);
4115         TCGv_i64 tcg_rm = cpu_reg(s, rm);
4116
4117         if (is_signed) {
4118             tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
4119         } else {
4120             tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
4121         }
4122
4123         tcg_temp_free_i64(low_bits);
4124         return;
4125     }
4126
4127     tcg_op1 = tcg_temp_new_i64();
4128     tcg_op2 = tcg_temp_new_i64();
4129     tcg_tmp = tcg_temp_new_i64();
4130
4131     if (op_id < 0x42) {
4132         tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
4133         tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
4134     } else {
4135         if (is_signed) {
4136             tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
4137             tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
4138         } else {
4139             tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
4140             tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
4141         }
4142     }
4143
4144     if (ra == 31 && !is_sub) {
4145         /* Special-case MADD with rA == XZR; it is the standard MUL alias */
4146         tcg_gen_mul_i64(cpu_reg(s, rd), tcg_op1, tcg_op2);
4147     } else {
4148         tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
4149         if (is_sub) {
4150             tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
4151         } else {
4152             tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
4153         }
4154     }
4155
4156     if (!sf) {
4157         tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
4158     }
4159
4160     tcg_temp_free_i64(tcg_op1);
4161     tcg_temp_free_i64(tcg_op2);
4162     tcg_temp_free_i64(tcg_tmp);
4163 }
4164
4165 /* Add/subtract (with carry)
4166  *  31 30 29 28 27 26 25 24 23 22 21  20  16  15   10  9    5 4   0
4167  * +--+--+--+------------------------+------+---------+------+-----+
4168  * |sf|op| S| 1  1  0  1  0  0  0  0 |  rm  | opcode2 |  Rn  |  Rd |
4169  * +--+--+--+------------------------+------+---------+------+-----+
4170  *                                            [000000]
4171  */
4172
4173 static void disas_adc_sbc(DisasContext *s, uint32_t insn)
4174 {
4175     unsigned int sf, op, setflags, rm, rn, rd;
4176     TCGv_i64 tcg_y, tcg_rn, tcg_rd;
4177
4178     if (extract32(insn, 10, 6) != 0) {
4179         unallocated_encoding(s);
4180         return;
4181     }
4182
4183     sf = extract32(insn, 31, 1);
4184     op = extract32(insn, 30, 1);
4185     setflags = extract32(insn, 29, 1);
4186     rm = extract32(insn, 16, 5);
4187     rn = extract32(insn, 5, 5);
4188     rd = extract32(insn, 0, 5);
4189
4190     tcg_rd = cpu_reg(s, rd);
4191     tcg_rn = cpu_reg(s, rn);
4192
4193     if (op) {
4194         tcg_y = new_tmp_a64(s);
4195         tcg_gen_not_i64(tcg_y, cpu_reg(s, rm));
4196     } else {
4197         tcg_y = cpu_reg(s, rm);
4198     }
4199
4200     if (setflags) {
4201         gen_adc_CC(sf, tcg_rd, tcg_rn, tcg_y);
4202     } else {
4203         gen_adc(sf, tcg_rd, tcg_rn, tcg_y);
4204     }
4205 }
4206
4207 /* Conditional compare (immediate / register)
4208  *  31 30 29 28 27 26 25 24 23 22 21  20    16 15  12  11  10  9   5  4 3   0
4209  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
4210  * |sf|op| S| 1  1  0  1  0  0  1  0 |imm5/rm | cond |i/r |o2|  Rn  |o3|nzcv |
4211  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
4212  *        [1]                             y                [0]       [0]
4213  */
4214 static void disas_cc(DisasContext *s, uint32_t insn)
4215 {
4216     unsigned int sf, op, y, cond, rn, nzcv, is_imm;
4217     TCGv_i32 tcg_t0, tcg_t1, tcg_t2;
4218     TCGv_i64 tcg_tmp, tcg_y, tcg_rn;
4219     DisasCompare c;
4220
4221     if (!extract32(insn, 29, 1)) {
4222         unallocated_encoding(s);
4223         return;
4224     }
4225     if (insn & (1 << 10 | 1 << 4)) {
4226         unallocated_encoding(s);
4227         return;
4228     }
4229     sf = extract32(insn, 31, 1);
4230     op = extract32(insn, 30, 1);
4231     is_imm = extract32(insn, 11, 1);
4232     y = extract32(insn, 16, 5); /* y = rm (reg) or imm5 (imm) */
4233     cond = extract32(insn, 12, 4);
4234     rn = extract32(insn, 5, 5);
4235     nzcv = extract32(insn, 0, 4);
4236
4237     /* Set T0 = !COND.  */
4238     tcg_t0 = tcg_temp_new_i32();
4239     arm_test_cc(&c, cond);
4240     tcg_gen_setcondi_i32(tcg_invert_cond(c.cond), tcg_t0, c.value, 0);
4241     arm_free_cc(&c);
4242
4243     /* Load the arguments for the new comparison.  */
4244     if (is_imm) {
4245         tcg_y = new_tmp_a64(s);
4246         tcg_gen_movi_i64(tcg_y, y);
4247     } else {
4248         tcg_y = cpu_reg(s, y);
4249     }
4250     tcg_rn = cpu_reg(s, rn);
4251
4252     /* Set the flags for the new comparison.  */
4253     tcg_tmp = tcg_temp_new_i64();
4254     if (op) {
4255         gen_sub_CC(sf, tcg_tmp, tcg_rn, tcg_y);
4256     } else {
4257         gen_add_CC(sf, tcg_tmp, tcg_rn, tcg_y);
4258     }
4259     tcg_temp_free_i64(tcg_tmp);
4260
4261     /* If COND was false, force the flags to #nzcv.  Compute two masks
4262      * to help with this: T1 = (COND ? 0 : -1), T2 = (COND ? -1 : 0).
4263      * For tcg hosts that support ANDC, we can make do with just T1.
4264      * In either case, allow the tcg optimizer to delete any unused mask.
4265      */
4266     tcg_t1 = tcg_temp_new_i32();
4267     tcg_t2 = tcg_temp_new_i32();
4268     tcg_gen_neg_i32(tcg_t1, tcg_t0);
4269     tcg_gen_subi_i32(tcg_t2, tcg_t0, 1);
4270
4271     if (nzcv & 8) { /* N */
4272         tcg_gen_or_i32(cpu_NF, cpu_NF, tcg_t1);
4273     } else {
4274         if (TCG_TARGET_HAS_andc_i32) {
4275             tcg_gen_andc_i32(cpu_NF, cpu_NF, tcg_t1);
4276         } else {
4277             tcg_gen_and_i32(cpu_NF, cpu_NF, tcg_t2);
4278         }
4279     }
4280     if (nzcv & 4) { /* Z */
4281         if (TCG_TARGET_HAS_andc_i32) {
4282             tcg_gen_andc_i32(cpu_ZF, cpu_ZF, tcg_t1);
4283         } else {
4284             tcg_gen_and_i32(cpu_ZF, cpu_ZF, tcg_t2);
4285         }
4286     } else {
4287         tcg_gen_or_i32(cpu_ZF, cpu_ZF, tcg_t0);
4288     }
4289     if (nzcv & 2) { /* C */
4290         tcg_gen_or_i32(cpu_CF, cpu_CF, tcg_t0);
4291     } else {
4292         if (TCG_TARGET_HAS_andc_i32) {
4293             tcg_gen_andc_i32(cpu_CF, cpu_CF, tcg_t1);
4294         } else {
4295             tcg_gen_and_i32(cpu_CF, cpu_CF, tcg_t2);
4296         }
4297     }
4298     if (nzcv & 1) { /* V */
4299         tcg_gen_or_i32(cpu_VF, cpu_VF, tcg_t1);
4300     } else {
4301         if (TCG_TARGET_HAS_andc_i32) {
4302             tcg_gen_andc_i32(cpu_VF, cpu_VF, tcg_t1);
4303         } else {
4304             tcg_gen_and_i32(cpu_VF, cpu_VF, tcg_t2);
4305         }
4306     }
4307     tcg_temp_free_i32(tcg_t0);
4308     tcg_temp_free_i32(tcg_t1);
4309     tcg_temp_free_i32(tcg_t2);
4310 }
4311
4312 /* Conditional select
4313  *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
4314  * +----+----+---+-----------------+------+------+-----+------+------+
4315  * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
4316  * +----+----+---+-----------------+------+------+-----+------+------+
4317  */
4318 static void disas_cond_select(DisasContext *s, uint32_t insn)
4319 {
4320     unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
4321     TCGv_i64 tcg_rd, zero;
4322     DisasCompare64 c;
4323
4324     if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
4325         /* S == 1 or op2<1> == 1 */
4326         unallocated_encoding(s);
4327         return;
4328     }
4329     sf = extract32(insn, 31, 1);
4330     else_inv = extract32(insn, 30, 1);
4331     rm = extract32(insn, 16, 5);
4332     cond = extract32(insn, 12, 4);
4333     else_inc = extract32(insn, 10, 1);
4334     rn = extract32(insn, 5, 5);
4335     rd = extract32(insn, 0, 5);
4336
4337     tcg_rd = cpu_reg(s, rd);
4338
4339     a64_test_cc(&c, cond);
4340     zero = tcg_const_i64(0);
4341
4342     if (rn == 31 && rm == 31 && (else_inc ^ else_inv)) {
4343         /* CSET & CSETM.  */
4344         tcg_gen_setcond_i64(tcg_invert_cond(c.cond), tcg_rd, c.value, zero);
4345         if (else_inv) {
4346             tcg_gen_neg_i64(tcg_rd, tcg_rd);
4347         }
4348     } else {
4349         TCGv_i64 t_true = cpu_reg(s, rn);
4350         TCGv_i64 t_false = read_cpu_reg(s, rm, 1);
4351         if (else_inv && else_inc) {
4352             tcg_gen_neg_i64(t_false, t_false);
4353         } else if (else_inv) {
4354             tcg_gen_not_i64(t_false, t_false);
4355         } else if (else_inc) {
4356             tcg_gen_addi_i64(t_false, t_false, 1);
4357         }
4358         tcg_gen_movcond_i64(c.cond, tcg_rd, c.value, zero, t_true, t_false);
4359     }
4360
4361     tcg_temp_free_i64(zero);
4362     a64_free_cc(&c);
4363
4364     if (!sf) {
4365         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4366     }
4367 }
4368
4369 static void handle_clz(DisasContext *s, unsigned int sf,
4370                        unsigned int rn, unsigned int rd)
4371 {
4372     TCGv_i64 tcg_rd, tcg_rn;
4373     tcg_rd = cpu_reg(s, rd);
4374     tcg_rn = cpu_reg(s, rn);
4375
4376     if (sf) {
4377         tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
4378     } else {
4379         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4380         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4381         tcg_gen_clzi_i32(tcg_tmp32, tcg_tmp32, 32);
4382         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4383         tcg_temp_free_i32(tcg_tmp32);
4384     }
4385 }
4386
4387 static void handle_cls(DisasContext *s, unsigned int sf,
4388                        unsigned int rn, unsigned int rd)
4389 {
4390     TCGv_i64 tcg_rd, tcg_rn;
4391     tcg_rd = cpu_reg(s, rd);
4392     tcg_rn = cpu_reg(s, rn);
4393
4394     if (sf) {
4395         tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
4396     } else {
4397         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4398         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4399         tcg_gen_clrsb_i32(tcg_tmp32, tcg_tmp32);
4400         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4401         tcg_temp_free_i32(tcg_tmp32);
4402     }
4403 }
4404
4405 static void handle_rbit(DisasContext *s, unsigned int sf,
4406                         unsigned int rn, unsigned int rd)
4407 {
4408     TCGv_i64 tcg_rd, tcg_rn;
4409     tcg_rd = cpu_reg(s, rd);
4410     tcg_rn = cpu_reg(s, rn);
4411
4412     if (sf) {
4413         gen_helper_rbit64(tcg_rd, tcg_rn);
4414     } else {
4415         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4416         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4417         gen_helper_rbit(tcg_tmp32, tcg_tmp32);
4418         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4419         tcg_temp_free_i32(tcg_tmp32);
4420     }
4421 }
4422
4423 /* REV with sf==1, opcode==3 ("REV64") */
4424 static void handle_rev64(DisasContext *s, unsigned int sf,
4425                          unsigned int rn, unsigned int rd)
4426 {
4427     if (!sf) {
4428         unallocated_encoding(s);
4429         return;
4430     }
4431     tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
4432 }
4433
4434 /* REV with sf==0, opcode==2
4435  * REV32 (sf==1, opcode==2)
4436  */
4437 static void handle_rev32(DisasContext *s, unsigned int sf,
4438                          unsigned int rn, unsigned int rd)
4439 {
4440     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4441
4442     if (sf) {
4443         TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4444         TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
4445
4446         /* bswap32_i64 requires zero high word */
4447         tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
4448         tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
4449         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
4450         tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
4451         tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
4452
4453         tcg_temp_free_i64(tcg_tmp);
4454     } else {
4455         tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
4456         tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
4457     }
4458 }
4459
4460 /* REV16 (opcode==1) */
4461 static void handle_rev16(DisasContext *s, unsigned int sf,
4462                          unsigned int rn, unsigned int rd)
4463 {
4464     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4465     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4466     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
4467     TCGv_i64 mask = tcg_const_i64(sf ? 0x00ff00ff00ff00ffull : 0x00ff00ff);
4468
4469     tcg_gen_shri_i64(tcg_tmp, tcg_rn, 8);
4470     tcg_gen_and_i64(tcg_rd, tcg_rn, mask);
4471     tcg_gen_and_i64(tcg_tmp, tcg_tmp, mask);
4472     tcg_gen_shli_i64(tcg_rd, tcg_rd, 8);
4473     tcg_gen_or_i64(tcg_rd, tcg_rd, tcg_tmp);
4474
4475     tcg_temp_free_i64(mask);
4476     tcg_temp_free_i64(tcg_tmp);
4477 }
4478
4479 /* Data-processing (1 source)
4480  *   31  30  29  28             21 20     16 15    10 9    5 4    0
4481  * +----+---+---+-----------------+---------+--------+------+------+
4482  * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
4483  * +----+---+---+-----------------+---------+--------+------+------+
4484  */
4485 static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
4486 {
4487     unsigned int sf, opcode, rn, rd;
4488
4489     if (extract32(insn, 29, 1) || extract32(insn, 16, 5)) {
4490         unallocated_encoding(s);
4491         return;
4492     }
4493
4494     sf = extract32(insn, 31, 1);
4495     opcode = extract32(insn, 10, 6);
4496     rn = extract32(insn, 5, 5);
4497     rd = extract32(insn, 0, 5);
4498
4499     switch (opcode) {
4500     case 0: /* RBIT */
4501         handle_rbit(s, sf, rn, rd);
4502         break;
4503     case 1: /* REV16 */
4504         handle_rev16(s, sf, rn, rd);
4505         break;
4506     case 2: /* REV32 */
4507         handle_rev32(s, sf, rn, rd);
4508         break;
4509     case 3: /* REV64 */
4510         handle_rev64(s, sf, rn, rd);
4511         break;
4512     case 4: /* CLZ */
4513         handle_clz(s, sf, rn, rd);
4514         break;
4515     case 5: /* CLS */
4516         handle_cls(s, sf, rn, rd);
4517         break;
4518     }
4519 }
4520
4521 static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
4522                        unsigned int rm, unsigned int rn, unsigned int rd)
4523 {
4524     TCGv_i64 tcg_n, tcg_m, tcg_rd;
4525     tcg_rd = cpu_reg(s, rd);
4526
4527     if (!sf && is_signed) {
4528         tcg_n = new_tmp_a64(s);
4529         tcg_m = new_tmp_a64(s);
4530         tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
4531         tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
4532     } else {
4533         tcg_n = read_cpu_reg(s, rn, sf);
4534         tcg_m = read_cpu_reg(s, rm, sf);
4535     }
4536
4537     if (is_signed) {
4538         gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
4539     } else {
4540         gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
4541     }
4542
4543     if (!sf) { /* zero extend final result */
4544         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4545     }
4546 }
4547
4548 /* LSLV, LSRV, ASRV, RORV */
4549 static void handle_shift_reg(DisasContext *s,
4550                              enum a64_shift_type shift_type, unsigned int sf,
4551                              unsigned int rm, unsigned int rn, unsigned int rd)
4552 {
4553     TCGv_i64 tcg_shift = tcg_temp_new_i64();
4554     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4555     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
4556
4557     tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
4558     shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
4559     tcg_temp_free_i64(tcg_shift);
4560 }
4561
4562 /* CRC32[BHWX], CRC32C[BHWX] */
4563 static void handle_crc32(DisasContext *s,
4564                          unsigned int sf, unsigned int sz, bool crc32c,
4565                          unsigned int rm, unsigned int rn, unsigned int rd)
4566 {
4567     TCGv_i64 tcg_acc, tcg_val;
4568     TCGv_i32 tcg_bytes;
4569
4570     if (!arm_dc_feature(s, ARM_FEATURE_CRC)
4571         || (sf == 1 && sz != 3)
4572         || (sf == 0 && sz == 3)) {
4573         unallocated_encoding(s);
4574         return;
4575     }
4576
4577     if (sz == 3) {
4578         tcg_val = cpu_reg(s, rm);
4579     } else {
4580         uint64_t mask;
4581         switch (sz) {
4582         case 0:
4583             mask = 0xFF;
4584             break;
4585         case 1:
4586             mask = 0xFFFF;
4587             break;
4588         case 2:
4589             mask = 0xFFFFFFFF;
4590             break;
4591         default:
4592             g_assert_not_reached();
4593         }
4594         tcg_val = new_tmp_a64(s);
4595         tcg_gen_andi_i64(tcg_val, cpu_reg(s, rm), mask);
4596     }
4597
4598     tcg_acc = cpu_reg(s, rn);
4599     tcg_bytes = tcg_const_i32(1 << sz);
4600
4601     if (crc32c) {
4602         gen_helper_crc32c_64(cpu_reg(s, rd), tcg_acc, tcg_val, tcg_bytes);
4603     } else {
4604         gen_helper_crc32_64(cpu_reg(s, rd), tcg_acc, tcg_val, tcg_bytes);
4605     }
4606
4607     tcg_temp_free_i32(tcg_bytes);
4608 }
4609
4610 /* Data-processing (2 source)
4611  *   31   30  29 28             21 20  16 15    10 9    5 4    0
4612  * +----+---+---+-----------------+------+--------+------+------+
4613  * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
4614  * +----+---+---+-----------------+------+--------+------+------+
4615  */
4616 static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
4617 {
4618     unsigned int sf, rm, opcode, rn, rd;
4619     sf = extract32(insn, 31, 1);
4620     rm = extract32(insn, 16, 5);
4621     opcode = extract32(insn, 10, 6);
4622     rn = extract32(insn, 5, 5);
4623     rd = extract32(insn, 0, 5);
4624
4625     if (extract32(insn, 29, 1)) {
4626         unallocated_encoding(s);
4627         return;
4628     }
4629
4630     switch (opcode) {
4631     case 2: /* UDIV */
4632         handle_div(s, false, sf, rm, rn, rd);
4633         break;
4634     case 3: /* SDIV */
4635         handle_div(s, true, sf, rm, rn, rd);
4636         break;
4637     case 8: /* LSLV */
4638         handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
4639         break;
4640     case 9: /* LSRV */
4641         handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
4642         break;
4643     case 10: /* ASRV */
4644         handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
4645         break;
4646     case 11: /* RORV */
4647         handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
4648         break;
4649     case 16:
4650     case 17:
4651     case 18:
4652     case 19:
4653     case 20:
4654     case 21:
4655     case 22:
4656     case 23: /* CRC32 */
4657     {
4658         int sz = extract32(opcode, 0, 2);
4659         bool crc32c = extract32(opcode, 2, 1);
4660         handle_crc32(s, sf, sz, crc32c, rm, rn, rd);
4661         break;
4662     }
4663     default:
4664         unallocated_encoding(s);
4665         break;
4666     }
4667 }
4668
4669 /* Data processing - register */
4670 static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
4671 {
4672     switch (extract32(insn, 24, 5)) {
4673     case 0x0a: /* Logical (shifted register) */
4674         disas_logic_reg(s, insn);
4675         break;
4676     case 0x0b: /* Add/subtract */
4677         if (insn & (1 << 21)) { /* (extended register) */
4678             disas_add_sub_ext_reg(s, insn);
4679         } else {
4680             disas_add_sub_reg(s, insn);
4681         }
4682         break;
4683     case 0x1b: /* Data-processing (3 source) */
4684         disas_data_proc_3src(s, insn);
4685         break;
4686     case 0x1a:
4687         switch (extract32(insn, 21, 3)) {
4688         case 0x0: /* Add/subtract (with carry) */
4689             disas_adc_sbc(s, insn);
4690             break;
4691         case 0x2: /* Conditional compare */
4692             disas_cc(s, insn); /* both imm and reg forms */
4693             break;
4694         case 0x4: /* Conditional select */
4695             disas_cond_select(s, insn);
4696             break;
4697         case 0x6: /* Data-processing */
4698             if (insn & (1 << 30)) { /* (1 source) */
4699                 disas_data_proc_1src(s, insn);
4700             } else {            /* (2 source) */
4701                 disas_data_proc_2src(s, insn);
4702             }
4703             break;
4704         default:
4705             unallocated_encoding(s);
4706             break;
4707         }
4708         break;
4709     default:
4710         unallocated_encoding(s);
4711         break;
4712     }
4713 }
4714
4715 static void handle_fp_compare(DisasContext *s, int size,
4716                               unsigned int rn, unsigned int rm,
4717                               bool cmp_with_zero, bool signal_all_nans)
4718 {
4719     TCGv_i64 tcg_flags = tcg_temp_new_i64();
4720     TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
4721
4722     if (size == MO_64) {
4723         TCGv_i64 tcg_vn, tcg_vm;
4724
4725         tcg_vn = read_fp_dreg(s, rn);
4726         if (cmp_with_zero) {
4727             tcg_vm = tcg_const_i64(0);
4728         } else {
4729             tcg_vm = read_fp_dreg(s, rm);
4730         }
4731         if (signal_all_nans) {
4732             gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
4733         } else {
4734             gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
4735         }
4736         tcg_temp_free_i64(tcg_vn);
4737         tcg_temp_free_i64(tcg_vm);
4738     } else {
4739         TCGv_i32 tcg_vn = tcg_temp_new_i32();
4740         TCGv_i32 tcg_vm = tcg_temp_new_i32();
4741
4742         read_vec_element_i32(s, tcg_vn, rn, 0, size);
4743         if (cmp_with_zero) {
4744             tcg_gen_movi_i32(tcg_vm, 0);
4745         } else {
4746             read_vec_element_i32(s, tcg_vm, rm, 0, size);
4747         }
4748
4749         switch (size) {
4750         case MO_32:
4751             if (signal_all_nans) {
4752                 gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
4753             } else {
4754                 gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
4755             }
4756             break;
4757         case MO_16:
4758             if (signal_all_nans) {
4759                 gen_helper_vfp_cmpeh_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
4760             } else {
4761                 gen_helper_vfp_cmph_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
4762             }
4763             break;
4764         default:
4765             g_assert_not_reached();
4766         }
4767
4768         tcg_temp_free_i32(tcg_vn);
4769         tcg_temp_free_i32(tcg_vm);
4770     }
4771
4772     tcg_temp_free_ptr(fpst);
4773
4774     gen_set_nzcv(tcg_flags);
4775
4776     tcg_temp_free_i64(tcg_flags);
4777 }
4778
4779 /* Floating point compare
4780  *   31  30  29 28       24 23  22  21 20  16 15 14 13  10    9    5 4     0
4781  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
4782  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | op  | 1 0 0 0 |  Rn  |  op2  |
4783  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
4784  */
4785 static void disas_fp_compare(DisasContext *s, uint32_t insn)
4786 {
4787     unsigned int mos, type, rm, op, rn, opc, op2r;
4788     int size;
4789
4790     mos = extract32(insn, 29, 3);
4791     type = extract32(insn, 22, 2);
4792     rm = extract32(insn, 16, 5);
4793     op = extract32(insn, 14, 2);
4794     rn = extract32(insn, 5, 5);
4795     opc = extract32(insn, 3, 2);
4796     op2r = extract32(insn, 0, 3);
4797
4798     if (mos || op || op2r) {
4799         unallocated_encoding(s);
4800         return;
4801     }
4802
4803     switch (type) {
4804     case 0:
4805         size = MO_32;
4806         break;
4807     case 1:
4808         size = MO_64;
4809         break;
4810     case 3:
4811         size = MO_16;
4812         if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
4813             break;
4814         }
4815         /* fallthru */
4816     default:
4817         unallocated_encoding(s);
4818         return;
4819     }
4820
4821     if (!fp_access_check(s)) {
4822         return;
4823     }
4824
4825     handle_fp_compare(s, size, rn, rm, opc & 1, opc & 2);
4826 }
4827
4828 /* Floating point conditional compare
4829  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5  4   3    0
4830  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
4831  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 0 1 |  Rn  | op | nzcv |
4832  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
4833  */
4834 static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
4835 {
4836     unsigned int mos, type, rm, cond, rn, op, nzcv;
4837     TCGv_i64 tcg_flags;
4838     TCGLabel *label_continue = NULL;
4839     int size;
4840
4841     mos = extract32(insn, 29, 3);
4842     type = extract32(insn, 22, 2);
4843     rm = extract32(insn, 16, 5);
4844     cond = extract32(insn, 12, 4);
4845     rn = extract32(insn, 5, 5);
4846     op = extract32(insn, 4, 1);
4847     nzcv = extract32(insn, 0, 4);
4848
4849     if (mos) {
4850         unallocated_encoding(s);
4851         return;
4852     }
4853
4854     switch (type) {
4855     case 0:
4856         size = MO_32;
4857         break;
4858     case 1:
4859         size = MO_64;
4860         break;
4861     case 3:
4862         size = MO_16;
4863         if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
4864             break;
4865         }
4866         /* fallthru */
4867     default:
4868         unallocated_encoding(s);
4869         return;
4870     }
4871
4872     if (!fp_access_check(s)) {
4873         return;
4874     }
4875
4876     if (cond < 0x0e) { /* not always */
4877         TCGLabel *label_match = gen_new_label();
4878         label_continue = gen_new_label();
4879         arm_gen_test_cc(cond, label_match);
4880         /* nomatch: */
4881         tcg_flags = tcg_const_i64(nzcv << 28);
4882         gen_set_nzcv(tcg_flags);
4883         tcg_temp_free_i64(tcg_flags);
4884         tcg_gen_br(label_continue);
4885         gen_set_label(label_match);
4886     }
4887
4888     handle_fp_compare(s, size, rn, rm, false, op);
4889
4890     if (cond < 0x0e) {
4891         gen_set_label(label_continue);
4892     }
4893 }
4894
4895 /* Floating point conditional select
4896  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5 4    0
4897  * +---+---+---+-----------+------+---+------+------+-----+------+------+
4898  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 1 1 |  Rn  |  Rd  |
4899  * +---+---+---+-----------+------+---+------+------+-----+------+------+
4900  */
4901 static void disas_fp_csel(DisasContext *s, uint32_t insn)
4902 {
4903     unsigned int mos, type, rm, cond, rn, rd;
4904     TCGv_i64 t_true, t_false, t_zero;
4905     DisasCompare64 c;
4906     TCGMemOp sz;
4907
4908     mos = extract32(insn, 29, 3);
4909     type = extract32(insn, 22, 2);
4910     rm = extract32(insn, 16, 5);
4911     cond = extract32(insn, 12, 4);
4912     rn = extract32(insn, 5, 5);
4913     rd = extract32(insn, 0, 5);
4914
4915     if (mos) {
4916         unallocated_encoding(s);
4917         return;
4918     }
4919
4920     switch (type) {
4921     case 0:
4922         sz = MO_32;
4923         break;
4924     case 1:
4925         sz = MO_64;
4926         break;
4927     case 3:
4928         sz = MO_16;
4929         if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
4930             break;
4931         }
4932         /* fallthru */
4933     default:
4934         unallocated_encoding(s);
4935         return;
4936     }
4937
4938     if (!fp_access_check(s)) {
4939         return;
4940     }
4941
4942     /* Zero extend sreg & hreg inputs to 64 bits now.  */
4943     t_true = tcg_temp_new_i64();
4944     t_false = tcg_temp_new_i64();
4945     read_vec_element(s, t_true, rn, 0, sz);
4946     read_vec_element(s, t_false, rm, 0, sz);
4947
4948     a64_test_cc(&c, cond);
4949     t_zero = tcg_const_i64(0);
4950     tcg_gen_movcond_i64(c.cond, t_true, c.value, t_zero, t_true, t_false);
4951     tcg_temp_free_i64(t_zero);
4952     tcg_temp_free_i64(t_false);
4953     a64_free_cc(&c);
4954
4955     /* Note that sregs & hregs write back zeros to the high bits,
4956        and we've already done the zero-extension.  */
4957     write_fp_dreg(s, rd, t_true);
4958     tcg_temp_free_i64(t_true);
4959 }
4960
4961 /* Floating-point data-processing (1 source) - half precision */
4962 static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
4963 {
4964     TCGv_ptr fpst = NULL;
4965     TCGv_i32 tcg_op = read_fp_hreg(s, rn);
4966     TCGv_i32 tcg_res = tcg_temp_new_i32();
4967
4968     switch (opcode) {
4969     case 0x0: /* FMOV */
4970         tcg_gen_mov_i32(tcg_res, tcg_op);
4971         break;
4972     case 0x1: /* FABS */
4973         tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
4974         break;
4975     case 0x2: /* FNEG */
4976         tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
4977         break;
4978     case 0x3: /* FSQRT */
4979         gen_helper_sqrt_f16(tcg_res, tcg_op, cpu_env);
4980         break;
4981     case 0x8: /* FRINTN */
4982     case 0x9: /* FRINTP */
4983     case 0xa: /* FRINTM */
4984     case 0xb: /* FRINTZ */
4985     case 0xc: /* FRINTA */
4986     {
4987         TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
4988         fpst = get_fpstatus_ptr(true);
4989
4990         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
4991         gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
4992
4993         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
4994         tcg_temp_free_i32(tcg_rmode);
4995         break;
4996     }
4997     case 0xe: /* FRINTX */
4998         fpst = get_fpstatus_ptr(true);
4999         gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, fpst);
5000         break;
5001     case 0xf: /* FRINTI */
5002         fpst = get_fpstatus_ptr(true);
5003         gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
5004         break;
5005     default:
5006         abort();
5007     }
5008
5009     write_fp_sreg(s, rd, tcg_res);
5010
5011     if (fpst) {
5012         tcg_temp_free_ptr(fpst);
5013     }
5014     tcg_temp_free_i32(tcg_op);
5015     tcg_temp_free_i32(tcg_res);
5016 }
5017
5018 /* Floating-point data-processing (1 source) - single precision */
5019 static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
5020 {
5021     TCGv_ptr fpst;
5022     TCGv_i32 tcg_op;
5023     TCGv_i32 tcg_res;
5024
5025     fpst = get_fpstatus_ptr(false);
5026     tcg_op = read_fp_sreg(s, rn);
5027     tcg_res = tcg_temp_new_i32();
5028
5029     switch (opcode) {
5030     case 0x0: /* FMOV */
5031         tcg_gen_mov_i32(tcg_res, tcg_op);
5032         break;
5033     case 0x1: /* FABS */
5034         gen_helper_vfp_abss(tcg_res, tcg_op);
5035         break;
5036     case 0x2: /* FNEG */
5037         gen_helper_vfp_negs(tcg_res, tcg_op);
5038         break;
5039     case 0x3: /* FSQRT */
5040         gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
5041         break;
5042     case 0x8: /* FRINTN */
5043     case 0x9: /* FRINTP */
5044     case 0xa: /* FRINTM */
5045     case 0xb: /* FRINTZ */
5046     case 0xc: /* FRINTA */
5047     {
5048         TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
5049
5050         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5051         gen_helper_rints(tcg_res, tcg_op, fpst);
5052
5053         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5054         tcg_temp_free_i32(tcg_rmode);
5055         break;
5056     }
5057     case 0xe: /* FRINTX */
5058         gen_helper_rints_exact(tcg_res, tcg_op, fpst);
5059         break;
5060     case 0xf: /* FRINTI */
5061         gen_helper_rints(tcg_res, tcg_op, fpst);
5062         break;
5063     default:
5064         abort();
5065     }
5066
5067     write_fp_sreg(s, rd, tcg_res);
5068
5069     tcg_temp_free_ptr(fpst);
5070     tcg_temp_free_i32(tcg_op);
5071     tcg_temp_free_i32(tcg_res);
5072 }
5073
5074 /* Floating-point data-processing (1 source) - double precision */
5075 static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
5076 {
5077     TCGv_ptr fpst;
5078     TCGv_i64 tcg_op;
5079     TCGv_i64 tcg_res;
5080
5081     switch (opcode) {
5082     case 0x0: /* FMOV */
5083         gen_gvec_fn2(s, false, rd, rn, tcg_gen_gvec_mov, 0);
5084         return;
5085     }
5086
5087     fpst = get_fpstatus_ptr(false);
5088     tcg_op = read_fp_dreg(s, rn);
5089     tcg_res = tcg_temp_new_i64();
5090
5091     switch (opcode) {
5092     case 0x1: /* FABS */
5093         gen_helper_vfp_absd(tcg_res, tcg_op);
5094         break;
5095     case 0x2: /* FNEG */
5096         gen_helper_vfp_negd(tcg_res, tcg_op);
5097         break;
5098     case 0x3: /* FSQRT */
5099         gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
5100         break;
5101     case 0x8: /* FRINTN */
5102     case 0x9: /* FRINTP */
5103     case 0xa: /* FRINTM */
5104     case 0xb: /* FRINTZ */
5105     case 0xc: /* FRINTA */
5106     {
5107         TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
5108
5109         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5110         gen_helper_rintd(tcg_res, tcg_op, fpst);
5111
5112         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5113         tcg_temp_free_i32(tcg_rmode);
5114         break;
5115     }
5116     case 0xe: /* FRINTX */
5117         gen_helper_rintd_exact(tcg_res, tcg_op, fpst);
5118         break;
5119     case 0xf: /* FRINTI */
5120         gen_helper_rintd(tcg_res, tcg_op, fpst);
5121         break;
5122     default:
5123         abort();
5124     }
5125
5126     write_fp_dreg(s, rd, tcg_res);
5127
5128     tcg_temp_free_ptr(fpst);
5129     tcg_temp_free_i64(tcg_op);
5130     tcg_temp_free_i64(tcg_res);
5131 }
5132
5133 static void handle_fp_fcvt(DisasContext *s, int opcode,
5134                            int rd, int rn, int dtype, int ntype)
5135 {
5136     switch (ntype) {
5137     case 0x0:
5138     {
5139         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
5140         if (dtype == 1) {
5141             /* Single to double */
5142             TCGv_i64 tcg_rd = tcg_temp_new_i64();
5143             gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
5144             write_fp_dreg(s, rd, tcg_rd);
5145             tcg_temp_free_i64(tcg_rd);
5146         } else {
5147             /* Single to half */
5148             TCGv_i32 tcg_rd = tcg_temp_new_i32();
5149             gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, cpu_env);
5150             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
5151             write_fp_sreg(s, rd, tcg_rd);
5152             tcg_temp_free_i32(tcg_rd);
5153         }
5154         tcg_temp_free_i32(tcg_rn);
5155         break;
5156     }
5157     case 0x1:
5158     {
5159         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
5160         TCGv_i32 tcg_rd = tcg_temp_new_i32();
5161         if (dtype == 0) {
5162             /* Double to single */
5163             gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
5164         } else {
5165             /* Double to half */
5166             gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, cpu_env);
5167             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
5168         }
5169         write_fp_sreg(s, rd, tcg_rd);
5170         tcg_temp_free_i32(tcg_rd);
5171         tcg_temp_free_i64(tcg_rn);
5172         break;
5173     }
5174     case 0x3:
5175     {
5176         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
5177         tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
5178         if (dtype == 0) {
5179             /* Half to single */
5180             TCGv_i32 tcg_rd = tcg_temp_new_i32();
5181             gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, cpu_env);
5182             write_fp_sreg(s, rd, tcg_rd);
5183             tcg_temp_free_i32(tcg_rd);
5184         } else {
5185             /* Half to double */
5186             TCGv_i64 tcg_rd = tcg_temp_new_i64();
5187             gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, cpu_env);
5188             write_fp_dreg(s, rd, tcg_rd);
5189             tcg_temp_free_i64(tcg_rd);
5190         }
5191         tcg_temp_free_i32(tcg_rn);
5192         break;
5193     }
5194     default:
5195         abort();
5196     }
5197 }
5198
5199 /* Floating point data-processing (1 source)
5200  *   31  30  29 28       24 23  22  21 20    15 14       10 9    5 4    0
5201  * +---+---+---+-----------+------+---+--------+-----------+------+------+
5202  * | M | 0 | S | 1 1 1 1 0 | type | 1 | opcode | 1 0 0 0 0 |  Rn  |  Rd  |
5203  * +---+---+---+-----------+------+---+--------+-----------+------+------+
5204  */
5205 static void disas_fp_1src(DisasContext *s, uint32_t insn)
5206 {
5207     int type = extract32(insn, 22, 2);
5208     int opcode = extract32(insn, 15, 6);
5209     int rn = extract32(insn, 5, 5);
5210     int rd = extract32(insn, 0, 5);
5211
5212     switch (opcode) {
5213     case 0x4: case 0x5: case 0x7:
5214     {
5215         /* FCVT between half, single and double precision */
5216         int dtype = extract32(opcode, 0, 2);
5217         if (type == 2 || dtype == type) {
5218             unallocated_encoding(s);
5219             return;
5220         }
5221         if (!fp_access_check(s)) {
5222             return;
5223         }
5224
5225         handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
5226         break;
5227     }
5228     case 0x0 ... 0x3:
5229     case 0x8 ... 0xc:
5230     case 0xe ... 0xf:
5231         /* 32-to-32 and 64-to-64 ops */
5232         switch (type) {
5233         case 0:
5234             if (!fp_access_check(s)) {
5235                 return;
5236             }
5237
5238             handle_fp_1src_single(s, opcode, rd, rn);
5239             break;
5240         case 1:
5241             if (!fp_access_check(s)) {
5242                 return;
5243             }
5244
5245             handle_fp_1src_double(s, opcode, rd, rn);
5246             break;
5247         case 3:
5248             if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
5249                 unallocated_encoding(s);
5250                 return;
5251             }
5252
5253             if (!fp_access_check(s)) {
5254                 return;
5255             }
5256
5257             handle_fp_1src_half(s, opcode, rd, rn);
5258             break;
5259         default:
5260             unallocated_encoding(s);
5261         }
5262         break;
5263     default:
5264         unallocated_encoding(s);
5265         break;
5266     }
5267 }
5268
5269 /* Floating-point data-processing (2 source) - single precision */
5270 static void handle_fp_2src_single(DisasContext *s, int opcode,
5271                                   int rd, int rn, int rm)
5272 {
5273     TCGv_i32 tcg_op1;
5274     TCGv_i32 tcg_op2;
5275     TCGv_i32 tcg_res;
5276     TCGv_ptr fpst;
5277
5278     tcg_res = tcg_temp_new_i32();
5279     fpst = get_fpstatus_ptr(false);
5280     tcg_op1 = read_fp_sreg(s, rn);
5281     tcg_op2 = read_fp_sreg(s, rm);
5282
5283     switch (opcode) {
5284     case 0x0: /* FMUL */
5285         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
5286         break;
5287     case 0x1: /* FDIV */
5288         gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
5289         break;
5290     case 0x2: /* FADD */
5291         gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
5292         break;
5293     case 0x3: /* FSUB */
5294         gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
5295         break;
5296     case 0x4: /* FMAX */
5297         gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
5298         break;
5299     case 0x5: /* FMIN */
5300         gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
5301         break;
5302     case 0x6: /* FMAXNM */
5303         gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
5304         break;
5305     case 0x7: /* FMINNM */
5306         gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
5307         break;
5308     case 0x8: /* FNMUL */
5309         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
5310         gen_helper_vfp_negs(tcg_res, tcg_res);
5311         break;
5312     }
5313
5314     write_fp_sreg(s, rd, tcg_res);
5315
5316     tcg_temp_free_ptr(fpst);
5317     tcg_temp_free_i32(tcg_op1);
5318     tcg_temp_free_i32(tcg_op2);
5319     tcg_temp_free_i32(tcg_res);
5320 }
5321
5322 /* Floating-point data-processing (2 source) - double precision */
5323 static void handle_fp_2src_double(DisasContext *s, int opcode,
5324                                   int rd, int rn, int rm)
5325 {
5326     TCGv_i64 tcg_op1;
5327     TCGv_i64 tcg_op2;
5328     TCGv_i64 tcg_res;
5329     TCGv_ptr fpst;
5330
5331     tcg_res = tcg_temp_new_i64();
5332     fpst = get_fpstatus_ptr(false);
5333     tcg_op1 = read_fp_dreg(s, rn);
5334     tcg_op2 = read_fp_dreg(s, rm);
5335
5336     switch (opcode) {
5337     case 0x0: /* FMUL */
5338         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
5339         break;
5340     case 0x1: /* FDIV */
5341         gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
5342         break;
5343     case 0x2: /* FADD */
5344         gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
5345         break;
5346     case 0x3: /* FSUB */
5347         gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
5348         break;
5349     case 0x4: /* FMAX */
5350         gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
5351         break;
5352     case 0x5: /* FMIN */
5353         gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
5354         break;
5355     case 0x6: /* FMAXNM */
5356         gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
5357         break;
5358     case 0x7: /* FMINNM */
5359         gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
5360         break;
5361     case 0x8: /* FNMUL */
5362         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
5363         gen_helper_vfp_negd(tcg_res, tcg_res);
5364         break;
5365     }
5366
5367     write_fp_dreg(s, rd, tcg_res);
5368
5369     tcg_temp_free_ptr(fpst);
5370     tcg_temp_free_i64(tcg_op1);
5371     tcg_temp_free_i64(tcg_op2);
5372     tcg_temp_free_i64(tcg_res);
5373 }
5374
5375 /* Floating-point data-processing (2 source) - half precision */
5376 static void handle_fp_2src_half(DisasContext *s, int opcode,
5377                                 int rd, int rn, int rm)
5378 {
5379     TCGv_i32 tcg_op1;
5380     TCGv_i32 tcg_op2;
5381     TCGv_i32 tcg_res;
5382     TCGv_ptr fpst;
5383
5384     tcg_res = tcg_temp_new_i32();
5385     fpst = get_fpstatus_ptr(true);
5386     tcg_op1 = read_fp_hreg(s, rn);
5387     tcg_op2 = read_fp_hreg(s, rm);
5388
5389     switch (opcode) {
5390     case 0x0: /* FMUL */
5391         gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
5392         break;
5393     case 0x1: /* FDIV */
5394         gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
5395         break;
5396     case 0x2: /* FADD */
5397         gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
5398         break;
5399     case 0x3: /* FSUB */
5400         gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
5401         break;
5402     case 0x4: /* FMAX */
5403         gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
5404         break;
5405     case 0x5: /* FMIN */
5406         gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
5407         break;
5408     case 0x6: /* FMAXNM */
5409         gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
5410         break;
5411     case 0x7: /* FMINNM */
5412         gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
5413         break;
5414     case 0x8: /* FNMUL */
5415         gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
5416         tcg_gen_xori_i32(tcg_res, tcg_res, 0x8000);
5417         break;
5418     default:
5419         g_assert_not_reached();
5420     }
5421
5422     write_fp_sreg(s, rd, tcg_res);
5423
5424     tcg_temp_free_ptr(fpst);
5425     tcg_temp_free_i32(tcg_op1);
5426     tcg_temp_free_i32(tcg_op2);
5427     tcg_temp_free_i32(tcg_res);
5428 }
5429
5430 /* Floating point data-processing (2 source)
5431  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
5432  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
5433  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | opcode | 1 0 |  Rn  |  Rd  |
5434  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
5435  */
5436 static void disas_fp_2src(DisasContext *s, uint32_t insn)
5437 {
5438     int type = extract32(insn, 22, 2);
5439     int rd = extract32(insn, 0, 5);
5440     int rn = extract32(insn, 5, 5);
5441     int rm = extract32(insn, 16, 5);
5442     int opcode = extract32(insn, 12, 4);
5443
5444     if (opcode > 8) {
5445         unallocated_encoding(s);
5446         return;
5447     }
5448
5449     switch (type) {
5450     case 0:
5451         if (!fp_access_check(s)) {
5452             return;
5453         }
5454         handle_fp_2src_single(s, opcode, rd, rn, rm);
5455         break;
5456     case 1:
5457         if (!fp_access_check(s)) {
5458             return;
5459         }
5460         handle_fp_2src_double(s, opcode, rd, rn, rm);
5461         break;
5462     case 3:
5463         if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
5464             unallocated_encoding(s);
5465             return;
5466         }
5467         if (!fp_access_check(s)) {
5468             return;
5469         }
5470         handle_fp_2src_half(s, opcode, rd, rn, rm);
5471         break;
5472     default:
5473         unallocated_encoding(s);
5474     }
5475 }
5476
5477 /* Floating-point data-processing (3 source) - single precision */
5478 static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
5479                                   int rd, int rn, int rm, int ra)
5480 {
5481     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
5482     TCGv_i32 tcg_res = tcg_temp_new_i32();
5483     TCGv_ptr fpst = get_fpstatus_ptr(false);
5484
5485     tcg_op1 = read_fp_sreg(s, rn);
5486     tcg_op2 = read_fp_sreg(s, rm);
5487     tcg_op3 = read_fp_sreg(s, ra);
5488
5489     /* These are fused multiply-add, and must be done as one
5490      * floating point operation with no rounding between the
5491      * multiplication and addition steps.
5492      * NB that doing the negations here as separate steps is
5493      * correct : an input NaN should come out with its sign bit
5494      * flipped if it is a negated-input.
5495      */
5496     if (o1 == true) {
5497         gen_helper_vfp_negs(tcg_op3, tcg_op3);
5498     }
5499
5500     if (o0 != o1) {
5501         gen_helper_vfp_negs(tcg_op1, tcg_op1);
5502     }
5503
5504     gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
5505
5506     write_fp_sreg(s, rd, tcg_res);
5507
5508     tcg_temp_free_ptr(fpst);
5509     tcg_temp_free_i32(tcg_op1);
5510     tcg_temp_free_i32(tcg_op2);
5511     tcg_temp_free_i32(tcg_op3);
5512     tcg_temp_free_i32(tcg_res);
5513 }
5514
5515 /* Floating-point data-processing (3 source) - double precision */
5516 static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
5517                                   int rd, int rn, int rm, int ra)
5518 {
5519     TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
5520     TCGv_i64 tcg_res = tcg_temp_new_i64();
5521     TCGv_ptr fpst = get_fpstatus_ptr(false);
5522
5523     tcg_op1 = read_fp_dreg(s, rn);
5524     tcg_op2 = read_fp_dreg(s, rm);
5525     tcg_op3 = read_fp_dreg(s, ra);
5526
5527     /* These are fused multiply-add, and must be done as one
5528      * floating point operation with no rounding between the
5529      * multiplication and addition steps.
5530      * NB that doing the negations here as separate steps is
5531      * correct : an input NaN should come out with its sign bit
5532      * flipped if it is a negated-input.
5533      */
5534     if (o1 == true) {
5535         gen_helper_vfp_negd(tcg_op3, tcg_op3);
5536     }
5537
5538     if (o0 != o1) {
5539         gen_helper_vfp_negd(tcg_op1, tcg_op1);
5540     }
5541
5542     gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
5543
5544     write_fp_dreg(s, rd, tcg_res);
5545
5546     tcg_temp_free_ptr(fpst);
5547     tcg_temp_free_i64(tcg_op1);
5548     tcg_temp_free_i64(tcg_op2);
5549     tcg_temp_free_i64(tcg_op3);
5550     tcg_temp_free_i64(tcg_res);
5551 }
5552
5553 /* Floating-point data-processing (3 source) - half precision */
5554 static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1,
5555                                 int rd, int rn, int rm, int ra)
5556 {
5557     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
5558     TCGv_i32 tcg_res = tcg_temp_new_i32();
5559     TCGv_ptr fpst = get_fpstatus_ptr(true);
5560
5561     tcg_op1 = read_fp_hreg(s, rn);
5562     tcg_op2 = read_fp_hreg(s, rm);
5563     tcg_op3 = read_fp_hreg(s, ra);
5564
5565     /* These are fused multiply-add, and must be done as one
5566      * floating point operation with no rounding between the
5567      * multiplication and addition steps.
5568      * NB that doing the negations here as separate steps is
5569      * correct : an input NaN should come out with its sign bit
5570      * flipped if it is a negated-input.
5571      */
5572     if (o1 == true) {
5573         tcg_gen_xori_i32(tcg_op3, tcg_op3, 0x8000);
5574     }
5575
5576     if (o0 != o1) {
5577         tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
5578     }
5579
5580     gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
5581
5582     write_fp_sreg(s, rd, tcg_res);
5583
5584     tcg_temp_free_ptr(fpst);
5585     tcg_temp_free_i32(tcg_op1);
5586     tcg_temp_free_i32(tcg_op2);
5587     tcg_temp_free_i32(tcg_op3);
5588     tcg_temp_free_i32(tcg_res);
5589 }
5590
5591 /* Floating point data-processing (3 source)
5592  *   31  30  29 28       24 23  22  21  20  16  15  14  10 9    5 4    0
5593  * +---+---+---+-----------+------+----+------+----+------+------+------+
5594  * | M | 0 | S | 1 1 1 1 1 | type | o1 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
5595  * +---+---+---+-----------+------+----+------+----+------+------+------+
5596  */
5597 static void disas_fp_3src(DisasContext *s, uint32_t insn)
5598 {
5599     int type = extract32(insn, 22, 2);
5600     int rd = extract32(insn, 0, 5);
5601     int rn = extract32(insn, 5, 5);
5602     int ra = extract32(insn, 10, 5);
5603     int rm = extract32(insn, 16, 5);
5604     bool o0 = extract32(insn, 15, 1);
5605     bool o1 = extract32(insn, 21, 1);
5606
5607     switch (type) {
5608     case 0:
5609         if (!fp_access_check(s)) {
5610             return;
5611         }
5612         handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
5613         break;
5614     case 1:
5615         if (!fp_access_check(s)) {
5616             return;
5617         }
5618         handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
5619         break;
5620     case 3:
5621         if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
5622             unallocated_encoding(s);
5623             return;
5624         }
5625         if (!fp_access_check(s)) {
5626             return;
5627         }
5628         handle_fp_3src_half(s, o0, o1, rd, rn, rm, ra);
5629         break;
5630     default:
5631         unallocated_encoding(s);
5632     }
5633 }
5634
5635 /* The imm8 encodes the sign bit, enough bits to represent an exponent in
5636  * the range 01....1xx to 10....0xx, and the most significant 4 bits of
5637  * the mantissa; see VFPExpandImm() in the v8 ARM ARM.
5638  */
5639 static uint64_t vfp_expand_imm(int size, uint8_t imm8)
5640 {
5641     uint64_t imm;
5642
5643     switch (size) {
5644     case MO_64:
5645         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
5646             (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
5647             extract32(imm8, 0, 6);
5648         imm <<= 48;
5649         break;
5650     case MO_32:
5651         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
5652             (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
5653             (extract32(imm8, 0, 6) << 3);
5654         imm <<= 16;
5655         break;
5656     case MO_16:
5657         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
5658             (extract32(imm8, 6, 1) ? 0x3000 : 0x4000) |
5659             (extract32(imm8, 0, 6) << 6);
5660         break;
5661     default:
5662         g_assert_not_reached();
5663     }
5664     return imm;
5665 }
5666
5667 /* Floating point immediate
5668  *   31  30  29 28       24 23  22  21 20        13 12   10 9    5 4    0
5669  * +---+---+---+-----------+------+---+------------+-------+------+------+
5670  * | M | 0 | S | 1 1 1 1 0 | type | 1 |    imm8    | 1 0 0 | imm5 |  Rd  |
5671  * +---+---+---+-----------+------+---+------------+-------+------+------+
5672  */
5673 static void disas_fp_imm(DisasContext *s, uint32_t insn)
5674 {
5675     int rd = extract32(insn, 0, 5);
5676     int imm8 = extract32(insn, 13, 8);
5677     int is_double = extract32(insn, 22, 2);
5678     uint64_t imm;
5679     TCGv_i64 tcg_res;
5680
5681     if (is_double > 1) {
5682         unallocated_encoding(s);
5683         return;
5684     }
5685
5686     if (!fp_access_check(s)) {
5687         return;
5688     }
5689
5690     imm = vfp_expand_imm(MO_32 + is_double, imm8);
5691
5692     tcg_res = tcg_const_i64(imm);
5693     write_fp_dreg(s, rd, tcg_res);
5694     tcg_temp_free_i64(tcg_res);
5695 }
5696
5697 /* Handle floating point <=> fixed point conversions. Note that we can
5698  * also deal with fp <=> integer conversions as a special case (scale == 64)
5699  * OPTME: consider handling that special case specially or at least skipping
5700  * the call to scalbn in the helpers for zero shifts.
5701  */
5702 static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
5703                            bool itof, int rmode, int scale, int sf, int type)
5704 {
5705     bool is_signed = !(opcode & 1);
5706     TCGv_ptr tcg_fpstatus;
5707     TCGv_i32 tcg_shift, tcg_single;
5708     TCGv_i64 tcg_double;
5709
5710     tcg_fpstatus = get_fpstatus_ptr(type == 3);
5711
5712     tcg_shift = tcg_const_i32(64 - scale);
5713
5714     if (itof) {
5715         TCGv_i64 tcg_int = cpu_reg(s, rn);
5716         if (!sf) {
5717             TCGv_i64 tcg_extend = new_tmp_a64(s);
5718
5719             if (is_signed) {
5720                 tcg_gen_ext32s_i64(tcg_extend, tcg_int);
5721             } else {
5722                 tcg_gen_ext32u_i64(tcg_extend, tcg_int);
5723             }
5724
5725             tcg_int = tcg_extend;
5726         }
5727
5728         switch (type) {
5729         case 1: /* float64 */
5730             tcg_double = tcg_temp_new_i64();
5731             if (is_signed) {
5732                 gen_helper_vfp_sqtod(tcg_double, tcg_int,
5733                                      tcg_shift, tcg_fpstatus);
5734             } else {
5735                 gen_helper_vfp_uqtod(tcg_double, tcg_int,
5736                                      tcg_shift, tcg_fpstatus);
5737             }
5738             write_fp_dreg(s, rd, tcg_double);
5739             tcg_temp_free_i64(tcg_double);
5740             break;
5741
5742         case 0: /* float32 */
5743             tcg_single = tcg_temp_new_i32();
5744             if (is_signed) {
5745                 gen_helper_vfp_sqtos(tcg_single, tcg_int,
5746                                      tcg_shift, tcg_fpstatus);
5747             } else {
5748                 gen_helper_vfp_uqtos(tcg_single, tcg_int,
5749                                      tcg_shift, tcg_fpstatus);
5750             }
5751             write_fp_sreg(s, rd, tcg_single);
5752             tcg_temp_free_i32(tcg_single);
5753             break;
5754
5755         case 3: /* float16 */
5756             tcg_single = tcg_temp_new_i32();
5757             if (is_signed) {
5758                 gen_helper_vfp_sqtoh(tcg_single, tcg_int,
5759                                      tcg_shift, tcg_fpstatus);
5760             } else {
5761                 gen_helper_vfp_uqtoh(tcg_single, tcg_int,
5762                                      tcg_shift, tcg_fpstatus);
5763             }
5764             write_fp_sreg(s, rd, tcg_single);
5765             tcg_temp_free_i32(tcg_single);
5766             break;
5767
5768         default:
5769             g_assert_not_reached();
5770         }
5771     } else {
5772         TCGv_i64 tcg_int = cpu_reg(s, rd);
5773         TCGv_i32 tcg_rmode;
5774
5775         if (extract32(opcode, 2, 1)) {
5776             /* There are too many rounding modes to all fit into rmode,
5777              * so FCVTA[US] is a special case.
5778              */
5779             rmode = FPROUNDING_TIEAWAY;
5780         }
5781
5782         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
5783
5784         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
5785
5786         switch (type) {
5787         case 1: /* float64 */
5788             tcg_double = read_fp_dreg(s, rn);
5789             if (is_signed) {
5790                 if (!sf) {
5791                     gen_helper_vfp_tosld(tcg_int, tcg_double,
5792                                          tcg_shift, tcg_fpstatus);
5793                 } else {
5794                     gen_helper_vfp_tosqd(tcg_int, tcg_double,
5795                                          tcg_shift, tcg_fpstatus);
5796                 }
5797             } else {
5798                 if (!sf) {
5799                     gen_helper_vfp_tould(tcg_int, tcg_double,
5800                                          tcg_shift, tcg_fpstatus);
5801                 } else {
5802                     gen_helper_vfp_touqd(tcg_int, tcg_double,
5803                                          tcg_shift, tcg_fpstatus);
5804                 }
5805             }
5806             if (!sf) {
5807                 tcg_gen_ext32u_i64(tcg_int, tcg_int);
5808             }
5809             tcg_temp_free_i64(tcg_double);
5810             break;
5811
5812         case 0: /* float32 */
5813             tcg_single = read_fp_sreg(s, rn);
5814             if (sf) {
5815                 if (is_signed) {
5816                     gen_helper_vfp_tosqs(tcg_int, tcg_single,
5817                                          tcg_shift, tcg_fpstatus);
5818                 } else {
5819                     gen_helper_vfp_touqs(tcg_int, tcg_single,
5820                                          tcg_shift, tcg_fpstatus);
5821                 }
5822             } else {
5823                 TCGv_i32 tcg_dest = tcg_temp_new_i32();
5824                 if (is_signed) {
5825                     gen_helper_vfp_tosls(tcg_dest, tcg_single,
5826                                          tcg_shift, tcg_fpstatus);
5827                 } else {
5828                     gen_helper_vfp_touls(tcg_dest, tcg_single,
5829                                          tcg_shift, tcg_fpstatus);
5830                 }
5831                 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
5832                 tcg_temp_free_i32(tcg_dest);
5833             }
5834             tcg_temp_free_i32(tcg_single);
5835             break;
5836
5837         case 3: /* float16 */
5838             tcg_single = read_fp_sreg(s, rn);
5839             if (sf) {
5840                 if (is_signed) {
5841                     gen_helper_vfp_tosqh(tcg_int, tcg_single,
5842                                          tcg_shift, tcg_fpstatus);
5843                 } else {
5844                     gen_helper_vfp_touqh(tcg_int, tcg_single,
5845                                          tcg_shift, tcg_fpstatus);
5846                 }
5847             } else {
5848                 TCGv_i32 tcg_dest = tcg_temp_new_i32();
5849                 if (is_signed) {
5850                     gen_helper_vfp_toslh(tcg_dest, tcg_single,
5851                                          tcg_shift, tcg_fpstatus);
5852                 } else {
5853                     gen_helper_vfp_toulh(tcg_dest, tcg_single,
5854                                          tcg_shift, tcg_fpstatus);
5855                 }
5856                 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
5857                 tcg_temp_free_i32(tcg_dest);
5858             }
5859             tcg_temp_free_i32(tcg_single);
5860             break;
5861
5862         default:
5863             g_assert_not_reached();
5864         }
5865
5866         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
5867         tcg_temp_free_i32(tcg_rmode);
5868     }
5869
5870     tcg_temp_free_ptr(tcg_fpstatus);
5871     tcg_temp_free_i32(tcg_shift);
5872 }
5873
5874 /* Floating point <-> fixed point conversions
5875  *   31   30  29 28       24 23  22  21 20   19 18    16 15   10 9    5 4    0
5876  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
5877  * | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opcode | scale |  Rn  |  Rd  |
5878  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
5879  */
5880 static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
5881 {
5882     int rd = extract32(insn, 0, 5);
5883     int rn = extract32(insn, 5, 5);
5884     int scale = extract32(insn, 10, 6);
5885     int opcode = extract32(insn, 16, 3);
5886     int rmode = extract32(insn, 19, 2);
5887     int type = extract32(insn, 22, 2);
5888     bool sbit = extract32(insn, 29, 1);
5889     bool sf = extract32(insn, 31, 1);
5890     bool itof;
5891
5892     if (sbit || (!sf && scale < 32)) {
5893         unallocated_encoding(s);
5894         return;
5895     }
5896
5897     switch (type) {
5898     case 0: /* float32 */
5899     case 1: /* float64 */
5900         break;
5901     case 3: /* float16 */
5902         if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
5903             break;
5904         }
5905         /* fallthru */
5906     default:
5907         unallocated_encoding(s);
5908         return;
5909     }
5910
5911     switch ((rmode << 3) | opcode) {
5912     case 0x2: /* SCVTF */
5913     case 0x3: /* UCVTF */
5914         itof = true;
5915         break;
5916     case 0x18: /* FCVTZS */
5917     case 0x19: /* FCVTZU */
5918         itof = false;
5919         break;
5920     default:
5921         unallocated_encoding(s);
5922         return;
5923     }
5924
5925     if (!fp_access_check(s)) {
5926         return;
5927     }
5928
5929     handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
5930 }
5931
5932 static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
5933 {
5934     /* FMOV: gpr to or from float, double, or top half of quad fp reg,
5935      * without conversion.
5936      */
5937
5938     if (itof) {
5939         TCGv_i64 tcg_rn = cpu_reg(s, rn);
5940         TCGv_i64 tmp;
5941
5942         switch (type) {
5943         case 0:
5944             /* 32 bit */
5945             tmp = tcg_temp_new_i64();
5946             tcg_gen_ext32u_i64(tmp, tcg_rn);
5947             write_fp_dreg(s, rd, tmp);
5948             tcg_temp_free_i64(tmp);
5949             break;
5950         case 1:
5951             /* 64 bit */
5952             write_fp_dreg(s, rd, tcg_rn);
5953             break;
5954         case 2:
5955             /* 64 bit to top half. */
5956             tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd));
5957             clear_vec_high(s, true, rd);
5958             break;
5959         case 3:
5960             /* 16 bit */
5961             tmp = tcg_temp_new_i64();
5962             tcg_gen_ext16u_i64(tmp, tcg_rn);
5963             write_fp_dreg(s, rd, tmp);
5964             tcg_temp_free_i64(tmp);
5965             break;
5966         default:
5967             g_assert_not_reached();
5968         }
5969     } else {
5970         TCGv_i64 tcg_rd = cpu_reg(s, rd);
5971
5972         switch (type) {
5973         case 0:
5974             /* 32 bit */
5975             tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_32));
5976             break;
5977         case 1:
5978             /* 64 bit */
5979             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_64));
5980             break;
5981         case 2:
5982             /* 64 bits from top half */
5983             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(s, rn));
5984             break;
5985         case 3:
5986             /* 16 bit */
5987             tcg_gen_ld16u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_16));
5988             break;
5989         default:
5990             g_assert_not_reached();
5991         }
5992     }
5993 }
5994
5995 /* Floating point <-> integer conversions
5996  *   31   30  29 28       24 23  22  21 20   19 18 16 15         10 9  5 4  0
5997  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
5998  * | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
5999  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
6000  */
6001 static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
6002 {
6003     int rd = extract32(insn, 0, 5);
6004     int rn = extract32(insn, 5, 5);
6005     int opcode = extract32(insn, 16, 3);
6006     int rmode = extract32(insn, 19, 2);
6007     int type = extract32(insn, 22, 2);
6008     bool sbit = extract32(insn, 29, 1);
6009     bool sf = extract32(insn, 31, 1);
6010
6011     if (sbit) {
6012         unallocated_encoding(s);
6013         return;
6014     }
6015
6016     if (opcode > 5) {
6017         /* FMOV */
6018         bool itof = opcode & 1;
6019
6020         if (rmode >= 2) {
6021             unallocated_encoding(s);
6022             return;
6023         }
6024
6025         switch (sf << 3 | type << 1 | rmode) {
6026         case 0x0: /* 32 bit */
6027         case 0xa: /* 64 bit */
6028         case 0xd: /* 64 bit to top half of quad */
6029             break;
6030         case 0x6: /* 16-bit float, 32-bit int */
6031         case 0xe: /* 16-bit float, 64-bit int */
6032             if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
6033                 break;
6034             }
6035             /* fallthru */
6036         default:
6037             /* all other sf/type/rmode combinations are invalid */
6038             unallocated_encoding(s);
6039             return;
6040         }
6041
6042         if (!fp_access_check(s)) {
6043             return;
6044         }
6045         handle_fmov(s, rd, rn, type, itof);
6046     } else {
6047         /* actual FP conversions */
6048         bool itof = extract32(opcode, 1, 1);
6049
6050         if (rmode != 0 && opcode > 1) {
6051             unallocated_encoding(s);
6052             return;
6053         }
6054         switch (type) {
6055         case 0: /* float32 */
6056         case 1: /* float64 */
6057             break;
6058         case 3: /* float16 */
6059             if (arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
6060                 break;
6061             }
6062             /* fallthru */
6063         default:
6064             unallocated_encoding(s);
6065             return;
6066         }
6067
6068         if (!fp_access_check(s)) {
6069             return;
6070         }
6071         handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
6072     }
6073 }
6074
6075 /* FP-specific subcases of table C3-6 (SIMD and FP data processing)
6076  *   31  30  29 28     25 24                          0
6077  * +---+---+---+---------+-----------------------------+
6078  * |   | 0 |   | 1 1 1 1 |                             |
6079  * +---+---+---+---------+-----------------------------+
6080  */
6081 static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
6082 {
6083     if (extract32(insn, 24, 1)) {
6084         /* Floating point data-processing (3 source) */
6085         disas_fp_3src(s, insn);
6086     } else if (extract32(insn, 21, 1) == 0) {
6087         /* Floating point to fixed point conversions */
6088         disas_fp_fixed_conv(s, insn);
6089     } else {
6090         switch (extract32(insn, 10, 2)) {
6091         case 1:
6092             /* Floating point conditional compare */
6093             disas_fp_ccomp(s, insn);
6094             break;
6095         case 2:
6096             /* Floating point data-processing (2 source) */
6097             disas_fp_2src(s, insn);
6098             break;
6099         case 3:
6100             /* Floating point conditional select */
6101             disas_fp_csel(s, insn);
6102             break;
6103         case 0:
6104             switch (ctz32(extract32(insn, 12, 4))) {
6105             case 0: /* [15:12] == xxx1 */
6106                 /* Floating point immediate */
6107                 disas_fp_imm(s, insn);
6108                 break;
6109             case 1: /* [15:12] == xx10 */
6110                 /* Floating point compare */
6111                 disas_fp_compare(s, insn);
6112                 break;
6113             case 2: /* [15:12] == x100 */
6114                 /* Floating point data-processing (1 source) */
6115                 disas_fp_1src(s, insn);
6116                 break;
6117             case 3: /* [15:12] == 1000 */
6118                 unallocated_encoding(s);
6119                 break;
6120             default: /* [15:12] == 0000 */
6121                 /* Floating point <-> integer conversions */
6122                 disas_fp_int_conv(s, insn);
6123                 break;
6124             }
6125             break;
6126         }
6127     }
6128 }
6129
6130 static void do_ext64(DisasContext *s, TCGv_i64 tcg_left, TCGv_i64 tcg_right,
6131                      int pos)
6132 {
6133     /* Extract 64 bits from the middle of two concatenated 64 bit
6134      * vector register slices left:right. The extracted bits start
6135      * at 'pos' bits into the right (least significant) side.
6136      * We return the result in tcg_right, and guarantee not to
6137      * trash tcg_left.
6138      */
6139     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
6140     assert(pos > 0 && pos < 64);
6141
6142     tcg_gen_shri_i64(tcg_right, tcg_right, pos);
6143     tcg_gen_shli_i64(tcg_tmp, tcg_left, 64 - pos);
6144     tcg_gen_or_i64(tcg_right, tcg_right, tcg_tmp);
6145
6146     tcg_temp_free_i64(tcg_tmp);
6147 }
6148
6149 /* EXT
6150  *   31  30 29         24 23 22  21 20  16 15  14  11 10  9    5 4    0
6151  * +---+---+-------------+-----+---+------+---+------+---+------+------+
6152  * | 0 | Q | 1 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | imm4 | 0 |  Rn  |  Rd  |
6153  * +---+---+-------------+-----+---+------+---+------+---+------+------+
6154  */
6155 static void disas_simd_ext(DisasContext *s, uint32_t insn)
6156 {
6157     int is_q = extract32(insn, 30, 1);
6158     int op2 = extract32(insn, 22, 2);
6159     int imm4 = extract32(insn, 11, 4);
6160     int rm = extract32(insn, 16, 5);
6161     int rn = extract32(insn, 5, 5);
6162     int rd = extract32(insn, 0, 5);
6163     int pos = imm4 << 3;
6164     TCGv_i64 tcg_resl, tcg_resh;
6165
6166     if (op2 != 0 || (!is_q && extract32(imm4, 3, 1))) {
6167         unallocated_encoding(s);
6168         return;
6169     }
6170
6171     if (!fp_access_check(s)) {
6172         return;
6173     }
6174
6175     tcg_resh = tcg_temp_new_i64();
6176     tcg_resl = tcg_temp_new_i64();
6177
6178     /* Vd gets bits starting at pos bits into Vm:Vn. This is
6179      * either extracting 128 bits from a 128:128 concatenation, or
6180      * extracting 64 bits from a 64:64 concatenation.
6181      */
6182     if (!is_q) {
6183         read_vec_element(s, tcg_resl, rn, 0, MO_64);
6184         if (pos != 0) {
6185             read_vec_element(s, tcg_resh, rm, 0, MO_64);
6186             do_ext64(s, tcg_resh, tcg_resl, pos);
6187         }
6188         tcg_gen_movi_i64(tcg_resh, 0);
6189     } else {
6190         TCGv_i64 tcg_hh;
6191         typedef struct {
6192             int reg;
6193             int elt;
6194         } EltPosns;
6195         EltPosns eltposns[] = { {rn, 0}, {rn, 1}, {rm, 0}, {rm, 1} };
6196         EltPosns *elt = eltposns;
6197
6198         if (pos >= 64) {
6199             elt++;
6200             pos -= 64;
6201         }
6202
6203         read_vec_element(s, tcg_resl, elt->reg, elt->elt, MO_64);
6204         elt++;
6205         read_vec_element(s, tcg_resh, elt->reg, elt->elt, MO_64);
6206         elt++;
6207         if (pos != 0) {
6208             do_ext64(s, tcg_resh, tcg_resl, pos);
6209             tcg_hh = tcg_temp_new_i64();
6210             read_vec_element(s, tcg_hh, elt->reg, elt->elt, MO_64);
6211             do_ext64(s, tcg_hh, tcg_resh, pos);
6212             tcg_temp_free_i64(tcg_hh);
6213         }
6214     }
6215
6216     write_vec_element(s, tcg_resl, rd, 0, MO_64);
6217     tcg_temp_free_i64(tcg_resl);
6218     write_vec_element(s, tcg_resh, rd, 1, MO_64);
6219     tcg_temp_free_i64(tcg_resh);
6220 }
6221
6222 /* TBL/TBX
6223  *   31  30 29         24 23 22  21 20  16 15  14 13  12  11 10 9    5 4    0
6224  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
6225  * | 0 | Q | 0 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | len | op | 0 0 |  Rn  |  Rd  |
6226  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
6227  */
6228 static void disas_simd_tb(DisasContext *s, uint32_t insn)
6229 {
6230     int op2 = extract32(insn, 22, 2);
6231     int is_q = extract32(insn, 30, 1);
6232     int rm = extract32(insn, 16, 5);
6233     int rn = extract32(insn, 5, 5);
6234     int rd = extract32(insn, 0, 5);
6235     int is_tblx = extract32(insn, 12, 1);
6236     int len = extract32(insn, 13, 2);
6237     TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
6238     TCGv_i32 tcg_regno, tcg_numregs;
6239
6240     if (op2 != 0) {
6241         unallocated_encoding(s);
6242         return;
6243     }
6244
6245     if (!fp_access_check(s)) {
6246         return;
6247     }
6248
6249     /* This does a table lookup: for every byte element in the input
6250      * we index into a table formed from up to four vector registers,
6251      * and then the output is the result of the lookups. Our helper
6252      * function does the lookup operation for a single 64 bit part of
6253      * the input.
6254      */
6255     tcg_resl = tcg_temp_new_i64();
6256     tcg_resh = tcg_temp_new_i64();
6257
6258     if (is_tblx) {
6259         read_vec_element(s, tcg_resl, rd, 0, MO_64);
6260     } else {
6261         tcg_gen_movi_i64(tcg_resl, 0);
6262     }
6263     if (is_tblx && is_q) {
6264         read_vec_element(s, tcg_resh, rd, 1, MO_64);
6265     } else {
6266         tcg_gen_movi_i64(tcg_resh, 0);
6267     }
6268
6269     tcg_idx = tcg_temp_new_i64();
6270     tcg_regno = tcg_const_i32(rn);
6271     tcg_numregs = tcg_const_i32(len + 1);
6272     read_vec_element(s, tcg_idx, rm, 0, MO_64);
6273     gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
6274                         tcg_regno, tcg_numregs);
6275     if (is_q) {
6276         read_vec_element(s, tcg_idx, rm, 1, MO_64);
6277         gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
6278                             tcg_regno, tcg_numregs);
6279     }
6280     tcg_temp_free_i64(tcg_idx);
6281     tcg_temp_free_i32(tcg_regno);
6282     tcg_temp_free_i32(tcg_numregs);
6283
6284     write_vec_element(s, tcg_resl, rd, 0, MO_64);
6285     tcg_temp_free_i64(tcg_resl);
6286     write_vec_element(s, tcg_resh, rd, 1, MO_64);
6287     tcg_temp_free_i64(tcg_resh);
6288 }
6289
6290 /* ZIP/UZP/TRN
6291  *   31  30 29         24 23  22  21 20   16 15 14 12 11 10 9    5 4    0
6292  * +---+---+-------------+------+---+------+---+------------------+------+
6293  * | 0 | Q | 0 0 1 1 1 0 | size | 0 |  Rm  | 0 | opc | 1 0 |  Rn  |  Rd  |
6294  * +---+---+-------------+------+---+------+---+------------------+------+
6295  */
6296 static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
6297 {
6298     int rd = extract32(insn, 0, 5);
6299     int rn = extract32(insn, 5, 5);
6300     int rm = extract32(insn, 16, 5);
6301     int size = extract32(insn, 22, 2);
6302     /* opc field bits [1:0] indicate ZIP/UZP/TRN;
6303      * bit 2 indicates 1 vs 2 variant of the insn.
6304      */
6305     int opcode = extract32(insn, 12, 2);
6306     bool part = extract32(insn, 14, 1);
6307     bool is_q = extract32(insn, 30, 1);
6308     int esize = 8 << size;
6309     int i, ofs;
6310     int datasize = is_q ? 128 : 64;
6311     int elements = datasize / esize;
6312     TCGv_i64 tcg_res, tcg_resl, tcg_resh;
6313
6314     if (opcode == 0 || (size == 3 && !is_q)) {
6315         unallocated_encoding(s);
6316         return;
6317     }
6318
6319     if (!fp_access_check(s)) {
6320         return;
6321     }
6322
6323     tcg_resl = tcg_const_i64(0);
6324     tcg_resh = tcg_const_i64(0);
6325     tcg_res = tcg_temp_new_i64();
6326
6327     for (i = 0; i < elements; i++) {
6328         switch (opcode) {
6329         case 1: /* UZP1/2 */
6330         {
6331             int midpoint = elements / 2;
6332             if (i < midpoint) {
6333                 read_vec_element(s, tcg_res, rn, 2 * i + part, size);
6334             } else {
6335                 read_vec_element(s, tcg_res, rm,
6336                                  2 * (i - midpoint) + part, size);
6337             }
6338             break;
6339         }
6340         case 2: /* TRN1/2 */
6341             if (i & 1) {
6342                 read_vec_element(s, tcg_res, rm, (i & ~1) + part, size);
6343             } else {
6344                 read_vec_element(s, tcg_res, rn, (i & ~1) + part, size);
6345             }
6346             break;
6347         case 3: /* ZIP1/2 */
6348         {
6349             int base = part * elements / 2;
6350             if (i & 1) {
6351                 read_vec_element(s, tcg_res, rm, base + (i >> 1), size);
6352             } else {
6353                 read_vec_element(s, tcg_res, rn, base + (i >> 1), size);
6354             }
6355             break;
6356         }
6357         default:
6358             g_assert_not_reached();
6359         }
6360
6361         ofs = i * esize;
6362         if (ofs < 64) {
6363             tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
6364             tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
6365         } else {
6366             tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
6367             tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
6368         }
6369     }
6370
6371     tcg_temp_free_i64(tcg_res);
6372
6373     write_vec_element(s, tcg_resl, rd, 0, MO_64);
6374     tcg_temp_free_i64(tcg_resl);
6375     write_vec_element(s, tcg_resh, rd, 1, MO_64);
6376     tcg_temp_free_i64(tcg_resh);
6377 }
6378
6379 /*
6380  * do_reduction_op helper
6381  *
6382  * This mirrors the Reduce() pseudocode in the ARM ARM. It is
6383  * important for correct NaN propagation that we do these
6384  * operations in exactly the order specified by the pseudocode.
6385  *
6386  * This is a recursive function, TCG temps should be freed by the
6387  * calling function once it is done with the values.
6388  */
6389 static TCGv_i32 do_reduction_op(DisasContext *s, int fpopcode, int rn,
6390                                 int esize, int size, int vmap, TCGv_ptr fpst)
6391 {
6392     if (esize == size) {
6393         int element;
6394         TCGMemOp msize = esize == 16 ? MO_16 : MO_32;
6395         TCGv_i32 tcg_elem;
6396
6397         /* We should have one register left here */
6398         assert(ctpop8(vmap) == 1);
6399         element = ctz32(vmap);
6400         assert(element < 8);
6401
6402         tcg_elem = tcg_temp_new_i32();
6403         read_vec_element_i32(s, tcg_elem, rn, element, msize);
6404         return tcg_elem;
6405     } else {
6406         int bits = size / 2;
6407         int shift = ctpop8(vmap) / 2;
6408         int vmap_lo = (vmap >> shift) & vmap;
6409         int vmap_hi = (vmap & ~vmap_lo);
6410         TCGv_i32 tcg_hi, tcg_lo, tcg_res;
6411
6412         tcg_hi = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_hi, fpst);
6413         tcg_lo = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_lo, fpst);
6414         tcg_res = tcg_temp_new_i32();
6415
6416         switch (fpopcode) {
6417         case 0x0c: /* fmaxnmv half-precision */
6418             gen_helper_advsimd_maxnumh(tcg_res, tcg_lo, tcg_hi, fpst);
6419             break;
6420         case 0x0f: /* fmaxv half-precision */
6421             gen_helper_advsimd_maxh(tcg_res, tcg_lo, tcg_hi, fpst);
6422             break;
6423         case 0x1c: /* fminnmv half-precision */
6424             gen_helper_advsimd_minnumh(tcg_res, tcg_lo, tcg_hi, fpst);
6425             break;
6426         case 0x1f: /* fminv half-precision */
6427             gen_helper_advsimd_minh(tcg_res, tcg_lo, tcg_hi, fpst);
6428             break;
6429         case 0x2c: /* fmaxnmv */
6430             gen_helper_vfp_maxnums(tcg_res, tcg_lo, tcg_hi, fpst);
6431             break;
6432         case 0x2f: /* fmaxv */
6433             gen_helper_vfp_maxs(tcg_res, tcg_lo, tcg_hi, fpst);
6434             break;
6435         case 0x3c: /* fminnmv */
6436             gen_helper_vfp_minnums(tcg_res, tcg_lo, tcg_hi, fpst);
6437             break;
6438         case 0x3f: /* fminv */
6439             gen_helper_vfp_mins(tcg_res, tcg_lo, tcg_hi, fpst);
6440             break;
6441         default:
6442             g_assert_not_reached();
6443         }
6444
6445         tcg_temp_free_i32(tcg_hi);
6446         tcg_temp_free_i32(tcg_lo);
6447         return tcg_res;
6448     }
6449 }
6450
6451 /* AdvSIMD across lanes
6452  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
6453  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
6454  * | 0 | Q | U | 0 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
6455  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
6456  */
6457 static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
6458 {
6459     int rd = extract32(insn, 0, 5);
6460     int rn = extract32(insn, 5, 5);
6461     int size = extract32(insn, 22, 2);
6462     int opcode = extract32(insn, 12, 5);
6463     bool is_q = extract32(insn, 30, 1);
6464     bool is_u = extract32(insn, 29, 1);
6465     bool is_fp = false;
6466     bool is_min = false;
6467     int esize;
6468     int elements;
6469     int i;
6470     TCGv_i64 tcg_res, tcg_elt;
6471
6472     switch (opcode) {
6473     case 0x1b: /* ADDV */
6474         if (is_u) {
6475             unallocated_encoding(s);
6476             return;
6477         }
6478         /* fall through */
6479     case 0x3: /* SADDLV, UADDLV */
6480     case 0xa: /* SMAXV, UMAXV */
6481     case 0x1a: /* SMINV, UMINV */
6482         if (size == 3 || (size == 2 && !is_q)) {
6483             unallocated_encoding(s);
6484             return;
6485         }
6486         break;
6487     case 0xc: /* FMAXNMV, FMINNMV */
6488     case 0xf: /* FMAXV, FMINV */
6489         /* Bit 1 of size field encodes min vs max and the actual size
6490          * depends on the encoding of the U bit. If not set (and FP16
6491          * enabled) then we do half-precision float instead of single
6492          * precision.
6493          */
6494         is_min = extract32(size, 1, 1);
6495         is_fp = true;
6496         if (!is_u && arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
6497             size = 1;
6498         } else if (!is_u || !is_q || extract32(size, 0, 1)) {
6499             unallocated_encoding(s);
6500             return;
6501         } else {
6502             size = 2;
6503         }
6504         break;
6505     default:
6506         unallocated_encoding(s);
6507         return;
6508     }
6509
6510     if (!fp_access_check(s)) {
6511         return;
6512     }
6513
6514     esize = 8 << size;
6515     elements = (is_q ? 128 : 64) / esize;
6516
6517     tcg_res = tcg_temp_new_i64();
6518     tcg_elt = tcg_temp_new_i64();
6519
6520     /* These instructions operate across all lanes of a vector
6521      * to produce a single result. We can guarantee that a 64
6522      * bit intermediate is sufficient:
6523      *  + for [US]ADDLV the maximum element size is 32 bits, and
6524      *    the result type is 64 bits
6525      *  + for FMAX*V, FMIN*V, ADDV the intermediate type is the
6526      *    same as the element size, which is 32 bits at most
6527      * For the integer operations we can choose to work at 64
6528      * or 32 bits and truncate at the end; for simplicity
6529      * we use 64 bits always. The floating point
6530      * ops do require 32 bit intermediates, though.
6531      */
6532     if (!is_fp) {
6533         read_vec_element(s, tcg_res, rn, 0, size | (is_u ? 0 : MO_SIGN));
6534
6535         for (i = 1; i < elements; i++) {
6536             read_vec_element(s, tcg_elt, rn, i, size | (is_u ? 0 : MO_SIGN));
6537
6538             switch (opcode) {
6539             case 0x03: /* SADDLV / UADDLV */
6540             case 0x1b: /* ADDV */
6541                 tcg_gen_add_i64(tcg_res, tcg_res, tcg_elt);
6542                 break;
6543             case 0x0a: /* SMAXV / UMAXV */
6544                 if (is_u) {
6545                     tcg_gen_umax_i64(tcg_res, tcg_res, tcg_elt);
6546                 } else {
6547                     tcg_gen_smax_i64(tcg_res, tcg_res, tcg_elt);
6548                 }
6549                 break;
6550             case 0x1a: /* SMINV / UMINV */
6551                 if (is_u) {
6552                     tcg_gen_umin_i64(tcg_res, tcg_res, tcg_elt);
6553                 } else {
6554                     tcg_gen_smin_i64(tcg_res, tcg_res, tcg_elt);
6555                 }
6556                 break;
6557             default:
6558                 g_assert_not_reached();
6559             }
6560
6561         }
6562     } else {
6563         /* Floating point vector reduction ops which work across 32
6564          * bit (single) or 16 bit (half-precision) intermediates.
6565          * Note that correct NaN propagation requires that we do these
6566          * operations in exactly the order specified by the pseudocode.
6567          */
6568         TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
6569         int fpopcode = opcode | is_min << 4 | is_u << 5;
6570         int vmap = (1 << elements) - 1;
6571         TCGv_i32 tcg_res32 = do_reduction_op(s, fpopcode, rn, esize,
6572                                              (is_q ? 128 : 64), vmap, fpst);
6573         tcg_gen_extu_i32_i64(tcg_res, tcg_res32);
6574         tcg_temp_free_i32(tcg_res32);
6575         tcg_temp_free_ptr(fpst);
6576     }
6577
6578     tcg_temp_free_i64(tcg_elt);
6579
6580     /* Now truncate the result to the width required for the final output */
6581     if (opcode == 0x03) {
6582         /* SADDLV, UADDLV: result is 2*esize */
6583         size++;
6584     }
6585
6586     switch (size) {
6587     case 0:
6588         tcg_gen_ext8u_i64(tcg_res, tcg_res);
6589         break;
6590     case 1:
6591         tcg_gen_ext16u_i64(tcg_res, tcg_res);
6592         break;
6593     case 2:
6594         tcg_gen_ext32u_i64(tcg_res, tcg_res);
6595         break;
6596     case 3:
6597         break;
6598     default:
6599         g_assert_not_reached();
6600     }
6601
6602     write_fp_dreg(s, rd, tcg_res);
6603     tcg_temp_free_i64(tcg_res);
6604 }
6605
6606 /* DUP (Element, Vector)
6607  *
6608  *  31  30   29              21 20    16 15        10  9    5 4    0
6609  * +---+---+-------------------+--------+-------------+------+------+
6610  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
6611  * +---+---+-------------------+--------+-------------+------+------+
6612  *
6613  * size: encoded in imm5 (see ARM ARM LowestSetBit())
6614  */
6615 static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
6616                              int imm5)
6617 {
6618     int size = ctz32(imm5);
6619     int index = imm5 >> (size + 1);
6620
6621     if (size > 3 || (size == 3 && !is_q)) {
6622         unallocated_encoding(s);
6623         return;
6624     }
6625
6626     if (!fp_access_check(s)) {
6627         return;
6628     }
6629
6630     tcg_gen_gvec_dup_mem(size, vec_full_reg_offset(s, rd),
6631                          vec_reg_offset(s, rn, index, size),
6632                          is_q ? 16 : 8, vec_full_reg_size(s));
6633 }
6634
6635 /* DUP (element, scalar)
6636  *  31                   21 20    16 15        10  9    5 4    0
6637  * +-----------------------+--------+-------------+------+------+
6638  * | 0 1 0 1 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
6639  * +-----------------------+--------+-------------+------+------+
6640  */
6641 static void handle_simd_dupes(DisasContext *s, int rd, int rn,
6642                               int imm5)
6643 {
6644     int size = ctz32(imm5);
6645     int index;
6646     TCGv_i64 tmp;
6647
6648     if (size > 3) {
6649         unallocated_encoding(s);
6650         return;
6651     }
6652
6653     if (!fp_access_check(s)) {
6654         return;
6655     }
6656
6657     index = imm5 >> (size + 1);
6658
6659     /* This instruction just extracts the specified element and
6660      * zero-extends it into the bottom of the destination register.
6661      */
6662     tmp = tcg_temp_new_i64();
6663     read_vec_element(s, tmp, rn, index, size);
6664     write_fp_dreg(s, rd, tmp);
6665     tcg_temp_free_i64(tmp);
6666 }
6667
6668 /* DUP (General)
6669  *
6670  *  31  30   29              21 20    16 15        10  9    5 4    0
6671  * +---+---+-------------------+--------+-------------+------+------+
6672  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 1 1 |  Rn  |  Rd  |
6673  * +---+---+-------------------+--------+-------------+------+------+
6674  *
6675  * size: encoded in imm5 (see ARM ARM LowestSetBit())
6676  */
6677 static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn,
6678                              int imm5)
6679 {
6680     int size = ctz32(imm5);
6681     uint32_t dofs, oprsz, maxsz;
6682
6683     if (size > 3 || ((size == 3) && !is_q)) {
6684         unallocated_encoding(s);
6685         return;
6686     }
6687
6688     if (!fp_access_check(s)) {
6689         return;
6690     }
6691
6692     dofs = vec_full_reg_offset(s, rd);
6693     oprsz = is_q ? 16 : 8;
6694     maxsz = vec_full_reg_size(s);
6695
6696     tcg_gen_gvec_dup_i64(size, dofs, oprsz, maxsz, cpu_reg(s, rn));
6697 }
6698
6699 /* INS (Element)
6700  *
6701  *  31                   21 20    16 15  14    11  10 9    5 4    0
6702  * +-----------------------+--------+------------+---+------+------+
6703  * | 0 1 1 0 1 1 1 0 0 0 0 |  imm5  | 0 |  imm4  | 1 |  Rn  |  Rd  |
6704  * +-----------------------+--------+------------+---+------+------+
6705  *
6706  * size: encoded in imm5 (see ARM ARM LowestSetBit())
6707  * index: encoded in imm5<4:size+1>
6708  */
6709 static void handle_simd_inse(DisasContext *s, int rd, int rn,
6710                              int imm4, int imm5)
6711 {
6712     int size = ctz32(imm5);
6713     int src_index, dst_index;
6714     TCGv_i64 tmp;
6715
6716     if (size > 3) {
6717         unallocated_encoding(s);
6718         return;
6719     }
6720
6721     if (!fp_access_check(s)) {
6722         return;
6723     }
6724
6725     dst_index = extract32(imm5, 1+size, 5);
6726     src_index = extract32(imm4, size, 4);
6727
6728     tmp = tcg_temp_new_i64();
6729
6730     read_vec_element(s, tmp, rn, src_index, size);
6731     write_vec_element(s, tmp, rd, dst_index, size);
6732
6733     tcg_temp_free_i64(tmp);
6734 }
6735
6736
6737 /* INS (General)
6738  *
6739  *  31                   21 20    16 15        10  9    5 4    0
6740  * +-----------------------+--------+-------------+------+------+
6741  * | 0 1 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 1 1 1 |  Rn  |  Rd  |
6742  * +-----------------------+--------+-------------+------+------+
6743  *
6744  * size: encoded in imm5 (see ARM ARM LowestSetBit())
6745  * index: encoded in imm5<4:size+1>
6746  */
6747 static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
6748 {
6749     int size = ctz32(imm5);
6750     int idx;
6751
6752     if (size > 3) {
6753         unallocated_encoding(s);
6754         return;
6755     }
6756
6757     if (!fp_access_check(s)) {
6758         return;
6759     }
6760
6761     idx = extract32(imm5, 1 + size, 4 - size);
6762     write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
6763 }
6764
6765 /*
6766  * UMOV (General)
6767  * SMOV (General)
6768  *
6769  *  31  30   29              21 20    16 15    12   10 9    5 4    0
6770  * +---+---+-------------------+--------+-------------+------+------+
6771  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 1 U 1 1 |  Rn  |  Rd  |
6772  * +---+---+-------------------+--------+-------------+------+------+
6773  *
6774  * U: unsigned when set
6775  * size: encoded in imm5 (see ARM ARM LowestSetBit())
6776  */
6777 static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed,
6778                                   int rn, int rd, int imm5)
6779 {
6780     int size = ctz32(imm5);
6781     int element;
6782     TCGv_i64 tcg_rd;
6783
6784     /* Check for UnallocatedEncodings */
6785     if (is_signed) {
6786         if (size > 2 || (size == 2 && !is_q)) {
6787             unallocated_encoding(s);
6788             return;
6789         }
6790     } else {
6791         if (size > 3
6792             || (size < 3 && is_q)
6793             || (size == 3 && !is_q)) {
6794             unallocated_encoding(s);
6795             return;
6796         }
6797     }
6798
6799     if (!fp_access_check(s)) {
6800         return;
6801     }
6802
6803     element = extract32(imm5, 1+size, 4);
6804
6805     tcg_rd = cpu_reg(s, rd);
6806     read_vec_element(s, tcg_rd, rn, element, size | (is_signed ? MO_SIGN : 0));
6807     if (is_signed && !is_q) {
6808         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
6809     }
6810 }
6811
6812 /* AdvSIMD copy
6813  *   31  30  29  28             21 20  16 15  14  11 10  9    5 4    0
6814  * +---+---+----+-----------------+------+---+------+---+------+------+
6815  * | 0 | Q | op | 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
6816  * +---+---+----+-----------------+------+---+------+---+------+------+
6817  */
6818 static void disas_simd_copy(DisasContext *s, uint32_t insn)
6819 {
6820     int rd = extract32(insn, 0, 5);
6821     int rn = extract32(insn, 5, 5);
6822     int imm4 = extract32(insn, 11, 4);
6823     int op = extract32(insn, 29, 1);
6824     int is_q = extract32(insn, 30, 1);
6825     int imm5 = extract32(insn, 16, 5);
6826
6827     if (op) {
6828         if (is_q) {
6829             /* INS (element) */
6830             handle_simd_inse(s, rd, rn, imm4, imm5);
6831         } else {
6832             unallocated_encoding(s);
6833         }
6834     } else {
6835         switch (imm4) {
6836         case 0:
6837             /* DUP (element - vector) */
6838             handle_simd_dupe(s, is_q, rd, rn, imm5);
6839             break;
6840         case 1:
6841             /* DUP (general) */
6842             handle_simd_dupg(s, is_q, rd, rn, imm5);
6843             break;
6844         case 3:
6845             if (is_q) {
6846                 /* INS (general) */
6847                 handle_simd_insg(s, rd, rn, imm5);
6848             } else {
6849                 unallocated_encoding(s);
6850             }
6851             break;
6852         case 5:
6853         case 7:
6854             /* UMOV/SMOV (is_q indicates 32/64; imm4 indicates signedness) */
6855             handle_simd_umov_smov(s, is_q, (imm4 == 5), rn, rd, imm5);
6856             break;
6857         default:
6858             unallocated_encoding(s);
6859             break;
6860         }
6861     }
6862 }
6863
6864 /* AdvSIMD modified immediate
6865  *  31  30   29  28                 19 18 16 15   12  11  10  9     5 4    0
6866  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
6867  * | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh |  Rd  |
6868  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
6869  *
6870  * There are a number of operations that can be carried out here:
6871  *   MOVI - move (shifted) imm into register
6872  *   MVNI - move inverted (shifted) imm into register
6873  *   ORR  - bitwise OR of (shifted) imm with register
6874  *   BIC  - bitwise clear of (shifted) imm with register
6875  * With ARMv8.2 we also have:
6876  *   FMOV half-precision
6877  */
6878 static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
6879 {
6880     int rd = extract32(insn, 0, 5);
6881     int cmode = extract32(insn, 12, 4);
6882     int cmode_3_1 = extract32(cmode, 1, 3);
6883     int cmode_0 = extract32(cmode, 0, 1);
6884     int o2 = extract32(insn, 11, 1);
6885     uint64_t abcdefgh = extract32(insn, 5, 5) | (extract32(insn, 16, 3) << 5);
6886     bool is_neg = extract32(insn, 29, 1);
6887     bool is_q = extract32(insn, 30, 1);
6888     uint64_t imm = 0;
6889
6890     if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {
6891         /* Check for FMOV (vector, immediate) - half-precision */
6892         if (!(arm_dc_feature(s, ARM_FEATURE_V8_FP16) && o2 && cmode == 0xf)) {
6893             unallocated_encoding(s);
6894             return;
6895         }
6896     }
6897
6898     if (!fp_access_check(s)) {
6899         return;
6900     }
6901
6902     /* See AdvSIMDExpandImm() in ARM ARM */
6903     switch (cmode_3_1) {
6904     case 0: /* Replicate(Zeros(24):imm8, 2) */
6905     case 1: /* Replicate(Zeros(16):imm8:Zeros(8), 2) */
6906     case 2: /* Replicate(Zeros(8):imm8:Zeros(16), 2) */
6907     case 3: /* Replicate(imm8:Zeros(24), 2) */
6908     {
6909         int shift = cmode_3_1 * 8;
6910         imm = bitfield_replicate(abcdefgh << shift, 32);
6911         break;
6912     }
6913     case 4: /* Replicate(Zeros(8):imm8, 4) */
6914     case 5: /* Replicate(imm8:Zeros(8), 4) */
6915     {
6916         int shift = (cmode_3_1 & 0x1) * 8;
6917         imm = bitfield_replicate(abcdefgh << shift, 16);
6918         break;
6919     }
6920     case 6:
6921         if (cmode_0) {
6922             /* Replicate(Zeros(8):imm8:Ones(16), 2) */
6923             imm = (abcdefgh << 16) | 0xffff;
6924         } else {
6925             /* Replicate(Zeros(16):imm8:Ones(8), 2) */
6926             imm = (abcdefgh << 8) | 0xff;
6927         }
6928         imm = bitfield_replicate(imm, 32);
6929         break;
6930     case 7:
6931         if (!cmode_0 && !is_neg) {
6932             imm = bitfield_replicate(abcdefgh, 8);
6933         } else if (!cmode_0 && is_neg) {
6934             int i;
6935             imm = 0;
6936             for (i = 0; i < 8; i++) {
6937                 if ((abcdefgh) & (1 << i)) {
6938                     imm |= 0xffULL << (i * 8);
6939                 }
6940             }
6941         } else if (cmode_0) {
6942             if (is_neg) {
6943                 imm = (abcdefgh & 0x3f) << 48;
6944                 if (abcdefgh & 0x80) {
6945                     imm |= 0x8000000000000000ULL;
6946                 }
6947                 if (abcdefgh & 0x40) {
6948                     imm |= 0x3fc0000000000000ULL;
6949                 } else {
6950                     imm |= 0x4000000000000000ULL;
6951                 }
6952             } else {
6953                 if (o2) {
6954                     /* FMOV (vector, immediate) - half-precision */
6955                     imm = vfp_expand_imm(MO_16, abcdefgh);
6956                     /* now duplicate across the lanes */
6957                     imm = bitfield_replicate(imm, 16);
6958                 } else {
6959                     imm = (abcdefgh & 0x3f) << 19;
6960                     if (abcdefgh & 0x80) {
6961                         imm |= 0x80000000;
6962                     }
6963                     if (abcdefgh & 0x40) {
6964                         imm |= 0x3e000000;
6965                     } else {
6966                         imm |= 0x40000000;
6967                     }
6968                     imm |= (imm << 32);
6969                 }
6970             }
6971         }
6972         break;
6973     default:
6974         fprintf(stderr, "%s: cmode_3_1: %x\n", __func__, cmode_3_1);
6975         g_assert_not_reached();
6976     }
6977
6978     if (cmode_3_1 != 7 && is_neg) {
6979         imm = ~imm;
6980     }
6981
6982     if (!((cmode & 0x9) == 0x1 || (cmode & 0xd) == 0x9)) {
6983         /* MOVI or MVNI, with MVNI negation handled above.  */
6984         tcg_gen_gvec_dup64i(vec_full_reg_offset(s, rd), is_q ? 16 : 8,
6985                             vec_full_reg_size(s), imm);
6986     } else {
6987         /* ORR or BIC, with BIC negation to AND handled above.  */
6988         if (is_neg) {
6989             gen_gvec_fn2i(s, is_q, rd, rd, imm, tcg_gen_gvec_andi, MO_64);
6990         } else {
6991             gen_gvec_fn2i(s, is_q, rd, rd, imm, tcg_gen_gvec_ori, MO_64);
6992         }
6993     }
6994 }
6995
6996 /* AdvSIMD scalar copy
6997  *  31 30  29  28             21 20  16 15  14  11 10  9    5 4    0
6998  * +-----+----+-----------------+------+---+------+---+------+------+
6999  * | 0 1 | op | 1 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
7000  * +-----+----+-----------------+------+---+------+---+------+------+
7001  */
7002 static void disas_simd_scalar_copy(DisasContext *s, uint32_t insn)
7003 {
7004     int rd = extract32(insn, 0, 5);
7005     int rn = extract32(insn, 5, 5);
7006     int imm4 = extract32(insn, 11, 4);
7007     int imm5 = extract32(insn, 16, 5);
7008     int op = extract32(insn, 29, 1);
7009
7010     if (op != 0 || imm4 != 0) {
7011         unallocated_encoding(s);
7012         return;
7013     }
7014
7015     /* DUP (element, scalar) */
7016     handle_simd_dupes(s, rd, rn, imm5);
7017 }
7018
7019 /* AdvSIMD scalar pairwise
7020  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
7021  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7022  * | 0 1 | U | 1 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
7023  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7024  */
7025 static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
7026 {
7027     int u = extract32(insn, 29, 1);
7028     int size = extract32(insn, 22, 2);
7029     int opcode = extract32(insn, 12, 5);
7030     int rn = extract32(insn, 5, 5);
7031     int rd = extract32(insn, 0, 5);
7032     TCGv_ptr fpst;
7033
7034     /* For some ops (the FP ones), size[1] is part of the encoding.
7035      * For ADDP strictly it is not but size[1] is always 1 for valid
7036      * encodings.
7037      */
7038     opcode |= (extract32(size, 1, 1) << 5);
7039
7040     switch (opcode) {
7041     case 0x3b: /* ADDP */
7042         if (u || size != 3) {
7043             unallocated_encoding(s);
7044             return;
7045         }
7046         if (!fp_access_check(s)) {
7047             return;
7048         }
7049
7050         fpst = NULL;
7051         break;
7052     case 0xc: /* FMAXNMP */
7053     case 0xd: /* FADDP */
7054     case 0xf: /* FMAXP */
7055     case 0x2c: /* FMINNMP */
7056     case 0x2f: /* FMINP */
7057         /* FP op, size[0] is 32 or 64 bit*/
7058         if (!u) {
7059             if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
7060                 unallocated_encoding(s);
7061                 return;
7062             } else {
7063                 size = MO_16;
7064             }
7065         } else {
7066             size = extract32(size, 0, 1) ? MO_64 : MO_32;
7067         }
7068
7069         if (!fp_access_check(s)) {
7070             return;
7071         }
7072
7073         fpst = get_fpstatus_ptr(size == MO_16);
7074         break;
7075     default:
7076         unallocated_encoding(s);
7077         return;
7078     }
7079
7080     if (size == MO_64) {
7081         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
7082         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
7083         TCGv_i64 tcg_res = tcg_temp_new_i64();
7084
7085         read_vec_element(s, tcg_op1, rn, 0, MO_64);
7086         read_vec_element(s, tcg_op2, rn, 1, MO_64);
7087
7088         switch (opcode) {
7089         case 0x3b: /* ADDP */
7090             tcg_gen_add_i64(tcg_res, tcg_op1, tcg_op2);
7091             break;
7092         case 0xc: /* FMAXNMP */
7093             gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
7094             break;
7095         case 0xd: /* FADDP */
7096             gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
7097             break;
7098         case 0xf: /* FMAXP */
7099             gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
7100             break;
7101         case 0x2c: /* FMINNMP */
7102             gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
7103             break;
7104         case 0x2f: /* FMINP */
7105             gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
7106             break;
7107         default:
7108             g_assert_not_reached();
7109         }
7110
7111         write_fp_dreg(s, rd, tcg_res);
7112
7113         tcg_temp_free_i64(tcg_op1);
7114         tcg_temp_free_i64(tcg_op2);
7115         tcg_temp_free_i64(tcg_res);
7116     } else {
7117         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
7118         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
7119         TCGv_i32 tcg_res = tcg_temp_new_i32();
7120
7121         read_vec_element_i32(s, tcg_op1, rn, 0, size);
7122         read_vec_element_i32(s, tcg_op2, rn, 1, size);
7123
7124         if (size == MO_16) {
7125             switch (opcode) {
7126             case 0xc: /* FMAXNMP */
7127                 gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
7128                 break;
7129             case 0xd: /* FADDP */
7130                 gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
7131                 break;
7132             case 0xf: /* FMAXP */
7133                 gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
7134                 break;
7135             case 0x2c: /* FMINNMP */
7136                 gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
7137                 break;
7138             case 0x2f: /* FMINP */
7139                 gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
7140                 break;
7141             default:
7142                 g_assert_not_reached();
7143             }
7144         } else {
7145             switch (opcode) {
7146             case 0xc: /* FMAXNMP */
7147                 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
7148                 break;
7149             case 0xd: /* FADDP */
7150                 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
7151                 break;
7152             case 0xf: /* FMAXP */
7153                 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
7154                 break;
7155             case 0x2c: /* FMINNMP */
7156                 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
7157                 break;
7158             case 0x2f: /* FMINP */
7159                 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
7160                 break;
7161             default:
7162                 g_assert_not_reached();
7163             }
7164         }
7165
7166         write_fp_sreg(s, rd, tcg_res);
7167
7168         tcg_temp_free_i32(tcg_op1);
7169         tcg_temp_free_i32(tcg_op2);
7170         tcg_temp_free_i32(tcg_res);
7171     }
7172
7173     if (fpst) {
7174         tcg_temp_free_ptr(fpst);
7175     }
7176 }
7177
7178 /*
7179  * Common SSHR[RA]/USHR[RA] - Shift right (optional rounding/accumulate)
7180  *
7181  * This code is handles the common shifting code and is used by both
7182  * the vector and scalar code.
7183  */
7184 static void handle_shri_with_rndacc(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
7185                                     TCGv_i64 tcg_rnd, bool accumulate,
7186                                     bool is_u, int size, int shift)
7187 {
7188     bool extended_result = false;
7189     bool round = tcg_rnd != NULL;
7190     int ext_lshift = 0;
7191     TCGv_i64 tcg_src_hi;
7192
7193     if (round && size == 3) {
7194         extended_result = true;
7195         ext_lshift = 64 - shift;
7196         tcg_src_hi = tcg_temp_new_i64();
7197     } else if (shift == 64) {
7198         if (!accumulate && is_u) {
7199             /* result is zero */
7200             tcg_gen_movi_i64(tcg_res, 0);
7201             return;
7202         }
7203     }
7204
7205     /* Deal with the rounding step */
7206     if (round) {
7207         if (extended_result) {
7208             TCGv_i64 tcg_zero = tcg_const_i64(0);
7209             if (!is_u) {
7210                 /* take care of sign extending tcg_res */
7211                 tcg_gen_sari_i64(tcg_src_hi, tcg_src, 63);
7212                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
7213                                  tcg_src, tcg_src_hi,
7214                                  tcg_rnd, tcg_zero);
7215             } else {
7216                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
7217                                  tcg_src, tcg_zero,
7218                                  tcg_rnd, tcg_zero);
7219             }
7220             tcg_temp_free_i64(tcg_zero);
7221         } else {
7222             tcg_gen_add_i64(tcg_src, tcg_src, tcg_rnd);
7223         }
7224     }
7225
7226     /* Now do the shift right */
7227     if (round && extended_result) {
7228         /* extended case, >64 bit precision required */
7229         if (ext_lshift == 0) {
7230             /* special case, only high bits matter */
7231             tcg_gen_mov_i64(tcg_src, tcg_src_hi);
7232         } else {
7233             tcg_gen_shri_i64(tcg_src, tcg_src, shift);
7234             tcg_gen_shli_i64(tcg_src_hi, tcg_src_hi, ext_lshift);
7235             tcg_gen_or_i64(tcg_src, tcg_src, tcg_src_hi);
7236         }
7237     } else {
7238         if (is_u) {
7239             if (shift == 64) {
7240                 /* essentially shifting in 64 zeros */
7241                 tcg_gen_movi_i64(tcg_src, 0);
7242             } else {
7243                 tcg_gen_shri_i64(tcg_src, tcg_src, shift);
7244             }
7245         } else {
7246             if (shift == 64) {
7247                 /* effectively extending the sign-bit */
7248                 tcg_gen_sari_i64(tcg_src, tcg_src, 63);
7249             } else {
7250                 tcg_gen_sari_i64(tcg_src, tcg_src, shift);
7251             }
7252         }
7253     }
7254
7255     if (accumulate) {
7256         tcg_gen_add_i64(tcg_res, tcg_res, tcg_src);
7257     } else {
7258         tcg_gen_mov_i64(tcg_res, tcg_src);
7259     }
7260
7261     if (extended_result) {
7262         tcg_temp_free_i64(tcg_src_hi);
7263     }
7264 }
7265
7266 /* SSHR[RA]/USHR[RA] - Scalar shift right (optional rounding/accumulate) */
7267 static void handle_scalar_simd_shri(DisasContext *s,
7268                                     bool is_u, int immh, int immb,
7269                                     int opcode, int rn, int rd)
7270 {
7271     const int size = 3;
7272     int immhb = immh << 3 | immb;
7273     int shift = 2 * (8 << size) - immhb;
7274     bool accumulate = false;
7275     bool round = false;
7276     bool insert = false;
7277     TCGv_i64 tcg_rn;
7278     TCGv_i64 tcg_rd;
7279     TCGv_i64 tcg_round;
7280
7281     if (!extract32(immh, 3, 1)) {
7282         unallocated_encoding(s);
7283         return;
7284     }
7285
7286     if (!fp_access_check(s)) {
7287         return;
7288     }
7289
7290     switch (opcode) {
7291     case 0x02: /* SSRA / USRA (accumulate) */
7292         accumulate = true;
7293         break;
7294     case 0x04: /* SRSHR / URSHR (rounding) */
7295         round = true;
7296         break;
7297     case 0x06: /* SRSRA / URSRA (accum + rounding) */
7298         accumulate = round = true;
7299         break;
7300     case 0x08: /* SRI */
7301         insert = true;
7302         break;
7303     }
7304
7305     if (round) {
7306         uint64_t round_const = 1ULL << (shift - 1);
7307         tcg_round = tcg_const_i64(round_const);
7308     } else {
7309         tcg_round = NULL;
7310     }
7311
7312     tcg_rn = read_fp_dreg(s, rn);
7313     tcg_rd = (accumulate || insert) ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
7314
7315     if (insert) {
7316         /* shift count same as element size is valid but does nothing;
7317          * special case to avoid potential shift by 64.
7318          */
7319         int esize = 8 << size;
7320         if (shift != esize) {
7321             tcg_gen_shri_i64(tcg_rn, tcg_rn, shift);
7322             tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, 0, esize - shift);
7323         }
7324     } else {
7325         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
7326                                 accumulate, is_u, size, shift);
7327     }
7328
7329     write_fp_dreg(s, rd, tcg_rd);
7330
7331     tcg_temp_free_i64(tcg_rn);
7332     tcg_temp_free_i64(tcg_rd);
7333     if (round) {
7334         tcg_temp_free_i64(tcg_round);
7335     }
7336 }
7337
7338 /* SHL/SLI - Scalar shift left */
7339 static void handle_scalar_simd_shli(DisasContext *s, bool insert,
7340                                     int immh, int immb, int opcode,
7341                                     int rn, int rd)
7342 {
7343     int size = 32 - clz32(immh) - 1;
7344     int immhb = immh << 3 | immb;
7345     int shift = immhb - (8 << size);
7346     TCGv_i64 tcg_rn = new_tmp_a64(s);
7347     TCGv_i64 tcg_rd = new_tmp_a64(s);
7348
7349     if (!extract32(immh, 3, 1)) {
7350         unallocated_encoding(s);
7351         return;
7352     }
7353
7354     if (!fp_access_check(s)) {
7355         return;
7356     }
7357
7358     tcg_rn = read_fp_dreg(s, rn);
7359     tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
7360
7361     if (insert) {
7362         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, shift, 64 - shift);
7363     } else {
7364         tcg_gen_shli_i64(tcg_rd, tcg_rn, shift);
7365     }
7366
7367     write_fp_dreg(s, rd, tcg_rd);
7368
7369     tcg_temp_free_i64(tcg_rn);
7370     tcg_temp_free_i64(tcg_rd);
7371 }
7372
7373 /* SQSHRN/SQSHRUN - Saturating (signed/unsigned) shift right with
7374  * (signed/unsigned) narrowing */
7375 static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
7376                                    bool is_u_shift, bool is_u_narrow,
7377                                    int immh, int immb, int opcode,
7378                                    int rn, int rd)
7379 {
7380     int immhb = immh << 3 | immb;
7381     int size = 32 - clz32(immh) - 1;
7382     int esize = 8 << size;
7383     int shift = (2 * esize) - immhb;
7384     int elements = is_scalar ? 1 : (64 / esize);
7385     bool round = extract32(opcode, 0, 1);
7386     TCGMemOp ldop = (size + 1) | (is_u_shift ? 0 : MO_SIGN);
7387     TCGv_i64 tcg_rn, tcg_rd, tcg_round;
7388     TCGv_i32 tcg_rd_narrowed;
7389     TCGv_i64 tcg_final;
7390
7391     static NeonGenNarrowEnvFn * const signed_narrow_fns[4][2] = {
7392         { gen_helper_neon_narrow_sat_s8,
7393           gen_helper_neon_unarrow_sat8 },
7394         { gen_helper_neon_narrow_sat_s16,
7395           gen_helper_neon_unarrow_sat16 },
7396         { gen_helper_neon_narrow_sat_s32,
7397           gen_helper_neon_unarrow_sat32 },
7398         { NULL, NULL },
7399     };
7400     static NeonGenNarrowEnvFn * const unsigned_narrow_fns[4] = {
7401         gen_helper_neon_narrow_sat_u8,
7402         gen_helper_neon_narrow_sat_u16,
7403         gen_helper_neon_narrow_sat_u32,
7404         NULL
7405     };
7406     NeonGenNarrowEnvFn *narrowfn;
7407
7408     int i;
7409
7410     assert(size < 4);
7411
7412     if (extract32(immh, 3, 1)) {
7413         unallocated_encoding(s);
7414         return;
7415     }
7416
7417     if (!fp_access_check(s)) {
7418         return;
7419     }
7420
7421     if (is_u_shift) {
7422         narrowfn = unsigned_narrow_fns[size];
7423     } else {
7424         narrowfn = signed_narrow_fns[size][is_u_narrow ? 1 : 0];
7425     }
7426
7427     tcg_rn = tcg_temp_new_i64();
7428     tcg_rd = tcg_temp_new_i64();
7429     tcg_rd_narrowed = tcg_temp_new_i32();
7430     tcg_final = tcg_const_i64(0);
7431
7432     if (round) {
7433         uint64_t round_const = 1ULL << (shift - 1);
7434         tcg_round = tcg_const_i64(round_const);
7435     } else {
7436         tcg_round = NULL;
7437     }
7438
7439     for (i = 0; i < elements; i++) {
7440         read_vec_element(s, tcg_rn, rn, i, ldop);
7441         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
7442                                 false, is_u_shift, size+1, shift);
7443         narrowfn(tcg_rd_narrowed, cpu_env, tcg_rd);
7444         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd_narrowed);
7445         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
7446     }
7447
7448     if (!is_q) {
7449         write_vec_element(s, tcg_final, rd, 0, MO_64);
7450     } else {
7451         write_vec_element(s, tcg_final, rd, 1, MO_64);
7452     }
7453
7454     if (round) {
7455         tcg_temp_free_i64(tcg_round);
7456     }
7457     tcg_temp_free_i64(tcg_rn);
7458     tcg_temp_free_i64(tcg_rd);
7459     tcg_temp_free_i32(tcg_rd_narrowed);
7460     tcg_temp_free_i64(tcg_final);
7461
7462     clear_vec_high(s, is_q, rd);
7463 }
7464
7465 /* SQSHLU, UQSHL, SQSHL: saturating left shifts */
7466 static void handle_simd_qshl(DisasContext *s, bool scalar, bool is_q,
7467                              bool src_unsigned, bool dst_unsigned,
7468                              int immh, int immb, int rn, int rd)
7469 {
7470     int immhb = immh << 3 | immb;
7471     int size = 32 - clz32(immh) - 1;
7472     int shift = immhb - (8 << size);
7473     int pass;
7474
7475     assert(immh != 0);
7476     assert(!(scalar && is_q));
7477
7478     if (!scalar) {
7479         if (!is_q && extract32(immh, 3, 1)) {
7480             unallocated_encoding(s);
7481             return;
7482         }
7483
7484         /* Since we use the variable-shift helpers we must
7485          * replicate the shift count into each element of
7486          * the tcg_shift value.
7487          */
7488         switch (size) {
7489         case 0:
7490             shift |= shift << 8;
7491             /* fall through */
7492         case 1:
7493             shift |= shift << 16;
7494             break;
7495         case 2:
7496         case 3:
7497             break;
7498         default:
7499             g_assert_not_reached();
7500         }
7501     }
7502
7503     if (!fp_access_check(s)) {
7504         return;
7505     }
7506
7507     if (size == 3) {
7508         TCGv_i64 tcg_shift = tcg_const_i64(shift);
7509         static NeonGenTwo64OpEnvFn * const fns[2][2] = {
7510             { gen_helper_neon_qshl_s64, gen_helper_neon_qshlu_s64 },
7511             { NULL, gen_helper_neon_qshl_u64 },
7512         };
7513         NeonGenTwo64OpEnvFn *genfn = fns[src_unsigned][dst_unsigned];
7514         int maxpass = is_q ? 2 : 1;
7515
7516         for (pass = 0; pass < maxpass; pass++) {
7517             TCGv_i64 tcg_op = tcg_temp_new_i64();
7518
7519             read_vec_element(s, tcg_op, rn, pass, MO_64);
7520             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
7521             write_vec_element(s, tcg_op, rd, pass, MO_64);
7522
7523             tcg_temp_free_i64(tcg_op);
7524         }
7525         tcg_temp_free_i64(tcg_shift);
7526         clear_vec_high(s, is_q, rd);
7527     } else {
7528         TCGv_i32 tcg_shift = tcg_const_i32(shift);
7529         static NeonGenTwoOpEnvFn * const fns[2][2][3] = {
7530             {
7531                 { gen_helper_neon_qshl_s8,
7532                   gen_helper_neon_qshl_s16,
7533                   gen_helper_neon_qshl_s32 },
7534                 { gen_helper_neon_qshlu_s8,
7535                   gen_helper_neon_qshlu_s16,
7536                   gen_helper_neon_qshlu_s32 }
7537             }, {
7538                 { NULL, NULL, NULL },
7539                 { gen_helper_neon_qshl_u8,
7540                   gen_helper_neon_qshl_u16,
7541                   gen_helper_neon_qshl_u32 }
7542             }
7543         };
7544         NeonGenTwoOpEnvFn *genfn = fns[src_unsigned][dst_unsigned][size];
7545         TCGMemOp memop = scalar ? size : MO_32;
7546         int maxpass = scalar ? 1 : is_q ? 4 : 2;
7547
7548         for (pass = 0; pass < maxpass; pass++) {
7549             TCGv_i32 tcg_op = tcg_temp_new_i32();
7550
7551             read_vec_element_i32(s, tcg_op, rn, pass, memop);
7552             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
7553             if (scalar) {
7554                 switch (size) {
7555                 case 0:
7556                     tcg_gen_ext8u_i32(tcg_op, tcg_op);
7557                     break;
7558                 case 1:
7559                     tcg_gen_ext16u_i32(tcg_op, tcg_op);
7560                     break;
7561                 case 2:
7562                     break;
7563                 default:
7564                     g_assert_not_reached();
7565                 }
7566                 write_fp_sreg(s, rd, tcg_op);
7567             } else {
7568                 write_vec_element_i32(s, tcg_op, rd, pass, MO_32);
7569             }
7570
7571             tcg_temp_free_i32(tcg_op);
7572         }
7573         tcg_temp_free_i32(tcg_shift);
7574
7575         if (!scalar) {
7576             clear_vec_high(s, is_q, rd);
7577         }
7578     }
7579 }
7580
7581 /* Common vector code for handling integer to FP conversion */
7582 static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
7583                                    int elements, int is_signed,
7584                                    int fracbits, int size)
7585 {
7586     TCGv_ptr tcg_fpst = get_fpstatus_ptr(size == MO_16);
7587     TCGv_i32 tcg_shift = NULL;
7588
7589     TCGMemOp mop = size | (is_signed ? MO_SIGN : 0);
7590     int pass;
7591
7592     if (fracbits || size == MO_64) {
7593         tcg_shift = tcg_const_i32(fracbits);
7594     }
7595
7596     if (size == MO_64) {
7597         TCGv_i64 tcg_int64 = tcg_temp_new_i64();
7598         TCGv_i64 tcg_double = tcg_temp_new_i64();
7599
7600         for (pass = 0; pass < elements; pass++) {
7601             read_vec_element(s, tcg_int64, rn, pass, mop);
7602
7603             if (is_signed) {
7604                 gen_helper_vfp_sqtod(tcg_double, tcg_int64,
7605                                      tcg_shift, tcg_fpst);
7606             } else {
7607                 gen_helper_vfp_uqtod(tcg_double, tcg_int64,
7608                                      tcg_shift, tcg_fpst);
7609             }
7610             if (elements == 1) {
7611                 write_fp_dreg(s, rd, tcg_double);
7612             } else {
7613                 write_vec_element(s, tcg_double, rd, pass, MO_64);
7614             }
7615         }
7616
7617         tcg_temp_free_i64(tcg_int64);
7618         tcg_temp_free_i64(tcg_double);
7619
7620     } else {
7621         TCGv_i32 tcg_int32 = tcg_temp_new_i32();
7622         TCGv_i32 tcg_float = tcg_temp_new_i32();
7623
7624         for (pass = 0; pass < elements; pass++) {
7625             read_vec_element_i32(s, tcg_int32, rn, pass, mop);
7626
7627             switch (size) {
7628             case MO_32:
7629                 if (fracbits) {
7630                     if (is_signed) {
7631                         gen_helper_vfp_sltos(tcg_float, tcg_int32,
7632                                              tcg_shift, tcg_fpst);
7633                     } else {
7634                         gen_helper_vfp_ultos(tcg_float, tcg_int32,
7635                                              tcg_shift, tcg_fpst);
7636                     }
7637                 } else {
7638                     if (is_signed) {
7639                         gen_helper_vfp_sitos(tcg_float, tcg_int32, tcg_fpst);
7640                     } else {
7641                         gen_helper_vfp_uitos(tcg_float, tcg_int32, tcg_fpst);
7642                     }
7643                 }
7644                 break;
7645             case MO_16:
7646                 if (fracbits) {
7647                     if (is_signed) {
7648                         gen_helper_vfp_sltoh(tcg_float, tcg_int32,
7649                                              tcg_shift, tcg_fpst);
7650                     } else {
7651                         gen_helper_vfp_ultoh(tcg_float, tcg_int32,
7652                                              tcg_shift, tcg_fpst);
7653                     }
7654                 } else {
7655                     if (is_signed) {
7656                         gen_helper_vfp_sitoh(tcg_float, tcg_int32, tcg_fpst);
7657                     } else {
7658                         gen_helper_vfp_uitoh(tcg_float, tcg_int32, tcg_fpst);
7659                     }
7660                 }
7661                 break;
7662             default:
7663                 g_assert_not_reached();
7664             }
7665
7666             if (elements == 1) {
7667                 write_fp_sreg(s, rd, tcg_float);
7668             } else {
7669                 write_vec_element_i32(s, tcg_float, rd, pass, size);
7670             }
7671         }
7672
7673         tcg_temp_free_i32(tcg_int32);
7674         tcg_temp_free_i32(tcg_float);
7675     }
7676
7677     tcg_temp_free_ptr(tcg_fpst);
7678     if (tcg_shift) {
7679         tcg_temp_free_i32(tcg_shift);
7680     }
7681
7682     clear_vec_high(s, elements << size == 16, rd);
7683 }
7684
7685 /* UCVTF/SCVTF - Integer to FP conversion */
7686 static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
7687                                          bool is_q, bool is_u,
7688                                          int immh, int immb, int opcode,
7689                                          int rn, int rd)
7690 {
7691     int size, elements, fracbits;
7692     int immhb = immh << 3 | immb;
7693
7694     if (immh & 8) {
7695         size = MO_64;
7696         if (!is_scalar && !is_q) {
7697             unallocated_encoding(s);
7698             return;
7699         }
7700     } else if (immh & 4) {
7701         size = MO_32;
7702     } else if (immh & 2) {
7703         size = MO_16;
7704         if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
7705             unallocated_encoding(s);
7706             return;
7707         }
7708     } else {
7709         /* immh == 0 would be a failure of the decode logic */
7710         g_assert(immh == 1);
7711         unallocated_encoding(s);
7712         return;
7713     }
7714
7715     if (is_scalar) {
7716         elements = 1;
7717     } else {
7718         elements = (8 << is_q) >> size;
7719     }
7720     fracbits = (16 << size) - immhb;
7721
7722     if (!fp_access_check(s)) {
7723         return;
7724     }
7725
7726     handle_simd_intfp_conv(s, rd, rn, elements, !is_u, fracbits, size);
7727 }
7728
7729 /* FCVTZS, FVCVTZU - FP to fixedpoint conversion */
7730 static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
7731                                          bool is_q, bool is_u,
7732                                          int immh, int immb, int rn, int rd)
7733 {
7734     int immhb = immh << 3 | immb;
7735     int pass, size, fracbits;
7736     TCGv_ptr tcg_fpstatus;
7737     TCGv_i32 tcg_rmode, tcg_shift;
7738
7739     if (immh & 0x8) {
7740         size = MO_64;
7741         if (!is_scalar && !is_q) {
7742             unallocated_encoding(s);
7743             return;
7744         }
7745     } else if (immh & 0x4) {
7746         size = MO_32;
7747     } else if (immh & 0x2) {
7748         size = MO_16;
7749         if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
7750             unallocated_encoding(s);
7751             return;
7752         }
7753     } else {
7754         /* Should have split out AdvSIMD modified immediate earlier.  */
7755         assert(immh == 1);
7756         unallocated_encoding(s);
7757         return;
7758     }
7759
7760     if (!fp_access_check(s)) {
7761         return;
7762     }
7763
7764     assert(!(is_scalar && is_q));
7765
7766     tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
7767     tcg_fpstatus = get_fpstatus_ptr(size == MO_16);
7768     gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
7769     fracbits = (16 << size) - immhb;
7770     tcg_shift = tcg_const_i32(fracbits);
7771
7772     if (size == MO_64) {
7773         int maxpass = is_scalar ? 1 : 2;
7774
7775         for (pass = 0; pass < maxpass; pass++) {
7776             TCGv_i64 tcg_op = tcg_temp_new_i64();
7777
7778             read_vec_element(s, tcg_op, rn, pass, MO_64);
7779             if (is_u) {
7780                 gen_helper_vfp_touqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
7781             } else {
7782                 gen_helper_vfp_tosqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
7783             }
7784             write_vec_element(s, tcg_op, rd, pass, MO_64);
7785             tcg_temp_free_i64(tcg_op);
7786         }
7787         clear_vec_high(s, is_q, rd);
7788     } else {
7789         void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
7790         int maxpass = is_scalar ? 1 : ((8 << is_q) >> size);
7791
7792         switch (size) {
7793         case MO_16:
7794             if (is_u) {
7795                 fn = gen_helper_vfp_touhh;
7796             } else {
7797                 fn = gen_helper_vfp_toshh;
7798             }
7799             break;
7800         case MO_32:
7801             if (is_u) {
7802                 fn = gen_helper_vfp_touls;
7803             } else {
7804                 fn = gen_helper_vfp_tosls;
7805             }
7806             break;
7807         default:
7808             g_assert_not_reached();
7809         }
7810
7811         for (pass = 0; pass < maxpass; pass++) {
7812             TCGv_i32 tcg_op = tcg_temp_new_i32();
7813
7814             read_vec_element_i32(s, tcg_op, rn, pass, size);
7815             fn(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
7816             if (is_scalar) {
7817                 write_fp_sreg(s, rd, tcg_op);
7818             } else {
7819                 write_vec_element_i32(s, tcg_op, rd, pass, size);
7820             }
7821             tcg_temp_free_i32(tcg_op);
7822         }
7823         if (!is_scalar) {
7824             clear_vec_high(s, is_q, rd);
7825         }
7826     }
7827
7828     tcg_temp_free_ptr(tcg_fpstatus);
7829     tcg_temp_free_i32(tcg_shift);
7830     gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
7831     tcg_temp_free_i32(tcg_rmode);
7832 }
7833
7834 /* AdvSIMD scalar shift by immediate
7835  *  31 30  29 28         23 22  19 18  16 15    11  10 9    5 4    0
7836  * +-----+---+-------------+------+------+--------+---+------+------+
7837  * | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
7838  * +-----+---+-------------+------+------+--------+---+------+------+
7839  *
7840  * This is the scalar version so it works on a fixed sized registers
7841  */
7842 static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn)
7843 {
7844     int rd = extract32(insn, 0, 5);
7845     int rn = extract32(insn, 5, 5);
7846     int opcode = extract32(insn, 11, 5);
7847     int immb = extract32(insn, 16, 3);
7848     int immh = extract32(insn, 19, 4);
7849     bool is_u = extract32(insn, 29, 1);
7850
7851     if (immh == 0) {
7852         unallocated_encoding(s);
7853         return;
7854     }
7855
7856     switch (opcode) {
7857     case 0x08: /* SRI */
7858         if (!is_u) {
7859             unallocated_encoding(s);
7860             return;
7861         }
7862         /* fall through */
7863     case 0x00: /* SSHR / USHR */
7864     case 0x02: /* SSRA / USRA */
7865     case 0x04: /* SRSHR / URSHR */
7866     case 0x06: /* SRSRA / URSRA */
7867         handle_scalar_simd_shri(s, is_u, immh, immb, opcode, rn, rd);
7868         break;
7869     case 0x0a: /* SHL / SLI */
7870         handle_scalar_simd_shli(s, is_u, immh, immb, opcode, rn, rd);
7871         break;
7872     case 0x1c: /* SCVTF, UCVTF */
7873         handle_simd_shift_intfp_conv(s, true, false, is_u, immh, immb,
7874                                      opcode, rn, rd);
7875         break;
7876     case 0x10: /* SQSHRUN, SQSHRUN2 */
7877     case 0x11: /* SQRSHRUN, SQRSHRUN2 */
7878         if (!is_u) {
7879             unallocated_encoding(s);
7880             return;
7881         }
7882         handle_vec_simd_sqshrn(s, true, false, false, true,
7883                                immh, immb, opcode, rn, rd);
7884         break;
7885     case 0x12: /* SQSHRN, SQSHRN2, UQSHRN */
7886     case 0x13: /* SQRSHRN, SQRSHRN2, UQRSHRN, UQRSHRN2 */
7887         handle_vec_simd_sqshrn(s, true, false, is_u, is_u,
7888                                immh, immb, opcode, rn, rd);
7889         break;
7890     case 0xc: /* SQSHLU */
7891         if (!is_u) {
7892             unallocated_encoding(s);
7893             return;
7894         }
7895         handle_simd_qshl(s, true, false, false, true, immh, immb, rn, rd);
7896         break;
7897     case 0xe: /* SQSHL, UQSHL */
7898         handle_simd_qshl(s, true, false, is_u, is_u, immh, immb, rn, rd);
7899         break;
7900     case 0x1f: /* FCVTZS, FCVTZU */
7901         handle_simd_shift_fpint_conv(s, true, false, is_u, immh, immb, rn, rd);
7902         break;
7903     default:
7904         unallocated_encoding(s);
7905         break;
7906     }
7907 }
7908
7909 /* AdvSIMD scalar three different
7910  *  31 30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
7911  * +-----+---+-----------+------+---+------+--------+-----+------+------+
7912  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
7913  * +-----+---+-----------+------+---+------+--------+-----+------+------+
7914  */
7915 static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
7916 {
7917     bool is_u = extract32(insn, 29, 1);
7918     int size = extract32(insn, 22, 2);
7919     int opcode = extract32(insn, 12, 4);
7920     int rm = extract32(insn, 16, 5);
7921     int rn = extract32(insn, 5, 5);
7922     int rd = extract32(insn, 0, 5);
7923
7924     if (is_u) {
7925         unallocated_encoding(s);
7926         return;
7927     }
7928
7929     switch (opcode) {
7930     case 0x9: /* SQDMLAL, SQDMLAL2 */
7931     case 0xb: /* SQDMLSL, SQDMLSL2 */
7932     case 0xd: /* SQDMULL, SQDMULL2 */
7933         if (size == 0 || size == 3) {
7934             unallocated_encoding(s);
7935             return;
7936         }
7937         break;
7938     default:
7939         unallocated_encoding(s);
7940         return;
7941     }
7942
7943     if (!fp_access_check(s)) {
7944         return;
7945     }
7946
7947     if (size == 2) {
7948         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
7949         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
7950         TCGv_i64 tcg_res = tcg_temp_new_i64();
7951
7952         read_vec_element(s, tcg_op1, rn, 0, MO_32 | MO_SIGN);
7953         read_vec_element(s, tcg_op2, rm, 0, MO_32 | MO_SIGN);
7954
7955         tcg_gen_mul_i64(tcg_res, tcg_op1, tcg_op2);
7956         gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env, tcg_res, tcg_res);
7957
7958         switch (opcode) {
7959         case 0xd: /* SQDMULL, SQDMULL2 */
7960             break;
7961         case 0xb: /* SQDMLSL, SQDMLSL2 */
7962             tcg_gen_neg_i64(tcg_res, tcg_res);
7963             /* fall through */
7964         case 0x9: /* SQDMLAL, SQDMLAL2 */
7965             read_vec_element(s, tcg_op1, rd, 0, MO_64);
7966             gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env,
7967                                               tcg_res, tcg_op1);
7968             break;
7969         default:
7970             g_assert_not_reached();
7971         }
7972
7973         write_fp_dreg(s, rd, tcg_res);
7974
7975         tcg_temp_free_i64(tcg_op1);
7976         tcg_temp_free_i64(tcg_op2);
7977         tcg_temp_free_i64(tcg_res);
7978     } else {
7979         TCGv_i32 tcg_op1 = read_fp_hreg(s, rn);
7980         TCGv_i32 tcg_op2 = read_fp_hreg(s, rm);
7981         TCGv_i64 tcg_res = tcg_temp_new_i64();
7982
7983         gen_helper_neon_mull_s16(tcg_res, tcg_op1, tcg_op2);
7984         gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env, tcg_res, tcg_res);
7985
7986         switch (opcode) {
7987         case 0xd: /* SQDMULL, SQDMULL2 */
7988             break;
7989         case 0xb: /* SQDMLSL, SQDMLSL2 */
7990             gen_helper_neon_negl_u32(tcg_res, tcg_res);
7991             /* fall through */
7992         case 0x9: /* SQDMLAL, SQDMLAL2 */
7993         {
7994             TCGv_i64 tcg_op3 = tcg_temp_new_i64();
7995             read_vec_element(s, tcg_op3, rd, 0, MO_32);
7996             gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env,
7997                                               tcg_res, tcg_op3);
7998             tcg_temp_free_i64(tcg_op3);
7999             break;
8000         }
8001         default:
8002             g_assert_not_reached();
8003         }
8004
8005         tcg_gen_ext32u_i64(tcg_res, tcg_res);
8006         write_fp_dreg(s, rd, tcg_res);
8007
8008         tcg_temp_free_i32(tcg_op1);
8009         tcg_temp_free_i32(tcg_op2);
8010         tcg_temp_free_i64(tcg_res);
8011     }
8012 }
8013
8014 /* CMTST : test is "if (X & Y != 0)". */
8015 static void gen_cmtst_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
8016 {
8017     tcg_gen_and_i32(d, a, b);
8018     tcg_gen_setcondi_i32(TCG_COND_NE, d, d, 0);
8019     tcg_gen_neg_i32(d, d);
8020 }
8021
8022 static void gen_cmtst_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
8023 {
8024     tcg_gen_and_i64(d, a, b);
8025     tcg_gen_setcondi_i64(TCG_COND_NE, d, d, 0);
8026     tcg_gen_neg_i64(d, d);
8027 }
8028
8029 static void gen_cmtst_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
8030 {
8031     tcg_gen_and_vec(vece, d, a, b);
8032     tcg_gen_dupi_vec(vece, a, 0);
8033     tcg_gen_cmp_vec(TCG_COND_NE, vece, d, d, a);
8034 }
8035
8036 static void handle_3same_64(DisasContext *s, int opcode, bool u,
8037                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn, TCGv_i64 tcg_rm)
8038 {
8039     /* Handle 64x64->64 opcodes which are shared between the scalar
8040      * and vector 3-same groups. We cover every opcode where size == 3
8041      * is valid in either the three-reg-same (integer, not pairwise)
8042      * or scalar-three-reg-same groups.
8043      */
8044     TCGCond cond;
8045
8046     switch (opcode) {
8047     case 0x1: /* SQADD */
8048         if (u) {
8049             gen_helper_neon_qadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8050         } else {
8051             gen_helper_neon_qadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8052         }
8053         break;
8054     case 0x5: /* SQSUB */
8055         if (u) {
8056             gen_helper_neon_qsub_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8057         } else {
8058             gen_helper_neon_qsub_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8059         }
8060         break;
8061     case 0x6: /* CMGT, CMHI */
8062         /* 64 bit integer comparison, result = test ? (2^64 - 1) : 0.
8063          * We implement this using setcond (test) and then negating.
8064          */
8065         cond = u ? TCG_COND_GTU : TCG_COND_GT;
8066     do_cmop:
8067         tcg_gen_setcond_i64(cond, tcg_rd, tcg_rn, tcg_rm);
8068         tcg_gen_neg_i64(tcg_rd, tcg_rd);
8069         break;
8070     case 0x7: /* CMGE, CMHS */
8071         cond = u ? TCG_COND_GEU : TCG_COND_GE;
8072         goto do_cmop;
8073     case 0x11: /* CMTST, CMEQ */
8074         if (u) {
8075             cond = TCG_COND_EQ;
8076             goto do_cmop;
8077         }
8078         gen_cmtst_i64(tcg_rd, tcg_rn, tcg_rm);
8079         break;
8080     case 0x8: /* SSHL, USHL */
8081         if (u) {
8082             gen_helper_neon_shl_u64(tcg_rd, tcg_rn, tcg_rm);
8083         } else {
8084             gen_helper_neon_shl_s64(tcg_rd, tcg_rn, tcg_rm);
8085         }
8086         break;
8087     case 0x9: /* SQSHL, UQSHL */
8088         if (u) {
8089             gen_helper_neon_qshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8090         } else {
8091             gen_helper_neon_qshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8092         }
8093         break;
8094     case 0xa: /* SRSHL, URSHL */
8095         if (u) {
8096             gen_helper_neon_rshl_u64(tcg_rd, tcg_rn, tcg_rm);
8097         } else {
8098             gen_helper_neon_rshl_s64(tcg_rd, tcg_rn, tcg_rm);
8099         }
8100         break;
8101     case 0xb: /* SQRSHL, UQRSHL */
8102         if (u) {
8103             gen_helper_neon_qrshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8104         } else {
8105             gen_helper_neon_qrshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8106         }
8107         break;
8108     case 0x10: /* ADD, SUB */
8109         if (u) {
8110             tcg_gen_sub_i64(tcg_rd, tcg_rn, tcg_rm);
8111         } else {
8112             tcg_gen_add_i64(tcg_rd, tcg_rn, tcg_rm);
8113         }
8114         break;
8115     default:
8116         g_assert_not_reached();
8117     }
8118 }
8119
8120 /* Handle the 3-same-operands float operations; shared by the scalar
8121  * and vector encodings. The caller must filter out any encodings
8122  * not allocated for the encoding it is dealing with.
8123  */
8124 static void handle_3same_float(DisasContext *s, int size, int elements,
8125                                int fpopcode, int rd, int rn, int rm)
8126 {
8127     int pass;
8128     TCGv_ptr fpst = get_fpstatus_ptr(false);
8129
8130     for (pass = 0; pass < elements; pass++) {
8131         if (size) {
8132             /* Double */
8133             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8134             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8135             TCGv_i64 tcg_res = tcg_temp_new_i64();
8136
8137             read_vec_element(s, tcg_op1, rn, pass, MO_64);
8138             read_vec_element(s, tcg_op2, rm, pass, MO_64);
8139
8140             switch (fpopcode) {
8141             case 0x39: /* FMLS */
8142                 /* As usual for ARM, separate negation for fused multiply-add */
8143                 gen_helper_vfp_negd(tcg_op1, tcg_op1);
8144                 /* fall through */
8145             case 0x19: /* FMLA */
8146                 read_vec_element(s, tcg_res, rd, pass, MO_64);
8147                 gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2,
8148                                        tcg_res, fpst);
8149                 break;
8150             case 0x18: /* FMAXNM */
8151                 gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
8152                 break;
8153             case 0x1a: /* FADD */
8154                 gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
8155                 break;
8156             case 0x1b: /* FMULX */
8157                 gen_helper_vfp_mulxd(tcg_res, tcg_op1, tcg_op2, fpst);
8158                 break;
8159             case 0x1c: /* FCMEQ */
8160                 gen_helper_neon_ceq_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8161                 break;
8162             case 0x1e: /* FMAX */
8163                 gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
8164                 break;
8165             case 0x1f: /* FRECPS */
8166                 gen_helper_recpsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8167                 break;
8168             case 0x38: /* FMINNM */
8169                 gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
8170                 break;
8171             case 0x3a: /* FSUB */
8172                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
8173                 break;
8174             case 0x3e: /* FMIN */
8175                 gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
8176                 break;
8177             case 0x3f: /* FRSQRTS */
8178                 gen_helper_rsqrtsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8179                 break;
8180             case 0x5b: /* FMUL */
8181                 gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
8182                 break;
8183             case 0x5c: /* FCMGE */
8184                 gen_helper_neon_cge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8185                 break;
8186             case 0x5d: /* FACGE */
8187                 gen_helper_neon_acge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8188                 break;
8189             case 0x5f: /* FDIV */
8190                 gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
8191                 break;
8192             case 0x7a: /* FABD */
8193                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
8194                 gen_helper_vfp_absd(tcg_res, tcg_res);
8195                 break;
8196             case 0x7c: /* FCMGT */
8197                 gen_helper_neon_cgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8198                 break;
8199             case 0x7d: /* FACGT */
8200                 gen_helper_neon_acgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8201                 break;
8202             default:
8203                 g_assert_not_reached();
8204             }
8205
8206             write_vec_element(s, tcg_res, rd, pass, MO_64);
8207
8208             tcg_temp_free_i64(tcg_res);
8209             tcg_temp_free_i64(tcg_op1);
8210             tcg_temp_free_i64(tcg_op2);
8211         } else {
8212             /* Single */
8213             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
8214             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
8215             TCGv_i32 tcg_res = tcg_temp_new_i32();
8216
8217             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
8218             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
8219
8220             switch (fpopcode) {
8221             case 0x39: /* FMLS */
8222                 /* As usual for ARM, separate negation for fused multiply-add */
8223                 gen_helper_vfp_negs(tcg_op1, tcg_op1);
8224                 /* fall through */
8225             case 0x19: /* FMLA */
8226                 read_vec_element_i32(s, tcg_res, rd, pass, MO_32);
8227                 gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2,
8228                                        tcg_res, fpst);
8229                 break;
8230             case 0x1a: /* FADD */
8231                 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
8232                 break;
8233             case 0x1b: /* FMULX */
8234                 gen_helper_vfp_mulxs(tcg_res, tcg_op1, tcg_op2, fpst);
8235                 break;
8236             case 0x1c: /* FCMEQ */
8237                 gen_helper_neon_ceq_f32(tcg_res, tcg_op1, tcg_op2, fpst);
8238                 break;
8239             case 0x1e: /* FMAX */
8240                 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
8241                 break;
8242             case 0x1f: /* FRECPS */
8243                 gen_helper_recpsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
8244                 break;
8245             case 0x18: /* FMAXNM */
8246                 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
8247                 break;
8248             case 0x38: /* FMINNM */
8249                 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
8250                 break;
8251             case 0x3a: /* FSUB */
8252                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
8253                 break;
8254             case 0x3e: /* FMIN */
8255                 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
8256                 break;
8257             case 0x3f: /* FRSQRTS */
8258                 gen_helper_rsqrtsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
8259                 break;
8260             case 0x5b: /* FMUL */
8261                 gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
8262                 break;
8263             case 0x5c: /* FCMGE */
8264                 gen_helper_neon_cge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
8265                 break;
8266             case 0x5d: /* FACGE */
8267                 gen_helper_neon_acge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
8268                 break;
8269             case 0x5f: /* FDIV */
8270                 gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
8271                 break;
8272             case 0x7a: /* FABD */
8273                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
8274                 gen_helper_vfp_abss(tcg_res, tcg_res);
8275                 break;
8276             case 0x7c: /* FCMGT */
8277                 gen_helper_neon_cgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
8278                 break;
8279             case 0x7d: /* FACGT */
8280                 gen_helper_neon_acgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
8281                 break;
8282             default:
8283                 g_assert_not_reached();
8284             }
8285
8286             if (elements == 1) {
8287                 /* scalar single so clear high part */
8288                 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
8289
8290                 tcg_gen_extu_i32_i64(tcg_tmp, tcg_res);
8291                 write_vec_element(s, tcg_tmp, rd, pass, MO_64);
8292                 tcg_temp_free_i64(tcg_tmp);
8293             } else {
8294                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
8295             }
8296
8297             tcg_temp_free_i32(tcg_res);
8298             tcg_temp_free_i32(tcg_op1);
8299             tcg_temp_free_i32(tcg_op2);
8300         }
8301     }
8302
8303     tcg_temp_free_ptr(fpst);
8304
8305     clear_vec_high(s, elements * (size ? 8 : 4) > 8, rd);
8306 }
8307
8308 /* AdvSIMD scalar three same
8309  *  31 30  29 28       24 23  22  21 20  16 15    11  10 9    5 4    0
8310  * +-----+---+-----------+------+---+------+--------+---+------+------+
8311  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
8312  * +-----+---+-----------+------+---+------+--------+---+------+------+
8313  */
8314 static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
8315 {
8316     int rd = extract32(insn, 0, 5);
8317     int rn = extract32(insn, 5, 5);
8318     int opcode = extract32(insn, 11, 5);
8319     int rm = extract32(insn, 16, 5);
8320     int size = extract32(insn, 22, 2);
8321     bool u = extract32(insn, 29, 1);
8322     TCGv_i64 tcg_rd;
8323
8324     if (opcode >= 0x18) {
8325         /* Floating point: U, size[1] and opcode indicate operation */
8326         int fpopcode = opcode | (extract32(size, 1, 1) << 5) | (u << 6);
8327         switch (fpopcode) {
8328         case 0x1b: /* FMULX */
8329         case 0x1f: /* FRECPS */
8330         case 0x3f: /* FRSQRTS */
8331         case 0x5d: /* FACGE */
8332         case 0x7d: /* FACGT */
8333         case 0x1c: /* FCMEQ */
8334         case 0x5c: /* FCMGE */
8335         case 0x7c: /* FCMGT */
8336         case 0x7a: /* FABD */
8337             break;
8338         default:
8339             unallocated_encoding(s);
8340             return;
8341         }
8342
8343         if (!fp_access_check(s)) {
8344             return;
8345         }
8346
8347         handle_3same_float(s, extract32(size, 0, 1), 1, fpopcode, rd, rn, rm);
8348         return;
8349     }
8350
8351     switch (opcode) {
8352     case 0x1: /* SQADD, UQADD */
8353     case 0x5: /* SQSUB, UQSUB */
8354     case 0x9: /* SQSHL, UQSHL */
8355     case 0xb: /* SQRSHL, UQRSHL */
8356         break;
8357     case 0x8: /* SSHL, USHL */
8358     case 0xa: /* SRSHL, URSHL */
8359     case 0x6: /* CMGT, CMHI */
8360     case 0x7: /* CMGE, CMHS */
8361     case 0x11: /* CMTST, CMEQ */
8362     case 0x10: /* ADD, SUB (vector) */
8363         if (size != 3) {
8364             unallocated_encoding(s);
8365             return;
8366         }
8367         break;
8368     case 0x16: /* SQDMULH, SQRDMULH (vector) */
8369         if (size != 1 && size != 2) {
8370             unallocated_encoding(s);
8371             return;
8372         }
8373         break;
8374     default:
8375         unallocated_encoding(s);
8376         return;
8377     }
8378
8379     if (!fp_access_check(s)) {
8380         return;
8381     }
8382
8383     tcg_rd = tcg_temp_new_i64();
8384
8385     if (size == 3) {
8386         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
8387         TCGv_i64 tcg_rm = read_fp_dreg(s, rm);
8388
8389         handle_3same_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rm);
8390         tcg_temp_free_i64(tcg_rn);
8391         tcg_temp_free_i64(tcg_rm);
8392     } else {
8393         /* Do a single operation on the lowest element in the vector.
8394          * We use the standard Neon helpers and rely on 0 OP 0 == 0 with
8395          * no side effects for all these operations.
8396          * OPTME: special-purpose helpers would avoid doing some
8397          * unnecessary work in the helper for the 8 and 16 bit cases.
8398          */
8399         NeonGenTwoOpEnvFn *genenvfn;
8400         TCGv_i32 tcg_rn = tcg_temp_new_i32();
8401         TCGv_i32 tcg_rm = tcg_temp_new_i32();
8402         TCGv_i32 tcg_rd32 = tcg_temp_new_i32();
8403
8404         read_vec_element_i32(s, tcg_rn, rn, 0, size);
8405         read_vec_element_i32(s, tcg_rm, rm, 0, size);
8406
8407         switch (opcode) {
8408         case 0x1: /* SQADD, UQADD */
8409         {
8410             static NeonGenTwoOpEnvFn * const fns[3][2] = {
8411                 { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 },
8412                 { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 },
8413                 { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 },
8414             };
8415             genenvfn = fns[size][u];
8416             break;
8417         }
8418         case 0x5: /* SQSUB, UQSUB */
8419         {
8420             static NeonGenTwoOpEnvFn * const fns[3][2] = {
8421                 { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 },
8422                 { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 },
8423                 { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 },
8424             };
8425             genenvfn = fns[size][u];
8426             break;
8427         }
8428         case 0x9: /* SQSHL, UQSHL */
8429         {
8430             static NeonGenTwoOpEnvFn * const fns[3][2] = {
8431                 { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
8432                 { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
8433                 { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
8434             };
8435             genenvfn = fns[size][u];
8436             break;
8437         }
8438         case 0xb: /* SQRSHL, UQRSHL */
8439         {
8440             static NeonGenTwoOpEnvFn * const fns[3][2] = {
8441                 { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
8442                 { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
8443                 { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
8444             };
8445             genenvfn = fns[size][u];
8446             break;
8447         }
8448         case 0x16: /* SQDMULH, SQRDMULH */
8449         {
8450             static NeonGenTwoOpEnvFn * const fns[2][2] = {
8451                 { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
8452                 { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
8453             };
8454             assert(size == 1 || size == 2);
8455             genenvfn = fns[size - 1][u];
8456             break;
8457         }
8458         default:
8459             g_assert_not_reached();
8460         }
8461
8462         genenvfn(tcg_rd32, cpu_env, tcg_rn, tcg_rm);
8463         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd32);
8464         tcg_temp_free_i32(tcg_rd32);
8465         tcg_temp_free_i32(tcg_rn);
8466         tcg_temp_free_i32(tcg_rm);
8467     }
8468
8469     write_fp_dreg(s, rd, tcg_rd);
8470
8471     tcg_temp_free_i64(tcg_rd);
8472 }
8473
8474 /* AdvSIMD scalar three same FP16
8475  *  31 30  29 28       24 23  22 21 20  16 15 14 13    11 10  9  5 4  0
8476  * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
8477  * | 0 1 | U | 1 1 1 1 0 | a | 1 0 |  Rm  | 0 0 | opcode | 1 | Rn | Rd |
8478  * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
8479  * v: 0101 1110 0100 0000 0000 0100 0000 0000 => 5e400400
8480  * m: 1101 1111 0110 0000 1100 0100 0000 0000 => df60c400
8481  */
8482 static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
8483                                                   uint32_t insn)
8484 {
8485     int rd = extract32(insn, 0, 5);
8486     int rn = extract32(insn, 5, 5);
8487     int opcode = extract32(insn, 11, 3);
8488     int rm = extract32(insn, 16, 5);
8489     bool u = extract32(insn, 29, 1);
8490     bool a = extract32(insn, 23, 1);
8491     int fpopcode = opcode | (a << 3) |  (u << 4);
8492     TCGv_ptr fpst;
8493     TCGv_i32 tcg_op1;
8494     TCGv_i32 tcg_op2;
8495     TCGv_i32 tcg_res;
8496
8497     switch (fpopcode) {
8498     case 0x03: /* FMULX */
8499     case 0x04: /* FCMEQ (reg) */
8500     case 0x07: /* FRECPS */
8501     case 0x0f: /* FRSQRTS */
8502     case 0x14: /* FCMGE (reg) */
8503     case 0x15: /* FACGE */
8504     case 0x1a: /* FABD */
8505     case 0x1c: /* FCMGT (reg) */
8506     case 0x1d: /* FACGT */
8507         break;
8508     default:
8509         unallocated_encoding(s);
8510         return;
8511     }
8512
8513     if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
8514         unallocated_encoding(s);
8515     }
8516
8517     if (!fp_access_check(s)) {
8518         return;
8519     }
8520
8521     fpst = get_fpstatus_ptr(true);
8522
8523     tcg_op1 = read_fp_hreg(s, rn);
8524     tcg_op2 = read_fp_hreg(s, rm);
8525     tcg_res = tcg_temp_new_i32();
8526
8527     switch (fpopcode) {
8528     case 0x03: /* FMULX */
8529         gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
8530         break;
8531     case 0x04: /* FCMEQ (reg) */
8532         gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
8533         break;
8534     case 0x07: /* FRECPS */
8535         gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
8536         break;
8537     case 0x0f: /* FRSQRTS */
8538         gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
8539         break;
8540     case 0x14: /* FCMGE (reg) */
8541         gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
8542         break;
8543     case 0x15: /* FACGE */
8544         gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
8545         break;
8546     case 0x1a: /* FABD */
8547         gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
8548         tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
8549         break;
8550     case 0x1c: /* FCMGT (reg) */
8551         gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
8552         break;
8553     case 0x1d: /* FACGT */
8554         gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
8555         break;
8556     default:
8557         g_assert_not_reached();
8558     }
8559
8560     write_fp_sreg(s, rd, tcg_res);
8561
8562
8563     tcg_temp_free_i32(tcg_res);
8564     tcg_temp_free_i32(tcg_op1);
8565     tcg_temp_free_i32(tcg_op2);
8566     tcg_temp_free_ptr(fpst);
8567 }
8568
8569 /* AdvSIMD scalar three same extra
8570  *  31 30  29 28       24 23  22  21 20  16  15 14    11  10 9  5 4  0
8571  * +-----+---+-----------+------+---+------+---+--------+---+----+----+
8572  * | 0 1 | U | 1 1 1 1 0 | size | 0 |  Rm  | 1 | opcode | 1 | Rn | Rd |
8573  * +-----+---+-----------+------+---+------+---+--------+---+----+----+
8574  */
8575 static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
8576                                                    uint32_t insn)
8577 {
8578     int rd = extract32(insn, 0, 5);
8579     int rn = extract32(insn, 5, 5);
8580     int opcode = extract32(insn, 11, 4);
8581     int rm = extract32(insn, 16, 5);
8582     int size = extract32(insn, 22, 2);
8583     bool u = extract32(insn, 29, 1);
8584     TCGv_i32 ele1, ele2, ele3;
8585     TCGv_i64 res;
8586     int feature;
8587
8588     switch (u * 16 + opcode) {
8589     case 0x10: /* SQRDMLAH (vector) */
8590     case 0x11: /* SQRDMLSH (vector) */
8591         if (size != 1 && size != 2) {
8592             unallocated_encoding(s);
8593             return;
8594         }
8595         feature = ARM_FEATURE_V8_RDM;
8596         break;
8597     default:
8598         unallocated_encoding(s);
8599         return;
8600     }
8601     if (!arm_dc_feature(s, feature)) {
8602         unallocated_encoding(s);
8603         return;
8604     }
8605     if (!fp_access_check(s)) {
8606         return;
8607     }
8608
8609     /* Do a single operation on the lowest element in the vector.
8610      * We use the standard Neon helpers and rely on 0 OP 0 == 0
8611      * with no side effects for all these operations.
8612      * OPTME: special-purpose helpers would avoid doing some
8613      * unnecessary work in the helper for the 16 bit cases.
8614      */
8615     ele1 = tcg_temp_new_i32();
8616     ele2 = tcg_temp_new_i32();
8617     ele3 = tcg_temp_new_i32();
8618
8619     read_vec_element_i32(s, ele1, rn, 0, size);
8620     read_vec_element_i32(s, ele2, rm, 0, size);
8621     read_vec_element_i32(s, ele3, rd, 0, size);
8622
8623     switch (opcode) {
8624     case 0x0: /* SQRDMLAH */
8625         if (size == 1) {
8626             gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
8627         } else {
8628             gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
8629         }
8630         break;
8631     case 0x1: /* SQRDMLSH */
8632         if (size == 1) {
8633             gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
8634         } else {
8635             gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
8636         }
8637         break;
8638     default:
8639         g_assert_not_reached();
8640     }
8641     tcg_temp_free_i32(ele1);
8642     tcg_temp_free_i32(ele2);
8643
8644     res = tcg_temp_new_i64();
8645     tcg_gen_extu_i32_i64(res, ele3);
8646     tcg_temp_free_i32(ele3);
8647
8648     write_fp_dreg(s, rd, res);
8649     tcg_temp_free_i64(res);
8650 }
8651
8652 static void handle_2misc_64(DisasContext *s, int opcode, bool u,
8653                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
8654                             TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
8655 {
8656     /* Handle 64->64 opcodes which are shared between the scalar and
8657      * vector 2-reg-misc groups. We cover every integer opcode where size == 3
8658      * is valid in either group and also the double-precision fp ops.
8659      * The caller only need provide tcg_rmode and tcg_fpstatus if the op
8660      * requires them.
8661      */
8662     TCGCond cond;
8663
8664     switch (opcode) {
8665     case 0x4: /* CLS, CLZ */
8666         if (u) {
8667             tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
8668         } else {
8669             tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
8670         }
8671         break;
8672     case 0x5: /* NOT */
8673         /* This opcode is shared with CNT and RBIT but we have earlier
8674          * enforced that size == 3 if and only if this is the NOT insn.
8675          */
8676         tcg_gen_not_i64(tcg_rd, tcg_rn);
8677         break;
8678     case 0x7: /* SQABS, SQNEG */
8679         if (u) {
8680             gen_helper_neon_qneg_s64(tcg_rd, cpu_env, tcg_rn);
8681         } else {
8682             gen_helper_neon_qabs_s64(tcg_rd, cpu_env, tcg_rn);
8683         }
8684         break;
8685     case 0xa: /* CMLT */
8686         /* 64 bit integer comparison against zero, result is
8687          * test ? (2^64 - 1) : 0. We implement via setcond(!test) and
8688          * subtracting 1.
8689          */
8690         cond = TCG_COND_LT;
8691     do_cmop:
8692         tcg_gen_setcondi_i64(cond, tcg_rd, tcg_rn, 0);
8693         tcg_gen_neg_i64(tcg_rd, tcg_rd);
8694         break;
8695     case 0x8: /* CMGT, CMGE */
8696         cond = u ? TCG_COND_GE : TCG_COND_GT;
8697         goto do_cmop;
8698     case 0x9: /* CMEQ, CMLE */
8699         cond = u ? TCG_COND_LE : TCG_COND_EQ;
8700         goto do_cmop;
8701     case 0xb: /* ABS, NEG */
8702         if (u) {
8703             tcg_gen_neg_i64(tcg_rd, tcg_rn);
8704         } else {
8705             TCGv_i64 tcg_zero = tcg_const_i64(0);
8706             tcg_gen_neg_i64(tcg_rd, tcg_rn);
8707             tcg_gen_movcond_i64(TCG_COND_GT, tcg_rd, tcg_rn, tcg_zero,
8708                                 tcg_rn, tcg_rd);
8709             tcg_temp_free_i64(tcg_zero);
8710         }
8711         break;
8712     case 0x2f: /* FABS */
8713         gen_helper_vfp_absd(tcg_rd, tcg_rn);
8714         break;
8715     case 0x6f: /* FNEG */
8716         gen_helper_vfp_negd(tcg_rd, tcg_rn);
8717         break;
8718     case 0x7f: /* FSQRT */
8719         gen_helper_vfp_sqrtd(tcg_rd, tcg_rn, cpu_env);
8720         break;
8721     case 0x1a: /* FCVTNS */
8722     case 0x1b: /* FCVTMS */
8723     case 0x1c: /* FCVTAS */
8724     case 0x3a: /* FCVTPS */
8725     case 0x3b: /* FCVTZS */
8726     {
8727         TCGv_i32 tcg_shift = tcg_const_i32(0);
8728         gen_helper_vfp_tosqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
8729         tcg_temp_free_i32(tcg_shift);
8730         break;
8731     }
8732     case 0x5a: /* FCVTNU */
8733     case 0x5b: /* FCVTMU */
8734     case 0x5c: /* FCVTAU */
8735     case 0x7a: /* FCVTPU */
8736     case 0x7b: /* FCVTZU */
8737     {
8738         TCGv_i32 tcg_shift = tcg_const_i32(0);
8739         gen_helper_vfp_touqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
8740         tcg_temp_free_i32(tcg_shift);
8741         break;
8742     }
8743     case 0x18: /* FRINTN */
8744     case 0x19: /* FRINTM */
8745     case 0x38: /* FRINTP */
8746     case 0x39: /* FRINTZ */
8747     case 0x58: /* FRINTA */
8748     case 0x79: /* FRINTI */
8749         gen_helper_rintd(tcg_rd, tcg_rn, tcg_fpstatus);
8750         break;
8751     case 0x59: /* FRINTX */
8752         gen_helper_rintd_exact(tcg_rd, tcg_rn, tcg_fpstatus);
8753         break;
8754     default:
8755         g_assert_not_reached();
8756     }
8757 }
8758
8759 static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
8760                                    bool is_scalar, bool is_u, bool is_q,
8761                                    int size, int rn, int rd)
8762 {
8763     bool is_double = (size == MO_64);
8764     TCGv_ptr fpst;
8765
8766     if (!fp_access_check(s)) {
8767         return;
8768     }
8769
8770     fpst = get_fpstatus_ptr(size == MO_16);
8771
8772     if (is_double) {
8773         TCGv_i64 tcg_op = tcg_temp_new_i64();
8774         TCGv_i64 tcg_zero = tcg_const_i64(0);
8775         TCGv_i64 tcg_res = tcg_temp_new_i64();
8776         NeonGenTwoDoubleOPFn *genfn;
8777         bool swap = false;
8778         int pass;
8779
8780         switch (opcode) {
8781         case 0x2e: /* FCMLT (zero) */
8782             swap = true;
8783             /* fallthrough */
8784         case 0x2c: /* FCMGT (zero) */
8785             genfn = gen_helper_neon_cgt_f64;
8786             break;
8787         case 0x2d: /* FCMEQ (zero) */
8788             genfn = gen_helper_neon_ceq_f64;
8789             break;
8790         case 0x6d: /* FCMLE (zero) */
8791             swap = true;
8792             /* fall through */
8793         case 0x6c: /* FCMGE (zero) */
8794             genfn = gen_helper_neon_cge_f64;
8795             break;
8796         default:
8797             g_assert_not_reached();
8798         }
8799
8800         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
8801             read_vec_element(s, tcg_op, rn, pass, MO_64);
8802             if (swap) {
8803                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
8804             } else {
8805                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
8806             }
8807             write_vec_element(s, tcg_res, rd, pass, MO_64);
8808         }
8809         tcg_temp_free_i64(tcg_res);
8810         tcg_temp_free_i64(tcg_zero);
8811         tcg_temp_free_i64(tcg_op);
8812
8813         clear_vec_high(s, !is_scalar, rd);
8814     } else {
8815         TCGv_i32 tcg_op = tcg_temp_new_i32();
8816         TCGv_i32 tcg_zero = tcg_const_i32(0);
8817         TCGv_i32 tcg_res = tcg_temp_new_i32();
8818         NeonGenTwoSingleOPFn *genfn;
8819         bool swap = false;
8820         int pass, maxpasses;
8821
8822         if (size == MO_16) {
8823             switch (opcode) {
8824             case 0x2e: /* FCMLT (zero) */
8825                 swap = true;
8826                 /* fall through */
8827             case 0x2c: /* FCMGT (zero) */
8828                 genfn = gen_helper_advsimd_cgt_f16;
8829                 break;
8830             case 0x2d: /* FCMEQ (zero) */
8831                 genfn = gen_helper_advsimd_ceq_f16;
8832                 break;
8833             case 0x6d: /* FCMLE (zero) */
8834                 swap = true;
8835                 /* fall through */
8836             case 0x6c: /* FCMGE (zero) */
8837                 genfn = gen_helper_advsimd_cge_f16;
8838                 break;
8839             default:
8840                 g_assert_not_reached();
8841             }
8842         } else {
8843             switch (opcode) {
8844             case 0x2e: /* FCMLT (zero) */
8845                 swap = true;
8846                 /* fall through */
8847             case 0x2c: /* FCMGT (zero) */
8848                 genfn = gen_helper_neon_cgt_f32;
8849                 break;
8850             case 0x2d: /* FCMEQ (zero) */
8851                 genfn = gen_helper_neon_ceq_f32;
8852                 break;
8853             case 0x6d: /* FCMLE (zero) */
8854                 swap = true;
8855                 /* fall through */
8856             case 0x6c: /* FCMGE (zero) */
8857                 genfn = gen_helper_neon_cge_f32;
8858                 break;
8859             default:
8860                 g_assert_not_reached();
8861             }
8862         }
8863
8864         if (is_scalar) {
8865             maxpasses = 1;
8866         } else {
8867             int vector_size = 8 << is_q;
8868             maxpasses = vector_size >> size;
8869         }
8870
8871         for (pass = 0; pass < maxpasses; pass++) {
8872             read_vec_element_i32(s, tcg_op, rn, pass, size);
8873             if (swap) {
8874                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
8875             } else {
8876                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
8877             }
8878             if (is_scalar) {
8879                 write_fp_sreg(s, rd, tcg_res);
8880             } else {
8881                 write_vec_element_i32(s, tcg_res, rd, pass, size);
8882             }
8883         }
8884         tcg_temp_free_i32(tcg_res);
8885         tcg_temp_free_i32(tcg_zero);
8886         tcg_temp_free_i32(tcg_op);
8887         if (!is_scalar) {
8888             clear_vec_high(s, is_q, rd);
8889         }
8890     }
8891
8892     tcg_temp_free_ptr(fpst);
8893 }
8894
8895 static void handle_2misc_reciprocal(DisasContext *s, int opcode,
8896                                     bool is_scalar, bool is_u, bool is_q,
8897                                     int size, int rn, int rd)
8898 {
8899     bool is_double = (size == 3);
8900     TCGv_ptr fpst = get_fpstatus_ptr(false);
8901
8902     if (is_double) {
8903         TCGv_i64 tcg_op = tcg_temp_new_i64();
8904         TCGv_i64 tcg_res = tcg_temp_new_i64();
8905         int pass;
8906
8907         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
8908             read_vec_element(s, tcg_op, rn, pass, MO_64);
8909             switch (opcode) {
8910             case 0x3d: /* FRECPE */
8911                 gen_helper_recpe_f64(tcg_res, tcg_op, fpst);
8912                 break;
8913             case 0x3f: /* FRECPX */
8914                 gen_helper_frecpx_f64(tcg_res, tcg_op, fpst);
8915                 break;
8916             case 0x7d: /* FRSQRTE */
8917                 gen_helper_rsqrte_f64(tcg_res, tcg_op, fpst);
8918                 break;
8919             default:
8920                 g_assert_not_reached();
8921             }
8922             write_vec_element(s, tcg_res, rd, pass, MO_64);
8923         }
8924         tcg_temp_free_i64(tcg_res);
8925         tcg_temp_free_i64(tcg_op);
8926         clear_vec_high(s, !is_scalar, rd);
8927     } else {
8928         TCGv_i32 tcg_op = tcg_temp_new_i32();
8929         TCGv_i32 tcg_res = tcg_temp_new_i32();
8930         int pass, maxpasses;
8931
8932         if (is_scalar) {
8933             maxpasses = 1;
8934         } else {
8935             maxpasses = is_q ? 4 : 2;
8936         }
8937
8938         for (pass = 0; pass < maxpasses; pass++) {
8939             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
8940
8941             switch (opcode) {
8942             case 0x3c: /* URECPE */
8943                 gen_helper_recpe_u32(tcg_res, tcg_op, fpst);
8944                 break;
8945             case 0x3d: /* FRECPE */
8946                 gen_helper_recpe_f32(tcg_res, tcg_op, fpst);
8947                 break;
8948             case 0x3f: /* FRECPX */
8949                 gen_helper_frecpx_f32(tcg_res, tcg_op, fpst);
8950                 break;
8951             case 0x7d: /* FRSQRTE */
8952                 gen_helper_rsqrte_f32(tcg_res, tcg_op, fpst);
8953                 break;
8954             default:
8955                 g_assert_not_reached();
8956             }
8957
8958             if (is_scalar) {
8959                 write_fp_sreg(s, rd, tcg_res);
8960             } else {
8961                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
8962             }
8963         }
8964         tcg_temp_free_i32(tcg_res);
8965         tcg_temp_free_i32(tcg_op);
8966         if (!is_scalar) {
8967             clear_vec_high(s, is_q, rd);
8968         }
8969     }
8970     tcg_temp_free_ptr(fpst);
8971 }
8972
8973 static void handle_2misc_narrow(DisasContext *s, bool scalar,
8974                                 int opcode, bool u, bool is_q,
8975                                 int size, int rn, int rd)
8976 {
8977     /* Handle 2-reg-misc ops which are narrowing (so each 2*size element
8978      * in the source becomes a size element in the destination).
8979      */
8980     int pass;
8981     TCGv_i32 tcg_res[2];
8982     int destelt = is_q ? 2 : 0;
8983     int passes = scalar ? 1 : 2;
8984
8985     if (scalar) {
8986         tcg_res[1] = tcg_const_i32(0);
8987     }
8988
8989     for (pass = 0; pass < passes; pass++) {
8990         TCGv_i64 tcg_op = tcg_temp_new_i64();
8991         NeonGenNarrowFn *genfn = NULL;
8992         NeonGenNarrowEnvFn *genenvfn = NULL;
8993
8994         if (scalar) {
8995             read_vec_element(s, tcg_op, rn, pass, size + 1);
8996         } else {
8997             read_vec_element(s, tcg_op, rn, pass, MO_64);
8998         }
8999         tcg_res[pass] = tcg_temp_new_i32();
9000
9001         switch (opcode) {
9002         case 0x12: /* XTN, SQXTUN */
9003         {
9004             static NeonGenNarrowFn * const xtnfns[3] = {
9005                 gen_helper_neon_narrow_u8,
9006                 gen_helper_neon_narrow_u16,
9007                 tcg_gen_extrl_i64_i32,
9008             };
9009             static NeonGenNarrowEnvFn * const sqxtunfns[3] = {
9010                 gen_helper_neon_unarrow_sat8,
9011                 gen_helper_neon_unarrow_sat16,
9012                 gen_helper_neon_unarrow_sat32,
9013             };
9014             if (u) {
9015                 genenvfn = sqxtunfns[size];
9016             } else {
9017                 genfn = xtnfns[size];
9018             }
9019             break;
9020         }
9021         case 0x14: /* SQXTN, UQXTN */
9022         {
9023             static NeonGenNarrowEnvFn * const fns[3][2] = {
9024                 { gen_helper_neon_narrow_sat_s8,
9025                   gen_helper_neon_narrow_sat_u8 },
9026                 { gen_helper_neon_narrow_sat_s16,
9027                   gen_helper_neon_narrow_sat_u16 },
9028                 { gen_helper_neon_narrow_sat_s32,
9029                   gen_helper_neon_narrow_sat_u32 },
9030             };
9031             genenvfn = fns[size][u];
9032             break;
9033         }
9034         case 0x16: /* FCVTN, FCVTN2 */
9035             /* 32 bit to 16 bit or 64 bit to 32 bit float conversion */
9036             if (size == 2) {
9037                 gen_helper_vfp_fcvtsd(tcg_res[pass], tcg_op, cpu_env);
9038             } else {
9039                 TCGv_i32 tcg_lo = tcg_temp_new_i32();
9040                 TCGv_i32 tcg_hi = tcg_temp_new_i32();
9041                 tcg_gen_extr_i64_i32(tcg_lo, tcg_hi, tcg_op);
9042                 gen_helper_vfp_fcvt_f32_to_f16(tcg_lo, tcg_lo, cpu_env);
9043                 gen_helper_vfp_fcvt_f32_to_f16(tcg_hi, tcg_hi, cpu_env);
9044                 tcg_gen_deposit_i32(tcg_res[pass], tcg_lo, tcg_hi, 16, 16);
9045                 tcg_temp_free_i32(tcg_lo);
9046                 tcg_temp_free_i32(tcg_hi);
9047             }
9048             break;
9049         case 0x56:  /* FCVTXN, FCVTXN2 */
9050             /* 64 bit to 32 bit float conversion
9051              * with von Neumann rounding (round to odd)
9052              */
9053             assert(size == 2);
9054             gen_helper_fcvtx_f64_to_f32(tcg_res[pass], tcg_op, cpu_env);
9055             break;
9056         default:
9057             g_assert_not_reached();
9058         }
9059
9060         if (genfn) {
9061             genfn(tcg_res[pass], tcg_op);
9062         } else if (genenvfn) {
9063             genenvfn(tcg_res[pass], cpu_env, tcg_op);
9064         }
9065
9066         tcg_temp_free_i64(tcg_op);
9067     }
9068
9069     for (pass = 0; pass < 2; pass++) {
9070         write_vec_element_i32(s, tcg_res[pass], rd, destelt + pass, MO_32);
9071         tcg_temp_free_i32(tcg_res[pass]);
9072     }
9073     clear_vec_high(s, is_q, rd);
9074 }
9075
9076 /* Remaining saturating accumulating ops */
9077 static void handle_2misc_satacc(DisasContext *s, bool is_scalar, bool is_u,
9078                                 bool is_q, int size, int rn, int rd)
9079 {
9080     bool is_double = (size == 3);
9081
9082     if (is_double) {
9083         TCGv_i64 tcg_rn = tcg_temp_new_i64();
9084         TCGv_i64 tcg_rd = tcg_temp_new_i64();
9085         int pass;
9086
9087         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9088             read_vec_element(s, tcg_rn, rn, pass, MO_64);
9089             read_vec_element(s, tcg_rd, rd, pass, MO_64);
9090
9091             if (is_u) { /* USQADD */
9092                 gen_helper_neon_uqadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9093             } else { /* SUQADD */
9094                 gen_helper_neon_sqadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9095             }
9096             write_vec_element(s, tcg_rd, rd, pass, MO_64);
9097         }
9098         tcg_temp_free_i64(tcg_rd);
9099         tcg_temp_free_i64(tcg_rn);
9100         clear_vec_high(s, !is_scalar, rd);
9101     } else {
9102         TCGv_i32 tcg_rn = tcg_temp_new_i32();
9103         TCGv_i32 tcg_rd = tcg_temp_new_i32();
9104         int pass, maxpasses;
9105
9106         if (is_scalar) {
9107             maxpasses = 1;
9108         } else {
9109             maxpasses = is_q ? 4 : 2;
9110         }
9111
9112         for (pass = 0; pass < maxpasses; pass++) {
9113             if (is_scalar) {
9114                 read_vec_element_i32(s, tcg_rn, rn, pass, size);
9115                 read_vec_element_i32(s, tcg_rd, rd, pass, size);
9116             } else {
9117                 read_vec_element_i32(s, tcg_rn, rn, pass, MO_32);
9118                 read_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
9119             }
9120
9121             if (is_u) { /* USQADD */
9122                 switch (size) {
9123                 case 0:
9124                     gen_helper_neon_uqadd_s8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9125                     break;
9126                 case 1:
9127                     gen_helper_neon_uqadd_s16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9128                     break;
9129                 case 2:
9130                     gen_helper_neon_uqadd_s32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9131                     break;
9132                 default:
9133                     g_assert_not_reached();
9134                 }
9135             } else { /* SUQADD */
9136                 switch (size) {
9137                 case 0:
9138                     gen_helper_neon_sqadd_u8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9139                     break;
9140                 case 1:
9141                     gen_helper_neon_sqadd_u16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9142                     break;
9143                 case 2:
9144                     gen_helper_neon_sqadd_u32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9145                     break;
9146                 default:
9147                     g_assert_not_reached();
9148                 }
9149             }
9150
9151             if (is_scalar) {
9152                 TCGv_i64 tcg_zero = tcg_const_i64(0);
9153                 write_vec_element(s, tcg_zero, rd, 0, MO_64);
9154                 tcg_temp_free_i64(tcg_zero);
9155             }
9156             write_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
9157         }
9158         tcg_temp_free_i32(tcg_rd);
9159         tcg_temp_free_i32(tcg_rn);
9160         clear_vec_high(s, is_q, rd);
9161     }
9162 }
9163
9164 /* AdvSIMD scalar two reg misc
9165  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
9166  * +-----+---+-----------+------+-----------+--------+-----+------+------+
9167  * | 0 1 | U | 1 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
9168  * +-----+---+-----------+------+-----------+--------+-----+------+------+
9169  */
9170 static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
9171 {
9172     int rd = extract32(insn, 0, 5);
9173     int rn = extract32(insn, 5, 5);
9174     int opcode = extract32(insn, 12, 5);
9175     int size = extract32(insn, 22, 2);
9176     bool u = extract32(insn, 29, 1);
9177     bool is_fcvt = false;
9178     int rmode;
9179     TCGv_i32 tcg_rmode;
9180     TCGv_ptr tcg_fpstatus;
9181
9182     switch (opcode) {
9183     case 0x3: /* USQADD / SUQADD*/
9184         if (!fp_access_check(s)) {
9185             return;
9186         }
9187         handle_2misc_satacc(s, true, u, false, size, rn, rd);
9188         return;
9189     case 0x7: /* SQABS / SQNEG */
9190         break;
9191     case 0xa: /* CMLT */
9192         if (u) {
9193             unallocated_encoding(s);
9194             return;
9195         }
9196         /* fall through */
9197     case 0x8: /* CMGT, CMGE */
9198     case 0x9: /* CMEQ, CMLE */
9199     case 0xb: /* ABS, NEG */
9200         if (size != 3) {
9201             unallocated_encoding(s);
9202             return;
9203         }
9204         break;
9205     case 0x12: /* SQXTUN */
9206         if (!u) {
9207             unallocated_encoding(s);
9208             return;
9209         }
9210         /* fall through */
9211     case 0x14: /* SQXTN, UQXTN */
9212         if (size == 3) {
9213             unallocated_encoding(s);
9214             return;
9215         }
9216         if (!fp_access_check(s)) {
9217             return;
9218         }
9219         handle_2misc_narrow(s, true, opcode, u, false, size, rn, rd);
9220         return;
9221     case 0xc ... 0xf:
9222     case 0x16 ... 0x1d:
9223     case 0x1f:
9224         /* Floating point: U, size[1] and opcode indicate operation;
9225          * size[0] indicates single or double precision.
9226          */
9227         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
9228         size = extract32(size, 0, 1) ? 3 : 2;
9229         switch (opcode) {
9230         case 0x2c: /* FCMGT (zero) */
9231         case 0x2d: /* FCMEQ (zero) */
9232         case 0x2e: /* FCMLT (zero) */
9233         case 0x6c: /* FCMGE (zero) */
9234         case 0x6d: /* FCMLE (zero) */
9235             handle_2misc_fcmp_zero(s, opcode, true, u, true, size, rn, rd);
9236             return;
9237         case 0x1d: /* SCVTF */
9238         case 0x5d: /* UCVTF */
9239         {
9240             bool is_signed = (opcode == 0x1d);
9241             if (!fp_access_check(s)) {
9242                 return;
9243             }
9244             handle_simd_intfp_conv(s, rd, rn, 1, is_signed, 0, size);
9245             return;
9246         }
9247         case 0x3d: /* FRECPE */
9248         case 0x3f: /* FRECPX */
9249         case 0x7d: /* FRSQRTE */
9250             if (!fp_access_check(s)) {
9251                 return;
9252             }
9253             handle_2misc_reciprocal(s, opcode, true, u, true, size, rn, rd);
9254             return;
9255         case 0x1a: /* FCVTNS */
9256         case 0x1b: /* FCVTMS */
9257         case 0x3a: /* FCVTPS */
9258         case 0x3b: /* FCVTZS */
9259         case 0x5a: /* FCVTNU */
9260         case 0x5b: /* FCVTMU */
9261         case 0x7a: /* FCVTPU */
9262         case 0x7b: /* FCVTZU */
9263             is_fcvt = true;
9264             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
9265             break;
9266         case 0x1c: /* FCVTAS */
9267         case 0x5c: /* FCVTAU */
9268             /* TIEAWAY doesn't fit in the usual rounding mode encoding */
9269             is_fcvt = true;
9270             rmode = FPROUNDING_TIEAWAY;
9271             break;
9272         case 0x56: /* FCVTXN, FCVTXN2 */
9273             if (size == 2) {
9274                 unallocated_encoding(s);
9275                 return;
9276             }
9277             if (!fp_access_check(s)) {
9278                 return;
9279             }
9280             handle_2misc_narrow(s, true, opcode, u, false, size - 1, rn, rd);
9281             return;
9282         default:
9283             unallocated_encoding(s);
9284             return;
9285         }
9286         break;
9287     default:
9288         unallocated_encoding(s);
9289         return;
9290     }
9291
9292     if (!fp_access_check(s)) {
9293         return;
9294     }
9295
9296     if (is_fcvt) {
9297         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
9298         tcg_fpstatus = get_fpstatus_ptr(false);
9299         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
9300     } else {
9301         tcg_rmode = NULL;
9302         tcg_fpstatus = NULL;
9303     }
9304
9305     if (size == 3) {
9306         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
9307         TCGv_i64 tcg_rd = tcg_temp_new_i64();
9308
9309         handle_2misc_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rmode, tcg_fpstatus);
9310         write_fp_dreg(s, rd, tcg_rd);
9311         tcg_temp_free_i64(tcg_rd);
9312         tcg_temp_free_i64(tcg_rn);
9313     } else {
9314         TCGv_i32 tcg_rn = tcg_temp_new_i32();
9315         TCGv_i32 tcg_rd = tcg_temp_new_i32();
9316
9317         read_vec_element_i32(s, tcg_rn, rn, 0, size);
9318
9319         switch (opcode) {
9320         case 0x7: /* SQABS, SQNEG */
9321         {
9322             NeonGenOneOpEnvFn *genfn;
9323             static NeonGenOneOpEnvFn * const fns[3][2] = {
9324                 { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
9325                 { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
9326                 { gen_helper_neon_qabs_s32, gen_helper_neon_qneg_s32 },
9327             };
9328             genfn = fns[size][u];
9329             genfn(tcg_rd, cpu_env, tcg_rn);
9330             break;
9331         }
9332         case 0x1a: /* FCVTNS */
9333         case 0x1b: /* FCVTMS */
9334         case 0x1c: /* FCVTAS */
9335         case 0x3a: /* FCVTPS */
9336         case 0x3b: /* FCVTZS */
9337         {
9338             TCGv_i32 tcg_shift = tcg_const_i32(0);
9339             gen_helper_vfp_tosls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
9340             tcg_temp_free_i32(tcg_shift);
9341             break;
9342         }
9343         case 0x5a: /* FCVTNU */
9344         case 0x5b: /* FCVTMU */
9345         case 0x5c: /* FCVTAU */
9346         case 0x7a: /* FCVTPU */
9347         case 0x7b: /* FCVTZU */
9348         {
9349             TCGv_i32 tcg_shift = tcg_const_i32(0);
9350             gen_helper_vfp_touls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
9351             tcg_temp_free_i32(tcg_shift);
9352             break;
9353         }
9354         default:
9355             g_assert_not_reached();
9356         }
9357
9358         write_fp_sreg(s, rd, tcg_rd);
9359         tcg_temp_free_i32(tcg_rd);
9360         tcg_temp_free_i32(tcg_rn);
9361     }
9362
9363     if (is_fcvt) {
9364         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
9365         tcg_temp_free_i32(tcg_rmode);
9366         tcg_temp_free_ptr(tcg_fpstatus);
9367     }
9368 }
9369
9370 static void gen_ssra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9371 {
9372     tcg_gen_vec_sar8i_i64(a, a, shift);
9373     tcg_gen_vec_add8_i64(d, d, a);
9374 }
9375
9376 static void gen_ssra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9377 {
9378     tcg_gen_vec_sar16i_i64(a, a, shift);
9379     tcg_gen_vec_add16_i64(d, d, a);
9380 }
9381
9382 static void gen_ssra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
9383 {
9384     tcg_gen_sari_i32(a, a, shift);
9385     tcg_gen_add_i32(d, d, a);
9386 }
9387
9388 static void gen_ssra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9389 {
9390     tcg_gen_sari_i64(a, a, shift);
9391     tcg_gen_add_i64(d, d, a);
9392 }
9393
9394 static void gen_ssra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
9395 {
9396     tcg_gen_sari_vec(vece, a, a, sh);
9397     tcg_gen_add_vec(vece, d, d, a);
9398 }
9399
9400 static void gen_usra8_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9401 {
9402     tcg_gen_vec_shr8i_i64(a, a, shift);
9403     tcg_gen_vec_add8_i64(d, d, a);
9404 }
9405
9406 static void gen_usra16_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9407 {
9408     tcg_gen_vec_shr16i_i64(a, a, shift);
9409     tcg_gen_vec_add16_i64(d, d, a);
9410 }
9411
9412 static void gen_usra32_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
9413 {
9414     tcg_gen_shri_i32(a, a, shift);
9415     tcg_gen_add_i32(d, d, a);
9416 }
9417
9418 static void gen_usra64_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9419 {
9420     tcg_gen_shri_i64(a, a, shift);
9421     tcg_gen_add_i64(d, d, a);
9422 }
9423
9424 static void gen_usra_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
9425 {
9426     tcg_gen_shri_vec(vece, a, a, sh);
9427     tcg_gen_add_vec(vece, d, d, a);
9428 }
9429
9430 static void gen_shr8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9431 {
9432     uint64_t mask = dup_const(MO_8, 0xff >> shift);
9433     TCGv_i64 t = tcg_temp_new_i64();
9434
9435     tcg_gen_shri_i64(t, a, shift);
9436     tcg_gen_andi_i64(t, t, mask);
9437     tcg_gen_andi_i64(d, d, ~mask);
9438     tcg_gen_or_i64(d, d, t);
9439     tcg_temp_free_i64(t);
9440 }
9441
9442 static void gen_shr16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9443 {
9444     uint64_t mask = dup_const(MO_16, 0xffff >> shift);
9445     TCGv_i64 t = tcg_temp_new_i64();
9446
9447     tcg_gen_shri_i64(t, a, shift);
9448     tcg_gen_andi_i64(t, t, mask);
9449     tcg_gen_andi_i64(d, d, ~mask);
9450     tcg_gen_or_i64(d, d, t);
9451     tcg_temp_free_i64(t);
9452 }
9453
9454 static void gen_shr32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
9455 {
9456     tcg_gen_shri_i32(a, a, shift);
9457     tcg_gen_deposit_i32(d, d, a, 0, 32 - shift);
9458 }
9459
9460 static void gen_shr64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9461 {
9462     tcg_gen_shri_i64(a, a, shift);
9463     tcg_gen_deposit_i64(d, d, a, 0, 64 - shift);
9464 }
9465
9466 static void gen_shr_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
9467 {
9468     uint64_t mask = (2ull << ((8 << vece) - 1)) - 1;
9469     TCGv_vec t = tcg_temp_new_vec_matching(d);
9470     TCGv_vec m = tcg_temp_new_vec_matching(d);
9471
9472     tcg_gen_dupi_vec(vece, m, mask ^ (mask >> sh));
9473     tcg_gen_shri_vec(vece, t, a, sh);
9474     tcg_gen_and_vec(vece, d, d, m);
9475     tcg_gen_or_vec(vece, d, d, t);
9476
9477     tcg_temp_free_vec(t);
9478     tcg_temp_free_vec(m);
9479 }
9480
9481 /* SSHR[RA]/USHR[RA] - Vector shift right (optional rounding/accumulate) */
9482 static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
9483                                  int immh, int immb, int opcode, int rn, int rd)
9484 {
9485     static const GVecGen2i ssra_op[4] = {
9486         { .fni8 = gen_ssra8_i64,
9487           .fniv = gen_ssra_vec,
9488           .load_dest = true,
9489           .opc = INDEX_op_sari_vec,
9490           .vece = MO_8 },
9491         { .fni8 = gen_ssra16_i64,
9492           .fniv = gen_ssra_vec,
9493           .load_dest = true,
9494           .opc = INDEX_op_sari_vec,
9495           .vece = MO_16 },
9496         { .fni4 = gen_ssra32_i32,
9497           .fniv = gen_ssra_vec,
9498           .load_dest = true,
9499           .opc = INDEX_op_sari_vec,
9500           .vece = MO_32 },
9501         { .fni8 = gen_ssra64_i64,
9502           .fniv = gen_ssra_vec,
9503           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
9504           .load_dest = true,
9505           .opc = INDEX_op_sari_vec,
9506           .vece = MO_64 },
9507     };
9508     static const GVecGen2i usra_op[4] = {
9509         { .fni8 = gen_usra8_i64,
9510           .fniv = gen_usra_vec,
9511           .load_dest = true,
9512           .opc = INDEX_op_shri_vec,
9513           .vece = MO_8, },
9514         { .fni8 = gen_usra16_i64,
9515           .fniv = gen_usra_vec,
9516           .load_dest = true,
9517           .opc = INDEX_op_shri_vec,
9518           .vece = MO_16, },
9519         { .fni4 = gen_usra32_i32,
9520           .fniv = gen_usra_vec,
9521           .load_dest = true,
9522           .opc = INDEX_op_shri_vec,
9523           .vece = MO_32, },
9524         { .fni8 = gen_usra64_i64,
9525           .fniv = gen_usra_vec,
9526           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
9527           .load_dest = true,
9528           .opc = INDEX_op_shri_vec,
9529           .vece = MO_64, },
9530     };
9531     static const GVecGen2i sri_op[4] = {
9532         { .fni8 = gen_shr8_ins_i64,
9533           .fniv = gen_shr_ins_vec,
9534           .load_dest = true,
9535           .opc = INDEX_op_shri_vec,
9536           .vece = MO_8 },
9537         { .fni8 = gen_shr16_ins_i64,
9538           .fniv = gen_shr_ins_vec,
9539           .load_dest = true,
9540           .opc = INDEX_op_shri_vec,
9541           .vece = MO_16 },
9542         { .fni4 = gen_shr32_ins_i32,
9543           .fniv = gen_shr_ins_vec,
9544           .load_dest = true,
9545           .opc = INDEX_op_shri_vec,
9546           .vece = MO_32 },
9547         { .fni8 = gen_shr64_ins_i64,
9548           .fniv = gen_shr_ins_vec,
9549           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
9550           .load_dest = true,
9551           .opc = INDEX_op_shri_vec,
9552           .vece = MO_64 },
9553     };
9554
9555     int size = 32 - clz32(immh) - 1;
9556     int immhb = immh << 3 | immb;
9557     int shift = 2 * (8 << size) - immhb;
9558     bool accumulate = false;
9559     int dsize = is_q ? 128 : 64;
9560     int esize = 8 << size;
9561     int elements = dsize/esize;
9562     TCGMemOp memop = size | (is_u ? 0 : MO_SIGN);
9563     TCGv_i64 tcg_rn = new_tmp_a64(s);
9564     TCGv_i64 tcg_rd = new_tmp_a64(s);
9565     TCGv_i64 tcg_round;
9566     uint64_t round_const;
9567     int i;
9568
9569     if (extract32(immh, 3, 1) && !is_q) {
9570         unallocated_encoding(s);
9571         return;
9572     }
9573     tcg_debug_assert(size <= 3);
9574
9575     if (!fp_access_check(s)) {
9576         return;
9577     }
9578
9579     switch (opcode) {
9580     case 0x02: /* SSRA / USRA (accumulate) */
9581         if (is_u) {
9582             /* Shift count same as element size produces zero to add.  */
9583             if (shift == 8 << size) {
9584                 goto done;
9585             }
9586             gen_gvec_op2i(s, is_q, rd, rn, shift, &usra_op[size]);
9587         } else {
9588             /* Shift count same as element size produces all sign to add.  */
9589             if (shift == 8 << size) {
9590                 shift -= 1;
9591             }
9592             gen_gvec_op2i(s, is_q, rd, rn, shift, &ssra_op[size]);
9593         }
9594         return;
9595     case 0x08: /* SRI */
9596         /* Shift count same as element size is valid but does nothing.  */
9597         if (shift == 8 << size) {
9598             goto done;
9599         }
9600         gen_gvec_op2i(s, is_q, rd, rn, shift, &sri_op[size]);
9601         return;
9602
9603     case 0x00: /* SSHR / USHR */
9604         if (is_u) {
9605             if (shift == 8 << size) {
9606                 /* Shift count the same size as element size produces zero.  */
9607                 tcg_gen_gvec_dup8i(vec_full_reg_offset(s, rd),
9608                                    is_q ? 16 : 8, vec_full_reg_size(s), 0);
9609             } else {
9610                 gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shri, size);
9611             }
9612         } else {
9613             /* Shift count the same size as element size produces all sign.  */
9614             if (shift == 8 << size) {
9615                 shift -= 1;
9616             }
9617             gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_sari, size);
9618         }
9619         return;
9620
9621     case 0x04: /* SRSHR / URSHR (rounding) */
9622         break;
9623     case 0x06: /* SRSRA / URSRA (accum + rounding) */
9624         accumulate = true;
9625         break;
9626     default:
9627         g_assert_not_reached();
9628     }
9629
9630     round_const = 1ULL << (shift - 1);
9631     tcg_round = tcg_const_i64(round_const);
9632
9633     for (i = 0; i < elements; i++) {
9634         read_vec_element(s, tcg_rn, rn, i, memop);
9635         if (accumulate) {
9636             read_vec_element(s, tcg_rd, rd, i, memop);
9637         }
9638
9639         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
9640                                 accumulate, is_u, size, shift);
9641
9642         write_vec_element(s, tcg_rd, rd, i, size);
9643     }
9644     tcg_temp_free_i64(tcg_round);
9645
9646  done:
9647     clear_vec_high(s, is_q, rd);
9648 }
9649
9650 static void gen_shl8_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9651 {
9652     uint64_t mask = dup_const(MO_8, 0xff << shift);
9653     TCGv_i64 t = tcg_temp_new_i64();
9654
9655     tcg_gen_shli_i64(t, a, shift);
9656     tcg_gen_andi_i64(t, t, mask);
9657     tcg_gen_andi_i64(d, d, ~mask);
9658     tcg_gen_or_i64(d, d, t);
9659     tcg_temp_free_i64(t);
9660 }
9661
9662 static void gen_shl16_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9663 {
9664     uint64_t mask = dup_const(MO_16, 0xffff << shift);
9665     TCGv_i64 t = tcg_temp_new_i64();
9666
9667     tcg_gen_shli_i64(t, a, shift);
9668     tcg_gen_andi_i64(t, t, mask);
9669     tcg_gen_andi_i64(d, d, ~mask);
9670     tcg_gen_or_i64(d, d, t);
9671     tcg_temp_free_i64(t);
9672 }
9673
9674 static void gen_shl32_ins_i32(TCGv_i32 d, TCGv_i32 a, int32_t shift)
9675 {
9676     tcg_gen_deposit_i32(d, d, a, shift, 32 - shift);
9677 }
9678
9679 static void gen_shl64_ins_i64(TCGv_i64 d, TCGv_i64 a, int64_t shift)
9680 {
9681     tcg_gen_deposit_i64(d, d, a, shift, 64 - shift);
9682 }
9683
9684 static void gen_shl_ins_vec(unsigned vece, TCGv_vec d, TCGv_vec a, int64_t sh)
9685 {
9686     uint64_t mask = (1ull << sh) - 1;
9687     TCGv_vec t = tcg_temp_new_vec_matching(d);
9688     TCGv_vec m = tcg_temp_new_vec_matching(d);
9689
9690     tcg_gen_dupi_vec(vece, m, mask);
9691     tcg_gen_shli_vec(vece, t, a, sh);
9692     tcg_gen_and_vec(vece, d, d, m);
9693     tcg_gen_or_vec(vece, d, d, t);
9694
9695     tcg_temp_free_vec(t);
9696     tcg_temp_free_vec(m);
9697 }
9698
9699 /* SHL/SLI - Vector shift left */
9700 static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
9701                                  int immh, int immb, int opcode, int rn, int rd)
9702 {
9703     static const GVecGen2i shi_op[4] = {
9704         { .fni8 = gen_shl8_ins_i64,
9705           .fniv = gen_shl_ins_vec,
9706           .opc = INDEX_op_shli_vec,
9707           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
9708           .load_dest = true,
9709           .vece = MO_8 },
9710         { .fni8 = gen_shl16_ins_i64,
9711           .fniv = gen_shl_ins_vec,
9712           .opc = INDEX_op_shli_vec,
9713           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
9714           .load_dest = true,
9715           .vece = MO_16 },
9716         { .fni4 = gen_shl32_ins_i32,
9717           .fniv = gen_shl_ins_vec,
9718           .opc = INDEX_op_shli_vec,
9719           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
9720           .load_dest = true,
9721           .vece = MO_32 },
9722         { .fni8 = gen_shl64_ins_i64,
9723           .fniv = gen_shl_ins_vec,
9724           .opc = INDEX_op_shli_vec,
9725           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
9726           .load_dest = true,
9727           .vece = MO_64 },
9728     };
9729     int size = 32 - clz32(immh) - 1;
9730     int immhb = immh << 3 | immb;
9731     int shift = immhb - (8 << size);
9732
9733     if (extract32(immh, 3, 1) && !is_q) {
9734         unallocated_encoding(s);
9735         return;
9736     }
9737
9738     if (size > 3 && !is_q) {
9739         unallocated_encoding(s);
9740         return;
9741     }
9742
9743     if (!fp_access_check(s)) {
9744         return;
9745     }
9746
9747     if (insert) {
9748         gen_gvec_op2i(s, is_q, rd, rn, shift, &shi_op[size]);
9749     } else {
9750         gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shli, size);
9751     }
9752 }
9753
9754 /* USHLL/SHLL - Vector shift left with widening */
9755 static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u,
9756                                  int immh, int immb, int opcode, int rn, int rd)
9757 {
9758     int size = 32 - clz32(immh) - 1;
9759     int immhb = immh << 3 | immb;
9760     int shift = immhb - (8 << size);
9761     int dsize = 64;
9762     int esize = 8 << size;
9763     int elements = dsize/esize;
9764     TCGv_i64 tcg_rn = new_tmp_a64(s);
9765     TCGv_i64 tcg_rd = new_tmp_a64(s);
9766     int i;
9767
9768     if (size >= 3) {
9769         unallocated_encoding(s);
9770         return;
9771     }
9772
9773     if (!fp_access_check(s)) {
9774         return;
9775     }
9776
9777     /* For the LL variants the store is larger than the load,
9778      * so if rd == rn we would overwrite parts of our input.
9779      * So load everything right now and use shifts in the main loop.
9780      */
9781     read_vec_element(s, tcg_rn, rn, is_q ? 1 : 0, MO_64);
9782
9783     for (i = 0; i < elements; i++) {
9784         tcg_gen_shri_i64(tcg_rd, tcg_rn, i * esize);
9785         ext_and_shift_reg(tcg_rd, tcg_rd, size | (!is_u << 2), 0);
9786         tcg_gen_shli_i64(tcg_rd, tcg_rd, shift);
9787         write_vec_element(s, tcg_rd, rd, i, size + 1);
9788     }
9789 }
9790
9791 /* SHRN/RSHRN - Shift right with narrowing (and potential rounding) */
9792 static void handle_vec_simd_shrn(DisasContext *s, bool is_q,
9793                                  int immh, int immb, int opcode, int rn, int rd)
9794 {
9795     int immhb = immh << 3 | immb;
9796     int size = 32 - clz32(immh) - 1;
9797     int dsize = 64;
9798     int esize = 8 << size;
9799     int elements = dsize/esize;
9800     int shift = (2 * esize) - immhb;
9801     bool round = extract32(opcode, 0, 1);
9802     TCGv_i64 tcg_rn, tcg_rd, tcg_final;
9803     TCGv_i64 tcg_round;
9804     int i;
9805
9806     if (extract32(immh, 3, 1)) {
9807         unallocated_encoding(s);
9808         return;
9809     }
9810
9811     if (!fp_access_check(s)) {
9812         return;
9813     }
9814
9815     tcg_rn = tcg_temp_new_i64();
9816     tcg_rd = tcg_temp_new_i64();
9817     tcg_final = tcg_temp_new_i64();
9818     read_vec_element(s, tcg_final, rd, is_q ? 1 : 0, MO_64);
9819
9820     if (round) {
9821         uint64_t round_const = 1ULL << (shift - 1);
9822         tcg_round = tcg_const_i64(round_const);
9823     } else {
9824         tcg_round = NULL;
9825     }
9826
9827     for (i = 0; i < elements; i++) {
9828         read_vec_element(s, tcg_rn, rn, i, size+1);
9829         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
9830                                 false, true, size+1, shift);
9831
9832         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
9833     }
9834
9835     if (!is_q) {
9836         write_vec_element(s, tcg_final, rd, 0, MO_64);
9837     } else {
9838         write_vec_element(s, tcg_final, rd, 1, MO_64);
9839     }
9840     if (round) {
9841         tcg_temp_free_i64(tcg_round);
9842     }
9843     tcg_temp_free_i64(tcg_rn);
9844     tcg_temp_free_i64(tcg_rd);
9845     tcg_temp_free_i64(tcg_final);
9846
9847     clear_vec_high(s, is_q, rd);
9848 }
9849
9850
9851 /* AdvSIMD shift by immediate
9852  *  31  30   29 28         23 22  19 18  16 15    11  10 9    5 4    0
9853  * +---+---+---+-------------+------+------+--------+---+------+------+
9854  * | 0 | Q | U | 0 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
9855  * +---+---+---+-------------+------+------+--------+---+------+------+
9856  */
9857 static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
9858 {
9859     int rd = extract32(insn, 0, 5);
9860     int rn = extract32(insn, 5, 5);
9861     int opcode = extract32(insn, 11, 5);
9862     int immb = extract32(insn, 16, 3);
9863     int immh = extract32(insn, 19, 4);
9864     bool is_u = extract32(insn, 29, 1);
9865     bool is_q = extract32(insn, 30, 1);
9866
9867     switch (opcode) {
9868     case 0x08: /* SRI */
9869         if (!is_u) {
9870             unallocated_encoding(s);
9871             return;
9872         }
9873         /* fall through */
9874     case 0x00: /* SSHR / USHR */
9875     case 0x02: /* SSRA / USRA (accumulate) */
9876     case 0x04: /* SRSHR / URSHR (rounding) */
9877     case 0x06: /* SRSRA / URSRA (accum + rounding) */
9878         handle_vec_simd_shri(s, is_q, is_u, immh, immb, opcode, rn, rd);
9879         break;
9880     case 0x0a: /* SHL / SLI */
9881         handle_vec_simd_shli(s, is_q, is_u, immh, immb, opcode, rn, rd);
9882         break;
9883     case 0x10: /* SHRN */
9884     case 0x11: /* RSHRN / SQRSHRUN */
9885         if (is_u) {
9886             handle_vec_simd_sqshrn(s, false, is_q, false, true, immh, immb,
9887                                    opcode, rn, rd);
9888         } else {
9889             handle_vec_simd_shrn(s, is_q, immh, immb, opcode, rn, rd);
9890         }
9891         break;
9892     case 0x12: /* SQSHRN / UQSHRN */
9893     case 0x13: /* SQRSHRN / UQRSHRN */
9894         handle_vec_simd_sqshrn(s, false, is_q, is_u, is_u, immh, immb,
9895                                opcode, rn, rd);
9896         break;
9897     case 0x14: /* SSHLL / USHLL */
9898         handle_vec_simd_wshli(s, is_q, is_u, immh, immb, opcode, rn, rd);
9899         break;
9900     case 0x1c: /* SCVTF / UCVTF */
9901         handle_simd_shift_intfp_conv(s, false, is_q, is_u, immh, immb,
9902                                      opcode, rn, rd);
9903         break;
9904     case 0xc: /* SQSHLU */
9905         if (!is_u) {
9906             unallocated_encoding(s);
9907             return;
9908         }
9909         handle_simd_qshl(s, false, is_q, false, true, immh, immb, rn, rd);
9910         break;
9911     case 0xe: /* SQSHL, UQSHL */
9912         handle_simd_qshl(s, false, is_q, is_u, is_u, immh, immb, rn, rd);
9913         break;
9914     case 0x1f: /* FCVTZS/ FCVTZU */
9915         handle_simd_shift_fpint_conv(s, false, is_q, is_u, immh, immb, rn, rd);
9916         return;
9917     default:
9918         unallocated_encoding(s);
9919         return;
9920     }
9921 }
9922
9923 /* Generate code to do a "long" addition or subtraction, ie one done in
9924  * TCGv_i64 on vector lanes twice the width specified by size.
9925  */
9926 static void gen_neon_addl(int size, bool is_sub, TCGv_i64 tcg_res,
9927                           TCGv_i64 tcg_op1, TCGv_i64 tcg_op2)
9928 {
9929     static NeonGenTwo64OpFn * const fns[3][2] = {
9930         { gen_helper_neon_addl_u16, gen_helper_neon_subl_u16 },
9931         { gen_helper_neon_addl_u32, gen_helper_neon_subl_u32 },
9932         { tcg_gen_add_i64, tcg_gen_sub_i64 },
9933     };
9934     NeonGenTwo64OpFn *genfn;
9935     assert(size < 3);
9936
9937     genfn = fns[size][is_sub];
9938     genfn(tcg_res, tcg_op1, tcg_op2);
9939 }
9940
9941 static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
9942                                 int opcode, int rd, int rn, int rm)
9943 {
9944     /* 3-reg-different widening insns: 64 x 64 -> 128 */
9945     TCGv_i64 tcg_res[2];
9946     int pass, accop;
9947
9948     tcg_res[0] = tcg_temp_new_i64();
9949     tcg_res[1] = tcg_temp_new_i64();
9950
9951     /* Does this op do an adding accumulate, a subtracting accumulate,
9952      * or no accumulate at all?
9953      */
9954     switch (opcode) {
9955     case 5:
9956     case 8:
9957     case 9:
9958         accop = 1;
9959         break;
9960     case 10:
9961     case 11:
9962         accop = -1;
9963         break;
9964     default:
9965         accop = 0;
9966         break;
9967     }
9968
9969     if (accop != 0) {
9970         read_vec_element(s, tcg_res[0], rd, 0, MO_64);
9971         read_vec_element(s, tcg_res[1], rd, 1, MO_64);
9972     }
9973
9974     /* size == 2 means two 32x32->64 operations; this is worth special
9975      * casing because we can generally handle it inline.
9976      */
9977     if (size == 2) {
9978         for (pass = 0; pass < 2; pass++) {
9979             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
9980             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
9981             TCGv_i64 tcg_passres;
9982             TCGMemOp memop = MO_32 | (is_u ? 0 : MO_SIGN);
9983
9984             int elt = pass + is_q * 2;
9985
9986             read_vec_element(s, tcg_op1, rn, elt, memop);
9987             read_vec_element(s, tcg_op2, rm, elt, memop);
9988
9989             if (accop == 0) {
9990                 tcg_passres = tcg_res[pass];
9991             } else {
9992                 tcg_passres = tcg_temp_new_i64();
9993             }
9994
9995             switch (opcode) {
9996             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
9997                 tcg_gen_add_i64(tcg_passres, tcg_op1, tcg_op2);
9998                 break;
9999             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10000                 tcg_gen_sub_i64(tcg_passres, tcg_op1, tcg_op2);
10001                 break;
10002             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10003             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10004             {
10005                 TCGv_i64 tcg_tmp1 = tcg_temp_new_i64();
10006                 TCGv_i64 tcg_tmp2 = tcg_temp_new_i64();
10007
10008                 tcg_gen_sub_i64(tcg_tmp1, tcg_op1, tcg_op2);
10009                 tcg_gen_sub_i64(tcg_tmp2, tcg_op2, tcg_op1);
10010                 tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
10011                                     tcg_passres,
10012                                     tcg_op1, tcg_op2, tcg_tmp1, tcg_tmp2);
10013                 tcg_temp_free_i64(tcg_tmp1);
10014                 tcg_temp_free_i64(tcg_tmp2);
10015                 break;
10016             }
10017             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10018             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10019             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
10020                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
10021                 break;
10022             case 9: /* SQDMLAL, SQDMLAL2 */
10023             case 11: /* SQDMLSL, SQDMLSL2 */
10024             case 13: /* SQDMULL, SQDMULL2 */
10025                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
10026                 gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
10027                                                   tcg_passres, tcg_passres);
10028                 break;
10029             default:
10030                 g_assert_not_reached();
10031             }
10032
10033             if (opcode == 9 || opcode == 11) {
10034                 /* saturating accumulate ops */
10035                 if (accop < 0) {
10036                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
10037                 }
10038                 gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
10039                                                   tcg_res[pass], tcg_passres);
10040             } else if (accop > 0) {
10041                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10042             } else if (accop < 0) {
10043                 tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10044             }
10045
10046             if (accop != 0) {
10047                 tcg_temp_free_i64(tcg_passres);
10048             }
10049
10050             tcg_temp_free_i64(tcg_op1);
10051             tcg_temp_free_i64(tcg_op2);
10052         }
10053     } else {
10054         /* size 0 or 1, generally helper functions */
10055         for (pass = 0; pass < 2; pass++) {
10056             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
10057             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10058             TCGv_i64 tcg_passres;
10059             int elt = pass + is_q * 2;
10060
10061             read_vec_element_i32(s, tcg_op1, rn, elt, MO_32);
10062             read_vec_element_i32(s, tcg_op2, rm, elt, MO_32);
10063
10064             if (accop == 0) {
10065                 tcg_passres = tcg_res[pass];
10066             } else {
10067                 tcg_passres = tcg_temp_new_i64();
10068             }
10069
10070             switch (opcode) {
10071             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10072             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10073             {
10074                 TCGv_i64 tcg_op2_64 = tcg_temp_new_i64();
10075                 static NeonGenWidenFn * const widenfns[2][2] = {
10076                     { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
10077                     { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
10078                 };
10079                 NeonGenWidenFn *widenfn = widenfns[size][is_u];
10080
10081                 widenfn(tcg_op2_64, tcg_op2);
10082                 widenfn(tcg_passres, tcg_op1);
10083                 gen_neon_addl(size, (opcode == 2), tcg_passres,
10084                               tcg_passres, tcg_op2_64);
10085                 tcg_temp_free_i64(tcg_op2_64);
10086                 break;
10087             }
10088             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10089             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10090                 if (size == 0) {
10091                     if (is_u) {
10092                         gen_helper_neon_abdl_u16(tcg_passres, tcg_op1, tcg_op2);
10093                     } else {
10094                         gen_helper_neon_abdl_s16(tcg_passres, tcg_op1, tcg_op2);
10095                     }
10096                 } else {
10097                     if (is_u) {
10098                         gen_helper_neon_abdl_u32(tcg_passres, tcg_op1, tcg_op2);
10099                     } else {
10100                         gen_helper_neon_abdl_s32(tcg_passres, tcg_op1, tcg_op2);
10101                     }
10102                 }
10103                 break;
10104             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10105             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10106             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
10107                 if (size == 0) {
10108                     if (is_u) {
10109                         gen_helper_neon_mull_u8(tcg_passres, tcg_op1, tcg_op2);
10110                     } else {
10111                         gen_helper_neon_mull_s8(tcg_passres, tcg_op1, tcg_op2);
10112                     }
10113                 } else {
10114                     if (is_u) {
10115                         gen_helper_neon_mull_u16(tcg_passres, tcg_op1, tcg_op2);
10116                     } else {
10117                         gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
10118                     }
10119                 }
10120                 break;
10121             case 9: /* SQDMLAL, SQDMLAL2 */
10122             case 11: /* SQDMLSL, SQDMLSL2 */
10123             case 13: /* SQDMULL, SQDMULL2 */
10124                 assert(size == 1);
10125                 gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
10126                 gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
10127                                                   tcg_passres, tcg_passres);
10128                 break;
10129             case 14: /* PMULL */
10130                 assert(size == 0);
10131                 gen_helper_neon_mull_p8(tcg_passres, tcg_op1, tcg_op2);
10132                 break;
10133             default:
10134                 g_assert_not_reached();
10135             }
10136             tcg_temp_free_i32(tcg_op1);
10137             tcg_temp_free_i32(tcg_op2);
10138
10139             if (accop != 0) {
10140                 if (opcode == 9 || opcode == 11) {
10141                     /* saturating accumulate ops */
10142                     if (accop < 0) {
10143                         gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
10144                     }
10145                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
10146                                                       tcg_res[pass],
10147                                                       tcg_passres);
10148                 } else {
10149                     gen_neon_addl(size, (accop < 0), tcg_res[pass],
10150                                   tcg_res[pass], tcg_passres);
10151                 }
10152                 tcg_temp_free_i64(tcg_passres);
10153             }
10154         }
10155     }
10156
10157     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
10158     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
10159     tcg_temp_free_i64(tcg_res[0]);
10160     tcg_temp_free_i64(tcg_res[1]);
10161 }
10162
10163 static void handle_3rd_wide(DisasContext *s, int is_q, int is_u, int size,
10164                             int opcode, int rd, int rn, int rm)
10165 {
10166     TCGv_i64 tcg_res[2];
10167     int part = is_q ? 2 : 0;
10168     int pass;
10169
10170     for (pass = 0; pass < 2; pass++) {
10171         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10172         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10173         TCGv_i64 tcg_op2_wide = tcg_temp_new_i64();
10174         static NeonGenWidenFn * const widenfns[3][2] = {
10175             { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
10176             { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
10177             { tcg_gen_ext_i32_i64, tcg_gen_extu_i32_i64 },
10178         };
10179         NeonGenWidenFn *widenfn = widenfns[size][is_u];
10180
10181         read_vec_element(s, tcg_op1, rn, pass, MO_64);
10182         read_vec_element_i32(s, tcg_op2, rm, part + pass, MO_32);
10183         widenfn(tcg_op2_wide, tcg_op2);
10184         tcg_temp_free_i32(tcg_op2);
10185         tcg_res[pass] = tcg_temp_new_i64();
10186         gen_neon_addl(size, (opcode == 3),
10187                       tcg_res[pass], tcg_op1, tcg_op2_wide);
10188         tcg_temp_free_i64(tcg_op1);
10189         tcg_temp_free_i64(tcg_op2_wide);
10190     }
10191
10192     for (pass = 0; pass < 2; pass++) {
10193         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
10194         tcg_temp_free_i64(tcg_res[pass]);
10195     }
10196 }
10197
10198 static void do_narrow_round_high_u32(TCGv_i32 res, TCGv_i64 in)
10199 {
10200     tcg_gen_addi_i64(in, in, 1U << 31);
10201     tcg_gen_extrh_i64_i32(res, in);
10202 }
10203
10204 static void handle_3rd_narrowing(DisasContext *s, int is_q, int is_u, int size,
10205                                  int opcode, int rd, int rn, int rm)
10206 {
10207     TCGv_i32 tcg_res[2];
10208     int part = is_q ? 2 : 0;
10209     int pass;
10210
10211     for (pass = 0; pass < 2; pass++) {
10212         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10213         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10214         TCGv_i64 tcg_wideres = tcg_temp_new_i64();
10215         static NeonGenNarrowFn * const narrowfns[3][2] = {
10216             { gen_helper_neon_narrow_high_u8,
10217               gen_helper_neon_narrow_round_high_u8 },
10218             { gen_helper_neon_narrow_high_u16,
10219               gen_helper_neon_narrow_round_high_u16 },
10220             { tcg_gen_extrh_i64_i32, do_narrow_round_high_u32 },
10221         };
10222         NeonGenNarrowFn *gennarrow = narrowfns[size][is_u];
10223
10224         read_vec_element(s, tcg_op1, rn, pass, MO_64);
10225         read_vec_element(s, tcg_op2, rm, pass, MO_64);
10226
10227         gen_neon_addl(size, (opcode == 6), tcg_wideres, tcg_op1, tcg_op2);
10228
10229         tcg_temp_free_i64(tcg_op1);
10230         tcg_temp_free_i64(tcg_op2);
10231
10232         tcg_res[pass] = tcg_temp_new_i32();
10233         gennarrow(tcg_res[pass], tcg_wideres);
10234         tcg_temp_free_i64(tcg_wideres);
10235     }
10236
10237     for (pass = 0; pass < 2; pass++) {
10238         write_vec_element_i32(s, tcg_res[pass], rd, pass + part, MO_32);
10239         tcg_temp_free_i32(tcg_res[pass]);
10240     }
10241     clear_vec_high(s, is_q, rd);
10242 }
10243
10244 static void handle_pmull_64(DisasContext *s, int is_q, int rd, int rn, int rm)
10245 {
10246     /* PMULL of 64 x 64 -> 128 is an odd special case because it
10247      * is the only three-reg-diff instruction which produces a
10248      * 128-bit wide result from a single operation. However since
10249      * it's possible to calculate the two halves more or less
10250      * separately we just use two helper calls.
10251      */
10252     TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10253     TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10254     TCGv_i64 tcg_res = tcg_temp_new_i64();
10255
10256     read_vec_element(s, tcg_op1, rn, is_q, MO_64);
10257     read_vec_element(s, tcg_op2, rm, is_q, MO_64);
10258     gen_helper_neon_pmull_64_lo(tcg_res, tcg_op1, tcg_op2);
10259     write_vec_element(s, tcg_res, rd, 0, MO_64);
10260     gen_helper_neon_pmull_64_hi(tcg_res, tcg_op1, tcg_op2);
10261     write_vec_element(s, tcg_res, rd, 1, MO_64);
10262
10263     tcg_temp_free_i64(tcg_op1);
10264     tcg_temp_free_i64(tcg_op2);
10265     tcg_temp_free_i64(tcg_res);
10266 }
10267
10268 /* AdvSIMD three different
10269  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
10270  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
10271  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
10272  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
10273  */
10274 static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
10275 {
10276     /* Instructions in this group fall into three basic classes
10277      * (in each case with the operation working on each element in
10278      * the input vectors):
10279      * (1) widening 64 x 64 -> 128 (with possibly Vd as an extra
10280      *     128 bit input)
10281      * (2) wide 64 x 128 -> 128
10282      * (3) narrowing 128 x 128 -> 64
10283      * Here we do initial decode, catch unallocated cases and
10284      * dispatch to separate functions for each class.
10285      */
10286     int is_q = extract32(insn, 30, 1);
10287     int is_u = extract32(insn, 29, 1);
10288     int size = extract32(insn, 22, 2);
10289     int opcode = extract32(insn, 12, 4);
10290     int rm = extract32(insn, 16, 5);
10291     int rn = extract32(insn, 5, 5);
10292     int rd = extract32(insn, 0, 5);
10293
10294     switch (opcode) {
10295     case 1: /* SADDW, SADDW2, UADDW, UADDW2 */
10296     case 3: /* SSUBW, SSUBW2, USUBW, USUBW2 */
10297         /* 64 x 128 -> 128 */
10298         if (size == 3) {
10299             unallocated_encoding(s);
10300             return;
10301         }
10302         if (!fp_access_check(s)) {
10303             return;
10304         }
10305         handle_3rd_wide(s, is_q, is_u, size, opcode, rd, rn, rm);
10306         break;
10307     case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */
10308     case 6: /* SUBHN, SUBHN2, RSUBHN, RSUBHN2 */
10309         /* 128 x 128 -> 64 */
10310         if (size == 3) {
10311             unallocated_encoding(s);
10312             return;
10313         }
10314         if (!fp_access_check(s)) {
10315             return;
10316         }
10317         handle_3rd_narrowing(s, is_q, is_u, size, opcode, rd, rn, rm);
10318         break;
10319     case 14: /* PMULL, PMULL2 */
10320         if (is_u || size == 1 || size == 2) {
10321             unallocated_encoding(s);
10322             return;
10323         }
10324         if (size == 3) {
10325             if (!arm_dc_feature(s, ARM_FEATURE_V8_PMULL)) {
10326                 unallocated_encoding(s);
10327                 return;
10328             }
10329             if (!fp_access_check(s)) {
10330                 return;
10331             }
10332             handle_pmull_64(s, is_q, rd, rn, rm);
10333             return;
10334         }
10335         goto is_widening;
10336     case 9: /* SQDMLAL, SQDMLAL2 */
10337     case 11: /* SQDMLSL, SQDMLSL2 */
10338     case 13: /* SQDMULL, SQDMULL2 */
10339         if (is_u || size == 0) {
10340             unallocated_encoding(s);
10341             return;
10342         }
10343         /* fall through */
10344     case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10345     case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10346     case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10347     case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10348     case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10349     case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10350     case 12: /* SMULL, SMULL2, UMULL, UMULL2 */
10351         /* 64 x 64 -> 128 */
10352         if (size == 3) {
10353             unallocated_encoding(s);
10354             return;
10355         }
10356     is_widening:
10357         if (!fp_access_check(s)) {
10358             return;
10359         }
10360
10361         handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm);
10362         break;
10363     default:
10364         /* opcode 15 not allocated */
10365         unallocated_encoding(s);
10366         break;
10367     }
10368 }
10369
10370 static void gen_bsl_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
10371 {
10372     tcg_gen_xor_i64(rn, rn, rm);
10373     tcg_gen_and_i64(rn, rn, rd);
10374     tcg_gen_xor_i64(rd, rm, rn);
10375 }
10376
10377 static void gen_bit_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
10378 {
10379     tcg_gen_xor_i64(rn, rn, rd);
10380     tcg_gen_and_i64(rn, rn, rm);
10381     tcg_gen_xor_i64(rd, rd, rn);
10382 }
10383
10384 static void gen_bif_i64(TCGv_i64 rd, TCGv_i64 rn, TCGv_i64 rm)
10385 {
10386     tcg_gen_xor_i64(rn, rn, rd);
10387     tcg_gen_andc_i64(rn, rn, rm);
10388     tcg_gen_xor_i64(rd, rd, rn);
10389 }
10390
10391 static void gen_bsl_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
10392 {
10393     tcg_gen_xor_vec(vece, rn, rn, rm);
10394     tcg_gen_and_vec(vece, rn, rn, rd);
10395     tcg_gen_xor_vec(vece, rd, rm, rn);
10396 }
10397
10398 static void gen_bit_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
10399 {
10400     tcg_gen_xor_vec(vece, rn, rn, rd);
10401     tcg_gen_and_vec(vece, rn, rn, rm);
10402     tcg_gen_xor_vec(vece, rd, rd, rn);
10403 }
10404
10405 static void gen_bif_vec(unsigned vece, TCGv_vec rd, TCGv_vec rn, TCGv_vec rm)
10406 {
10407     tcg_gen_xor_vec(vece, rn, rn, rd);
10408     tcg_gen_andc_vec(vece, rn, rn, rm);
10409     tcg_gen_xor_vec(vece, rd, rd, rn);
10410 }
10411
10412 /* Logic op (opcode == 3) subgroup of C3.6.16. */
10413 static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
10414 {
10415     static const GVecGen3 bsl_op = {
10416         .fni8 = gen_bsl_i64,
10417         .fniv = gen_bsl_vec,
10418         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
10419         .load_dest = true
10420     };
10421     static const GVecGen3 bit_op = {
10422         .fni8 = gen_bit_i64,
10423         .fniv = gen_bit_vec,
10424         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
10425         .load_dest = true
10426     };
10427     static const GVecGen3 bif_op = {
10428         .fni8 = gen_bif_i64,
10429         .fniv = gen_bif_vec,
10430         .prefer_i64 = TCG_TARGET_REG_BITS == 64,
10431         .load_dest = true
10432     };
10433
10434     int rd = extract32(insn, 0, 5);
10435     int rn = extract32(insn, 5, 5);
10436     int rm = extract32(insn, 16, 5);
10437     int size = extract32(insn, 22, 2);
10438     bool is_u = extract32(insn, 29, 1);
10439     bool is_q = extract32(insn, 30, 1);
10440
10441     if (!fp_access_check(s)) {
10442         return;
10443     }
10444
10445     switch (size + 4 * is_u) {
10446     case 0: /* AND */
10447         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_and, 0);
10448         return;
10449     case 1: /* BIC */
10450         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_andc, 0);
10451         return;
10452     case 2: /* ORR */
10453         if (rn == rm) { /* MOV */
10454             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_mov, 0);
10455         } else {
10456             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0);
10457         }
10458         return;
10459     case 3: /* ORN */
10460         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_orc, 0);
10461         return;
10462     case 4: /* EOR */
10463         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_xor, 0);
10464         return;
10465
10466     case 5: /* BSL bitwise select */
10467         gen_gvec_op3(s, is_q, rd, rn, rm, &bsl_op);
10468         return;
10469     case 6: /* BIT, bitwise insert if true */
10470         gen_gvec_op3(s, is_q, rd, rn, rm, &bit_op);
10471         return;
10472     case 7: /* BIF, bitwise insert if false */
10473         gen_gvec_op3(s, is_q, rd, rn, rm, &bif_op);
10474         return;
10475
10476     default:
10477         g_assert_not_reached();
10478     }
10479 }
10480
10481 /* Pairwise op subgroup of C3.6.16.
10482  *
10483  * This is called directly or via the handle_3same_float for float pairwise
10484  * operations where the opcode and size are calculated differently.
10485  */
10486 static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
10487                                    int size, int rn, int rm, int rd)
10488 {
10489     TCGv_ptr fpst;
10490     int pass;
10491
10492     /* Floating point operations need fpst */
10493     if (opcode >= 0x58) {
10494         fpst = get_fpstatus_ptr(false);
10495     } else {
10496         fpst = NULL;
10497     }
10498
10499     if (!fp_access_check(s)) {
10500         return;
10501     }
10502
10503     /* These operations work on the concatenated rm:rn, with each pair of
10504      * adjacent elements being operated on to produce an element in the result.
10505      */
10506     if (size == 3) {
10507         TCGv_i64 tcg_res[2];
10508
10509         for (pass = 0; pass < 2; pass++) {
10510             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10511             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10512             int passreg = (pass == 0) ? rn : rm;
10513
10514             read_vec_element(s, tcg_op1, passreg, 0, MO_64);
10515             read_vec_element(s, tcg_op2, passreg, 1, MO_64);
10516             tcg_res[pass] = tcg_temp_new_i64();
10517
10518             switch (opcode) {
10519             case 0x17: /* ADDP */
10520                 tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
10521                 break;
10522             case 0x58: /* FMAXNMP */
10523                 gen_helper_vfp_maxnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10524                 break;
10525             case 0x5a: /* FADDP */
10526                 gen_helper_vfp_addd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10527                 break;
10528             case 0x5e: /* FMAXP */
10529                 gen_helper_vfp_maxd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10530                 break;
10531             case 0x78: /* FMINNMP */
10532                 gen_helper_vfp_minnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10533                 break;
10534             case 0x7e: /* FMINP */
10535                 gen_helper_vfp_mind(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10536                 break;
10537             default:
10538                 g_assert_not_reached();
10539             }
10540
10541             tcg_temp_free_i64(tcg_op1);
10542             tcg_temp_free_i64(tcg_op2);
10543         }
10544
10545         for (pass = 0; pass < 2; pass++) {
10546             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
10547             tcg_temp_free_i64(tcg_res[pass]);
10548         }
10549     } else {
10550         int maxpass = is_q ? 4 : 2;
10551         TCGv_i32 tcg_res[4];
10552
10553         for (pass = 0; pass < maxpass; pass++) {
10554             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
10555             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10556             NeonGenTwoOpFn *genfn = NULL;
10557             int passreg = pass < (maxpass / 2) ? rn : rm;
10558             int passelt = (is_q && (pass & 1)) ? 2 : 0;
10559
10560             read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_32);
10561             read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_32);
10562             tcg_res[pass] = tcg_temp_new_i32();
10563
10564             switch (opcode) {
10565             case 0x17: /* ADDP */
10566             {
10567                 static NeonGenTwoOpFn * const fns[3] = {
10568                     gen_helper_neon_padd_u8,
10569                     gen_helper_neon_padd_u16,
10570                     tcg_gen_add_i32,
10571                 };
10572                 genfn = fns[size];
10573                 break;
10574             }
10575             case 0x14: /* SMAXP, UMAXP */
10576             {
10577                 static NeonGenTwoOpFn * const fns[3][2] = {
10578                     { gen_helper_neon_pmax_s8, gen_helper_neon_pmax_u8 },
10579                     { gen_helper_neon_pmax_s16, gen_helper_neon_pmax_u16 },
10580                     { tcg_gen_smax_i32, tcg_gen_umax_i32 },
10581                 };
10582                 genfn = fns[size][u];
10583                 break;
10584             }
10585             case 0x15: /* SMINP, UMINP */
10586             {
10587                 static NeonGenTwoOpFn * const fns[3][2] = {
10588                     { gen_helper_neon_pmin_s8, gen_helper_neon_pmin_u8 },
10589                     { gen_helper_neon_pmin_s16, gen_helper_neon_pmin_u16 },
10590                     { tcg_gen_smin_i32, tcg_gen_umin_i32 },
10591                 };
10592                 genfn = fns[size][u];
10593                 break;
10594             }
10595             /* The FP operations are all on single floats (32 bit) */
10596             case 0x58: /* FMAXNMP */
10597                 gen_helper_vfp_maxnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10598                 break;
10599             case 0x5a: /* FADDP */
10600                 gen_helper_vfp_adds(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10601                 break;
10602             case 0x5e: /* FMAXP */
10603                 gen_helper_vfp_maxs(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10604                 break;
10605             case 0x78: /* FMINNMP */
10606                 gen_helper_vfp_minnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10607                 break;
10608             case 0x7e: /* FMINP */
10609                 gen_helper_vfp_mins(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10610                 break;
10611             default:
10612                 g_assert_not_reached();
10613             }
10614
10615             /* FP ops called directly, otherwise call now */
10616             if (genfn) {
10617                 genfn(tcg_res[pass], tcg_op1, tcg_op2);
10618             }
10619
10620             tcg_temp_free_i32(tcg_op1);
10621             tcg_temp_free_i32(tcg_op2);
10622         }
10623
10624         for (pass = 0; pass < maxpass; pass++) {
10625             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
10626             tcg_temp_free_i32(tcg_res[pass]);
10627         }
10628         clear_vec_high(s, is_q, rd);
10629     }
10630
10631     if (fpst) {
10632         tcg_temp_free_ptr(fpst);
10633     }
10634 }
10635
10636 /* Floating point op subgroup of C3.6.16. */
10637 static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
10638 {
10639     /* For floating point ops, the U, size[1] and opcode bits
10640      * together indicate the operation. size[0] indicates single
10641      * or double.
10642      */
10643     int fpopcode = extract32(insn, 11, 5)
10644         | (extract32(insn, 23, 1) << 5)
10645         | (extract32(insn, 29, 1) << 6);
10646     int is_q = extract32(insn, 30, 1);
10647     int size = extract32(insn, 22, 1);
10648     int rm = extract32(insn, 16, 5);
10649     int rn = extract32(insn, 5, 5);
10650     int rd = extract32(insn, 0, 5);
10651
10652     int datasize = is_q ? 128 : 64;
10653     int esize = 32 << size;
10654     int elements = datasize / esize;
10655
10656     if (size == 1 && !is_q) {
10657         unallocated_encoding(s);
10658         return;
10659     }
10660
10661     switch (fpopcode) {
10662     case 0x58: /* FMAXNMP */
10663     case 0x5a: /* FADDP */
10664     case 0x5e: /* FMAXP */
10665     case 0x78: /* FMINNMP */
10666     case 0x7e: /* FMINP */
10667         if (size && !is_q) {
10668             unallocated_encoding(s);
10669             return;
10670         }
10671         handle_simd_3same_pair(s, is_q, 0, fpopcode, size ? MO_64 : MO_32,
10672                                rn, rm, rd);
10673         return;
10674     case 0x1b: /* FMULX */
10675     case 0x1f: /* FRECPS */
10676     case 0x3f: /* FRSQRTS */
10677     case 0x5d: /* FACGE */
10678     case 0x7d: /* FACGT */
10679     case 0x19: /* FMLA */
10680     case 0x39: /* FMLS */
10681     case 0x18: /* FMAXNM */
10682     case 0x1a: /* FADD */
10683     case 0x1c: /* FCMEQ */
10684     case 0x1e: /* FMAX */
10685     case 0x38: /* FMINNM */
10686     case 0x3a: /* FSUB */
10687     case 0x3e: /* FMIN */
10688     case 0x5b: /* FMUL */
10689     case 0x5c: /* FCMGE */
10690     case 0x5f: /* FDIV */
10691     case 0x7a: /* FABD */
10692     case 0x7c: /* FCMGT */
10693         if (!fp_access_check(s)) {
10694             return;
10695         }
10696
10697         handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
10698         return;
10699     default:
10700         unallocated_encoding(s);
10701         return;
10702     }
10703 }
10704
10705 static void gen_mla8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
10706 {
10707     gen_helper_neon_mul_u8(a, a, b);
10708     gen_helper_neon_add_u8(d, d, a);
10709 }
10710
10711 static void gen_mla16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
10712 {
10713     gen_helper_neon_mul_u16(a, a, b);
10714     gen_helper_neon_add_u16(d, d, a);
10715 }
10716
10717 static void gen_mla32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
10718 {
10719     tcg_gen_mul_i32(a, a, b);
10720     tcg_gen_add_i32(d, d, a);
10721 }
10722
10723 static void gen_mla64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
10724 {
10725     tcg_gen_mul_i64(a, a, b);
10726     tcg_gen_add_i64(d, d, a);
10727 }
10728
10729 static void gen_mla_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
10730 {
10731     tcg_gen_mul_vec(vece, a, a, b);
10732     tcg_gen_add_vec(vece, d, d, a);
10733 }
10734
10735 static void gen_mls8_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
10736 {
10737     gen_helper_neon_mul_u8(a, a, b);
10738     gen_helper_neon_sub_u8(d, d, a);
10739 }
10740
10741 static void gen_mls16_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
10742 {
10743     gen_helper_neon_mul_u16(a, a, b);
10744     gen_helper_neon_sub_u16(d, d, a);
10745 }
10746
10747 static void gen_mls32_i32(TCGv_i32 d, TCGv_i32 a, TCGv_i32 b)
10748 {
10749     tcg_gen_mul_i32(a, a, b);
10750     tcg_gen_sub_i32(d, d, a);
10751 }
10752
10753 static void gen_mls64_i64(TCGv_i64 d, TCGv_i64 a, TCGv_i64 b)
10754 {
10755     tcg_gen_mul_i64(a, a, b);
10756     tcg_gen_sub_i64(d, d, a);
10757 }
10758
10759 static void gen_mls_vec(unsigned vece, TCGv_vec d, TCGv_vec a, TCGv_vec b)
10760 {
10761     tcg_gen_mul_vec(vece, a, a, b);
10762     tcg_gen_sub_vec(vece, d, d, a);
10763 }
10764
10765 /* Integer op subgroup of C3.6.16. */
10766 static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
10767 {
10768     static const GVecGen3 cmtst_op[4] = {
10769         { .fni4 = gen_helper_neon_tst_u8,
10770           .fniv = gen_cmtst_vec,
10771           .vece = MO_8 },
10772         { .fni4 = gen_helper_neon_tst_u16,
10773           .fniv = gen_cmtst_vec,
10774           .vece = MO_16 },
10775         { .fni4 = gen_cmtst_i32,
10776           .fniv = gen_cmtst_vec,
10777           .vece = MO_32 },
10778         { .fni8 = gen_cmtst_i64,
10779           .fniv = gen_cmtst_vec,
10780           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
10781           .vece = MO_64 },
10782     };
10783     static const GVecGen3 mla_op[4] = {
10784         { .fni4 = gen_mla8_i32,
10785           .fniv = gen_mla_vec,
10786           .opc = INDEX_op_mul_vec,
10787           .load_dest = true,
10788           .vece = MO_8 },
10789         { .fni4 = gen_mla16_i32,
10790           .fniv = gen_mla_vec,
10791           .opc = INDEX_op_mul_vec,
10792           .load_dest = true,
10793           .vece = MO_16 },
10794         { .fni4 = gen_mla32_i32,
10795           .fniv = gen_mla_vec,
10796           .opc = INDEX_op_mul_vec,
10797           .load_dest = true,
10798           .vece = MO_32 },
10799         { .fni8 = gen_mla64_i64,
10800           .fniv = gen_mla_vec,
10801           .opc = INDEX_op_mul_vec,
10802           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
10803           .load_dest = true,
10804           .vece = MO_64 },
10805     };
10806     static const GVecGen3 mls_op[4] = {
10807         { .fni4 = gen_mls8_i32,
10808           .fniv = gen_mls_vec,
10809           .opc = INDEX_op_mul_vec,
10810           .load_dest = true,
10811           .vece = MO_8 },
10812         { .fni4 = gen_mls16_i32,
10813           .fniv = gen_mls_vec,
10814           .opc = INDEX_op_mul_vec,
10815           .load_dest = true,
10816           .vece = MO_16 },
10817         { .fni4 = gen_mls32_i32,
10818           .fniv = gen_mls_vec,
10819           .opc = INDEX_op_mul_vec,
10820           .load_dest = true,
10821           .vece = MO_32 },
10822         { .fni8 = gen_mls64_i64,
10823           .fniv = gen_mls_vec,
10824           .opc = INDEX_op_mul_vec,
10825           .prefer_i64 = TCG_TARGET_REG_BITS == 64,
10826           .load_dest = true,
10827           .vece = MO_64 },
10828     };
10829
10830     int is_q = extract32(insn, 30, 1);
10831     int u = extract32(insn, 29, 1);
10832     int size = extract32(insn, 22, 2);
10833     int opcode = extract32(insn, 11, 5);
10834     int rm = extract32(insn, 16, 5);
10835     int rn = extract32(insn, 5, 5);
10836     int rd = extract32(insn, 0, 5);
10837     int pass;
10838     TCGCond cond;
10839
10840     switch (opcode) {
10841     case 0x13: /* MUL, PMUL */
10842         if (u && size != 0) {
10843             unallocated_encoding(s);
10844             return;
10845         }
10846         /* fall through */
10847     case 0x0: /* SHADD, UHADD */
10848     case 0x2: /* SRHADD, URHADD */
10849     case 0x4: /* SHSUB, UHSUB */
10850     case 0xc: /* SMAX, UMAX */
10851     case 0xd: /* SMIN, UMIN */
10852     case 0xe: /* SABD, UABD */
10853     case 0xf: /* SABA, UABA */
10854     case 0x12: /* MLA, MLS */
10855         if (size == 3) {
10856             unallocated_encoding(s);
10857             return;
10858         }
10859         break;
10860     case 0x16: /* SQDMULH, SQRDMULH */
10861         if (size == 0 || size == 3) {
10862             unallocated_encoding(s);
10863             return;
10864         }
10865         break;
10866     default:
10867         if (size == 3 && !is_q) {
10868             unallocated_encoding(s);
10869             return;
10870         }
10871         break;
10872     }
10873
10874     if (!fp_access_check(s)) {
10875         return;
10876     }
10877
10878     switch (opcode) {
10879     case 0x10: /* ADD, SUB */
10880         if (u) {
10881             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
10882         } else {
10883             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_add, size);
10884         }
10885         return;
10886     case 0x13: /* MUL, PMUL */
10887         if (!u) { /* MUL */
10888             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_mul, size);
10889             return;
10890         }
10891         break;
10892     case 0x12: /* MLA, MLS */
10893         if (u) {
10894             gen_gvec_op3(s, is_q, rd, rn, rm, &mls_op[size]);
10895         } else {
10896             gen_gvec_op3(s, is_q, rd, rn, rm, &mla_op[size]);
10897         }
10898         return;
10899     case 0x11:
10900         if (!u) { /* CMTST */
10901             gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]);
10902             return;
10903         }
10904         /* else CMEQ */
10905         cond = TCG_COND_EQ;
10906         goto do_gvec_cmp;
10907     case 0x06: /* CMGT, CMHI */
10908         cond = u ? TCG_COND_GTU : TCG_COND_GT;
10909         goto do_gvec_cmp;
10910     case 0x07: /* CMGE, CMHS */
10911         cond = u ? TCG_COND_GEU : TCG_COND_GE;
10912     do_gvec_cmp:
10913         tcg_gen_gvec_cmp(cond, size, vec_full_reg_offset(s, rd),
10914                          vec_full_reg_offset(s, rn),
10915                          vec_full_reg_offset(s, rm),
10916                          is_q ? 16 : 8, vec_full_reg_size(s));
10917         return;
10918     }
10919
10920     if (size == 3) {
10921         assert(is_q);
10922         for (pass = 0; pass < 2; pass++) {
10923             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10924             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10925             TCGv_i64 tcg_res = tcg_temp_new_i64();
10926
10927             read_vec_element(s, tcg_op1, rn, pass, MO_64);
10928             read_vec_element(s, tcg_op2, rm, pass, MO_64);
10929
10930             handle_3same_64(s, opcode, u, tcg_res, tcg_op1, tcg_op2);
10931
10932             write_vec_element(s, tcg_res, rd, pass, MO_64);
10933
10934             tcg_temp_free_i64(tcg_res);
10935             tcg_temp_free_i64(tcg_op1);
10936             tcg_temp_free_i64(tcg_op2);
10937         }
10938     } else {
10939         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
10940             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
10941             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10942             TCGv_i32 tcg_res = tcg_temp_new_i32();
10943             NeonGenTwoOpFn *genfn = NULL;
10944             NeonGenTwoOpEnvFn *genenvfn = NULL;
10945
10946             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
10947             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
10948
10949             switch (opcode) {
10950             case 0x0: /* SHADD, UHADD */
10951             {
10952                 static NeonGenTwoOpFn * const fns[3][2] = {
10953                     { gen_helper_neon_hadd_s8, gen_helper_neon_hadd_u8 },
10954                     { gen_helper_neon_hadd_s16, gen_helper_neon_hadd_u16 },
10955                     { gen_helper_neon_hadd_s32, gen_helper_neon_hadd_u32 },
10956                 };
10957                 genfn = fns[size][u];
10958                 break;
10959             }
10960             case 0x1: /* SQADD, UQADD */
10961             {
10962                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
10963                     { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 },
10964                     { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 },
10965                     { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 },
10966                 };
10967                 genenvfn = fns[size][u];
10968                 break;
10969             }
10970             case 0x2: /* SRHADD, URHADD */
10971             {
10972                 static NeonGenTwoOpFn * const fns[3][2] = {
10973                     { gen_helper_neon_rhadd_s8, gen_helper_neon_rhadd_u8 },
10974                     { gen_helper_neon_rhadd_s16, gen_helper_neon_rhadd_u16 },
10975                     { gen_helper_neon_rhadd_s32, gen_helper_neon_rhadd_u32 },
10976                 };
10977                 genfn = fns[size][u];
10978                 break;
10979             }
10980             case 0x4: /* SHSUB, UHSUB */
10981             {
10982                 static NeonGenTwoOpFn * const fns[3][2] = {
10983                     { gen_helper_neon_hsub_s8, gen_helper_neon_hsub_u8 },
10984                     { gen_helper_neon_hsub_s16, gen_helper_neon_hsub_u16 },
10985                     { gen_helper_neon_hsub_s32, gen_helper_neon_hsub_u32 },
10986                 };
10987                 genfn = fns[size][u];
10988                 break;
10989             }
10990             case 0x5: /* SQSUB, UQSUB */
10991             {
10992                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
10993                     { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 },
10994                     { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 },
10995                     { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 },
10996                 };
10997                 genenvfn = fns[size][u];
10998                 break;
10999             }
11000             case 0x8: /* SSHL, USHL */
11001             {
11002                 static NeonGenTwoOpFn * const fns[3][2] = {
11003                     { gen_helper_neon_shl_s8, gen_helper_neon_shl_u8 },
11004                     { gen_helper_neon_shl_s16, gen_helper_neon_shl_u16 },
11005                     { gen_helper_neon_shl_s32, gen_helper_neon_shl_u32 },
11006                 };
11007                 genfn = fns[size][u];
11008                 break;
11009             }
11010             case 0x9: /* SQSHL, UQSHL */
11011             {
11012                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
11013                     { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
11014                     { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
11015                     { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
11016                 };
11017                 genenvfn = fns[size][u];
11018                 break;
11019             }
11020             case 0xa: /* SRSHL, URSHL */
11021             {
11022                 static NeonGenTwoOpFn * const fns[3][2] = {
11023                     { gen_helper_neon_rshl_s8, gen_helper_neon_rshl_u8 },
11024                     { gen_helper_neon_rshl_s16, gen_helper_neon_rshl_u16 },
11025                     { gen_helper_neon_rshl_s32, gen_helper_neon_rshl_u32 },
11026                 };
11027                 genfn = fns[size][u];
11028                 break;
11029             }
11030             case 0xb: /* SQRSHL, UQRSHL */
11031             {
11032                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
11033                     { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
11034                     { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
11035                     { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
11036                 };
11037                 genenvfn = fns[size][u];
11038                 break;
11039             }
11040             case 0xc: /* SMAX, UMAX */
11041             {
11042                 static NeonGenTwoOpFn * const fns[3][2] = {
11043                     { gen_helper_neon_max_s8, gen_helper_neon_max_u8 },
11044                     { gen_helper_neon_max_s16, gen_helper_neon_max_u16 },
11045                     { tcg_gen_smax_i32, tcg_gen_umax_i32 },
11046                 };
11047                 genfn = fns[size][u];
11048                 break;
11049             }
11050
11051             case 0xd: /* SMIN, UMIN */
11052             {
11053                 static NeonGenTwoOpFn * const fns[3][2] = {
11054                     { gen_helper_neon_min_s8, gen_helper_neon_min_u8 },
11055                     { gen_helper_neon_min_s16, gen_helper_neon_min_u16 },
11056                     { tcg_gen_smin_i32, tcg_gen_umin_i32 },
11057                 };
11058                 genfn = fns[size][u];
11059                 break;
11060             }
11061             case 0xe: /* SABD, UABD */
11062             case 0xf: /* SABA, UABA */
11063             {
11064                 static NeonGenTwoOpFn * const fns[3][2] = {
11065                     { gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 },
11066                     { gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 },
11067                     { gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 },
11068                 };
11069                 genfn = fns[size][u];
11070                 break;
11071             }
11072             case 0x13: /* MUL, PMUL */
11073                 assert(u); /* PMUL */
11074                 assert(size == 0);
11075                 genfn = gen_helper_neon_mul_p8;
11076                 break;
11077             case 0x16: /* SQDMULH, SQRDMULH */
11078             {
11079                 static NeonGenTwoOpEnvFn * const fns[2][2] = {
11080                     { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
11081                     { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
11082                 };
11083                 assert(size == 1 || size == 2);
11084                 genenvfn = fns[size - 1][u];
11085                 break;
11086             }
11087             default:
11088                 g_assert_not_reached();
11089             }
11090
11091             if (genenvfn) {
11092                 genenvfn(tcg_res, cpu_env, tcg_op1, tcg_op2);
11093             } else {
11094                 genfn(tcg_res, tcg_op1, tcg_op2);
11095             }
11096
11097             if (opcode == 0xf) {
11098                 /* SABA, UABA: accumulating ops */
11099                 static NeonGenTwoOpFn * const fns[3] = {
11100                     gen_helper_neon_add_u8,
11101                     gen_helper_neon_add_u16,
11102                     tcg_gen_add_i32,
11103                 };
11104
11105                 read_vec_element_i32(s, tcg_op1, rd, pass, MO_32);
11106                 fns[size](tcg_res, tcg_op1, tcg_res);
11107             }
11108
11109             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
11110
11111             tcg_temp_free_i32(tcg_res);
11112             tcg_temp_free_i32(tcg_op1);
11113             tcg_temp_free_i32(tcg_op2);
11114         }
11115     }
11116     clear_vec_high(s, is_q, rd);
11117 }
11118
11119 /* AdvSIMD three same
11120  *  31  30  29  28       24 23  22  21 20  16 15    11  10 9    5 4    0
11121  * +---+---+---+-----------+------+---+------+--------+---+------+------+
11122  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
11123  * +---+---+---+-----------+------+---+------+--------+---+------+------+
11124  */
11125 static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
11126 {
11127     int opcode = extract32(insn, 11, 5);
11128
11129     switch (opcode) {
11130     case 0x3: /* logic ops */
11131         disas_simd_3same_logic(s, insn);
11132         break;
11133     case 0x17: /* ADDP */
11134     case 0x14: /* SMAXP, UMAXP */
11135     case 0x15: /* SMINP, UMINP */
11136     {
11137         /* Pairwise operations */
11138         int is_q = extract32(insn, 30, 1);
11139         int u = extract32(insn, 29, 1);
11140         int size = extract32(insn, 22, 2);
11141         int rm = extract32(insn, 16, 5);
11142         int rn = extract32(insn, 5, 5);
11143         int rd = extract32(insn, 0, 5);
11144         if (opcode == 0x17) {
11145             if (u || (size == 3 && !is_q)) {
11146                 unallocated_encoding(s);
11147                 return;
11148             }
11149         } else {
11150             if (size == 3) {
11151                 unallocated_encoding(s);
11152                 return;
11153             }
11154         }
11155         handle_simd_3same_pair(s, is_q, u, opcode, size, rn, rm, rd);
11156         break;
11157     }
11158     case 0x18 ... 0x31:
11159         /* floating point ops, sz[1] and U are part of opcode */
11160         disas_simd_3same_float(s, insn);
11161         break;
11162     default:
11163         disas_simd_3same_int(s, insn);
11164         break;
11165     }
11166 }
11167
11168 /*
11169  * Advanced SIMD three same (ARMv8.2 FP16 variants)
11170  *
11171  *  31  30  29  28       24 23  22 21 20  16 15 14 13    11 10  9    5 4    0
11172  * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
11173  * | 0 | Q | U | 0 1 1 1 0 | a | 1 0 |  Rm  | 0 0 | opcode | 1 |  Rn  |  Rd  |
11174  * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
11175  *
11176  * This includes FMULX, FCMEQ (register), FRECPS, FRSQRTS, FCMGE
11177  * (register), FACGE, FABD, FCMGT (register) and FACGT.
11178  *
11179  */
11180 static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
11181 {
11182     int opcode, fpopcode;
11183     int is_q, u, a, rm, rn, rd;
11184     int datasize, elements;
11185     int pass;
11186     TCGv_ptr fpst;
11187     bool pairwise = false;
11188
11189     if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
11190         unallocated_encoding(s);
11191         return;
11192     }
11193
11194     if (!fp_access_check(s)) {
11195         return;
11196     }
11197
11198     /* For these floating point ops, the U, a and opcode bits
11199      * together indicate the operation.
11200      */
11201     opcode = extract32(insn, 11, 3);
11202     u = extract32(insn, 29, 1);
11203     a = extract32(insn, 23, 1);
11204     is_q = extract32(insn, 30, 1);
11205     rm = extract32(insn, 16, 5);
11206     rn = extract32(insn, 5, 5);
11207     rd = extract32(insn, 0, 5);
11208
11209     fpopcode = opcode | (a << 3) |  (u << 4);
11210     datasize = is_q ? 128 : 64;
11211     elements = datasize / 16;
11212
11213     switch (fpopcode) {
11214     case 0x10: /* FMAXNMP */
11215     case 0x12: /* FADDP */
11216     case 0x16: /* FMAXP */
11217     case 0x18: /* FMINNMP */
11218     case 0x1e: /* FMINP */
11219         pairwise = true;
11220         break;
11221     }
11222
11223     fpst = get_fpstatus_ptr(true);
11224
11225     if (pairwise) {
11226         int maxpass = is_q ? 8 : 4;
11227         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11228         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11229         TCGv_i32 tcg_res[8];
11230
11231         for (pass = 0; pass < maxpass; pass++) {
11232             int passreg = pass < (maxpass / 2) ? rn : rm;
11233             int passelt = (pass << 1) & (maxpass - 1);
11234
11235             read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_16);
11236             read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_16);
11237             tcg_res[pass] = tcg_temp_new_i32();
11238
11239             switch (fpopcode) {
11240             case 0x10: /* FMAXNMP */
11241                 gen_helper_advsimd_maxnumh(tcg_res[pass], tcg_op1, tcg_op2,
11242                                            fpst);
11243                 break;
11244             case 0x12: /* FADDP */
11245                 gen_helper_advsimd_addh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11246                 break;
11247             case 0x16: /* FMAXP */
11248                 gen_helper_advsimd_maxh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11249                 break;
11250             case 0x18: /* FMINNMP */
11251                 gen_helper_advsimd_minnumh(tcg_res[pass], tcg_op1, tcg_op2,
11252                                            fpst);
11253                 break;
11254             case 0x1e: /* FMINP */
11255                 gen_helper_advsimd_minh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11256                 break;
11257             default:
11258                 g_assert_not_reached();
11259             }
11260         }
11261
11262         for (pass = 0; pass < maxpass; pass++) {
11263             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_16);
11264             tcg_temp_free_i32(tcg_res[pass]);
11265         }
11266
11267         tcg_temp_free_i32(tcg_op1);
11268         tcg_temp_free_i32(tcg_op2);
11269
11270     } else {
11271         for (pass = 0; pass < elements; pass++) {
11272             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11273             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11274             TCGv_i32 tcg_res = tcg_temp_new_i32();
11275
11276             read_vec_element_i32(s, tcg_op1, rn, pass, MO_16);
11277             read_vec_element_i32(s, tcg_op2, rm, pass, MO_16);
11278
11279             switch (fpopcode) {
11280             case 0x0: /* FMAXNM */
11281                 gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
11282                 break;
11283             case 0x1: /* FMLA */
11284                 read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11285                 gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
11286                                            fpst);
11287                 break;
11288             case 0x2: /* FADD */
11289                 gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
11290                 break;
11291             case 0x3: /* FMULX */
11292                 gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
11293                 break;
11294             case 0x4: /* FCMEQ */
11295                 gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11296                 break;
11297             case 0x6: /* FMAX */
11298                 gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
11299                 break;
11300             case 0x7: /* FRECPS */
11301                 gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11302                 break;
11303             case 0x8: /* FMINNM */
11304                 gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
11305                 break;
11306             case 0x9: /* FMLS */
11307                 /* As usual for ARM, separate negation for fused multiply-add */
11308                 tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
11309                 read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11310                 gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
11311                                            fpst);
11312                 break;
11313             case 0xa: /* FSUB */
11314                 gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
11315                 break;
11316             case 0xe: /* FMIN */
11317                 gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
11318                 break;
11319             case 0xf: /* FRSQRTS */
11320                 gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11321                 break;
11322             case 0x13: /* FMUL */
11323                 gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
11324                 break;
11325             case 0x14: /* FCMGE */
11326                 gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11327                 break;
11328             case 0x15: /* FACGE */
11329                 gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11330                 break;
11331             case 0x17: /* FDIV */
11332                 gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
11333                 break;
11334             case 0x1a: /* FABD */
11335                 gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
11336                 tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
11337                 break;
11338             case 0x1c: /* FCMGT */
11339                 gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11340                 break;
11341             case 0x1d: /* FACGT */
11342                 gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11343                 break;
11344             default:
11345                 fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n",
11346                         __func__, insn, fpopcode, s->pc);
11347                 g_assert_not_reached();
11348             }
11349
11350             write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11351             tcg_temp_free_i32(tcg_res);
11352             tcg_temp_free_i32(tcg_op1);
11353             tcg_temp_free_i32(tcg_op2);
11354         }
11355     }
11356
11357     tcg_temp_free_ptr(fpst);
11358
11359     clear_vec_high(s, is_q, rd);
11360 }
11361
11362 /* AdvSIMD three same extra
11363  *  31   30  29 28       24 23  22  21 20  16  15 14    11  10 9  5 4  0
11364  * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
11365  * | 0 | Q | U | 0 1 1 1 0 | size | 0 |  Rm  | 1 | opcode | 1 | Rn | Rd |
11366  * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
11367  */
11368 static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
11369 {
11370     int rd = extract32(insn, 0, 5);
11371     int rn = extract32(insn, 5, 5);
11372     int opcode = extract32(insn, 11, 4);
11373     int rm = extract32(insn, 16, 5);
11374     int size = extract32(insn, 22, 2);
11375     bool u = extract32(insn, 29, 1);
11376     bool is_q = extract32(insn, 30, 1);
11377     int feature, rot;
11378
11379     switch (u * 16 + opcode) {
11380     case 0x10: /* SQRDMLAH (vector) */
11381     case 0x11: /* SQRDMLSH (vector) */
11382         if (size != 1 && size != 2) {
11383             unallocated_encoding(s);
11384             return;
11385         }
11386         feature = ARM_FEATURE_V8_RDM;
11387         break;
11388     case 0x8: /* FCMLA, #0 */
11389     case 0x9: /* FCMLA, #90 */
11390     case 0xa: /* FCMLA, #180 */
11391     case 0xb: /* FCMLA, #270 */
11392     case 0xc: /* FCADD, #90 */
11393     case 0xe: /* FCADD, #270 */
11394         if (size == 0
11395             || (size == 1 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16))
11396             || (size == 3 && !is_q)) {
11397             unallocated_encoding(s);
11398             return;
11399         }
11400         feature = ARM_FEATURE_V8_FCMA;
11401         break;
11402     default:
11403         unallocated_encoding(s);
11404         return;
11405     }
11406     if (!arm_dc_feature(s, feature)) {
11407         unallocated_encoding(s);
11408         return;
11409     }
11410     if (!fp_access_check(s)) {
11411         return;
11412     }
11413
11414     switch (opcode) {
11415     case 0x0: /* SQRDMLAH (vector) */
11416         switch (size) {
11417         case 1:
11418             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
11419             break;
11420         case 2:
11421             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
11422             break;
11423         default:
11424             g_assert_not_reached();
11425         }
11426         return;
11427
11428     case 0x1: /* SQRDMLSH (vector) */
11429         switch (size) {
11430         case 1:
11431             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
11432             break;
11433         case 2:
11434             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
11435             break;
11436         default:
11437             g_assert_not_reached();
11438         }
11439         return;
11440
11441     case 0x8: /* FCMLA, #0 */
11442     case 0x9: /* FCMLA, #90 */
11443     case 0xa: /* FCMLA, #180 */
11444     case 0xb: /* FCMLA, #270 */
11445         rot = extract32(opcode, 0, 2);
11446         switch (size) {
11447         case 1:
11448             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
11449                               gen_helper_gvec_fcmlah);
11450             break;
11451         case 2:
11452             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
11453                               gen_helper_gvec_fcmlas);
11454             break;
11455         case 3:
11456             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
11457                               gen_helper_gvec_fcmlad);
11458             break;
11459         default:
11460             g_assert_not_reached();
11461         }
11462         return;
11463
11464     case 0xc: /* FCADD, #90 */
11465     case 0xe: /* FCADD, #270 */
11466         rot = extract32(opcode, 1, 1);
11467         switch (size) {
11468         case 1:
11469             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11470                               gen_helper_gvec_fcaddh);
11471             break;
11472         case 2:
11473             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11474                               gen_helper_gvec_fcadds);
11475             break;
11476         case 3:
11477             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11478                               gen_helper_gvec_fcaddd);
11479             break;
11480         default:
11481             g_assert_not_reached();
11482         }
11483         return;
11484
11485     default:
11486         g_assert_not_reached();
11487     }
11488 }
11489
11490 static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
11491                                   int size, int rn, int rd)
11492 {
11493     /* Handle 2-reg-misc ops which are widening (so each size element
11494      * in the source becomes a 2*size element in the destination.
11495      * The only instruction like this is FCVTL.
11496      */
11497     int pass;
11498
11499     if (size == 3) {
11500         /* 32 -> 64 bit fp conversion */
11501         TCGv_i64 tcg_res[2];
11502         int srcelt = is_q ? 2 : 0;
11503
11504         for (pass = 0; pass < 2; pass++) {
11505             TCGv_i32 tcg_op = tcg_temp_new_i32();
11506             tcg_res[pass] = tcg_temp_new_i64();
11507
11508             read_vec_element_i32(s, tcg_op, rn, srcelt + pass, MO_32);
11509             gen_helper_vfp_fcvtds(tcg_res[pass], tcg_op, cpu_env);
11510             tcg_temp_free_i32(tcg_op);
11511         }
11512         for (pass = 0; pass < 2; pass++) {
11513             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
11514             tcg_temp_free_i64(tcg_res[pass]);
11515         }
11516     } else {
11517         /* 16 -> 32 bit fp conversion */
11518         int srcelt = is_q ? 4 : 0;
11519         TCGv_i32 tcg_res[4];
11520
11521         for (pass = 0; pass < 4; pass++) {
11522             tcg_res[pass] = tcg_temp_new_i32();
11523
11524             read_vec_element_i32(s, tcg_res[pass], rn, srcelt + pass, MO_16);
11525             gen_helper_vfp_fcvt_f16_to_f32(tcg_res[pass], tcg_res[pass],
11526                                            cpu_env);
11527         }
11528         for (pass = 0; pass < 4; pass++) {
11529             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
11530             tcg_temp_free_i32(tcg_res[pass]);
11531         }
11532     }
11533 }
11534
11535 static void handle_rev(DisasContext *s, int opcode, bool u,
11536                        bool is_q, int size, int rn, int rd)
11537 {
11538     int op = (opcode << 1) | u;
11539     int opsz = op + size;
11540     int grp_size = 3 - opsz;
11541     int dsize = is_q ? 128 : 64;
11542     int i;
11543
11544     if (opsz >= 3) {
11545         unallocated_encoding(s);
11546         return;
11547     }
11548
11549     if (!fp_access_check(s)) {
11550         return;
11551     }
11552
11553     if (size == 0) {
11554         /* Special case bytes, use bswap op on each group of elements */
11555         int groups = dsize / (8 << grp_size);
11556
11557         for (i = 0; i < groups; i++) {
11558             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
11559
11560             read_vec_element(s, tcg_tmp, rn, i, grp_size);
11561             switch (grp_size) {
11562             case MO_16:
11563                 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
11564                 break;
11565             case MO_32:
11566                 tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
11567                 break;
11568             case MO_64:
11569                 tcg_gen_bswap64_i64(tcg_tmp, tcg_tmp);
11570                 break;
11571             default:
11572                 g_assert_not_reached();
11573             }
11574             write_vec_element(s, tcg_tmp, rd, i, grp_size);
11575             tcg_temp_free_i64(tcg_tmp);
11576         }
11577         clear_vec_high(s, is_q, rd);
11578     } else {
11579         int revmask = (1 << grp_size) - 1;
11580         int esize = 8 << size;
11581         int elements = dsize / esize;
11582         TCGv_i64 tcg_rn = tcg_temp_new_i64();
11583         TCGv_i64 tcg_rd = tcg_const_i64(0);
11584         TCGv_i64 tcg_rd_hi = tcg_const_i64(0);
11585
11586         for (i = 0; i < elements; i++) {
11587             int e_rev = (i & 0xf) ^ revmask;
11588             int off = e_rev * esize;
11589             read_vec_element(s, tcg_rn, rn, i, size);
11590             if (off >= 64) {
11591                 tcg_gen_deposit_i64(tcg_rd_hi, tcg_rd_hi,
11592                                     tcg_rn, off - 64, esize);
11593             } else {
11594                 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, off, esize);
11595             }
11596         }
11597         write_vec_element(s, tcg_rd, rd, 0, MO_64);
11598         write_vec_element(s, tcg_rd_hi, rd, 1, MO_64);
11599
11600         tcg_temp_free_i64(tcg_rd_hi);
11601         tcg_temp_free_i64(tcg_rd);
11602         tcg_temp_free_i64(tcg_rn);
11603     }
11604 }
11605
11606 static void handle_2misc_pairwise(DisasContext *s, int opcode, bool u,
11607                                   bool is_q, int size, int rn, int rd)
11608 {
11609     /* Implement the pairwise operations from 2-misc:
11610      * SADDLP, UADDLP, SADALP, UADALP.
11611      * These all add pairs of elements in the input to produce a
11612      * double-width result element in the output (possibly accumulating).
11613      */
11614     bool accum = (opcode == 0x6);
11615     int maxpass = is_q ? 2 : 1;
11616     int pass;
11617     TCGv_i64 tcg_res[2];
11618
11619     if (size == 2) {
11620         /* 32 + 32 -> 64 op */
11621         TCGMemOp memop = size + (u ? 0 : MO_SIGN);
11622
11623         for (pass = 0; pass < maxpass; pass++) {
11624             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
11625             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
11626
11627             tcg_res[pass] = tcg_temp_new_i64();
11628
11629             read_vec_element(s, tcg_op1, rn, pass * 2, memop);
11630             read_vec_element(s, tcg_op2, rn, pass * 2 + 1, memop);
11631             tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
11632             if (accum) {
11633                 read_vec_element(s, tcg_op1, rd, pass, MO_64);
11634                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
11635             }
11636
11637             tcg_temp_free_i64(tcg_op1);
11638             tcg_temp_free_i64(tcg_op2);
11639         }
11640     } else {
11641         for (pass = 0; pass < maxpass; pass++) {
11642             TCGv_i64 tcg_op = tcg_temp_new_i64();
11643             NeonGenOneOpFn *genfn;
11644             static NeonGenOneOpFn * const fns[2][2] = {
11645                 { gen_helper_neon_addlp_s8,  gen_helper_neon_addlp_u8 },
11646                 { gen_helper_neon_addlp_s16,  gen_helper_neon_addlp_u16 },
11647             };
11648
11649             genfn = fns[size][u];
11650
11651             tcg_res[pass] = tcg_temp_new_i64();
11652
11653             read_vec_element(s, tcg_op, rn, pass, MO_64);
11654             genfn(tcg_res[pass], tcg_op);
11655
11656             if (accum) {
11657                 read_vec_element(s, tcg_op, rd, pass, MO_64);
11658                 if (size == 0) {
11659                     gen_helper_neon_addl_u16(tcg_res[pass],
11660                                              tcg_res[pass], tcg_op);
11661                 } else {
11662                     gen_helper_neon_addl_u32(tcg_res[pass],
11663                                              tcg_res[pass], tcg_op);
11664                 }
11665             }
11666             tcg_temp_free_i64(tcg_op);
11667         }
11668     }
11669     if (!is_q) {
11670         tcg_res[1] = tcg_const_i64(0);
11671     }
11672     for (pass = 0; pass < 2; pass++) {
11673         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
11674         tcg_temp_free_i64(tcg_res[pass]);
11675     }
11676 }
11677
11678 static void handle_shll(DisasContext *s, bool is_q, int size, int rn, int rd)
11679 {
11680     /* Implement SHLL and SHLL2 */
11681     int pass;
11682     int part = is_q ? 2 : 0;
11683     TCGv_i64 tcg_res[2];
11684
11685     for (pass = 0; pass < 2; pass++) {
11686         static NeonGenWidenFn * const widenfns[3] = {
11687             gen_helper_neon_widen_u8,
11688             gen_helper_neon_widen_u16,
11689             tcg_gen_extu_i32_i64,
11690         };
11691         NeonGenWidenFn *widenfn = widenfns[size];
11692         TCGv_i32 tcg_op = tcg_temp_new_i32();
11693
11694         read_vec_element_i32(s, tcg_op, rn, part + pass, MO_32);
11695         tcg_res[pass] = tcg_temp_new_i64();
11696         widenfn(tcg_res[pass], tcg_op);
11697         tcg_gen_shli_i64(tcg_res[pass], tcg_res[pass], 8 << size);
11698
11699         tcg_temp_free_i32(tcg_op);
11700     }
11701
11702     for (pass = 0; pass < 2; pass++) {
11703         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
11704         tcg_temp_free_i64(tcg_res[pass]);
11705     }
11706 }
11707
11708 /* AdvSIMD two reg misc
11709  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
11710  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
11711  * | 0 | Q | U | 0 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
11712  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
11713  */
11714 static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
11715 {
11716     int size = extract32(insn, 22, 2);
11717     int opcode = extract32(insn, 12, 5);
11718     bool u = extract32(insn, 29, 1);
11719     bool is_q = extract32(insn, 30, 1);
11720     int rn = extract32(insn, 5, 5);
11721     int rd = extract32(insn, 0, 5);
11722     bool need_fpstatus = false;
11723     bool need_rmode = false;
11724     int rmode = -1;
11725     TCGv_i32 tcg_rmode;
11726     TCGv_ptr tcg_fpstatus;
11727
11728     switch (opcode) {
11729     case 0x0: /* REV64, REV32 */
11730     case 0x1: /* REV16 */
11731         handle_rev(s, opcode, u, is_q, size, rn, rd);
11732         return;
11733     case 0x5: /* CNT, NOT, RBIT */
11734         if (u && size == 0) {
11735             /* NOT */
11736             break;
11737         } else if (u && size == 1) {
11738             /* RBIT */
11739             break;
11740         } else if (!u && size == 0) {
11741             /* CNT */
11742             break;
11743         }
11744         unallocated_encoding(s);
11745         return;
11746     case 0x12: /* XTN, XTN2, SQXTUN, SQXTUN2 */
11747     case 0x14: /* SQXTN, SQXTN2, UQXTN, UQXTN2 */
11748         if (size == 3) {
11749             unallocated_encoding(s);
11750             return;
11751         }
11752         if (!fp_access_check(s)) {
11753             return;
11754         }
11755
11756         handle_2misc_narrow(s, false, opcode, u, is_q, size, rn, rd);
11757         return;
11758     case 0x4: /* CLS, CLZ */
11759         if (size == 3) {
11760             unallocated_encoding(s);
11761             return;
11762         }
11763         break;
11764     case 0x2: /* SADDLP, UADDLP */
11765     case 0x6: /* SADALP, UADALP */
11766         if (size == 3) {
11767             unallocated_encoding(s);
11768             return;
11769         }
11770         if (!fp_access_check(s)) {
11771             return;
11772         }
11773         handle_2misc_pairwise(s, opcode, u, is_q, size, rn, rd);
11774         return;
11775     case 0x13: /* SHLL, SHLL2 */
11776         if (u == 0 || size == 3) {
11777             unallocated_encoding(s);
11778             return;
11779         }
11780         if (!fp_access_check(s)) {
11781             return;
11782         }
11783         handle_shll(s, is_q, size, rn, rd);
11784         return;
11785     case 0xa: /* CMLT */
11786         if (u == 1) {
11787             unallocated_encoding(s);
11788             return;
11789         }
11790         /* fall through */
11791     case 0x8: /* CMGT, CMGE */
11792     case 0x9: /* CMEQ, CMLE */
11793     case 0xb: /* ABS, NEG */
11794         if (size == 3 && !is_q) {
11795             unallocated_encoding(s);
11796             return;
11797         }
11798         break;
11799     case 0x3: /* SUQADD, USQADD */
11800         if (size == 3 && !is_q) {
11801             unallocated_encoding(s);
11802             return;
11803         }
11804         if (!fp_access_check(s)) {
11805             return;
11806         }
11807         handle_2misc_satacc(s, false, u, is_q, size, rn, rd);
11808         return;
11809     case 0x7: /* SQABS, SQNEG */
11810         if (size == 3 && !is_q) {
11811             unallocated_encoding(s);
11812             return;
11813         }
11814         break;
11815     case 0xc ... 0xf:
11816     case 0x16 ... 0x1d:
11817     case 0x1f:
11818     {
11819         /* Floating point: U, size[1] and opcode indicate operation;
11820          * size[0] indicates single or double precision.
11821          */
11822         int is_double = extract32(size, 0, 1);
11823         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
11824         size = is_double ? 3 : 2;
11825         switch (opcode) {
11826         case 0x2f: /* FABS */
11827         case 0x6f: /* FNEG */
11828             if (size == 3 && !is_q) {
11829                 unallocated_encoding(s);
11830                 return;
11831             }
11832             break;
11833         case 0x1d: /* SCVTF */
11834         case 0x5d: /* UCVTF */
11835         {
11836             bool is_signed = (opcode == 0x1d) ? true : false;
11837             int elements = is_double ? 2 : is_q ? 4 : 2;
11838             if (is_double && !is_q) {
11839                 unallocated_encoding(s);
11840                 return;
11841             }
11842             if (!fp_access_check(s)) {
11843                 return;
11844             }
11845             handle_simd_intfp_conv(s, rd, rn, elements, is_signed, 0, size);
11846             return;
11847         }
11848         case 0x2c: /* FCMGT (zero) */
11849         case 0x2d: /* FCMEQ (zero) */
11850         case 0x2e: /* FCMLT (zero) */
11851         case 0x6c: /* FCMGE (zero) */
11852         case 0x6d: /* FCMLE (zero) */
11853             if (size == 3 && !is_q) {
11854                 unallocated_encoding(s);
11855                 return;
11856             }
11857             handle_2misc_fcmp_zero(s, opcode, false, u, is_q, size, rn, rd);
11858             return;
11859         case 0x7f: /* FSQRT */
11860             if (size == 3 && !is_q) {
11861                 unallocated_encoding(s);
11862                 return;
11863             }
11864             break;
11865         case 0x1a: /* FCVTNS */
11866         case 0x1b: /* FCVTMS */
11867         case 0x3a: /* FCVTPS */
11868         case 0x3b: /* FCVTZS */
11869         case 0x5a: /* FCVTNU */
11870         case 0x5b: /* FCVTMU */
11871         case 0x7a: /* FCVTPU */
11872         case 0x7b: /* FCVTZU */
11873             need_fpstatus = true;
11874             need_rmode = true;
11875             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
11876             if (size == 3 && !is_q) {
11877                 unallocated_encoding(s);
11878                 return;
11879             }
11880             break;
11881         case 0x5c: /* FCVTAU */
11882         case 0x1c: /* FCVTAS */
11883             need_fpstatus = true;
11884             need_rmode = true;
11885             rmode = FPROUNDING_TIEAWAY;
11886             if (size == 3 && !is_q) {
11887                 unallocated_encoding(s);
11888                 return;
11889             }
11890             break;
11891         case 0x3c: /* URECPE */
11892             if (size == 3) {
11893                 unallocated_encoding(s);
11894                 return;
11895             }
11896             /* fall through */
11897         case 0x3d: /* FRECPE */
11898         case 0x7d: /* FRSQRTE */
11899             if (size == 3 && !is_q) {
11900                 unallocated_encoding(s);
11901                 return;
11902             }
11903             if (!fp_access_check(s)) {
11904                 return;
11905             }
11906             handle_2misc_reciprocal(s, opcode, false, u, is_q, size, rn, rd);
11907             return;
11908         case 0x56: /* FCVTXN, FCVTXN2 */
11909             if (size == 2) {
11910                 unallocated_encoding(s);
11911                 return;
11912             }
11913             /* fall through */
11914         case 0x16: /* FCVTN, FCVTN2 */
11915             /* handle_2misc_narrow does a 2*size -> size operation, but these
11916              * instructions encode the source size rather than dest size.
11917              */
11918             if (!fp_access_check(s)) {
11919                 return;
11920             }
11921             handle_2misc_narrow(s, false, opcode, 0, is_q, size - 1, rn, rd);
11922             return;
11923         case 0x17: /* FCVTL, FCVTL2 */
11924             if (!fp_access_check(s)) {
11925                 return;
11926             }
11927             handle_2misc_widening(s, opcode, is_q, size, rn, rd);
11928             return;
11929         case 0x18: /* FRINTN */
11930         case 0x19: /* FRINTM */
11931         case 0x38: /* FRINTP */
11932         case 0x39: /* FRINTZ */
11933             need_rmode = true;
11934             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
11935             /* fall through */
11936         case 0x59: /* FRINTX */
11937         case 0x79: /* FRINTI */
11938             need_fpstatus = true;
11939             if (size == 3 && !is_q) {
11940                 unallocated_encoding(s);
11941                 return;
11942             }
11943             break;
11944         case 0x58: /* FRINTA */
11945             need_rmode = true;
11946             rmode = FPROUNDING_TIEAWAY;
11947             need_fpstatus = true;
11948             if (size == 3 && !is_q) {
11949                 unallocated_encoding(s);
11950                 return;
11951             }
11952             break;
11953         case 0x7c: /* URSQRTE */
11954             if (size == 3) {
11955                 unallocated_encoding(s);
11956                 return;
11957             }
11958             need_fpstatus = true;
11959             break;
11960         default:
11961             unallocated_encoding(s);
11962             return;
11963         }
11964         break;
11965     }
11966     default:
11967         unallocated_encoding(s);
11968         return;
11969     }
11970
11971     if (!fp_access_check(s)) {
11972         return;
11973     }
11974
11975     if (need_fpstatus || need_rmode) {
11976         tcg_fpstatus = get_fpstatus_ptr(false);
11977     } else {
11978         tcg_fpstatus = NULL;
11979     }
11980     if (need_rmode) {
11981         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
11982         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
11983     } else {
11984         tcg_rmode = NULL;
11985     }
11986
11987     switch (opcode) {
11988     case 0x5:
11989         if (u && size == 0) { /* NOT */
11990             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_not, 0);
11991             return;
11992         }
11993         break;
11994     case 0xb:
11995         if (u) { /* NEG */
11996             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_neg, size);
11997             return;
11998         }
11999         break;
12000     }
12001
12002     if (size == 3) {
12003         /* All 64-bit element operations can be shared with scalar 2misc */
12004         int pass;
12005
12006         /* Coverity claims (size == 3 && !is_q) has been eliminated
12007          * from all paths leading to here.
12008          */
12009         tcg_debug_assert(is_q);
12010         for (pass = 0; pass < 2; pass++) {
12011             TCGv_i64 tcg_op = tcg_temp_new_i64();
12012             TCGv_i64 tcg_res = tcg_temp_new_i64();
12013
12014             read_vec_element(s, tcg_op, rn, pass, MO_64);
12015
12016             handle_2misc_64(s, opcode, u, tcg_res, tcg_op,
12017                             tcg_rmode, tcg_fpstatus);
12018
12019             write_vec_element(s, tcg_res, rd, pass, MO_64);
12020
12021             tcg_temp_free_i64(tcg_res);
12022             tcg_temp_free_i64(tcg_op);
12023         }
12024     } else {
12025         int pass;
12026
12027         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
12028             TCGv_i32 tcg_op = tcg_temp_new_i32();
12029             TCGv_i32 tcg_res = tcg_temp_new_i32();
12030             TCGCond cond;
12031
12032             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
12033
12034             if (size == 2) {
12035                 /* Special cases for 32 bit elements */
12036                 switch (opcode) {
12037                 case 0xa: /* CMLT */
12038                     /* 32 bit integer comparison against zero, result is
12039                      * test ? (2^32 - 1) : 0. We implement via setcond(test)
12040                      * and inverting.
12041                      */
12042                     cond = TCG_COND_LT;
12043                 do_cmop:
12044                     tcg_gen_setcondi_i32(cond, tcg_res, tcg_op, 0);
12045                     tcg_gen_neg_i32(tcg_res, tcg_res);
12046                     break;
12047                 case 0x8: /* CMGT, CMGE */
12048                     cond = u ? TCG_COND_GE : TCG_COND_GT;
12049                     goto do_cmop;
12050                 case 0x9: /* CMEQ, CMLE */
12051                     cond = u ? TCG_COND_LE : TCG_COND_EQ;
12052                     goto do_cmop;
12053                 case 0x4: /* CLS */
12054                     if (u) {
12055                         tcg_gen_clzi_i32(tcg_res, tcg_op, 32);
12056                     } else {
12057                         tcg_gen_clrsb_i32(tcg_res, tcg_op);
12058                     }
12059                     break;
12060                 case 0x7: /* SQABS, SQNEG */
12061                     if (u) {
12062                         gen_helper_neon_qneg_s32(tcg_res, cpu_env, tcg_op);
12063                     } else {
12064                         gen_helper_neon_qabs_s32(tcg_res, cpu_env, tcg_op);
12065                     }
12066                     break;
12067                 case 0xb: /* ABS, NEG */
12068                     if (u) {
12069                         tcg_gen_neg_i32(tcg_res, tcg_op);
12070                     } else {
12071                         TCGv_i32 tcg_zero = tcg_const_i32(0);
12072                         tcg_gen_neg_i32(tcg_res, tcg_op);
12073                         tcg_gen_movcond_i32(TCG_COND_GT, tcg_res, tcg_op,
12074                                             tcg_zero, tcg_op, tcg_res);
12075                         tcg_temp_free_i32(tcg_zero);
12076                     }
12077                     break;
12078                 case 0x2f: /* FABS */
12079                     gen_helper_vfp_abss(tcg_res, tcg_op);
12080                     break;
12081                 case 0x6f: /* FNEG */
12082                     gen_helper_vfp_negs(tcg_res, tcg_op);
12083                     break;
12084                 case 0x7f: /* FSQRT */
12085                     gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
12086                     break;
12087                 case 0x1a: /* FCVTNS */
12088                 case 0x1b: /* FCVTMS */
12089                 case 0x1c: /* FCVTAS */
12090                 case 0x3a: /* FCVTPS */
12091                 case 0x3b: /* FCVTZS */
12092                 {
12093                     TCGv_i32 tcg_shift = tcg_const_i32(0);
12094                     gen_helper_vfp_tosls(tcg_res, tcg_op,
12095                                          tcg_shift, tcg_fpstatus);
12096                     tcg_temp_free_i32(tcg_shift);
12097                     break;
12098                 }
12099                 case 0x5a: /* FCVTNU */
12100                 case 0x5b: /* FCVTMU */
12101                 case 0x5c: /* FCVTAU */
12102                 case 0x7a: /* FCVTPU */
12103                 case 0x7b: /* FCVTZU */
12104                 {
12105                     TCGv_i32 tcg_shift = tcg_const_i32(0);
12106                     gen_helper_vfp_touls(tcg_res, tcg_op,
12107                                          tcg_shift, tcg_fpstatus);
12108                     tcg_temp_free_i32(tcg_shift);
12109                     break;
12110                 }
12111                 case 0x18: /* FRINTN */
12112                 case 0x19: /* FRINTM */
12113                 case 0x38: /* FRINTP */
12114                 case 0x39: /* FRINTZ */
12115                 case 0x58: /* FRINTA */
12116                 case 0x79: /* FRINTI */
12117                     gen_helper_rints(tcg_res, tcg_op, tcg_fpstatus);
12118                     break;
12119                 case 0x59: /* FRINTX */
12120                     gen_helper_rints_exact(tcg_res, tcg_op, tcg_fpstatus);
12121                     break;
12122                 case 0x7c: /* URSQRTE */
12123                     gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
12124                     break;
12125                 default:
12126                     g_assert_not_reached();
12127                 }
12128             } else {
12129                 /* Use helpers for 8 and 16 bit elements */
12130                 switch (opcode) {
12131                 case 0x5: /* CNT, RBIT */
12132                     /* For these two insns size is part of the opcode specifier
12133                      * (handled earlier); they always operate on byte elements.
12134                      */
12135                     if (u) {
12136                         gen_helper_neon_rbit_u8(tcg_res, tcg_op);
12137                     } else {
12138                         gen_helper_neon_cnt_u8(tcg_res, tcg_op);
12139                     }
12140                     break;
12141                 case 0x7: /* SQABS, SQNEG */
12142                 {
12143                     NeonGenOneOpEnvFn *genfn;
12144                     static NeonGenOneOpEnvFn * const fns[2][2] = {
12145                         { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
12146                         { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
12147                     };
12148                     genfn = fns[size][u];
12149                     genfn(tcg_res, cpu_env, tcg_op);
12150                     break;
12151                 }
12152                 case 0x8: /* CMGT, CMGE */
12153                 case 0x9: /* CMEQ, CMLE */
12154                 case 0xa: /* CMLT */
12155                 {
12156                     static NeonGenTwoOpFn * const fns[3][2] = {
12157                         { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_s16 },
12158                         { gen_helper_neon_cge_s8, gen_helper_neon_cge_s16 },
12159                         { gen_helper_neon_ceq_u8, gen_helper_neon_ceq_u16 },
12160                     };
12161                     NeonGenTwoOpFn *genfn;
12162                     int comp;
12163                     bool reverse;
12164                     TCGv_i32 tcg_zero = tcg_const_i32(0);
12165
12166                     /* comp = index into [CMGT, CMGE, CMEQ, CMLE, CMLT] */
12167                     comp = (opcode - 0x8) * 2 + u;
12168                     /* ...but LE, LT are implemented as reverse GE, GT */
12169                     reverse = (comp > 2);
12170                     if (reverse) {
12171                         comp = 4 - comp;
12172                     }
12173                     genfn = fns[comp][size];
12174                     if (reverse) {
12175                         genfn(tcg_res, tcg_zero, tcg_op);
12176                     } else {
12177                         genfn(tcg_res, tcg_op, tcg_zero);
12178                     }
12179                     tcg_temp_free_i32(tcg_zero);
12180                     break;
12181                 }
12182                 case 0xb: /* ABS, NEG */
12183                     if (u) {
12184                         TCGv_i32 tcg_zero = tcg_const_i32(0);
12185                         if (size) {
12186                             gen_helper_neon_sub_u16(tcg_res, tcg_zero, tcg_op);
12187                         } else {
12188                             gen_helper_neon_sub_u8(tcg_res, tcg_zero, tcg_op);
12189                         }
12190                         tcg_temp_free_i32(tcg_zero);
12191                     } else {
12192                         if (size) {
12193                             gen_helper_neon_abs_s16(tcg_res, tcg_op);
12194                         } else {
12195                             gen_helper_neon_abs_s8(tcg_res, tcg_op);
12196                         }
12197                     }
12198                     break;
12199                 case 0x4: /* CLS, CLZ */
12200                     if (u) {
12201                         if (size == 0) {
12202                             gen_helper_neon_clz_u8(tcg_res, tcg_op);
12203                         } else {
12204                             gen_helper_neon_clz_u16(tcg_res, tcg_op);
12205                         }
12206                     } else {
12207                         if (size == 0) {
12208                             gen_helper_neon_cls_s8(tcg_res, tcg_op);
12209                         } else {
12210                             gen_helper_neon_cls_s16(tcg_res, tcg_op);
12211                         }
12212                     }
12213                     break;
12214                 default:
12215                     g_assert_not_reached();
12216                 }
12217             }
12218
12219             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
12220
12221             tcg_temp_free_i32(tcg_res);
12222             tcg_temp_free_i32(tcg_op);
12223         }
12224     }
12225     clear_vec_high(s, is_q, rd);
12226
12227     if (need_rmode) {
12228         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12229         tcg_temp_free_i32(tcg_rmode);
12230     }
12231     if (need_fpstatus) {
12232         tcg_temp_free_ptr(tcg_fpstatus);
12233     }
12234 }
12235
12236 /* AdvSIMD [scalar] two register miscellaneous (FP16)
12237  *
12238  *   31  30  29 28  27     24  23 22 21       17 16    12 11 10 9    5 4    0
12239  * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
12240  * | 0 | Q | U | S | 1 1 1 0 | a | 1 1 1 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
12241  * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
12242  *   mask: 1000 1111 0111 1110 0000 1100 0000 0000 0x8f7e 0c00
12243  *   val:  0000 1110 0111 1000 0000 1000 0000 0000 0x0e78 0800
12244  *
12245  * This actually covers two groups where scalar access is governed by
12246  * bit 28. A bunch of the instructions (float to integral) only exist
12247  * in the vector form and are un-allocated for the scalar decode. Also
12248  * in the scalar decode Q is always 1.
12249  */
12250 static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
12251 {
12252     int fpop, opcode, a, u;
12253     int rn, rd;
12254     bool is_q;
12255     bool is_scalar;
12256     bool only_in_vector = false;
12257
12258     int pass;
12259     TCGv_i32 tcg_rmode = NULL;
12260     TCGv_ptr tcg_fpstatus = NULL;
12261     bool need_rmode = false;
12262     bool need_fpst = true;
12263     int rmode;
12264
12265     if (!arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
12266         unallocated_encoding(s);
12267         return;
12268     }
12269
12270     rd = extract32(insn, 0, 5);
12271     rn = extract32(insn, 5, 5);
12272
12273     a = extract32(insn, 23, 1);
12274     u = extract32(insn, 29, 1);
12275     is_scalar = extract32(insn, 28, 1);
12276     is_q = extract32(insn, 30, 1);
12277
12278     opcode = extract32(insn, 12, 5);
12279     fpop = deposit32(opcode, 5, 1, a);
12280     fpop = deposit32(fpop, 6, 1, u);
12281
12282     rd = extract32(insn, 0, 5);
12283     rn = extract32(insn, 5, 5);
12284
12285     switch (fpop) {
12286     case 0x1d: /* SCVTF */
12287     case 0x5d: /* UCVTF */
12288     {
12289         int elements;
12290
12291         if (is_scalar) {
12292             elements = 1;
12293         } else {
12294             elements = (is_q ? 8 : 4);
12295         }
12296
12297         if (!fp_access_check(s)) {
12298             return;
12299         }
12300         handle_simd_intfp_conv(s, rd, rn, elements, !u, 0, MO_16);
12301         return;
12302     }
12303     break;
12304     case 0x2c: /* FCMGT (zero) */
12305     case 0x2d: /* FCMEQ (zero) */
12306     case 0x2e: /* FCMLT (zero) */
12307     case 0x6c: /* FCMGE (zero) */
12308     case 0x6d: /* FCMLE (zero) */
12309         handle_2misc_fcmp_zero(s, fpop, is_scalar, 0, is_q, MO_16, rn, rd);
12310         return;
12311     case 0x3d: /* FRECPE */
12312     case 0x3f: /* FRECPX */
12313         break;
12314     case 0x18: /* FRINTN */
12315         need_rmode = true;
12316         only_in_vector = true;
12317         rmode = FPROUNDING_TIEEVEN;
12318         break;
12319     case 0x19: /* FRINTM */
12320         need_rmode = true;
12321         only_in_vector = true;
12322         rmode = FPROUNDING_NEGINF;
12323         break;
12324     case 0x38: /* FRINTP */
12325         need_rmode = true;
12326         only_in_vector = true;
12327         rmode = FPROUNDING_POSINF;
12328         break;
12329     case 0x39: /* FRINTZ */
12330         need_rmode = true;
12331         only_in_vector = true;
12332         rmode = FPROUNDING_ZERO;
12333         break;
12334     case 0x58: /* FRINTA */
12335         need_rmode = true;
12336         only_in_vector = true;
12337         rmode = FPROUNDING_TIEAWAY;
12338         break;
12339     case 0x59: /* FRINTX */
12340     case 0x79: /* FRINTI */
12341         only_in_vector = true;
12342         /* current rounding mode */
12343         break;
12344     case 0x1a: /* FCVTNS */
12345         need_rmode = true;
12346         rmode = FPROUNDING_TIEEVEN;
12347         break;
12348     case 0x1b: /* FCVTMS */
12349         need_rmode = true;
12350         rmode = FPROUNDING_NEGINF;
12351         break;
12352     case 0x1c: /* FCVTAS */
12353         need_rmode = true;
12354         rmode = FPROUNDING_TIEAWAY;
12355         break;
12356     case 0x3a: /* FCVTPS */
12357         need_rmode = true;
12358         rmode = FPROUNDING_POSINF;
12359         break;
12360     case 0x3b: /* FCVTZS */
12361         need_rmode = true;
12362         rmode = FPROUNDING_ZERO;
12363         break;
12364     case 0x5a: /* FCVTNU */
12365         need_rmode = true;
12366         rmode = FPROUNDING_TIEEVEN;
12367         break;
12368     case 0x5b: /* FCVTMU */
12369         need_rmode = true;
12370         rmode = FPROUNDING_NEGINF;
12371         break;
12372     case 0x5c: /* FCVTAU */
12373         need_rmode = true;
12374         rmode = FPROUNDING_TIEAWAY;
12375         break;
12376     case 0x7a: /* FCVTPU */
12377         need_rmode = true;
12378         rmode = FPROUNDING_POSINF;
12379         break;
12380     case 0x7b: /* FCVTZU */
12381         need_rmode = true;
12382         rmode = FPROUNDING_ZERO;
12383         break;
12384     case 0x2f: /* FABS */
12385     case 0x6f: /* FNEG */
12386         need_fpst = false;
12387         break;
12388     case 0x7d: /* FRSQRTE */
12389     case 0x7f: /* FSQRT (vector) */
12390         break;
12391     default:
12392         fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop);
12393         g_assert_not_reached();
12394     }
12395
12396
12397     /* Check additional constraints for the scalar encoding */
12398     if (is_scalar) {
12399         if (!is_q) {
12400             unallocated_encoding(s);
12401             return;
12402         }
12403         /* FRINTxx is only in the vector form */
12404         if (only_in_vector) {
12405             unallocated_encoding(s);
12406             return;
12407         }
12408     }
12409
12410     if (!fp_access_check(s)) {
12411         return;
12412     }
12413
12414     if (need_rmode || need_fpst) {
12415         tcg_fpstatus = get_fpstatus_ptr(true);
12416     }
12417
12418     if (need_rmode) {
12419         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
12420         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12421     }
12422
12423     if (is_scalar) {
12424         TCGv_i32 tcg_op = read_fp_hreg(s, rn);
12425         TCGv_i32 tcg_res = tcg_temp_new_i32();
12426
12427         switch (fpop) {
12428         case 0x1a: /* FCVTNS */
12429         case 0x1b: /* FCVTMS */
12430         case 0x1c: /* FCVTAS */
12431         case 0x3a: /* FCVTPS */
12432         case 0x3b: /* FCVTZS */
12433             gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
12434             break;
12435         case 0x3d: /* FRECPE */
12436             gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
12437             break;
12438         case 0x3f: /* FRECPX */
12439             gen_helper_frecpx_f16(tcg_res, tcg_op, tcg_fpstatus);
12440             break;
12441         case 0x5a: /* FCVTNU */
12442         case 0x5b: /* FCVTMU */
12443         case 0x5c: /* FCVTAU */
12444         case 0x7a: /* FCVTPU */
12445         case 0x7b: /* FCVTZU */
12446             gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
12447             break;
12448         case 0x6f: /* FNEG */
12449             tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
12450             break;
12451         case 0x7d: /* FRSQRTE */
12452             gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
12453             break;
12454         default:
12455             g_assert_not_reached();
12456         }
12457
12458         /* limit any sign extension going on */
12459         tcg_gen_andi_i32(tcg_res, tcg_res, 0xffff);
12460         write_fp_sreg(s, rd, tcg_res);
12461
12462         tcg_temp_free_i32(tcg_res);
12463         tcg_temp_free_i32(tcg_op);
12464     } else {
12465         for (pass = 0; pass < (is_q ? 8 : 4); pass++) {
12466             TCGv_i32 tcg_op = tcg_temp_new_i32();
12467             TCGv_i32 tcg_res = tcg_temp_new_i32();
12468
12469             read_vec_element_i32(s, tcg_op, rn, pass, MO_16);
12470
12471             switch (fpop) {
12472             case 0x1a: /* FCVTNS */
12473             case 0x1b: /* FCVTMS */
12474             case 0x1c: /* FCVTAS */
12475             case 0x3a: /* FCVTPS */
12476             case 0x3b: /* FCVTZS */
12477                 gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
12478                 break;
12479             case 0x3d: /* FRECPE */
12480                 gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
12481                 break;
12482             case 0x5a: /* FCVTNU */
12483             case 0x5b: /* FCVTMU */
12484             case 0x5c: /* FCVTAU */
12485             case 0x7a: /* FCVTPU */
12486             case 0x7b: /* FCVTZU */
12487                 gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
12488                 break;
12489             case 0x18: /* FRINTN */
12490             case 0x19: /* FRINTM */
12491             case 0x38: /* FRINTP */
12492             case 0x39: /* FRINTZ */
12493             case 0x58: /* FRINTA */
12494             case 0x79: /* FRINTI */
12495                 gen_helper_advsimd_rinth(tcg_res, tcg_op, tcg_fpstatus);
12496                 break;
12497             case 0x59: /* FRINTX */
12498                 gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, tcg_fpstatus);
12499                 break;
12500             case 0x2f: /* FABS */
12501                 tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
12502                 break;
12503             case 0x6f: /* FNEG */
12504                 tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
12505                 break;
12506             case 0x7d: /* FRSQRTE */
12507                 gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
12508                 break;
12509             case 0x7f: /* FSQRT */
12510                 gen_helper_sqrt_f16(tcg_res, tcg_op, tcg_fpstatus);
12511                 break;
12512             default:
12513                 g_assert_not_reached();
12514             }
12515
12516             write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
12517
12518             tcg_temp_free_i32(tcg_res);
12519             tcg_temp_free_i32(tcg_op);
12520         }
12521
12522         clear_vec_high(s, is_q, rd);
12523     }
12524
12525     if (tcg_rmode) {
12526         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12527         tcg_temp_free_i32(tcg_rmode);
12528     }
12529
12530     if (tcg_fpstatus) {
12531         tcg_temp_free_ptr(tcg_fpstatus);
12532     }
12533 }
12534
12535 /* AdvSIMD scalar x indexed element
12536  *  31 30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
12537  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
12538  * | 0 1 | U | 1 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
12539  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
12540  * AdvSIMD vector x indexed element
12541  *   31  30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
12542  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
12543  * | 0 | Q | U | 0 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
12544  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
12545  */
12546 static void disas_simd_indexed(DisasContext *s, uint32_t insn)
12547 {
12548     /* This encoding has two kinds of instruction:
12549      *  normal, where we perform elt x idxelt => elt for each
12550      *     element in the vector
12551      *  long, where we perform elt x idxelt and generate a result of
12552      *     double the width of the input element
12553      * The long ops have a 'part' specifier (ie come in INSN, INSN2 pairs).
12554      */
12555     bool is_scalar = extract32(insn, 28, 1);
12556     bool is_q = extract32(insn, 30, 1);
12557     bool u = extract32(insn, 29, 1);
12558     int size = extract32(insn, 22, 2);
12559     int l = extract32(insn, 21, 1);
12560     int m = extract32(insn, 20, 1);
12561     /* Note that the Rm field here is only 4 bits, not 5 as it usually is */
12562     int rm = extract32(insn, 16, 4);
12563     int opcode = extract32(insn, 12, 4);
12564     int h = extract32(insn, 11, 1);
12565     int rn = extract32(insn, 5, 5);
12566     int rd = extract32(insn, 0, 5);
12567     bool is_long = false;
12568     int is_fp = 0;
12569     bool is_fp16 = false;
12570     int index;
12571     TCGv_ptr fpst;
12572
12573     switch (16 * u + opcode) {
12574     case 0x08: /* MUL */
12575     case 0x10: /* MLA */
12576     case 0x14: /* MLS */
12577         if (is_scalar) {
12578             unallocated_encoding(s);
12579             return;
12580         }
12581         break;
12582     case 0x02: /* SMLAL, SMLAL2 */
12583     case 0x12: /* UMLAL, UMLAL2 */
12584     case 0x06: /* SMLSL, SMLSL2 */
12585     case 0x16: /* UMLSL, UMLSL2 */
12586     case 0x0a: /* SMULL, SMULL2 */
12587     case 0x1a: /* UMULL, UMULL2 */
12588         if (is_scalar) {
12589             unallocated_encoding(s);
12590             return;
12591         }
12592         is_long = true;
12593         break;
12594     case 0x03: /* SQDMLAL, SQDMLAL2 */
12595     case 0x07: /* SQDMLSL, SQDMLSL2 */
12596     case 0x0b: /* SQDMULL, SQDMULL2 */
12597         is_long = true;
12598         break;
12599     case 0x0c: /* SQDMULH */
12600     case 0x0d: /* SQRDMULH */
12601         break;
12602     case 0x01: /* FMLA */
12603     case 0x05: /* FMLS */
12604     case 0x09: /* FMUL */
12605     case 0x19: /* FMULX */
12606         is_fp = 1;
12607         break;
12608     case 0x1d: /* SQRDMLAH */
12609     case 0x1f: /* SQRDMLSH */
12610         if (!arm_dc_feature(s, ARM_FEATURE_V8_RDM)) {
12611             unallocated_encoding(s);
12612             return;
12613         }
12614         break;
12615     case 0x11: /* FCMLA #0 */
12616     case 0x13: /* FCMLA #90 */
12617     case 0x15: /* FCMLA #180 */
12618     case 0x17: /* FCMLA #270 */
12619         if (!arm_dc_feature(s, ARM_FEATURE_V8_FCMA)) {
12620             unallocated_encoding(s);
12621             return;
12622         }
12623         is_fp = 2;
12624         break;
12625     default:
12626         unallocated_encoding(s);
12627         return;
12628     }
12629
12630     switch (is_fp) {
12631     case 1: /* normal fp */
12632         /* convert insn encoded size to TCGMemOp size */
12633         switch (size) {
12634         case 0: /* half-precision */
12635             size = MO_16;
12636             is_fp16 = true;
12637             break;
12638         case MO_32: /* single precision */
12639         case MO_64: /* double precision */
12640             break;
12641         default:
12642             unallocated_encoding(s);
12643             return;
12644         }
12645         break;
12646
12647     case 2: /* complex fp */
12648         /* Each indexable element is a complex pair.  */
12649         size <<= 1;
12650         switch (size) {
12651         case MO_32:
12652             if (h && !is_q) {
12653                 unallocated_encoding(s);
12654                 return;
12655             }
12656             is_fp16 = true;
12657             break;
12658         case MO_64:
12659             break;
12660         default:
12661             unallocated_encoding(s);
12662             return;
12663         }
12664         break;
12665
12666     default: /* integer */
12667         switch (size) {
12668         case MO_8:
12669         case MO_64:
12670             unallocated_encoding(s);
12671             return;
12672         }
12673         break;
12674     }
12675     if (is_fp16 && !arm_dc_feature(s, ARM_FEATURE_V8_FP16)) {
12676         unallocated_encoding(s);
12677         return;
12678     }
12679
12680     /* Given TCGMemOp size, adjust register and indexing.  */
12681     switch (size) {
12682     case MO_16:
12683         index = h << 2 | l << 1 | m;
12684         break;
12685     case MO_32:
12686         index = h << 1 | l;
12687         rm |= m << 4;
12688         break;
12689     case MO_64:
12690         if (l || !is_q) {
12691             unallocated_encoding(s);
12692             return;
12693         }
12694         index = h;
12695         rm |= m << 4;
12696         break;
12697     default:
12698         g_assert_not_reached();
12699     }
12700
12701     if (!fp_access_check(s)) {
12702         return;
12703     }
12704
12705     if (is_fp) {
12706         fpst = get_fpstatus_ptr(is_fp16);
12707     } else {
12708         fpst = NULL;
12709     }
12710
12711     switch (16 * u + opcode) {
12712     case 0x11: /* FCMLA #0 */
12713     case 0x13: /* FCMLA #90 */
12714     case 0x15: /* FCMLA #180 */
12715     case 0x17: /* FCMLA #270 */
12716         tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
12717                            vec_full_reg_offset(s, rn),
12718                            vec_reg_offset(s, rm, index, size), fpst,
12719                            is_q ? 16 : 8, vec_full_reg_size(s),
12720                            extract32(insn, 13, 2), /* rot */
12721                            size == MO_64
12722                            ? gen_helper_gvec_fcmlas_idx
12723                            : gen_helper_gvec_fcmlah_idx);
12724         tcg_temp_free_ptr(fpst);
12725         return;
12726     }
12727
12728     if (size == 3) {
12729         TCGv_i64 tcg_idx = tcg_temp_new_i64();
12730         int pass;
12731
12732         assert(is_fp && is_q && !is_long);
12733
12734         read_vec_element(s, tcg_idx, rm, index, MO_64);
12735
12736         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
12737             TCGv_i64 tcg_op = tcg_temp_new_i64();
12738             TCGv_i64 tcg_res = tcg_temp_new_i64();
12739
12740             read_vec_element(s, tcg_op, rn, pass, MO_64);
12741
12742             switch (16 * u + opcode) {
12743             case 0x05: /* FMLS */
12744                 /* As usual for ARM, separate negation for fused multiply-add */
12745                 gen_helper_vfp_negd(tcg_op, tcg_op);
12746                 /* fall through */
12747             case 0x01: /* FMLA */
12748                 read_vec_element(s, tcg_res, rd, pass, MO_64);
12749                 gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
12750                 break;
12751             case 0x09: /* FMUL */
12752                 gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
12753                 break;
12754             case 0x19: /* FMULX */
12755                 gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
12756                 break;
12757             default:
12758                 g_assert_not_reached();
12759             }
12760
12761             write_vec_element(s, tcg_res, rd, pass, MO_64);
12762             tcg_temp_free_i64(tcg_op);
12763             tcg_temp_free_i64(tcg_res);
12764         }
12765
12766         tcg_temp_free_i64(tcg_idx);
12767         clear_vec_high(s, !is_scalar, rd);
12768     } else if (!is_long) {
12769         /* 32 bit floating point, or 16 or 32 bit integer.
12770          * For the 16 bit scalar case we use the usual Neon helpers and
12771          * rely on the fact that 0 op 0 == 0 with no side effects.
12772          */
12773         TCGv_i32 tcg_idx = tcg_temp_new_i32();
12774         int pass, maxpasses;
12775
12776         if (is_scalar) {
12777             maxpasses = 1;
12778         } else {
12779             maxpasses = is_q ? 4 : 2;
12780         }
12781
12782         read_vec_element_i32(s, tcg_idx, rm, index, size);
12783
12784         if (size == 1 && !is_scalar) {
12785             /* The simplest way to handle the 16x16 indexed ops is to duplicate
12786              * the index into both halves of the 32 bit tcg_idx and then use
12787              * the usual Neon helpers.
12788              */
12789             tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
12790         }
12791
12792         for (pass = 0; pass < maxpasses; pass++) {
12793             TCGv_i32 tcg_op = tcg_temp_new_i32();
12794             TCGv_i32 tcg_res = tcg_temp_new_i32();
12795
12796             read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
12797
12798             switch (16 * u + opcode) {
12799             case 0x08: /* MUL */
12800             case 0x10: /* MLA */
12801             case 0x14: /* MLS */
12802             {
12803                 static NeonGenTwoOpFn * const fns[2][2] = {
12804                     { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
12805                     { tcg_gen_add_i32, tcg_gen_sub_i32 },
12806                 };
12807                 NeonGenTwoOpFn *genfn;
12808                 bool is_sub = opcode == 0x4;
12809
12810                 if (size == 1) {
12811                     gen_helper_neon_mul_u16(tcg_res, tcg_op, tcg_idx);
12812                 } else {
12813                     tcg_gen_mul_i32(tcg_res, tcg_op, tcg_idx);
12814                 }
12815                 if (opcode == 0x8) {
12816                     break;
12817                 }
12818                 read_vec_element_i32(s, tcg_op, rd, pass, MO_32);
12819                 genfn = fns[size - 1][is_sub];
12820                 genfn(tcg_res, tcg_op, tcg_res);
12821                 break;
12822             }
12823             case 0x05: /* FMLS */
12824             case 0x01: /* FMLA */
12825                 read_vec_element_i32(s, tcg_res, rd, pass,
12826                                      is_scalar ? size : MO_32);
12827                 switch (size) {
12828                 case 1:
12829                     if (opcode == 0x5) {
12830                         /* As usual for ARM, separate negation for fused
12831                          * multiply-add */
12832                         tcg_gen_xori_i32(tcg_op, tcg_op, 0x80008000);
12833                     }
12834                     if (is_scalar) {
12835                         gen_helper_advsimd_muladdh(tcg_res, tcg_op, tcg_idx,
12836                                                    tcg_res, fpst);
12837                     } else {
12838                         gen_helper_advsimd_muladd2h(tcg_res, tcg_op, tcg_idx,
12839                                                     tcg_res, fpst);
12840                     }
12841                     break;
12842                 case 2:
12843                     if (opcode == 0x5) {
12844                         /* As usual for ARM, separate negation for
12845                          * fused multiply-add */
12846                         tcg_gen_xori_i32(tcg_op, tcg_op, 0x80000000);
12847                     }
12848                     gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx,
12849                                            tcg_res, fpst);
12850                     break;
12851                 default:
12852                     g_assert_not_reached();
12853                 }
12854                 break;
12855             case 0x09: /* FMUL */
12856                 switch (size) {
12857                 case 1:
12858                     if (is_scalar) {
12859                         gen_helper_advsimd_mulh(tcg_res, tcg_op,
12860                                                 tcg_idx, fpst);
12861                     } else {
12862                         gen_helper_advsimd_mul2h(tcg_res, tcg_op,
12863                                                  tcg_idx, fpst);
12864                     }
12865                     break;
12866                 case 2:
12867                     gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
12868                     break;
12869                 default:
12870                     g_assert_not_reached();
12871                 }
12872                 break;
12873             case 0x19: /* FMULX */
12874                 switch (size) {
12875                 case 1:
12876                     if (is_scalar) {
12877                         gen_helper_advsimd_mulxh(tcg_res, tcg_op,
12878                                                  tcg_idx, fpst);
12879                     } else {
12880                         gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
12881                                                   tcg_idx, fpst);
12882                     }
12883                     break;
12884                 case 2:
12885                     gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
12886                     break;
12887                 default:
12888                     g_assert_not_reached();
12889                 }
12890                 break;
12891             case 0x0c: /* SQDMULH */
12892                 if (size == 1) {
12893                     gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
12894                                                tcg_op, tcg_idx);
12895                 } else {
12896                     gen_helper_neon_qdmulh_s32(tcg_res, cpu_env,
12897                                                tcg_op, tcg_idx);
12898                 }
12899                 break;
12900             case 0x0d: /* SQRDMULH */
12901                 if (size == 1) {
12902                     gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
12903                                                 tcg_op, tcg_idx);
12904                 } else {
12905                     gen_helper_neon_qrdmulh_s32(tcg_res, cpu_env,
12906                                                 tcg_op, tcg_idx);
12907                 }
12908                 break;
12909             case 0x1d: /* SQRDMLAH */
12910                 read_vec_element_i32(s, tcg_res, rd, pass,
12911                                      is_scalar ? size : MO_32);
12912                 if (size == 1) {
12913                     gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
12914                                                 tcg_op, tcg_idx, tcg_res);
12915                 } else {
12916                     gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
12917                                                 tcg_op, tcg_idx, tcg_res);
12918                 }
12919                 break;
12920             case 0x1f: /* SQRDMLSH */
12921                 read_vec_element_i32(s, tcg_res, rd, pass,
12922                                      is_scalar ? size : MO_32);
12923                 if (size == 1) {
12924                     gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
12925                                                 tcg_op, tcg_idx, tcg_res);
12926                 } else {
12927                     gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
12928                                                 tcg_op, tcg_idx, tcg_res);
12929                 }
12930                 break;
12931             default:
12932                 g_assert_not_reached();
12933             }
12934
12935             if (is_scalar) {
12936                 write_fp_sreg(s, rd, tcg_res);
12937             } else {
12938                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
12939             }
12940
12941             tcg_temp_free_i32(tcg_op);
12942             tcg_temp_free_i32(tcg_res);
12943         }
12944
12945         tcg_temp_free_i32(tcg_idx);
12946         clear_vec_high(s, is_q, rd);
12947     } else {
12948         /* long ops: 16x16->32 or 32x32->64 */
12949         TCGv_i64 tcg_res[2];
12950         int pass;
12951         bool satop = extract32(opcode, 0, 1);
12952         TCGMemOp memop = MO_32;
12953
12954         if (satop || !u) {
12955             memop |= MO_SIGN;
12956         }
12957
12958         if (size == 2) {
12959             TCGv_i64 tcg_idx = tcg_temp_new_i64();
12960
12961             read_vec_element(s, tcg_idx, rm, index, memop);
12962
12963             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
12964                 TCGv_i64 tcg_op = tcg_temp_new_i64();
12965                 TCGv_i64 tcg_passres;
12966                 int passelt;
12967
12968                 if (is_scalar) {
12969                     passelt = 0;
12970                 } else {
12971                     passelt = pass + (is_q * 2);
12972                 }
12973
12974                 read_vec_element(s, tcg_op, rn, passelt, memop);
12975
12976                 tcg_res[pass] = tcg_temp_new_i64();
12977
12978                 if (opcode == 0xa || opcode == 0xb) {
12979                     /* Non-accumulating ops */
12980                     tcg_passres = tcg_res[pass];
12981                 } else {
12982                     tcg_passres = tcg_temp_new_i64();
12983                 }
12984
12985                 tcg_gen_mul_i64(tcg_passres, tcg_op, tcg_idx);
12986                 tcg_temp_free_i64(tcg_op);
12987
12988                 if (satop) {
12989                     /* saturating, doubling */
12990                     gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
12991                                                       tcg_passres, tcg_passres);
12992                 }
12993
12994                 if (opcode == 0xa || opcode == 0xb) {
12995                     continue;
12996                 }
12997
12998                 /* Accumulating op: handle accumulate step */
12999                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13000
13001                 switch (opcode) {
13002                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
13003                     tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
13004                     break;
13005                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
13006                     tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
13007                     break;
13008                 case 0x7: /* SQDMLSL, SQDMLSL2 */
13009                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
13010                     /* fall through */
13011                 case 0x3: /* SQDMLAL, SQDMLAL2 */
13012                     gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
13013                                                       tcg_res[pass],
13014                                                       tcg_passres);
13015                     break;
13016                 default:
13017                     g_assert_not_reached();
13018                 }
13019                 tcg_temp_free_i64(tcg_passres);
13020             }
13021             tcg_temp_free_i64(tcg_idx);
13022
13023             clear_vec_high(s, !is_scalar, rd);
13024         } else {
13025             TCGv_i32 tcg_idx = tcg_temp_new_i32();
13026
13027             assert(size == 1);
13028             read_vec_element_i32(s, tcg_idx, rm, index, size);
13029
13030             if (!is_scalar) {
13031                 /* The simplest way to handle the 16x16 indexed ops is to
13032                  * duplicate the index into both halves of the 32 bit tcg_idx
13033                  * and then use the usual Neon helpers.
13034                  */
13035                 tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
13036             }
13037
13038             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13039                 TCGv_i32 tcg_op = tcg_temp_new_i32();
13040                 TCGv_i64 tcg_passres;
13041
13042                 if (is_scalar) {
13043                     read_vec_element_i32(s, tcg_op, rn, pass, size);
13044                 } else {
13045                     read_vec_element_i32(s, tcg_op, rn,
13046                                          pass + (is_q * 2), MO_32);
13047                 }
13048
13049                 tcg_res[pass] = tcg_temp_new_i64();
13050
13051                 if (opcode == 0xa || opcode == 0xb) {
13052                     /* Non-accumulating ops */
13053                     tcg_passres = tcg_res[pass];
13054                 } else {
13055                     tcg_passres = tcg_temp_new_i64();
13056                 }
13057
13058                 if (memop & MO_SIGN) {
13059                     gen_helper_neon_mull_s16(tcg_passres, tcg_op, tcg_idx);
13060                 } else {
13061                     gen_helper_neon_mull_u16(tcg_passres, tcg_op, tcg_idx);
13062                 }
13063                 if (satop) {
13064                     gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
13065                                                       tcg_passres, tcg_passres);
13066                 }
13067                 tcg_temp_free_i32(tcg_op);
13068
13069                 if (opcode == 0xa || opcode == 0xb) {
13070                     continue;
13071                 }
13072
13073                 /* Accumulating op: handle accumulate step */
13074                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13075
13076                 switch (opcode) {
13077                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
13078                     gen_helper_neon_addl_u32(tcg_res[pass], tcg_res[pass],
13079                                              tcg_passres);
13080                     break;
13081                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
13082                     gen_helper_neon_subl_u32(tcg_res[pass], tcg_res[pass],
13083                                              tcg_passres);
13084                     break;
13085                 case 0x7: /* SQDMLSL, SQDMLSL2 */
13086                     gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
13087                     /* fall through */
13088                 case 0x3: /* SQDMLAL, SQDMLAL2 */
13089                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
13090                                                       tcg_res[pass],
13091                                                       tcg_passres);
13092                     break;
13093                 default:
13094                     g_assert_not_reached();
13095                 }
13096                 tcg_temp_free_i64(tcg_passres);
13097             }
13098             tcg_temp_free_i32(tcg_idx);
13099
13100             if (is_scalar) {
13101                 tcg_gen_ext32u_i64(tcg_res[0], tcg_res[0]);
13102             }
13103         }
13104
13105         if (is_scalar) {
13106             tcg_res[1] = tcg_const_i64(0);
13107         }
13108
13109         for (pass = 0; pass < 2; pass++) {
13110             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13111             tcg_temp_free_i64(tcg_res[pass]);
13112         }
13113     }
13114
13115     if (fpst) {
13116         tcg_temp_free_ptr(fpst);
13117     }
13118 }
13119
13120 /* Crypto AES
13121  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
13122  * +-----------------+------+-----------+--------+-----+------+------+
13123  * | 0 1 0 0 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
13124  * +-----------------+------+-----------+--------+-----+------+------+
13125  */
13126 static void disas_crypto_aes(DisasContext *s, uint32_t insn)
13127 {
13128     int size = extract32(insn, 22, 2);
13129     int opcode = extract32(insn, 12, 5);
13130     int rn = extract32(insn, 5, 5);
13131     int rd = extract32(insn, 0, 5);
13132     int decrypt;
13133     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13134     TCGv_i32 tcg_decrypt;
13135     CryptoThreeOpIntFn *genfn;
13136
13137     if (!arm_dc_feature(s, ARM_FEATURE_V8_AES)
13138         || size != 0) {
13139         unallocated_encoding(s);
13140         return;
13141     }
13142
13143     switch (opcode) {
13144     case 0x4: /* AESE */
13145         decrypt = 0;
13146         genfn = gen_helper_crypto_aese;
13147         break;
13148     case 0x6: /* AESMC */
13149         decrypt = 0;
13150         genfn = gen_helper_crypto_aesmc;
13151         break;
13152     case 0x5: /* AESD */
13153         decrypt = 1;
13154         genfn = gen_helper_crypto_aese;
13155         break;
13156     case 0x7: /* AESIMC */
13157         decrypt = 1;
13158         genfn = gen_helper_crypto_aesmc;
13159         break;
13160     default:
13161         unallocated_encoding(s);
13162         return;
13163     }
13164
13165     if (!fp_access_check(s)) {
13166         return;
13167     }
13168
13169     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13170     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13171     tcg_decrypt = tcg_const_i32(decrypt);
13172
13173     genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt);
13174
13175     tcg_temp_free_ptr(tcg_rd_ptr);
13176     tcg_temp_free_ptr(tcg_rn_ptr);
13177     tcg_temp_free_i32(tcg_decrypt);
13178 }
13179
13180 /* Crypto three-reg SHA
13181  *  31             24 23  22  21 20  16  15 14    12 11 10 9    5 4    0
13182  * +-----------------+------+---+------+---+--------+-----+------+------+
13183  * | 0 1 0 1 1 1 1 0 | size | 0 |  Rm  | 0 | opcode | 0 0 |  Rn  |  Rd  |
13184  * +-----------------+------+---+------+---+--------+-----+------+------+
13185  */
13186 static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
13187 {
13188     int size = extract32(insn, 22, 2);
13189     int opcode = extract32(insn, 12, 3);
13190     int rm = extract32(insn, 16, 5);
13191     int rn = extract32(insn, 5, 5);
13192     int rd = extract32(insn, 0, 5);
13193     CryptoThreeOpFn *genfn;
13194     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
13195     int feature = ARM_FEATURE_V8_SHA256;
13196
13197     if (size != 0) {
13198         unallocated_encoding(s);
13199         return;
13200     }
13201
13202     switch (opcode) {
13203     case 0: /* SHA1C */
13204     case 1: /* SHA1P */
13205     case 2: /* SHA1M */
13206     case 3: /* SHA1SU0 */
13207         genfn = NULL;
13208         feature = ARM_FEATURE_V8_SHA1;
13209         break;
13210     case 4: /* SHA256H */
13211         genfn = gen_helper_crypto_sha256h;
13212         break;
13213     case 5: /* SHA256H2 */
13214         genfn = gen_helper_crypto_sha256h2;
13215         break;
13216     case 6: /* SHA256SU1 */
13217         genfn = gen_helper_crypto_sha256su1;
13218         break;
13219     default:
13220         unallocated_encoding(s);
13221         return;
13222     }
13223
13224     if (!arm_dc_feature(s, feature)) {
13225         unallocated_encoding(s);
13226         return;
13227     }
13228
13229     if (!fp_access_check(s)) {
13230         return;
13231     }
13232
13233     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13234     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13235     tcg_rm_ptr = vec_full_reg_ptr(s, rm);
13236
13237     if (genfn) {
13238         genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
13239     } else {
13240         TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
13241
13242         gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
13243                                     tcg_rm_ptr, tcg_opcode);
13244         tcg_temp_free_i32(tcg_opcode);
13245     }
13246
13247     tcg_temp_free_ptr(tcg_rd_ptr);
13248     tcg_temp_free_ptr(tcg_rn_ptr);
13249     tcg_temp_free_ptr(tcg_rm_ptr);
13250 }
13251
13252 /* Crypto two-reg SHA
13253  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
13254  * +-----------------+------+-----------+--------+-----+------+------+
13255  * | 0 1 0 1 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
13256  * +-----------------+------+-----------+--------+-----+------+------+
13257  */
13258 static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
13259 {
13260     int size = extract32(insn, 22, 2);
13261     int opcode = extract32(insn, 12, 5);
13262     int rn = extract32(insn, 5, 5);
13263     int rd = extract32(insn, 0, 5);
13264     CryptoTwoOpFn *genfn;
13265     int feature;
13266     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13267
13268     if (size != 0) {
13269         unallocated_encoding(s);
13270         return;
13271     }
13272
13273     switch (opcode) {
13274     case 0: /* SHA1H */
13275         feature = ARM_FEATURE_V8_SHA1;
13276         genfn = gen_helper_crypto_sha1h;
13277         break;
13278     case 1: /* SHA1SU1 */
13279         feature = ARM_FEATURE_V8_SHA1;
13280         genfn = gen_helper_crypto_sha1su1;
13281         break;
13282     case 2: /* SHA256SU0 */
13283         feature = ARM_FEATURE_V8_SHA256;
13284         genfn = gen_helper_crypto_sha256su0;
13285         break;
13286     default:
13287         unallocated_encoding(s);
13288         return;
13289     }
13290
13291     if (!arm_dc_feature(s, feature)) {
13292         unallocated_encoding(s);
13293         return;
13294     }
13295
13296     if (!fp_access_check(s)) {
13297         return;
13298     }
13299
13300     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13301     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13302
13303     genfn(tcg_rd_ptr, tcg_rn_ptr);
13304
13305     tcg_temp_free_ptr(tcg_rd_ptr);
13306     tcg_temp_free_ptr(tcg_rn_ptr);
13307 }
13308
13309 /* Crypto three-reg SHA512
13310  *  31                   21 20  16 15  14  13 12  11  10  9    5 4    0
13311  * +-----------------------+------+---+---+-----+--------+------+------+
13312  * | 1 1 0 0 1 1 1 0 0 1 1 |  Rm  | 1 | O | 0 0 | opcode |  Rn  |  Rd  |
13313  * +-----------------------+------+---+---+-----+--------+------+------+
13314  */
13315 static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
13316 {
13317     int opcode = extract32(insn, 10, 2);
13318     int o =  extract32(insn, 14, 1);
13319     int rm = extract32(insn, 16, 5);
13320     int rn = extract32(insn, 5, 5);
13321     int rd = extract32(insn, 0, 5);
13322     int feature;
13323     CryptoThreeOpFn *genfn;
13324
13325     if (o == 0) {
13326         switch (opcode) {
13327         case 0: /* SHA512H */
13328             feature = ARM_FEATURE_V8_SHA512;
13329             genfn = gen_helper_crypto_sha512h;
13330             break;
13331         case 1: /* SHA512H2 */
13332             feature = ARM_FEATURE_V8_SHA512;
13333             genfn = gen_helper_crypto_sha512h2;
13334             break;
13335         case 2: /* SHA512SU1 */
13336             feature = ARM_FEATURE_V8_SHA512;
13337             genfn = gen_helper_crypto_sha512su1;
13338             break;
13339         case 3: /* RAX1 */
13340             feature = ARM_FEATURE_V8_SHA3;
13341             genfn = NULL;
13342             break;
13343         }
13344     } else {
13345         switch (opcode) {
13346         case 0: /* SM3PARTW1 */
13347             feature = ARM_FEATURE_V8_SM3;
13348             genfn = gen_helper_crypto_sm3partw1;
13349             break;
13350         case 1: /* SM3PARTW2 */
13351             feature = ARM_FEATURE_V8_SM3;
13352             genfn = gen_helper_crypto_sm3partw2;
13353             break;
13354         case 2: /* SM4EKEY */
13355             feature = ARM_FEATURE_V8_SM4;
13356             genfn = gen_helper_crypto_sm4ekey;
13357             break;
13358         default:
13359             unallocated_encoding(s);
13360             return;
13361         }
13362     }
13363
13364     if (!arm_dc_feature(s, feature)) {
13365         unallocated_encoding(s);
13366         return;
13367     }
13368
13369     if (!fp_access_check(s)) {
13370         return;
13371     }
13372
13373     if (genfn) {
13374         TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
13375
13376         tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13377         tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13378         tcg_rm_ptr = vec_full_reg_ptr(s, rm);
13379
13380         genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
13381
13382         tcg_temp_free_ptr(tcg_rd_ptr);
13383         tcg_temp_free_ptr(tcg_rn_ptr);
13384         tcg_temp_free_ptr(tcg_rm_ptr);
13385     } else {
13386         TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
13387         int pass;
13388
13389         tcg_op1 = tcg_temp_new_i64();
13390         tcg_op2 = tcg_temp_new_i64();
13391         tcg_res[0] = tcg_temp_new_i64();
13392         tcg_res[1] = tcg_temp_new_i64();
13393
13394         for (pass = 0; pass < 2; pass++) {
13395             read_vec_element(s, tcg_op1, rn, pass, MO_64);
13396             read_vec_element(s, tcg_op2, rm, pass, MO_64);
13397
13398             tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1);
13399             tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
13400         }
13401         write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13402         write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13403
13404         tcg_temp_free_i64(tcg_op1);
13405         tcg_temp_free_i64(tcg_op2);
13406         tcg_temp_free_i64(tcg_res[0]);
13407         tcg_temp_free_i64(tcg_res[1]);
13408     }
13409 }
13410
13411 /* Crypto two-reg SHA512
13412  *  31                                     12  11  10  9    5 4    0
13413  * +-----------------------------------------+--------+------+------+
13414  * | 1 1 0 0 1 1 1 0 1 1 0 0 0 0 0 0 1 0 0 0 | opcode |  Rn  |  Rd  |
13415  * +-----------------------------------------+--------+------+------+
13416  */
13417 static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
13418 {
13419     int opcode = extract32(insn, 10, 2);
13420     int rn = extract32(insn, 5, 5);
13421     int rd = extract32(insn, 0, 5);
13422     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13423     int feature;
13424     CryptoTwoOpFn *genfn;
13425
13426     switch (opcode) {
13427     case 0: /* SHA512SU0 */
13428         feature = ARM_FEATURE_V8_SHA512;
13429         genfn = gen_helper_crypto_sha512su0;
13430         break;
13431     case 1: /* SM4E */
13432         feature = ARM_FEATURE_V8_SM4;
13433         genfn = gen_helper_crypto_sm4e;
13434         break;
13435     default:
13436         unallocated_encoding(s);
13437         return;
13438     }
13439
13440     if (!arm_dc_feature(s, feature)) {
13441         unallocated_encoding(s);
13442         return;
13443     }
13444
13445     if (!fp_access_check(s)) {
13446         return;
13447     }
13448
13449     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13450     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13451
13452     genfn(tcg_rd_ptr, tcg_rn_ptr);
13453
13454     tcg_temp_free_ptr(tcg_rd_ptr);
13455     tcg_temp_free_ptr(tcg_rn_ptr);
13456 }
13457
13458 /* Crypto four-register
13459  *  31               23 22 21 20  16 15  14  10 9    5 4    0
13460  * +-------------------+-----+------+---+------+------+------+
13461  * | 1 1 0 0 1 1 1 0 0 | Op0 |  Rm  | 0 |  Ra  |  Rn  |  Rd  |
13462  * +-------------------+-----+------+---+------+------+------+
13463  */
13464 static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
13465 {
13466     int op0 = extract32(insn, 21, 2);
13467     int rm = extract32(insn, 16, 5);
13468     int ra = extract32(insn, 10, 5);
13469     int rn = extract32(insn, 5, 5);
13470     int rd = extract32(insn, 0, 5);
13471     int feature;
13472
13473     switch (op0) {
13474     case 0: /* EOR3 */
13475     case 1: /* BCAX */
13476         feature = ARM_FEATURE_V8_SHA3;
13477         break;
13478     case 2: /* SM3SS1 */
13479         feature = ARM_FEATURE_V8_SM3;
13480         break;
13481     default:
13482         unallocated_encoding(s);
13483         return;
13484     }
13485
13486     if (!arm_dc_feature(s, feature)) {
13487         unallocated_encoding(s);
13488         return;
13489     }
13490
13491     if (!fp_access_check(s)) {
13492         return;
13493     }
13494
13495     if (op0 < 2) {
13496         TCGv_i64 tcg_op1, tcg_op2, tcg_op3, tcg_res[2];
13497         int pass;
13498
13499         tcg_op1 = tcg_temp_new_i64();
13500         tcg_op2 = tcg_temp_new_i64();
13501         tcg_op3 = tcg_temp_new_i64();
13502         tcg_res[0] = tcg_temp_new_i64();
13503         tcg_res[1] = tcg_temp_new_i64();
13504
13505         for (pass = 0; pass < 2; pass++) {
13506             read_vec_element(s, tcg_op1, rn, pass, MO_64);
13507             read_vec_element(s, tcg_op2, rm, pass, MO_64);
13508             read_vec_element(s, tcg_op3, ra, pass, MO_64);
13509
13510             if (op0 == 0) {
13511                 /* EOR3 */
13512                 tcg_gen_xor_i64(tcg_res[pass], tcg_op2, tcg_op3);
13513             } else {
13514                 /* BCAX */
13515                 tcg_gen_andc_i64(tcg_res[pass], tcg_op2, tcg_op3);
13516             }
13517             tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
13518         }
13519         write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13520         write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13521
13522         tcg_temp_free_i64(tcg_op1);
13523         tcg_temp_free_i64(tcg_op2);
13524         tcg_temp_free_i64(tcg_op3);
13525         tcg_temp_free_i64(tcg_res[0]);
13526         tcg_temp_free_i64(tcg_res[1]);
13527     } else {
13528         TCGv_i32 tcg_op1, tcg_op2, tcg_op3, tcg_res, tcg_zero;
13529
13530         tcg_op1 = tcg_temp_new_i32();
13531         tcg_op2 = tcg_temp_new_i32();
13532         tcg_op3 = tcg_temp_new_i32();
13533         tcg_res = tcg_temp_new_i32();
13534         tcg_zero = tcg_const_i32(0);
13535
13536         read_vec_element_i32(s, tcg_op1, rn, 3, MO_32);
13537         read_vec_element_i32(s, tcg_op2, rm, 3, MO_32);
13538         read_vec_element_i32(s, tcg_op3, ra, 3, MO_32);
13539
13540         tcg_gen_rotri_i32(tcg_res, tcg_op1, 20);
13541         tcg_gen_add_i32(tcg_res, tcg_res, tcg_op2);
13542         tcg_gen_add_i32(tcg_res, tcg_res, tcg_op3);
13543         tcg_gen_rotri_i32(tcg_res, tcg_res, 25);
13544
13545         write_vec_element_i32(s, tcg_zero, rd, 0, MO_32);
13546         write_vec_element_i32(s, tcg_zero, rd, 1, MO_32);
13547         write_vec_element_i32(s, tcg_zero, rd, 2, MO_32);
13548         write_vec_element_i32(s, tcg_res, rd, 3, MO_32);
13549
13550         tcg_temp_free_i32(tcg_op1);
13551         tcg_temp_free_i32(tcg_op2);
13552         tcg_temp_free_i32(tcg_op3);
13553         tcg_temp_free_i32(tcg_res);
13554         tcg_temp_free_i32(tcg_zero);
13555     }
13556 }
13557
13558 /* Crypto XAR
13559  *  31                   21 20  16 15    10 9    5 4    0
13560  * +-----------------------+------+--------+------+------+
13561  * | 1 1 0 0 1 1 1 0 1 0 0 |  Rm  |  imm6  |  Rn  |  Rd  |
13562  * +-----------------------+------+--------+------+------+
13563  */
13564 static void disas_crypto_xar(DisasContext *s, uint32_t insn)
13565 {
13566     int rm = extract32(insn, 16, 5);
13567     int imm6 = extract32(insn, 10, 6);
13568     int rn = extract32(insn, 5, 5);
13569     int rd = extract32(insn, 0, 5);
13570     TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
13571     int pass;
13572
13573     if (!arm_dc_feature(s, ARM_FEATURE_V8_SHA3)) {
13574         unallocated_encoding(s);
13575         return;
13576     }
13577
13578     if (!fp_access_check(s)) {
13579         return;
13580     }
13581
13582     tcg_op1 = tcg_temp_new_i64();
13583     tcg_op2 = tcg_temp_new_i64();
13584     tcg_res[0] = tcg_temp_new_i64();
13585     tcg_res[1] = tcg_temp_new_i64();
13586
13587     for (pass = 0; pass < 2; pass++) {
13588         read_vec_element(s, tcg_op1, rn, pass, MO_64);
13589         read_vec_element(s, tcg_op2, rm, pass, MO_64);
13590
13591         tcg_gen_xor_i64(tcg_res[pass], tcg_op1, tcg_op2);
13592         tcg_gen_rotri_i64(tcg_res[pass], tcg_res[pass], imm6);
13593     }
13594     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13595     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13596
13597     tcg_temp_free_i64(tcg_op1);
13598     tcg_temp_free_i64(tcg_op2);
13599     tcg_temp_free_i64(tcg_res[0]);
13600     tcg_temp_free_i64(tcg_res[1]);
13601 }
13602
13603 /* Crypto three-reg imm2
13604  *  31                   21 20  16 15  14 13 12  11  10  9    5 4    0
13605  * +-----------------------+------+-----+------+--------+------+------+
13606  * | 1 1 0 0 1 1 1 0 0 1 0 |  Rm  | 1 0 | imm2 | opcode |  Rn  |  Rd  |
13607  * +-----------------------+------+-----+------+--------+------+------+
13608  */
13609 static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
13610 {
13611     int opcode = extract32(insn, 10, 2);
13612     int imm2 = extract32(insn, 12, 2);
13613     int rm = extract32(insn, 16, 5);
13614     int rn = extract32(insn, 5, 5);
13615     int rd = extract32(insn, 0, 5);
13616     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
13617     TCGv_i32 tcg_imm2, tcg_opcode;
13618
13619     if (!arm_dc_feature(s, ARM_FEATURE_V8_SM3)) {
13620         unallocated_encoding(s);
13621         return;
13622     }
13623
13624     if (!fp_access_check(s)) {
13625         return;
13626     }
13627
13628     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13629     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13630     tcg_rm_ptr = vec_full_reg_ptr(s, rm);
13631     tcg_imm2   = tcg_const_i32(imm2);
13632     tcg_opcode = tcg_const_i32(opcode);
13633
13634     gen_helper_crypto_sm3tt(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr, tcg_imm2,
13635                             tcg_opcode);
13636
13637     tcg_temp_free_ptr(tcg_rd_ptr);
13638     tcg_temp_free_ptr(tcg_rn_ptr);
13639     tcg_temp_free_ptr(tcg_rm_ptr);
13640     tcg_temp_free_i32(tcg_imm2);
13641     tcg_temp_free_i32(tcg_opcode);
13642 }
13643
13644 /* C3.6 Data processing - SIMD, inc Crypto
13645  *
13646  * As the decode gets a little complex we are using a table based
13647  * approach for this part of the decode.
13648  */
13649 static const AArch64DecodeTable data_proc_simd[] = {
13650     /* pattern  ,  mask     ,  fn                        */
13651     { 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
13652     { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
13653     { 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
13654     { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
13655     { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
13656     { 0x0e000400, 0x9fe08400, disas_simd_copy },
13657     { 0x0f000000, 0x9f000400, disas_simd_indexed }, /* vector indexed */
13658     /* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */
13659     { 0x0f000400, 0x9ff80400, disas_simd_mod_imm },
13660     { 0x0f000400, 0x9f800400, disas_simd_shift_imm },
13661     { 0x0e000000, 0xbf208c00, disas_simd_tb },
13662     { 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
13663     { 0x2e000000, 0xbf208400, disas_simd_ext },
13664     { 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
13665     { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
13666     { 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
13667     { 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
13668     { 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
13669     { 0x5e000400, 0xdfe08400, disas_simd_scalar_copy },
13670     { 0x5f000000, 0xdf000400, disas_simd_indexed }, /* scalar indexed */
13671     { 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm },
13672     { 0x4e280800, 0xff3e0c00, disas_crypto_aes },
13673     { 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
13674     { 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
13675     { 0xce608000, 0xffe0b000, disas_crypto_three_reg_sha512 },
13676     { 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
13677     { 0xce000000, 0xff808000, disas_crypto_four_reg },
13678     { 0xce800000, 0xffe00000, disas_crypto_xar },
13679     { 0xce408000, 0xffe0c000, disas_crypto_three_reg_imm2 },
13680     { 0x0e400400, 0x9f60c400, disas_simd_three_reg_same_fp16 },
13681     { 0x0e780800, 0x8f7e0c00, disas_simd_two_reg_misc_fp16 },
13682     { 0x5e400400, 0xdf60c400, disas_simd_scalar_three_reg_same_fp16 },
13683     { 0x00000000, 0x00000000, NULL }
13684 };
13685
13686 static void disas_data_proc_simd(DisasContext *s, uint32_t insn)
13687 {
13688     /* Note that this is called with all non-FP cases from
13689      * table C3-6 so it must UNDEF for entries not specifically
13690      * allocated to instructions in that table.
13691      */
13692     AArch64DecodeFn *fn = lookup_disas_fn(&data_proc_simd[0], insn);
13693     if (fn) {
13694         fn(s, insn);
13695     } else {
13696         unallocated_encoding(s);
13697     }
13698 }
13699
13700 /* C3.6 Data processing - SIMD and floating point */
13701 static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
13702 {
13703     if (extract32(insn, 28, 1) == 1 && extract32(insn, 30, 1) == 0) {
13704         disas_data_proc_fp(s, insn);
13705     } else {
13706         /* SIMD, including crypto */
13707         disas_data_proc_simd(s, insn);
13708     }
13709 }
13710
13711 /* C3.1 A64 instruction index by encoding */
13712 static void disas_a64_insn(CPUARMState *env, DisasContext *s)
13713 {
13714     uint32_t insn;
13715
13716     insn = arm_ldl_code(env, s->pc, s->sctlr_b);
13717     s->insn = insn;
13718     s->pc += 4;
13719
13720     s->fp_access_checked = false;
13721
13722     switch (extract32(insn, 25, 4)) {
13723     case 0x0: case 0x1: case 0x2: case 0x3: /* UNALLOCATED */
13724         unallocated_encoding(s);
13725         break;
13726     case 0x8: case 0x9: /* Data processing - immediate */
13727         disas_data_proc_imm(s, insn);
13728         break;
13729     case 0xa: case 0xb: /* Branch, exception generation and system insns */
13730         disas_b_exc_sys(s, insn);
13731         break;
13732     case 0x4:
13733     case 0x6:
13734     case 0xc:
13735     case 0xe:      /* Loads and stores */
13736         disas_ldst(s, insn);
13737         break;
13738     case 0x5:
13739     case 0xd:      /* Data processing - register */
13740         disas_data_proc_reg(s, insn);
13741         break;
13742     case 0x7:
13743     case 0xf:      /* Data processing - SIMD and floating point */
13744         disas_data_proc_simd_fp(s, insn);
13745         break;
13746     default:
13747         assert(FALSE); /* all 15 cases should be handled above */
13748         break;
13749     }
13750
13751     /* if we allocated any temporaries, free them here */
13752     free_tmp_a64(s);
13753 }
13754
13755 static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
13756                                           CPUState *cpu)
13757 {
13758     DisasContext *dc = container_of(dcbase, DisasContext, base);
13759     CPUARMState *env = cpu->env_ptr;
13760     ARMCPU *arm_cpu = arm_env_get_cpu(env);
13761     int bound;
13762
13763     dc->pc = dc->base.pc_first;
13764     dc->condjmp = 0;
13765
13766     dc->aarch64 = 1;
13767     /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
13768      * there is no secure EL1, so we route exceptions to EL3.
13769      */
13770     dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
13771                                !arm_el_is_aa64(env, 3);
13772     dc->thumb = 0;
13773     dc->sctlr_b = 0;
13774     dc->be_data = ARM_TBFLAG_BE_DATA(dc->base.tb->flags) ? MO_BE : MO_LE;
13775     dc->condexec_mask = 0;
13776     dc->condexec_cond = 0;
13777     dc->mmu_idx = core_to_arm_mmu_idx(env, ARM_TBFLAG_MMUIDX(dc->base.tb->flags));
13778     dc->tbi0 = ARM_TBFLAG_TBI0(dc->base.tb->flags);
13779     dc->tbi1 = ARM_TBFLAG_TBI1(dc->base.tb->flags);
13780     dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
13781 #if !defined(CONFIG_USER_ONLY)
13782     dc->user = (dc->current_el == 0);
13783 #endif
13784     dc->fp_excp_el = ARM_TBFLAG_FPEXC_EL(dc->base.tb->flags);
13785     dc->sve_excp_el = ARM_TBFLAG_SVEEXC_EL(dc->base.tb->flags);
13786     dc->sve_len = (ARM_TBFLAG_ZCR_LEN(dc->base.tb->flags) + 1) * 16;
13787     dc->vec_len = 0;
13788     dc->vec_stride = 0;
13789     dc->cp_regs = arm_cpu->cp_regs;
13790     dc->features = env->features;
13791
13792     /* Single step state. The code-generation logic here is:
13793      *  SS_ACTIVE == 0:
13794      *   generate code with no special handling for single-stepping (except
13795      *   that anything that can make us go to SS_ACTIVE == 1 must end the TB;
13796      *   this happens anyway because those changes are all system register or
13797      *   PSTATE writes).
13798      *  SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
13799      *   emit code for one insn
13800      *   emit code to clear PSTATE.SS
13801      *   emit code to generate software step exception for completed step
13802      *   end TB (as usual for having generated an exception)
13803      *  SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
13804      *   emit code to generate a software step exception
13805      *   end the TB
13806      */
13807     dc->ss_active = ARM_TBFLAG_SS_ACTIVE(dc->base.tb->flags);
13808     dc->pstate_ss = ARM_TBFLAG_PSTATE_SS(dc->base.tb->flags);
13809     dc->is_ldex = false;
13810     dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
13811
13812     /* Bound the number of insns to execute to those left on the page.  */
13813     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
13814
13815     /* If architectural single step active, limit to 1.  */
13816     if (dc->ss_active) {
13817         bound = 1;
13818     }
13819     dc->base.max_insns = MIN(dc->base.max_insns, bound);
13820
13821     init_tmp_a64_array(dc);
13822 }
13823
13824 static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu)
13825 {
13826     tcg_clear_temp_count();
13827 }
13828
13829 static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
13830 {
13831     DisasContext *dc = container_of(dcbase, DisasContext, base);
13832
13833     tcg_gen_insn_start(dc->pc, 0, 0);
13834     dc->insn_start = tcg_last_op();
13835 }
13836
13837 static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
13838                                         const CPUBreakpoint *bp)
13839 {
13840     DisasContext *dc = container_of(dcbase, DisasContext, base);
13841
13842     if (bp->flags & BP_CPU) {
13843         gen_a64_set_pc_im(dc->pc);
13844         gen_helper_check_breakpoints(cpu_env);
13845         /* End the TB early; it likely won't be executed */
13846         dc->base.is_jmp = DISAS_TOO_MANY;
13847     } else {
13848         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
13849         /* The address covered by the breakpoint must be
13850            included in [tb->pc, tb->pc + tb->size) in order
13851            to for it to be properly cleared -- thus we
13852            increment the PC here so that the logic setting
13853            tb->size below does the right thing.  */
13854         dc->pc += 4;
13855         dc->base.is_jmp = DISAS_NORETURN;
13856     }
13857
13858     return true;
13859 }
13860
13861 static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
13862 {
13863     DisasContext *dc = container_of(dcbase, DisasContext, base);
13864     CPUARMState *env = cpu->env_ptr;
13865
13866     if (dc->ss_active && !dc->pstate_ss) {
13867         /* Singlestep state is Active-pending.
13868          * If we're in this state at the start of a TB then either
13869          *  a) we just took an exception to an EL which is being debugged
13870          *     and this is the first insn in the exception handler
13871          *  b) debug exceptions were masked and we just unmasked them
13872          *     without changing EL (eg by clearing PSTATE.D)
13873          * In either case we're going to take a swstep exception in the
13874          * "did not step an insn" case, and so the syndrome ISV and EX
13875          * bits should be zero.
13876          */
13877         assert(dc->base.num_insns == 1);
13878         gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
13879                       default_exception_el(dc));
13880         dc->base.is_jmp = DISAS_NORETURN;
13881     } else {
13882         disas_a64_insn(env, dc);
13883     }
13884
13885     dc->base.pc_next = dc->pc;
13886     translator_loop_temp_check(&dc->base);
13887 }
13888
13889 static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
13890 {
13891     DisasContext *dc = container_of(dcbase, DisasContext, base);
13892
13893     if (unlikely(dc->base.singlestep_enabled || dc->ss_active)) {
13894         /* Note that this means single stepping WFI doesn't halt the CPU.
13895          * For conditional branch insns this is harmless unreachable code as
13896          * gen_goto_tb() has already handled emitting the debug exception
13897          * (and thus a tb-jump is not possible when singlestepping).
13898          */
13899         switch (dc->base.is_jmp) {
13900         default:
13901             gen_a64_set_pc_im(dc->pc);
13902             /* fall through */
13903         case DISAS_EXIT:
13904         case DISAS_JUMP:
13905             if (dc->base.singlestep_enabled) {
13906                 gen_exception_internal(EXCP_DEBUG);
13907             } else {
13908                 gen_step_complete_exception(dc);
13909             }
13910             break;
13911         case DISAS_NORETURN:
13912             break;
13913         }
13914     } else {
13915         switch (dc->base.is_jmp) {
13916         case DISAS_NEXT:
13917         case DISAS_TOO_MANY:
13918             gen_goto_tb(dc, 1, dc->pc);
13919             break;
13920         default:
13921         case DISAS_UPDATE:
13922             gen_a64_set_pc_im(dc->pc);
13923             /* fall through */
13924         case DISAS_EXIT:
13925             tcg_gen_exit_tb(0);
13926             break;
13927         case DISAS_JUMP:
13928             tcg_gen_lookup_and_goto_ptr();
13929             break;
13930         case DISAS_NORETURN:
13931         case DISAS_SWI:
13932             break;
13933         case DISAS_WFE:
13934             gen_a64_set_pc_im(dc->pc);
13935             gen_helper_wfe(cpu_env);
13936             break;
13937         case DISAS_YIELD:
13938             gen_a64_set_pc_im(dc->pc);
13939             gen_helper_yield(cpu_env);
13940             break;
13941         case DISAS_WFI:
13942         {
13943             /* This is a special case because we don't want to just halt the CPU
13944              * if trying to debug across a WFI.
13945              */
13946             TCGv_i32 tmp = tcg_const_i32(4);
13947
13948             gen_a64_set_pc_im(dc->pc);
13949             gen_helper_wfi(cpu_env, tmp);
13950             tcg_temp_free_i32(tmp);
13951             /* The helper doesn't necessarily throw an exception, but we
13952              * must go back to the main loop to check for interrupts anyway.
13953              */
13954             tcg_gen_exit_tb(0);
13955             break;
13956         }
13957         }
13958     }
13959
13960     /* Functions above can change dc->pc, so re-align db->pc_next */
13961     dc->base.pc_next = dc->pc;
13962 }
13963
13964 static void aarch64_tr_disas_log(const DisasContextBase *dcbase,
13965                                       CPUState *cpu)
13966 {
13967     DisasContext *dc = container_of(dcbase, DisasContext, base);
13968
13969     qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
13970     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
13971 }
13972
13973 const TranslatorOps aarch64_translator_ops = {
13974     .init_disas_context = aarch64_tr_init_disas_context,
13975     .tb_start           = aarch64_tr_tb_start,
13976     .insn_start         = aarch64_tr_insn_start,
13977     .breakpoint_check   = aarch64_tr_breakpoint_check,
13978     .translate_insn     = aarch64_tr_translate_insn,
13979     .tb_stop            = aarch64_tr_tb_stop,
13980     .disas_log          = aarch64_tr_disas_log,
13981 };
This page took 0.811409 seconds and 4 git commands to generate.