]> Git Repo - qemu.git/blob - target/arm/translate-a64.c
target/arm: Fix non-parallel expansion of CASP
[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 #include "translate-a64.h"
40 #include "qemu/atomic128.h"
41
42 static TCGv_i64 cpu_X[32];
43 static TCGv_i64 cpu_pc;
44
45 /* Load/store exclusive handling */
46 static TCGv_i64 cpu_exclusive_high;
47
48 static const char *regnames[] = {
49     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
50     "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
51     "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
52     "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
53 };
54
55 enum a64_shift_type {
56     A64_SHIFT_TYPE_LSL = 0,
57     A64_SHIFT_TYPE_LSR = 1,
58     A64_SHIFT_TYPE_ASR = 2,
59     A64_SHIFT_TYPE_ROR = 3
60 };
61
62 /* Table based decoder typedefs - used when the relevant bits for decode
63  * are too awkwardly scattered across the instruction (eg SIMD).
64  */
65 typedef void AArch64DecodeFn(DisasContext *s, uint32_t insn);
66
67 typedef struct AArch64DecodeTable {
68     uint32_t pattern;
69     uint32_t mask;
70     AArch64DecodeFn *disas_fn;
71 } AArch64DecodeTable;
72
73 /* Function prototype for gen_ functions for calling Neon helpers */
74 typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
75 typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
76 typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
77 typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
78 typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
79 typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
80 typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
81 typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
82 typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
83 typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
84 typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
85 typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
86 typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
87 typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
88 typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, TCGMemOp);
89
90 /* initialize TCG globals.  */
91 void a64_translate_init(void)
92 {
93     int i;
94
95     cpu_pc = tcg_global_mem_new_i64(cpu_env,
96                                     offsetof(CPUARMState, pc),
97                                     "pc");
98     for (i = 0; i < 32; i++) {
99         cpu_X[i] = tcg_global_mem_new_i64(cpu_env,
100                                           offsetof(CPUARMState, xregs[i]),
101                                           regnames[i]);
102     }
103
104     cpu_exclusive_high = tcg_global_mem_new_i64(cpu_env,
105         offsetof(CPUARMState, exclusive_high), "exclusive_high");
106 }
107
108 static inline int get_a64_user_mem_index(DisasContext *s)
109 {
110     /* Return the core mmu_idx to use for A64 "unprivileged load/store" insns:
111      *  if EL1, access as if EL0; otherwise access at current EL
112      */
113     ARMMMUIdx useridx;
114
115     switch (s->mmu_idx) {
116     case ARMMMUIdx_S12NSE1:
117         useridx = ARMMMUIdx_S12NSE0;
118         break;
119     case ARMMMUIdx_S1SE1:
120         useridx = ARMMMUIdx_S1SE0;
121         break;
122     case ARMMMUIdx_S2NS:
123         g_assert_not_reached();
124     default:
125         useridx = s->mmu_idx;
126         break;
127     }
128     return arm_to_core_mmu_idx(useridx);
129 }
130
131 static void reset_btype(DisasContext *s)
132 {
133     if (s->btype != 0) {
134         TCGv_i32 zero = tcg_const_i32(0);
135         tcg_gen_st_i32(zero, cpu_env, offsetof(CPUARMState, btype));
136         tcg_temp_free_i32(zero);
137         s->btype = 0;
138     }
139 }
140
141 static void set_btype(DisasContext *s, int val)
142 {
143     TCGv_i32 tcg_val;
144
145     /* BTYPE is a 2-bit field, and 0 should be done with reset_btype.  */
146     tcg_debug_assert(val >= 1 && val <= 3);
147
148     tcg_val = tcg_const_i32(val);
149     tcg_gen_st_i32(tcg_val, cpu_env, offsetof(CPUARMState, btype));
150     tcg_temp_free_i32(tcg_val);
151     s->btype = -1;
152 }
153
154 void aarch64_cpu_dump_state(CPUState *cs, FILE *f,
155                             fprintf_function cpu_fprintf, int flags)
156 {
157     ARMCPU *cpu = ARM_CPU(cs);
158     CPUARMState *env = &cpu->env;
159     uint32_t psr = pstate_read(env);
160     int i;
161     int el = arm_current_el(env);
162     const char *ns_status;
163
164     cpu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
165     for (i = 0; i < 32; i++) {
166         if (i == 31) {
167             cpu_fprintf(f, " SP=%016" PRIx64 "\n", env->xregs[i]);
168         } else {
169             cpu_fprintf(f, "X%02d=%016" PRIx64 "%s", i, env->xregs[i],
170                         (i + 2) % 3 ? " " : "\n");
171         }
172     }
173
174     if (arm_feature(env, ARM_FEATURE_EL3) && el != 3) {
175         ns_status = env->cp15.scr_el3 & SCR_NS ? "NS " : "S ";
176     } else {
177         ns_status = "";
178     }
179     cpu_fprintf(f, "PSTATE=%08x %c%c%c%c %sEL%d%c",
180                 psr,
181                 psr & PSTATE_N ? 'N' : '-',
182                 psr & PSTATE_Z ? 'Z' : '-',
183                 psr & PSTATE_C ? 'C' : '-',
184                 psr & PSTATE_V ? 'V' : '-',
185                 ns_status,
186                 el,
187                 psr & PSTATE_SP ? 'h' : 't');
188
189     if (cpu_isar_feature(aa64_bti, cpu)) {
190         cpu_fprintf(f, "  BTYPE=%d", (psr & PSTATE_BTYPE) >> 10);
191     }
192     if (!(flags & CPU_DUMP_FPU)) {
193         cpu_fprintf(f, "\n");
194         return;
195     }
196     if (fp_exception_el(env, el) != 0) {
197         cpu_fprintf(f, "    FPU disabled\n");
198         return;
199     }
200     cpu_fprintf(f, "     FPCR=%08x FPSR=%08x\n",
201                 vfp_get_fpcr(env), vfp_get_fpsr(env));
202
203     if (cpu_isar_feature(aa64_sve, cpu) && sve_exception_el(env, el) == 0) {
204         int j, zcr_len = sve_zcr_len_for_el(env, el);
205
206         for (i = 0; i <= FFR_PRED_NUM; i++) {
207             bool eol;
208             if (i == FFR_PRED_NUM) {
209                 cpu_fprintf(f, "FFR=");
210                 /* It's last, so end the line.  */
211                 eol = true;
212             } else {
213                 cpu_fprintf(f, "P%02d=", i);
214                 switch (zcr_len) {
215                 case 0:
216                     eol = i % 8 == 7;
217                     break;
218                 case 1:
219                     eol = i % 6 == 5;
220                     break;
221                 case 2:
222                 case 3:
223                     eol = i % 3 == 2;
224                     break;
225                 default:
226                     /* More than one quadword per predicate.  */
227                     eol = true;
228                     break;
229                 }
230             }
231             for (j = zcr_len / 4; j >= 0; j--) {
232                 int digits;
233                 if (j * 4 + 4 <= zcr_len + 1) {
234                     digits = 16;
235                 } else {
236                     digits = (zcr_len % 4 + 1) * 4;
237                 }
238                 cpu_fprintf(f, "%0*" PRIx64 "%s", digits,
239                             env->vfp.pregs[i].p[j],
240                             j ? ":" : eol ? "\n" : " ");
241             }
242         }
243
244         for (i = 0; i < 32; i++) {
245             if (zcr_len == 0) {
246                 cpu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64 "%s",
247                             i, env->vfp.zregs[i].d[1],
248                             env->vfp.zregs[i].d[0], i & 1 ? "\n" : " ");
249             } else if (zcr_len == 1) {
250                 cpu_fprintf(f, "Z%02d=%016" PRIx64 ":%016" PRIx64
251                             ":%016" PRIx64 ":%016" PRIx64 "\n",
252                             i, env->vfp.zregs[i].d[3], env->vfp.zregs[i].d[2],
253                             env->vfp.zregs[i].d[1], env->vfp.zregs[i].d[0]);
254             } else {
255                 for (j = zcr_len; j >= 0; j--) {
256                     bool odd = (zcr_len - j) % 2 != 0;
257                     if (j == zcr_len) {
258                         cpu_fprintf(f, "Z%02d[%x-%x]=", i, j, j - 1);
259                     } else if (!odd) {
260                         if (j > 0) {
261                             cpu_fprintf(f, "   [%x-%x]=", j, j - 1);
262                         } else {
263                             cpu_fprintf(f, "     [%x]=", j);
264                         }
265                     }
266                     cpu_fprintf(f, "%016" PRIx64 ":%016" PRIx64 "%s",
267                                 env->vfp.zregs[i].d[j * 2 + 1],
268                                 env->vfp.zregs[i].d[j * 2],
269                                 odd || j == 0 ? "\n" : ":");
270                 }
271             }
272         }
273     } else {
274         for (i = 0; i < 32; i++) {
275             uint64_t *q = aa64_vfp_qreg(env, i);
276             cpu_fprintf(f, "Q%02d=%016" PRIx64 ":%016" PRIx64 "%s",
277                         i, q[1], q[0], (i & 1 ? "\n" : " "));
278         }
279     }
280 }
281
282 void gen_a64_set_pc_im(uint64_t val)
283 {
284     tcg_gen_movi_i64(cpu_pc, val);
285 }
286
287 /*
288  * Handle Top Byte Ignore (TBI) bits.
289  *
290  * If address tagging is enabled via the TCR TBI bits:
291  *  + for EL2 and EL3 there is only one TBI bit, and if it is set
292  *    then the address is zero-extended, clearing bits [63:56]
293  *  + for EL0 and EL1, TBI0 controls addresses with bit 55 == 0
294  *    and TBI1 controls addressses with bit 55 == 1.
295  *    If the appropriate TBI bit is set for the address then
296  *    the address is sign-extended from bit 55 into bits [63:56]
297  *
298  * Here We have concatenated TBI{1,0} into tbi.
299  */
300 static void gen_top_byte_ignore(DisasContext *s, TCGv_i64 dst,
301                                 TCGv_i64 src, int tbi)
302 {
303     if (tbi == 0) {
304         /* Load unmodified address */
305         tcg_gen_mov_i64(dst, src);
306     } else if (s->current_el >= 2) {
307         /* FIXME: ARMv8.1-VHE S2 translation regime.  */
308         /* Force tag byte to all zero */
309         tcg_gen_extract_i64(dst, src, 0, 56);
310     } else {
311         /* Sign-extend from bit 55.  */
312         tcg_gen_sextract_i64(dst, src, 0, 56);
313
314         if (tbi != 3) {
315             TCGv_i64 tcg_zero = tcg_const_i64(0);
316
317             /*
318              * The two TBI bits differ.
319              * If tbi0, then !tbi1: only use the extension if positive.
320              * if !tbi0, then tbi1: only use the extension if negative.
321              */
322             tcg_gen_movcond_i64(tbi == 1 ? TCG_COND_GE : TCG_COND_LT,
323                                 dst, dst, tcg_zero, dst, src);
324             tcg_temp_free_i64(tcg_zero);
325         }
326     }
327 }
328
329 static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
330 {
331     /*
332      * If address tagging is enabled for instructions via the TCR TBI bits,
333      * then loading an address into the PC will clear out any tag.
334      */
335     gen_top_byte_ignore(s, cpu_pc, src, s->tbii);
336 }
337
338 /*
339  * Return a "clean" address for ADDR according to TBID.
340  * This is always a fresh temporary, as we need to be able to
341  * increment this independently of a dirty write-back address.
342  */
343 static TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr)
344 {
345     TCGv_i64 clean = new_tmp_a64(s);
346     gen_top_byte_ignore(s, clean, addr, s->tbid);
347     return clean;
348 }
349
350 typedef struct DisasCompare64 {
351     TCGCond cond;
352     TCGv_i64 value;
353 } DisasCompare64;
354
355 static void a64_test_cc(DisasCompare64 *c64, int cc)
356 {
357     DisasCompare c32;
358
359     arm_test_cc(&c32, cc);
360
361     /* Sign-extend the 32-bit value so that the GE/LT comparisons work
362        * properly.  The NE/EQ comparisons are also fine with this choice.  */
363     c64->cond = c32.cond;
364     c64->value = tcg_temp_new_i64();
365     tcg_gen_ext_i32_i64(c64->value, c32.value);
366
367     arm_free_cc(&c32);
368 }
369
370 static void a64_free_cc(DisasCompare64 *c64)
371 {
372     tcg_temp_free_i64(c64->value);
373 }
374
375 static void gen_exception_internal(int excp)
376 {
377     TCGv_i32 tcg_excp = tcg_const_i32(excp);
378
379     assert(excp_is_internal(excp));
380     gen_helper_exception_internal(cpu_env, tcg_excp);
381     tcg_temp_free_i32(tcg_excp);
382 }
383
384 static void gen_exception(int excp, uint32_t syndrome, uint32_t target_el)
385 {
386     TCGv_i32 tcg_excp = tcg_const_i32(excp);
387     TCGv_i32 tcg_syn = tcg_const_i32(syndrome);
388     TCGv_i32 tcg_el = tcg_const_i32(target_el);
389
390     gen_helper_exception_with_syndrome(cpu_env, tcg_excp,
391                                        tcg_syn, tcg_el);
392     tcg_temp_free_i32(tcg_el);
393     tcg_temp_free_i32(tcg_syn);
394     tcg_temp_free_i32(tcg_excp);
395 }
396
397 static void gen_exception_internal_insn(DisasContext *s, int offset, int excp)
398 {
399     gen_a64_set_pc_im(s->pc - offset);
400     gen_exception_internal(excp);
401     s->base.is_jmp = DISAS_NORETURN;
402 }
403
404 static void gen_exception_insn(DisasContext *s, int offset, int excp,
405                                uint32_t syndrome, uint32_t target_el)
406 {
407     gen_a64_set_pc_im(s->pc - offset);
408     gen_exception(excp, syndrome, target_el);
409     s->base.is_jmp = DISAS_NORETURN;
410 }
411
412 static void gen_exception_bkpt_insn(DisasContext *s, int offset,
413                                     uint32_t syndrome)
414 {
415     TCGv_i32 tcg_syn;
416
417     gen_a64_set_pc_im(s->pc - offset);
418     tcg_syn = tcg_const_i32(syndrome);
419     gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
420     tcg_temp_free_i32(tcg_syn);
421     s->base.is_jmp = DISAS_NORETURN;
422 }
423
424 static void gen_step_complete_exception(DisasContext *s)
425 {
426     /* We just completed step of an insn. Move from Active-not-pending
427      * to Active-pending, and then also take the swstep exception.
428      * This corresponds to making the (IMPDEF) choice to prioritize
429      * swstep exceptions over asynchronous exceptions taken to an exception
430      * level where debug is disabled. This choice has the advantage that
431      * we do not need to maintain internal state corresponding to the
432      * ISV/EX syndrome bits between completion of the step and generation
433      * of the exception, and our syndrome information is always correct.
434      */
435     gen_ss_advance(s);
436     gen_exception(EXCP_UDEF, syn_swstep(s->ss_same_el, 1, s->is_ldex),
437                   default_exception_el(s));
438     s->base.is_jmp = DISAS_NORETURN;
439 }
440
441 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
442 {
443     /* No direct tb linking with singlestep (either QEMU's or the ARM
444      * debug architecture kind) or deterministic io
445      */
446     if (s->base.singlestep_enabled || s->ss_active ||
447         (tb_cflags(s->base.tb) & CF_LAST_IO)) {
448         return false;
449     }
450
451 #ifndef CONFIG_USER_ONLY
452     /* Only link tbs from inside the same guest page */
453     if ((s->base.tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
454         return false;
455     }
456 #endif
457
458     return true;
459 }
460
461 static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
462 {
463     TranslationBlock *tb;
464
465     tb = s->base.tb;
466     if (use_goto_tb(s, n, dest)) {
467         tcg_gen_goto_tb(n);
468         gen_a64_set_pc_im(dest);
469         tcg_gen_exit_tb(tb, n);
470         s->base.is_jmp = DISAS_NORETURN;
471     } else {
472         gen_a64_set_pc_im(dest);
473         if (s->ss_active) {
474             gen_step_complete_exception(s);
475         } else if (s->base.singlestep_enabled) {
476             gen_exception_internal(EXCP_DEBUG);
477         } else {
478             tcg_gen_lookup_and_goto_ptr();
479             s->base.is_jmp = DISAS_NORETURN;
480         }
481     }
482 }
483
484 void unallocated_encoding(DisasContext *s)
485 {
486     /* Unallocated and reserved encodings are uncategorized */
487     gen_exception_insn(s, 4, EXCP_UDEF, syn_uncategorized(),
488                        default_exception_el(s));
489 }
490
491 static void init_tmp_a64_array(DisasContext *s)
492 {
493 #ifdef CONFIG_DEBUG_TCG
494     memset(s->tmp_a64, 0, sizeof(s->tmp_a64));
495 #endif
496     s->tmp_a64_count = 0;
497 }
498
499 static void free_tmp_a64(DisasContext *s)
500 {
501     int i;
502     for (i = 0; i < s->tmp_a64_count; i++) {
503         tcg_temp_free_i64(s->tmp_a64[i]);
504     }
505     init_tmp_a64_array(s);
506 }
507
508 TCGv_i64 new_tmp_a64(DisasContext *s)
509 {
510     assert(s->tmp_a64_count < TMP_A64_MAX);
511     return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
512 }
513
514 TCGv_i64 new_tmp_a64_zero(DisasContext *s)
515 {
516     TCGv_i64 t = new_tmp_a64(s);
517     tcg_gen_movi_i64(t, 0);
518     return t;
519 }
520
521 /*
522  * Register access functions
523  *
524  * These functions are used for directly accessing a register in where
525  * changes to the final register value are likely to be made. If you
526  * need to use a register for temporary calculation (e.g. index type
527  * operations) use the read_* form.
528  *
529  * B1.2.1 Register mappings
530  *
531  * In instruction register encoding 31 can refer to ZR (zero register) or
532  * the SP (stack pointer) depending on context. In QEMU's case we map SP
533  * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
534  * This is the point of the _sp forms.
535  */
536 TCGv_i64 cpu_reg(DisasContext *s, int reg)
537 {
538     if (reg == 31) {
539         return new_tmp_a64_zero(s);
540     } else {
541         return cpu_X[reg];
542     }
543 }
544
545 /* register access for when 31 == SP */
546 TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
547 {
548     return cpu_X[reg];
549 }
550
551 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
552  * representing the register contents. This TCGv is an auto-freed
553  * temporary so it need not be explicitly freed, and may be modified.
554  */
555 TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
556 {
557     TCGv_i64 v = new_tmp_a64(s);
558     if (reg != 31) {
559         if (sf) {
560             tcg_gen_mov_i64(v, cpu_X[reg]);
561         } else {
562             tcg_gen_ext32u_i64(v, cpu_X[reg]);
563         }
564     } else {
565         tcg_gen_movi_i64(v, 0);
566     }
567     return v;
568 }
569
570 TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
571 {
572     TCGv_i64 v = new_tmp_a64(s);
573     if (sf) {
574         tcg_gen_mov_i64(v, cpu_X[reg]);
575     } else {
576         tcg_gen_ext32u_i64(v, cpu_X[reg]);
577     }
578     return v;
579 }
580
581 /* Return the offset into CPUARMState of a slice (from
582  * the least significant end) of FP register Qn (ie
583  * Dn, Sn, Hn or Bn).
584  * (Note that this is not the same mapping as for A32; see cpu.h)
585  */
586 static inline int fp_reg_offset(DisasContext *s, int regno, TCGMemOp size)
587 {
588     return vec_reg_offset(s, regno, 0, size);
589 }
590
591 /* Offset of the high half of the 128 bit vector Qn */
592 static inline int fp_reg_hi_offset(DisasContext *s, int regno)
593 {
594     return vec_reg_offset(s, regno, 1, MO_64);
595 }
596
597 /* Convenience accessors for reading and writing single and double
598  * FP registers. Writing clears the upper parts of the associated
599  * 128 bit vector register, as required by the architecture.
600  * Note that unlike the GP register accessors, the values returned
601  * by the read functions must be manually freed.
602  */
603 static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
604 {
605     TCGv_i64 v = tcg_temp_new_i64();
606
607     tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
608     return v;
609 }
610
611 static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
612 {
613     TCGv_i32 v = tcg_temp_new_i32();
614
615     tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(s, reg, MO_32));
616     return v;
617 }
618
619 static TCGv_i32 read_fp_hreg(DisasContext *s, int reg)
620 {
621     TCGv_i32 v = tcg_temp_new_i32();
622
623     tcg_gen_ld16u_i32(v, cpu_env, fp_reg_offset(s, reg, MO_16));
624     return v;
625 }
626
627 /* Clear the bits above an N-bit vector, for N = (is_q ? 128 : 64).
628  * If SVE is not enabled, then there are only 128 bits in the vector.
629  */
630 static void clear_vec_high(DisasContext *s, bool is_q, int rd)
631 {
632     unsigned ofs = fp_reg_offset(s, rd, MO_64);
633     unsigned vsz = vec_full_reg_size(s);
634
635     if (!is_q) {
636         TCGv_i64 tcg_zero = tcg_const_i64(0);
637         tcg_gen_st_i64(tcg_zero, cpu_env, ofs + 8);
638         tcg_temp_free_i64(tcg_zero);
639     }
640     if (vsz > 16) {
641         tcg_gen_gvec_dup8i(ofs + 16, vsz - 16, vsz - 16, 0);
642     }
643 }
644
645 void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
646 {
647     unsigned ofs = fp_reg_offset(s, reg, MO_64);
648
649     tcg_gen_st_i64(v, cpu_env, ofs);
650     clear_vec_high(s, false, reg);
651 }
652
653 static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
654 {
655     TCGv_i64 tmp = tcg_temp_new_i64();
656
657     tcg_gen_extu_i32_i64(tmp, v);
658     write_fp_dreg(s, reg, tmp);
659     tcg_temp_free_i64(tmp);
660 }
661
662 TCGv_ptr get_fpstatus_ptr(bool is_f16)
663 {
664     TCGv_ptr statusptr = tcg_temp_new_ptr();
665     int offset;
666
667     /* In A64 all instructions (both FP and Neon) use the FPCR; there
668      * is no equivalent of the A32 Neon "standard FPSCR value".
669      * However half-precision operations operate under a different
670      * FZ16 flag and use vfp.fp_status_f16 instead of vfp.fp_status.
671      */
672     if (is_f16) {
673         offset = offsetof(CPUARMState, vfp.fp_status_f16);
674     } else {
675         offset = offsetof(CPUARMState, vfp.fp_status);
676     }
677     tcg_gen_addi_ptr(statusptr, cpu_env, offset);
678     return statusptr;
679 }
680
681 /* Expand a 2-operand AdvSIMD vector operation using an expander function.  */
682 static void gen_gvec_fn2(DisasContext *s, bool is_q, int rd, int rn,
683                          GVecGen2Fn *gvec_fn, int vece)
684 {
685     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
686             is_q ? 16 : 8, vec_full_reg_size(s));
687 }
688
689 /* Expand a 2-operand + immediate AdvSIMD vector operation using
690  * an expander function.
691  */
692 static void gen_gvec_fn2i(DisasContext *s, bool is_q, int rd, int rn,
693                           int64_t imm, GVecGen2iFn *gvec_fn, int vece)
694 {
695     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
696             imm, is_q ? 16 : 8, vec_full_reg_size(s));
697 }
698
699 /* Expand a 3-operand AdvSIMD vector operation using an expander function.  */
700 static void gen_gvec_fn3(DisasContext *s, bool is_q, int rd, int rn, int rm,
701                          GVecGen3Fn *gvec_fn, int vece)
702 {
703     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
704             vec_full_reg_offset(s, rm), is_q ? 16 : 8, vec_full_reg_size(s));
705 }
706
707 /* Expand a 2-operand + immediate AdvSIMD vector operation using
708  * an op descriptor.
709  */
710 static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd,
711                           int rn, int64_t imm, const GVecGen2i *gvec_op)
712 {
713     tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
714                     is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op);
715 }
716
717 /* Expand a 3-operand AdvSIMD vector operation using an op descriptor.  */
718 static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
719                          int rn, int rm, const GVecGen3 *gvec_op)
720 {
721     tcg_gen_gvec_3(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
722                    vec_full_reg_offset(s, rm), is_q ? 16 : 8,
723                    vec_full_reg_size(s), gvec_op);
724 }
725
726 /* Expand a 3-operand operation using an out-of-line helper.  */
727 static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
728                              int rn, int rm, int data, gen_helper_gvec_3 *fn)
729 {
730     tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd),
731                        vec_full_reg_offset(s, rn),
732                        vec_full_reg_offset(s, rm),
733                        is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
734 }
735
736 /* Expand a 3-operand + env pointer operation using
737  * an out-of-line helper.
738  */
739 static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
740                              int rn, int rm, gen_helper_gvec_3_ptr *fn)
741 {
742     tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
743                        vec_full_reg_offset(s, rn),
744                        vec_full_reg_offset(s, rm), cpu_env,
745                        is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
746 }
747
748 /* Expand a 3-operand + fpstatus pointer + simd data value operation using
749  * an out-of-line helper.
750  */
751 static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
752                               int rm, bool is_fp16, int data,
753                               gen_helper_gvec_3_ptr *fn)
754 {
755     TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
756     tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
757                        vec_full_reg_offset(s, rn),
758                        vec_full_reg_offset(s, rm), fpst,
759                        is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
760     tcg_temp_free_ptr(fpst);
761 }
762
763 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
764  * than the 32 bit equivalent.
765  */
766 static inline void gen_set_NZ64(TCGv_i64 result)
767 {
768     tcg_gen_extr_i64_i32(cpu_ZF, cpu_NF, result);
769     tcg_gen_or_i32(cpu_ZF, cpu_ZF, cpu_NF);
770 }
771
772 /* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
773 static inline void gen_logic_CC(int sf, TCGv_i64 result)
774 {
775     if (sf) {
776         gen_set_NZ64(result);
777     } else {
778         tcg_gen_extrl_i64_i32(cpu_ZF, result);
779         tcg_gen_mov_i32(cpu_NF, cpu_ZF);
780     }
781     tcg_gen_movi_i32(cpu_CF, 0);
782     tcg_gen_movi_i32(cpu_VF, 0);
783 }
784
785 /* dest = T0 + T1; compute C, N, V and Z flags */
786 static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
787 {
788     if (sf) {
789         TCGv_i64 result, flag, tmp;
790         result = tcg_temp_new_i64();
791         flag = tcg_temp_new_i64();
792         tmp = tcg_temp_new_i64();
793
794         tcg_gen_movi_i64(tmp, 0);
795         tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
796
797         tcg_gen_extrl_i64_i32(cpu_CF, flag);
798
799         gen_set_NZ64(result);
800
801         tcg_gen_xor_i64(flag, result, t0);
802         tcg_gen_xor_i64(tmp, t0, t1);
803         tcg_gen_andc_i64(flag, flag, tmp);
804         tcg_temp_free_i64(tmp);
805         tcg_gen_extrh_i64_i32(cpu_VF, flag);
806
807         tcg_gen_mov_i64(dest, result);
808         tcg_temp_free_i64(result);
809         tcg_temp_free_i64(flag);
810     } else {
811         /* 32 bit arithmetic */
812         TCGv_i32 t0_32 = tcg_temp_new_i32();
813         TCGv_i32 t1_32 = tcg_temp_new_i32();
814         TCGv_i32 tmp = tcg_temp_new_i32();
815
816         tcg_gen_movi_i32(tmp, 0);
817         tcg_gen_extrl_i64_i32(t0_32, t0);
818         tcg_gen_extrl_i64_i32(t1_32, t1);
819         tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
820         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
821         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
822         tcg_gen_xor_i32(tmp, t0_32, t1_32);
823         tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
824         tcg_gen_extu_i32_i64(dest, cpu_NF);
825
826         tcg_temp_free_i32(tmp);
827         tcg_temp_free_i32(t0_32);
828         tcg_temp_free_i32(t1_32);
829     }
830 }
831
832 /* dest = T0 - T1; compute C, N, V and Z flags */
833 static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
834 {
835     if (sf) {
836         /* 64 bit arithmetic */
837         TCGv_i64 result, flag, tmp;
838
839         result = tcg_temp_new_i64();
840         flag = tcg_temp_new_i64();
841         tcg_gen_sub_i64(result, t0, t1);
842
843         gen_set_NZ64(result);
844
845         tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
846         tcg_gen_extrl_i64_i32(cpu_CF, flag);
847
848         tcg_gen_xor_i64(flag, result, t0);
849         tmp = tcg_temp_new_i64();
850         tcg_gen_xor_i64(tmp, t0, t1);
851         tcg_gen_and_i64(flag, flag, tmp);
852         tcg_temp_free_i64(tmp);
853         tcg_gen_extrh_i64_i32(cpu_VF, flag);
854         tcg_gen_mov_i64(dest, result);
855         tcg_temp_free_i64(flag);
856         tcg_temp_free_i64(result);
857     } else {
858         /* 32 bit arithmetic */
859         TCGv_i32 t0_32 = tcg_temp_new_i32();
860         TCGv_i32 t1_32 = tcg_temp_new_i32();
861         TCGv_i32 tmp;
862
863         tcg_gen_extrl_i64_i32(t0_32, t0);
864         tcg_gen_extrl_i64_i32(t1_32, t1);
865         tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
866         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
867         tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
868         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
869         tmp = tcg_temp_new_i32();
870         tcg_gen_xor_i32(tmp, t0_32, t1_32);
871         tcg_temp_free_i32(t0_32);
872         tcg_temp_free_i32(t1_32);
873         tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
874         tcg_temp_free_i32(tmp);
875         tcg_gen_extu_i32_i64(dest, cpu_NF);
876     }
877 }
878
879 /* dest = T0 + T1 + CF; do not compute flags. */
880 static void gen_adc(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
881 {
882     TCGv_i64 flag = tcg_temp_new_i64();
883     tcg_gen_extu_i32_i64(flag, cpu_CF);
884     tcg_gen_add_i64(dest, t0, t1);
885     tcg_gen_add_i64(dest, dest, flag);
886     tcg_temp_free_i64(flag);
887
888     if (!sf) {
889         tcg_gen_ext32u_i64(dest, dest);
890     }
891 }
892
893 /* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
894 static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
895 {
896     if (sf) {
897         TCGv_i64 result, cf_64, vf_64, tmp;
898         result = tcg_temp_new_i64();
899         cf_64 = tcg_temp_new_i64();
900         vf_64 = tcg_temp_new_i64();
901         tmp = tcg_const_i64(0);
902
903         tcg_gen_extu_i32_i64(cf_64, cpu_CF);
904         tcg_gen_add2_i64(result, cf_64, t0, tmp, cf_64, tmp);
905         tcg_gen_add2_i64(result, cf_64, result, cf_64, t1, tmp);
906         tcg_gen_extrl_i64_i32(cpu_CF, cf_64);
907         gen_set_NZ64(result);
908
909         tcg_gen_xor_i64(vf_64, result, t0);
910         tcg_gen_xor_i64(tmp, t0, t1);
911         tcg_gen_andc_i64(vf_64, vf_64, tmp);
912         tcg_gen_extrh_i64_i32(cpu_VF, vf_64);
913
914         tcg_gen_mov_i64(dest, result);
915
916         tcg_temp_free_i64(tmp);
917         tcg_temp_free_i64(vf_64);
918         tcg_temp_free_i64(cf_64);
919         tcg_temp_free_i64(result);
920     } else {
921         TCGv_i32 t0_32, t1_32, tmp;
922         t0_32 = tcg_temp_new_i32();
923         t1_32 = tcg_temp_new_i32();
924         tmp = tcg_const_i32(0);
925
926         tcg_gen_extrl_i64_i32(t0_32, t0);
927         tcg_gen_extrl_i64_i32(t1_32, t1);
928         tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, cpu_CF, tmp);
929         tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1_32, tmp);
930
931         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
932         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
933         tcg_gen_xor_i32(tmp, t0_32, t1_32);
934         tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
935         tcg_gen_extu_i32_i64(dest, cpu_NF);
936
937         tcg_temp_free_i32(tmp);
938         tcg_temp_free_i32(t1_32);
939         tcg_temp_free_i32(t0_32);
940     }
941 }
942
943 /*
944  * Load/Store generators
945  */
946
947 /*
948  * Store from GPR register to memory.
949  */
950 static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
951                              TCGv_i64 tcg_addr, int size, int memidx,
952                              bool iss_valid,
953                              unsigned int iss_srt,
954                              bool iss_sf, bool iss_ar)
955 {
956     g_assert(size <= 3);
957     tcg_gen_qemu_st_i64(source, tcg_addr, memidx, s->be_data + size);
958
959     if (iss_valid) {
960         uint32_t syn;
961
962         syn = syn_data_abort_with_iss(0,
963                                       size,
964                                       false,
965                                       iss_srt,
966                                       iss_sf,
967                                       iss_ar,
968                                       0, 0, 0, 0, 0, false);
969         disas_set_insn_syndrome(s, syn);
970     }
971 }
972
973 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
974                       TCGv_i64 tcg_addr, int size,
975                       bool iss_valid,
976                       unsigned int iss_srt,
977                       bool iss_sf, bool iss_ar)
978 {
979     do_gpr_st_memidx(s, source, tcg_addr, size, get_mem_index(s),
980                      iss_valid, iss_srt, iss_sf, iss_ar);
981 }
982
983 /*
984  * Load from memory to GPR register
985  */
986 static void do_gpr_ld_memidx(DisasContext *s,
987                              TCGv_i64 dest, TCGv_i64 tcg_addr,
988                              int size, bool is_signed,
989                              bool extend, int memidx,
990                              bool iss_valid, unsigned int iss_srt,
991                              bool iss_sf, bool iss_ar)
992 {
993     TCGMemOp memop = s->be_data + size;
994
995     g_assert(size <= 3);
996
997     if (is_signed) {
998         memop += MO_SIGN;
999     }
1000
1001     tcg_gen_qemu_ld_i64(dest, tcg_addr, memidx, memop);
1002
1003     if (extend && is_signed) {
1004         g_assert(size < 3);
1005         tcg_gen_ext32u_i64(dest, dest);
1006     }
1007
1008     if (iss_valid) {
1009         uint32_t syn;
1010
1011         syn = syn_data_abort_with_iss(0,
1012                                       size,
1013                                       is_signed,
1014                                       iss_srt,
1015                                       iss_sf,
1016                                       iss_ar,
1017                                       0, 0, 0, 0, 0, false);
1018         disas_set_insn_syndrome(s, syn);
1019     }
1020 }
1021
1022 static void do_gpr_ld(DisasContext *s,
1023                       TCGv_i64 dest, TCGv_i64 tcg_addr,
1024                       int size, bool is_signed, bool extend,
1025                       bool iss_valid, unsigned int iss_srt,
1026                       bool iss_sf, bool iss_ar)
1027 {
1028     do_gpr_ld_memidx(s, dest, tcg_addr, size, is_signed, extend,
1029                      get_mem_index(s),
1030                      iss_valid, iss_srt, iss_sf, iss_ar);
1031 }
1032
1033 /*
1034  * Store from FP register to memory
1035  */
1036 static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
1037 {
1038     /* This writes the bottom N bits of a 128 bit wide vector to memory */
1039     TCGv_i64 tmp = tcg_temp_new_i64();
1040     tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
1041     if (size < 4) {
1042         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s),
1043                             s->be_data + size);
1044     } else {
1045         bool be = s->be_data == MO_BE;
1046         TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
1047
1048         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
1049         tcg_gen_qemu_st_i64(tmp, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
1050                             s->be_data | MO_Q);
1051         tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
1052         tcg_gen_qemu_st_i64(tmp, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
1053                             s->be_data | MO_Q);
1054         tcg_temp_free_i64(tcg_hiaddr);
1055     }
1056
1057     tcg_temp_free_i64(tmp);
1058 }
1059
1060 /*
1061  * Load from memory to FP register
1062  */
1063 static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
1064 {
1065     /* This always zero-extends and writes to a full 128 bit wide vector */
1066     TCGv_i64 tmplo = tcg_temp_new_i64();
1067     TCGv_i64 tmphi;
1068
1069     if (size < 4) {
1070         TCGMemOp memop = s->be_data + size;
1071         tmphi = tcg_const_i64(0);
1072         tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
1073     } else {
1074         bool be = s->be_data == MO_BE;
1075         TCGv_i64 tcg_hiaddr;
1076
1077         tmphi = tcg_temp_new_i64();
1078         tcg_hiaddr = tcg_temp_new_i64();
1079
1080         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
1081         tcg_gen_qemu_ld_i64(tmplo, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
1082                             s->be_data | MO_Q);
1083         tcg_gen_qemu_ld_i64(tmphi, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
1084                             s->be_data | MO_Q);
1085         tcg_temp_free_i64(tcg_hiaddr);
1086     }
1087
1088     tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
1089     tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
1090
1091     tcg_temp_free_i64(tmplo);
1092     tcg_temp_free_i64(tmphi);
1093
1094     clear_vec_high(s, true, destidx);
1095 }
1096
1097 /*
1098  * Vector load/store helpers.
1099  *
1100  * The principal difference between this and a FP load is that we don't
1101  * zero extend as we are filling a partial chunk of the vector register.
1102  * These functions don't support 128 bit loads/stores, which would be
1103  * normal load/store operations.
1104  *
1105  * The _i32 versions are useful when operating on 32 bit quantities
1106  * (eg for floating point single or using Neon helper functions).
1107  */
1108
1109 /* Get value of an element within a vector register */
1110 static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
1111                              int element, TCGMemOp memop)
1112 {
1113     int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
1114     switch (memop) {
1115     case MO_8:
1116         tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
1117         break;
1118     case MO_16:
1119         tcg_gen_ld16u_i64(tcg_dest, cpu_env, vect_off);
1120         break;
1121     case MO_32:
1122         tcg_gen_ld32u_i64(tcg_dest, cpu_env, vect_off);
1123         break;
1124     case MO_8|MO_SIGN:
1125         tcg_gen_ld8s_i64(tcg_dest, cpu_env, vect_off);
1126         break;
1127     case MO_16|MO_SIGN:
1128         tcg_gen_ld16s_i64(tcg_dest, cpu_env, vect_off);
1129         break;
1130     case MO_32|MO_SIGN:
1131         tcg_gen_ld32s_i64(tcg_dest, cpu_env, vect_off);
1132         break;
1133     case MO_64:
1134     case MO_64|MO_SIGN:
1135         tcg_gen_ld_i64(tcg_dest, cpu_env, vect_off);
1136         break;
1137     default:
1138         g_assert_not_reached();
1139     }
1140 }
1141
1142 static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
1143                                  int element, TCGMemOp memop)
1144 {
1145     int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
1146     switch (memop) {
1147     case MO_8:
1148         tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off);
1149         break;
1150     case MO_16:
1151         tcg_gen_ld16u_i32(tcg_dest, cpu_env, vect_off);
1152         break;
1153     case MO_8|MO_SIGN:
1154         tcg_gen_ld8s_i32(tcg_dest, cpu_env, vect_off);
1155         break;
1156     case MO_16|MO_SIGN:
1157         tcg_gen_ld16s_i32(tcg_dest, cpu_env, vect_off);
1158         break;
1159     case MO_32:
1160     case MO_32|MO_SIGN:
1161         tcg_gen_ld_i32(tcg_dest, cpu_env, vect_off);
1162         break;
1163     default:
1164         g_assert_not_reached();
1165     }
1166 }
1167
1168 /* Set value of an element within a vector register */
1169 static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
1170                               int element, TCGMemOp memop)
1171 {
1172     int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
1173     switch (memop) {
1174     case MO_8:
1175         tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
1176         break;
1177     case MO_16:
1178         tcg_gen_st16_i64(tcg_src, cpu_env, vect_off);
1179         break;
1180     case MO_32:
1181         tcg_gen_st32_i64(tcg_src, cpu_env, vect_off);
1182         break;
1183     case MO_64:
1184         tcg_gen_st_i64(tcg_src, cpu_env, vect_off);
1185         break;
1186     default:
1187         g_assert_not_reached();
1188     }
1189 }
1190
1191 static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
1192                                   int destidx, int element, TCGMemOp memop)
1193 {
1194     int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
1195     switch (memop) {
1196     case MO_8:
1197         tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
1198         break;
1199     case MO_16:
1200         tcg_gen_st16_i32(tcg_src, cpu_env, vect_off);
1201         break;
1202     case MO_32:
1203         tcg_gen_st_i32(tcg_src, cpu_env, vect_off);
1204         break;
1205     default:
1206         g_assert_not_reached();
1207     }
1208 }
1209
1210 /* Store from vector register to memory */
1211 static void do_vec_st(DisasContext *s, int srcidx, int element,
1212                       TCGv_i64 tcg_addr, int size, TCGMemOp endian)
1213 {
1214     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1215
1216     read_vec_element(s, tcg_tmp, srcidx, element, size);
1217     tcg_gen_qemu_st_i64(tcg_tmp, tcg_addr, get_mem_index(s), endian | size);
1218
1219     tcg_temp_free_i64(tcg_tmp);
1220 }
1221
1222 /* Load from memory to vector register */
1223 static void do_vec_ld(DisasContext *s, int destidx, int element,
1224                       TCGv_i64 tcg_addr, int size, TCGMemOp endian)
1225 {
1226     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1227
1228     tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), endian | size);
1229     write_vec_element(s, tcg_tmp, destidx, element, size);
1230
1231     tcg_temp_free_i64(tcg_tmp);
1232 }
1233
1234 /* Check that FP/Neon access is enabled. If it is, return
1235  * true. If not, emit code to generate an appropriate exception,
1236  * and return false; the caller should not emit any code for
1237  * the instruction. Note that this check must happen after all
1238  * unallocated-encoding checks (otherwise the syndrome information
1239  * for the resulting exception will be incorrect).
1240  */
1241 static inline bool fp_access_check(DisasContext *s)
1242 {
1243     assert(!s->fp_access_checked);
1244     s->fp_access_checked = true;
1245
1246     if (!s->fp_excp_el) {
1247         return true;
1248     }
1249
1250     gen_exception_insn(s, 4, EXCP_UDEF, syn_fp_access_trap(1, 0xe, false),
1251                        s->fp_excp_el);
1252     return false;
1253 }
1254
1255 /* Check that SVE access is enabled.  If it is, return true.
1256  * If not, emit code to generate an appropriate exception and return false.
1257  */
1258 bool sve_access_check(DisasContext *s)
1259 {
1260     if (s->sve_excp_el) {
1261         gen_exception_insn(s, 4, EXCP_UDEF, syn_sve_access_trap(),
1262                            s->sve_excp_el);
1263         return false;
1264     }
1265     return fp_access_check(s);
1266 }
1267
1268 /*
1269  * This utility function is for doing register extension with an
1270  * optional shift. You will likely want to pass a temporary for the
1271  * destination register. See DecodeRegExtend() in the ARM ARM.
1272  */
1273 static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
1274                               int option, unsigned int shift)
1275 {
1276     int extsize = extract32(option, 0, 2);
1277     bool is_signed = extract32(option, 2, 1);
1278
1279     if (is_signed) {
1280         switch (extsize) {
1281         case 0:
1282             tcg_gen_ext8s_i64(tcg_out, tcg_in);
1283             break;
1284         case 1:
1285             tcg_gen_ext16s_i64(tcg_out, tcg_in);
1286             break;
1287         case 2:
1288             tcg_gen_ext32s_i64(tcg_out, tcg_in);
1289             break;
1290         case 3:
1291             tcg_gen_mov_i64(tcg_out, tcg_in);
1292             break;
1293         }
1294     } else {
1295         switch (extsize) {
1296         case 0:
1297             tcg_gen_ext8u_i64(tcg_out, tcg_in);
1298             break;
1299         case 1:
1300             tcg_gen_ext16u_i64(tcg_out, tcg_in);
1301             break;
1302         case 2:
1303             tcg_gen_ext32u_i64(tcg_out, tcg_in);
1304             break;
1305         case 3:
1306             tcg_gen_mov_i64(tcg_out, tcg_in);
1307             break;
1308         }
1309     }
1310
1311     if (shift) {
1312         tcg_gen_shli_i64(tcg_out, tcg_out, shift);
1313     }
1314 }
1315
1316 static inline void gen_check_sp_alignment(DisasContext *s)
1317 {
1318     /* The AArch64 architecture mandates that (if enabled via PSTATE
1319      * or SCTLR bits) there is a check that SP is 16-aligned on every
1320      * SP-relative load or store (with an exception generated if it is not).
1321      * In line with general QEMU practice regarding misaligned accesses,
1322      * we omit these checks for the sake of guest program performance.
1323      * This function is provided as a hook so we can more easily add these
1324      * checks in future (possibly as a "favour catching guest program bugs
1325      * over speed" user selectable option).
1326      */
1327 }
1328
1329 /*
1330  * This provides a simple table based table lookup decoder. It is
1331  * intended to be used when the relevant bits for decode are too
1332  * awkwardly placed and switch/if based logic would be confusing and
1333  * deeply nested. Since it's a linear search through the table, tables
1334  * should be kept small.
1335  *
1336  * It returns the first handler where insn & mask == pattern, or
1337  * NULL if there is no match.
1338  * The table is terminated by an empty mask (i.e. 0)
1339  */
1340 static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
1341                                                uint32_t insn)
1342 {
1343     const AArch64DecodeTable *tptr = table;
1344
1345     while (tptr->mask) {
1346         if ((insn & tptr->mask) == tptr->pattern) {
1347             return tptr->disas_fn;
1348         }
1349         tptr++;
1350     }
1351     return NULL;
1352 }
1353
1354 /*
1355  * The instruction disassembly implemented here matches
1356  * the instruction encoding classifications in chapter C4
1357  * of the ARM Architecture Reference Manual (DDI0487B_a);
1358  * classification names and decode diagrams here should generally
1359  * match up with those in the manual.
1360  */
1361
1362 /* Unconditional branch (immediate)
1363  *   31  30       26 25                                  0
1364  * +----+-----------+-------------------------------------+
1365  * | op | 0 0 1 0 1 |                 imm26               |
1366  * +----+-----------+-------------------------------------+
1367  */
1368 static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
1369 {
1370     uint64_t addr = s->pc + sextract32(insn, 0, 26) * 4 - 4;
1371
1372     if (insn & (1U << 31)) {
1373         /* BL Branch with link */
1374         tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
1375     }
1376
1377     /* B Branch / BL Branch with link */
1378     reset_btype(s);
1379     gen_goto_tb(s, 0, addr);
1380 }
1381
1382 /* Compare and branch (immediate)
1383  *   31  30         25  24  23                  5 4      0
1384  * +----+-------------+----+---------------------+--------+
1385  * | sf | 0 1 1 0 1 0 | op |         imm19       |   Rt   |
1386  * +----+-------------+----+---------------------+--------+
1387  */
1388 static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
1389 {
1390     unsigned int sf, op, rt;
1391     uint64_t addr;
1392     TCGLabel *label_match;
1393     TCGv_i64 tcg_cmp;
1394
1395     sf = extract32(insn, 31, 1);
1396     op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
1397     rt = extract32(insn, 0, 5);
1398     addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
1399
1400     tcg_cmp = read_cpu_reg(s, rt, sf);
1401     label_match = gen_new_label();
1402
1403     reset_btype(s);
1404     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1405                         tcg_cmp, 0, label_match);
1406
1407     gen_goto_tb(s, 0, s->pc);
1408     gen_set_label(label_match);
1409     gen_goto_tb(s, 1, addr);
1410 }
1411
1412 /* Test and branch (immediate)
1413  *   31  30         25  24  23   19 18          5 4    0
1414  * +----+-------------+----+-------+-------------+------+
1415  * | b5 | 0 1 1 0 1 1 | op |  b40  |    imm14    |  Rt  |
1416  * +----+-------------+----+-------+-------------+------+
1417  */
1418 static void disas_test_b_imm(DisasContext *s, uint32_t insn)
1419 {
1420     unsigned int bit_pos, op, rt;
1421     uint64_t addr;
1422     TCGLabel *label_match;
1423     TCGv_i64 tcg_cmp;
1424
1425     bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
1426     op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
1427     addr = s->pc + sextract32(insn, 5, 14) * 4 - 4;
1428     rt = extract32(insn, 0, 5);
1429
1430     tcg_cmp = tcg_temp_new_i64();
1431     tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
1432     label_match = gen_new_label();
1433
1434     reset_btype(s);
1435     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1436                         tcg_cmp, 0, label_match);
1437     tcg_temp_free_i64(tcg_cmp);
1438     gen_goto_tb(s, 0, s->pc);
1439     gen_set_label(label_match);
1440     gen_goto_tb(s, 1, addr);
1441 }
1442
1443 /* Conditional branch (immediate)
1444  *  31           25  24  23                  5   4  3    0
1445  * +---------------+----+---------------------+----+------+
1446  * | 0 1 0 1 0 1 0 | o1 |         imm19       | o0 | cond |
1447  * +---------------+----+---------------------+----+------+
1448  */
1449 static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
1450 {
1451     unsigned int cond;
1452     uint64_t addr;
1453
1454     if ((insn & (1 << 4)) || (insn & (1 << 24))) {
1455         unallocated_encoding(s);
1456         return;
1457     }
1458     addr = s->pc + sextract32(insn, 5, 19) * 4 - 4;
1459     cond = extract32(insn, 0, 4);
1460
1461     reset_btype(s);
1462     if (cond < 0x0e) {
1463         /* genuinely conditional branches */
1464         TCGLabel *label_match = gen_new_label();
1465         arm_gen_test_cc(cond, label_match);
1466         gen_goto_tb(s, 0, s->pc);
1467         gen_set_label(label_match);
1468         gen_goto_tb(s, 1, addr);
1469     } else {
1470         /* 0xe and 0xf are both "always" conditions */
1471         gen_goto_tb(s, 0, addr);
1472     }
1473 }
1474
1475 /* HINT instruction group, including various allocated HINTs */
1476 static void handle_hint(DisasContext *s, uint32_t insn,
1477                         unsigned int op1, unsigned int op2, unsigned int crm)
1478 {
1479     unsigned int selector = crm << 3 | op2;
1480
1481     if (op1 != 3) {
1482         unallocated_encoding(s);
1483         return;
1484     }
1485
1486     switch (selector) {
1487     case 0b00000: /* NOP */
1488         break;
1489     case 0b00011: /* WFI */
1490         s->base.is_jmp = DISAS_WFI;
1491         break;
1492     case 0b00001: /* YIELD */
1493         /* When running in MTTCG we don't generate jumps to the yield and
1494          * WFE helpers as it won't affect the scheduling of other vCPUs.
1495          * If we wanted to more completely model WFE/SEV so we don't busy
1496          * spin unnecessarily we would need to do something more involved.
1497          */
1498         if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
1499             s->base.is_jmp = DISAS_YIELD;
1500         }
1501         break;
1502     case 0b00010: /* WFE */
1503         if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
1504             s->base.is_jmp = DISAS_WFE;
1505         }
1506         break;
1507     case 0b00100: /* SEV */
1508     case 0b00101: /* SEVL */
1509         /* we treat all as NOP at least for now */
1510         break;
1511     case 0b00111: /* XPACLRI */
1512         if (s->pauth_active) {
1513             gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
1514         }
1515         break;
1516     case 0b01000: /* PACIA1716 */
1517         if (s->pauth_active) {
1518             gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
1519         }
1520         break;
1521     case 0b01010: /* PACIB1716 */
1522         if (s->pauth_active) {
1523             gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
1524         }
1525         break;
1526     case 0b01100: /* AUTIA1716 */
1527         if (s->pauth_active) {
1528             gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
1529         }
1530         break;
1531     case 0b01110: /* AUTIB1716 */
1532         if (s->pauth_active) {
1533             gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
1534         }
1535         break;
1536     case 0b11000: /* PACIAZ */
1537         if (s->pauth_active) {
1538             gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30],
1539                                 new_tmp_a64_zero(s));
1540         }
1541         break;
1542     case 0b11001: /* PACIASP */
1543         if (s->pauth_active) {
1544             gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
1545         }
1546         break;
1547     case 0b11010: /* PACIBZ */
1548         if (s->pauth_active) {
1549             gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30],
1550                                 new_tmp_a64_zero(s));
1551         }
1552         break;
1553     case 0b11011: /* PACIBSP */
1554         if (s->pauth_active) {
1555             gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
1556         }
1557         break;
1558     case 0b11100: /* AUTIAZ */
1559         if (s->pauth_active) {
1560             gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30],
1561                               new_tmp_a64_zero(s));
1562         }
1563         break;
1564     case 0b11101: /* AUTIASP */
1565         if (s->pauth_active) {
1566             gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
1567         }
1568         break;
1569     case 0b11110: /* AUTIBZ */
1570         if (s->pauth_active) {
1571             gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30],
1572                               new_tmp_a64_zero(s));
1573         }
1574         break;
1575     case 0b11111: /* AUTIBSP */
1576         if (s->pauth_active) {
1577             gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
1578         }
1579         break;
1580     default:
1581         /* default specified as NOP equivalent */
1582         break;
1583     }
1584 }
1585
1586 static void gen_clrex(DisasContext *s, uint32_t insn)
1587 {
1588     tcg_gen_movi_i64(cpu_exclusive_addr, -1);
1589 }
1590
1591 /* CLREX, DSB, DMB, ISB */
1592 static void handle_sync(DisasContext *s, uint32_t insn,
1593                         unsigned int op1, unsigned int op2, unsigned int crm)
1594 {
1595     TCGBar bar;
1596
1597     if (op1 != 3) {
1598         unallocated_encoding(s);
1599         return;
1600     }
1601
1602     switch (op2) {
1603     case 2: /* CLREX */
1604         gen_clrex(s, insn);
1605         return;
1606     case 4: /* DSB */
1607     case 5: /* DMB */
1608         switch (crm & 3) {
1609         case 1: /* MBReqTypes_Reads */
1610             bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
1611             break;
1612         case 2: /* MBReqTypes_Writes */
1613             bar = TCG_BAR_SC | TCG_MO_ST_ST;
1614             break;
1615         default: /* MBReqTypes_All */
1616             bar = TCG_BAR_SC | TCG_MO_ALL;
1617             break;
1618         }
1619         tcg_gen_mb(bar);
1620         return;
1621     case 6: /* ISB */
1622         /* We need to break the TB after this insn to execute
1623          * a self-modified code correctly and also to take
1624          * any pending interrupts immediately.
1625          */
1626         reset_btype(s);
1627         gen_goto_tb(s, 0, s->pc);
1628         return;
1629
1630     case 7: /* SB */
1631         if (crm != 0 || !dc_isar_feature(aa64_sb, s)) {
1632             goto do_unallocated;
1633         }
1634         /*
1635          * TODO: There is no speculation barrier opcode for TCG;
1636          * MB and end the TB instead.
1637          */
1638         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
1639         gen_goto_tb(s, 0, s->pc);
1640         return;
1641
1642     default:
1643     do_unallocated:
1644         unallocated_encoding(s);
1645         return;
1646     }
1647 }
1648
1649 static void gen_xaflag(void)
1650 {
1651     TCGv_i32 z = tcg_temp_new_i32();
1652
1653     tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
1654
1655     /*
1656      * (!C & !Z) << 31
1657      * (!(C | Z)) << 31
1658      * ~((C | Z) << 31)
1659      * ~-(C | Z)
1660      * (C | Z) - 1
1661      */
1662     tcg_gen_or_i32(cpu_NF, cpu_CF, z);
1663     tcg_gen_subi_i32(cpu_NF, cpu_NF, 1);
1664
1665     /* !(Z & C) */
1666     tcg_gen_and_i32(cpu_ZF, z, cpu_CF);
1667     tcg_gen_xori_i32(cpu_ZF, cpu_ZF, 1);
1668
1669     /* (!C & Z) << 31 -> -(Z & ~C) */
1670     tcg_gen_andc_i32(cpu_VF, z, cpu_CF);
1671     tcg_gen_neg_i32(cpu_VF, cpu_VF);
1672
1673     /* C | Z */
1674     tcg_gen_or_i32(cpu_CF, cpu_CF, z);
1675
1676     tcg_temp_free_i32(z);
1677 }
1678
1679 static void gen_axflag(void)
1680 {
1681     tcg_gen_sari_i32(cpu_VF, cpu_VF, 31);         /* V ? -1 : 0 */
1682     tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF);     /* C & !V */
1683
1684     /* !(Z | V) -> !(!ZF | V) -> ZF & !V -> ZF & ~VF */
1685     tcg_gen_andc_i32(cpu_ZF, cpu_ZF, cpu_VF);
1686
1687     tcg_gen_movi_i32(cpu_NF, 0);
1688     tcg_gen_movi_i32(cpu_VF, 0);
1689 }
1690
1691 /* MSR (immediate) - move immediate to processor state field */
1692 static void handle_msr_i(DisasContext *s, uint32_t insn,
1693                          unsigned int op1, unsigned int op2, unsigned int crm)
1694 {
1695     TCGv_i32 t1;
1696     int op = op1 << 3 | op2;
1697
1698     /* End the TB by default, chaining is ok.  */
1699     s->base.is_jmp = DISAS_TOO_MANY;
1700
1701     switch (op) {
1702     case 0x00: /* CFINV */
1703         if (crm != 0 || !dc_isar_feature(aa64_condm_4, s)) {
1704             goto do_unallocated;
1705         }
1706         tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
1707         s->base.is_jmp = DISAS_NEXT;
1708         break;
1709
1710     case 0x01: /* XAFlag */
1711         if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
1712             goto do_unallocated;
1713         }
1714         gen_xaflag();
1715         s->base.is_jmp = DISAS_NEXT;
1716         break;
1717
1718     case 0x02: /* AXFlag */
1719         if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
1720             goto do_unallocated;
1721         }
1722         gen_axflag();
1723         s->base.is_jmp = DISAS_NEXT;
1724         break;
1725
1726     case 0x05: /* SPSel */
1727         if (s->current_el == 0) {
1728             goto do_unallocated;
1729         }
1730         t1 = tcg_const_i32(crm & PSTATE_SP);
1731         gen_helper_msr_i_spsel(cpu_env, t1);
1732         tcg_temp_free_i32(t1);
1733         break;
1734
1735     case 0x1e: /* DAIFSet */
1736         t1 = tcg_const_i32(crm);
1737         gen_helper_msr_i_daifset(cpu_env, t1);
1738         tcg_temp_free_i32(t1);
1739         break;
1740
1741     case 0x1f: /* DAIFClear */
1742         t1 = tcg_const_i32(crm);
1743         gen_helper_msr_i_daifclear(cpu_env, t1);
1744         tcg_temp_free_i32(t1);
1745         /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs.  */
1746         s->base.is_jmp = DISAS_UPDATE;
1747         break;
1748
1749     default:
1750     do_unallocated:
1751         unallocated_encoding(s);
1752         return;
1753     }
1754 }
1755
1756 static void gen_get_nzcv(TCGv_i64 tcg_rt)
1757 {
1758     TCGv_i32 tmp = tcg_temp_new_i32();
1759     TCGv_i32 nzcv = tcg_temp_new_i32();
1760
1761     /* build bit 31, N */
1762     tcg_gen_andi_i32(nzcv, cpu_NF, (1U << 31));
1763     /* build bit 30, Z */
1764     tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
1765     tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
1766     /* build bit 29, C */
1767     tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
1768     /* build bit 28, V */
1769     tcg_gen_shri_i32(tmp, cpu_VF, 31);
1770     tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
1771     /* generate result */
1772     tcg_gen_extu_i32_i64(tcg_rt, nzcv);
1773
1774     tcg_temp_free_i32(nzcv);
1775     tcg_temp_free_i32(tmp);
1776 }
1777
1778 static void gen_set_nzcv(TCGv_i64 tcg_rt)
1779 {
1780     TCGv_i32 nzcv = tcg_temp_new_i32();
1781
1782     /* take NZCV from R[t] */
1783     tcg_gen_extrl_i64_i32(nzcv, tcg_rt);
1784
1785     /* bit 31, N */
1786     tcg_gen_andi_i32(cpu_NF, nzcv, (1U << 31));
1787     /* bit 30, Z */
1788     tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
1789     tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
1790     /* bit 29, C */
1791     tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
1792     tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
1793     /* bit 28, V */
1794     tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
1795     tcg_gen_shli_i32(cpu_VF, cpu_VF, 3);
1796     tcg_temp_free_i32(nzcv);
1797 }
1798
1799 /* MRS - move from system register
1800  * MSR (register) - move to system register
1801  * SYS
1802  * SYSL
1803  * These are all essentially the same insn in 'read' and 'write'
1804  * versions, with varying op0 fields.
1805  */
1806 static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
1807                        unsigned int op0, unsigned int op1, unsigned int op2,
1808                        unsigned int crn, unsigned int crm, unsigned int rt)
1809 {
1810     const ARMCPRegInfo *ri;
1811     TCGv_i64 tcg_rt;
1812
1813     ri = get_arm_cp_reginfo(s->cp_regs,
1814                             ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
1815                                                crn, crm, op0, op1, op2));
1816
1817     if (!ri) {
1818         /* Unknown register; this might be a guest error or a QEMU
1819          * unimplemented feature.
1820          */
1821         qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch64 "
1822                       "system register op0:%d op1:%d crn:%d crm:%d op2:%d\n",
1823                       isread ? "read" : "write", op0, op1, crn, crm, op2);
1824         unallocated_encoding(s);
1825         return;
1826     }
1827
1828     /* Check access permissions */
1829     if (!cp_access_ok(s->current_el, ri, isread)) {
1830         unallocated_encoding(s);
1831         return;
1832     }
1833
1834     if (ri->accessfn) {
1835         /* Emit code to perform further access permissions checks at
1836          * runtime; this may result in an exception.
1837          */
1838         TCGv_ptr tmpptr;
1839         TCGv_i32 tcg_syn, tcg_isread;
1840         uint32_t syndrome;
1841
1842         gen_a64_set_pc_im(s->pc - 4);
1843         tmpptr = tcg_const_ptr(ri);
1844         syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
1845         tcg_syn = tcg_const_i32(syndrome);
1846         tcg_isread = tcg_const_i32(isread);
1847         gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn, tcg_isread);
1848         tcg_temp_free_ptr(tmpptr);
1849         tcg_temp_free_i32(tcg_syn);
1850         tcg_temp_free_i32(tcg_isread);
1851     }
1852
1853     /* Handle special cases first */
1854     switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
1855     case ARM_CP_NOP:
1856         return;
1857     case ARM_CP_NZCV:
1858         tcg_rt = cpu_reg(s, rt);
1859         if (isread) {
1860             gen_get_nzcv(tcg_rt);
1861         } else {
1862             gen_set_nzcv(tcg_rt);
1863         }
1864         return;
1865     case ARM_CP_CURRENTEL:
1866         /* Reads as current EL value from pstate, which is
1867          * guaranteed to be constant by the tb flags.
1868          */
1869         tcg_rt = cpu_reg(s, rt);
1870         tcg_gen_movi_i64(tcg_rt, s->current_el << 2);
1871         return;
1872     case ARM_CP_DC_ZVA:
1873         /* Writes clear the aligned block of memory which rt points into. */
1874         tcg_rt = cpu_reg(s, rt);
1875         gen_helper_dc_zva(cpu_env, tcg_rt);
1876         return;
1877     default:
1878         break;
1879     }
1880     if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
1881         return;
1882     } else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
1883         return;
1884     }
1885
1886     if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
1887         gen_io_start();
1888     }
1889
1890     tcg_rt = cpu_reg(s, rt);
1891
1892     if (isread) {
1893         if (ri->type & ARM_CP_CONST) {
1894             tcg_gen_movi_i64(tcg_rt, ri->resetvalue);
1895         } else if (ri->readfn) {
1896             TCGv_ptr tmpptr;
1897             tmpptr = tcg_const_ptr(ri);
1898             gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr);
1899             tcg_temp_free_ptr(tmpptr);
1900         } else {
1901             tcg_gen_ld_i64(tcg_rt, cpu_env, ri->fieldoffset);
1902         }
1903     } else {
1904         if (ri->type & ARM_CP_CONST) {
1905             /* If not forbidden by access permissions, treat as WI */
1906             return;
1907         } else if (ri->writefn) {
1908             TCGv_ptr tmpptr;
1909             tmpptr = tcg_const_ptr(ri);
1910             gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt);
1911             tcg_temp_free_ptr(tmpptr);
1912         } else {
1913             tcg_gen_st_i64(tcg_rt, cpu_env, ri->fieldoffset);
1914         }
1915     }
1916
1917     if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
1918         /* I/O operations must end the TB here (whether read or write) */
1919         gen_io_end();
1920         s->base.is_jmp = DISAS_UPDATE;
1921     } else if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
1922         /* We default to ending the TB on a coprocessor register write,
1923          * but allow this to be suppressed by the register definition
1924          * (usually only necessary to work around guest bugs).
1925          */
1926         s->base.is_jmp = DISAS_UPDATE;
1927     }
1928 }
1929
1930 /* System
1931  *  31                 22 21  20 19 18 16 15   12 11    8 7   5 4    0
1932  * +---------------------+---+-----+-----+-------+-------+-----+------+
1933  * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 |  CRn  |  CRm  | op2 |  Rt  |
1934  * +---------------------+---+-----+-----+-------+-------+-----+------+
1935  */
1936 static void disas_system(DisasContext *s, uint32_t insn)
1937 {
1938     unsigned int l, op0, op1, crn, crm, op2, rt;
1939     l = extract32(insn, 21, 1);
1940     op0 = extract32(insn, 19, 2);
1941     op1 = extract32(insn, 16, 3);
1942     crn = extract32(insn, 12, 4);
1943     crm = extract32(insn, 8, 4);
1944     op2 = extract32(insn, 5, 3);
1945     rt = extract32(insn, 0, 5);
1946
1947     if (op0 == 0) {
1948         if (l || rt != 31) {
1949             unallocated_encoding(s);
1950             return;
1951         }
1952         switch (crn) {
1953         case 2: /* HINT (including allocated hints like NOP, YIELD, etc) */
1954             handle_hint(s, insn, op1, op2, crm);
1955             break;
1956         case 3: /* CLREX, DSB, DMB, ISB */
1957             handle_sync(s, insn, op1, op2, crm);
1958             break;
1959         case 4: /* MSR (immediate) */
1960             handle_msr_i(s, insn, op1, op2, crm);
1961             break;
1962         default:
1963             unallocated_encoding(s);
1964             break;
1965         }
1966         return;
1967     }
1968     handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
1969 }
1970
1971 /* Exception generation
1972  *
1973  *  31             24 23 21 20                     5 4   2 1  0
1974  * +-----------------+-----+------------------------+-----+----+
1975  * | 1 1 0 1 0 1 0 0 | opc |          imm16         | op2 | LL |
1976  * +-----------------------+------------------------+----------+
1977  */
1978 static void disas_exc(DisasContext *s, uint32_t insn)
1979 {
1980     int opc = extract32(insn, 21, 3);
1981     int op2_ll = extract32(insn, 0, 5);
1982     int imm16 = extract32(insn, 5, 16);
1983     TCGv_i32 tmp;
1984
1985     switch (opc) {
1986     case 0:
1987         /* For SVC, HVC and SMC we advance the single-step state
1988          * machine before taking the exception. This is architecturally
1989          * mandated, to ensure that single-stepping a system call
1990          * instruction works properly.
1991          */
1992         switch (op2_ll) {
1993         case 1:                                                     /* SVC */
1994             gen_ss_advance(s);
1995             gen_exception_insn(s, 0, EXCP_SWI, syn_aa64_svc(imm16),
1996                                default_exception_el(s));
1997             break;
1998         case 2:                                                     /* HVC */
1999             if (s->current_el == 0) {
2000                 unallocated_encoding(s);
2001                 break;
2002             }
2003             /* The pre HVC helper handles cases when HVC gets trapped
2004              * as an undefined insn by runtime configuration.
2005              */
2006             gen_a64_set_pc_im(s->pc - 4);
2007             gen_helper_pre_hvc(cpu_env);
2008             gen_ss_advance(s);
2009             gen_exception_insn(s, 0, EXCP_HVC, syn_aa64_hvc(imm16), 2);
2010             break;
2011         case 3:                                                     /* SMC */
2012             if (s->current_el == 0) {
2013                 unallocated_encoding(s);
2014                 break;
2015             }
2016             gen_a64_set_pc_im(s->pc - 4);
2017             tmp = tcg_const_i32(syn_aa64_smc(imm16));
2018             gen_helper_pre_smc(cpu_env, tmp);
2019             tcg_temp_free_i32(tmp);
2020             gen_ss_advance(s);
2021             gen_exception_insn(s, 0, EXCP_SMC, syn_aa64_smc(imm16), 3);
2022             break;
2023         default:
2024             unallocated_encoding(s);
2025             break;
2026         }
2027         break;
2028     case 1:
2029         if (op2_ll != 0) {
2030             unallocated_encoding(s);
2031             break;
2032         }
2033         /* BRK */
2034         gen_exception_bkpt_insn(s, 4, syn_aa64_bkpt(imm16));
2035         break;
2036     case 2:
2037         if (op2_ll != 0) {
2038             unallocated_encoding(s);
2039             break;
2040         }
2041         /* HLT. This has two purposes.
2042          * Architecturally, it is an external halting debug instruction.
2043          * Since QEMU doesn't implement external debug, we treat this as
2044          * it is required for halting debug disabled: it will UNDEF.
2045          * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
2046          */
2047         if (semihosting_enabled() && imm16 == 0xf000) {
2048 #ifndef CONFIG_USER_ONLY
2049             /* In system mode, don't allow userspace access to semihosting,
2050              * to provide some semblance of security (and for consistency
2051              * with our 32-bit semihosting).
2052              */
2053             if (s->current_el == 0) {
2054                 unsupported_encoding(s, insn);
2055                 break;
2056             }
2057 #endif
2058             gen_exception_internal_insn(s, 0, EXCP_SEMIHOST);
2059         } else {
2060             unsupported_encoding(s, insn);
2061         }
2062         break;
2063     case 5:
2064         if (op2_ll < 1 || op2_ll > 3) {
2065             unallocated_encoding(s);
2066             break;
2067         }
2068         /* DCPS1, DCPS2, DCPS3 */
2069         unsupported_encoding(s, insn);
2070         break;
2071     default:
2072         unallocated_encoding(s);
2073         break;
2074     }
2075 }
2076
2077 /* Unconditional branch (register)
2078  *  31           25 24   21 20   16 15   10 9    5 4     0
2079  * +---------------+-------+-------+-------+------+-------+
2080  * | 1 1 0 1 0 1 1 |  opc  |  op2  |  op3  |  Rn  |  op4  |
2081  * +---------------+-------+-------+-------+------+-------+
2082  */
2083 static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
2084 {
2085     unsigned int opc, op2, op3, rn, op4;
2086     unsigned btype_mod = 2;   /* 0: BR, 1: BLR, 2: other */
2087     TCGv_i64 dst;
2088     TCGv_i64 modifier;
2089
2090     opc = extract32(insn, 21, 4);
2091     op2 = extract32(insn, 16, 5);
2092     op3 = extract32(insn, 10, 6);
2093     rn = extract32(insn, 5, 5);
2094     op4 = extract32(insn, 0, 5);
2095
2096     if (op2 != 0x1f) {
2097         goto do_unallocated;
2098     }
2099
2100     switch (opc) {
2101     case 0: /* BR */
2102     case 1: /* BLR */
2103     case 2: /* RET */
2104         btype_mod = opc;
2105         switch (op3) {
2106         case 0:
2107             /* BR, BLR, RET */
2108             if (op4 != 0) {
2109                 goto do_unallocated;
2110             }
2111             dst = cpu_reg(s, rn);
2112             break;
2113
2114         case 2:
2115         case 3:
2116             if (!dc_isar_feature(aa64_pauth, s)) {
2117                 goto do_unallocated;
2118             }
2119             if (opc == 2) {
2120                 /* RETAA, RETAB */
2121                 if (rn != 0x1f || op4 != 0x1f) {
2122                     goto do_unallocated;
2123                 }
2124                 rn = 30;
2125                 modifier = cpu_X[31];
2126             } else {
2127                 /* BRAAZ, BRABZ, BLRAAZ, BLRABZ */
2128                 if (op4 != 0x1f) {
2129                     goto do_unallocated;
2130                 }
2131                 modifier = new_tmp_a64_zero(s);
2132             }
2133             if (s->pauth_active) {
2134                 dst = new_tmp_a64(s);
2135                 if (op3 == 2) {
2136                     gen_helper_autia(dst, cpu_env, cpu_reg(s, rn), modifier);
2137                 } else {
2138                     gen_helper_autib(dst, cpu_env, cpu_reg(s, rn), modifier);
2139                 }
2140             } else {
2141                 dst = cpu_reg(s, rn);
2142             }
2143             break;
2144
2145         default:
2146             goto do_unallocated;
2147         }
2148         gen_a64_set_pc(s, dst);
2149         /* BLR also needs to load return address */
2150         if (opc == 1) {
2151             tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
2152         }
2153         break;
2154
2155     case 8: /* BRAA */
2156     case 9: /* BLRAA */
2157         if (!dc_isar_feature(aa64_pauth, s)) {
2158             goto do_unallocated;
2159         }
2160         if ((op3 & ~1) != 2) {
2161             goto do_unallocated;
2162         }
2163         btype_mod = opc & 1;
2164         if (s->pauth_active) {
2165             dst = new_tmp_a64(s);
2166             modifier = cpu_reg_sp(s, op4);
2167             if (op3 == 2) {
2168                 gen_helper_autia(dst, cpu_env, cpu_reg(s, rn), modifier);
2169             } else {
2170                 gen_helper_autib(dst, cpu_env, cpu_reg(s, rn), modifier);
2171             }
2172         } else {
2173             dst = cpu_reg(s, rn);
2174         }
2175         gen_a64_set_pc(s, dst);
2176         /* BLRAA also needs to load return address */
2177         if (opc == 9) {
2178             tcg_gen_movi_i64(cpu_reg(s, 30), s->pc);
2179         }
2180         break;
2181
2182     case 4: /* ERET */
2183         if (s->current_el == 0) {
2184             goto do_unallocated;
2185         }
2186         switch (op3) {
2187         case 0: /* ERET */
2188             if (op4 != 0) {
2189                 goto do_unallocated;
2190             }
2191             dst = tcg_temp_new_i64();
2192             tcg_gen_ld_i64(dst, cpu_env,
2193                            offsetof(CPUARMState, elr_el[s->current_el]));
2194             break;
2195
2196         case 2: /* ERETAA */
2197         case 3: /* ERETAB */
2198             if (!dc_isar_feature(aa64_pauth, s)) {
2199                 goto do_unallocated;
2200             }
2201             if (rn != 0x1f || op4 != 0x1f) {
2202                 goto do_unallocated;
2203             }
2204             dst = tcg_temp_new_i64();
2205             tcg_gen_ld_i64(dst, cpu_env,
2206                            offsetof(CPUARMState, elr_el[s->current_el]));
2207             if (s->pauth_active) {
2208                 modifier = cpu_X[31];
2209                 if (op3 == 2) {
2210                     gen_helper_autia(dst, cpu_env, dst, modifier);
2211                 } else {
2212                     gen_helper_autib(dst, cpu_env, dst, modifier);
2213                 }
2214             }
2215             break;
2216
2217         default:
2218             goto do_unallocated;
2219         }
2220         if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2221             gen_io_start();
2222         }
2223
2224         gen_helper_exception_return(cpu_env, dst);
2225         tcg_temp_free_i64(dst);
2226         if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2227             gen_io_end();
2228         }
2229         /* Must exit loop to check un-masked IRQs */
2230         s->base.is_jmp = DISAS_EXIT;
2231         return;
2232
2233     case 5: /* DRPS */
2234         if (op3 != 0 || op4 != 0 || rn != 0x1f) {
2235             goto do_unallocated;
2236         } else {
2237             unsupported_encoding(s, insn);
2238         }
2239         return;
2240
2241     default:
2242     do_unallocated:
2243         unallocated_encoding(s);
2244         return;
2245     }
2246
2247     switch (btype_mod) {
2248     case 0: /* BR */
2249         if (dc_isar_feature(aa64_bti, s)) {
2250             /* BR to {x16,x17} or !guard -> 1, else 3.  */
2251             set_btype(s, rn == 16 || rn == 17 || !s->guarded_page ? 1 : 3);
2252         }
2253         break;
2254
2255     case 1: /* BLR */
2256         if (dc_isar_feature(aa64_bti, s)) {
2257             /* BLR sets BTYPE to 2, regardless of source guarded page.  */
2258             set_btype(s, 2);
2259         }
2260         break;
2261
2262     default: /* RET or none of the above.  */
2263         /* BTYPE will be set to 0 by normal end-of-insn processing.  */
2264         break;
2265     }
2266
2267     s->base.is_jmp = DISAS_JUMP;
2268 }
2269
2270 /* Branches, exception generating and system instructions */
2271 static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
2272 {
2273     switch (extract32(insn, 25, 7)) {
2274     case 0x0a: case 0x0b:
2275     case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
2276         disas_uncond_b_imm(s, insn);
2277         break;
2278     case 0x1a: case 0x5a: /* Compare & branch (immediate) */
2279         disas_comp_b_imm(s, insn);
2280         break;
2281     case 0x1b: case 0x5b: /* Test & branch (immediate) */
2282         disas_test_b_imm(s, insn);
2283         break;
2284     case 0x2a: /* Conditional branch (immediate) */
2285         disas_cond_b_imm(s, insn);
2286         break;
2287     case 0x6a: /* Exception generation / System */
2288         if (insn & (1 << 24)) {
2289             if (extract32(insn, 22, 2) == 0) {
2290                 disas_system(s, insn);
2291             } else {
2292                 unallocated_encoding(s);
2293             }
2294         } else {
2295             disas_exc(s, insn);
2296         }
2297         break;
2298     case 0x6b: /* Unconditional branch (register) */
2299         disas_uncond_b_reg(s, insn);
2300         break;
2301     default:
2302         unallocated_encoding(s);
2303         break;
2304     }
2305 }
2306
2307 /*
2308  * Load/Store exclusive instructions are implemented by remembering
2309  * the value/address loaded, and seeing if these are the same
2310  * when the store is performed. This is not actually the architecturally
2311  * mandated semantics, but it works for typical guest code sequences
2312  * and avoids having to monitor regular stores.
2313  *
2314  * The store exclusive uses the atomic cmpxchg primitives to avoid
2315  * races in multi-threaded linux-user and when MTTCG softmmu is
2316  * enabled.
2317  */
2318 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
2319                                TCGv_i64 addr, int size, bool is_pair)
2320 {
2321     int idx = get_mem_index(s);
2322     TCGMemOp memop = s->be_data;
2323
2324     g_assert(size <= 3);
2325     if (is_pair) {
2326         g_assert(size >= 2);
2327         if (size == 2) {
2328             /* The pair must be single-copy atomic for the doubleword.  */
2329             memop |= MO_64 | MO_ALIGN;
2330             tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
2331             if (s->be_data == MO_LE) {
2332                 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
2333                 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 32, 32);
2334             } else {
2335                 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 32, 32);
2336                 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 0, 32);
2337             }
2338         } else {
2339             /* The pair must be single-copy atomic for *each* doubleword, not
2340                the entire quadword, however it must be quadword aligned.  */
2341             memop |= MO_64;
2342             tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx,
2343                                 memop | MO_ALIGN_16);
2344
2345             TCGv_i64 addr2 = tcg_temp_new_i64();
2346             tcg_gen_addi_i64(addr2, addr, 8);
2347             tcg_gen_qemu_ld_i64(cpu_exclusive_high, addr2, idx, memop);
2348             tcg_temp_free_i64(addr2);
2349
2350             tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
2351             tcg_gen_mov_i64(cpu_reg(s, rt2), cpu_exclusive_high);
2352         }
2353     } else {
2354         memop |= size | MO_ALIGN;
2355         tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
2356         tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
2357     }
2358     tcg_gen_mov_i64(cpu_exclusive_addr, addr);
2359 }
2360
2361 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
2362                                 TCGv_i64 addr, int size, int is_pair)
2363 {
2364     /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]
2365      *     && (!is_pair || env->exclusive_high == [addr + datasize])) {
2366      *     [addr] = {Rt};
2367      *     if (is_pair) {
2368      *         [addr + datasize] = {Rt2};
2369      *     }
2370      *     {Rd} = 0;
2371      * } else {
2372      *     {Rd} = 1;
2373      * }
2374      * env->exclusive_addr = -1;
2375      */
2376     TCGLabel *fail_label = gen_new_label();
2377     TCGLabel *done_label = gen_new_label();
2378     TCGv_i64 tmp;
2379
2380     tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
2381
2382     tmp = tcg_temp_new_i64();
2383     if (is_pair) {
2384         if (size == 2) {
2385             if (s->be_data == MO_LE) {
2386                 tcg_gen_concat32_i64(tmp, cpu_reg(s, rt), cpu_reg(s, rt2));
2387             } else {
2388                 tcg_gen_concat32_i64(tmp, cpu_reg(s, rt2), cpu_reg(s, rt));
2389             }
2390             tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr,
2391                                        cpu_exclusive_val, tmp,
2392                                        get_mem_index(s),
2393                                        MO_64 | MO_ALIGN | s->be_data);
2394             tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
2395         } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2396             if (!HAVE_CMPXCHG128) {
2397                 gen_helper_exit_atomic(cpu_env);
2398                 s->base.is_jmp = DISAS_NORETURN;
2399             } else if (s->be_data == MO_LE) {
2400                 gen_helper_paired_cmpxchg64_le_parallel(tmp, cpu_env,
2401                                                         cpu_exclusive_addr,
2402                                                         cpu_reg(s, rt),
2403                                                         cpu_reg(s, rt2));
2404             } else {
2405                 gen_helper_paired_cmpxchg64_be_parallel(tmp, cpu_env,
2406                                                         cpu_exclusive_addr,
2407                                                         cpu_reg(s, rt),
2408                                                         cpu_reg(s, rt2));
2409             }
2410         } else if (s->be_data == MO_LE) {
2411             gen_helper_paired_cmpxchg64_le(tmp, cpu_env, cpu_exclusive_addr,
2412                                            cpu_reg(s, rt), cpu_reg(s, rt2));
2413         } else {
2414             gen_helper_paired_cmpxchg64_be(tmp, cpu_env, cpu_exclusive_addr,
2415                                            cpu_reg(s, rt), cpu_reg(s, rt2));
2416         }
2417     } else {
2418         tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr, cpu_exclusive_val,
2419                                    cpu_reg(s, rt), get_mem_index(s),
2420                                    size | MO_ALIGN | s->be_data);
2421         tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
2422     }
2423     tcg_gen_mov_i64(cpu_reg(s, rd), tmp);
2424     tcg_temp_free_i64(tmp);
2425     tcg_gen_br(done_label);
2426
2427     gen_set_label(fail_label);
2428     tcg_gen_movi_i64(cpu_reg(s, rd), 1);
2429     gen_set_label(done_label);
2430     tcg_gen_movi_i64(cpu_exclusive_addr, -1);
2431 }
2432
2433 static void gen_compare_and_swap(DisasContext *s, int rs, int rt,
2434                                  int rn, int size)
2435 {
2436     TCGv_i64 tcg_rs = cpu_reg(s, rs);
2437     TCGv_i64 tcg_rt = cpu_reg(s, rt);
2438     int memidx = get_mem_index(s);
2439     TCGv_i64 clean_addr;
2440
2441     if (rn == 31) {
2442         gen_check_sp_alignment(s);
2443     }
2444     clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2445     tcg_gen_atomic_cmpxchg_i64(tcg_rs, clean_addr, tcg_rs, tcg_rt, memidx,
2446                                size | MO_ALIGN | s->be_data);
2447 }
2448
2449 static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
2450                                       int rn, int size)
2451 {
2452     TCGv_i64 s1 = cpu_reg(s, rs);
2453     TCGv_i64 s2 = cpu_reg(s, rs + 1);
2454     TCGv_i64 t1 = cpu_reg(s, rt);
2455     TCGv_i64 t2 = cpu_reg(s, rt + 1);
2456     TCGv_i64 clean_addr;
2457     int memidx = get_mem_index(s);
2458
2459     if (rn == 31) {
2460         gen_check_sp_alignment(s);
2461     }
2462     clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2463
2464     if (size == 2) {
2465         TCGv_i64 cmp = tcg_temp_new_i64();
2466         TCGv_i64 val = tcg_temp_new_i64();
2467
2468         if (s->be_data == MO_LE) {
2469             tcg_gen_concat32_i64(val, t1, t2);
2470             tcg_gen_concat32_i64(cmp, s1, s2);
2471         } else {
2472             tcg_gen_concat32_i64(val, t2, t1);
2473             tcg_gen_concat32_i64(cmp, s2, s1);
2474         }
2475
2476         tcg_gen_atomic_cmpxchg_i64(cmp, clean_addr, cmp, val, memidx,
2477                                    MO_64 | MO_ALIGN | s->be_data);
2478         tcg_temp_free_i64(val);
2479
2480         if (s->be_data == MO_LE) {
2481             tcg_gen_extr32_i64(s1, s2, cmp);
2482         } else {
2483             tcg_gen_extr32_i64(s2, s1, cmp);
2484         }
2485         tcg_temp_free_i64(cmp);
2486     } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2487         if (HAVE_CMPXCHG128) {
2488             TCGv_i32 tcg_rs = tcg_const_i32(rs);
2489             if (s->be_data == MO_LE) {
2490                 gen_helper_casp_le_parallel(cpu_env, tcg_rs,
2491                                             clean_addr, t1, t2);
2492             } else {
2493                 gen_helper_casp_be_parallel(cpu_env, tcg_rs,
2494                                             clean_addr, t1, t2);
2495             }
2496             tcg_temp_free_i32(tcg_rs);
2497         } else {
2498             gen_helper_exit_atomic(cpu_env);
2499             s->base.is_jmp = DISAS_NORETURN;
2500         }
2501     } else {
2502         TCGv_i64 d1 = tcg_temp_new_i64();
2503         TCGv_i64 d2 = tcg_temp_new_i64();
2504         TCGv_i64 a2 = tcg_temp_new_i64();
2505         TCGv_i64 c1 = tcg_temp_new_i64();
2506         TCGv_i64 c2 = tcg_temp_new_i64();
2507         TCGv_i64 zero = tcg_const_i64(0);
2508
2509         /* Load the two words, in memory order.  */
2510         tcg_gen_qemu_ld_i64(d1, clean_addr, memidx,
2511                             MO_64 | MO_ALIGN_16 | s->be_data);
2512         tcg_gen_addi_i64(a2, clean_addr, 8);
2513         tcg_gen_qemu_ld_i64(d2, a2, memidx, MO_64 | s->be_data);
2514
2515         /* Compare the two words, also in memory order.  */
2516         tcg_gen_setcond_i64(TCG_COND_EQ, c1, d1, s1);
2517         tcg_gen_setcond_i64(TCG_COND_EQ, c2, d2, s2);
2518         tcg_gen_and_i64(c2, c2, c1);
2519
2520         /* If compare equal, write back new data, else write back old data.  */
2521         tcg_gen_movcond_i64(TCG_COND_NE, c1, c2, zero, t1, d1);
2522         tcg_gen_movcond_i64(TCG_COND_NE, c2, c2, zero, t2, d2);
2523         tcg_gen_qemu_st_i64(c1, clean_addr, memidx, MO_64 | s->be_data);
2524         tcg_gen_qemu_st_i64(c2, a2, memidx, MO_64 | s->be_data);
2525         tcg_temp_free_i64(a2);
2526         tcg_temp_free_i64(c1);
2527         tcg_temp_free_i64(c2);
2528         tcg_temp_free_i64(zero);
2529
2530         /* Write back the data from memory to Rs.  */
2531         tcg_gen_mov_i64(s1, d1);
2532         tcg_gen_mov_i64(s2, d2);
2533         tcg_temp_free_i64(d1);
2534         tcg_temp_free_i64(d2);
2535     }
2536 }
2537
2538 /* Update the Sixty-Four bit (SF) registersize. This logic is derived
2539  * from the ARMv8 specs for LDR (Shared decode for all encodings).
2540  */
2541 static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
2542 {
2543     int opc0 = extract32(opc, 0, 1);
2544     int regsize;
2545
2546     if (is_signed) {
2547         regsize = opc0 ? 32 : 64;
2548     } else {
2549         regsize = size == 3 ? 64 : 32;
2550     }
2551     return regsize == 64;
2552 }
2553
2554 /* Load/store exclusive
2555  *
2556  *  31 30 29         24  23  22   21  20  16  15  14   10 9    5 4    0
2557  * +-----+-------------+----+---+----+------+----+-------+------+------+
2558  * | sz  | 0 0 1 0 0 0 | o2 | L | o1 |  Rs  | o0 |  Rt2  |  Rn  | Rt   |
2559  * +-----+-------------+----+---+----+------+----+-------+------+------+
2560  *
2561  *  sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
2562  *   L: 0 -> store, 1 -> load
2563  *  o2: 0 -> exclusive, 1 -> not
2564  *  o1: 0 -> single register, 1 -> register pair
2565  *  o0: 1 -> load-acquire/store-release, 0 -> not
2566  */
2567 static void disas_ldst_excl(DisasContext *s, uint32_t insn)
2568 {
2569     int rt = extract32(insn, 0, 5);
2570     int rn = extract32(insn, 5, 5);
2571     int rt2 = extract32(insn, 10, 5);
2572     int rs = extract32(insn, 16, 5);
2573     int is_lasr = extract32(insn, 15, 1);
2574     int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
2575     int size = extract32(insn, 30, 2);
2576     TCGv_i64 clean_addr;
2577
2578     switch (o2_L_o1_o0) {
2579     case 0x0: /* STXR */
2580     case 0x1: /* STLXR */
2581         if (rn == 31) {
2582             gen_check_sp_alignment(s);
2583         }
2584         if (is_lasr) {
2585             tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2586         }
2587         clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2588         gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, false);
2589         return;
2590
2591     case 0x4: /* LDXR */
2592     case 0x5: /* LDAXR */
2593         if (rn == 31) {
2594             gen_check_sp_alignment(s);
2595         }
2596         clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2597         s->is_ldex = true;
2598         gen_load_exclusive(s, rt, rt2, clean_addr, size, false);
2599         if (is_lasr) {
2600             tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2601         }
2602         return;
2603
2604     case 0x8: /* STLLR */
2605         if (!dc_isar_feature(aa64_lor, s)) {
2606             break;
2607         }
2608         /* StoreLORelease is the same as Store-Release for QEMU.  */
2609         /* fall through */
2610     case 0x9: /* STLR */
2611         /* Generate ISS for non-exclusive accesses including LASR.  */
2612         if (rn == 31) {
2613             gen_check_sp_alignment(s);
2614         }
2615         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2616         clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2617         do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt,
2618                   disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
2619         return;
2620
2621     case 0xc: /* LDLAR */
2622         if (!dc_isar_feature(aa64_lor, s)) {
2623             break;
2624         }
2625         /* LoadLOAcquire is the same as Load-Acquire for QEMU.  */
2626         /* fall through */
2627     case 0xd: /* LDAR */
2628         /* Generate ISS for non-exclusive accesses including LASR.  */
2629         if (rn == 31) {
2630             gen_check_sp_alignment(s);
2631         }
2632         clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2633         do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false, false, true, rt,
2634                   disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
2635         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2636         return;
2637
2638     case 0x2: case 0x3: /* CASP / STXP */
2639         if (size & 2) { /* STXP / STLXP */
2640             if (rn == 31) {
2641                 gen_check_sp_alignment(s);
2642             }
2643             if (is_lasr) {
2644                 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2645             }
2646             clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2647             gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, true);
2648             return;
2649         }
2650         if (rt2 == 31
2651             && ((rt | rs) & 1) == 0
2652             && dc_isar_feature(aa64_atomics, s)) {
2653             /* CASP / CASPL */
2654             gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
2655             return;
2656         }
2657         break;
2658
2659     case 0x6: case 0x7: /* CASPA / LDXP */
2660         if (size & 2) { /* LDXP / LDAXP */
2661             if (rn == 31) {
2662                 gen_check_sp_alignment(s);
2663             }
2664             clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2665             s->is_ldex = true;
2666             gen_load_exclusive(s, rt, rt2, clean_addr, size, true);
2667             if (is_lasr) {
2668                 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2669             }
2670             return;
2671         }
2672         if (rt2 == 31
2673             && ((rt | rs) & 1) == 0
2674             && dc_isar_feature(aa64_atomics, s)) {
2675             /* CASPA / CASPAL */
2676             gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
2677             return;
2678         }
2679         break;
2680
2681     case 0xa: /* CAS */
2682     case 0xb: /* CASL */
2683     case 0xe: /* CASA */
2684     case 0xf: /* CASAL */
2685         if (rt2 == 31 && dc_isar_feature(aa64_atomics, s)) {
2686             gen_compare_and_swap(s, rs, rt, rn, size);
2687             return;
2688         }
2689         break;
2690     }
2691     unallocated_encoding(s);
2692 }
2693
2694 /*
2695  * Load register (literal)
2696  *
2697  *  31 30 29   27  26 25 24 23                5 4     0
2698  * +-----+-------+---+-----+-------------------+-------+
2699  * | opc | 0 1 1 | V | 0 0 |     imm19         |  Rt   |
2700  * +-----+-------+---+-----+-------------------+-------+
2701  *
2702  * V: 1 -> vector (simd/fp)
2703  * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
2704  *                   10-> 32 bit signed, 11 -> prefetch
2705  * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
2706  */
2707 static void disas_ld_lit(DisasContext *s, uint32_t insn)
2708 {
2709     int rt = extract32(insn, 0, 5);
2710     int64_t imm = sextract32(insn, 5, 19) << 2;
2711     bool is_vector = extract32(insn, 26, 1);
2712     int opc = extract32(insn, 30, 2);
2713     bool is_signed = false;
2714     int size = 2;
2715     TCGv_i64 tcg_rt, clean_addr;
2716
2717     if (is_vector) {
2718         if (opc == 3) {
2719             unallocated_encoding(s);
2720             return;
2721         }
2722         size = 2 + opc;
2723         if (!fp_access_check(s)) {
2724             return;
2725         }
2726     } else {
2727         if (opc == 3) {
2728             /* PRFM (literal) : prefetch */
2729             return;
2730         }
2731         size = 2 + extract32(opc, 0, 1);
2732         is_signed = extract32(opc, 1, 1);
2733     }
2734
2735     tcg_rt = cpu_reg(s, rt);
2736
2737     clean_addr = tcg_const_i64((s->pc - 4) + imm);
2738     if (is_vector) {
2739         do_fp_ld(s, rt, clean_addr, size);
2740     } else {
2741         /* Only unsigned 32bit loads target 32bit registers.  */
2742         bool iss_sf = opc != 0;
2743
2744         do_gpr_ld(s, tcg_rt, clean_addr, size, is_signed, false,
2745                   true, rt, iss_sf, false);
2746     }
2747     tcg_temp_free_i64(clean_addr);
2748 }
2749
2750 /*
2751  * LDNP (Load Pair - non-temporal hint)
2752  * LDP (Load Pair - non vector)
2753  * LDPSW (Load Pair Signed Word - non vector)
2754  * STNP (Store Pair - non-temporal hint)
2755  * STP (Store Pair - non vector)
2756  * LDNP (Load Pair of SIMD&FP - non-temporal hint)
2757  * LDP (Load Pair of SIMD&FP)
2758  * STNP (Store Pair of SIMD&FP - non-temporal hint)
2759  * STP (Store Pair of SIMD&FP)
2760  *
2761  *  31 30 29   27  26  25 24   23  22 21   15 14   10 9    5 4    0
2762  * +-----+-------+---+---+-------+---+-----------------------------+
2763  * | opc | 1 0 1 | V | 0 | index | L |  imm7 |  Rt2  |  Rn  | Rt   |
2764  * +-----+-------+---+---+-------+---+-------+-------+------+------+
2765  *
2766  * opc: LDP/STP/LDNP/STNP        00 -> 32 bit, 10 -> 64 bit
2767  *      LDPSW                    01
2768  *      LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
2769  *   V: 0 -> GPR, 1 -> Vector
2770  * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
2771  *      10 -> signed offset, 11 -> pre-index
2772  *   L: 0 -> Store 1 -> Load
2773  *
2774  * Rt, Rt2 = GPR or SIMD registers to be stored
2775  * Rn = general purpose register containing address
2776  * imm7 = signed offset (multiple of 4 or 8 depending on size)
2777  */
2778 static void disas_ldst_pair(DisasContext *s, uint32_t insn)
2779 {
2780     int rt = extract32(insn, 0, 5);
2781     int rn = extract32(insn, 5, 5);
2782     int rt2 = extract32(insn, 10, 5);
2783     uint64_t offset = sextract64(insn, 15, 7);
2784     int index = extract32(insn, 23, 2);
2785     bool is_vector = extract32(insn, 26, 1);
2786     bool is_load = extract32(insn, 22, 1);
2787     int opc = extract32(insn, 30, 2);
2788
2789     bool is_signed = false;
2790     bool postindex = false;
2791     bool wback = false;
2792
2793     TCGv_i64 clean_addr, dirty_addr;
2794
2795     int size;
2796
2797     if (opc == 3) {
2798         unallocated_encoding(s);
2799         return;
2800     }
2801
2802     if (is_vector) {
2803         size = 2 + opc;
2804     } else {
2805         size = 2 + extract32(opc, 1, 1);
2806         is_signed = extract32(opc, 0, 1);
2807         if (!is_load && is_signed) {
2808             unallocated_encoding(s);
2809             return;
2810         }
2811     }
2812
2813     switch (index) {
2814     case 1: /* post-index */
2815         postindex = true;
2816         wback = true;
2817         break;
2818     case 0:
2819         /* signed offset with "non-temporal" hint. Since we don't emulate
2820          * caches we don't care about hints to the cache system about
2821          * data access patterns, and handle this identically to plain
2822          * signed offset.
2823          */
2824         if (is_signed) {
2825             /* There is no non-temporal-hint version of LDPSW */
2826             unallocated_encoding(s);
2827             return;
2828         }
2829         postindex = false;
2830         break;
2831     case 2: /* signed offset, rn not updated */
2832         postindex = false;
2833         break;
2834     case 3: /* pre-index */
2835         postindex = false;
2836         wback = true;
2837         break;
2838     }
2839
2840     if (is_vector && !fp_access_check(s)) {
2841         return;
2842     }
2843
2844     offset <<= size;
2845
2846     if (rn == 31) {
2847         gen_check_sp_alignment(s);
2848     }
2849
2850     dirty_addr = read_cpu_reg_sp(s, rn, 1);
2851     if (!postindex) {
2852         tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
2853     }
2854     clean_addr = clean_data_tbi(s, dirty_addr);
2855
2856     if (is_vector) {
2857         if (is_load) {
2858             do_fp_ld(s, rt, clean_addr, size);
2859         } else {
2860             do_fp_st(s, rt, clean_addr, size);
2861         }
2862         tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
2863         if (is_load) {
2864             do_fp_ld(s, rt2, clean_addr, size);
2865         } else {
2866             do_fp_st(s, rt2, clean_addr, size);
2867         }
2868     } else {
2869         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2870         TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
2871
2872         if (is_load) {
2873             TCGv_i64 tmp = tcg_temp_new_i64();
2874
2875             /* Do not modify tcg_rt before recognizing any exception
2876              * from the second load.
2877              */
2878             do_gpr_ld(s, tmp, clean_addr, size, is_signed, false,
2879                       false, 0, false, false);
2880             tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
2881             do_gpr_ld(s, tcg_rt2, clean_addr, size, is_signed, false,
2882                       false, 0, false, false);
2883
2884             tcg_gen_mov_i64(tcg_rt, tmp);
2885             tcg_temp_free_i64(tmp);
2886         } else {
2887             do_gpr_st(s, tcg_rt, clean_addr, size,
2888                       false, 0, false, false);
2889             tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
2890             do_gpr_st(s, tcg_rt2, clean_addr, size,
2891                       false, 0, false, false);
2892         }
2893     }
2894
2895     if (wback) {
2896         if (postindex) {
2897             tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
2898         }
2899         tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
2900     }
2901 }
2902
2903 /*
2904  * Load/store (immediate post-indexed)
2905  * Load/store (immediate pre-indexed)
2906  * Load/store (unscaled immediate)
2907  *
2908  * 31 30 29   27  26 25 24 23 22 21  20    12 11 10 9    5 4    0
2909  * +----+-------+---+-----+-----+---+--------+-----+------+------+
2910  * |size| 1 1 1 | V | 0 0 | opc | 0 |  imm9  | idx |  Rn  |  Rt  |
2911  * +----+-------+---+-----+-----+---+--------+-----+------+------+
2912  *
2913  * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
2914          10 -> unprivileged
2915  * V = 0 -> non-vector
2916  * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
2917  * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2918  */
2919 static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
2920                                 int opc,
2921                                 int size,
2922                                 int rt,
2923                                 bool is_vector)
2924 {
2925     int rn = extract32(insn, 5, 5);
2926     int imm9 = sextract32(insn, 12, 9);
2927     int idx = extract32(insn, 10, 2);
2928     bool is_signed = false;
2929     bool is_store = false;
2930     bool is_extended = false;
2931     bool is_unpriv = (idx == 2);
2932     bool iss_valid = !is_vector;
2933     bool post_index;
2934     bool writeback;
2935
2936     TCGv_i64 clean_addr, dirty_addr;
2937
2938     if (is_vector) {
2939         size |= (opc & 2) << 1;
2940         if (size > 4 || is_unpriv) {
2941             unallocated_encoding(s);
2942             return;
2943         }
2944         is_store = ((opc & 1) == 0);
2945         if (!fp_access_check(s)) {
2946             return;
2947         }
2948     } else {
2949         if (size == 3 && opc == 2) {
2950             /* PRFM - prefetch */
2951             if (idx != 0) {
2952                 unallocated_encoding(s);
2953                 return;
2954             }
2955             return;
2956         }
2957         if (opc == 3 && size > 1) {
2958             unallocated_encoding(s);
2959             return;
2960         }
2961         is_store = (opc == 0);
2962         is_signed = extract32(opc, 1, 1);
2963         is_extended = (size < 3) && extract32(opc, 0, 1);
2964     }
2965
2966     switch (idx) {
2967     case 0:
2968     case 2:
2969         post_index = false;
2970         writeback = false;
2971         break;
2972     case 1:
2973         post_index = true;
2974         writeback = true;
2975         break;
2976     case 3:
2977         post_index = false;
2978         writeback = true;
2979         break;
2980     default:
2981         g_assert_not_reached();
2982     }
2983
2984     if (rn == 31) {
2985         gen_check_sp_alignment(s);
2986     }
2987
2988     dirty_addr = read_cpu_reg_sp(s, rn, 1);
2989     if (!post_index) {
2990         tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
2991     }
2992     clean_addr = clean_data_tbi(s, dirty_addr);
2993
2994     if (is_vector) {
2995         if (is_store) {
2996             do_fp_st(s, rt, clean_addr, size);
2997         } else {
2998             do_fp_ld(s, rt, clean_addr, size);
2999         }
3000     } else {
3001         TCGv_i64 tcg_rt = cpu_reg(s, rt);
3002         int memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
3003         bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
3004
3005         if (is_store) {
3006             do_gpr_st_memidx(s, tcg_rt, clean_addr, size, memidx,
3007                              iss_valid, rt, iss_sf, false);
3008         } else {
3009             do_gpr_ld_memidx(s, tcg_rt, clean_addr, size,
3010                              is_signed, is_extended, memidx,
3011                              iss_valid, rt, iss_sf, false);
3012         }
3013     }
3014
3015     if (writeback) {
3016         TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
3017         if (post_index) {
3018             tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
3019         }
3020         tcg_gen_mov_i64(tcg_rn, dirty_addr);
3021     }
3022 }
3023
3024 /*
3025  * Load/store (register offset)
3026  *
3027  * 31 30 29   27  26 25 24 23 22 21  20  16 15 13 12 11 10 9  5 4  0
3028  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
3029  * |size| 1 1 1 | V | 0 0 | opc | 1 |  Rm  | opt | S| 1 0 | Rn | Rt |
3030  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
3031  *
3032  * For non-vector:
3033  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
3034  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
3035  * For vector:
3036  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
3037  *   opc<0>: 0 -> store, 1 -> load
3038  * V: 1 -> vector/simd
3039  * opt: extend encoding (see DecodeRegExtend)
3040  * S: if S=1 then scale (essentially index by sizeof(size))
3041  * Rt: register to transfer into/out of
3042  * Rn: address register or SP for base
3043  * Rm: offset register or ZR for offset
3044  */
3045 static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
3046                                    int opc,
3047                                    int size,
3048                                    int rt,
3049                                    bool is_vector)
3050 {
3051     int rn = extract32(insn, 5, 5);
3052     int shift = extract32(insn, 12, 1);
3053     int rm = extract32(insn, 16, 5);
3054     int opt = extract32(insn, 13, 3);
3055     bool is_signed = false;
3056     bool is_store = false;
3057     bool is_extended = false;
3058
3059     TCGv_i64 tcg_rm, clean_addr, dirty_addr;
3060
3061     if (extract32(opt, 1, 1) == 0) {
3062         unallocated_encoding(s);
3063         return;
3064     }
3065
3066     if (is_vector) {
3067         size |= (opc & 2) << 1;
3068         if (size > 4) {
3069             unallocated_encoding(s);
3070             return;
3071         }
3072         is_store = !extract32(opc, 0, 1);
3073         if (!fp_access_check(s)) {
3074             return;
3075         }
3076     } else {
3077         if (size == 3 && opc == 2) {
3078             /* PRFM - prefetch */
3079             return;
3080         }
3081         if (opc == 3 && size > 1) {
3082             unallocated_encoding(s);
3083             return;
3084         }
3085         is_store = (opc == 0);
3086         is_signed = extract32(opc, 1, 1);
3087         is_extended = (size < 3) && extract32(opc, 0, 1);
3088     }
3089
3090     if (rn == 31) {
3091         gen_check_sp_alignment(s);
3092     }
3093     dirty_addr = read_cpu_reg_sp(s, rn, 1);
3094
3095     tcg_rm = read_cpu_reg(s, rm, 1);
3096     ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
3097
3098     tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
3099     clean_addr = clean_data_tbi(s, dirty_addr);
3100
3101     if (is_vector) {
3102         if (is_store) {
3103             do_fp_st(s, rt, clean_addr, size);
3104         } else {
3105             do_fp_ld(s, rt, clean_addr, size);
3106         }
3107     } else {
3108         TCGv_i64 tcg_rt = cpu_reg(s, rt);
3109         bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
3110         if (is_store) {
3111             do_gpr_st(s, tcg_rt, clean_addr, size,
3112                       true, rt, iss_sf, false);
3113         } else {
3114             do_gpr_ld(s, tcg_rt, clean_addr, size,
3115                       is_signed, is_extended,
3116                       true, rt, iss_sf, false);
3117         }
3118     }
3119 }
3120
3121 /*
3122  * Load/store (unsigned immediate)
3123  *
3124  * 31 30 29   27  26 25 24 23 22 21        10 9     5
3125  * +----+-------+---+-----+-----+------------+-------+------+
3126  * |size| 1 1 1 | V | 0 1 | opc |   imm12    |  Rn   |  Rt  |
3127  * +----+-------+---+-----+-----+------------+-------+------+
3128  *
3129  * For non-vector:
3130  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
3131  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
3132  * For vector:
3133  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
3134  *   opc<0>: 0 -> store, 1 -> load
3135  * Rn: base address register (inc SP)
3136  * Rt: target register
3137  */
3138 static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
3139                                         int opc,
3140                                         int size,
3141                                         int rt,
3142                                         bool is_vector)
3143 {
3144     int rn = extract32(insn, 5, 5);
3145     unsigned int imm12 = extract32(insn, 10, 12);
3146     unsigned int offset;
3147
3148     TCGv_i64 clean_addr, dirty_addr;
3149
3150     bool is_store;
3151     bool is_signed = false;
3152     bool is_extended = false;
3153
3154     if (is_vector) {
3155         size |= (opc & 2) << 1;
3156         if (size > 4) {
3157             unallocated_encoding(s);
3158             return;
3159         }
3160         is_store = !extract32(opc, 0, 1);
3161         if (!fp_access_check(s)) {
3162             return;
3163         }
3164     } else {
3165         if (size == 3 && opc == 2) {
3166             /* PRFM - prefetch */
3167             return;
3168         }
3169         if (opc == 3 && size > 1) {
3170             unallocated_encoding(s);
3171             return;
3172         }
3173         is_store = (opc == 0);
3174         is_signed = extract32(opc, 1, 1);
3175         is_extended = (size < 3) && extract32(opc, 0, 1);
3176     }
3177
3178     if (rn == 31) {
3179         gen_check_sp_alignment(s);
3180     }
3181     dirty_addr = read_cpu_reg_sp(s, rn, 1);
3182     offset = imm12 << size;
3183     tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
3184     clean_addr = clean_data_tbi(s, dirty_addr);
3185
3186     if (is_vector) {
3187         if (is_store) {
3188             do_fp_st(s, rt, clean_addr, size);
3189         } else {
3190             do_fp_ld(s, rt, clean_addr, size);
3191         }
3192     } else {
3193         TCGv_i64 tcg_rt = cpu_reg(s, rt);
3194         bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
3195         if (is_store) {
3196             do_gpr_st(s, tcg_rt, clean_addr, size,
3197                       true, rt, iss_sf, false);
3198         } else {
3199             do_gpr_ld(s, tcg_rt, clean_addr, size, is_signed, is_extended,
3200                       true, rt, iss_sf, false);
3201         }
3202     }
3203 }
3204
3205 /* Atomic memory operations
3206  *
3207  *  31  30      27  26    24    22  21   16   15    12    10    5     0
3208  * +------+-------+---+-----+-----+---+----+----+-----+-----+----+-----+
3209  * | size | 1 1 1 | V | 0 0 | A R | 1 | Rs | o3 | opc | 0 0 | Rn |  Rt |
3210  * +------+-------+---+-----+-----+--------+----+-----+-----+----+-----+
3211  *
3212  * Rt: the result register
3213  * Rn: base address or SP
3214  * Rs: the source register for the operation
3215  * V: vector flag (always 0 as of v8.3)
3216  * A: acquire flag
3217  * R: release flag
3218  */
3219 static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
3220                               int size, int rt, bool is_vector)
3221 {
3222     int rs = extract32(insn, 16, 5);
3223     int rn = extract32(insn, 5, 5);
3224     int o3_opc = extract32(insn, 12, 4);
3225     TCGv_i64 tcg_rs, clean_addr;
3226     AtomicThreeOpFn *fn;
3227
3228     if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
3229         unallocated_encoding(s);
3230         return;
3231     }
3232     switch (o3_opc) {
3233     case 000: /* LDADD */
3234         fn = tcg_gen_atomic_fetch_add_i64;
3235         break;
3236     case 001: /* LDCLR */
3237         fn = tcg_gen_atomic_fetch_and_i64;
3238         break;
3239     case 002: /* LDEOR */
3240         fn = tcg_gen_atomic_fetch_xor_i64;
3241         break;
3242     case 003: /* LDSET */
3243         fn = tcg_gen_atomic_fetch_or_i64;
3244         break;
3245     case 004: /* LDSMAX */
3246         fn = tcg_gen_atomic_fetch_smax_i64;
3247         break;
3248     case 005: /* LDSMIN */
3249         fn = tcg_gen_atomic_fetch_smin_i64;
3250         break;
3251     case 006: /* LDUMAX */
3252         fn = tcg_gen_atomic_fetch_umax_i64;
3253         break;
3254     case 007: /* LDUMIN */
3255         fn = tcg_gen_atomic_fetch_umin_i64;
3256         break;
3257     case 010: /* SWP */
3258         fn = tcg_gen_atomic_xchg_i64;
3259         break;
3260     default:
3261         unallocated_encoding(s);
3262         return;
3263     }
3264
3265     if (rn == 31) {
3266         gen_check_sp_alignment(s);
3267     }
3268     clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
3269     tcg_rs = read_cpu_reg(s, rs, true);
3270
3271     if (o3_opc == 1) { /* LDCLR */
3272         tcg_gen_not_i64(tcg_rs, tcg_rs);
3273     }
3274
3275     /* The tcg atomic primitives are all full barriers.  Therefore we
3276      * can ignore the Acquire and Release bits of this instruction.
3277      */
3278     fn(cpu_reg(s, rt), clean_addr, tcg_rs, get_mem_index(s),
3279        s->be_data | size | MO_ALIGN);
3280 }
3281
3282 /*
3283  * PAC memory operations
3284  *
3285  *  31  30      27  26    24    22  21       12  11  10    5     0
3286  * +------+-------+---+-----+-----+---+--------+---+---+----+-----+
3287  * | size | 1 1 1 | V | 0 0 | M S | 1 |  imm9  | W | 1 | Rn |  Rt |
3288  * +------+-------+---+-----+-----+---+--------+---+---+----+-----+
3289  *
3290  * Rt: the result register
3291  * Rn: base address or SP
3292  * V: vector flag (always 0 as of v8.3)
3293  * M: clear for key DA, set for key DB
3294  * W: pre-indexing flag
3295  * S: sign for imm9.
3296  */
3297 static void disas_ldst_pac(DisasContext *s, uint32_t insn,
3298                            int size, int rt, bool is_vector)
3299 {
3300     int rn = extract32(insn, 5, 5);
3301     bool is_wback = extract32(insn, 11, 1);
3302     bool use_key_a = !extract32(insn, 23, 1);
3303     int offset;
3304     TCGv_i64 clean_addr, dirty_addr, tcg_rt;
3305
3306     if (size != 3 || is_vector || !dc_isar_feature(aa64_pauth, s)) {
3307         unallocated_encoding(s);
3308         return;
3309     }
3310
3311     if (rn == 31) {
3312         gen_check_sp_alignment(s);
3313     }
3314     dirty_addr = read_cpu_reg_sp(s, rn, 1);
3315
3316     if (s->pauth_active) {
3317         if (use_key_a) {
3318             gen_helper_autda(dirty_addr, cpu_env, dirty_addr, cpu_X[31]);
3319         } else {
3320             gen_helper_autdb(dirty_addr, cpu_env, dirty_addr, cpu_X[31]);
3321         }
3322     }
3323
3324     /* Form the 10-bit signed, scaled offset.  */
3325     offset = (extract32(insn, 22, 1) << 9) | extract32(insn, 12, 9);
3326     offset = sextract32(offset << size, 0, 10 + size);
3327     tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
3328
3329     /* Note that "clean" and "dirty" here refer to TBI not PAC.  */
3330     clean_addr = clean_data_tbi(s, dirty_addr);
3331
3332     tcg_rt = cpu_reg(s, rt);
3333     do_gpr_ld(s, tcg_rt, clean_addr, size, /* is_signed */ false,
3334               /* extend */ false, /* iss_valid */ !is_wback,
3335               /* iss_srt */ rt, /* iss_sf */ true, /* iss_ar */ false);
3336
3337     if (is_wback) {
3338         tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
3339     }
3340 }
3341
3342 /* Load/store register (all forms) */
3343 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
3344 {
3345     int rt = extract32(insn, 0, 5);
3346     int opc = extract32(insn, 22, 2);
3347     bool is_vector = extract32(insn, 26, 1);
3348     int size = extract32(insn, 30, 2);
3349
3350     switch (extract32(insn, 24, 2)) {
3351     case 0:
3352         if (extract32(insn, 21, 1) == 0) {
3353             /* Load/store register (unscaled immediate)
3354              * Load/store immediate pre/post-indexed
3355              * Load/store register unprivileged
3356              */
3357             disas_ldst_reg_imm9(s, insn, opc, size, rt, is_vector);
3358             return;
3359         }
3360         switch (extract32(insn, 10, 2)) {
3361         case 0:
3362             disas_ldst_atomic(s, insn, size, rt, is_vector);
3363             return;
3364         case 2:
3365             disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector);
3366             return;
3367         default:
3368             disas_ldst_pac(s, insn, size, rt, is_vector);
3369             return;
3370         }
3371         break;
3372     case 1:
3373         disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector);
3374         return;
3375     }
3376     unallocated_encoding(s);
3377 }
3378
3379 /* AdvSIMD load/store multiple structures
3380  *
3381  *  31  30  29           23 22  21         16 15    12 11  10 9    5 4    0
3382  * +---+---+---------------+---+-------------+--------+------+------+------+
3383  * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size |  Rn  |  Rt  |
3384  * +---+---+---------------+---+-------------+--------+------+------+------+
3385  *
3386  * AdvSIMD load/store multiple structures (post-indexed)
3387  *
3388  *  31  30  29           23 22  21  20     16 15    12 11  10 9    5 4    0
3389  * +---+---+---------------+---+---+---------+--------+------+------+------+
3390  * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 |   Rm    | opcode | size |  Rn  |  Rt  |
3391  * +---+---+---------------+---+---+---------+--------+------+------+------+
3392  *
3393  * Rt: first (or only) SIMD&FP register to be transferred
3394  * Rn: base address or SP
3395  * Rm (post-index only): post-index register (when !31) or size dependent #imm
3396  */
3397 static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
3398 {
3399     int rt = extract32(insn, 0, 5);
3400     int rn = extract32(insn, 5, 5);
3401     int rm = extract32(insn, 16, 5);
3402     int size = extract32(insn, 10, 2);
3403     int opcode = extract32(insn, 12, 4);
3404     bool is_store = !extract32(insn, 22, 1);
3405     bool is_postidx = extract32(insn, 23, 1);
3406     bool is_q = extract32(insn, 30, 1);
3407     TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
3408     TCGMemOp endian = s->be_data;
3409
3410     int ebytes;   /* bytes per element */
3411     int elements; /* elements per vector */
3412     int rpt;    /* num iterations */
3413     int selem;  /* structure elements */
3414     int r;
3415
3416     if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
3417         unallocated_encoding(s);
3418         return;
3419     }
3420
3421     if (!is_postidx && rm != 0) {
3422         unallocated_encoding(s);
3423         return;
3424     }
3425
3426     /* From the shared decode logic */
3427     switch (opcode) {
3428     case 0x0:
3429         rpt = 1;
3430         selem = 4;
3431         break;
3432     case 0x2:
3433         rpt = 4;
3434         selem = 1;
3435         break;
3436     case 0x4:
3437         rpt = 1;
3438         selem = 3;
3439         break;
3440     case 0x6:
3441         rpt = 3;
3442         selem = 1;
3443         break;
3444     case 0x7:
3445         rpt = 1;
3446         selem = 1;
3447         break;
3448     case 0x8:
3449         rpt = 1;
3450         selem = 2;
3451         break;
3452     case 0xa:
3453         rpt = 2;
3454         selem = 1;
3455         break;
3456     default:
3457         unallocated_encoding(s);
3458         return;
3459     }
3460
3461     if (size == 3 && !is_q && selem != 1) {
3462         /* reserved */
3463         unallocated_encoding(s);
3464         return;
3465     }
3466
3467     if (!fp_access_check(s)) {
3468         return;
3469     }
3470
3471     if (rn == 31) {
3472         gen_check_sp_alignment(s);
3473     }
3474
3475     /* For our purposes, bytes are always little-endian.  */
3476     if (size == 0) {
3477         endian = MO_LE;
3478     }
3479
3480     /* Consecutive little-endian elements from a single register
3481      * can be promoted to a larger little-endian operation.
3482      */
3483     if (selem == 1 && endian == MO_LE) {
3484         size = 3;
3485     }
3486     ebytes = 1 << size;
3487     elements = (is_q ? 16 : 8) / ebytes;
3488
3489     tcg_rn = cpu_reg_sp(s, rn);
3490     clean_addr = clean_data_tbi(s, tcg_rn);
3491     tcg_ebytes = tcg_const_i64(ebytes);
3492
3493     for (r = 0; r < rpt; r++) {
3494         int e;
3495         for (e = 0; e < elements; e++) {
3496             int xs;
3497             for (xs = 0; xs < selem; xs++) {
3498                 int tt = (rt + r + xs) % 32;
3499                 if (is_store) {
3500                     do_vec_st(s, tt, e, clean_addr, size, endian);
3501                 } else {
3502                     do_vec_ld(s, tt, e, clean_addr, size, endian);
3503                 }
3504                 tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
3505             }
3506         }
3507     }
3508     tcg_temp_free_i64(tcg_ebytes);
3509
3510     if (!is_store) {
3511         /* For non-quad operations, setting a slice of the low
3512          * 64 bits of the register clears the high 64 bits (in
3513          * the ARM ARM pseudocode this is implicit in the fact
3514          * that 'rval' is a 64 bit wide variable).
3515          * For quad operations, we might still need to zero the
3516          * high bits of SVE.
3517          */
3518         for (r = 0; r < rpt * selem; r++) {
3519             int tt = (rt + r) % 32;
3520             clear_vec_high(s, is_q, tt);
3521         }
3522     }
3523
3524     if (is_postidx) {
3525         if (rm == 31) {
3526             tcg_gen_addi_i64(tcg_rn, tcg_rn, rpt * elements * selem * ebytes);
3527         } else {
3528             tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
3529         }
3530     }
3531 }
3532
3533 /* AdvSIMD load/store single structure
3534  *
3535  *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
3536  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3537  * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size |  Rn  |  Rt  |
3538  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3539  *
3540  * AdvSIMD load/store single structure (post-indexed)
3541  *
3542  *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
3543  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3544  * | 0 | Q | 0 0 1 1 0 1 1 | L R |     Rm    | opc | S | size |  Rn  |  Rt  |
3545  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3546  *
3547  * Rt: first (or only) SIMD&FP register to be transferred
3548  * Rn: base address or SP
3549  * Rm (post-index only): post-index register (when !31) or size dependent #imm
3550  * index = encoded in Q:S:size dependent on size
3551  *
3552  * lane_size = encoded in R, opc
3553  * transfer width = encoded in opc, S, size
3554  */
3555 static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
3556 {
3557     int rt = extract32(insn, 0, 5);
3558     int rn = extract32(insn, 5, 5);
3559     int rm = extract32(insn, 16, 5);
3560     int size = extract32(insn, 10, 2);
3561     int S = extract32(insn, 12, 1);
3562     int opc = extract32(insn, 13, 3);
3563     int R = extract32(insn, 21, 1);
3564     int is_load = extract32(insn, 22, 1);
3565     int is_postidx = extract32(insn, 23, 1);
3566     int is_q = extract32(insn, 30, 1);
3567
3568     int scale = extract32(opc, 1, 2);
3569     int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
3570     bool replicate = false;
3571     int index = is_q << 3 | S << 2 | size;
3572     int ebytes, xs;
3573     TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
3574
3575     if (extract32(insn, 31, 1)) {
3576         unallocated_encoding(s);
3577         return;
3578     }
3579     if (!is_postidx && rm != 0) {
3580         unallocated_encoding(s);
3581         return;
3582     }
3583
3584     switch (scale) {
3585     case 3:
3586         if (!is_load || S) {
3587             unallocated_encoding(s);
3588             return;
3589         }
3590         scale = size;
3591         replicate = true;
3592         break;
3593     case 0:
3594         break;
3595     case 1:
3596         if (extract32(size, 0, 1)) {
3597             unallocated_encoding(s);
3598             return;
3599         }
3600         index >>= 1;
3601         break;
3602     case 2:
3603         if (extract32(size, 1, 1)) {
3604             unallocated_encoding(s);
3605             return;
3606         }
3607         if (!extract32(size, 0, 1)) {
3608             index >>= 2;
3609         } else {
3610             if (S) {
3611                 unallocated_encoding(s);
3612                 return;
3613             }
3614             index >>= 3;
3615             scale = 3;
3616         }
3617         break;
3618     default:
3619         g_assert_not_reached();
3620     }
3621
3622     if (!fp_access_check(s)) {
3623         return;
3624     }
3625
3626     ebytes = 1 << scale;
3627
3628     if (rn == 31) {
3629         gen_check_sp_alignment(s);
3630     }
3631
3632     tcg_rn = cpu_reg_sp(s, rn);
3633     clean_addr = clean_data_tbi(s, tcg_rn);
3634     tcg_ebytes = tcg_const_i64(ebytes);
3635
3636     for (xs = 0; xs < selem; xs++) {
3637         if (replicate) {
3638             /* Load and replicate to all elements */
3639             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3640
3641             tcg_gen_qemu_ld_i64(tcg_tmp, clean_addr,
3642                                 get_mem_index(s), s->be_data + scale);
3643             tcg_gen_gvec_dup_i64(scale, vec_full_reg_offset(s, rt),
3644                                  (is_q + 1) * 8, vec_full_reg_size(s),
3645                                  tcg_tmp);
3646             tcg_temp_free_i64(tcg_tmp);
3647         } else {
3648             /* Load/store one element per register */
3649             if (is_load) {
3650                 do_vec_ld(s, rt, index, clean_addr, scale, s->be_data);
3651             } else {
3652                 do_vec_st(s, rt, index, clean_addr, scale, s->be_data);
3653             }
3654         }
3655         tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
3656         rt = (rt + 1) % 32;
3657     }
3658     tcg_temp_free_i64(tcg_ebytes);
3659
3660     if (is_postidx) {
3661         if (rm == 31) {
3662             tcg_gen_addi_i64(tcg_rn, tcg_rn, selem * ebytes);
3663         } else {
3664             tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
3665         }
3666     }
3667 }
3668
3669 /* Loads and stores */
3670 static void disas_ldst(DisasContext *s, uint32_t insn)
3671 {
3672     switch (extract32(insn, 24, 6)) {
3673     case 0x08: /* Load/store exclusive */
3674         disas_ldst_excl(s, insn);
3675         break;
3676     case 0x18: case 0x1c: /* Load register (literal) */
3677         disas_ld_lit(s, insn);
3678         break;
3679     case 0x28: case 0x29:
3680     case 0x2c: case 0x2d: /* Load/store pair (all forms) */
3681         disas_ldst_pair(s, insn);
3682         break;
3683     case 0x38: case 0x39:
3684     case 0x3c: case 0x3d: /* Load/store register (all forms) */
3685         disas_ldst_reg(s, insn);
3686         break;
3687     case 0x0c: /* AdvSIMD load/store multiple structures */
3688         disas_ldst_multiple_struct(s, insn);
3689         break;
3690     case 0x0d: /* AdvSIMD load/store single structure */
3691         disas_ldst_single_struct(s, insn);
3692         break;
3693     default:
3694         unallocated_encoding(s);
3695         break;
3696     }
3697 }
3698
3699 /* PC-rel. addressing
3700  *   31  30   29 28       24 23                5 4    0
3701  * +----+-------+-----------+-------------------+------+
3702  * | op | immlo | 1 0 0 0 0 |       immhi       |  Rd  |
3703  * +----+-------+-----------+-------------------+------+
3704  */
3705 static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
3706 {
3707     unsigned int page, rd;
3708     uint64_t base;
3709     uint64_t offset;
3710
3711     page = extract32(insn, 31, 1);
3712     /* SignExtend(immhi:immlo) -> offset */
3713     offset = sextract64(insn, 5, 19);
3714     offset = offset << 2 | extract32(insn, 29, 2);
3715     rd = extract32(insn, 0, 5);
3716     base = s->pc - 4;
3717
3718     if (page) {
3719         /* ADRP (page based) */
3720         base &= ~0xfff;
3721         offset <<= 12;
3722     }
3723
3724     tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
3725 }
3726
3727 /*
3728  * Add/subtract (immediate)
3729  *
3730  *  31 30 29 28       24 23 22 21         10 9   5 4   0
3731  * +--+--+--+-----------+-----+-------------+-----+-----+
3732  * |sf|op| S| 1 0 0 0 1 |shift|    imm12    |  Rn | Rd  |
3733  * +--+--+--+-----------+-----+-------------+-----+-----+
3734  *
3735  *    sf: 0 -> 32bit, 1 -> 64bit
3736  *    op: 0 -> add  , 1 -> sub
3737  *     S: 1 -> set flags
3738  * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
3739  */
3740 static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
3741 {
3742     int rd = extract32(insn, 0, 5);
3743     int rn = extract32(insn, 5, 5);
3744     uint64_t imm = extract32(insn, 10, 12);
3745     int shift = extract32(insn, 22, 2);
3746     bool setflags = extract32(insn, 29, 1);
3747     bool sub_op = extract32(insn, 30, 1);
3748     bool is_64bit = extract32(insn, 31, 1);
3749
3750     TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
3751     TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
3752     TCGv_i64 tcg_result;
3753
3754     switch (shift) {
3755     case 0x0:
3756         break;
3757     case 0x1:
3758         imm <<= 12;
3759         break;
3760     default:
3761         unallocated_encoding(s);
3762         return;
3763     }
3764
3765     tcg_result = tcg_temp_new_i64();
3766     if (!setflags) {
3767         if (sub_op) {
3768             tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
3769         } else {
3770             tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
3771         }
3772     } else {
3773         TCGv_i64 tcg_imm = tcg_const_i64(imm);
3774         if (sub_op) {
3775             gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
3776         } else {
3777             gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
3778         }
3779         tcg_temp_free_i64(tcg_imm);
3780     }
3781
3782     if (is_64bit) {
3783         tcg_gen_mov_i64(tcg_rd, tcg_result);
3784     } else {
3785         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
3786     }
3787
3788     tcg_temp_free_i64(tcg_result);
3789 }
3790
3791 /* The input should be a value in the bottom e bits (with higher
3792  * bits zero); returns that value replicated into every element
3793  * of size e in a 64 bit integer.
3794  */
3795 static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
3796 {
3797     assert(e != 0);
3798     while (e < 64) {
3799         mask |= mask << e;
3800         e *= 2;
3801     }
3802     return mask;
3803 }
3804
3805 /* Return a value with the bottom len bits set (where 0 < len <= 64) */
3806 static inline uint64_t bitmask64(unsigned int length)
3807 {
3808     assert(length > 0 && length <= 64);
3809     return ~0ULL >> (64 - length);
3810 }
3811
3812 /* Simplified variant of pseudocode DecodeBitMasks() for the case where we
3813  * only require the wmask. Returns false if the imms/immr/immn are a reserved
3814  * value (ie should cause a guest UNDEF exception), and true if they are
3815  * valid, in which case the decoded bit pattern is written to result.
3816  */
3817 bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
3818                             unsigned int imms, unsigned int immr)
3819 {
3820     uint64_t mask;
3821     unsigned e, levels, s, r;
3822     int len;
3823
3824     assert(immn < 2 && imms < 64 && immr < 64);
3825
3826     /* The bit patterns we create here are 64 bit patterns which
3827      * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
3828      * 64 bits each. Each element contains the same value: a run
3829      * of between 1 and e-1 non-zero bits, rotated within the
3830      * element by between 0 and e-1 bits.
3831      *
3832      * The element size and run length are encoded into immn (1 bit)
3833      * and imms (6 bits) as follows:
3834      * 64 bit elements: immn = 1, imms = <length of run - 1>
3835      * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
3836      * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
3837      *  8 bit elements: immn = 0, imms = 110 : <length of run - 1>
3838      *  4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
3839      *  2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
3840      * Notice that immn = 0, imms = 11111x is the only combination
3841      * not covered by one of the above options; this is reserved.
3842      * Further, <length of run - 1> all-ones is a reserved pattern.
3843      *
3844      * In all cases the rotation is by immr % e (and immr is 6 bits).
3845      */
3846
3847     /* First determine the element size */
3848     len = 31 - clz32((immn << 6) | (~imms & 0x3f));
3849     if (len < 1) {
3850         /* This is the immn == 0, imms == 0x11111x case */
3851         return false;
3852     }
3853     e = 1 << len;
3854
3855     levels = e - 1;
3856     s = imms & levels;
3857     r = immr & levels;
3858
3859     if (s == levels) {
3860         /* <length of run - 1> mustn't be all-ones. */
3861         return false;
3862     }
3863
3864     /* Create the value of one element: s+1 set bits rotated
3865      * by r within the element (which is e bits wide)...
3866      */
3867     mask = bitmask64(s + 1);
3868     if (r) {
3869         mask = (mask >> r) | (mask << (e - r));
3870         mask &= bitmask64(e);
3871     }
3872     /* ...then replicate the element over the whole 64 bit value */
3873     mask = bitfield_replicate(mask, e);
3874     *result = mask;
3875     return true;
3876 }
3877
3878 /* Logical (immediate)
3879  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
3880  * +----+-----+-------------+---+------+------+------+------+
3881  * | sf | opc | 1 0 0 1 0 0 | N | immr | imms |  Rn  |  Rd  |
3882  * +----+-----+-------------+---+------+------+------+------+
3883  */
3884 static void disas_logic_imm(DisasContext *s, uint32_t insn)
3885 {
3886     unsigned int sf, opc, is_n, immr, imms, rn, rd;
3887     TCGv_i64 tcg_rd, tcg_rn;
3888     uint64_t wmask;
3889     bool is_and = false;
3890
3891     sf = extract32(insn, 31, 1);
3892     opc = extract32(insn, 29, 2);
3893     is_n = extract32(insn, 22, 1);
3894     immr = extract32(insn, 16, 6);
3895     imms = extract32(insn, 10, 6);
3896     rn = extract32(insn, 5, 5);
3897     rd = extract32(insn, 0, 5);
3898
3899     if (!sf && is_n) {
3900         unallocated_encoding(s);
3901         return;
3902     }
3903
3904     if (opc == 0x3) { /* ANDS */
3905         tcg_rd = cpu_reg(s, rd);
3906     } else {
3907         tcg_rd = cpu_reg_sp(s, rd);
3908     }
3909     tcg_rn = cpu_reg(s, rn);
3910
3911     if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
3912         /* some immediate field values are reserved */
3913         unallocated_encoding(s);
3914         return;
3915     }
3916
3917     if (!sf) {
3918         wmask &= 0xffffffff;
3919     }
3920
3921     switch (opc) {
3922     case 0x3: /* ANDS */
3923     case 0x0: /* AND */
3924         tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
3925         is_and = true;
3926         break;
3927     case 0x1: /* ORR */
3928         tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
3929         break;
3930     case 0x2: /* EOR */
3931         tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
3932         break;
3933     default:
3934         assert(FALSE); /* must handle all above */
3935         break;
3936     }
3937
3938     if (!sf && !is_and) {
3939         /* zero extend final result; we know we can skip this for AND
3940          * since the immediate had the high 32 bits clear.
3941          */
3942         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3943     }
3944
3945     if (opc == 3) { /* ANDS */
3946         gen_logic_CC(sf, tcg_rd);
3947     }
3948 }
3949
3950 /*
3951  * Move wide (immediate)
3952  *
3953  *  31 30 29 28         23 22 21 20             5 4    0
3954  * +--+-----+-------------+-----+----------------+------+
3955  * |sf| opc | 1 0 0 1 0 1 |  hw |  imm16         |  Rd  |
3956  * +--+-----+-------------+-----+----------------+------+
3957  *
3958  * sf: 0 -> 32 bit, 1 -> 64 bit
3959  * opc: 00 -> N, 10 -> Z, 11 -> K
3960  * hw: shift/16 (0,16, and sf only 32, 48)
3961  */
3962 static void disas_movw_imm(DisasContext *s, uint32_t insn)
3963 {
3964     int rd = extract32(insn, 0, 5);
3965     uint64_t imm = extract32(insn, 5, 16);
3966     int sf = extract32(insn, 31, 1);
3967     int opc = extract32(insn, 29, 2);
3968     int pos = extract32(insn, 21, 2) << 4;
3969     TCGv_i64 tcg_rd = cpu_reg(s, rd);
3970     TCGv_i64 tcg_imm;
3971
3972     if (!sf && (pos >= 32)) {
3973         unallocated_encoding(s);
3974         return;
3975     }
3976
3977     switch (opc) {
3978     case 0: /* MOVN */
3979     case 2: /* MOVZ */
3980         imm <<= pos;
3981         if (opc == 0) {
3982             imm = ~imm;
3983         }
3984         if (!sf) {
3985             imm &= 0xffffffffu;
3986         }
3987         tcg_gen_movi_i64(tcg_rd, imm);
3988         break;
3989     case 3: /* MOVK */
3990         tcg_imm = tcg_const_i64(imm);
3991         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_imm, pos, 16);
3992         tcg_temp_free_i64(tcg_imm);
3993         if (!sf) {
3994             tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3995         }
3996         break;
3997     default:
3998         unallocated_encoding(s);
3999         break;
4000     }
4001 }
4002
4003 /* Bitfield
4004  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
4005  * +----+-----+-------------+---+------+------+------+------+
4006  * | sf | opc | 1 0 0 1 1 0 | N | immr | imms |  Rn  |  Rd  |
4007  * +----+-----+-------------+---+------+------+------+------+
4008  */
4009 static void disas_bitfield(DisasContext *s, uint32_t insn)
4010 {
4011     unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
4012     TCGv_i64 tcg_rd, tcg_tmp;
4013
4014     sf = extract32(insn, 31, 1);
4015     opc = extract32(insn, 29, 2);
4016     n = extract32(insn, 22, 1);
4017     ri = extract32(insn, 16, 6);
4018     si = extract32(insn, 10, 6);
4019     rn = extract32(insn, 5, 5);
4020     rd = extract32(insn, 0, 5);
4021     bitsize = sf ? 64 : 32;
4022
4023     if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
4024         unallocated_encoding(s);
4025         return;
4026     }
4027
4028     tcg_rd = cpu_reg(s, rd);
4029
4030     /* Suppress the zero-extend for !sf.  Since RI and SI are constrained
4031        to be smaller than bitsize, we'll never reference data outside the
4032        low 32-bits anyway.  */
4033     tcg_tmp = read_cpu_reg(s, rn, 1);
4034
4035     /* Recognize simple(r) extractions.  */
4036     if (si >= ri) {
4037         /* Wd<s-r:0> = Wn<s:r> */
4038         len = (si - ri) + 1;
4039         if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
4040             tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
4041             goto done;
4042         } else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */
4043             tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
4044             return;
4045         }
4046         /* opc == 1, BXFIL fall through to deposit */
4047         tcg_gen_extract_i64(tcg_tmp, tcg_tmp, ri, len);
4048         pos = 0;
4049     } else {
4050         /* Handle the ri > si case with a deposit
4051          * Wd<32+s-r,32-r> = Wn<s:0>
4052          */
4053         len = si + 1;
4054         pos = (bitsize - ri) & (bitsize - 1);
4055     }
4056
4057     if (opc == 0 && len < ri) {
4058         /* SBFM: sign extend the destination field from len to fill
4059            the balance of the word.  Let the deposit below insert all
4060            of those sign bits.  */
4061         tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
4062         len = ri;
4063     }
4064
4065     if (opc == 1) { /* BFM, BXFIL */
4066         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
4067     } else {
4068         /* SBFM or UBFM: We start with zero, and we haven't modified
4069            any bits outside bitsize, therefore the zero-extension
4070            below is unneeded.  */
4071         tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
4072         return;
4073     }
4074
4075  done:
4076     if (!sf) { /* zero extend final result */
4077         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4078     }
4079 }
4080
4081 /* Extract
4082  *   31  30  29 28         23 22   21  20  16 15    10 9    5 4    0
4083  * +----+------+-------------+---+----+------+--------+------+------+
4084  * | sf | op21 | 1 0 0 1 1 1 | N | o0 |  Rm  |  imms  |  Rn  |  Rd  |
4085  * +----+------+-------------+---+----+------+--------+------+------+
4086  */
4087 static void disas_extract(DisasContext *s, uint32_t insn)
4088 {
4089     unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
4090
4091     sf = extract32(insn, 31, 1);
4092     n = extract32(insn, 22, 1);
4093     rm = extract32(insn, 16, 5);
4094     imm = extract32(insn, 10, 6);
4095     rn = extract32(insn, 5, 5);
4096     rd = extract32(insn, 0, 5);
4097     op21 = extract32(insn, 29, 2);
4098     op0 = extract32(insn, 21, 1);
4099     bitsize = sf ? 64 : 32;
4100
4101     if (sf != n || op21 || op0 || imm >= bitsize) {
4102         unallocated_encoding(s);
4103     } else {
4104         TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
4105
4106         tcg_rd = cpu_reg(s, rd);
4107
4108         if (unlikely(imm == 0)) {
4109             /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
4110              * so an extract from bit 0 is a special case.
4111              */
4112             if (sf) {
4113                 tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
4114             } else {
4115                 tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
4116             }
4117         } else if (rm == rn) { /* ROR */
4118             tcg_rm = cpu_reg(s, rm);
4119             if (sf) {
4120                 tcg_gen_rotri_i64(tcg_rd, tcg_rm, imm);
4121             } else {
4122                 TCGv_i32 tmp = tcg_temp_new_i32();
4123                 tcg_gen_extrl_i64_i32(tmp, tcg_rm);
4124                 tcg_gen_rotri_i32(tmp, tmp, imm);
4125                 tcg_gen_extu_i32_i64(tcg_rd, tmp);
4126                 tcg_temp_free_i32(tmp);
4127             }
4128         } else {
4129             tcg_rm = read_cpu_reg(s, rm, sf);
4130             tcg_rn = read_cpu_reg(s, rn, sf);
4131             tcg_gen_shri_i64(tcg_rm, tcg_rm, imm);
4132             tcg_gen_shli_i64(tcg_rn, tcg_rn, bitsize - imm);
4133             tcg_gen_or_i64(tcg_rd, tcg_rm, tcg_rn);
4134             if (!sf) {
4135                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4136             }
4137         }
4138     }
4139 }
4140
4141 /* Data processing - immediate */
4142 static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
4143 {
4144     switch (extract32(insn, 23, 6)) {
4145     case 0x20: case 0x21: /* PC-rel. addressing */
4146         disas_pc_rel_adr(s, insn);
4147         break;
4148     case 0x22: case 0x23: /* Add/subtract (immediate) */
4149         disas_add_sub_imm(s, insn);
4150         break;
4151     case 0x24: /* Logical (immediate) */
4152         disas_logic_imm(s, insn);
4153         break;
4154     case 0x25: /* Move wide (immediate) */
4155         disas_movw_imm(s, insn);
4156         break;
4157     case 0x26: /* Bitfield */
4158         disas_bitfield(s, insn);
4159         break;
4160     case 0x27: /* Extract */
4161         disas_extract(s, insn);
4162         break;
4163     default:
4164         unallocated_encoding(s);
4165         break;
4166     }
4167 }
4168
4169 /* Shift a TCGv src by TCGv shift_amount, put result in dst.
4170  * Note that it is the caller's responsibility to ensure that the
4171  * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
4172  * mandated semantics for out of range shifts.
4173  */
4174 static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
4175                       enum a64_shift_type shift_type, TCGv_i64 shift_amount)
4176 {
4177     switch (shift_type) {
4178     case A64_SHIFT_TYPE_LSL:
4179         tcg_gen_shl_i64(dst, src, shift_amount);
4180         break;
4181     case A64_SHIFT_TYPE_LSR:
4182         tcg_gen_shr_i64(dst, src, shift_amount);
4183         break;
4184     case A64_SHIFT_TYPE_ASR:
4185         if (!sf) {
4186             tcg_gen_ext32s_i64(dst, src);
4187         }
4188         tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
4189         break;
4190     case A64_SHIFT_TYPE_ROR:
4191         if (sf) {
4192             tcg_gen_rotr_i64(dst, src, shift_amount);
4193         } else {
4194             TCGv_i32 t0, t1;
4195             t0 = tcg_temp_new_i32();
4196             t1 = tcg_temp_new_i32();
4197             tcg_gen_extrl_i64_i32(t0, src);
4198             tcg_gen_extrl_i64_i32(t1, shift_amount);
4199             tcg_gen_rotr_i32(t0, t0, t1);
4200             tcg_gen_extu_i32_i64(dst, t0);
4201             tcg_temp_free_i32(t0);
4202             tcg_temp_free_i32(t1);
4203         }
4204         break;
4205     default:
4206         assert(FALSE); /* all shift types should be handled */
4207         break;
4208     }
4209
4210     if (!sf) { /* zero extend final result */
4211         tcg_gen_ext32u_i64(dst, dst);
4212     }
4213 }
4214
4215 /* Shift a TCGv src by immediate, put result in dst.
4216  * The shift amount must be in range (this should always be true as the
4217  * relevant instructions will UNDEF on bad shift immediates).
4218  */
4219 static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
4220                           enum a64_shift_type shift_type, unsigned int shift_i)
4221 {
4222     assert(shift_i < (sf ? 64 : 32));
4223
4224     if (shift_i == 0) {
4225         tcg_gen_mov_i64(dst, src);
4226     } else {
4227         TCGv_i64 shift_const;
4228
4229         shift_const = tcg_const_i64(shift_i);
4230         shift_reg(dst, src, sf, shift_type, shift_const);
4231         tcg_temp_free_i64(shift_const);
4232     }
4233 }
4234
4235 /* Logical (shifted register)
4236  *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
4237  * +----+-----+-----------+-------+---+------+--------+------+------+
4238  * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
4239  * +----+-----+-----------+-------+---+------+--------+------+------+
4240  */
4241 static void disas_logic_reg(DisasContext *s, uint32_t insn)
4242 {
4243     TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
4244     unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
4245
4246     sf = extract32(insn, 31, 1);
4247     opc = extract32(insn, 29, 2);
4248     shift_type = extract32(insn, 22, 2);
4249     invert = extract32(insn, 21, 1);
4250     rm = extract32(insn, 16, 5);
4251     shift_amount = extract32(insn, 10, 6);
4252     rn = extract32(insn, 5, 5);
4253     rd = extract32(insn, 0, 5);
4254
4255     if (!sf && (shift_amount & (1 << 5))) {
4256         unallocated_encoding(s);
4257         return;
4258     }
4259
4260     tcg_rd = cpu_reg(s, rd);
4261
4262     if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
4263         /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
4264          * register-register MOV and MVN, so it is worth special casing.
4265          */
4266         tcg_rm = cpu_reg(s, rm);
4267         if (invert) {
4268             tcg_gen_not_i64(tcg_rd, tcg_rm);
4269             if (!sf) {
4270                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4271             }
4272         } else {
4273             if (sf) {
4274                 tcg_gen_mov_i64(tcg_rd, tcg_rm);
4275             } else {
4276                 tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
4277             }
4278         }
4279         return;
4280     }
4281
4282     tcg_rm = read_cpu_reg(s, rm, sf);
4283
4284     if (shift_amount) {
4285         shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
4286     }
4287
4288     tcg_rn = cpu_reg(s, rn);
4289
4290     switch (opc | (invert << 2)) {
4291     case 0: /* AND */
4292     case 3: /* ANDS */
4293         tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
4294         break;
4295     case 1: /* ORR */
4296         tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
4297         break;
4298     case 2: /* EOR */
4299         tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
4300         break;
4301     case 4: /* BIC */
4302     case 7: /* BICS */
4303         tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
4304         break;
4305     case 5: /* ORN */
4306         tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
4307         break;
4308     case 6: /* EON */
4309         tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
4310         break;
4311     default:
4312         assert(FALSE);
4313         break;
4314     }
4315
4316     if (!sf) {
4317         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4318     }
4319
4320     if (opc == 3) {
4321         gen_logic_CC(sf, tcg_rd);
4322     }
4323 }
4324
4325 /*
4326  * Add/subtract (extended register)
4327  *
4328  *  31|30|29|28       24|23 22|21|20   16|15  13|12  10|9  5|4  0|
4329  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
4330  * |sf|op| S| 0 1 0 1 1 | opt | 1|  Rm   |option| imm3 | Rn | Rd |
4331  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
4332  *
4333  *  sf: 0 -> 32bit, 1 -> 64bit
4334  *  op: 0 -> add  , 1 -> sub
4335  *   S: 1 -> set flags
4336  * opt: 00
4337  * option: extension type (see DecodeRegExtend)
4338  * imm3: optional shift to Rm
4339  *
4340  * Rd = Rn + LSL(extend(Rm), amount)
4341  */
4342 static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
4343 {
4344     int rd = extract32(insn, 0, 5);
4345     int rn = extract32(insn, 5, 5);
4346     int imm3 = extract32(insn, 10, 3);
4347     int option = extract32(insn, 13, 3);
4348     int rm = extract32(insn, 16, 5);
4349     int opt = extract32(insn, 22, 2);
4350     bool setflags = extract32(insn, 29, 1);
4351     bool sub_op = extract32(insn, 30, 1);
4352     bool sf = extract32(insn, 31, 1);
4353
4354     TCGv_i64 tcg_rm, tcg_rn; /* temps */
4355     TCGv_i64 tcg_rd;
4356     TCGv_i64 tcg_result;
4357
4358     if (imm3 > 4 || opt != 0) {
4359         unallocated_encoding(s);
4360         return;
4361     }
4362
4363     /* non-flag setting ops may use SP */
4364     if (!setflags) {
4365         tcg_rd = cpu_reg_sp(s, rd);
4366     } else {
4367         tcg_rd = cpu_reg(s, rd);
4368     }
4369     tcg_rn = read_cpu_reg_sp(s, rn, sf);
4370
4371     tcg_rm = read_cpu_reg(s, rm, sf);
4372     ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
4373
4374     tcg_result = tcg_temp_new_i64();
4375
4376     if (!setflags) {
4377         if (sub_op) {
4378             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
4379         } else {
4380             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
4381         }
4382     } else {
4383         if (sub_op) {
4384             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
4385         } else {
4386             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
4387         }
4388     }
4389
4390     if (sf) {
4391         tcg_gen_mov_i64(tcg_rd, tcg_result);
4392     } else {
4393         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
4394     }
4395
4396     tcg_temp_free_i64(tcg_result);
4397 }
4398
4399 /*
4400  * Add/subtract (shifted register)
4401  *
4402  *  31 30 29 28       24 23 22 21 20   16 15     10 9    5 4    0
4403  * +--+--+--+-----------+-----+--+-------+---------+------+------+
4404  * |sf|op| S| 0 1 0 1 1 |shift| 0|  Rm   |  imm6   |  Rn  |  Rd  |
4405  * +--+--+--+-----------+-----+--+-------+---------+------+------+
4406  *
4407  *    sf: 0 -> 32bit, 1 -> 64bit
4408  *    op: 0 -> add  , 1 -> sub
4409  *     S: 1 -> set flags
4410  * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
4411  *  imm6: Shift amount to apply to Rm before the add/sub
4412  */
4413 static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
4414 {
4415     int rd = extract32(insn, 0, 5);
4416     int rn = extract32(insn, 5, 5);
4417     int imm6 = extract32(insn, 10, 6);
4418     int rm = extract32(insn, 16, 5);
4419     int shift_type = extract32(insn, 22, 2);
4420     bool setflags = extract32(insn, 29, 1);
4421     bool sub_op = extract32(insn, 30, 1);
4422     bool sf = extract32(insn, 31, 1);
4423
4424     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4425     TCGv_i64 tcg_rn, tcg_rm;
4426     TCGv_i64 tcg_result;
4427
4428     if ((shift_type == 3) || (!sf && (imm6 > 31))) {
4429         unallocated_encoding(s);
4430         return;
4431     }
4432
4433     tcg_rn = read_cpu_reg(s, rn, sf);
4434     tcg_rm = read_cpu_reg(s, rm, sf);
4435
4436     shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
4437
4438     tcg_result = tcg_temp_new_i64();
4439
4440     if (!setflags) {
4441         if (sub_op) {
4442             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
4443         } else {
4444             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
4445         }
4446     } else {
4447         if (sub_op) {
4448             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
4449         } else {
4450             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
4451         }
4452     }
4453
4454     if (sf) {
4455         tcg_gen_mov_i64(tcg_rd, tcg_result);
4456     } else {
4457         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
4458     }
4459
4460     tcg_temp_free_i64(tcg_result);
4461 }
4462
4463 /* Data-processing (3 source)
4464  *
4465  *    31 30  29 28       24 23 21  20  16  15  14  10 9    5 4    0
4466  *  +--+------+-----------+------+------+----+------+------+------+
4467  *  |sf| op54 | 1 1 0 1 1 | op31 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
4468  *  +--+------+-----------+------+------+----+------+------+------+
4469  */
4470 static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
4471 {
4472     int rd = extract32(insn, 0, 5);
4473     int rn = extract32(insn, 5, 5);
4474     int ra = extract32(insn, 10, 5);
4475     int rm = extract32(insn, 16, 5);
4476     int op_id = (extract32(insn, 29, 3) << 4) |
4477         (extract32(insn, 21, 3) << 1) |
4478         extract32(insn, 15, 1);
4479     bool sf = extract32(insn, 31, 1);
4480     bool is_sub = extract32(op_id, 0, 1);
4481     bool is_high = extract32(op_id, 2, 1);
4482     bool is_signed = false;
4483     TCGv_i64 tcg_op1;
4484     TCGv_i64 tcg_op2;
4485     TCGv_i64 tcg_tmp;
4486
4487     /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
4488     switch (op_id) {
4489     case 0x42: /* SMADDL */
4490     case 0x43: /* SMSUBL */
4491     case 0x44: /* SMULH */
4492         is_signed = true;
4493         break;
4494     case 0x0: /* MADD (32bit) */
4495     case 0x1: /* MSUB (32bit) */
4496     case 0x40: /* MADD (64bit) */
4497     case 0x41: /* MSUB (64bit) */
4498     case 0x4a: /* UMADDL */
4499     case 0x4b: /* UMSUBL */
4500     case 0x4c: /* UMULH */
4501         break;
4502     default:
4503         unallocated_encoding(s);
4504         return;
4505     }
4506
4507     if (is_high) {
4508         TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
4509         TCGv_i64 tcg_rd = cpu_reg(s, rd);
4510         TCGv_i64 tcg_rn = cpu_reg(s, rn);
4511         TCGv_i64 tcg_rm = cpu_reg(s, rm);
4512
4513         if (is_signed) {
4514             tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
4515         } else {
4516             tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
4517         }
4518
4519         tcg_temp_free_i64(low_bits);
4520         return;
4521     }
4522
4523     tcg_op1 = tcg_temp_new_i64();
4524     tcg_op2 = tcg_temp_new_i64();
4525     tcg_tmp = tcg_temp_new_i64();
4526
4527     if (op_id < 0x42) {
4528         tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
4529         tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
4530     } else {
4531         if (is_signed) {
4532             tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
4533             tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
4534         } else {
4535             tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
4536             tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
4537         }
4538     }
4539
4540     if (ra == 31 && !is_sub) {
4541         /* Special-case MADD with rA == XZR; it is the standard MUL alias */
4542         tcg_gen_mul_i64(cpu_reg(s, rd), tcg_op1, tcg_op2);
4543     } else {
4544         tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
4545         if (is_sub) {
4546             tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
4547         } else {
4548             tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
4549         }
4550     }
4551
4552     if (!sf) {
4553         tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
4554     }
4555
4556     tcg_temp_free_i64(tcg_op1);
4557     tcg_temp_free_i64(tcg_op2);
4558     tcg_temp_free_i64(tcg_tmp);
4559 }
4560
4561 /* Add/subtract (with carry)
4562  *  31 30 29 28 27 26 25 24 23 22 21  20  16  15       10  9    5 4   0
4563  * +--+--+--+------------------------+------+-------------+------+-----+
4564  * |sf|op| S| 1  1  0  1  0  0  0  0 |  rm  | 0 0 0 0 0 0 |  Rn  |  Rd |
4565  * +--+--+--+------------------------+------+-------------+------+-----+
4566  */
4567
4568 static void disas_adc_sbc(DisasContext *s, uint32_t insn)
4569 {
4570     unsigned int sf, op, setflags, rm, rn, rd;
4571     TCGv_i64 tcg_y, tcg_rn, tcg_rd;
4572
4573     sf = extract32(insn, 31, 1);
4574     op = extract32(insn, 30, 1);
4575     setflags = extract32(insn, 29, 1);
4576     rm = extract32(insn, 16, 5);
4577     rn = extract32(insn, 5, 5);
4578     rd = extract32(insn, 0, 5);
4579
4580     tcg_rd = cpu_reg(s, rd);
4581     tcg_rn = cpu_reg(s, rn);
4582
4583     if (op) {
4584         tcg_y = new_tmp_a64(s);
4585         tcg_gen_not_i64(tcg_y, cpu_reg(s, rm));
4586     } else {
4587         tcg_y = cpu_reg(s, rm);
4588     }
4589
4590     if (setflags) {
4591         gen_adc_CC(sf, tcg_rd, tcg_rn, tcg_y);
4592     } else {
4593         gen_adc(sf, tcg_rd, tcg_rn, tcg_y);
4594     }
4595 }
4596
4597 /*
4598  * Rotate right into flags
4599  *  31 30 29                21       15          10      5  4      0
4600  * +--+--+--+-----------------+--------+-----------+------+--+------+
4601  * |sf|op| S| 1 1 0 1 0 0 0 0 |  imm6  | 0 0 0 0 1 |  Rn  |o2| mask |
4602  * +--+--+--+-----------------+--------+-----------+------+--+------+
4603  */
4604 static void disas_rotate_right_into_flags(DisasContext *s, uint32_t insn)
4605 {
4606     int mask = extract32(insn, 0, 4);
4607     int o2 = extract32(insn, 4, 1);
4608     int rn = extract32(insn, 5, 5);
4609     int imm6 = extract32(insn, 15, 6);
4610     int sf_op_s = extract32(insn, 29, 3);
4611     TCGv_i64 tcg_rn;
4612     TCGv_i32 nzcv;
4613
4614     if (sf_op_s != 5 || o2 != 0 || !dc_isar_feature(aa64_condm_4, s)) {
4615         unallocated_encoding(s);
4616         return;
4617     }
4618
4619     tcg_rn = read_cpu_reg(s, rn, 1);
4620     tcg_gen_rotri_i64(tcg_rn, tcg_rn, imm6);
4621
4622     nzcv = tcg_temp_new_i32();
4623     tcg_gen_extrl_i64_i32(nzcv, tcg_rn);
4624
4625     if (mask & 8) { /* N */
4626         tcg_gen_shli_i32(cpu_NF, nzcv, 31 - 3);
4627     }
4628     if (mask & 4) { /* Z */
4629         tcg_gen_not_i32(cpu_ZF, nzcv);
4630         tcg_gen_andi_i32(cpu_ZF, cpu_ZF, 4);
4631     }
4632     if (mask & 2) { /* C */
4633         tcg_gen_extract_i32(cpu_CF, nzcv, 1, 1);
4634     }
4635     if (mask & 1) { /* V */
4636         tcg_gen_shli_i32(cpu_VF, nzcv, 31 - 0);
4637     }
4638
4639     tcg_temp_free_i32(nzcv);
4640 }
4641
4642 /*
4643  * Evaluate into flags
4644  *  31 30 29                21        15   14        10      5  4      0
4645  * +--+--+--+-----------------+---------+----+---------+------+--+------+
4646  * |sf|op| S| 1 1 0 1 0 0 0 0 | opcode2 | sz | 0 0 1 0 |  Rn  |o3| mask |
4647  * +--+--+--+-----------------+---------+----+---------+------+--+------+
4648  */
4649 static void disas_evaluate_into_flags(DisasContext *s, uint32_t insn)
4650 {
4651     int o3_mask = extract32(insn, 0, 5);
4652     int rn = extract32(insn, 5, 5);
4653     int o2 = extract32(insn, 15, 6);
4654     int sz = extract32(insn, 14, 1);
4655     int sf_op_s = extract32(insn, 29, 3);
4656     TCGv_i32 tmp;
4657     int shift;
4658
4659     if (sf_op_s != 1 || o2 != 0 || o3_mask != 0xd ||
4660         !dc_isar_feature(aa64_condm_4, s)) {
4661         unallocated_encoding(s);
4662         return;
4663     }
4664     shift = sz ? 16 : 24;  /* SETF16 or SETF8 */
4665
4666     tmp = tcg_temp_new_i32();
4667     tcg_gen_extrl_i64_i32(tmp, cpu_reg(s, rn));
4668     tcg_gen_shli_i32(cpu_NF, tmp, shift);
4669     tcg_gen_shli_i32(cpu_VF, tmp, shift - 1);
4670     tcg_gen_mov_i32(cpu_ZF, cpu_NF);
4671     tcg_gen_xor_i32(cpu_VF, cpu_VF, cpu_NF);
4672     tcg_temp_free_i32(tmp);
4673 }
4674
4675 /* Conditional compare (immediate / register)
4676  *  31 30 29 28 27 26 25 24 23 22 21  20    16 15  12  11  10  9   5  4 3   0
4677  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
4678  * |sf|op| S| 1  1  0  1  0  0  1  0 |imm5/rm | cond |i/r |o2|  Rn  |o3|nzcv |
4679  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
4680  *        [1]                             y                [0]       [0]
4681  */
4682 static void disas_cc(DisasContext *s, uint32_t insn)
4683 {
4684     unsigned int sf, op, y, cond, rn, nzcv, is_imm;
4685     TCGv_i32 tcg_t0, tcg_t1, tcg_t2;
4686     TCGv_i64 tcg_tmp, tcg_y, tcg_rn;
4687     DisasCompare c;
4688
4689     if (!extract32(insn, 29, 1)) {
4690         unallocated_encoding(s);
4691         return;
4692     }
4693     if (insn & (1 << 10 | 1 << 4)) {
4694         unallocated_encoding(s);
4695         return;
4696     }
4697     sf = extract32(insn, 31, 1);
4698     op = extract32(insn, 30, 1);
4699     is_imm = extract32(insn, 11, 1);
4700     y = extract32(insn, 16, 5); /* y = rm (reg) or imm5 (imm) */
4701     cond = extract32(insn, 12, 4);
4702     rn = extract32(insn, 5, 5);
4703     nzcv = extract32(insn, 0, 4);
4704
4705     /* Set T0 = !COND.  */
4706     tcg_t0 = tcg_temp_new_i32();
4707     arm_test_cc(&c, cond);
4708     tcg_gen_setcondi_i32(tcg_invert_cond(c.cond), tcg_t0, c.value, 0);
4709     arm_free_cc(&c);
4710
4711     /* Load the arguments for the new comparison.  */
4712     if (is_imm) {
4713         tcg_y = new_tmp_a64(s);
4714         tcg_gen_movi_i64(tcg_y, y);
4715     } else {
4716         tcg_y = cpu_reg(s, y);
4717     }
4718     tcg_rn = cpu_reg(s, rn);
4719
4720     /* Set the flags for the new comparison.  */
4721     tcg_tmp = tcg_temp_new_i64();
4722     if (op) {
4723         gen_sub_CC(sf, tcg_tmp, tcg_rn, tcg_y);
4724     } else {
4725         gen_add_CC(sf, tcg_tmp, tcg_rn, tcg_y);
4726     }
4727     tcg_temp_free_i64(tcg_tmp);
4728
4729     /* If COND was false, force the flags to #nzcv.  Compute two masks
4730      * to help with this: T1 = (COND ? 0 : -1), T2 = (COND ? -1 : 0).
4731      * For tcg hosts that support ANDC, we can make do with just T1.
4732      * In either case, allow the tcg optimizer to delete any unused mask.
4733      */
4734     tcg_t1 = tcg_temp_new_i32();
4735     tcg_t2 = tcg_temp_new_i32();
4736     tcg_gen_neg_i32(tcg_t1, tcg_t0);
4737     tcg_gen_subi_i32(tcg_t2, tcg_t0, 1);
4738
4739     if (nzcv & 8) { /* N */
4740         tcg_gen_or_i32(cpu_NF, cpu_NF, tcg_t1);
4741     } else {
4742         if (TCG_TARGET_HAS_andc_i32) {
4743             tcg_gen_andc_i32(cpu_NF, cpu_NF, tcg_t1);
4744         } else {
4745             tcg_gen_and_i32(cpu_NF, cpu_NF, tcg_t2);
4746         }
4747     }
4748     if (nzcv & 4) { /* Z */
4749         if (TCG_TARGET_HAS_andc_i32) {
4750             tcg_gen_andc_i32(cpu_ZF, cpu_ZF, tcg_t1);
4751         } else {
4752             tcg_gen_and_i32(cpu_ZF, cpu_ZF, tcg_t2);
4753         }
4754     } else {
4755         tcg_gen_or_i32(cpu_ZF, cpu_ZF, tcg_t0);
4756     }
4757     if (nzcv & 2) { /* C */
4758         tcg_gen_or_i32(cpu_CF, cpu_CF, tcg_t0);
4759     } else {
4760         if (TCG_TARGET_HAS_andc_i32) {
4761             tcg_gen_andc_i32(cpu_CF, cpu_CF, tcg_t1);
4762         } else {
4763             tcg_gen_and_i32(cpu_CF, cpu_CF, tcg_t2);
4764         }
4765     }
4766     if (nzcv & 1) { /* V */
4767         tcg_gen_or_i32(cpu_VF, cpu_VF, tcg_t1);
4768     } else {
4769         if (TCG_TARGET_HAS_andc_i32) {
4770             tcg_gen_andc_i32(cpu_VF, cpu_VF, tcg_t1);
4771         } else {
4772             tcg_gen_and_i32(cpu_VF, cpu_VF, tcg_t2);
4773         }
4774     }
4775     tcg_temp_free_i32(tcg_t0);
4776     tcg_temp_free_i32(tcg_t1);
4777     tcg_temp_free_i32(tcg_t2);
4778 }
4779
4780 /* Conditional select
4781  *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
4782  * +----+----+---+-----------------+------+------+-----+------+------+
4783  * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
4784  * +----+----+---+-----------------+------+------+-----+------+------+
4785  */
4786 static void disas_cond_select(DisasContext *s, uint32_t insn)
4787 {
4788     unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
4789     TCGv_i64 tcg_rd, zero;
4790     DisasCompare64 c;
4791
4792     if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
4793         /* S == 1 or op2<1> == 1 */
4794         unallocated_encoding(s);
4795         return;
4796     }
4797     sf = extract32(insn, 31, 1);
4798     else_inv = extract32(insn, 30, 1);
4799     rm = extract32(insn, 16, 5);
4800     cond = extract32(insn, 12, 4);
4801     else_inc = extract32(insn, 10, 1);
4802     rn = extract32(insn, 5, 5);
4803     rd = extract32(insn, 0, 5);
4804
4805     tcg_rd = cpu_reg(s, rd);
4806
4807     a64_test_cc(&c, cond);
4808     zero = tcg_const_i64(0);
4809
4810     if (rn == 31 && rm == 31 && (else_inc ^ else_inv)) {
4811         /* CSET & CSETM.  */
4812         tcg_gen_setcond_i64(tcg_invert_cond(c.cond), tcg_rd, c.value, zero);
4813         if (else_inv) {
4814             tcg_gen_neg_i64(tcg_rd, tcg_rd);
4815         }
4816     } else {
4817         TCGv_i64 t_true = cpu_reg(s, rn);
4818         TCGv_i64 t_false = read_cpu_reg(s, rm, 1);
4819         if (else_inv && else_inc) {
4820             tcg_gen_neg_i64(t_false, t_false);
4821         } else if (else_inv) {
4822             tcg_gen_not_i64(t_false, t_false);
4823         } else if (else_inc) {
4824             tcg_gen_addi_i64(t_false, t_false, 1);
4825         }
4826         tcg_gen_movcond_i64(c.cond, tcg_rd, c.value, zero, t_true, t_false);
4827     }
4828
4829     tcg_temp_free_i64(zero);
4830     a64_free_cc(&c);
4831
4832     if (!sf) {
4833         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4834     }
4835 }
4836
4837 static void handle_clz(DisasContext *s, unsigned int sf,
4838                        unsigned int rn, unsigned int rd)
4839 {
4840     TCGv_i64 tcg_rd, tcg_rn;
4841     tcg_rd = cpu_reg(s, rd);
4842     tcg_rn = cpu_reg(s, rn);
4843
4844     if (sf) {
4845         tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
4846     } else {
4847         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4848         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4849         tcg_gen_clzi_i32(tcg_tmp32, tcg_tmp32, 32);
4850         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4851         tcg_temp_free_i32(tcg_tmp32);
4852     }
4853 }
4854
4855 static void handle_cls(DisasContext *s, unsigned int sf,
4856                        unsigned int rn, unsigned int rd)
4857 {
4858     TCGv_i64 tcg_rd, tcg_rn;
4859     tcg_rd = cpu_reg(s, rd);
4860     tcg_rn = cpu_reg(s, rn);
4861
4862     if (sf) {
4863         tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
4864     } else {
4865         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4866         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4867         tcg_gen_clrsb_i32(tcg_tmp32, tcg_tmp32);
4868         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4869         tcg_temp_free_i32(tcg_tmp32);
4870     }
4871 }
4872
4873 static void handle_rbit(DisasContext *s, unsigned int sf,
4874                         unsigned int rn, unsigned int rd)
4875 {
4876     TCGv_i64 tcg_rd, tcg_rn;
4877     tcg_rd = cpu_reg(s, rd);
4878     tcg_rn = cpu_reg(s, rn);
4879
4880     if (sf) {
4881         gen_helper_rbit64(tcg_rd, tcg_rn);
4882     } else {
4883         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4884         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4885         gen_helper_rbit(tcg_tmp32, tcg_tmp32);
4886         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4887         tcg_temp_free_i32(tcg_tmp32);
4888     }
4889 }
4890
4891 /* REV with sf==1, opcode==3 ("REV64") */
4892 static void handle_rev64(DisasContext *s, unsigned int sf,
4893                          unsigned int rn, unsigned int rd)
4894 {
4895     if (!sf) {
4896         unallocated_encoding(s);
4897         return;
4898     }
4899     tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
4900 }
4901
4902 /* REV with sf==0, opcode==2
4903  * REV32 (sf==1, opcode==2)
4904  */
4905 static void handle_rev32(DisasContext *s, unsigned int sf,
4906                          unsigned int rn, unsigned int rd)
4907 {
4908     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4909
4910     if (sf) {
4911         TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4912         TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
4913
4914         /* bswap32_i64 requires zero high word */
4915         tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
4916         tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
4917         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
4918         tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
4919         tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
4920
4921         tcg_temp_free_i64(tcg_tmp);
4922     } else {
4923         tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
4924         tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
4925     }
4926 }
4927
4928 /* REV16 (opcode==1) */
4929 static void handle_rev16(DisasContext *s, unsigned int sf,
4930                          unsigned int rn, unsigned int rd)
4931 {
4932     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4933     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4934     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
4935     TCGv_i64 mask = tcg_const_i64(sf ? 0x00ff00ff00ff00ffull : 0x00ff00ff);
4936
4937     tcg_gen_shri_i64(tcg_tmp, tcg_rn, 8);
4938     tcg_gen_and_i64(tcg_rd, tcg_rn, mask);
4939     tcg_gen_and_i64(tcg_tmp, tcg_tmp, mask);
4940     tcg_gen_shli_i64(tcg_rd, tcg_rd, 8);
4941     tcg_gen_or_i64(tcg_rd, tcg_rd, tcg_tmp);
4942
4943     tcg_temp_free_i64(mask);
4944     tcg_temp_free_i64(tcg_tmp);
4945 }
4946
4947 /* Data-processing (1 source)
4948  *   31  30  29  28             21 20     16 15    10 9    5 4    0
4949  * +----+---+---+-----------------+---------+--------+------+------+
4950  * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
4951  * +----+---+---+-----------------+---------+--------+------+------+
4952  */
4953 static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
4954 {
4955     unsigned int sf, opcode, opcode2, rn, rd;
4956     TCGv_i64 tcg_rd;
4957
4958     if (extract32(insn, 29, 1)) {
4959         unallocated_encoding(s);
4960         return;
4961     }
4962
4963     sf = extract32(insn, 31, 1);
4964     opcode = extract32(insn, 10, 6);
4965     opcode2 = extract32(insn, 16, 5);
4966     rn = extract32(insn, 5, 5);
4967     rd = extract32(insn, 0, 5);
4968
4969 #define MAP(SF, O2, O1) ((SF) | (O1 << 1) | (O2 << 7))
4970
4971     switch (MAP(sf, opcode2, opcode)) {
4972     case MAP(0, 0x00, 0x00): /* RBIT */
4973     case MAP(1, 0x00, 0x00):
4974         handle_rbit(s, sf, rn, rd);
4975         break;
4976     case MAP(0, 0x00, 0x01): /* REV16 */
4977     case MAP(1, 0x00, 0x01):
4978         handle_rev16(s, sf, rn, rd);
4979         break;
4980     case MAP(0, 0x00, 0x02): /* REV/REV32 */
4981     case MAP(1, 0x00, 0x02):
4982         handle_rev32(s, sf, rn, rd);
4983         break;
4984     case MAP(1, 0x00, 0x03): /* REV64 */
4985         handle_rev64(s, sf, rn, rd);
4986         break;
4987     case MAP(0, 0x00, 0x04): /* CLZ */
4988     case MAP(1, 0x00, 0x04):
4989         handle_clz(s, sf, rn, rd);
4990         break;
4991     case MAP(0, 0x00, 0x05): /* CLS */
4992     case MAP(1, 0x00, 0x05):
4993         handle_cls(s, sf, rn, rd);
4994         break;
4995     case MAP(1, 0x01, 0x00): /* PACIA */
4996         if (s->pauth_active) {
4997             tcg_rd = cpu_reg(s, rd);
4998             gen_helper_pacia(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
4999         } else if (!dc_isar_feature(aa64_pauth, s)) {
5000             goto do_unallocated;
5001         }
5002         break;
5003     case MAP(1, 0x01, 0x01): /* PACIB */
5004         if (s->pauth_active) {
5005             tcg_rd = cpu_reg(s, rd);
5006             gen_helper_pacib(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5007         } else if (!dc_isar_feature(aa64_pauth, s)) {
5008             goto do_unallocated;
5009         }
5010         break;
5011     case MAP(1, 0x01, 0x02): /* PACDA */
5012         if (s->pauth_active) {
5013             tcg_rd = cpu_reg(s, rd);
5014             gen_helper_pacda(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5015         } else if (!dc_isar_feature(aa64_pauth, s)) {
5016             goto do_unallocated;
5017         }
5018         break;
5019     case MAP(1, 0x01, 0x03): /* PACDB */
5020         if (s->pauth_active) {
5021             tcg_rd = cpu_reg(s, rd);
5022             gen_helper_pacdb(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5023         } else if (!dc_isar_feature(aa64_pauth, s)) {
5024             goto do_unallocated;
5025         }
5026         break;
5027     case MAP(1, 0x01, 0x04): /* AUTIA */
5028         if (s->pauth_active) {
5029             tcg_rd = cpu_reg(s, rd);
5030             gen_helper_autia(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5031         } else if (!dc_isar_feature(aa64_pauth, s)) {
5032             goto do_unallocated;
5033         }
5034         break;
5035     case MAP(1, 0x01, 0x05): /* AUTIB */
5036         if (s->pauth_active) {
5037             tcg_rd = cpu_reg(s, rd);
5038             gen_helper_autib(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5039         } else if (!dc_isar_feature(aa64_pauth, s)) {
5040             goto do_unallocated;
5041         }
5042         break;
5043     case MAP(1, 0x01, 0x06): /* AUTDA */
5044         if (s->pauth_active) {
5045             tcg_rd = cpu_reg(s, rd);
5046             gen_helper_autda(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5047         } else if (!dc_isar_feature(aa64_pauth, s)) {
5048             goto do_unallocated;
5049         }
5050         break;
5051     case MAP(1, 0x01, 0x07): /* AUTDB */
5052         if (s->pauth_active) {
5053             tcg_rd = cpu_reg(s, rd);
5054             gen_helper_autdb(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5055         } else if (!dc_isar_feature(aa64_pauth, s)) {
5056             goto do_unallocated;
5057         }
5058         break;
5059     case MAP(1, 0x01, 0x08): /* PACIZA */
5060         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5061             goto do_unallocated;
5062         } else if (s->pauth_active) {
5063             tcg_rd = cpu_reg(s, rd);
5064             gen_helper_pacia(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5065         }
5066         break;
5067     case MAP(1, 0x01, 0x09): /* PACIZB */
5068         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5069             goto do_unallocated;
5070         } else if (s->pauth_active) {
5071             tcg_rd = cpu_reg(s, rd);
5072             gen_helper_pacib(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5073         }
5074         break;
5075     case MAP(1, 0x01, 0x0a): /* PACDZA */
5076         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5077             goto do_unallocated;
5078         } else if (s->pauth_active) {
5079             tcg_rd = cpu_reg(s, rd);
5080             gen_helper_pacda(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5081         }
5082         break;
5083     case MAP(1, 0x01, 0x0b): /* PACDZB */
5084         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5085             goto do_unallocated;
5086         } else if (s->pauth_active) {
5087             tcg_rd = cpu_reg(s, rd);
5088             gen_helper_pacdb(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5089         }
5090         break;
5091     case MAP(1, 0x01, 0x0c): /* AUTIZA */
5092         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5093             goto do_unallocated;
5094         } else if (s->pauth_active) {
5095             tcg_rd = cpu_reg(s, rd);
5096             gen_helper_autia(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5097         }
5098         break;
5099     case MAP(1, 0x01, 0x0d): /* AUTIZB */
5100         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5101             goto do_unallocated;
5102         } else if (s->pauth_active) {
5103             tcg_rd = cpu_reg(s, rd);
5104             gen_helper_autib(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5105         }
5106         break;
5107     case MAP(1, 0x01, 0x0e): /* AUTDZA */
5108         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5109             goto do_unallocated;
5110         } else if (s->pauth_active) {
5111             tcg_rd = cpu_reg(s, rd);
5112             gen_helper_autda(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5113         }
5114         break;
5115     case MAP(1, 0x01, 0x0f): /* AUTDZB */
5116         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5117             goto do_unallocated;
5118         } else if (s->pauth_active) {
5119             tcg_rd = cpu_reg(s, rd);
5120             gen_helper_autdb(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5121         }
5122         break;
5123     case MAP(1, 0x01, 0x10): /* XPACI */
5124         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5125             goto do_unallocated;
5126         } else if (s->pauth_active) {
5127             tcg_rd = cpu_reg(s, rd);
5128             gen_helper_xpaci(tcg_rd, cpu_env, tcg_rd);
5129         }
5130         break;
5131     case MAP(1, 0x01, 0x11): /* XPACD */
5132         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5133             goto do_unallocated;
5134         } else if (s->pauth_active) {
5135             tcg_rd = cpu_reg(s, rd);
5136             gen_helper_xpacd(tcg_rd, cpu_env, tcg_rd);
5137         }
5138         break;
5139     default:
5140     do_unallocated:
5141         unallocated_encoding(s);
5142         break;
5143     }
5144
5145 #undef MAP
5146 }
5147
5148 static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
5149                        unsigned int rm, unsigned int rn, unsigned int rd)
5150 {
5151     TCGv_i64 tcg_n, tcg_m, tcg_rd;
5152     tcg_rd = cpu_reg(s, rd);
5153
5154     if (!sf && is_signed) {
5155         tcg_n = new_tmp_a64(s);
5156         tcg_m = new_tmp_a64(s);
5157         tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
5158         tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
5159     } else {
5160         tcg_n = read_cpu_reg(s, rn, sf);
5161         tcg_m = read_cpu_reg(s, rm, sf);
5162     }
5163
5164     if (is_signed) {
5165         gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
5166     } else {
5167         gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
5168     }
5169
5170     if (!sf) { /* zero extend final result */
5171         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
5172     }
5173 }
5174
5175 /* LSLV, LSRV, ASRV, RORV */
5176 static void handle_shift_reg(DisasContext *s,
5177                              enum a64_shift_type shift_type, unsigned int sf,
5178                              unsigned int rm, unsigned int rn, unsigned int rd)
5179 {
5180     TCGv_i64 tcg_shift = tcg_temp_new_i64();
5181     TCGv_i64 tcg_rd = cpu_reg(s, rd);
5182     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
5183
5184     tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
5185     shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
5186     tcg_temp_free_i64(tcg_shift);
5187 }
5188
5189 /* CRC32[BHWX], CRC32C[BHWX] */
5190 static void handle_crc32(DisasContext *s,
5191                          unsigned int sf, unsigned int sz, bool crc32c,
5192                          unsigned int rm, unsigned int rn, unsigned int rd)
5193 {
5194     TCGv_i64 tcg_acc, tcg_val;
5195     TCGv_i32 tcg_bytes;
5196
5197     if (!dc_isar_feature(aa64_crc32, s)
5198         || (sf == 1 && sz != 3)
5199         || (sf == 0 && sz == 3)) {
5200         unallocated_encoding(s);
5201         return;
5202     }
5203
5204     if (sz == 3) {
5205         tcg_val = cpu_reg(s, rm);
5206     } else {
5207         uint64_t mask;
5208         switch (sz) {
5209         case 0:
5210             mask = 0xFF;
5211             break;
5212         case 1:
5213             mask = 0xFFFF;
5214             break;
5215         case 2:
5216             mask = 0xFFFFFFFF;
5217             break;
5218         default:
5219             g_assert_not_reached();
5220         }
5221         tcg_val = new_tmp_a64(s);
5222         tcg_gen_andi_i64(tcg_val, cpu_reg(s, rm), mask);
5223     }
5224
5225     tcg_acc = cpu_reg(s, rn);
5226     tcg_bytes = tcg_const_i32(1 << sz);
5227
5228     if (crc32c) {
5229         gen_helper_crc32c_64(cpu_reg(s, rd), tcg_acc, tcg_val, tcg_bytes);
5230     } else {
5231         gen_helper_crc32_64(cpu_reg(s, rd), tcg_acc, tcg_val, tcg_bytes);
5232     }
5233
5234     tcg_temp_free_i32(tcg_bytes);
5235 }
5236
5237 /* Data-processing (2 source)
5238  *   31   30  29 28             21 20  16 15    10 9    5 4    0
5239  * +----+---+---+-----------------+------+--------+------+------+
5240  * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
5241  * +----+---+---+-----------------+------+--------+------+------+
5242  */
5243 static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
5244 {
5245     unsigned int sf, rm, opcode, rn, rd;
5246     sf = extract32(insn, 31, 1);
5247     rm = extract32(insn, 16, 5);
5248     opcode = extract32(insn, 10, 6);
5249     rn = extract32(insn, 5, 5);
5250     rd = extract32(insn, 0, 5);
5251
5252     if (extract32(insn, 29, 1)) {
5253         unallocated_encoding(s);
5254         return;
5255     }
5256
5257     switch (opcode) {
5258     case 2: /* UDIV */
5259         handle_div(s, false, sf, rm, rn, rd);
5260         break;
5261     case 3: /* SDIV */
5262         handle_div(s, true, sf, rm, rn, rd);
5263         break;
5264     case 8: /* LSLV */
5265         handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
5266         break;
5267     case 9: /* LSRV */
5268         handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
5269         break;
5270     case 10: /* ASRV */
5271         handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
5272         break;
5273     case 11: /* RORV */
5274         handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
5275         break;
5276     case 12: /* PACGA */
5277         if (sf == 0 || !dc_isar_feature(aa64_pauth, s)) {
5278             goto do_unallocated;
5279         }
5280         gen_helper_pacga(cpu_reg(s, rd), cpu_env,
5281                          cpu_reg(s, rn), cpu_reg_sp(s, rm));
5282         break;
5283     case 16:
5284     case 17:
5285     case 18:
5286     case 19:
5287     case 20:
5288     case 21:
5289     case 22:
5290     case 23: /* CRC32 */
5291     {
5292         int sz = extract32(opcode, 0, 2);
5293         bool crc32c = extract32(opcode, 2, 1);
5294         handle_crc32(s, sf, sz, crc32c, rm, rn, rd);
5295         break;
5296     }
5297     default:
5298     do_unallocated:
5299         unallocated_encoding(s);
5300         break;
5301     }
5302 }
5303
5304 /*
5305  * Data processing - register
5306  *  31  30 29  28      25    21  20  16      10         0
5307  * +--+---+--+---+-------+-----+-------+-------+---------+
5308  * |  |op0|  |op1| 1 0 1 | op2 |       |  op3  |         |
5309  * +--+---+--+---+-------+-----+-------+-------+---------+
5310  */
5311 static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
5312 {
5313     int op0 = extract32(insn, 30, 1);
5314     int op1 = extract32(insn, 28, 1);
5315     int op2 = extract32(insn, 21, 4);
5316     int op3 = extract32(insn, 10, 6);
5317
5318     if (!op1) {
5319         if (op2 & 8) {
5320             if (op2 & 1) {
5321                 /* Add/sub (extended register) */
5322                 disas_add_sub_ext_reg(s, insn);
5323             } else {
5324                 /* Add/sub (shifted register) */
5325                 disas_add_sub_reg(s, insn);
5326             }
5327         } else {
5328             /* Logical (shifted register) */
5329             disas_logic_reg(s, insn);
5330         }
5331         return;
5332     }
5333
5334     switch (op2) {
5335     case 0x0:
5336         switch (op3) {
5337         case 0x00: /* Add/subtract (with carry) */
5338             disas_adc_sbc(s, insn);
5339             break;
5340
5341         case 0x01: /* Rotate right into flags */
5342         case 0x21:
5343             disas_rotate_right_into_flags(s, insn);
5344             break;
5345
5346         case 0x02: /* Evaluate into flags */
5347         case 0x12:
5348         case 0x22:
5349         case 0x32:
5350             disas_evaluate_into_flags(s, insn);
5351             break;
5352
5353         default:
5354             goto do_unallocated;
5355         }
5356         break;
5357
5358     case 0x2: /* Conditional compare */
5359         disas_cc(s, insn); /* both imm and reg forms */
5360         break;
5361
5362     case 0x4: /* Conditional select */
5363         disas_cond_select(s, insn);
5364         break;
5365
5366     case 0x6: /* Data-processing */
5367         if (op0) {    /* (1 source) */
5368             disas_data_proc_1src(s, insn);
5369         } else {      /* (2 source) */
5370             disas_data_proc_2src(s, insn);
5371         }
5372         break;
5373     case 0x8 ... 0xf: /* (3 source) */
5374         disas_data_proc_3src(s, insn);
5375         break;
5376
5377     default:
5378     do_unallocated:
5379         unallocated_encoding(s);
5380         break;
5381     }
5382 }
5383
5384 static void handle_fp_compare(DisasContext *s, int size,
5385                               unsigned int rn, unsigned int rm,
5386                               bool cmp_with_zero, bool signal_all_nans)
5387 {
5388     TCGv_i64 tcg_flags = tcg_temp_new_i64();
5389     TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
5390
5391     if (size == MO_64) {
5392         TCGv_i64 tcg_vn, tcg_vm;
5393
5394         tcg_vn = read_fp_dreg(s, rn);
5395         if (cmp_with_zero) {
5396             tcg_vm = tcg_const_i64(0);
5397         } else {
5398             tcg_vm = read_fp_dreg(s, rm);
5399         }
5400         if (signal_all_nans) {
5401             gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5402         } else {
5403             gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5404         }
5405         tcg_temp_free_i64(tcg_vn);
5406         tcg_temp_free_i64(tcg_vm);
5407     } else {
5408         TCGv_i32 tcg_vn = tcg_temp_new_i32();
5409         TCGv_i32 tcg_vm = tcg_temp_new_i32();
5410
5411         read_vec_element_i32(s, tcg_vn, rn, 0, size);
5412         if (cmp_with_zero) {
5413             tcg_gen_movi_i32(tcg_vm, 0);
5414         } else {
5415             read_vec_element_i32(s, tcg_vm, rm, 0, size);
5416         }
5417
5418         switch (size) {
5419         case MO_32:
5420             if (signal_all_nans) {
5421                 gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5422             } else {
5423                 gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5424             }
5425             break;
5426         case MO_16:
5427             if (signal_all_nans) {
5428                 gen_helper_vfp_cmpeh_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5429             } else {
5430                 gen_helper_vfp_cmph_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5431             }
5432             break;
5433         default:
5434             g_assert_not_reached();
5435         }
5436
5437         tcg_temp_free_i32(tcg_vn);
5438         tcg_temp_free_i32(tcg_vm);
5439     }
5440
5441     tcg_temp_free_ptr(fpst);
5442
5443     gen_set_nzcv(tcg_flags);
5444
5445     tcg_temp_free_i64(tcg_flags);
5446 }
5447
5448 /* Floating point compare
5449  *   31  30  29 28       24 23  22  21 20  16 15 14 13  10    9    5 4     0
5450  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
5451  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | op  | 1 0 0 0 |  Rn  |  op2  |
5452  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
5453  */
5454 static void disas_fp_compare(DisasContext *s, uint32_t insn)
5455 {
5456     unsigned int mos, type, rm, op, rn, opc, op2r;
5457     int size;
5458
5459     mos = extract32(insn, 29, 3);
5460     type = extract32(insn, 22, 2);
5461     rm = extract32(insn, 16, 5);
5462     op = extract32(insn, 14, 2);
5463     rn = extract32(insn, 5, 5);
5464     opc = extract32(insn, 3, 2);
5465     op2r = extract32(insn, 0, 3);
5466
5467     if (mos || op || op2r) {
5468         unallocated_encoding(s);
5469         return;
5470     }
5471
5472     switch (type) {
5473     case 0:
5474         size = MO_32;
5475         break;
5476     case 1:
5477         size = MO_64;
5478         break;
5479     case 3:
5480         size = MO_16;
5481         if (dc_isar_feature(aa64_fp16, s)) {
5482             break;
5483         }
5484         /* fallthru */
5485     default:
5486         unallocated_encoding(s);
5487         return;
5488     }
5489
5490     if (!fp_access_check(s)) {
5491         return;
5492     }
5493
5494     handle_fp_compare(s, size, rn, rm, opc & 1, opc & 2);
5495 }
5496
5497 /* Floating point conditional compare
5498  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5  4   3    0
5499  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
5500  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 0 1 |  Rn  | op | nzcv |
5501  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
5502  */
5503 static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
5504 {
5505     unsigned int mos, type, rm, cond, rn, op, nzcv;
5506     TCGv_i64 tcg_flags;
5507     TCGLabel *label_continue = NULL;
5508     int size;
5509
5510     mos = extract32(insn, 29, 3);
5511     type = extract32(insn, 22, 2);
5512     rm = extract32(insn, 16, 5);
5513     cond = extract32(insn, 12, 4);
5514     rn = extract32(insn, 5, 5);
5515     op = extract32(insn, 4, 1);
5516     nzcv = extract32(insn, 0, 4);
5517
5518     if (mos) {
5519         unallocated_encoding(s);
5520         return;
5521     }
5522
5523     switch (type) {
5524     case 0:
5525         size = MO_32;
5526         break;
5527     case 1:
5528         size = MO_64;
5529         break;
5530     case 3:
5531         size = MO_16;
5532         if (dc_isar_feature(aa64_fp16, s)) {
5533             break;
5534         }
5535         /* fallthru */
5536     default:
5537         unallocated_encoding(s);
5538         return;
5539     }
5540
5541     if (!fp_access_check(s)) {
5542         return;
5543     }
5544
5545     if (cond < 0x0e) { /* not always */
5546         TCGLabel *label_match = gen_new_label();
5547         label_continue = gen_new_label();
5548         arm_gen_test_cc(cond, label_match);
5549         /* nomatch: */
5550         tcg_flags = tcg_const_i64(nzcv << 28);
5551         gen_set_nzcv(tcg_flags);
5552         tcg_temp_free_i64(tcg_flags);
5553         tcg_gen_br(label_continue);
5554         gen_set_label(label_match);
5555     }
5556
5557     handle_fp_compare(s, size, rn, rm, false, op);
5558
5559     if (cond < 0x0e) {
5560         gen_set_label(label_continue);
5561     }
5562 }
5563
5564 /* Floating point conditional select
5565  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5 4    0
5566  * +---+---+---+-----------+------+---+------+------+-----+------+------+
5567  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 1 1 |  Rn  |  Rd  |
5568  * +---+---+---+-----------+------+---+------+------+-----+------+------+
5569  */
5570 static void disas_fp_csel(DisasContext *s, uint32_t insn)
5571 {
5572     unsigned int mos, type, rm, cond, rn, rd;
5573     TCGv_i64 t_true, t_false, t_zero;
5574     DisasCompare64 c;
5575     TCGMemOp sz;
5576
5577     mos = extract32(insn, 29, 3);
5578     type = extract32(insn, 22, 2);
5579     rm = extract32(insn, 16, 5);
5580     cond = extract32(insn, 12, 4);
5581     rn = extract32(insn, 5, 5);
5582     rd = extract32(insn, 0, 5);
5583
5584     if (mos) {
5585         unallocated_encoding(s);
5586         return;
5587     }
5588
5589     switch (type) {
5590     case 0:
5591         sz = MO_32;
5592         break;
5593     case 1:
5594         sz = MO_64;
5595         break;
5596     case 3:
5597         sz = MO_16;
5598         if (dc_isar_feature(aa64_fp16, s)) {
5599             break;
5600         }
5601         /* fallthru */
5602     default:
5603         unallocated_encoding(s);
5604         return;
5605     }
5606
5607     if (!fp_access_check(s)) {
5608         return;
5609     }
5610
5611     /* Zero extend sreg & hreg inputs to 64 bits now.  */
5612     t_true = tcg_temp_new_i64();
5613     t_false = tcg_temp_new_i64();
5614     read_vec_element(s, t_true, rn, 0, sz);
5615     read_vec_element(s, t_false, rm, 0, sz);
5616
5617     a64_test_cc(&c, cond);
5618     t_zero = tcg_const_i64(0);
5619     tcg_gen_movcond_i64(c.cond, t_true, c.value, t_zero, t_true, t_false);
5620     tcg_temp_free_i64(t_zero);
5621     tcg_temp_free_i64(t_false);
5622     a64_free_cc(&c);
5623
5624     /* Note that sregs & hregs write back zeros to the high bits,
5625        and we've already done the zero-extension.  */
5626     write_fp_dreg(s, rd, t_true);
5627     tcg_temp_free_i64(t_true);
5628 }
5629
5630 /* Floating-point data-processing (1 source) - half precision */
5631 static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
5632 {
5633     TCGv_ptr fpst = NULL;
5634     TCGv_i32 tcg_op = read_fp_hreg(s, rn);
5635     TCGv_i32 tcg_res = tcg_temp_new_i32();
5636
5637     switch (opcode) {
5638     case 0x0: /* FMOV */
5639         tcg_gen_mov_i32(tcg_res, tcg_op);
5640         break;
5641     case 0x1: /* FABS */
5642         tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
5643         break;
5644     case 0x2: /* FNEG */
5645         tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
5646         break;
5647     case 0x3: /* FSQRT */
5648         fpst = get_fpstatus_ptr(true);
5649         gen_helper_sqrt_f16(tcg_res, tcg_op, fpst);
5650         break;
5651     case 0x8: /* FRINTN */
5652     case 0x9: /* FRINTP */
5653     case 0xa: /* FRINTM */
5654     case 0xb: /* FRINTZ */
5655     case 0xc: /* FRINTA */
5656     {
5657         TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
5658         fpst = get_fpstatus_ptr(true);
5659
5660         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5661         gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
5662
5663         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5664         tcg_temp_free_i32(tcg_rmode);
5665         break;
5666     }
5667     case 0xe: /* FRINTX */
5668         fpst = get_fpstatus_ptr(true);
5669         gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, fpst);
5670         break;
5671     case 0xf: /* FRINTI */
5672         fpst = get_fpstatus_ptr(true);
5673         gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
5674         break;
5675     default:
5676         abort();
5677     }
5678
5679     write_fp_sreg(s, rd, tcg_res);
5680
5681     if (fpst) {
5682         tcg_temp_free_ptr(fpst);
5683     }
5684     tcg_temp_free_i32(tcg_op);
5685     tcg_temp_free_i32(tcg_res);
5686 }
5687
5688 /* Floating-point data-processing (1 source) - single precision */
5689 static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
5690 {
5691     void (*gen_fpst)(TCGv_i32, TCGv_i32, TCGv_ptr);
5692     TCGv_i32 tcg_op, tcg_res;
5693     TCGv_ptr fpst;
5694     int rmode = -1;
5695
5696     tcg_op = read_fp_sreg(s, rn);
5697     tcg_res = tcg_temp_new_i32();
5698
5699     switch (opcode) {
5700     case 0x0: /* FMOV */
5701         tcg_gen_mov_i32(tcg_res, tcg_op);
5702         goto done;
5703     case 0x1: /* FABS */
5704         gen_helper_vfp_abss(tcg_res, tcg_op);
5705         goto done;
5706     case 0x2: /* FNEG */
5707         gen_helper_vfp_negs(tcg_res, tcg_op);
5708         goto done;
5709     case 0x3: /* FSQRT */
5710         gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
5711         goto done;
5712     case 0x8: /* FRINTN */
5713     case 0x9: /* FRINTP */
5714     case 0xa: /* FRINTM */
5715     case 0xb: /* FRINTZ */
5716     case 0xc: /* FRINTA */
5717         rmode = arm_rmode_to_sf(opcode & 7);
5718         gen_fpst = gen_helper_rints;
5719         break;
5720     case 0xe: /* FRINTX */
5721         gen_fpst = gen_helper_rints_exact;
5722         break;
5723     case 0xf: /* FRINTI */
5724         gen_fpst = gen_helper_rints;
5725         break;
5726     case 0x10: /* FRINT32Z */
5727         rmode = float_round_to_zero;
5728         gen_fpst = gen_helper_frint32_s;
5729         break;
5730     case 0x11: /* FRINT32X */
5731         gen_fpst = gen_helper_frint32_s;
5732         break;
5733     case 0x12: /* FRINT64Z */
5734         rmode = float_round_to_zero;
5735         gen_fpst = gen_helper_frint64_s;
5736         break;
5737     case 0x13: /* FRINT64X */
5738         gen_fpst = gen_helper_frint64_s;
5739         break;
5740     default:
5741         g_assert_not_reached();
5742     }
5743
5744     fpst = get_fpstatus_ptr(false);
5745     if (rmode >= 0) {
5746         TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
5747         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5748         gen_fpst(tcg_res, tcg_op, fpst);
5749         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5750         tcg_temp_free_i32(tcg_rmode);
5751     } else {
5752         gen_fpst(tcg_res, tcg_op, fpst);
5753     }
5754     tcg_temp_free_ptr(fpst);
5755
5756  done:
5757     write_fp_sreg(s, rd, tcg_res);
5758     tcg_temp_free_i32(tcg_op);
5759     tcg_temp_free_i32(tcg_res);
5760 }
5761
5762 /* Floating-point data-processing (1 source) - double precision */
5763 static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
5764 {
5765     void (*gen_fpst)(TCGv_i64, TCGv_i64, TCGv_ptr);
5766     TCGv_i64 tcg_op, tcg_res;
5767     TCGv_ptr fpst;
5768     int rmode = -1;
5769
5770     switch (opcode) {
5771     case 0x0: /* FMOV */
5772         gen_gvec_fn2(s, false, rd, rn, tcg_gen_gvec_mov, 0);
5773         return;
5774     }
5775
5776     tcg_op = read_fp_dreg(s, rn);
5777     tcg_res = tcg_temp_new_i64();
5778
5779     switch (opcode) {
5780     case 0x1: /* FABS */
5781         gen_helper_vfp_absd(tcg_res, tcg_op);
5782         goto done;
5783     case 0x2: /* FNEG */
5784         gen_helper_vfp_negd(tcg_res, tcg_op);
5785         goto done;
5786     case 0x3: /* FSQRT */
5787         gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
5788         goto done;
5789     case 0x8: /* FRINTN */
5790     case 0x9: /* FRINTP */
5791     case 0xa: /* FRINTM */
5792     case 0xb: /* FRINTZ */
5793     case 0xc: /* FRINTA */
5794         rmode = arm_rmode_to_sf(opcode & 7);
5795         gen_fpst = gen_helper_rintd;
5796         break;
5797     case 0xe: /* FRINTX */
5798         gen_fpst = gen_helper_rintd_exact;
5799         break;
5800     case 0xf: /* FRINTI */
5801         gen_fpst = gen_helper_rintd;
5802         break;
5803     case 0x10: /* FRINT32Z */
5804         rmode = float_round_to_zero;
5805         gen_fpst = gen_helper_frint32_d;
5806         break;
5807     case 0x11: /* FRINT32X */
5808         gen_fpst = gen_helper_frint32_d;
5809         break;
5810     case 0x12: /* FRINT64Z */
5811         rmode = float_round_to_zero;
5812         gen_fpst = gen_helper_frint64_d;
5813         break;
5814     case 0x13: /* FRINT64X */
5815         gen_fpst = gen_helper_frint64_d;
5816         break;
5817     default:
5818         g_assert_not_reached();
5819     }
5820
5821     fpst = get_fpstatus_ptr(false);
5822     if (rmode >= 0) {
5823         TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
5824         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5825         gen_fpst(tcg_res, tcg_op, fpst);
5826         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5827         tcg_temp_free_i32(tcg_rmode);
5828     } else {
5829         gen_fpst(tcg_res, tcg_op, fpst);
5830     }
5831     tcg_temp_free_ptr(fpst);
5832
5833  done:
5834     write_fp_dreg(s, rd, tcg_res);
5835     tcg_temp_free_i64(tcg_op);
5836     tcg_temp_free_i64(tcg_res);
5837 }
5838
5839 static void handle_fp_fcvt(DisasContext *s, int opcode,
5840                            int rd, int rn, int dtype, int ntype)
5841 {
5842     switch (ntype) {
5843     case 0x0:
5844     {
5845         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
5846         if (dtype == 1) {
5847             /* Single to double */
5848             TCGv_i64 tcg_rd = tcg_temp_new_i64();
5849             gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
5850             write_fp_dreg(s, rd, tcg_rd);
5851             tcg_temp_free_i64(tcg_rd);
5852         } else {
5853             /* Single to half */
5854             TCGv_i32 tcg_rd = tcg_temp_new_i32();
5855             TCGv_i32 ahp = get_ahp_flag();
5856             TCGv_ptr fpst = get_fpstatus_ptr(false);
5857
5858             gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, fpst, ahp);
5859             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
5860             write_fp_sreg(s, rd, tcg_rd);
5861             tcg_temp_free_i32(tcg_rd);
5862             tcg_temp_free_i32(ahp);
5863             tcg_temp_free_ptr(fpst);
5864         }
5865         tcg_temp_free_i32(tcg_rn);
5866         break;
5867     }
5868     case 0x1:
5869     {
5870         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
5871         TCGv_i32 tcg_rd = tcg_temp_new_i32();
5872         if (dtype == 0) {
5873             /* Double to single */
5874             gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
5875         } else {
5876             TCGv_ptr fpst = get_fpstatus_ptr(false);
5877             TCGv_i32 ahp = get_ahp_flag();
5878             /* Double to half */
5879             gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, fpst, ahp);
5880             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
5881             tcg_temp_free_ptr(fpst);
5882             tcg_temp_free_i32(ahp);
5883         }
5884         write_fp_sreg(s, rd, tcg_rd);
5885         tcg_temp_free_i32(tcg_rd);
5886         tcg_temp_free_i64(tcg_rn);
5887         break;
5888     }
5889     case 0x3:
5890     {
5891         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
5892         TCGv_ptr tcg_fpst = get_fpstatus_ptr(false);
5893         TCGv_i32 tcg_ahp = get_ahp_flag();
5894         tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
5895         if (dtype == 0) {
5896             /* Half to single */
5897             TCGv_i32 tcg_rd = tcg_temp_new_i32();
5898             gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp);
5899             write_fp_sreg(s, rd, tcg_rd);
5900             tcg_temp_free_ptr(tcg_fpst);
5901             tcg_temp_free_i32(tcg_ahp);
5902             tcg_temp_free_i32(tcg_rd);
5903         } else {
5904             /* Half to double */
5905             TCGv_i64 tcg_rd = tcg_temp_new_i64();
5906             gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp);
5907             write_fp_dreg(s, rd, tcg_rd);
5908             tcg_temp_free_i64(tcg_rd);
5909         }
5910         tcg_temp_free_i32(tcg_rn);
5911         break;
5912     }
5913     default:
5914         abort();
5915     }
5916 }
5917
5918 /* Floating point data-processing (1 source)
5919  *   31  30  29 28       24 23  22  21 20    15 14       10 9    5 4    0
5920  * +---+---+---+-----------+------+---+--------+-----------+------+------+
5921  * | M | 0 | S | 1 1 1 1 0 | type | 1 | opcode | 1 0 0 0 0 |  Rn  |  Rd  |
5922  * +---+---+---+-----------+------+---+--------+-----------+------+------+
5923  */
5924 static void disas_fp_1src(DisasContext *s, uint32_t insn)
5925 {
5926     int mos = extract32(insn, 29, 3);
5927     int type = extract32(insn, 22, 2);
5928     int opcode = extract32(insn, 15, 6);
5929     int rn = extract32(insn, 5, 5);
5930     int rd = extract32(insn, 0, 5);
5931
5932     if (mos) {
5933         unallocated_encoding(s);
5934         return;
5935     }
5936
5937     switch (opcode) {
5938     case 0x4: case 0x5: case 0x7:
5939     {
5940         /* FCVT between half, single and double precision */
5941         int dtype = extract32(opcode, 0, 2);
5942         if (type == 2 || dtype == type) {
5943             unallocated_encoding(s);
5944             return;
5945         }
5946         if (!fp_access_check(s)) {
5947             return;
5948         }
5949
5950         handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
5951         break;
5952     }
5953
5954     case 0x10 ... 0x13: /* FRINT{32,64}{X,Z} */
5955         if (type > 1 || !dc_isar_feature(aa64_frint, s)) {
5956             unallocated_encoding(s);
5957             return;
5958         }
5959         /* fall through */
5960     case 0x0 ... 0x3:
5961     case 0x8 ... 0xc:
5962     case 0xe ... 0xf:
5963         /* 32-to-32 and 64-to-64 ops */
5964         switch (type) {
5965         case 0:
5966             if (!fp_access_check(s)) {
5967                 return;
5968             }
5969             handle_fp_1src_single(s, opcode, rd, rn);
5970             break;
5971         case 1:
5972             if (!fp_access_check(s)) {
5973                 return;
5974             }
5975             handle_fp_1src_double(s, opcode, rd, rn);
5976             break;
5977         case 3:
5978             if (!dc_isar_feature(aa64_fp16, s)) {
5979                 unallocated_encoding(s);
5980                 return;
5981             }
5982
5983             if (!fp_access_check(s)) {
5984                 return;
5985             }
5986             handle_fp_1src_half(s, opcode, rd, rn);
5987             break;
5988         default:
5989             unallocated_encoding(s);
5990         }
5991         break;
5992
5993     default:
5994         unallocated_encoding(s);
5995         break;
5996     }
5997 }
5998
5999 /* Floating-point data-processing (2 source) - single precision */
6000 static void handle_fp_2src_single(DisasContext *s, int opcode,
6001                                   int rd, int rn, int rm)
6002 {
6003     TCGv_i32 tcg_op1;
6004     TCGv_i32 tcg_op2;
6005     TCGv_i32 tcg_res;
6006     TCGv_ptr fpst;
6007
6008     tcg_res = tcg_temp_new_i32();
6009     fpst = get_fpstatus_ptr(false);
6010     tcg_op1 = read_fp_sreg(s, rn);
6011     tcg_op2 = read_fp_sreg(s, rm);
6012
6013     switch (opcode) {
6014     case 0x0: /* FMUL */
6015         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
6016         break;
6017     case 0x1: /* FDIV */
6018         gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
6019         break;
6020     case 0x2: /* FADD */
6021         gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
6022         break;
6023     case 0x3: /* FSUB */
6024         gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
6025         break;
6026     case 0x4: /* FMAX */
6027         gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
6028         break;
6029     case 0x5: /* FMIN */
6030         gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
6031         break;
6032     case 0x6: /* FMAXNM */
6033         gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
6034         break;
6035     case 0x7: /* FMINNM */
6036         gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
6037         break;
6038     case 0x8: /* FNMUL */
6039         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
6040         gen_helper_vfp_negs(tcg_res, tcg_res);
6041         break;
6042     }
6043
6044     write_fp_sreg(s, rd, tcg_res);
6045
6046     tcg_temp_free_ptr(fpst);
6047     tcg_temp_free_i32(tcg_op1);
6048     tcg_temp_free_i32(tcg_op2);
6049     tcg_temp_free_i32(tcg_res);
6050 }
6051
6052 /* Floating-point data-processing (2 source) - double precision */
6053 static void handle_fp_2src_double(DisasContext *s, int opcode,
6054                                   int rd, int rn, int rm)
6055 {
6056     TCGv_i64 tcg_op1;
6057     TCGv_i64 tcg_op2;
6058     TCGv_i64 tcg_res;
6059     TCGv_ptr fpst;
6060
6061     tcg_res = tcg_temp_new_i64();
6062     fpst = get_fpstatus_ptr(false);
6063     tcg_op1 = read_fp_dreg(s, rn);
6064     tcg_op2 = read_fp_dreg(s, rm);
6065
6066     switch (opcode) {
6067     case 0x0: /* FMUL */
6068         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
6069         break;
6070     case 0x1: /* FDIV */
6071         gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
6072         break;
6073     case 0x2: /* FADD */
6074         gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
6075         break;
6076     case 0x3: /* FSUB */
6077         gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
6078         break;
6079     case 0x4: /* FMAX */
6080         gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
6081         break;
6082     case 0x5: /* FMIN */
6083         gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
6084         break;
6085     case 0x6: /* FMAXNM */
6086         gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
6087         break;
6088     case 0x7: /* FMINNM */
6089         gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
6090         break;
6091     case 0x8: /* FNMUL */
6092         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
6093         gen_helper_vfp_negd(tcg_res, tcg_res);
6094         break;
6095     }
6096
6097     write_fp_dreg(s, rd, tcg_res);
6098
6099     tcg_temp_free_ptr(fpst);
6100     tcg_temp_free_i64(tcg_op1);
6101     tcg_temp_free_i64(tcg_op2);
6102     tcg_temp_free_i64(tcg_res);
6103 }
6104
6105 /* Floating-point data-processing (2 source) - half precision */
6106 static void handle_fp_2src_half(DisasContext *s, int opcode,
6107                                 int rd, int rn, int rm)
6108 {
6109     TCGv_i32 tcg_op1;
6110     TCGv_i32 tcg_op2;
6111     TCGv_i32 tcg_res;
6112     TCGv_ptr fpst;
6113
6114     tcg_res = tcg_temp_new_i32();
6115     fpst = get_fpstatus_ptr(true);
6116     tcg_op1 = read_fp_hreg(s, rn);
6117     tcg_op2 = read_fp_hreg(s, rm);
6118
6119     switch (opcode) {
6120     case 0x0: /* FMUL */
6121         gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
6122         break;
6123     case 0x1: /* FDIV */
6124         gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
6125         break;
6126     case 0x2: /* FADD */
6127         gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
6128         break;
6129     case 0x3: /* FSUB */
6130         gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
6131         break;
6132     case 0x4: /* FMAX */
6133         gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
6134         break;
6135     case 0x5: /* FMIN */
6136         gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
6137         break;
6138     case 0x6: /* FMAXNM */
6139         gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
6140         break;
6141     case 0x7: /* FMINNM */
6142         gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
6143         break;
6144     case 0x8: /* FNMUL */
6145         gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
6146         tcg_gen_xori_i32(tcg_res, tcg_res, 0x8000);
6147         break;
6148     default:
6149         g_assert_not_reached();
6150     }
6151
6152     write_fp_sreg(s, rd, tcg_res);
6153
6154     tcg_temp_free_ptr(fpst);
6155     tcg_temp_free_i32(tcg_op1);
6156     tcg_temp_free_i32(tcg_op2);
6157     tcg_temp_free_i32(tcg_res);
6158 }
6159
6160 /* Floating point data-processing (2 source)
6161  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
6162  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
6163  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | opcode | 1 0 |  Rn  |  Rd  |
6164  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
6165  */
6166 static void disas_fp_2src(DisasContext *s, uint32_t insn)
6167 {
6168     int mos = extract32(insn, 29, 3);
6169     int type = extract32(insn, 22, 2);
6170     int rd = extract32(insn, 0, 5);
6171     int rn = extract32(insn, 5, 5);
6172     int rm = extract32(insn, 16, 5);
6173     int opcode = extract32(insn, 12, 4);
6174
6175     if (opcode > 8 || mos) {
6176         unallocated_encoding(s);
6177         return;
6178     }
6179
6180     switch (type) {
6181     case 0:
6182         if (!fp_access_check(s)) {
6183             return;
6184         }
6185         handle_fp_2src_single(s, opcode, rd, rn, rm);
6186         break;
6187     case 1:
6188         if (!fp_access_check(s)) {
6189             return;
6190         }
6191         handle_fp_2src_double(s, opcode, rd, rn, rm);
6192         break;
6193     case 3:
6194         if (!dc_isar_feature(aa64_fp16, s)) {
6195             unallocated_encoding(s);
6196             return;
6197         }
6198         if (!fp_access_check(s)) {
6199             return;
6200         }
6201         handle_fp_2src_half(s, opcode, rd, rn, rm);
6202         break;
6203     default:
6204         unallocated_encoding(s);
6205     }
6206 }
6207
6208 /* Floating-point data-processing (3 source) - single precision */
6209 static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
6210                                   int rd, int rn, int rm, int ra)
6211 {
6212     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
6213     TCGv_i32 tcg_res = tcg_temp_new_i32();
6214     TCGv_ptr fpst = get_fpstatus_ptr(false);
6215
6216     tcg_op1 = read_fp_sreg(s, rn);
6217     tcg_op2 = read_fp_sreg(s, rm);
6218     tcg_op3 = read_fp_sreg(s, ra);
6219
6220     /* These are fused multiply-add, and must be done as one
6221      * floating point operation with no rounding between the
6222      * multiplication and addition steps.
6223      * NB that doing the negations here as separate steps is
6224      * correct : an input NaN should come out with its sign bit
6225      * flipped if it is a negated-input.
6226      */
6227     if (o1 == true) {
6228         gen_helper_vfp_negs(tcg_op3, tcg_op3);
6229     }
6230
6231     if (o0 != o1) {
6232         gen_helper_vfp_negs(tcg_op1, tcg_op1);
6233     }
6234
6235     gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
6236
6237     write_fp_sreg(s, rd, tcg_res);
6238
6239     tcg_temp_free_ptr(fpst);
6240     tcg_temp_free_i32(tcg_op1);
6241     tcg_temp_free_i32(tcg_op2);
6242     tcg_temp_free_i32(tcg_op3);
6243     tcg_temp_free_i32(tcg_res);
6244 }
6245
6246 /* Floating-point data-processing (3 source) - double precision */
6247 static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
6248                                   int rd, int rn, int rm, int ra)
6249 {
6250     TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
6251     TCGv_i64 tcg_res = tcg_temp_new_i64();
6252     TCGv_ptr fpst = get_fpstatus_ptr(false);
6253
6254     tcg_op1 = read_fp_dreg(s, rn);
6255     tcg_op2 = read_fp_dreg(s, rm);
6256     tcg_op3 = read_fp_dreg(s, ra);
6257
6258     /* These are fused multiply-add, and must be done as one
6259      * floating point operation with no rounding between the
6260      * multiplication and addition steps.
6261      * NB that doing the negations here as separate steps is
6262      * correct : an input NaN should come out with its sign bit
6263      * flipped if it is a negated-input.
6264      */
6265     if (o1 == true) {
6266         gen_helper_vfp_negd(tcg_op3, tcg_op3);
6267     }
6268
6269     if (o0 != o1) {
6270         gen_helper_vfp_negd(tcg_op1, tcg_op1);
6271     }
6272
6273     gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
6274
6275     write_fp_dreg(s, rd, tcg_res);
6276
6277     tcg_temp_free_ptr(fpst);
6278     tcg_temp_free_i64(tcg_op1);
6279     tcg_temp_free_i64(tcg_op2);
6280     tcg_temp_free_i64(tcg_op3);
6281     tcg_temp_free_i64(tcg_res);
6282 }
6283
6284 /* Floating-point data-processing (3 source) - half precision */
6285 static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1,
6286                                 int rd, int rn, int rm, int ra)
6287 {
6288     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
6289     TCGv_i32 tcg_res = tcg_temp_new_i32();
6290     TCGv_ptr fpst = get_fpstatus_ptr(true);
6291
6292     tcg_op1 = read_fp_hreg(s, rn);
6293     tcg_op2 = read_fp_hreg(s, rm);
6294     tcg_op3 = read_fp_hreg(s, ra);
6295
6296     /* These are fused multiply-add, and must be done as one
6297      * floating point operation with no rounding between the
6298      * multiplication and addition steps.
6299      * NB that doing the negations here as separate steps is
6300      * correct : an input NaN should come out with its sign bit
6301      * flipped if it is a negated-input.
6302      */
6303     if (o1 == true) {
6304         tcg_gen_xori_i32(tcg_op3, tcg_op3, 0x8000);
6305     }
6306
6307     if (o0 != o1) {
6308         tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
6309     }
6310
6311     gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
6312
6313     write_fp_sreg(s, rd, tcg_res);
6314
6315     tcg_temp_free_ptr(fpst);
6316     tcg_temp_free_i32(tcg_op1);
6317     tcg_temp_free_i32(tcg_op2);
6318     tcg_temp_free_i32(tcg_op3);
6319     tcg_temp_free_i32(tcg_res);
6320 }
6321
6322 /* Floating point data-processing (3 source)
6323  *   31  30  29 28       24 23  22  21  20  16  15  14  10 9    5 4    0
6324  * +---+---+---+-----------+------+----+------+----+------+------+------+
6325  * | M | 0 | S | 1 1 1 1 1 | type | o1 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
6326  * +---+---+---+-----------+------+----+------+----+------+------+------+
6327  */
6328 static void disas_fp_3src(DisasContext *s, uint32_t insn)
6329 {
6330     int mos = extract32(insn, 29, 3);
6331     int type = extract32(insn, 22, 2);
6332     int rd = extract32(insn, 0, 5);
6333     int rn = extract32(insn, 5, 5);
6334     int ra = extract32(insn, 10, 5);
6335     int rm = extract32(insn, 16, 5);
6336     bool o0 = extract32(insn, 15, 1);
6337     bool o1 = extract32(insn, 21, 1);
6338
6339     if (mos) {
6340         unallocated_encoding(s);
6341         return;
6342     }
6343
6344     switch (type) {
6345     case 0:
6346         if (!fp_access_check(s)) {
6347             return;
6348         }
6349         handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
6350         break;
6351     case 1:
6352         if (!fp_access_check(s)) {
6353             return;
6354         }
6355         handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
6356         break;
6357     case 3:
6358         if (!dc_isar_feature(aa64_fp16, s)) {
6359             unallocated_encoding(s);
6360             return;
6361         }
6362         if (!fp_access_check(s)) {
6363             return;
6364         }
6365         handle_fp_3src_half(s, o0, o1, rd, rn, rm, ra);
6366         break;
6367     default:
6368         unallocated_encoding(s);
6369     }
6370 }
6371
6372 /* The imm8 encodes the sign bit, enough bits to represent an exponent in
6373  * the range 01....1xx to 10....0xx, and the most significant 4 bits of
6374  * the mantissa; see VFPExpandImm() in the v8 ARM ARM.
6375  */
6376 uint64_t vfp_expand_imm(int size, uint8_t imm8)
6377 {
6378     uint64_t imm;
6379
6380     switch (size) {
6381     case MO_64:
6382         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
6383             (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
6384             extract32(imm8, 0, 6);
6385         imm <<= 48;
6386         break;
6387     case MO_32:
6388         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
6389             (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
6390             (extract32(imm8, 0, 6) << 3);
6391         imm <<= 16;
6392         break;
6393     case MO_16:
6394         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
6395             (extract32(imm8, 6, 1) ? 0x3000 : 0x4000) |
6396             (extract32(imm8, 0, 6) << 6);
6397         break;
6398     default:
6399         g_assert_not_reached();
6400     }
6401     return imm;
6402 }
6403
6404 /* Floating point immediate
6405  *   31  30  29 28       24 23  22  21 20        13 12   10 9    5 4    0
6406  * +---+---+---+-----------+------+---+------------+-------+------+------+
6407  * | M | 0 | S | 1 1 1 1 0 | type | 1 |    imm8    | 1 0 0 | imm5 |  Rd  |
6408  * +---+---+---+-----------+------+---+------------+-------+------+------+
6409  */
6410 static void disas_fp_imm(DisasContext *s, uint32_t insn)
6411 {
6412     int rd = extract32(insn, 0, 5);
6413     int imm5 = extract32(insn, 5, 5);
6414     int imm8 = extract32(insn, 13, 8);
6415     int type = extract32(insn, 22, 2);
6416     int mos = extract32(insn, 29, 3);
6417     uint64_t imm;
6418     TCGv_i64 tcg_res;
6419     TCGMemOp sz;
6420
6421     if (mos || imm5) {
6422         unallocated_encoding(s);
6423         return;
6424     }
6425
6426     switch (type) {
6427     case 0:
6428         sz = MO_32;
6429         break;
6430     case 1:
6431         sz = MO_64;
6432         break;
6433     case 3:
6434         sz = MO_16;
6435         if (dc_isar_feature(aa64_fp16, s)) {
6436             break;
6437         }
6438         /* fallthru */
6439     default:
6440         unallocated_encoding(s);
6441         return;
6442     }
6443
6444     if (!fp_access_check(s)) {
6445         return;
6446     }
6447
6448     imm = vfp_expand_imm(sz, imm8);
6449
6450     tcg_res = tcg_const_i64(imm);
6451     write_fp_dreg(s, rd, tcg_res);
6452     tcg_temp_free_i64(tcg_res);
6453 }
6454
6455 /* Handle floating point <=> fixed point conversions. Note that we can
6456  * also deal with fp <=> integer conversions as a special case (scale == 64)
6457  * OPTME: consider handling that special case specially or at least skipping
6458  * the call to scalbn in the helpers for zero shifts.
6459  */
6460 static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
6461                            bool itof, int rmode, int scale, int sf, int type)
6462 {
6463     bool is_signed = !(opcode & 1);
6464     TCGv_ptr tcg_fpstatus;
6465     TCGv_i32 tcg_shift, tcg_single;
6466     TCGv_i64 tcg_double;
6467
6468     tcg_fpstatus = get_fpstatus_ptr(type == 3);
6469
6470     tcg_shift = tcg_const_i32(64 - scale);
6471
6472     if (itof) {
6473         TCGv_i64 tcg_int = cpu_reg(s, rn);
6474         if (!sf) {
6475             TCGv_i64 tcg_extend = new_tmp_a64(s);
6476
6477             if (is_signed) {
6478                 tcg_gen_ext32s_i64(tcg_extend, tcg_int);
6479             } else {
6480                 tcg_gen_ext32u_i64(tcg_extend, tcg_int);
6481             }
6482
6483             tcg_int = tcg_extend;
6484         }
6485
6486         switch (type) {
6487         case 1: /* float64 */
6488             tcg_double = tcg_temp_new_i64();
6489             if (is_signed) {
6490                 gen_helper_vfp_sqtod(tcg_double, tcg_int,
6491                                      tcg_shift, tcg_fpstatus);
6492             } else {
6493                 gen_helper_vfp_uqtod(tcg_double, tcg_int,
6494                                      tcg_shift, tcg_fpstatus);
6495             }
6496             write_fp_dreg(s, rd, tcg_double);
6497             tcg_temp_free_i64(tcg_double);
6498             break;
6499
6500         case 0: /* float32 */
6501             tcg_single = tcg_temp_new_i32();
6502             if (is_signed) {
6503                 gen_helper_vfp_sqtos(tcg_single, tcg_int,
6504                                      tcg_shift, tcg_fpstatus);
6505             } else {
6506                 gen_helper_vfp_uqtos(tcg_single, tcg_int,
6507                                      tcg_shift, tcg_fpstatus);
6508             }
6509             write_fp_sreg(s, rd, tcg_single);
6510             tcg_temp_free_i32(tcg_single);
6511             break;
6512
6513         case 3: /* float16 */
6514             tcg_single = tcg_temp_new_i32();
6515             if (is_signed) {
6516                 gen_helper_vfp_sqtoh(tcg_single, tcg_int,
6517                                      tcg_shift, tcg_fpstatus);
6518             } else {
6519                 gen_helper_vfp_uqtoh(tcg_single, tcg_int,
6520                                      tcg_shift, tcg_fpstatus);
6521             }
6522             write_fp_sreg(s, rd, tcg_single);
6523             tcg_temp_free_i32(tcg_single);
6524             break;
6525
6526         default:
6527             g_assert_not_reached();
6528         }
6529     } else {
6530         TCGv_i64 tcg_int = cpu_reg(s, rd);
6531         TCGv_i32 tcg_rmode;
6532
6533         if (extract32(opcode, 2, 1)) {
6534             /* There are too many rounding modes to all fit into rmode,
6535              * so FCVTA[US] is a special case.
6536              */
6537             rmode = FPROUNDING_TIEAWAY;
6538         }
6539
6540         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6541
6542         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
6543
6544         switch (type) {
6545         case 1: /* float64 */
6546             tcg_double = read_fp_dreg(s, rn);
6547             if (is_signed) {
6548                 if (!sf) {
6549                     gen_helper_vfp_tosld(tcg_int, tcg_double,
6550                                          tcg_shift, tcg_fpstatus);
6551                 } else {
6552                     gen_helper_vfp_tosqd(tcg_int, tcg_double,
6553                                          tcg_shift, tcg_fpstatus);
6554                 }
6555             } else {
6556                 if (!sf) {
6557                     gen_helper_vfp_tould(tcg_int, tcg_double,
6558                                          tcg_shift, tcg_fpstatus);
6559                 } else {
6560                     gen_helper_vfp_touqd(tcg_int, tcg_double,
6561                                          tcg_shift, tcg_fpstatus);
6562                 }
6563             }
6564             if (!sf) {
6565                 tcg_gen_ext32u_i64(tcg_int, tcg_int);
6566             }
6567             tcg_temp_free_i64(tcg_double);
6568             break;
6569
6570         case 0: /* float32 */
6571             tcg_single = read_fp_sreg(s, rn);
6572             if (sf) {
6573                 if (is_signed) {
6574                     gen_helper_vfp_tosqs(tcg_int, tcg_single,
6575                                          tcg_shift, tcg_fpstatus);
6576                 } else {
6577                     gen_helper_vfp_touqs(tcg_int, tcg_single,
6578                                          tcg_shift, tcg_fpstatus);
6579                 }
6580             } else {
6581                 TCGv_i32 tcg_dest = tcg_temp_new_i32();
6582                 if (is_signed) {
6583                     gen_helper_vfp_tosls(tcg_dest, tcg_single,
6584                                          tcg_shift, tcg_fpstatus);
6585                 } else {
6586                     gen_helper_vfp_touls(tcg_dest, tcg_single,
6587                                          tcg_shift, tcg_fpstatus);
6588                 }
6589                 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
6590                 tcg_temp_free_i32(tcg_dest);
6591             }
6592             tcg_temp_free_i32(tcg_single);
6593             break;
6594
6595         case 3: /* float16 */
6596             tcg_single = read_fp_sreg(s, rn);
6597             if (sf) {
6598                 if (is_signed) {
6599                     gen_helper_vfp_tosqh(tcg_int, tcg_single,
6600                                          tcg_shift, tcg_fpstatus);
6601                 } else {
6602                     gen_helper_vfp_touqh(tcg_int, tcg_single,
6603                                          tcg_shift, tcg_fpstatus);
6604                 }
6605             } else {
6606                 TCGv_i32 tcg_dest = tcg_temp_new_i32();
6607                 if (is_signed) {
6608                     gen_helper_vfp_toslh(tcg_dest, tcg_single,
6609                                          tcg_shift, tcg_fpstatus);
6610                 } else {
6611                     gen_helper_vfp_toulh(tcg_dest, tcg_single,
6612                                          tcg_shift, tcg_fpstatus);
6613                 }
6614                 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
6615                 tcg_temp_free_i32(tcg_dest);
6616             }
6617             tcg_temp_free_i32(tcg_single);
6618             break;
6619
6620         default:
6621             g_assert_not_reached();
6622         }
6623
6624         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
6625         tcg_temp_free_i32(tcg_rmode);
6626     }
6627
6628     tcg_temp_free_ptr(tcg_fpstatus);
6629     tcg_temp_free_i32(tcg_shift);
6630 }
6631
6632 /* Floating point <-> fixed point conversions
6633  *   31   30  29 28       24 23  22  21 20   19 18    16 15   10 9    5 4    0
6634  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
6635  * | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opcode | scale |  Rn  |  Rd  |
6636  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
6637  */
6638 static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
6639 {
6640     int rd = extract32(insn, 0, 5);
6641     int rn = extract32(insn, 5, 5);
6642     int scale = extract32(insn, 10, 6);
6643     int opcode = extract32(insn, 16, 3);
6644     int rmode = extract32(insn, 19, 2);
6645     int type = extract32(insn, 22, 2);
6646     bool sbit = extract32(insn, 29, 1);
6647     bool sf = extract32(insn, 31, 1);
6648     bool itof;
6649
6650     if (sbit || (!sf && scale < 32)) {
6651         unallocated_encoding(s);
6652         return;
6653     }
6654
6655     switch (type) {
6656     case 0: /* float32 */
6657     case 1: /* float64 */
6658         break;
6659     case 3: /* float16 */
6660         if (dc_isar_feature(aa64_fp16, s)) {
6661             break;
6662         }
6663         /* fallthru */
6664     default:
6665         unallocated_encoding(s);
6666         return;
6667     }
6668
6669     switch ((rmode << 3) | opcode) {
6670     case 0x2: /* SCVTF */
6671     case 0x3: /* UCVTF */
6672         itof = true;
6673         break;
6674     case 0x18: /* FCVTZS */
6675     case 0x19: /* FCVTZU */
6676         itof = false;
6677         break;
6678     default:
6679         unallocated_encoding(s);
6680         return;
6681     }
6682
6683     if (!fp_access_check(s)) {
6684         return;
6685     }
6686
6687     handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
6688 }
6689
6690 static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
6691 {
6692     /* FMOV: gpr to or from float, double, or top half of quad fp reg,
6693      * without conversion.
6694      */
6695
6696     if (itof) {
6697         TCGv_i64 tcg_rn = cpu_reg(s, rn);
6698         TCGv_i64 tmp;
6699
6700         switch (type) {
6701         case 0:
6702             /* 32 bit */
6703             tmp = tcg_temp_new_i64();
6704             tcg_gen_ext32u_i64(tmp, tcg_rn);
6705             write_fp_dreg(s, rd, tmp);
6706             tcg_temp_free_i64(tmp);
6707             break;
6708         case 1:
6709             /* 64 bit */
6710             write_fp_dreg(s, rd, tcg_rn);
6711             break;
6712         case 2:
6713             /* 64 bit to top half. */
6714             tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd));
6715             clear_vec_high(s, true, rd);
6716             break;
6717         case 3:
6718             /* 16 bit */
6719             tmp = tcg_temp_new_i64();
6720             tcg_gen_ext16u_i64(tmp, tcg_rn);
6721             write_fp_dreg(s, rd, tmp);
6722             tcg_temp_free_i64(tmp);
6723             break;
6724         default:
6725             g_assert_not_reached();
6726         }
6727     } else {
6728         TCGv_i64 tcg_rd = cpu_reg(s, rd);
6729
6730         switch (type) {
6731         case 0:
6732             /* 32 bit */
6733             tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_32));
6734             break;
6735         case 1:
6736             /* 64 bit */
6737             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_64));
6738             break;
6739         case 2:
6740             /* 64 bits from top half */
6741             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(s, rn));
6742             break;
6743         case 3:
6744             /* 16 bit */
6745             tcg_gen_ld16u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_16));
6746             break;
6747         default:
6748             g_assert_not_reached();
6749         }
6750     }
6751 }
6752
6753 static void handle_fjcvtzs(DisasContext *s, int rd, int rn)
6754 {
6755     TCGv_i64 t = read_fp_dreg(s, rn);
6756     TCGv_ptr fpstatus = get_fpstatus_ptr(false);
6757
6758     gen_helper_fjcvtzs(t, t, fpstatus);
6759
6760     tcg_temp_free_ptr(fpstatus);
6761
6762     tcg_gen_ext32u_i64(cpu_reg(s, rd), t);
6763     tcg_gen_extrh_i64_i32(cpu_ZF, t);
6764     tcg_gen_movi_i32(cpu_CF, 0);
6765     tcg_gen_movi_i32(cpu_NF, 0);
6766     tcg_gen_movi_i32(cpu_VF, 0);
6767
6768     tcg_temp_free_i64(t);
6769 }
6770
6771 /* Floating point <-> integer conversions
6772  *   31   30  29 28       24 23  22  21 20   19 18 16 15         10 9  5 4  0
6773  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
6774  * | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
6775  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
6776  */
6777 static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
6778 {
6779     int rd = extract32(insn, 0, 5);
6780     int rn = extract32(insn, 5, 5);
6781     int opcode = extract32(insn, 16, 3);
6782     int rmode = extract32(insn, 19, 2);
6783     int type = extract32(insn, 22, 2);
6784     bool sbit = extract32(insn, 29, 1);
6785     bool sf = extract32(insn, 31, 1);
6786     bool itof = false;
6787
6788     if (sbit) {
6789         goto do_unallocated;
6790     }
6791
6792     switch (opcode) {
6793     case 2: /* SCVTF */
6794     case 3: /* UCVTF */
6795         itof = true;
6796         /* fallthru */
6797     case 4: /* FCVTAS */
6798     case 5: /* FCVTAU */
6799         if (rmode != 0) {
6800             goto do_unallocated;
6801         }
6802         /* fallthru */
6803     case 0: /* FCVT[NPMZ]S */
6804     case 1: /* FCVT[NPMZ]U */
6805         switch (type) {
6806         case 0: /* float32 */
6807         case 1: /* float64 */
6808             break;
6809         case 3: /* float16 */
6810             if (!dc_isar_feature(aa64_fp16, s)) {
6811                 goto do_unallocated;
6812             }
6813             break;
6814         default:
6815             goto do_unallocated;
6816         }
6817         if (!fp_access_check(s)) {
6818             return;
6819         }
6820         handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
6821         break;
6822
6823     default:
6824         switch (sf << 7 | type << 5 | rmode << 3 | opcode) {
6825         case 0b01100110: /* FMOV half <-> 32-bit int */
6826         case 0b01100111:
6827         case 0b11100110: /* FMOV half <-> 64-bit int */
6828         case 0b11100111:
6829             if (!dc_isar_feature(aa64_fp16, s)) {
6830                 goto do_unallocated;
6831             }
6832             /* fallthru */
6833         case 0b00000110: /* FMOV 32-bit */
6834         case 0b00000111:
6835         case 0b10100110: /* FMOV 64-bit */
6836         case 0b10100111:
6837         case 0b11001110: /* FMOV top half of 128-bit */
6838         case 0b11001111:
6839             if (!fp_access_check(s)) {
6840                 return;
6841             }
6842             itof = opcode & 1;
6843             handle_fmov(s, rd, rn, type, itof);
6844             break;
6845
6846         case 0b00111110: /* FJCVTZS */
6847             if (!dc_isar_feature(aa64_jscvt, s)) {
6848                 goto do_unallocated;
6849             } else if (fp_access_check(s)) {
6850                 handle_fjcvtzs(s, rd, rn);
6851             }
6852             break;
6853
6854         default:
6855         do_unallocated:
6856             unallocated_encoding(s);
6857             return;
6858         }
6859         break;
6860     }
6861 }
6862
6863 /* FP-specific subcases of table C3-6 (SIMD and FP data processing)
6864  *   31  30  29 28     25 24                          0
6865  * +---+---+---+---------+-----------------------------+
6866  * |   | 0 |   | 1 1 1 1 |                             |
6867  * +---+---+---+---------+-----------------------------+
6868  */
6869 static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
6870 {
6871     if (extract32(insn, 24, 1)) {
6872         /* Floating point data-processing (3 source) */
6873         disas_fp_3src(s, insn);
6874     } else if (extract32(insn, 21, 1) == 0) {
6875         /* Floating point to fixed point conversions */
6876         disas_fp_fixed_conv(s, insn);
6877     } else {
6878         switch (extract32(insn, 10, 2)) {
6879         case 1:
6880             /* Floating point conditional compare */
6881             disas_fp_ccomp(s, insn);
6882             break;
6883         case 2:
6884             /* Floating point data-processing (2 source) */
6885             disas_fp_2src(s, insn);
6886             break;
6887         case 3:
6888             /* Floating point conditional select */
6889             disas_fp_csel(s, insn);
6890             break;
6891         case 0:
6892             switch (ctz32(extract32(insn, 12, 4))) {
6893             case 0: /* [15:12] == xxx1 */
6894                 /* Floating point immediate */
6895                 disas_fp_imm(s, insn);
6896                 break;
6897             case 1: /* [15:12] == xx10 */
6898                 /* Floating point compare */
6899                 disas_fp_compare(s, insn);
6900                 break;
6901             case 2: /* [15:12] == x100 */
6902                 /* Floating point data-processing (1 source) */
6903                 disas_fp_1src(s, insn);
6904                 break;
6905             case 3: /* [15:12] == 1000 */
6906                 unallocated_encoding(s);
6907                 break;
6908             default: /* [15:12] == 0000 */
6909                 /* Floating point <-> integer conversions */
6910                 disas_fp_int_conv(s, insn);
6911                 break;
6912             }
6913             break;
6914         }
6915     }
6916 }
6917
6918 static void do_ext64(DisasContext *s, TCGv_i64 tcg_left, TCGv_i64 tcg_right,
6919                      int pos)
6920 {
6921     /* Extract 64 bits from the middle of two concatenated 64 bit
6922      * vector register slices left:right. The extracted bits start
6923      * at 'pos' bits into the right (least significant) side.
6924      * We return the result in tcg_right, and guarantee not to
6925      * trash tcg_left.
6926      */
6927     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
6928     assert(pos > 0 && pos < 64);
6929
6930     tcg_gen_shri_i64(tcg_right, tcg_right, pos);
6931     tcg_gen_shli_i64(tcg_tmp, tcg_left, 64 - pos);
6932     tcg_gen_or_i64(tcg_right, tcg_right, tcg_tmp);
6933
6934     tcg_temp_free_i64(tcg_tmp);
6935 }
6936
6937 /* EXT
6938  *   31  30 29         24 23 22  21 20  16 15  14  11 10  9    5 4    0
6939  * +---+---+-------------+-----+---+------+---+------+---+------+------+
6940  * | 0 | Q | 1 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | imm4 | 0 |  Rn  |  Rd  |
6941  * +---+---+-------------+-----+---+------+---+------+---+------+------+
6942  */
6943 static void disas_simd_ext(DisasContext *s, uint32_t insn)
6944 {
6945     int is_q = extract32(insn, 30, 1);
6946     int op2 = extract32(insn, 22, 2);
6947     int imm4 = extract32(insn, 11, 4);
6948     int rm = extract32(insn, 16, 5);
6949     int rn = extract32(insn, 5, 5);
6950     int rd = extract32(insn, 0, 5);
6951     int pos = imm4 << 3;
6952     TCGv_i64 tcg_resl, tcg_resh;
6953
6954     if (op2 != 0 || (!is_q && extract32(imm4, 3, 1))) {
6955         unallocated_encoding(s);
6956         return;
6957     }
6958
6959     if (!fp_access_check(s)) {
6960         return;
6961     }
6962
6963     tcg_resh = tcg_temp_new_i64();
6964     tcg_resl = tcg_temp_new_i64();
6965
6966     /* Vd gets bits starting at pos bits into Vm:Vn. This is
6967      * either extracting 128 bits from a 128:128 concatenation, or
6968      * extracting 64 bits from a 64:64 concatenation.
6969      */
6970     if (!is_q) {
6971         read_vec_element(s, tcg_resl, rn, 0, MO_64);
6972         if (pos != 0) {
6973             read_vec_element(s, tcg_resh, rm, 0, MO_64);
6974             do_ext64(s, tcg_resh, tcg_resl, pos);
6975         }
6976         tcg_gen_movi_i64(tcg_resh, 0);
6977     } else {
6978         TCGv_i64 tcg_hh;
6979         typedef struct {
6980             int reg;
6981             int elt;
6982         } EltPosns;
6983         EltPosns eltposns[] = { {rn, 0}, {rn, 1}, {rm, 0}, {rm, 1} };
6984         EltPosns *elt = eltposns;
6985
6986         if (pos >= 64) {
6987             elt++;
6988             pos -= 64;
6989         }
6990
6991         read_vec_element(s, tcg_resl, elt->reg, elt->elt, MO_64);
6992         elt++;
6993         read_vec_element(s, tcg_resh, elt->reg, elt->elt, MO_64);
6994         elt++;
6995         if (pos != 0) {
6996             do_ext64(s, tcg_resh, tcg_resl, pos);
6997             tcg_hh = tcg_temp_new_i64();
6998             read_vec_element(s, tcg_hh, elt->reg, elt->elt, MO_64);
6999             do_ext64(s, tcg_hh, tcg_resh, pos);
7000             tcg_temp_free_i64(tcg_hh);
7001         }
7002     }
7003
7004     write_vec_element(s, tcg_resl, rd, 0, MO_64);
7005     tcg_temp_free_i64(tcg_resl);
7006     write_vec_element(s, tcg_resh, rd, 1, MO_64);
7007     tcg_temp_free_i64(tcg_resh);
7008 }
7009
7010 /* TBL/TBX
7011  *   31  30 29         24 23 22  21 20  16 15  14 13  12  11 10 9    5 4    0
7012  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
7013  * | 0 | Q | 0 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | len | op | 0 0 |  Rn  |  Rd  |
7014  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
7015  */
7016 static void disas_simd_tb(DisasContext *s, uint32_t insn)
7017 {
7018     int op2 = extract32(insn, 22, 2);
7019     int is_q = extract32(insn, 30, 1);
7020     int rm = extract32(insn, 16, 5);
7021     int rn = extract32(insn, 5, 5);
7022     int rd = extract32(insn, 0, 5);
7023     int is_tblx = extract32(insn, 12, 1);
7024     int len = extract32(insn, 13, 2);
7025     TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
7026     TCGv_i32 tcg_regno, tcg_numregs;
7027
7028     if (op2 != 0) {
7029         unallocated_encoding(s);
7030         return;
7031     }
7032
7033     if (!fp_access_check(s)) {
7034         return;
7035     }
7036
7037     /* This does a table lookup: for every byte element in the input
7038      * we index into a table formed from up to four vector registers,
7039      * and then the output is the result of the lookups. Our helper
7040      * function does the lookup operation for a single 64 bit part of
7041      * the input.
7042      */
7043     tcg_resl = tcg_temp_new_i64();
7044     tcg_resh = tcg_temp_new_i64();
7045
7046     if (is_tblx) {
7047         read_vec_element(s, tcg_resl, rd, 0, MO_64);
7048     } else {
7049         tcg_gen_movi_i64(tcg_resl, 0);
7050     }
7051     if (is_tblx && is_q) {
7052         read_vec_element(s, tcg_resh, rd, 1, MO_64);
7053     } else {
7054         tcg_gen_movi_i64(tcg_resh, 0);
7055     }
7056
7057     tcg_idx = tcg_temp_new_i64();
7058     tcg_regno = tcg_const_i32(rn);
7059     tcg_numregs = tcg_const_i32(len + 1);
7060     read_vec_element(s, tcg_idx, rm, 0, MO_64);
7061     gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
7062                         tcg_regno, tcg_numregs);
7063     if (is_q) {
7064         read_vec_element(s, tcg_idx, rm, 1, MO_64);
7065         gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
7066                             tcg_regno, tcg_numregs);
7067     }
7068     tcg_temp_free_i64(tcg_idx);
7069     tcg_temp_free_i32(tcg_regno);
7070     tcg_temp_free_i32(tcg_numregs);
7071
7072     write_vec_element(s, tcg_resl, rd, 0, MO_64);
7073     tcg_temp_free_i64(tcg_resl);
7074     write_vec_element(s, tcg_resh, rd, 1, MO_64);
7075     tcg_temp_free_i64(tcg_resh);
7076 }
7077
7078 /* ZIP/UZP/TRN
7079  *   31  30 29         24 23  22  21 20   16 15 14 12 11 10 9    5 4    0
7080  * +---+---+-------------+------+---+------+---+------------------+------+
7081  * | 0 | Q | 0 0 1 1 1 0 | size | 0 |  Rm  | 0 | opc | 1 0 |  Rn  |  Rd  |
7082  * +---+---+-------------+------+---+------+---+------------------+------+
7083  */
7084 static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
7085 {
7086     int rd = extract32(insn, 0, 5);
7087     int rn = extract32(insn, 5, 5);
7088     int rm = extract32(insn, 16, 5);
7089     int size = extract32(insn, 22, 2);
7090     /* opc field bits [1:0] indicate ZIP/UZP/TRN;
7091      * bit 2 indicates 1 vs 2 variant of the insn.
7092      */
7093     int opcode = extract32(insn, 12, 2);
7094     bool part = extract32(insn, 14, 1);
7095     bool is_q = extract32(insn, 30, 1);
7096     int esize = 8 << size;
7097     int i, ofs;
7098     int datasize = is_q ? 128 : 64;
7099     int elements = datasize / esize;
7100     TCGv_i64 tcg_res, tcg_resl, tcg_resh;
7101
7102     if (opcode == 0 || (size == 3 && !is_q)) {
7103         unallocated_encoding(s);
7104         return;
7105     }
7106
7107     if (!fp_access_check(s)) {
7108         return;
7109     }
7110
7111     tcg_resl = tcg_const_i64(0);
7112     tcg_resh = tcg_const_i64(0);
7113     tcg_res = tcg_temp_new_i64();
7114
7115     for (i = 0; i < elements; i++) {
7116         switch (opcode) {
7117         case 1: /* UZP1/2 */
7118         {
7119             int midpoint = elements / 2;
7120             if (i < midpoint) {
7121                 read_vec_element(s, tcg_res, rn, 2 * i + part, size);
7122             } else {
7123                 read_vec_element(s, tcg_res, rm,
7124                                  2 * (i - midpoint) + part, size);
7125             }
7126             break;
7127         }
7128         case 2: /* TRN1/2 */
7129             if (i & 1) {
7130                 read_vec_element(s, tcg_res, rm, (i & ~1) + part, size);
7131             } else {
7132                 read_vec_element(s, tcg_res, rn, (i & ~1) + part, size);
7133             }
7134             break;
7135         case 3: /* ZIP1/2 */
7136         {
7137             int base = part * elements / 2;
7138             if (i & 1) {
7139                 read_vec_element(s, tcg_res, rm, base + (i >> 1), size);
7140             } else {
7141                 read_vec_element(s, tcg_res, rn, base + (i >> 1), size);
7142             }
7143             break;
7144         }
7145         default:
7146             g_assert_not_reached();
7147         }
7148
7149         ofs = i * esize;
7150         if (ofs < 64) {
7151             tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
7152             tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
7153         } else {
7154             tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
7155             tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
7156         }
7157     }
7158
7159     tcg_temp_free_i64(tcg_res);
7160
7161     write_vec_element(s, tcg_resl, rd, 0, MO_64);
7162     tcg_temp_free_i64(tcg_resl);
7163     write_vec_element(s, tcg_resh, rd, 1, MO_64);
7164     tcg_temp_free_i64(tcg_resh);
7165 }
7166
7167 /*
7168  * do_reduction_op helper
7169  *
7170  * This mirrors the Reduce() pseudocode in the ARM ARM. It is
7171  * important for correct NaN propagation that we do these
7172  * operations in exactly the order specified by the pseudocode.
7173  *
7174  * This is a recursive function, TCG temps should be freed by the
7175  * calling function once it is done with the values.
7176  */
7177 static TCGv_i32 do_reduction_op(DisasContext *s, int fpopcode, int rn,
7178                                 int esize, int size, int vmap, TCGv_ptr fpst)
7179 {
7180     if (esize == size) {
7181         int element;
7182         TCGMemOp msize = esize == 16 ? MO_16 : MO_32;
7183         TCGv_i32 tcg_elem;
7184
7185         /* We should have one register left here */
7186         assert(ctpop8(vmap) == 1);
7187         element = ctz32(vmap);
7188         assert(element < 8);
7189
7190         tcg_elem = tcg_temp_new_i32();
7191         read_vec_element_i32(s, tcg_elem, rn, element, msize);
7192         return tcg_elem;
7193     } else {
7194         int bits = size / 2;
7195         int shift = ctpop8(vmap) / 2;
7196         int vmap_lo = (vmap >> shift) & vmap;
7197         int vmap_hi = (vmap & ~vmap_lo);
7198         TCGv_i32 tcg_hi, tcg_lo, tcg_res;
7199
7200         tcg_hi = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_hi, fpst);
7201         tcg_lo = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_lo, fpst);
7202         tcg_res = tcg_temp_new_i32();
7203
7204         switch (fpopcode) {
7205         case 0x0c: /* fmaxnmv half-precision */
7206             gen_helper_advsimd_maxnumh(tcg_res, tcg_lo, tcg_hi, fpst);
7207             break;
7208         case 0x0f: /* fmaxv half-precision */
7209             gen_helper_advsimd_maxh(tcg_res, tcg_lo, tcg_hi, fpst);
7210             break;
7211         case 0x1c: /* fminnmv half-precision */
7212             gen_helper_advsimd_minnumh(tcg_res, tcg_lo, tcg_hi, fpst);
7213             break;
7214         case 0x1f: /* fminv half-precision */
7215             gen_helper_advsimd_minh(tcg_res, tcg_lo, tcg_hi, fpst);
7216             break;
7217         case 0x2c: /* fmaxnmv */
7218             gen_helper_vfp_maxnums(tcg_res, tcg_lo, tcg_hi, fpst);
7219             break;
7220         case 0x2f: /* fmaxv */
7221             gen_helper_vfp_maxs(tcg_res, tcg_lo, tcg_hi, fpst);
7222             break;
7223         case 0x3c: /* fminnmv */
7224             gen_helper_vfp_minnums(tcg_res, tcg_lo, tcg_hi, fpst);
7225             break;
7226         case 0x3f: /* fminv */
7227             gen_helper_vfp_mins(tcg_res, tcg_lo, tcg_hi, fpst);
7228             break;
7229         default:
7230             g_assert_not_reached();
7231         }
7232
7233         tcg_temp_free_i32(tcg_hi);
7234         tcg_temp_free_i32(tcg_lo);
7235         return tcg_res;
7236     }
7237 }
7238
7239 /* AdvSIMD across lanes
7240  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
7241  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
7242  * | 0 | Q | U | 0 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
7243  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
7244  */
7245 static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
7246 {
7247     int rd = extract32(insn, 0, 5);
7248     int rn = extract32(insn, 5, 5);
7249     int size = extract32(insn, 22, 2);
7250     int opcode = extract32(insn, 12, 5);
7251     bool is_q = extract32(insn, 30, 1);
7252     bool is_u = extract32(insn, 29, 1);
7253     bool is_fp = false;
7254     bool is_min = false;
7255     int esize;
7256     int elements;
7257     int i;
7258     TCGv_i64 tcg_res, tcg_elt;
7259
7260     switch (opcode) {
7261     case 0x1b: /* ADDV */
7262         if (is_u) {
7263             unallocated_encoding(s);
7264             return;
7265         }
7266         /* fall through */
7267     case 0x3: /* SADDLV, UADDLV */
7268     case 0xa: /* SMAXV, UMAXV */
7269     case 0x1a: /* SMINV, UMINV */
7270         if (size == 3 || (size == 2 && !is_q)) {
7271             unallocated_encoding(s);
7272             return;
7273         }
7274         break;
7275     case 0xc: /* FMAXNMV, FMINNMV */
7276     case 0xf: /* FMAXV, FMINV */
7277         /* Bit 1 of size field encodes min vs max and the actual size
7278          * depends on the encoding of the U bit. If not set (and FP16
7279          * enabled) then we do half-precision float instead of single
7280          * precision.
7281          */
7282         is_min = extract32(size, 1, 1);
7283         is_fp = true;
7284         if (!is_u && dc_isar_feature(aa64_fp16, s)) {
7285             size = 1;
7286         } else if (!is_u || !is_q || extract32(size, 0, 1)) {
7287             unallocated_encoding(s);
7288             return;
7289         } else {
7290             size = 2;
7291         }
7292         break;
7293     default:
7294         unallocated_encoding(s);
7295         return;
7296     }
7297
7298     if (!fp_access_check(s)) {
7299         return;
7300     }
7301
7302     esize = 8 << size;
7303     elements = (is_q ? 128 : 64) / esize;
7304
7305     tcg_res = tcg_temp_new_i64();
7306     tcg_elt = tcg_temp_new_i64();
7307
7308     /* These instructions operate across all lanes of a vector
7309      * to produce a single result. We can guarantee that a 64
7310      * bit intermediate is sufficient:
7311      *  + for [US]ADDLV the maximum element size is 32 bits, and
7312      *    the result type is 64 bits
7313      *  + for FMAX*V, FMIN*V, ADDV the intermediate type is the
7314      *    same as the element size, which is 32 bits at most
7315      * For the integer operations we can choose to work at 64
7316      * or 32 bits and truncate at the end; for simplicity
7317      * we use 64 bits always. The floating point
7318      * ops do require 32 bit intermediates, though.
7319      */
7320     if (!is_fp) {
7321         read_vec_element(s, tcg_res, rn, 0, size | (is_u ? 0 : MO_SIGN));
7322
7323         for (i = 1; i < elements; i++) {
7324             read_vec_element(s, tcg_elt, rn, i, size | (is_u ? 0 : MO_SIGN));
7325
7326             switch (opcode) {
7327             case 0x03: /* SADDLV / UADDLV */
7328             case 0x1b: /* ADDV */
7329                 tcg_gen_add_i64(tcg_res, tcg_res, tcg_elt);
7330                 break;
7331             case 0x0a: /* SMAXV / UMAXV */
7332                 if (is_u) {
7333                     tcg_gen_umax_i64(tcg_res, tcg_res, tcg_elt);
7334                 } else {
7335                     tcg_gen_smax_i64(tcg_res, tcg_res, tcg_elt);
7336                 }
7337                 break;
7338             case 0x1a: /* SMINV / UMINV */
7339                 if (is_u) {
7340                     tcg_gen_umin_i64(tcg_res, tcg_res, tcg_elt);
7341                 } else {
7342                     tcg_gen_smin_i64(tcg_res, tcg_res, tcg_elt);
7343                 }
7344                 break;
7345             default:
7346                 g_assert_not_reached();
7347             }
7348
7349         }
7350     } else {
7351         /* Floating point vector reduction ops which work across 32
7352          * bit (single) or 16 bit (half-precision) intermediates.
7353          * Note that correct NaN propagation requires that we do these
7354          * operations in exactly the order specified by the pseudocode.
7355          */
7356         TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
7357         int fpopcode = opcode | is_min << 4 | is_u << 5;
7358         int vmap = (1 << elements) - 1;
7359         TCGv_i32 tcg_res32 = do_reduction_op(s, fpopcode, rn, esize,
7360                                              (is_q ? 128 : 64), vmap, fpst);
7361         tcg_gen_extu_i32_i64(tcg_res, tcg_res32);
7362         tcg_temp_free_i32(tcg_res32);
7363         tcg_temp_free_ptr(fpst);
7364     }
7365
7366     tcg_temp_free_i64(tcg_elt);
7367
7368     /* Now truncate the result to the width required for the final output */
7369     if (opcode == 0x03) {
7370         /* SADDLV, UADDLV: result is 2*esize */
7371         size++;
7372     }
7373
7374     switch (size) {
7375     case 0:
7376         tcg_gen_ext8u_i64(tcg_res, tcg_res);
7377         break;
7378     case 1:
7379         tcg_gen_ext16u_i64(tcg_res, tcg_res);
7380         break;
7381     case 2:
7382         tcg_gen_ext32u_i64(tcg_res, tcg_res);
7383         break;
7384     case 3:
7385         break;
7386     default:
7387         g_assert_not_reached();
7388     }
7389
7390     write_fp_dreg(s, rd, tcg_res);
7391     tcg_temp_free_i64(tcg_res);
7392 }
7393
7394 /* DUP (Element, Vector)
7395  *
7396  *  31  30   29              21 20    16 15        10  9    5 4    0
7397  * +---+---+-------------------+--------+-------------+------+------+
7398  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
7399  * +---+---+-------------------+--------+-------------+------+------+
7400  *
7401  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7402  */
7403 static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
7404                              int imm5)
7405 {
7406     int size = ctz32(imm5);
7407     int index = imm5 >> (size + 1);
7408
7409     if (size > 3 || (size == 3 && !is_q)) {
7410         unallocated_encoding(s);
7411         return;
7412     }
7413
7414     if (!fp_access_check(s)) {
7415         return;
7416     }
7417
7418     tcg_gen_gvec_dup_mem(size, vec_full_reg_offset(s, rd),
7419                          vec_reg_offset(s, rn, index, size),
7420                          is_q ? 16 : 8, vec_full_reg_size(s));
7421 }
7422
7423 /* DUP (element, scalar)
7424  *  31                   21 20    16 15        10  9    5 4    0
7425  * +-----------------------+--------+-------------+------+------+
7426  * | 0 1 0 1 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
7427  * +-----------------------+--------+-------------+------+------+
7428  */
7429 static void handle_simd_dupes(DisasContext *s, int rd, int rn,
7430                               int imm5)
7431 {
7432     int size = ctz32(imm5);
7433     int index;
7434     TCGv_i64 tmp;
7435
7436     if (size > 3) {
7437         unallocated_encoding(s);
7438         return;
7439     }
7440
7441     if (!fp_access_check(s)) {
7442         return;
7443     }
7444
7445     index = imm5 >> (size + 1);
7446
7447     /* This instruction just extracts the specified element and
7448      * zero-extends it into the bottom of the destination register.
7449      */
7450     tmp = tcg_temp_new_i64();
7451     read_vec_element(s, tmp, rn, index, size);
7452     write_fp_dreg(s, rd, tmp);
7453     tcg_temp_free_i64(tmp);
7454 }
7455
7456 /* DUP (General)
7457  *
7458  *  31  30   29              21 20    16 15        10  9    5 4    0
7459  * +---+---+-------------------+--------+-------------+------+------+
7460  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 1 1 |  Rn  |  Rd  |
7461  * +---+---+-------------------+--------+-------------+------+------+
7462  *
7463  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7464  */
7465 static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn,
7466                              int imm5)
7467 {
7468     int size = ctz32(imm5);
7469     uint32_t dofs, oprsz, maxsz;
7470
7471     if (size > 3 || ((size == 3) && !is_q)) {
7472         unallocated_encoding(s);
7473         return;
7474     }
7475
7476     if (!fp_access_check(s)) {
7477         return;
7478     }
7479
7480     dofs = vec_full_reg_offset(s, rd);
7481     oprsz = is_q ? 16 : 8;
7482     maxsz = vec_full_reg_size(s);
7483
7484     tcg_gen_gvec_dup_i64(size, dofs, oprsz, maxsz, cpu_reg(s, rn));
7485 }
7486
7487 /* INS (Element)
7488  *
7489  *  31                   21 20    16 15  14    11  10 9    5 4    0
7490  * +-----------------------+--------+------------+---+------+------+
7491  * | 0 1 1 0 1 1 1 0 0 0 0 |  imm5  | 0 |  imm4  | 1 |  Rn  |  Rd  |
7492  * +-----------------------+--------+------------+---+------+------+
7493  *
7494  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7495  * index: encoded in imm5<4:size+1>
7496  */
7497 static void handle_simd_inse(DisasContext *s, int rd, int rn,
7498                              int imm4, int imm5)
7499 {
7500     int size = ctz32(imm5);
7501     int src_index, dst_index;
7502     TCGv_i64 tmp;
7503
7504     if (size > 3) {
7505         unallocated_encoding(s);
7506         return;
7507     }
7508
7509     if (!fp_access_check(s)) {
7510         return;
7511     }
7512
7513     dst_index = extract32(imm5, 1+size, 5);
7514     src_index = extract32(imm4, size, 4);
7515
7516     tmp = tcg_temp_new_i64();
7517
7518     read_vec_element(s, tmp, rn, src_index, size);
7519     write_vec_element(s, tmp, rd, dst_index, size);
7520
7521     tcg_temp_free_i64(tmp);
7522 }
7523
7524
7525 /* INS (General)
7526  *
7527  *  31                   21 20    16 15        10  9    5 4    0
7528  * +-----------------------+--------+-------------+------+------+
7529  * | 0 1 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 1 1 1 |  Rn  |  Rd  |
7530  * +-----------------------+--------+-------------+------+------+
7531  *
7532  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7533  * index: encoded in imm5<4:size+1>
7534  */
7535 static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
7536 {
7537     int size = ctz32(imm5);
7538     int idx;
7539
7540     if (size > 3) {
7541         unallocated_encoding(s);
7542         return;
7543     }
7544
7545     if (!fp_access_check(s)) {
7546         return;
7547     }
7548
7549     idx = extract32(imm5, 1 + size, 4 - size);
7550     write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
7551 }
7552
7553 /*
7554  * UMOV (General)
7555  * SMOV (General)
7556  *
7557  *  31  30   29              21 20    16 15    12   10 9    5 4    0
7558  * +---+---+-------------------+--------+-------------+------+------+
7559  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 1 U 1 1 |  Rn  |  Rd  |
7560  * +---+---+-------------------+--------+-------------+------+------+
7561  *
7562  * U: unsigned when set
7563  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7564  */
7565 static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed,
7566                                   int rn, int rd, int imm5)
7567 {
7568     int size = ctz32(imm5);
7569     int element;
7570     TCGv_i64 tcg_rd;
7571
7572     /* Check for UnallocatedEncodings */
7573     if (is_signed) {
7574         if (size > 2 || (size == 2 && !is_q)) {
7575             unallocated_encoding(s);
7576             return;
7577         }
7578     } else {
7579         if (size > 3
7580             || (size < 3 && is_q)
7581             || (size == 3 && !is_q)) {
7582             unallocated_encoding(s);
7583             return;
7584         }
7585     }
7586
7587     if (!fp_access_check(s)) {
7588         return;
7589     }
7590
7591     element = extract32(imm5, 1+size, 4);
7592
7593     tcg_rd = cpu_reg(s, rd);
7594     read_vec_element(s, tcg_rd, rn, element, size | (is_signed ? MO_SIGN : 0));
7595     if (is_signed && !is_q) {
7596         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
7597     }
7598 }
7599
7600 /* AdvSIMD copy
7601  *   31  30  29  28             21 20  16 15  14  11 10  9    5 4    0
7602  * +---+---+----+-----------------+------+---+------+---+------+------+
7603  * | 0 | Q | op | 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
7604  * +---+---+----+-----------------+------+---+------+---+------+------+
7605  */
7606 static void disas_simd_copy(DisasContext *s, uint32_t insn)
7607 {
7608     int rd = extract32(insn, 0, 5);
7609     int rn = extract32(insn, 5, 5);
7610     int imm4 = extract32(insn, 11, 4);
7611     int op = extract32(insn, 29, 1);
7612     int is_q = extract32(insn, 30, 1);
7613     int imm5 = extract32(insn, 16, 5);
7614
7615     if (op) {
7616         if (is_q) {
7617             /* INS (element) */
7618             handle_simd_inse(s, rd, rn, imm4, imm5);
7619         } else {
7620             unallocated_encoding(s);
7621         }
7622     } else {
7623         switch (imm4) {
7624         case 0:
7625             /* DUP (element - vector) */
7626             handle_simd_dupe(s, is_q, rd, rn, imm5);
7627             break;
7628         case 1:
7629             /* DUP (general) */
7630             handle_simd_dupg(s, is_q, rd, rn, imm5);
7631             break;
7632         case 3:
7633             if (is_q) {
7634                 /* INS (general) */
7635                 handle_simd_insg(s, rd, rn, imm5);
7636             } else {
7637                 unallocated_encoding(s);
7638             }
7639             break;
7640         case 5:
7641         case 7:
7642             /* UMOV/SMOV (is_q indicates 32/64; imm4 indicates signedness) */
7643             handle_simd_umov_smov(s, is_q, (imm4 == 5), rn, rd, imm5);
7644             break;
7645         default:
7646             unallocated_encoding(s);
7647             break;
7648         }
7649     }
7650 }
7651
7652 /* AdvSIMD modified immediate
7653  *  31  30   29  28                 19 18 16 15   12  11  10  9     5 4    0
7654  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
7655  * | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh |  Rd  |
7656  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
7657  *
7658  * There are a number of operations that can be carried out here:
7659  *   MOVI - move (shifted) imm into register
7660  *   MVNI - move inverted (shifted) imm into register
7661  *   ORR  - bitwise OR of (shifted) imm with register
7662  *   BIC  - bitwise clear of (shifted) imm with register
7663  * With ARMv8.2 we also have:
7664  *   FMOV half-precision
7665  */
7666 static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
7667 {
7668     int rd = extract32(insn, 0, 5);
7669     int cmode = extract32(insn, 12, 4);
7670     int cmode_3_1 = extract32(cmode, 1, 3);
7671     int cmode_0 = extract32(cmode, 0, 1);
7672     int o2 = extract32(insn, 11, 1);
7673     uint64_t abcdefgh = extract32(insn, 5, 5) | (extract32(insn, 16, 3) << 5);
7674     bool is_neg = extract32(insn, 29, 1);
7675     bool is_q = extract32(insn, 30, 1);
7676     uint64_t imm = 0;
7677
7678     if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {
7679         /* Check for FMOV (vector, immediate) - half-precision */
7680         if (!(dc_isar_feature(aa64_fp16, s) && o2 && cmode == 0xf)) {
7681             unallocated_encoding(s);
7682             return;
7683         }
7684     }
7685
7686     if (!fp_access_check(s)) {
7687         return;
7688     }
7689
7690     /* See AdvSIMDExpandImm() in ARM ARM */
7691     switch (cmode_3_1) {
7692     case 0: /* Replicate(Zeros(24):imm8, 2) */
7693     case 1: /* Replicate(Zeros(16):imm8:Zeros(8), 2) */
7694     case 2: /* Replicate(Zeros(8):imm8:Zeros(16), 2) */
7695     case 3: /* Replicate(imm8:Zeros(24), 2) */
7696     {
7697         int shift = cmode_3_1 * 8;
7698         imm = bitfield_replicate(abcdefgh << shift, 32);
7699         break;
7700     }
7701     case 4: /* Replicate(Zeros(8):imm8, 4) */
7702     case 5: /* Replicate(imm8:Zeros(8), 4) */
7703     {
7704         int shift = (cmode_3_1 & 0x1) * 8;
7705         imm = bitfield_replicate(abcdefgh << shift, 16);
7706         break;
7707     }
7708     case 6:
7709         if (cmode_0) {
7710             /* Replicate(Zeros(8):imm8:Ones(16), 2) */
7711             imm = (abcdefgh << 16) | 0xffff;
7712         } else {
7713             /* Replicate(Zeros(16):imm8:Ones(8), 2) */
7714             imm = (abcdefgh << 8) | 0xff;
7715         }
7716         imm = bitfield_replicate(imm, 32);
7717         break;
7718     case 7:
7719         if (!cmode_0 && !is_neg) {
7720             imm = bitfield_replicate(abcdefgh, 8);
7721         } else if (!cmode_0 && is_neg) {
7722             int i;
7723             imm = 0;
7724             for (i = 0; i < 8; i++) {
7725                 if ((abcdefgh) & (1 << i)) {
7726                     imm |= 0xffULL << (i * 8);
7727                 }
7728             }
7729         } else if (cmode_0) {
7730             if (is_neg) {
7731                 imm = (abcdefgh & 0x3f) << 48;
7732                 if (abcdefgh & 0x80) {
7733                     imm |= 0x8000000000000000ULL;
7734                 }
7735                 if (abcdefgh & 0x40) {
7736                     imm |= 0x3fc0000000000000ULL;
7737                 } else {
7738                     imm |= 0x4000000000000000ULL;
7739                 }
7740             } else {
7741                 if (o2) {
7742                     /* FMOV (vector, immediate) - half-precision */
7743                     imm = vfp_expand_imm(MO_16, abcdefgh);
7744                     /* now duplicate across the lanes */
7745                     imm = bitfield_replicate(imm, 16);
7746                 } else {
7747                     imm = (abcdefgh & 0x3f) << 19;
7748                     if (abcdefgh & 0x80) {
7749                         imm |= 0x80000000;
7750                     }
7751                     if (abcdefgh & 0x40) {
7752                         imm |= 0x3e000000;
7753                     } else {
7754                         imm |= 0x40000000;
7755                     }
7756                     imm |= (imm << 32);
7757                 }
7758             }
7759         }
7760         break;
7761     default:
7762         fprintf(stderr, "%s: cmode_3_1: %x\n", __func__, cmode_3_1);
7763         g_assert_not_reached();
7764     }
7765
7766     if (cmode_3_1 != 7 && is_neg) {
7767         imm = ~imm;
7768     }
7769
7770     if (!((cmode & 0x9) == 0x1 || (cmode & 0xd) == 0x9)) {
7771         /* MOVI or MVNI, with MVNI negation handled above.  */
7772         tcg_gen_gvec_dup64i(vec_full_reg_offset(s, rd), is_q ? 16 : 8,
7773                             vec_full_reg_size(s), imm);
7774     } else {
7775         /* ORR or BIC, with BIC negation to AND handled above.  */
7776         if (is_neg) {
7777             gen_gvec_fn2i(s, is_q, rd, rd, imm, tcg_gen_gvec_andi, MO_64);
7778         } else {
7779             gen_gvec_fn2i(s, is_q, rd, rd, imm, tcg_gen_gvec_ori, MO_64);
7780         }
7781     }
7782 }
7783
7784 /* AdvSIMD scalar copy
7785  *  31 30  29  28             21 20  16 15  14  11 10  9    5 4    0
7786  * +-----+----+-----------------+------+---+------+---+------+------+
7787  * | 0 1 | op | 1 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
7788  * +-----+----+-----------------+------+---+------+---+------+------+
7789  */
7790 static void disas_simd_scalar_copy(DisasContext *s, uint32_t insn)
7791 {
7792     int rd = extract32(insn, 0, 5);
7793     int rn = extract32(insn, 5, 5);
7794     int imm4 = extract32(insn, 11, 4);
7795     int imm5 = extract32(insn, 16, 5);
7796     int op = extract32(insn, 29, 1);
7797
7798     if (op != 0 || imm4 != 0) {
7799         unallocated_encoding(s);
7800         return;
7801     }
7802
7803     /* DUP (element, scalar) */
7804     handle_simd_dupes(s, rd, rn, imm5);
7805 }
7806
7807 /* AdvSIMD scalar pairwise
7808  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
7809  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7810  * | 0 1 | U | 1 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
7811  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7812  */
7813 static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
7814 {
7815     int u = extract32(insn, 29, 1);
7816     int size = extract32(insn, 22, 2);
7817     int opcode = extract32(insn, 12, 5);
7818     int rn = extract32(insn, 5, 5);
7819     int rd = extract32(insn, 0, 5);
7820     TCGv_ptr fpst;
7821
7822     /* For some ops (the FP ones), size[1] is part of the encoding.
7823      * For ADDP strictly it is not but size[1] is always 1 for valid
7824      * encodings.
7825      */
7826     opcode |= (extract32(size, 1, 1) << 5);
7827
7828     switch (opcode) {
7829     case 0x3b: /* ADDP */
7830         if (u || size != 3) {
7831             unallocated_encoding(s);
7832             return;
7833         }
7834         if (!fp_access_check(s)) {
7835             return;
7836         }
7837
7838         fpst = NULL;
7839         break;
7840     case 0xc: /* FMAXNMP */
7841     case 0xd: /* FADDP */
7842     case 0xf: /* FMAXP */
7843     case 0x2c: /* FMINNMP */
7844     case 0x2f: /* FMINP */
7845         /* FP op, size[0] is 32 or 64 bit*/
7846         if (!u) {
7847             if (!dc_isar_feature(aa64_fp16, s)) {
7848                 unallocated_encoding(s);
7849                 return;
7850             } else {
7851                 size = MO_16;
7852             }
7853         } else {
7854             size = extract32(size, 0, 1) ? MO_64 : MO_32;
7855         }
7856
7857         if (!fp_access_check(s)) {
7858             return;
7859         }
7860
7861         fpst = get_fpstatus_ptr(size == MO_16);
7862         break;
7863     default:
7864         unallocated_encoding(s);
7865         return;
7866     }
7867
7868     if (size == MO_64) {
7869         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
7870         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
7871         TCGv_i64 tcg_res = tcg_temp_new_i64();
7872
7873         read_vec_element(s, tcg_op1, rn, 0, MO_64);
7874         read_vec_element(s, tcg_op2, rn, 1, MO_64);
7875
7876         switch (opcode) {
7877         case 0x3b: /* ADDP */
7878             tcg_gen_add_i64(tcg_res, tcg_op1, tcg_op2);
7879             break;
7880         case 0xc: /* FMAXNMP */
7881             gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
7882             break;
7883         case 0xd: /* FADDP */
7884             gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
7885             break;
7886         case 0xf: /* FMAXP */
7887             gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
7888             break;
7889         case 0x2c: /* FMINNMP */
7890             gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
7891             break;
7892         case 0x2f: /* FMINP */
7893             gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
7894             break;
7895         default:
7896             g_assert_not_reached();
7897         }
7898
7899         write_fp_dreg(s, rd, tcg_res);
7900
7901         tcg_temp_free_i64(tcg_op1);
7902         tcg_temp_free_i64(tcg_op2);
7903         tcg_temp_free_i64(tcg_res);
7904     } else {
7905         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
7906         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
7907         TCGv_i32 tcg_res = tcg_temp_new_i32();
7908
7909         read_vec_element_i32(s, tcg_op1, rn, 0, size);
7910         read_vec_element_i32(s, tcg_op2, rn, 1, size);
7911
7912         if (size == MO_16) {
7913             switch (opcode) {
7914             case 0xc: /* FMAXNMP */
7915                 gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
7916                 break;
7917             case 0xd: /* FADDP */
7918                 gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
7919                 break;
7920             case 0xf: /* FMAXP */
7921                 gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
7922                 break;
7923             case 0x2c: /* FMINNMP */
7924                 gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
7925                 break;
7926             case 0x2f: /* FMINP */
7927                 gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
7928                 break;
7929             default:
7930                 g_assert_not_reached();
7931             }
7932         } else {
7933             switch (opcode) {
7934             case 0xc: /* FMAXNMP */
7935                 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
7936                 break;
7937             case 0xd: /* FADDP */
7938                 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
7939                 break;
7940             case 0xf: /* FMAXP */
7941                 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
7942                 break;
7943             case 0x2c: /* FMINNMP */
7944                 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
7945                 break;
7946             case 0x2f: /* FMINP */
7947                 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
7948                 break;
7949             default:
7950                 g_assert_not_reached();
7951             }
7952         }
7953
7954         write_fp_sreg(s, rd, tcg_res);
7955
7956         tcg_temp_free_i32(tcg_op1);
7957         tcg_temp_free_i32(tcg_op2);
7958         tcg_temp_free_i32(tcg_res);
7959     }
7960
7961     if (fpst) {
7962         tcg_temp_free_ptr(fpst);
7963     }
7964 }
7965
7966 /*
7967  * Common SSHR[RA]/USHR[RA] - Shift right (optional rounding/accumulate)
7968  *
7969  * This code is handles the common shifting code and is used by both
7970  * the vector and scalar code.
7971  */
7972 static void handle_shri_with_rndacc(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
7973                                     TCGv_i64 tcg_rnd, bool accumulate,
7974                                     bool is_u, int size, int shift)
7975 {
7976     bool extended_result = false;
7977     bool round = tcg_rnd != NULL;
7978     int ext_lshift = 0;
7979     TCGv_i64 tcg_src_hi;
7980
7981     if (round && size == 3) {
7982         extended_result = true;
7983         ext_lshift = 64 - shift;
7984         tcg_src_hi = tcg_temp_new_i64();
7985     } else if (shift == 64) {
7986         if (!accumulate && is_u) {
7987             /* result is zero */
7988             tcg_gen_movi_i64(tcg_res, 0);
7989             return;
7990         }
7991     }
7992
7993     /* Deal with the rounding step */
7994     if (round) {
7995         if (extended_result) {
7996             TCGv_i64 tcg_zero = tcg_const_i64(0);
7997             if (!is_u) {
7998                 /* take care of sign extending tcg_res */
7999                 tcg_gen_sari_i64(tcg_src_hi, tcg_src, 63);
8000                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
8001                                  tcg_src, tcg_src_hi,
8002                                  tcg_rnd, tcg_zero);
8003             } else {
8004                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
8005                                  tcg_src, tcg_zero,
8006                                  tcg_rnd, tcg_zero);
8007             }
8008             tcg_temp_free_i64(tcg_zero);
8009         } else {
8010             tcg_gen_add_i64(tcg_src, tcg_src, tcg_rnd);
8011         }
8012     }
8013
8014     /* Now do the shift right */
8015     if (round && extended_result) {
8016         /* extended case, >64 bit precision required */
8017         if (ext_lshift == 0) {
8018             /* special case, only high bits matter */
8019             tcg_gen_mov_i64(tcg_src, tcg_src_hi);
8020         } else {
8021             tcg_gen_shri_i64(tcg_src, tcg_src, shift);
8022             tcg_gen_shli_i64(tcg_src_hi, tcg_src_hi, ext_lshift);
8023             tcg_gen_or_i64(tcg_src, tcg_src, tcg_src_hi);
8024         }
8025     } else {
8026         if (is_u) {
8027             if (shift == 64) {
8028                 /* essentially shifting in 64 zeros */
8029                 tcg_gen_movi_i64(tcg_src, 0);
8030             } else {
8031                 tcg_gen_shri_i64(tcg_src, tcg_src, shift);
8032             }
8033         } else {
8034             if (shift == 64) {
8035                 /* effectively extending the sign-bit */
8036                 tcg_gen_sari_i64(tcg_src, tcg_src, 63);
8037             } else {
8038                 tcg_gen_sari_i64(tcg_src, tcg_src, shift);
8039             }
8040         }
8041     }
8042
8043     if (accumulate) {
8044         tcg_gen_add_i64(tcg_res, tcg_res, tcg_src);
8045     } else {
8046         tcg_gen_mov_i64(tcg_res, tcg_src);
8047     }
8048
8049     if (extended_result) {
8050         tcg_temp_free_i64(tcg_src_hi);
8051     }
8052 }
8053
8054 /* SSHR[RA]/USHR[RA] - Scalar shift right (optional rounding/accumulate) */
8055 static void handle_scalar_simd_shri(DisasContext *s,
8056                                     bool is_u, int immh, int immb,
8057                                     int opcode, int rn, int rd)
8058 {
8059     const int size = 3;
8060     int immhb = immh << 3 | immb;
8061     int shift = 2 * (8 << size) - immhb;
8062     bool accumulate = false;
8063     bool round = false;
8064     bool insert = false;
8065     TCGv_i64 tcg_rn;
8066     TCGv_i64 tcg_rd;
8067     TCGv_i64 tcg_round;
8068
8069     if (!extract32(immh, 3, 1)) {
8070         unallocated_encoding(s);
8071         return;
8072     }
8073
8074     if (!fp_access_check(s)) {
8075         return;
8076     }
8077
8078     switch (opcode) {
8079     case 0x02: /* SSRA / USRA (accumulate) */
8080         accumulate = true;
8081         break;
8082     case 0x04: /* SRSHR / URSHR (rounding) */
8083         round = true;
8084         break;
8085     case 0x06: /* SRSRA / URSRA (accum + rounding) */
8086         accumulate = round = true;
8087         break;
8088     case 0x08: /* SRI */
8089         insert = true;
8090         break;
8091     }
8092
8093     if (round) {
8094         uint64_t round_const = 1ULL << (shift - 1);
8095         tcg_round = tcg_const_i64(round_const);
8096     } else {
8097         tcg_round = NULL;
8098     }
8099
8100     tcg_rn = read_fp_dreg(s, rn);
8101     tcg_rd = (accumulate || insert) ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
8102
8103     if (insert) {
8104         /* shift count same as element size is valid but does nothing;
8105          * special case to avoid potential shift by 64.
8106          */
8107         int esize = 8 << size;
8108         if (shift != esize) {
8109             tcg_gen_shri_i64(tcg_rn, tcg_rn, shift);
8110             tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, 0, esize - shift);
8111         }
8112     } else {
8113         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
8114                                 accumulate, is_u, size, shift);
8115     }
8116
8117     write_fp_dreg(s, rd, tcg_rd);
8118
8119     tcg_temp_free_i64(tcg_rn);
8120     tcg_temp_free_i64(tcg_rd);
8121     if (round) {
8122         tcg_temp_free_i64(tcg_round);
8123     }
8124 }
8125
8126 /* SHL/SLI - Scalar shift left */
8127 static void handle_scalar_simd_shli(DisasContext *s, bool insert,
8128                                     int immh, int immb, int opcode,
8129                                     int rn, int rd)
8130 {
8131     int size = 32 - clz32(immh) - 1;
8132     int immhb = immh << 3 | immb;
8133     int shift = immhb - (8 << size);
8134     TCGv_i64 tcg_rn = new_tmp_a64(s);
8135     TCGv_i64 tcg_rd = new_tmp_a64(s);
8136
8137     if (!extract32(immh, 3, 1)) {
8138         unallocated_encoding(s);
8139         return;
8140     }
8141
8142     if (!fp_access_check(s)) {
8143         return;
8144     }
8145
8146     tcg_rn = read_fp_dreg(s, rn);
8147     tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
8148
8149     if (insert) {
8150         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, shift, 64 - shift);
8151     } else {
8152         tcg_gen_shli_i64(tcg_rd, tcg_rn, shift);
8153     }
8154
8155     write_fp_dreg(s, rd, tcg_rd);
8156
8157     tcg_temp_free_i64(tcg_rn);
8158     tcg_temp_free_i64(tcg_rd);
8159 }
8160
8161 /* SQSHRN/SQSHRUN - Saturating (signed/unsigned) shift right with
8162  * (signed/unsigned) narrowing */
8163 static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
8164                                    bool is_u_shift, bool is_u_narrow,
8165                                    int immh, int immb, int opcode,
8166                                    int rn, int rd)
8167 {
8168     int immhb = immh << 3 | immb;
8169     int size = 32 - clz32(immh) - 1;
8170     int esize = 8 << size;
8171     int shift = (2 * esize) - immhb;
8172     int elements = is_scalar ? 1 : (64 / esize);
8173     bool round = extract32(opcode, 0, 1);
8174     TCGMemOp ldop = (size + 1) | (is_u_shift ? 0 : MO_SIGN);
8175     TCGv_i64 tcg_rn, tcg_rd, tcg_round;
8176     TCGv_i32 tcg_rd_narrowed;
8177     TCGv_i64 tcg_final;
8178
8179     static NeonGenNarrowEnvFn * const signed_narrow_fns[4][2] = {
8180         { gen_helper_neon_narrow_sat_s8,
8181           gen_helper_neon_unarrow_sat8 },
8182         { gen_helper_neon_narrow_sat_s16,
8183           gen_helper_neon_unarrow_sat16 },
8184         { gen_helper_neon_narrow_sat_s32,
8185           gen_helper_neon_unarrow_sat32 },
8186         { NULL, NULL },
8187     };
8188     static NeonGenNarrowEnvFn * const unsigned_narrow_fns[4] = {
8189         gen_helper_neon_narrow_sat_u8,
8190         gen_helper_neon_narrow_sat_u16,
8191         gen_helper_neon_narrow_sat_u32,
8192         NULL
8193     };
8194     NeonGenNarrowEnvFn *narrowfn;
8195
8196     int i;
8197
8198     assert(size < 4);
8199
8200     if (extract32(immh, 3, 1)) {
8201         unallocated_encoding(s);
8202         return;
8203     }
8204
8205     if (!fp_access_check(s)) {
8206         return;
8207     }
8208
8209     if (is_u_shift) {
8210         narrowfn = unsigned_narrow_fns[size];
8211     } else {
8212         narrowfn = signed_narrow_fns[size][is_u_narrow ? 1 : 0];
8213     }
8214
8215     tcg_rn = tcg_temp_new_i64();
8216     tcg_rd = tcg_temp_new_i64();
8217     tcg_rd_narrowed = tcg_temp_new_i32();
8218     tcg_final = tcg_const_i64(0);
8219
8220     if (round) {
8221         uint64_t round_const = 1ULL << (shift - 1);
8222         tcg_round = tcg_const_i64(round_const);
8223     } else {
8224         tcg_round = NULL;
8225     }
8226
8227     for (i = 0; i < elements; i++) {
8228         read_vec_element(s, tcg_rn, rn, i, ldop);
8229         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
8230                                 false, is_u_shift, size+1, shift);
8231         narrowfn(tcg_rd_narrowed, cpu_env, tcg_rd);
8232         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd_narrowed);
8233         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
8234     }
8235
8236     if (!is_q) {
8237         write_vec_element(s, tcg_final, rd, 0, MO_64);
8238     } else {
8239         write_vec_element(s, tcg_final, rd, 1, MO_64);
8240     }
8241
8242     if (round) {
8243         tcg_temp_free_i64(tcg_round);
8244     }
8245     tcg_temp_free_i64(tcg_rn);
8246     tcg_temp_free_i64(tcg_rd);
8247     tcg_temp_free_i32(tcg_rd_narrowed);
8248     tcg_temp_free_i64(tcg_final);
8249
8250     clear_vec_high(s, is_q, rd);
8251 }
8252
8253 /* SQSHLU, UQSHL, SQSHL: saturating left shifts */
8254 static void handle_simd_qshl(DisasContext *s, bool scalar, bool is_q,
8255                              bool src_unsigned, bool dst_unsigned,
8256                              int immh, int immb, int rn, int rd)
8257 {
8258     int immhb = immh << 3 | immb;
8259     int size = 32 - clz32(immh) - 1;
8260     int shift = immhb - (8 << size);
8261     int pass;
8262
8263     assert(immh != 0);
8264     assert(!(scalar && is_q));
8265
8266     if (!scalar) {
8267         if (!is_q && extract32(immh, 3, 1)) {
8268             unallocated_encoding(s);
8269             return;
8270         }
8271
8272         /* Since we use the variable-shift helpers we must
8273          * replicate the shift count into each element of
8274          * the tcg_shift value.
8275          */
8276         switch (size) {
8277         case 0:
8278             shift |= shift << 8;
8279             /* fall through */
8280         case 1:
8281             shift |= shift << 16;
8282             break;
8283         case 2:
8284         case 3:
8285             break;
8286         default:
8287             g_assert_not_reached();
8288         }
8289     }
8290
8291     if (!fp_access_check(s)) {
8292         return;
8293     }
8294
8295     if (size == 3) {
8296         TCGv_i64 tcg_shift = tcg_const_i64(shift);
8297         static NeonGenTwo64OpEnvFn * const fns[2][2] = {
8298             { gen_helper_neon_qshl_s64, gen_helper_neon_qshlu_s64 },
8299             { NULL, gen_helper_neon_qshl_u64 },
8300         };
8301         NeonGenTwo64OpEnvFn *genfn = fns[src_unsigned][dst_unsigned];
8302         int maxpass = is_q ? 2 : 1;
8303
8304         for (pass = 0; pass < maxpass; pass++) {
8305             TCGv_i64 tcg_op = tcg_temp_new_i64();
8306
8307             read_vec_element(s, tcg_op, rn, pass, MO_64);
8308             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
8309             write_vec_element(s, tcg_op, rd, pass, MO_64);
8310
8311             tcg_temp_free_i64(tcg_op);
8312         }
8313         tcg_temp_free_i64(tcg_shift);
8314         clear_vec_high(s, is_q, rd);
8315     } else {
8316         TCGv_i32 tcg_shift = tcg_const_i32(shift);
8317         static NeonGenTwoOpEnvFn * const fns[2][2][3] = {
8318             {
8319                 { gen_helper_neon_qshl_s8,
8320                   gen_helper_neon_qshl_s16,
8321                   gen_helper_neon_qshl_s32 },
8322                 { gen_helper_neon_qshlu_s8,
8323                   gen_helper_neon_qshlu_s16,
8324                   gen_helper_neon_qshlu_s32 }
8325             }, {
8326                 { NULL, NULL, NULL },
8327                 { gen_helper_neon_qshl_u8,
8328                   gen_helper_neon_qshl_u16,
8329                   gen_helper_neon_qshl_u32 }
8330             }
8331         };
8332         NeonGenTwoOpEnvFn *genfn = fns[src_unsigned][dst_unsigned][size];
8333         TCGMemOp memop = scalar ? size : MO_32;
8334         int maxpass = scalar ? 1 : is_q ? 4 : 2;
8335
8336         for (pass = 0; pass < maxpass; pass++) {
8337             TCGv_i32 tcg_op = tcg_temp_new_i32();
8338
8339             read_vec_element_i32(s, tcg_op, rn, pass, memop);
8340             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
8341             if (scalar) {
8342                 switch (size) {
8343                 case 0:
8344                     tcg_gen_ext8u_i32(tcg_op, tcg_op);
8345                     break;
8346                 case 1:
8347                     tcg_gen_ext16u_i32(tcg_op, tcg_op);
8348                     break;
8349                 case 2:
8350                     break;
8351                 default:
8352                     g_assert_not_reached();
8353                 }
8354                 write_fp_sreg(s, rd, tcg_op);
8355             } else {
8356                 write_vec_element_i32(s, tcg_op, rd, pass, MO_32);
8357             }
8358
8359             tcg_temp_free_i32(tcg_op);
8360         }
8361         tcg_temp_free_i32(tcg_shift);
8362
8363         if (!scalar) {
8364             clear_vec_high(s, is_q, rd);
8365         }
8366     }
8367 }
8368
8369 /* Common vector code for handling integer to FP conversion */
8370 static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
8371                                    int elements, int is_signed,
8372                                    int fracbits, int size)
8373 {
8374     TCGv_ptr tcg_fpst = get_fpstatus_ptr(size == MO_16);
8375     TCGv_i32 tcg_shift = NULL;
8376
8377     TCGMemOp mop = size | (is_signed ? MO_SIGN : 0);
8378     int pass;
8379
8380     if (fracbits || size == MO_64) {
8381         tcg_shift = tcg_const_i32(fracbits);
8382     }
8383
8384     if (size == MO_64) {
8385         TCGv_i64 tcg_int64 = tcg_temp_new_i64();
8386         TCGv_i64 tcg_double = tcg_temp_new_i64();
8387
8388         for (pass = 0; pass < elements; pass++) {
8389             read_vec_element(s, tcg_int64, rn, pass, mop);
8390
8391             if (is_signed) {
8392                 gen_helper_vfp_sqtod(tcg_double, tcg_int64,
8393                                      tcg_shift, tcg_fpst);
8394             } else {
8395                 gen_helper_vfp_uqtod(tcg_double, tcg_int64,
8396                                      tcg_shift, tcg_fpst);
8397             }
8398             if (elements == 1) {
8399                 write_fp_dreg(s, rd, tcg_double);
8400             } else {
8401                 write_vec_element(s, tcg_double, rd, pass, MO_64);
8402             }
8403         }
8404
8405         tcg_temp_free_i64(tcg_int64);
8406         tcg_temp_free_i64(tcg_double);
8407
8408     } else {
8409         TCGv_i32 tcg_int32 = tcg_temp_new_i32();
8410         TCGv_i32 tcg_float = tcg_temp_new_i32();
8411
8412         for (pass = 0; pass < elements; pass++) {
8413             read_vec_element_i32(s, tcg_int32, rn, pass, mop);
8414
8415             switch (size) {
8416             case MO_32:
8417                 if (fracbits) {
8418                     if (is_signed) {
8419                         gen_helper_vfp_sltos(tcg_float, tcg_int32,
8420                                              tcg_shift, tcg_fpst);
8421                     } else {
8422                         gen_helper_vfp_ultos(tcg_float, tcg_int32,
8423                                              tcg_shift, tcg_fpst);
8424                     }
8425                 } else {
8426                     if (is_signed) {
8427                         gen_helper_vfp_sitos(tcg_float, tcg_int32, tcg_fpst);
8428                     } else {
8429                         gen_helper_vfp_uitos(tcg_float, tcg_int32, tcg_fpst);
8430                     }
8431                 }
8432                 break;
8433             case MO_16:
8434                 if (fracbits) {
8435                     if (is_signed) {
8436                         gen_helper_vfp_sltoh(tcg_float, tcg_int32,
8437                                              tcg_shift, tcg_fpst);
8438                     } else {
8439                         gen_helper_vfp_ultoh(tcg_float, tcg_int32,
8440                                              tcg_shift, tcg_fpst);
8441                     }
8442                 } else {
8443                     if (is_signed) {
8444                         gen_helper_vfp_sitoh(tcg_float, tcg_int32, tcg_fpst);
8445                     } else {
8446                         gen_helper_vfp_uitoh(tcg_float, tcg_int32, tcg_fpst);
8447                     }
8448                 }
8449                 break;
8450             default:
8451                 g_assert_not_reached();
8452             }
8453
8454             if (elements == 1) {
8455                 write_fp_sreg(s, rd, tcg_float);
8456             } else {
8457                 write_vec_element_i32(s, tcg_float, rd, pass, size);
8458             }
8459         }
8460
8461         tcg_temp_free_i32(tcg_int32);
8462         tcg_temp_free_i32(tcg_float);
8463     }
8464
8465     tcg_temp_free_ptr(tcg_fpst);
8466     if (tcg_shift) {
8467         tcg_temp_free_i32(tcg_shift);
8468     }
8469
8470     clear_vec_high(s, elements << size == 16, rd);
8471 }
8472
8473 /* UCVTF/SCVTF - Integer to FP conversion */
8474 static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
8475                                          bool is_q, bool is_u,
8476                                          int immh, int immb, int opcode,
8477                                          int rn, int rd)
8478 {
8479     int size, elements, fracbits;
8480     int immhb = immh << 3 | immb;
8481
8482     if (immh & 8) {
8483         size = MO_64;
8484         if (!is_scalar && !is_q) {
8485             unallocated_encoding(s);
8486             return;
8487         }
8488     } else if (immh & 4) {
8489         size = MO_32;
8490     } else if (immh & 2) {
8491         size = MO_16;
8492         if (!dc_isar_feature(aa64_fp16, s)) {
8493             unallocated_encoding(s);
8494             return;
8495         }
8496     } else {
8497         /* immh == 0 would be a failure of the decode logic */
8498         g_assert(immh == 1);
8499         unallocated_encoding(s);
8500         return;
8501     }
8502
8503     if (is_scalar) {
8504         elements = 1;
8505     } else {
8506         elements = (8 << is_q) >> size;
8507     }
8508     fracbits = (16 << size) - immhb;
8509
8510     if (!fp_access_check(s)) {
8511         return;
8512     }
8513
8514     handle_simd_intfp_conv(s, rd, rn, elements, !is_u, fracbits, size);
8515 }
8516
8517 /* FCVTZS, FVCVTZU - FP to fixedpoint conversion */
8518 static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
8519                                          bool is_q, bool is_u,
8520                                          int immh, int immb, int rn, int rd)
8521 {
8522     int immhb = immh << 3 | immb;
8523     int pass, size, fracbits;
8524     TCGv_ptr tcg_fpstatus;
8525     TCGv_i32 tcg_rmode, tcg_shift;
8526
8527     if (immh & 0x8) {
8528         size = MO_64;
8529         if (!is_scalar && !is_q) {
8530             unallocated_encoding(s);
8531             return;
8532         }
8533     } else if (immh & 0x4) {
8534         size = MO_32;
8535     } else if (immh & 0x2) {
8536         size = MO_16;
8537         if (!dc_isar_feature(aa64_fp16, s)) {
8538             unallocated_encoding(s);
8539             return;
8540         }
8541     } else {
8542         /* Should have split out AdvSIMD modified immediate earlier.  */
8543         assert(immh == 1);
8544         unallocated_encoding(s);
8545         return;
8546     }
8547
8548     if (!fp_access_check(s)) {
8549         return;
8550     }
8551
8552     assert(!(is_scalar && is_q));
8553
8554     tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
8555     tcg_fpstatus = get_fpstatus_ptr(size == MO_16);
8556     gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
8557     fracbits = (16 << size) - immhb;
8558     tcg_shift = tcg_const_i32(fracbits);
8559
8560     if (size == MO_64) {
8561         int maxpass = is_scalar ? 1 : 2;
8562
8563         for (pass = 0; pass < maxpass; pass++) {
8564             TCGv_i64 tcg_op = tcg_temp_new_i64();
8565
8566             read_vec_element(s, tcg_op, rn, pass, MO_64);
8567             if (is_u) {
8568                 gen_helper_vfp_touqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
8569             } else {
8570                 gen_helper_vfp_tosqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
8571             }
8572             write_vec_element(s, tcg_op, rd, pass, MO_64);
8573             tcg_temp_free_i64(tcg_op);
8574         }
8575         clear_vec_high(s, is_q, rd);
8576     } else {
8577         void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
8578         int maxpass = is_scalar ? 1 : ((8 << is_q) >> size);
8579
8580         switch (size) {
8581         case MO_16:
8582             if (is_u) {
8583                 fn = gen_helper_vfp_touhh;
8584             } else {
8585                 fn = gen_helper_vfp_toshh;
8586             }
8587             break;
8588         case MO_32:
8589             if (is_u) {
8590                 fn = gen_helper_vfp_touls;
8591             } else {
8592                 fn = gen_helper_vfp_tosls;
8593             }
8594             break;
8595         default:
8596             g_assert_not_reached();
8597         }
8598
8599         for (pass = 0; pass < maxpass; pass++) {
8600             TCGv_i32 tcg_op = tcg_temp_new_i32();
8601
8602             read_vec_element_i32(s, tcg_op, rn, pass, size);
8603             fn(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
8604             if (is_scalar) {
8605                 write_fp_sreg(s, rd, tcg_op);
8606             } else {
8607                 write_vec_element_i32(s, tcg_op, rd, pass, size);
8608             }
8609             tcg_temp_free_i32(tcg_op);
8610         }
8611         if (!is_scalar) {
8612             clear_vec_high(s, is_q, rd);
8613         }
8614     }
8615
8616     tcg_temp_free_ptr(tcg_fpstatus);
8617     tcg_temp_free_i32(tcg_shift);
8618     gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
8619     tcg_temp_free_i32(tcg_rmode);
8620 }
8621
8622 /* AdvSIMD scalar shift by immediate
8623  *  31 30  29 28         23 22  19 18  16 15    11  10 9    5 4    0
8624  * +-----+---+-------------+------+------+--------+---+------+------+
8625  * | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
8626  * +-----+---+-------------+------+------+--------+---+------+------+
8627  *
8628  * This is the scalar version so it works on a fixed sized registers
8629  */
8630 static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn)
8631 {
8632     int rd = extract32(insn, 0, 5);
8633     int rn = extract32(insn, 5, 5);
8634     int opcode = extract32(insn, 11, 5);
8635     int immb = extract32(insn, 16, 3);
8636     int immh = extract32(insn, 19, 4);
8637     bool is_u = extract32(insn, 29, 1);
8638
8639     if (immh == 0) {
8640         unallocated_encoding(s);
8641         return;
8642     }
8643
8644     switch (opcode) {
8645     case 0x08: /* SRI */
8646         if (!is_u) {
8647             unallocated_encoding(s);
8648             return;
8649         }
8650         /* fall through */
8651     case 0x00: /* SSHR / USHR */
8652     case 0x02: /* SSRA / USRA */
8653     case 0x04: /* SRSHR / URSHR */
8654     case 0x06: /* SRSRA / URSRA */
8655         handle_scalar_simd_shri(s, is_u, immh, immb, opcode, rn, rd);
8656         break;
8657     case 0x0a: /* SHL / SLI */
8658         handle_scalar_simd_shli(s, is_u, immh, immb, opcode, rn, rd);
8659         break;
8660     case 0x1c: /* SCVTF, UCVTF */
8661         handle_simd_shift_intfp_conv(s, true, false, is_u, immh, immb,
8662                                      opcode, rn, rd);
8663         break;
8664     case 0x10: /* SQSHRUN, SQSHRUN2 */
8665     case 0x11: /* SQRSHRUN, SQRSHRUN2 */
8666         if (!is_u) {
8667             unallocated_encoding(s);
8668             return;
8669         }
8670         handle_vec_simd_sqshrn(s, true, false, false, true,
8671                                immh, immb, opcode, rn, rd);
8672         break;
8673     case 0x12: /* SQSHRN, SQSHRN2, UQSHRN */
8674     case 0x13: /* SQRSHRN, SQRSHRN2, UQRSHRN, UQRSHRN2 */
8675         handle_vec_simd_sqshrn(s, true, false, is_u, is_u,
8676                                immh, immb, opcode, rn, rd);
8677         break;
8678     case 0xc: /* SQSHLU */
8679         if (!is_u) {
8680             unallocated_encoding(s);
8681             return;
8682         }
8683         handle_simd_qshl(s, true, false, false, true, immh, immb, rn, rd);
8684         break;
8685     case 0xe: /* SQSHL, UQSHL */
8686         handle_simd_qshl(s, true, false, is_u, is_u, immh, immb, rn, rd);
8687         break;
8688     case 0x1f: /* FCVTZS, FCVTZU */
8689         handle_simd_shift_fpint_conv(s, true, false, is_u, immh, immb, rn, rd);
8690         break;
8691     default:
8692         unallocated_encoding(s);
8693         break;
8694     }
8695 }
8696
8697 /* AdvSIMD scalar three different
8698  *  31 30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
8699  * +-----+---+-----------+------+---+------+--------+-----+------+------+
8700  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
8701  * +-----+---+-----------+------+---+------+--------+-----+------+------+
8702  */
8703 static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
8704 {
8705     bool is_u = extract32(insn, 29, 1);
8706     int size = extract32(insn, 22, 2);
8707     int opcode = extract32(insn, 12, 4);
8708     int rm = extract32(insn, 16, 5);
8709     int rn = extract32(insn, 5, 5);
8710     int rd = extract32(insn, 0, 5);
8711
8712     if (is_u) {
8713         unallocated_encoding(s);
8714         return;
8715     }
8716
8717     switch (opcode) {
8718     case 0x9: /* SQDMLAL, SQDMLAL2 */
8719     case 0xb: /* SQDMLSL, SQDMLSL2 */
8720     case 0xd: /* SQDMULL, SQDMULL2 */
8721         if (size == 0 || size == 3) {
8722             unallocated_encoding(s);
8723             return;
8724         }
8725         break;
8726     default:
8727         unallocated_encoding(s);
8728         return;
8729     }
8730
8731     if (!fp_access_check(s)) {
8732         return;
8733     }
8734
8735     if (size == 2) {
8736         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8737         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8738         TCGv_i64 tcg_res = tcg_temp_new_i64();
8739
8740         read_vec_element(s, tcg_op1, rn, 0, MO_32 | MO_SIGN);
8741         read_vec_element(s, tcg_op2, rm, 0, MO_32 | MO_SIGN);
8742
8743         tcg_gen_mul_i64(tcg_res, tcg_op1, tcg_op2);
8744         gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env, tcg_res, tcg_res);
8745
8746         switch (opcode) {
8747         case 0xd: /* SQDMULL, SQDMULL2 */
8748             break;
8749         case 0xb: /* SQDMLSL, SQDMLSL2 */
8750             tcg_gen_neg_i64(tcg_res, tcg_res);
8751             /* fall through */
8752         case 0x9: /* SQDMLAL, SQDMLAL2 */
8753             read_vec_element(s, tcg_op1, rd, 0, MO_64);
8754             gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env,
8755                                               tcg_res, tcg_op1);
8756             break;
8757         default:
8758             g_assert_not_reached();
8759         }
8760
8761         write_fp_dreg(s, rd, tcg_res);
8762
8763         tcg_temp_free_i64(tcg_op1);
8764         tcg_temp_free_i64(tcg_op2);
8765         tcg_temp_free_i64(tcg_res);
8766     } else {
8767         TCGv_i32 tcg_op1 = read_fp_hreg(s, rn);
8768         TCGv_i32 tcg_op2 = read_fp_hreg(s, rm);
8769         TCGv_i64 tcg_res = tcg_temp_new_i64();
8770
8771         gen_helper_neon_mull_s16(tcg_res, tcg_op1, tcg_op2);
8772         gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env, tcg_res, tcg_res);
8773
8774         switch (opcode) {
8775         case 0xd: /* SQDMULL, SQDMULL2 */
8776             break;
8777         case 0xb: /* SQDMLSL, SQDMLSL2 */
8778             gen_helper_neon_negl_u32(tcg_res, tcg_res);
8779             /* fall through */
8780         case 0x9: /* SQDMLAL, SQDMLAL2 */
8781         {
8782             TCGv_i64 tcg_op3 = tcg_temp_new_i64();
8783             read_vec_element(s, tcg_op3, rd, 0, MO_32);
8784             gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env,
8785                                               tcg_res, tcg_op3);
8786             tcg_temp_free_i64(tcg_op3);
8787             break;
8788         }
8789         default:
8790             g_assert_not_reached();
8791         }
8792
8793         tcg_gen_ext32u_i64(tcg_res, tcg_res);
8794         write_fp_dreg(s, rd, tcg_res);
8795
8796         tcg_temp_free_i32(tcg_op1);
8797         tcg_temp_free_i32(tcg_op2);
8798         tcg_temp_free_i64(tcg_res);
8799     }
8800 }
8801
8802 static void handle_3same_64(DisasContext *s, int opcode, bool u,
8803                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn, TCGv_i64 tcg_rm)
8804 {
8805     /* Handle 64x64->64 opcodes which are shared between the scalar
8806      * and vector 3-same groups. We cover every opcode where size == 3
8807      * is valid in either the three-reg-same (integer, not pairwise)
8808      * or scalar-three-reg-same groups.
8809      */
8810     TCGCond cond;
8811
8812     switch (opcode) {
8813     case 0x1: /* SQADD */
8814         if (u) {
8815             gen_helper_neon_qadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8816         } else {
8817             gen_helper_neon_qadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8818         }
8819         break;
8820     case 0x5: /* SQSUB */
8821         if (u) {
8822             gen_helper_neon_qsub_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8823         } else {
8824             gen_helper_neon_qsub_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8825         }
8826         break;
8827     case 0x6: /* CMGT, CMHI */
8828         /* 64 bit integer comparison, result = test ? (2^64 - 1) : 0.
8829          * We implement this using setcond (test) and then negating.
8830          */
8831         cond = u ? TCG_COND_GTU : TCG_COND_GT;
8832     do_cmop:
8833         tcg_gen_setcond_i64(cond, tcg_rd, tcg_rn, tcg_rm);
8834         tcg_gen_neg_i64(tcg_rd, tcg_rd);
8835         break;
8836     case 0x7: /* CMGE, CMHS */
8837         cond = u ? TCG_COND_GEU : TCG_COND_GE;
8838         goto do_cmop;
8839     case 0x11: /* CMTST, CMEQ */
8840         if (u) {
8841             cond = TCG_COND_EQ;
8842             goto do_cmop;
8843         }
8844         gen_cmtst_i64(tcg_rd, tcg_rn, tcg_rm);
8845         break;
8846     case 0x8: /* SSHL, USHL */
8847         if (u) {
8848             gen_helper_neon_shl_u64(tcg_rd, tcg_rn, tcg_rm);
8849         } else {
8850             gen_helper_neon_shl_s64(tcg_rd, tcg_rn, tcg_rm);
8851         }
8852         break;
8853     case 0x9: /* SQSHL, UQSHL */
8854         if (u) {
8855             gen_helper_neon_qshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8856         } else {
8857             gen_helper_neon_qshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8858         }
8859         break;
8860     case 0xa: /* SRSHL, URSHL */
8861         if (u) {
8862             gen_helper_neon_rshl_u64(tcg_rd, tcg_rn, tcg_rm);
8863         } else {
8864             gen_helper_neon_rshl_s64(tcg_rd, tcg_rn, tcg_rm);
8865         }
8866         break;
8867     case 0xb: /* SQRSHL, UQRSHL */
8868         if (u) {
8869             gen_helper_neon_qrshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8870         } else {
8871             gen_helper_neon_qrshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8872         }
8873         break;
8874     case 0x10: /* ADD, SUB */
8875         if (u) {
8876             tcg_gen_sub_i64(tcg_rd, tcg_rn, tcg_rm);
8877         } else {
8878             tcg_gen_add_i64(tcg_rd, tcg_rn, tcg_rm);
8879         }
8880         break;
8881     default:
8882         g_assert_not_reached();
8883     }
8884 }
8885
8886 /* Handle the 3-same-operands float operations; shared by the scalar
8887  * and vector encodings. The caller must filter out any encodings
8888  * not allocated for the encoding it is dealing with.
8889  */
8890 static void handle_3same_float(DisasContext *s, int size, int elements,
8891                                int fpopcode, int rd, int rn, int rm)
8892 {
8893     int pass;
8894     TCGv_ptr fpst = get_fpstatus_ptr(false);
8895
8896     for (pass = 0; pass < elements; pass++) {
8897         if (size) {
8898             /* Double */
8899             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8900             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8901             TCGv_i64 tcg_res = tcg_temp_new_i64();
8902
8903             read_vec_element(s, tcg_op1, rn, pass, MO_64);
8904             read_vec_element(s, tcg_op2, rm, pass, MO_64);
8905
8906             switch (fpopcode) {
8907             case 0x39: /* FMLS */
8908                 /* As usual for ARM, separate negation for fused multiply-add */
8909                 gen_helper_vfp_negd(tcg_op1, tcg_op1);
8910                 /* fall through */
8911             case 0x19: /* FMLA */
8912                 read_vec_element(s, tcg_res, rd, pass, MO_64);
8913                 gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2,
8914                                        tcg_res, fpst);
8915                 break;
8916             case 0x18: /* FMAXNM */
8917                 gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
8918                 break;
8919             case 0x1a: /* FADD */
8920                 gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
8921                 break;
8922             case 0x1b: /* FMULX */
8923                 gen_helper_vfp_mulxd(tcg_res, tcg_op1, tcg_op2, fpst);
8924                 break;
8925             case 0x1c: /* FCMEQ */
8926                 gen_helper_neon_ceq_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8927                 break;
8928             case 0x1e: /* FMAX */
8929                 gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
8930                 break;
8931             case 0x1f: /* FRECPS */
8932                 gen_helper_recpsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8933                 break;
8934             case 0x38: /* FMINNM */
8935                 gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
8936                 break;
8937             case 0x3a: /* FSUB */
8938                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
8939                 break;
8940             case 0x3e: /* FMIN */
8941                 gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
8942                 break;
8943             case 0x3f: /* FRSQRTS */
8944                 gen_helper_rsqrtsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8945                 break;
8946             case 0x5b: /* FMUL */
8947                 gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
8948                 break;
8949             case 0x5c: /* FCMGE */
8950                 gen_helper_neon_cge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8951                 break;
8952             case 0x5d: /* FACGE */
8953                 gen_helper_neon_acge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8954                 break;
8955             case 0x5f: /* FDIV */
8956                 gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
8957                 break;
8958             case 0x7a: /* FABD */
8959                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
8960                 gen_helper_vfp_absd(tcg_res, tcg_res);
8961                 break;
8962             case 0x7c: /* FCMGT */
8963                 gen_helper_neon_cgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8964                 break;
8965             case 0x7d: /* FACGT */
8966                 gen_helper_neon_acgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8967                 break;
8968             default:
8969                 g_assert_not_reached();
8970             }
8971
8972             write_vec_element(s, tcg_res, rd, pass, MO_64);
8973
8974             tcg_temp_free_i64(tcg_res);
8975             tcg_temp_free_i64(tcg_op1);
8976             tcg_temp_free_i64(tcg_op2);
8977         } else {
8978             /* Single */
8979             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
8980             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
8981             TCGv_i32 tcg_res = tcg_temp_new_i32();
8982
8983             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
8984             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
8985
8986             switch (fpopcode) {
8987             case 0x39: /* FMLS */
8988                 /* As usual for ARM, separate negation for fused multiply-add */
8989                 gen_helper_vfp_negs(tcg_op1, tcg_op1);
8990                 /* fall through */
8991             case 0x19: /* FMLA */
8992                 read_vec_element_i32(s, tcg_res, rd, pass, MO_32);
8993                 gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2,
8994                                        tcg_res, fpst);
8995                 break;
8996             case 0x1a: /* FADD */
8997                 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
8998                 break;
8999             case 0x1b: /* FMULX */
9000                 gen_helper_vfp_mulxs(tcg_res, tcg_op1, tcg_op2, fpst);
9001                 break;
9002             case 0x1c: /* FCMEQ */
9003                 gen_helper_neon_ceq_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9004                 break;
9005             case 0x1e: /* FMAX */
9006                 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
9007                 break;
9008             case 0x1f: /* FRECPS */
9009                 gen_helper_recpsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9010                 break;
9011             case 0x18: /* FMAXNM */
9012                 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
9013                 break;
9014             case 0x38: /* FMINNM */
9015                 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
9016                 break;
9017             case 0x3a: /* FSUB */
9018                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
9019                 break;
9020             case 0x3e: /* FMIN */
9021                 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
9022                 break;
9023             case 0x3f: /* FRSQRTS */
9024                 gen_helper_rsqrtsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9025                 break;
9026             case 0x5b: /* FMUL */
9027                 gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
9028                 break;
9029             case 0x5c: /* FCMGE */
9030                 gen_helper_neon_cge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9031                 break;
9032             case 0x5d: /* FACGE */
9033                 gen_helper_neon_acge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9034                 break;
9035             case 0x5f: /* FDIV */
9036                 gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
9037                 break;
9038             case 0x7a: /* FABD */
9039                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
9040                 gen_helper_vfp_abss(tcg_res, tcg_res);
9041                 break;
9042             case 0x7c: /* FCMGT */
9043                 gen_helper_neon_cgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9044                 break;
9045             case 0x7d: /* FACGT */
9046                 gen_helper_neon_acgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9047                 break;
9048             default:
9049                 g_assert_not_reached();
9050             }
9051
9052             if (elements == 1) {
9053                 /* scalar single so clear high part */
9054                 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
9055
9056                 tcg_gen_extu_i32_i64(tcg_tmp, tcg_res);
9057                 write_vec_element(s, tcg_tmp, rd, pass, MO_64);
9058                 tcg_temp_free_i64(tcg_tmp);
9059             } else {
9060                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
9061             }
9062
9063             tcg_temp_free_i32(tcg_res);
9064             tcg_temp_free_i32(tcg_op1);
9065             tcg_temp_free_i32(tcg_op2);
9066         }
9067     }
9068
9069     tcg_temp_free_ptr(fpst);
9070
9071     clear_vec_high(s, elements * (size ? 8 : 4) > 8, rd);
9072 }
9073
9074 /* AdvSIMD scalar three same
9075  *  31 30  29 28       24 23  22  21 20  16 15    11  10 9    5 4    0
9076  * +-----+---+-----------+------+---+------+--------+---+------+------+
9077  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
9078  * +-----+---+-----------+------+---+------+--------+---+------+------+
9079  */
9080 static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
9081 {
9082     int rd = extract32(insn, 0, 5);
9083     int rn = extract32(insn, 5, 5);
9084     int opcode = extract32(insn, 11, 5);
9085     int rm = extract32(insn, 16, 5);
9086     int size = extract32(insn, 22, 2);
9087     bool u = extract32(insn, 29, 1);
9088     TCGv_i64 tcg_rd;
9089
9090     if (opcode >= 0x18) {
9091         /* Floating point: U, size[1] and opcode indicate operation */
9092         int fpopcode = opcode | (extract32(size, 1, 1) << 5) | (u << 6);
9093         switch (fpopcode) {
9094         case 0x1b: /* FMULX */
9095         case 0x1f: /* FRECPS */
9096         case 0x3f: /* FRSQRTS */
9097         case 0x5d: /* FACGE */
9098         case 0x7d: /* FACGT */
9099         case 0x1c: /* FCMEQ */
9100         case 0x5c: /* FCMGE */
9101         case 0x7c: /* FCMGT */
9102         case 0x7a: /* FABD */
9103             break;
9104         default:
9105             unallocated_encoding(s);
9106             return;
9107         }
9108
9109         if (!fp_access_check(s)) {
9110             return;
9111         }
9112
9113         handle_3same_float(s, extract32(size, 0, 1), 1, fpopcode, rd, rn, rm);
9114         return;
9115     }
9116
9117     switch (opcode) {
9118     case 0x1: /* SQADD, UQADD */
9119     case 0x5: /* SQSUB, UQSUB */
9120     case 0x9: /* SQSHL, UQSHL */
9121     case 0xb: /* SQRSHL, UQRSHL */
9122         break;
9123     case 0x8: /* SSHL, USHL */
9124     case 0xa: /* SRSHL, URSHL */
9125     case 0x6: /* CMGT, CMHI */
9126     case 0x7: /* CMGE, CMHS */
9127     case 0x11: /* CMTST, CMEQ */
9128     case 0x10: /* ADD, SUB (vector) */
9129         if (size != 3) {
9130             unallocated_encoding(s);
9131             return;
9132         }
9133         break;
9134     case 0x16: /* SQDMULH, SQRDMULH (vector) */
9135         if (size != 1 && size != 2) {
9136             unallocated_encoding(s);
9137             return;
9138         }
9139         break;
9140     default:
9141         unallocated_encoding(s);
9142         return;
9143     }
9144
9145     if (!fp_access_check(s)) {
9146         return;
9147     }
9148
9149     tcg_rd = tcg_temp_new_i64();
9150
9151     if (size == 3) {
9152         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
9153         TCGv_i64 tcg_rm = read_fp_dreg(s, rm);
9154
9155         handle_3same_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rm);
9156         tcg_temp_free_i64(tcg_rn);
9157         tcg_temp_free_i64(tcg_rm);
9158     } else {
9159         /* Do a single operation on the lowest element in the vector.
9160          * We use the standard Neon helpers and rely on 0 OP 0 == 0 with
9161          * no side effects for all these operations.
9162          * OPTME: special-purpose helpers would avoid doing some
9163          * unnecessary work in the helper for the 8 and 16 bit cases.
9164          */
9165         NeonGenTwoOpEnvFn *genenvfn;
9166         TCGv_i32 tcg_rn = tcg_temp_new_i32();
9167         TCGv_i32 tcg_rm = tcg_temp_new_i32();
9168         TCGv_i32 tcg_rd32 = tcg_temp_new_i32();
9169
9170         read_vec_element_i32(s, tcg_rn, rn, 0, size);
9171         read_vec_element_i32(s, tcg_rm, rm, 0, size);
9172
9173         switch (opcode) {
9174         case 0x1: /* SQADD, UQADD */
9175         {
9176             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9177                 { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 },
9178                 { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 },
9179                 { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 },
9180             };
9181             genenvfn = fns[size][u];
9182             break;
9183         }
9184         case 0x5: /* SQSUB, UQSUB */
9185         {
9186             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9187                 { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 },
9188                 { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 },
9189                 { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 },
9190             };
9191             genenvfn = fns[size][u];
9192             break;
9193         }
9194         case 0x9: /* SQSHL, UQSHL */
9195         {
9196             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9197                 { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
9198                 { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
9199                 { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
9200             };
9201             genenvfn = fns[size][u];
9202             break;
9203         }
9204         case 0xb: /* SQRSHL, UQRSHL */
9205         {
9206             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9207                 { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
9208                 { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
9209                 { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
9210             };
9211             genenvfn = fns[size][u];
9212             break;
9213         }
9214         case 0x16: /* SQDMULH, SQRDMULH */
9215         {
9216             static NeonGenTwoOpEnvFn * const fns[2][2] = {
9217                 { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
9218                 { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
9219             };
9220             assert(size == 1 || size == 2);
9221             genenvfn = fns[size - 1][u];
9222             break;
9223         }
9224         default:
9225             g_assert_not_reached();
9226         }
9227
9228         genenvfn(tcg_rd32, cpu_env, tcg_rn, tcg_rm);
9229         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd32);
9230         tcg_temp_free_i32(tcg_rd32);
9231         tcg_temp_free_i32(tcg_rn);
9232         tcg_temp_free_i32(tcg_rm);
9233     }
9234
9235     write_fp_dreg(s, rd, tcg_rd);
9236
9237     tcg_temp_free_i64(tcg_rd);
9238 }
9239
9240 /* AdvSIMD scalar three same FP16
9241  *  31 30  29 28       24 23  22 21 20  16 15 14 13    11 10  9  5 4  0
9242  * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
9243  * | 0 1 | U | 1 1 1 1 0 | a | 1 0 |  Rm  | 0 0 | opcode | 1 | Rn | Rd |
9244  * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
9245  * v: 0101 1110 0100 0000 0000 0100 0000 0000 => 5e400400
9246  * m: 1101 1111 0110 0000 1100 0100 0000 0000 => df60c400
9247  */
9248 static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
9249                                                   uint32_t insn)
9250 {
9251     int rd = extract32(insn, 0, 5);
9252     int rn = extract32(insn, 5, 5);
9253     int opcode = extract32(insn, 11, 3);
9254     int rm = extract32(insn, 16, 5);
9255     bool u = extract32(insn, 29, 1);
9256     bool a = extract32(insn, 23, 1);
9257     int fpopcode = opcode | (a << 3) |  (u << 4);
9258     TCGv_ptr fpst;
9259     TCGv_i32 tcg_op1;
9260     TCGv_i32 tcg_op2;
9261     TCGv_i32 tcg_res;
9262
9263     switch (fpopcode) {
9264     case 0x03: /* FMULX */
9265     case 0x04: /* FCMEQ (reg) */
9266     case 0x07: /* FRECPS */
9267     case 0x0f: /* FRSQRTS */
9268     case 0x14: /* FCMGE (reg) */
9269     case 0x15: /* FACGE */
9270     case 0x1a: /* FABD */
9271     case 0x1c: /* FCMGT (reg) */
9272     case 0x1d: /* FACGT */
9273         break;
9274     default:
9275         unallocated_encoding(s);
9276         return;
9277     }
9278
9279     if (!dc_isar_feature(aa64_fp16, s)) {
9280         unallocated_encoding(s);
9281     }
9282
9283     if (!fp_access_check(s)) {
9284         return;
9285     }
9286
9287     fpst = get_fpstatus_ptr(true);
9288
9289     tcg_op1 = read_fp_hreg(s, rn);
9290     tcg_op2 = read_fp_hreg(s, rm);
9291     tcg_res = tcg_temp_new_i32();
9292
9293     switch (fpopcode) {
9294     case 0x03: /* FMULX */
9295         gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
9296         break;
9297     case 0x04: /* FCMEQ (reg) */
9298         gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9299         break;
9300     case 0x07: /* FRECPS */
9301         gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9302         break;
9303     case 0x0f: /* FRSQRTS */
9304         gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9305         break;
9306     case 0x14: /* FCMGE (reg) */
9307         gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9308         break;
9309     case 0x15: /* FACGE */
9310         gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9311         break;
9312     case 0x1a: /* FABD */
9313         gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
9314         tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
9315         break;
9316     case 0x1c: /* FCMGT (reg) */
9317         gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9318         break;
9319     case 0x1d: /* FACGT */
9320         gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9321         break;
9322     default:
9323         g_assert_not_reached();
9324     }
9325
9326     write_fp_sreg(s, rd, tcg_res);
9327
9328
9329     tcg_temp_free_i32(tcg_res);
9330     tcg_temp_free_i32(tcg_op1);
9331     tcg_temp_free_i32(tcg_op2);
9332     tcg_temp_free_ptr(fpst);
9333 }
9334
9335 /* AdvSIMD scalar three same extra
9336  *  31 30  29 28       24 23  22  21 20  16  15 14    11  10 9  5 4  0
9337  * +-----+---+-----------+------+---+------+---+--------+---+----+----+
9338  * | 0 1 | U | 1 1 1 1 0 | size | 0 |  Rm  | 1 | opcode | 1 | Rn | Rd |
9339  * +-----+---+-----------+------+---+------+---+--------+---+----+----+
9340  */
9341 static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
9342                                                    uint32_t insn)
9343 {
9344     int rd = extract32(insn, 0, 5);
9345     int rn = extract32(insn, 5, 5);
9346     int opcode = extract32(insn, 11, 4);
9347     int rm = extract32(insn, 16, 5);
9348     int size = extract32(insn, 22, 2);
9349     bool u = extract32(insn, 29, 1);
9350     TCGv_i32 ele1, ele2, ele3;
9351     TCGv_i64 res;
9352     bool feature;
9353
9354     switch (u * 16 + opcode) {
9355     case 0x10: /* SQRDMLAH (vector) */
9356     case 0x11: /* SQRDMLSH (vector) */
9357         if (size != 1 && size != 2) {
9358             unallocated_encoding(s);
9359             return;
9360         }
9361         feature = dc_isar_feature(aa64_rdm, s);
9362         break;
9363     default:
9364         unallocated_encoding(s);
9365         return;
9366     }
9367     if (!feature) {
9368         unallocated_encoding(s);
9369         return;
9370     }
9371     if (!fp_access_check(s)) {
9372         return;
9373     }
9374
9375     /* Do a single operation on the lowest element in the vector.
9376      * We use the standard Neon helpers and rely on 0 OP 0 == 0
9377      * with no side effects for all these operations.
9378      * OPTME: special-purpose helpers would avoid doing some
9379      * unnecessary work in the helper for the 16 bit cases.
9380      */
9381     ele1 = tcg_temp_new_i32();
9382     ele2 = tcg_temp_new_i32();
9383     ele3 = tcg_temp_new_i32();
9384
9385     read_vec_element_i32(s, ele1, rn, 0, size);
9386     read_vec_element_i32(s, ele2, rm, 0, size);
9387     read_vec_element_i32(s, ele3, rd, 0, size);
9388
9389     switch (opcode) {
9390     case 0x0: /* SQRDMLAH */
9391         if (size == 1) {
9392             gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
9393         } else {
9394             gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
9395         }
9396         break;
9397     case 0x1: /* SQRDMLSH */
9398         if (size == 1) {
9399             gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
9400         } else {
9401             gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
9402         }
9403         break;
9404     default:
9405         g_assert_not_reached();
9406     }
9407     tcg_temp_free_i32(ele1);
9408     tcg_temp_free_i32(ele2);
9409
9410     res = tcg_temp_new_i64();
9411     tcg_gen_extu_i32_i64(res, ele3);
9412     tcg_temp_free_i32(ele3);
9413
9414     write_fp_dreg(s, rd, res);
9415     tcg_temp_free_i64(res);
9416 }
9417
9418 static void handle_2misc_64(DisasContext *s, int opcode, bool u,
9419                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
9420                             TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
9421 {
9422     /* Handle 64->64 opcodes which are shared between the scalar and
9423      * vector 2-reg-misc groups. We cover every integer opcode where size == 3
9424      * is valid in either group and also the double-precision fp ops.
9425      * The caller only need provide tcg_rmode and tcg_fpstatus if the op
9426      * requires them.
9427      */
9428     TCGCond cond;
9429
9430     switch (opcode) {
9431     case 0x4: /* CLS, CLZ */
9432         if (u) {
9433             tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
9434         } else {
9435             tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
9436         }
9437         break;
9438     case 0x5: /* NOT */
9439         /* This opcode is shared with CNT and RBIT but we have earlier
9440          * enforced that size == 3 if and only if this is the NOT insn.
9441          */
9442         tcg_gen_not_i64(tcg_rd, tcg_rn);
9443         break;
9444     case 0x7: /* SQABS, SQNEG */
9445         if (u) {
9446             gen_helper_neon_qneg_s64(tcg_rd, cpu_env, tcg_rn);
9447         } else {
9448             gen_helper_neon_qabs_s64(tcg_rd, cpu_env, tcg_rn);
9449         }
9450         break;
9451     case 0xa: /* CMLT */
9452         /* 64 bit integer comparison against zero, result is
9453          * test ? (2^64 - 1) : 0. We implement via setcond(!test) and
9454          * subtracting 1.
9455          */
9456         cond = TCG_COND_LT;
9457     do_cmop:
9458         tcg_gen_setcondi_i64(cond, tcg_rd, tcg_rn, 0);
9459         tcg_gen_neg_i64(tcg_rd, tcg_rd);
9460         break;
9461     case 0x8: /* CMGT, CMGE */
9462         cond = u ? TCG_COND_GE : TCG_COND_GT;
9463         goto do_cmop;
9464     case 0x9: /* CMEQ, CMLE */
9465         cond = u ? TCG_COND_LE : TCG_COND_EQ;
9466         goto do_cmop;
9467     case 0xb: /* ABS, NEG */
9468         if (u) {
9469             tcg_gen_neg_i64(tcg_rd, tcg_rn);
9470         } else {
9471             TCGv_i64 tcg_zero = tcg_const_i64(0);
9472             tcg_gen_neg_i64(tcg_rd, tcg_rn);
9473             tcg_gen_movcond_i64(TCG_COND_GT, tcg_rd, tcg_rn, tcg_zero,
9474                                 tcg_rn, tcg_rd);
9475             tcg_temp_free_i64(tcg_zero);
9476         }
9477         break;
9478     case 0x2f: /* FABS */
9479         gen_helper_vfp_absd(tcg_rd, tcg_rn);
9480         break;
9481     case 0x6f: /* FNEG */
9482         gen_helper_vfp_negd(tcg_rd, tcg_rn);
9483         break;
9484     case 0x7f: /* FSQRT */
9485         gen_helper_vfp_sqrtd(tcg_rd, tcg_rn, cpu_env);
9486         break;
9487     case 0x1a: /* FCVTNS */
9488     case 0x1b: /* FCVTMS */
9489     case 0x1c: /* FCVTAS */
9490     case 0x3a: /* FCVTPS */
9491     case 0x3b: /* FCVTZS */
9492     {
9493         TCGv_i32 tcg_shift = tcg_const_i32(0);
9494         gen_helper_vfp_tosqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
9495         tcg_temp_free_i32(tcg_shift);
9496         break;
9497     }
9498     case 0x5a: /* FCVTNU */
9499     case 0x5b: /* FCVTMU */
9500     case 0x5c: /* FCVTAU */
9501     case 0x7a: /* FCVTPU */
9502     case 0x7b: /* FCVTZU */
9503     {
9504         TCGv_i32 tcg_shift = tcg_const_i32(0);
9505         gen_helper_vfp_touqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
9506         tcg_temp_free_i32(tcg_shift);
9507         break;
9508     }
9509     case 0x18: /* FRINTN */
9510     case 0x19: /* FRINTM */
9511     case 0x38: /* FRINTP */
9512     case 0x39: /* FRINTZ */
9513     case 0x58: /* FRINTA */
9514     case 0x79: /* FRINTI */
9515         gen_helper_rintd(tcg_rd, tcg_rn, tcg_fpstatus);
9516         break;
9517     case 0x59: /* FRINTX */
9518         gen_helper_rintd_exact(tcg_rd, tcg_rn, tcg_fpstatus);
9519         break;
9520     case 0x1e: /* FRINT32Z */
9521     case 0x5e: /* FRINT32X */
9522         gen_helper_frint32_d(tcg_rd, tcg_rn, tcg_fpstatus);
9523         break;
9524     case 0x1f: /* FRINT64Z */
9525     case 0x5f: /* FRINT64X */
9526         gen_helper_frint64_d(tcg_rd, tcg_rn, tcg_fpstatus);
9527         break;
9528     default:
9529         g_assert_not_reached();
9530     }
9531 }
9532
9533 static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
9534                                    bool is_scalar, bool is_u, bool is_q,
9535                                    int size, int rn, int rd)
9536 {
9537     bool is_double = (size == MO_64);
9538     TCGv_ptr fpst;
9539
9540     if (!fp_access_check(s)) {
9541         return;
9542     }
9543
9544     fpst = get_fpstatus_ptr(size == MO_16);
9545
9546     if (is_double) {
9547         TCGv_i64 tcg_op = tcg_temp_new_i64();
9548         TCGv_i64 tcg_zero = tcg_const_i64(0);
9549         TCGv_i64 tcg_res = tcg_temp_new_i64();
9550         NeonGenTwoDoubleOPFn *genfn;
9551         bool swap = false;
9552         int pass;
9553
9554         switch (opcode) {
9555         case 0x2e: /* FCMLT (zero) */
9556             swap = true;
9557             /* fallthrough */
9558         case 0x2c: /* FCMGT (zero) */
9559             genfn = gen_helper_neon_cgt_f64;
9560             break;
9561         case 0x2d: /* FCMEQ (zero) */
9562             genfn = gen_helper_neon_ceq_f64;
9563             break;
9564         case 0x6d: /* FCMLE (zero) */
9565             swap = true;
9566             /* fall through */
9567         case 0x6c: /* FCMGE (zero) */
9568             genfn = gen_helper_neon_cge_f64;
9569             break;
9570         default:
9571             g_assert_not_reached();
9572         }
9573
9574         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9575             read_vec_element(s, tcg_op, rn, pass, MO_64);
9576             if (swap) {
9577                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
9578             } else {
9579                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
9580             }
9581             write_vec_element(s, tcg_res, rd, pass, MO_64);
9582         }
9583         tcg_temp_free_i64(tcg_res);
9584         tcg_temp_free_i64(tcg_zero);
9585         tcg_temp_free_i64(tcg_op);
9586
9587         clear_vec_high(s, !is_scalar, rd);
9588     } else {
9589         TCGv_i32 tcg_op = tcg_temp_new_i32();
9590         TCGv_i32 tcg_zero = tcg_const_i32(0);
9591         TCGv_i32 tcg_res = tcg_temp_new_i32();
9592         NeonGenTwoSingleOPFn *genfn;
9593         bool swap = false;
9594         int pass, maxpasses;
9595
9596         if (size == MO_16) {
9597             switch (opcode) {
9598             case 0x2e: /* FCMLT (zero) */
9599                 swap = true;
9600                 /* fall through */
9601             case 0x2c: /* FCMGT (zero) */
9602                 genfn = gen_helper_advsimd_cgt_f16;
9603                 break;
9604             case 0x2d: /* FCMEQ (zero) */
9605                 genfn = gen_helper_advsimd_ceq_f16;
9606                 break;
9607             case 0x6d: /* FCMLE (zero) */
9608                 swap = true;
9609                 /* fall through */
9610             case 0x6c: /* FCMGE (zero) */
9611                 genfn = gen_helper_advsimd_cge_f16;
9612                 break;
9613             default:
9614                 g_assert_not_reached();
9615             }
9616         } else {
9617             switch (opcode) {
9618             case 0x2e: /* FCMLT (zero) */
9619                 swap = true;
9620                 /* fall through */
9621             case 0x2c: /* FCMGT (zero) */
9622                 genfn = gen_helper_neon_cgt_f32;
9623                 break;
9624             case 0x2d: /* FCMEQ (zero) */
9625                 genfn = gen_helper_neon_ceq_f32;
9626                 break;
9627             case 0x6d: /* FCMLE (zero) */
9628                 swap = true;
9629                 /* fall through */
9630             case 0x6c: /* FCMGE (zero) */
9631                 genfn = gen_helper_neon_cge_f32;
9632                 break;
9633             default:
9634                 g_assert_not_reached();
9635             }
9636         }
9637
9638         if (is_scalar) {
9639             maxpasses = 1;
9640         } else {
9641             int vector_size = 8 << is_q;
9642             maxpasses = vector_size >> size;
9643         }
9644
9645         for (pass = 0; pass < maxpasses; pass++) {
9646             read_vec_element_i32(s, tcg_op, rn, pass, size);
9647             if (swap) {
9648                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
9649             } else {
9650                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
9651             }
9652             if (is_scalar) {
9653                 write_fp_sreg(s, rd, tcg_res);
9654             } else {
9655                 write_vec_element_i32(s, tcg_res, rd, pass, size);
9656             }
9657         }
9658         tcg_temp_free_i32(tcg_res);
9659         tcg_temp_free_i32(tcg_zero);
9660         tcg_temp_free_i32(tcg_op);
9661         if (!is_scalar) {
9662             clear_vec_high(s, is_q, rd);
9663         }
9664     }
9665
9666     tcg_temp_free_ptr(fpst);
9667 }
9668
9669 static void handle_2misc_reciprocal(DisasContext *s, int opcode,
9670                                     bool is_scalar, bool is_u, bool is_q,
9671                                     int size, int rn, int rd)
9672 {
9673     bool is_double = (size == 3);
9674     TCGv_ptr fpst = get_fpstatus_ptr(false);
9675
9676     if (is_double) {
9677         TCGv_i64 tcg_op = tcg_temp_new_i64();
9678         TCGv_i64 tcg_res = tcg_temp_new_i64();
9679         int pass;
9680
9681         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9682             read_vec_element(s, tcg_op, rn, pass, MO_64);
9683             switch (opcode) {
9684             case 0x3d: /* FRECPE */
9685                 gen_helper_recpe_f64(tcg_res, tcg_op, fpst);
9686                 break;
9687             case 0x3f: /* FRECPX */
9688                 gen_helper_frecpx_f64(tcg_res, tcg_op, fpst);
9689                 break;
9690             case 0x7d: /* FRSQRTE */
9691                 gen_helper_rsqrte_f64(tcg_res, tcg_op, fpst);
9692                 break;
9693             default:
9694                 g_assert_not_reached();
9695             }
9696             write_vec_element(s, tcg_res, rd, pass, MO_64);
9697         }
9698         tcg_temp_free_i64(tcg_res);
9699         tcg_temp_free_i64(tcg_op);
9700         clear_vec_high(s, !is_scalar, rd);
9701     } else {
9702         TCGv_i32 tcg_op = tcg_temp_new_i32();
9703         TCGv_i32 tcg_res = tcg_temp_new_i32();
9704         int pass, maxpasses;
9705
9706         if (is_scalar) {
9707             maxpasses = 1;
9708         } else {
9709             maxpasses = is_q ? 4 : 2;
9710         }
9711
9712         for (pass = 0; pass < maxpasses; pass++) {
9713             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
9714
9715             switch (opcode) {
9716             case 0x3c: /* URECPE */
9717                 gen_helper_recpe_u32(tcg_res, tcg_op, fpst);
9718                 break;
9719             case 0x3d: /* FRECPE */
9720                 gen_helper_recpe_f32(tcg_res, tcg_op, fpst);
9721                 break;
9722             case 0x3f: /* FRECPX */
9723                 gen_helper_frecpx_f32(tcg_res, tcg_op, fpst);
9724                 break;
9725             case 0x7d: /* FRSQRTE */
9726                 gen_helper_rsqrte_f32(tcg_res, tcg_op, fpst);
9727                 break;
9728             default:
9729                 g_assert_not_reached();
9730             }
9731
9732             if (is_scalar) {
9733                 write_fp_sreg(s, rd, tcg_res);
9734             } else {
9735                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
9736             }
9737         }
9738         tcg_temp_free_i32(tcg_res);
9739         tcg_temp_free_i32(tcg_op);
9740         if (!is_scalar) {
9741             clear_vec_high(s, is_q, rd);
9742         }
9743     }
9744     tcg_temp_free_ptr(fpst);
9745 }
9746
9747 static void handle_2misc_narrow(DisasContext *s, bool scalar,
9748                                 int opcode, bool u, bool is_q,
9749                                 int size, int rn, int rd)
9750 {
9751     /* Handle 2-reg-misc ops which are narrowing (so each 2*size element
9752      * in the source becomes a size element in the destination).
9753      */
9754     int pass;
9755     TCGv_i32 tcg_res[2];
9756     int destelt = is_q ? 2 : 0;
9757     int passes = scalar ? 1 : 2;
9758
9759     if (scalar) {
9760         tcg_res[1] = tcg_const_i32(0);
9761     }
9762
9763     for (pass = 0; pass < passes; pass++) {
9764         TCGv_i64 tcg_op = tcg_temp_new_i64();
9765         NeonGenNarrowFn *genfn = NULL;
9766         NeonGenNarrowEnvFn *genenvfn = NULL;
9767
9768         if (scalar) {
9769             read_vec_element(s, tcg_op, rn, pass, size + 1);
9770         } else {
9771             read_vec_element(s, tcg_op, rn, pass, MO_64);
9772         }
9773         tcg_res[pass] = tcg_temp_new_i32();
9774
9775         switch (opcode) {
9776         case 0x12: /* XTN, SQXTUN */
9777         {
9778             static NeonGenNarrowFn * const xtnfns[3] = {
9779                 gen_helper_neon_narrow_u8,
9780                 gen_helper_neon_narrow_u16,
9781                 tcg_gen_extrl_i64_i32,
9782             };
9783             static NeonGenNarrowEnvFn * const sqxtunfns[3] = {
9784                 gen_helper_neon_unarrow_sat8,
9785                 gen_helper_neon_unarrow_sat16,
9786                 gen_helper_neon_unarrow_sat32,
9787             };
9788             if (u) {
9789                 genenvfn = sqxtunfns[size];
9790             } else {
9791                 genfn = xtnfns[size];
9792             }
9793             break;
9794         }
9795         case 0x14: /* SQXTN, UQXTN */
9796         {
9797             static NeonGenNarrowEnvFn * const fns[3][2] = {
9798                 { gen_helper_neon_narrow_sat_s8,
9799                   gen_helper_neon_narrow_sat_u8 },
9800                 { gen_helper_neon_narrow_sat_s16,
9801                   gen_helper_neon_narrow_sat_u16 },
9802                 { gen_helper_neon_narrow_sat_s32,
9803                   gen_helper_neon_narrow_sat_u32 },
9804             };
9805             genenvfn = fns[size][u];
9806             break;
9807         }
9808         case 0x16: /* FCVTN, FCVTN2 */
9809             /* 32 bit to 16 bit or 64 bit to 32 bit float conversion */
9810             if (size == 2) {
9811                 gen_helper_vfp_fcvtsd(tcg_res[pass], tcg_op, cpu_env);
9812             } else {
9813                 TCGv_i32 tcg_lo = tcg_temp_new_i32();
9814                 TCGv_i32 tcg_hi = tcg_temp_new_i32();
9815                 TCGv_ptr fpst = get_fpstatus_ptr(false);
9816                 TCGv_i32 ahp = get_ahp_flag();
9817
9818                 tcg_gen_extr_i64_i32(tcg_lo, tcg_hi, tcg_op);
9819                 gen_helper_vfp_fcvt_f32_to_f16(tcg_lo, tcg_lo, fpst, ahp);
9820                 gen_helper_vfp_fcvt_f32_to_f16(tcg_hi, tcg_hi, fpst, ahp);
9821                 tcg_gen_deposit_i32(tcg_res[pass], tcg_lo, tcg_hi, 16, 16);
9822                 tcg_temp_free_i32(tcg_lo);
9823                 tcg_temp_free_i32(tcg_hi);
9824                 tcg_temp_free_ptr(fpst);
9825                 tcg_temp_free_i32(ahp);
9826             }
9827             break;
9828         case 0x56:  /* FCVTXN, FCVTXN2 */
9829             /* 64 bit to 32 bit float conversion
9830              * with von Neumann rounding (round to odd)
9831              */
9832             assert(size == 2);
9833             gen_helper_fcvtx_f64_to_f32(tcg_res[pass], tcg_op, cpu_env);
9834             break;
9835         default:
9836             g_assert_not_reached();
9837         }
9838
9839         if (genfn) {
9840             genfn(tcg_res[pass], tcg_op);
9841         } else if (genenvfn) {
9842             genenvfn(tcg_res[pass], cpu_env, tcg_op);
9843         }
9844
9845         tcg_temp_free_i64(tcg_op);
9846     }
9847
9848     for (pass = 0; pass < 2; pass++) {
9849         write_vec_element_i32(s, tcg_res[pass], rd, destelt + pass, MO_32);
9850         tcg_temp_free_i32(tcg_res[pass]);
9851     }
9852     clear_vec_high(s, is_q, rd);
9853 }
9854
9855 /* Remaining saturating accumulating ops */
9856 static void handle_2misc_satacc(DisasContext *s, bool is_scalar, bool is_u,
9857                                 bool is_q, int size, int rn, int rd)
9858 {
9859     bool is_double = (size == 3);
9860
9861     if (is_double) {
9862         TCGv_i64 tcg_rn = tcg_temp_new_i64();
9863         TCGv_i64 tcg_rd = tcg_temp_new_i64();
9864         int pass;
9865
9866         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9867             read_vec_element(s, tcg_rn, rn, pass, MO_64);
9868             read_vec_element(s, tcg_rd, rd, pass, MO_64);
9869
9870             if (is_u) { /* USQADD */
9871                 gen_helper_neon_uqadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9872             } else { /* SUQADD */
9873                 gen_helper_neon_sqadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9874             }
9875             write_vec_element(s, tcg_rd, rd, pass, MO_64);
9876         }
9877         tcg_temp_free_i64(tcg_rd);
9878         tcg_temp_free_i64(tcg_rn);
9879         clear_vec_high(s, !is_scalar, rd);
9880     } else {
9881         TCGv_i32 tcg_rn = tcg_temp_new_i32();
9882         TCGv_i32 tcg_rd = tcg_temp_new_i32();
9883         int pass, maxpasses;
9884
9885         if (is_scalar) {
9886             maxpasses = 1;
9887         } else {
9888             maxpasses = is_q ? 4 : 2;
9889         }
9890
9891         for (pass = 0; pass < maxpasses; pass++) {
9892             if (is_scalar) {
9893                 read_vec_element_i32(s, tcg_rn, rn, pass, size);
9894                 read_vec_element_i32(s, tcg_rd, rd, pass, size);
9895             } else {
9896                 read_vec_element_i32(s, tcg_rn, rn, pass, MO_32);
9897                 read_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
9898             }
9899
9900             if (is_u) { /* USQADD */
9901                 switch (size) {
9902                 case 0:
9903                     gen_helper_neon_uqadd_s8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9904                     break;
9905                 case 1:
9906                     gen_helper_neon_uqadd_s16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9907                     break;
9908                 case 2:
9909                     gen_helper_neon_uqadd_s32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9910                     break;
9911                 default:
9912                     g_assert_not_reached();
9913                 }
9914             } else { /* SUQADD */
9915                 switch (size) {
9916                 case 0:
9917                     gen_helper_neon_sqadd_u8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9918                     break;
9919                 case 1:
9920                     gen_helper_neon_sqadd_u16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9921                     break;
9922                 case 2:
9923                     gen_helper_neon_sqadd_u32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9924                     break;
9925                 default:
9926                     g_assert_not_reached();
9927                 }
9928             }
9929
9930             if (is_scalar) {
9931                 TCGv_i64 tcg_zero = tcg_const_i64(0);
9932                 write_vec_element(s, tcg_zero, rd, 0, MO_64);
9933                 tcg_temp_free_i64(tcg_zero);
9934             }
9935             write_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
9936         }
9937         tcg_temp_free_i32(tcg_rd);
9938         tcg_temp_free_i32(tcg_rn);
9939         clear_vec_high(s, is_q, rd);
9940     }
9941 }
9942
9943 /* AdvSIMD scalar two reg misc
9944  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
9945  * +-----+---+-----------+------+-----------+--------+-----+------+------+
9946  * | 0 1 | U | 1 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
9947  * +-----+---+-----------+------+-----------+--------+-----+------+------+
9948  */
9949 static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
9950 {
9951     int rd = extract32(insn, 0, 5);
9952     int rn = extract32(insn, 5, 5);
9953     int opcode = extract32(insn, 12, 5);
9954     int size = extract32(insn, 22, 2);
9955     bool u = extract32(insn, 29, 1);
9956     bool is_fcvt = false;
9957     int rmode;
9958     TCGv_i32 tcg_rmode;
9959     TCGv_ptr tcg_fpstatus;
9960
9961     switch (opcode) {
9962     case 0x3: /* USQADD / SUQADD*/
9963         if (!fp_access_check(s)) {
9964             return;
9965         }
9966         handle_2misc_satacc(s, true, u, false, size, rn, rd);
9967         return;
9968     case 0x7: /* SQABS / SQNEG */
9969         break;
9970     case 0xa: /* CMLT */
9971         if (u) {
9972             unallocated_encoding(s);
9973             return;
9974         }
9975         /* fall through */
9976     case 0x8: /* CMGT, CMGE */
9977     case 0x9: /* CMEQ, CMLE */
9978     case 0xb: /* ABS, NEG */
9979         if (size != 3) {
9980             unallocated_encoding(s);
9981             return;
9982         }
9983         break;
9984     case 0x12: /* SQXTUN */
9985         if (!u) {
9986             unallocated_encoding(s);
9987             return;
9988         }
9989         /* fall through */
9990     case 0x14: /* SQXTN, UQXTN */
9991         if (size == 3) {
9992             unallocated_encoding(s);
9993             return;
9994         }
9995         if (!fp_access_check(s)) {
9996             return;
9997         }
9998         handle_2misc_narrow(s, true, opcode, u, false, size, rn, rd);
9999         return;
10000     case 0xc ... 0xf:
10001     case 0x16 ... 0x1d:
10002     case 0x1f:
10003         /* Floating point: U, size[1] and opcode indicate operation;
10004          * size[0] indicates single or double precision.
10005          */
10006         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
10007         size = extract32(size, 0, 1) ? 3 : 2;
10008         switch (opcode) {
10009         case 0x2c: /* FCMGT (zero) */
10010         case 0x2d: /* FCMEQ (zero) */
10011         case 0x2e: /* FCMLT (zero) */
10012         case 0x6c: /* FCMGE (zero) */
10013         case 0x6d: /* FCMLE (zero) */
10014             handle_2misc_fcmp_zero(s, opcode, true, u, true, size, rn, rd);
10015             return;
10016         case 0x1d: /* SCVTF */
10017         case 0x5d: /* UCVTF */
10018         {
10019             bool is_signed = (opcode == 0x1d);
10020             if (!fp_access_check(s)) {
10021                 return;
10022             }
10023             handle_simd_intfp_conv(s, rd, rn, 1, is_signed, 0, size);
10024             return;
10025         }
10026         case 0x3d: /* FRECPE */
10027         case 0x3f: /* FRECPX */
10028         case 0x7d: /* FRSQRTE */
10029             if (!fp_access_check(s)) {
10030                 return;
10031             }
10032             handle_2misc_reciprocal(s, opcode, true, u, true, size, rn, rd);
10033             return;
10034         case 0x1a: /* FCVTNS */
10035         case 0x1b: /* FCVTMS */
10036         case 0x3a: /* FCVTPS */
10037         case 0x3b: /* FCVTZS */
10038         case 0x5a: /* FCVTNU */
10039         case 0x5b: /* FCVTMU */
10040         case 0x7a: /* FCVTPU */
10041         case 0x7b: /* FCVTZU */
10042             is_fcvt = true;
10043             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
10044             break;
10045         case 0x1c: /* FCVTAS */
10046         case 0x5c: /* FCVTAU */
10047             /* TIEAWAY doesn't fit in the usual rounding mode encoding */
10048             is_fcvt = true;
10049             rmode = FPROUNDING_TIEAWAY;
10050             break;
10051         case 0x56: /* FCVTXN, FCVTXN2 */
10052             if (size == 2) {
10053                 unallocated_encoding(s);
10054                 return;
10055             }
10056             if (!fp_access_check(s)) {
10057                 return;
10058             }
10059             handle_2misc_narrow(s, true, opcode, u, false, size - 1, rn, rd);
10060             return;
10061         default:
10062             unallocated_encoding(s);
10063             return;
10064         }
10065         break;
10066     default:
10067         unallocated_encoding(s);
10068         return;
10069     }
10070
10071     if (!fp_access_check(s)) {
10072         return;
10073     }
10074
10075     if (is_fcvt) {
10076         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
10077         tcg_fpstatus = get_fpstatus_ptr(false);
10078         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
10079     } else {
10080         tcg_rmode = NULL;
10081         tcg_fpstatus = NULL;
10082     }
10083
10084     if (size == 3) {
10085         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
10086         TCGv_i64 tcg_rd = tcg_temp_new_i64();
10087
10088         handle_2misc_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rmode, tcg_fpstatus);
10089         write_fp_dreg(s, rd, tcg_rd);
10090         tcg_temp_free_i64(tcg_rd);
10091         tcg_temp_free_i64(tcg_rn);
10092     } else {
10093         TCGv_i32 tcg_rn = tcg_temp_new_i32();
10094         TCGv_i32 tcg_rd = tcg_temp_new_i32();
10095
10096         read_vec_element_i32(s, tcg_rn, rn, 0, size);
10097
10098         switch (opcode) {
10099         case 0x7: /* SQABS, SQNEG */
10100         {
10101             NeonGenOneOpEnvFn *genfn;
10102             static NeonGenOneOpEnvFn * const fns[3][2] = {
10103                 { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
10104                 { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
10105                 { gen_helper_neon_qabs_s32, gen_helper_neon_qneg_s32 },
10106             };
10107             genfn = fns[size][u];
10108             genfn(tcg_rd, cpu_env, tcg_rn);
10109             break;
10110         }
10111         case 0x1a: /* FCVTNS */
10112         case 0x1b: /* FCVTMS */
10113         case 0x1c: /* FCVTAS */
10114         case 0x3a: /* FCVTPS */
10115         case 0x3b: /* FCVTZS */
10116         {
10117             TCGv_i32 tcg_shift = tcg_const_i32(0);
10118             gen_helper_vfp_tosls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
10119             tcg_temp_free_i32(tcg_shift);
10120             break;
10121         }
10122         case 0x5a: /* FCVTNU */
10123         case 0x5b: /* FCVTMU */
10124         case 0x5c: /* FCVTAU */
10125         case 0x7a: /* FCVTPU */
10126         case 0x7b: /* FCVTZU */
10127         {
10128             TCGv_i32 tcg_shift = tcg_const_i32(0);
10129             gen_helper_vfp_touls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
10130             tcg_temp_free_i32(tcg_shift);
10131             break;
10132         }
10133         default:
10134             g_assert_not_reached();
10135         }
10136
10137         write_fp_sreg(s, rd, tcg_rd);
10138         tcg_temp_free_i32(tcg_rd);
10139         tcg_temp_free_i32(tcg_rn);
10140     }
10141
10142     if (is_fcvt) {
10143         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
10144         tcg_temp_free_i32(tcg_rmode);
10145         tcg_temp_free_ptr(tcg_fpstatus);
10146     }
10147 }
10148
10149 /* SSHR[RA]/USHR[RA] - Vector shift right (optional rounding/accumulate) */
10150 static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
10151                                  int immh, int immb, int opcode, int rn, int rd)
10152 {
10153     int size = 32 - clz32(immh) - 1;
10154     int immhb = immh << 3 | immb;
10155     int shift = 2 * (8 << size) - immhb;
10156     bool accumulate = false;
10157     int dsize = is_q ? 128 : 64;
10158     int esize = 8 << size;
10159     int elements = dsize/esize;
10160     TCGMemOp memop = size | (is_u ? 0 : MO_SIGN);
10161     TCGv_i64 tcg_rn = new_tmp_a64(s);
10162     TCGv_i64 tcg_rd = new_tmp_a64(s);
10163     TCGv_i64 tcg_round;
10164     uint64_t round_const;
10165     int i;
10166
10167     if (extract32(immh, 3, 1) && !is_q) {
10168         unallocated_encoding(s);
10169         return;
10170     }
10171     tcg_debug_assert(size <= 3);
10172
10173     if (!fp_access_check(s)) {
10174         return;
10175     }
10176
10177     switch (opcode) {
10178     case 0x02: /* SSRA / USRA (accumulate) */
10179         if (is_u) {
10180             /* Shift count same as element size produces zero to add.  */
10181             if (shift == 8 << size) {
10182                 goto done;
10183             }
10184             gen_gvec_op2i(s, is_q, rd, rn, shift, &usra_op[size]);
10185         } else {
10186             /* Shift count same as element size produces all sign to add.  */
10187             if (shift == 8 << size) {
10188                 shift -= 1;
10189             }
10190             gen_gvec_op2i(s, is_q, rd, rn, shift, &ssra_op[size]);
10191         }
10192         return;
10193     case 0x08: /* SRI */
10194         /* Shift count same as element size is valid but does nothing.  */
10195         if (shift == 8 << size) {
10196             goto done;
10197         }
10198         gen_gvec_op2i(s, is_q, rd, rn, shift, &sri_op[size]);
10199         return;
10200
10201     case 0x00: /* SSHR / USHR */
10202         if (is_u) {
10203             if (shift == 8 << size) {
10204                 /* Shift count the same size as element size produces zero.  */
10205                 tcg_gen_gvec_dup8i(vec_full_reg_offset(s, rd),
10206                                    is_q ? 16 : 8, vec_full_reg_size(s), 0);
10207             } else {
10208                 gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shri, size);
10209             }
10210         } else {
10211             /* Shift count the same size as element size produces all sign.  */
10212             if (shift == 8 << size) {
10213                 shift -= 1;
10214             }
10215             gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_sari, size);
10216         }
10217         return;
10218
10219     case 0x04: /* SRSHR / URSHR (rounding) */
10220         break;
10221     case 0x06: /* SRSRA / URSRA (accum + rounding) */
10222         accumulate = true;
10223         break;
10224     default:
10225         g_assert_not_reached();
10226     }
10227
10228     round_const = 1ULL << (shift - 1);
10229     tcg_round = tcg_const_i64(round_const);
10230
10231     for (i = 0; i < elements; i++) {
10232         read_vec_element(s, tcg_rn, rn, i, memop);
10233         if (accumulate) {
10234             read_vec_element(s, tcg_rd, rd, i, memop);
10235         }
10236
10237         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
10238                                 accumulate, is_u, size, shift);
10239
10240         write_vec_element(s, tcg_rd, rd, i, size);
10241     }
10242     tcg_temp_free_i64(tcg_round);
10243
10244  done:
10245     clear_vec_high(s, is_q, rd);
10246 }
10247
10248 /* SHL/SLI - Vector shift left */
10249 static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
10250                                  int immh, int immb, int opcode, int rn, int rd)
10251 {
10252     int size = 32 - clz32(immh) - 1;
10253     int immhb = immh << 3 | immb;
10254     int shift = immhb - (8 << size);
10255
10256     /* Range of size is limited by decode: immh is a non-zero 4 bit field */
10257     assert(size >= 0 && size <= 3);
10258
10259     if (extract32(immh, 3, 1) && !is_q) {
10260         unallocated_encoding(s);
10261         return;
10262     }
10263
10264     if (!fp_access_check(s)) {
10265         return;
10266     }
10267
10268     if (insert) {
10269         gen_gvec_op2i(s, is_q, rd, rn, shift, &sli_op[size]);
10270     } else {
10271         gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shli, size);
10272     }
10273 }
10274
10275 /* USHLL/SHLL - Vector shift left with widening */
10276 static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u,
10277                                  int immh, int immb, int opcode, int rn, int rd)
10278 {
10279     int size = 32 - clz32(immh) - 1;
10280     int immhb = immh << 3 | immb;
10281     int shift = immhb - (8 << size);
10282     int dsize = 64;
10283     int esize = 8 << size;
10284     int elements = dsize/esize;
10285     TCGv_i64 tcg_rn = new_tmp_a64(s);
10286     TCGv_i64 tcg_rd = new_tmp_a64(s);
10287     int i;
10288
10289     if (size >= 3) {
10290         unallocated_encoding(s);
10291         return;
10292     }
10293
10294     if (!fp_access_check(s)) {
10295         return;
10296     }
10297
10298     /* For the LL variants the store is larger than the load,
10299      * so if rd == rn we would overwrite parts of our input.
10300      * So load everything right now and use shifts in the main loop.
10301      */
10302     read_vec_element(s, tcg_rn, rn, is_q ? 1 : 0, MO_64);
10303
10304     for (i = 0; i < elements; i++) {
10305         tcg_gen_shri_i64(tcg_rd, tcg_rn, i * esize);
10306         ext_and_shift_reg(tcg_rd, tcg_rd, size | (!is_u << 2), 0);
10307         tcg_gen_shli_i64(tcg_rd, tcg_rd, shift);
10308         write_vec_element(s, tcg_rd, rd, i, size + 1);
10309     }
10310 }
10311
10312 /* SHRN/RSHRN - Shift right with narrowing (and potential rounding) */
10313 static void handle_vec_simd_shrn(DisasContext *s, bool is_q,
10314                                  int immh, int immb, int opcode, int rn, int rd)
10315 {
10316     int immhb = immh << 3 | immb;
10317     int size = 32 - clz32(immh) - 1;
10318     int dsize = 64;
10319     int esize = 8 << size;
10320     int elements = dsize/esize;
10321     int shift = (2 * esize) - immhb;
10322     bool round = extract32(opcode, 0, 1);
10323     TCGv_i64 tcg_rn, tcg_rd, tcg_final;
10324     TCGv_i64 tcg_round;
10325     int i;
10326
10327     if (extract32(immh, 3, 1)) {
10328         unallocated_encoding(s);
10329         return;
10330     }
10331
10332     if (!fp_access_check(s)) {
10333         return;
10334     }
10335
10336     tcg_rn = tcg_temp_new_i64();
10337     tcg_rd = tcg_temp_new_i64();
10338     tcg_final = tcg_temp_new_i64();
10339     read_vec_element(s, tcg_final, rd, is_q ? 1 : 0, MO_64);
10340
10341     if (round) {
10342         uint64_t round_const = 1ULL << (shift - 1);
10343         tcg_round = tcg_const_i64(round_const);
10344     } else {
10345         tcg_round = NULL;
10346     }
10347
10348     for (i = 0; i < elements; i++) {
10349         read_vec_element(s, tcg_rn, rn, i, size+1);
10350         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
10351                                 false, true, size+1, shift);
10352
10353         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
10354     }
10355
10356     if (!is_q) {
10357         write_vec_element(s, tcg_final, rd, 0, MO_64);
10358     } else {
10359         write_vec_element(s, tcg_final, rd, 1, MO_64);
10360     }
10361     if (round) {
10362         tcg_temp_free_i64(tcg_round);
10363     }
10364     tcg_temp_free_i64(tcg_rn);
10365     tcg_temp_free_i64(tcg_rd);
10366     tcg_temp_free_i64(tcg_final);
10367
10368     clear_vec_high(s, is_q, rd);
10369 }
10370
10371
10372 /* AdvSIMD shift by immediate
10373  *  31  30   29 28         23 22  19 18  16 15    11  10 9    5 4    0
10374  * +---+---+---+-------------+------+------+--------+---+------+------+
10375  * | 0 | Q | U | 0 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
10376  * +---+---+---+-------------+------+------+--------+---+------+------+
10377  */
10378 static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
10379 {
10380     int rd = extract32(insn, 0, 5);
10381     int rn = extract32(insn, 5, 5);
10382     int opcode = extract32(insn, 11, 5);
10383     int immb = extract32(insn, 16, 3);
10384     int immh = extract32(insn, 19, 4);
10385     bool is_u = extract32(insn, 29, 1);
10386     bool is_q = extract32(insn, 30, 1);
10387
10388     switch (opcode) {
10389     case 0x08: /* SRI */
10390         if (!is_u) {
10391             unallocated_encoding(s);
10392             return;
10393         }
10394         /* fall through */
10395     case 0x00: /* SSHR / USHR */
10396     case 0x02: /* SSRA / USRA (accumulate) */
10397     case 0x04: /* SRSHR / URSHR (rounding) */
10398     case 0x06: /* SRSRA / URSRA (accum + rounding) */
10399         handle_vec_simd_shri(s, is_q, is_u, immh, immb, opcode, rn, rd);
10400         break;
10401     case 0x0a: /* SHL / SLI */
10402         handle_vec_simd_shli(s, is_q, is_u, immh, immb, opcode, rn, rd);
10403         break;
10404     case 0x10: /* SHRN */
10405     case 0x11: /* RSHRN / SQRSHRUN */
10406         if (is_u) {
10407             handle_vec_simd_sqshrn(s, false, is_q, false, true, immh, immb,
10408                                    opcode, rn, rd);
10409         } else {
10410             handle_vec_simd_shrn(s, is_q, immh, immb, opcode, rn, rd);
10411         }
10412         break;
10413     case 0x12: /* SQSHRN / UQSHRN */
10414     case 0x13: /* SQRSHRN / UQRSHRN */
10415         handle_vec_simd_sqshrn(s, false, is_q, is_u, is_u, immh, immb,
10416                                opcode, rn, rd);
10417         break;
10418     case 0x14: /* SSHLL / USHLL */
10419         handle_vec_simd_wshli(s, is_q, is_u, immh, immb, opcode, rn, rd);
10420         break;
10421     case 0x1c: /* SCVTF / UCVTF */
10422         handle_simd_shift_intfp_conv(s, false, is_q, is_u, immh, immb,
10423                                      opcode, rn, rd);
10424         break;
10425     case 0xc: /* SQSHLU */
10426         if (!is_u) {
10427             unallocated_encoding(s);
10428             return;
10429         }
10430         handle_simd_qshl(s, false, is_q, false, true, immh, immb, rn, rd);
10431         break;
10432     case 0xe: /* SQSHL, UQSHL */
10433         handle_simd_qshl(s, false, is_q, is_u, is_u, immh, immb, rn, rd);
10434         break;
10435     case 0x1f: /* FCVTZS/ FCVTZU */
10436         handle_simd_shift_fpint_conv(s, false, is_q, is_u, immh, immb, rn, rd);
10437         return;
10438     default:
10439         unallocated_encoding(s);
10440         return;
10441     }
10442 }
10443
10444 /* Generate code to do a "long" addition or subtraction, ie one done in
10445  * TCGv_i64 on vector lanes twice the width specified by size.
10446  */
10447 static void gen_neon_addl(int size, bool is_sub, TCGv_i64 tcg_res,
10448                           TCGv_i64 tcg_op1, TCGv_i64 tcg_op2)
10449 {
10450     static NeonGenTwo64OpFn * const fns[3][2] = {
10451         { gen_helper_neon_addl_u16, gen_helper_neon_subl_u16 },
10452         { gen_helper_neon_addl_u32, gen_helper_neon_subl_u32 },
10453         { tcg_gen_add_i64, tcg_gen_sub_i64 },
10454     };
10455     NeonGenTwo64OpFn *genfn;
10456     assert(size < 3);
10457
10458     genfn = fns[size][is_sub];
10459     genfn(tcg_res, tcg_op1, tcg_op2);
10460 }
10461
10462 static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
10463                                 int opcode, int rd, int rn, int rm)
10464 {
10465     /* 3-reg-different widening insns: 64 x 64 -> 128 */
10466     TCGv_i64 tcg_res[2];
10467     int pass, accop;
10468
10469     tcg_res[0] = tcg_temp_new_i64();
10470     tcg_res[1] = tcg_temp_new_i64();
10471
10472     /* Does this op do an adding accumulate, a subtracting accumulate,
10473      * or no accumulate at all?
10474      */
10475     switch (opcode) {
10476     case 5:
10477     case 8:
10478     case 9:
10479         accop = 1;
10480         break;
10481     case 10:
10482     case 11:
10483         accop = -1;
10484         break;
10485     default:
10486         accop = 0;
10487         break;
10488     }
10489
10490     if (accop != 0) {
10491         read_vec_element(s, tcg_res[0], rd, 0, MO_64);
10492         read_vec_element(s, tcg_res[1], rd, 1, MO_64);
10493     }
10494
10495     /* size == 2 means two 32x32->64 operations; this is worth special
10496      * casing because we can generally handle it inline.
10497      */
10498     if (size == 2) {
10499         for (pass = 0; pass < 2; pass++) {
10500             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10501             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10502             TCGv_i64 tcg_passres;
10503             TCGMemOp memop = MO_32 | (is_u ? 0 : MO_SIGN);
10504
10505             int elt = pass + is_q * 2;
10506
10507             read_vec_element(s, tcg_op1, rn, elt, memop);
10508             read_vec_element(s, tcg_op2, rm, elt, memop);
10509
10510             if (accop == 0) {
10511                 tcg_passres = tcg_res[pass];
10512             } else {
10513                 tcg_passres = tcg_temp_new_i64();
10514             }
10515
10516             switch (opcode) {
10517             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10518                 tcg_gen_add_i64(tcg_passres, tcg_op1, tcg_op2);
10519                 break;
10520             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10521                 tcg_gen_sub_i64(tcg_passres, tcg_op1, tcg_op2);
10522                 break;
10523             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10524             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10525             {
10526                 TCGv_i64 tcg_tmp1 = tcg_temp_new_i64();
10527                 TCGv_i64 tcg_tmp2 = tcg_temp_new_i64();
10528
10529                 tcg_gen_sub_i64(tcg_tmp1, tcg_op1, tcg_op2);
10530                 tcg_gen_sub_i64(tcg_tmp2, tcg_op2, tcg_op1);
10531                 tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
10532                                     tcg_passres,
10533                                     tcg_op1, tcg_op2, tcg_tmp1, tcg_tmp2);
10534                 tcg_temp_free_i64(tcg_tmp1);
10535                 tcg_temp_free_i64(tcg_tmp2);
10536                 break;
10537             }
10538             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10539             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10540             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
10541                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
10542                 break;
10543             case 9: /* SQDMLAL, SQDMLAL2 */
10544             case 11: /* SQDMLSL, SQDMLSL2 */
10545             case 13: /* SQDMULL, SQDMULL2 */
10546                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
10547                 gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
10548                                                   tcg_passres, tcg_passres);
10549                 break;
10550             default:
10551                 g_assert_not_reached();
10552             }
10553
10554             if (opcode == 9 || opcode == 11) {
10555                 /* saturating accumulate ops */
10556                 if (accop < 0) {
10557                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
10558                 }
10559                 gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
10560                                                   tcg_res[pass], tcg_passres);
10561             } else if (accop > 0) {
10562                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10563             } else if (accop < 0) {
10564                 tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10565             }
10566
10567             if (accop != 0) {
10568                 tcg_temp_free_i64(tcg_passres);
10569             }
10570
10571             tcg_temp_free_i64(tcg_op1);
10572             tcg_temp_free_i64(tcg_op2);
10573         }
10574     } else {
10575         /* size 0 or 1, generally helper functions */
10576         for (pass = 0; pass < 2; pass++) {
10577             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
10578             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10579             TCGv_i64 tcg_passres;
10580             int elt = pass + is_q * 2;
10581
10582             read_vec_element_i32(s, tcg_op1, rn, elt, MO_32);
10583             read_vec_element_i32(s, tcg_op2, rm, elt, MO_32);
10584
10585             if (accop == 0) {
10586                 tcg_passres = tcg_res[pass];
10587             } else {
10588                 tcg_passres = tcg_temp_new_i64();
10589             }
10590
10591             switch (opcode) {
10592             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10593             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10594             {
10595                 TCGv_i64 tcg_op2_64 = tcg_temp_new_i64();
10596                 static NeonGenWidenFn * const widenfns[2][2] = {
10597                     { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
10598                     { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
10599                 };
10600                 NeonGenWidenFn *widenfn = widenfns[size][is_u];
10601
10602                 widenfn(tcg_op2_64, tcg_op2);
10603                 widenfn(tcg_passres, tcg_op1);
10604                 gen_neon_addl(size, (opcode == 2), tcg_passres,
10605                               tcg_passres, tcg_op2_64);
10606                 tcg_temp_free_i64(tcg_op2_64);
10607                 break;
10608             }
10609             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10610             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10611                 if (size == 0) {
10612                     if (is_u) {
10613                         gen_helper_neon_abdl_u16(tcg_passres, tcg_op1, tcg_op2);
10614                     } else {
10615                         gen_helper_neon_abdl_s16(tcg_passres, tcg_op1, tcg_op2);
10616                     }
10617                 } else {
10618                     if (is_u) {
10619                         gen_helper_neon_abdl_u32(tcg_passres, tcg_op1, tcg_op2);
10620                     } else {
10621                         gen_helper_neon_abdl_s32(tcg_passres, tcg_op1, tcg_op2);
10622                     }
10623                 }
10624                 break;
10625             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10626             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10627             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
10628                 if (size == 0) {
10629                     if (is_u) {
10630                         gen_helper_neon_mull_u8(tcg_passres, tcg_op1, tcg_op2);
10631                     } else {
10632                         gen_helper_neon_mull_s8(tcg_passres, tcg_op1, tcg_op2);
10633                     }
10634                 } else {
10635                     if (is_u) {
10636                         gen_helper_neon_mull_u16(tcg_passres, tcg_op1, tcg_op2);
10637                     } else {
10638                         gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
10639                     }
10640                 }
10641                 break;
10642             case 9: /* SQDMLAL, SQDMLAL2 */
10643             case 11: /* SQDMLSL, SQDMLSL2 */
10644             case 13: /* SQDMULL, SQDMULL2 */
10645                 assert(size == 1);
10646                 gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
10647                 gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
10648                                                   tcg_passres, tcg_passres);
10649                 break;
10650             case 14: /* PMULL */
10651                 assert(size == 0);
10652                 gen_helper_neon_mull_p8(tcg_passres, tcg_op1, tcg_op2);
10653                 break;
10654             default:
10655                 g_assert_not_reached();
10656             }
10657             tcg_temp_free_i32(tcg_op1);
10658             tcg_temp_free_i32(tcg_op2);
10659
10660             if (accop != 0) {
10661                 if (opcode == 9 || opcode == 11) {
10662                     /* saturating accumulate ops */
10663                     if (accop < 0) {
10664                         gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
10665                     }
10666                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
10667                                                       tcg_res[pass],
10668                                                       tcg_passres);
10669                 } else {
10670                     gen_neon_addl(size, (accop < 0), tcg_res[pass],
10671                                   tcg_res[pass], tcg_passres);
10672                 }
10673                 tcg_temp_free_i64(tcg_passres);
10674             }
10675         }
10676     }
10677
10678     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
10679     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
10680     tcg_temp_free_i64(tcg_res[0]);
10681     tcg_temp_free_i64(tcg_res[1]);
10682 }
10683
10684 static void handle_3rd_wide(DisasContext *s, int is_q, int is_u, int size,
10685                             int opcode, int rd, int rn, int rm)
10686 {
10687     TCGv_i64 tcg_res[2];
10688     int part = is_q ? 2 : 0;
10689     int pass;
10690
10691     for (pass = 0; pass < 2; pass++) {
10692         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10693         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10694         TCGv_i64 tcg_op2_wide = tcg_temp_new_i64();
10695         static NeonGenWidenFn * const widenfns[3][2] = {
10696             { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
10697             { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
10698             { tcg_gen_ext_i32_i64, tcg_gen_extu_i32_i64 },
10699         };
10700         NeonGenWidenFn *widenfn = widenfns[size][is_u];
10701
10702         read_vec_element(s, tcg_op1, rn, pass, MO_64);
10703         read_vec_element_i32(s, tcg_op2, rm, part + pass, MO_32);
10704         widenfn(tcg_op2_wide, tcg_op2);
10705         tcg_temp_free_i32(tcg_op2);
10706         tcg_res[pass] = tcg_temp_new_i64();
10707         gen_neon_addl(size, (opcode == 3),
10708                       tcg_res[pass], tcg_op1, tcg_op2_wide);
10709         tcg_temp_free_i64(tcg_op1);
10710         tcg_temp_free_i64(tcg_op2_wide);
10711     }
10712
10713     for (pass = 0; pass < 2; pass++) {
10714         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
10715         tcg_temp_free_i64(tcg_res[pass]);
10716     }
10717 }
10718
10719 static void do_narrow_round_high_u32(TCGv_i32 res, TCGv_i64 in)
10720 {
10721     tcg_gen_addi_i64(in, in, 1U << 31);
10722     tcg_gen_extrh_i64_i32(res, in);
10723 }
10724
10725 static void handle_3rd_narrowing(DisasContext *s, int is_q, int is_u, int size,
10726                                  int opcode, int rd, int rn, int rm)
10727 {
10728     TCGv_i32 tcg_res[2];
10729     int part = is_q ? 2 : 0;
10730     int pass;
10731
10732     for (pass = 0; pass < 2; pass++) {
10733         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10734         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10735         TCGv_i64 tcg_wideres = tcg_temp_new_i64();
10736         static NeonGenNarrowFn * const narrowfns[3][2] = {
10737             { gen_helper_neon_narrow_high_u8,
10738               gen_helper_neon_narrow_round_high_u8 },
10739             { gen_helper_neon_narrow_high_u16,
10740               gen_helper_neon_narrow_round_high_u16 },
10741             { tcg_gen_extrh_i64_i32, do_narrow_round_high_u32 },
10742         };
10743         NeonGenNarrowFn *gennarrow = narrowfns[size][is_u];
10744
10745         read_vec_element(s, tcg_op1, rn, pass, MO_64);
10746         read_vec_element(s, tcg_op2, rm, pass, MO_64);
10747
10748         gen_neon_addl(size, (opcode == 6), tcg_wideres, tcg_op1, tcg_op2);
10749
10750         tcg_temp_free_i64(tcg_op1);
10751         tcg_temp_free_i64(tcg_op2);
10752
10753         tcg_res[pass] = tcg_temp_new_i32();
10754         gennarrow(tcg_res[pass], tcg_wideres);
10755         tcg_temp_free_i64(tcg_wideres);
10756     }
10757
10758     for (pass = 0; pass < 2; pass++) {
10759         write_vec_element_i32(s, tcg_res[pass], rd, pass + part, MO_32);
10760         tcg_temp_free_i32(tcg_res[pass]);
10761     }
10762     clear_vec_high(s, is_q, rd);
10763 }
10764
10765 static void handle_pmull_64(DisasContext *s, int is_q, int rd, int rn, int rm)
10766 {
10767     /* PMULL of 64 x 64 -> 128 is an odd special case because it
10768      * is the only three-reg-diff instruction which produces a
10769      * 128-bit wide result from a single operation. However since
10770      * it's possible to calculate the two halves more or less
10771      * separately we just use two helper calls.
10772      */
10773     TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10774     TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10775     TCGv_i64 tcg_res = tcg_temp_new_i64();
10776
10777     read_vec_element(s, tcg_op1, rn, is_q, MO_64);
10778     read_vec_element(s, tcg_op2, rm, is_q, MO_64);
10779     gen_helper_neon_pmull_64_lo(tcg_res, tcg_op1, tcg_op2);
10780     write_vec_element(s, tcg_res, rd, 0, MO_64);
10781     gen_helper_neon_pmull_64_hi(tcg_res, tcg_op1, tcg_op2);
10782     write_vec_element(s, tcg_res, rd, 1, MO_64);
10783
10784     tcg_temp_free_i64(tcg_op1);
10785     tcg_temp_free_i64(tcg_op2);
10786     tcg_temp_free_i64(tcg_res);
10787 }
10788
10789 /* AdvSIMD three different
10790  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
10791  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
10792  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
10793  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
10794  */
10795 static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
10796 {
10797     /* Instructions in this group fall into three basic classes
10798      * (in each case with the operation working on each element in
10799      * the input vectors):
10800      * (1) widening 64 x 64 -> 128 (with possibly Vd as an extra
10801      *     128 bit input)
10802      * (2) wide 64 x 128 -> 128
10803      * (3) narrowing 128 x 128 -> 64
10804      * Here we do initial decode, catch unallocated cases and
10805      * dispatch to separate functions for each class.
10806      */
10807     int is_q = extract32(insn, 30, 1);
10808     int is_u = extract32(insn, 29, 1);
10809     int size = extract32(insn, 22, 2);
10810     int opcode = extract32(insn, 12, 4);
10811     int rm = extract32(insn, 16, 5);
10812     int rn = extract32(insn, 5, 5);
10813     int rd = extract32(insn, 0, 5);
10814
10815     switch (opcode) {
10816     case 1: /* SADDW, SADDW2, UADDW, UADDW2 */
10817     case 3: /* SSUBW, SSUBW2, USUBW, USUBW2 */
10818         /* 64 x 128 -> 128 */
10819         if (size == 3) {
10820             unallocated_encoding(s);
10821             return;
10822         }
10823         if (!fp_access_check(s)) {
10824             return;
10825         }
10826         handle_3rd_wide(s, is_q, is_u, size, opcode, rd, rn, rm);
10827         break;
10828     case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */
10829     case 6: /* SUBHN, SUBHN2, RSUBHN, RSUBHN2 */
10830         /* 128 x 128 -> 64 */
10831         if (size == 3) {
10832             unallocated_encoding(s);
10833             return;
10834         }
10835         if (!fp_access_check(s)) {
10836             return;
10837         }
10838         handle_3rd_narrowing(s, is_q, is_u, size, opcode, rd, rn, rm);
10839         break;
10840     case 14: /* PMULL, PMULL2 */
10841         if (is_u || size == 1 || size == 2) {
10842             unallocated_encoding(s);
10843             return;
10844         }
10845         if (size == 3) {
10846             if (!dc_isar_feature(aa64_pmull, s)) {
10847                 unallocated_encoding(s);
10848                 return;
10849             }
10850             if (!fp_access_check(s)) {
10851                 return;
10852             }
10853             handle_pmull_64(s, is_q, rd, rn, rm);
10854             return;
10855         }
10856         goto is_widening;
10857     case 9: /* SQDMLAL, SQDMLAL2 */
10858     case 11: /* SQDMLSL, SQDMLSL2 */
10859     case 13: /* SQDMULL, SQDMULL2 */
10860         if (is_u || size == 0) {
10861             unallocated_encoding(s);
10862             return;
10863         }
10864         /* fall through */
10865     case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10866     case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10867     case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10868     case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10869     case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10870     case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10871     case 12: /* SMULL, SMULL2, UMULL, UMULL2 */
10872         /* 64 x 64 -> 128 */
10873         if (size == 3) {
10874             unallocated_encoding(s);
10875             return;
10876         }
10877     is_widening:
10878         if (!fp_access_check(s)) {
10879             return;
10880         }
10881
10882         handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm);
10883         break;
10884     default:
10885         /* opcode 15 not allocated */
10886         unallocated_encoding(s);
10887         break;
10888     }
10889 }
10890
10891 /* Logic op (opcode == 3) subgroup of C3.6.16. */
10892 static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
10893 {
10894     int rd = extract32(insn, 0, 5);
10895     int rn = extract32(insn, 5, 5);
10896     int rm = extract32(insn, 16, 5);
10897     int size = extract32(insn, 22, 2);
10898     bool is_u = extract32(insn, 29, 1);
10899     bool is_q = extract32(insn, 30, 1);
10900
10901     if (!fp_access_check(s)) {
10902         return;
10903     }
10904
10905     switch (size + 4 * is_u) {
10906     case 0: /* AND */
10907         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_and, 0);
10908         return;
10909     case 1: /* BIC */
10910         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_andc, 0);
10911         return;
10912     case 2: /* ORR */
10913         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0);
10914         return;
10915     case 3: /* ORN */
10916         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_orc, 0);
10917         return;
10918     case 4: /* EOR */
10919         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_xor, 0);
10920         return;
10921
10922     case 5: /* BSL bitwise select */
10923         gen_gvec_op3(s, is_q, rd, rn, rm, &bsl_op);
10924         return;
10925     case 6: /* BIT, bitwise insert if true */
10926         gen_gvec_op3(s, is_q, rd, rn, rm, &bit_op);
10927         return;
10928     case 7: /* BIF, bitwise insert if false */
10929         gen_gvec_op3(s, is_q, rd, rn, rm, &bif_op);
10930         return;
10931
10932     default:
10933         g_assert_not_reached();
10934     }
10935 }
10936
10937 /* Pairwise op subgroup of C3.6.16.
10938  *
10939  * This is called directly or via the handle_3same_float for float pairwise
10940  * operations where the opcode and size are calculated differently.
10941  */
10942 static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
10943                                    int size, int rn, int rm, int rd)
10944 {
10945     TCGv_ptr fpst;
10946     int pass;
10947
10948     /* Floating point operations need fpst */
10949     if (opcode >= 0x58) {
10950         fpst = get_fpstatus_ptr(false);
10951     } else {
10952         fpst = NULL;
10953     }
10954
10955     if (!fp_access_check(s)) {
10956         return;
10957     }
10958
10959     /* These operations work on the concatenated rm:rn, with each pair of
10960      * adjacent elements being operated on to produce an element in the result.
10961      */
10962     if (size == 3) {
10963         TCGv_i64 tcg_res[2];
10964
10965         for (pass = 0; pass < 2; pass++) {
10966             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10967             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10968             int passreg = (pass == 0) ? rn : rm;
10969
10970             read_vec_element(s, tcg_op1, passreg, 0, MO_64);
10971             read_vec_element(s, tcg_op2, passreg, 1, MO_64);
10972             tcg_res[pass] = tcg_temp_new_i64();
10973
10974             switch (opcode) {
10975             case 0x17: /* ADDP */
10976                 tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
10977                 break;
10978             case 0x58: /* FMAXNMP */
10979                 gen_helper_vfp_maxnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10980                 break;
10981             case 0x5a: /* FADDP */
10982                 gen_helper_vfp_addd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10983                 break;
10984             case 0x5e: /* FMAXP */
10985                 gen_helper_vfp_maxd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10986                 break;
10987             case 0x78: /* FMINNMP */
10988                 gen_helper_vfp_minnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10989                 break;
10990             case 0x7e: /* FMINP */
10991                 gen_helper_vfp_mind(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10992                 break;
10993             default:
10994                 g_assert_not_reached();
10995             }
10996
10997             tcg_temp_free_i64(tcg_op1);
10998             tcg_temp_free_i64(tcg_op2);
10999         }
11000
11001         for (pass = 0; pass < 2; pass++) {
11002             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
11003             tcg_temp_free_i64(tcg_res[pass]);
11004         }
11005     } else {
11006         int maxpass = is_q ? 4 : 2;
11007         TCGv_i32 tcg_res[4];
11008
11009         for (pass = 0; pass < maxpass; pass++) {
11010             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11011             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11012             NeonGenTwoOpFn *genfn = NULL;
11013             int passreg = pass < (maxpass / 2) ? rn : rm;
11014             int passelt = (is_q && (pass & 1)) ? 2 : 0;
11015
11016             read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_32);
11017             read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_32);
11018             tcg_res[pass] = tcg_temp_new_i32();
11019
11020             switch (opcode) {
11021             case 0x17: /* ADDP */
11022             {
11023                 static NeonGenTwoOpFn * const fns[3] = {
11024                     gen_helper_neon_padd_u8,
11025                     gen_helper_neon_padd_u16,
11026                     tcg_gen_add_i32,
11027                 };
11028                 genfn = fns[size];
11029                 break;
11030             }
11031             case 0x14: /* SMAXP, UMAXP */
11032             {
11033                 static NeonGenTwoOpFn * const fns[3][2] = {
11034                     { gen_helper_neon_pmax_s8, gen_helper_neon_pmax_u8 },
11035                     { gen_helper_neon_pmax_s16, gen_helper_neon_pmax_u16 },
11036                     { tcg_gen_smax_i32, tcg_gen_umax_i32 },
11037                 };
11038                 genfn = fns[size][u];
11039                 break;
11040             }
11041             case 0x15: /* SMINP, UMINP */
11042             {
11043                 static NeonGenTwoOpFn * const fns[3][2] = {
11044                     { gen_helper_neon_pmin_s8, gen_helper_neon_pmin_u8 },
11045                     { gen_helper_neon_pmin_s16, gen_helper_neon_pmin_u16 },
11046                     { tcg_gen_smin_i32, tcg_gen_umin_i32 },
11047                 };
11048                 genfn = fns[size][u];
11049                 break;
11050             }
11051             /* The FP operations are all on single floats (32 bit) */
11052             case 0x58: /* FMAXNMP */
11053                 gen_helper_vfp_maxnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11054                 break;
11055             case 0x5a: /* FADDP */
11056                 gen_helper_vfp_adds(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11057                 break;
11058             case 0x5e: /* FMAXP */
11059                 gen_helper_vfp_maxs(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11060                 break;
11061             case 0x78: /* FMINNMP */
11062                 gen_helper_vfp_minnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11063                 break;
11064             case 0x7e: /* FMINP */
11065                 gen_helper_vfp_mins(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11066                 break;
11067             default:
11068                 g_assert_not_reached();
11069             }
11070
11071             /* FP ops called directly, otherwise call now */
11072             if (genfn) {
11073                 genfn(tcg_res[pass], tcg_op1, tcg_op2);
11074             }
11075
11076             tcg_temp_free_i32(tcg_op1);
11077             tcg_temp_free_i32(tcg_op2);
11078         }
11079
11080         for (pass = 0; pass < maxpass; pass++) {
11081             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
11082             tcg_temp_free_i32(tcg_res[pass]);
11083         }
11084         clear_vec_high(s, is_q, rd);
11085     }
11086
11087     if (fpst) {
11088         tcg_temp_free_ptr(fpst);
11089     }
11090 }
11091
11092 /* Floating point op subgroup of C3.6.16. */
11093 static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
11094 {
11095     /* For floating point ops, the U, size[1] and opcode bits
11096      * together indicate the operation. size[0] indicates single
11097      * or double.
11098      */
11099     int fpopcode = extract32(insn, 11, 5)
11100         | (extract32(insn, 23, 1) << 5)
11101         | (extract32(insn, 29, 1) << 6);
11102     int is_q = extract32(insn, 30, 1);
11103     int size = extract32(insn, 22, 1);
11104     int rm = extract32(insn, 16, 5);
11105     int rn = extract32(insn, 5, 5);
11106     int rd = extract32(insn, 0, 5);
11107
11108     int datasize = is_q ? 128 : 64;
11109     int esize = 32 << size;
11110     int elements = datasize / esize;
11111
11112     if (size == 1 && !is_q) {
11113         unallocated_encoding(s);
11114         return;
11115     }
11116
11117     switch (fpopcode) {
11118     case 0x58: /* FMAXNMP */
11119     case 0x5a: /* FADDP */
11120     case 0x5e: /* FMAXP */
11121     case 0x78: /* FMINNMP */
11122     case 0x7e: /* FMINP */
11123         if (size && !is_q) {
11124             unallocated_encoding(s);
11125             return;
11126         }
11127         handle_simd_3same_pair(s, is_q, 0, fpopcode, size ? MO_64 : MO_32,
11128                                rn, rm, rd);
11129         return;
11130     case 0x1b: /* FMULX */
11131     case 0x1f: /* FRECPS */
11132     case 0x3f: /* FRSQRTS */
11133     case 0x5d: /* FACGE */
11134     case 0x7d: /* FACGT */
11135     case 0x19: /* FMLA */
11136     case 0x39: /* FMLS */
11137     case 0x18: /* FMAXNM */
11138     case 0x1a: /* FADD */
11139     case 0x1c: /* FCMEQ */
11140     case 0x1e: /* FMAX */
11141     case 0x38: /* FMINNM */
11142     case 0x3a: /* FSUB */
11143     case 0x3e: /* FMIN */
11144     case 0x5b: /* FMUL */
11145     case 0x5c: /* FCMGE */
11146     case 0x5f: /* FDIV */
11147     case 0x7a: /* FABD */
11148     case 0x7c: /* FCMGT */
11149         if (!fp_access_check(s)) {
11150             return;
11151         }
11152         handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
11153         return;
11154
11155     case 0x1d: /* FMLAL  */
11156     case 0x3d: /* FMLSL  */
11157     case 0x59: /* FMLAL2 */
11158     case 0x79: /* FMLSL2 */
11159         if (size & 1 || !dc_isar_feature(aa64_fhm, s)) {
11160             unallocated_encoding(s);
11161             return;
11162         }
11163         if (fp_access_check(s)) {
11164             int is_s = extract32(insn, 23, 1);
11165             int is_2 = extract32(insn, 29, 1);
11166             int data = (is_2 << 1) | is_s;
11167             tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
11168                                vec_full_reg_offset(s, rn),
11169                                vec_full_reg_offset(s, rm), cpu_env,
11170                                is_q ? 16 : 8, vec_full_reg_size(s),
11171                                data, gen_helper_gvec_fmlal_a64);
11172         }
11173         return;
11174
11175     default:
11176         unallocated_encoding(s);
11177         return;
11178     }
11179 }
11180
11181 /* Integer op subgroup of C3.6.16. */
11182 static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
11183 {
11184     int is_q = extract32(insn, 30, 1);
11185     int u = extract32(insn, 29, 1);
11186     int size = extract32(insn, 22, 2);
11187     int opcode = extract32(insn, 11, 5);
11188     int rm = extract32(insn, 16, 5);
11189     int rn = extract32(insn, 5, 5);
11190     int rd = extract32(insn, 0, 5);
11191     int pass;
11192     TCGCond cond;
11193
11194     switch (opcode) {
11195     case 0x13: /* MUL, PMUL */
11196         if (u && size != 0) {
11197             unallocated_encoding(s);
11198             return;
11199         }
11200         /* fall through */
11201     case 0x0: /* SHADD, UHADD */
11202     case 0x2: /* SRHADD, URHADD */
11203     case 0x4: /* SHSUB, UHSUB */
11204     case 0xc: /* SMAX, UMAX */
11205     case 0xd: /* SMIN, UMIN */
11206     case 0xe: /* SABD, UABD */
11207     case 0xf: /* SABA, UABA */
11208     case 0x12: /* MLA, MLS */
11209         if (size == 3) {
11210             unallocated_encoding(s);
11211             return;
11212         }
11213         break;
11214     case 0x16: /* SQDMULH, SQRDMULH */
11215         if (size == 0 || size == 3) {
11216             unallocated_encoding(s);
11217             return;
11218         }
11219         break;
11220     default:
11221         if (size == 3 && !is_q) {
11222             unallocated_encoding(s);
11223             return;
11224         }
11225         break;
11226     }
11227
11228     if (!fp_access_check(s)) {
11229         return;
11230     }
11231
11232     switch (opcode) {
11233     case 0x01: /* SQADD, UQADD */
11234         tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
11235                        offsetof(CPUARMState, vfp.qc),
11236                        vec_full_reg_offset(s, rn),
11237                        vec_full_reg_offset(s, rm),
11238                        is_q ? 16 : 8, vec_full_reg_size(s),
11239                        (u ? uqadd_op : sqadd_op) + size);
11240         return;
11241     case 0x05: /* SQSUB, UQSUB */
11242         tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
11243                        offsetof(CPUARMState, vfp.qc),
11244                        vec_full_reg_offset(s, rn),
11245                        vec_full_reg_offset(s, rm),
11246                        is_q ? 16 : 8, vec_full_reg_size(s),
11247                        (u ? uqsub_op : sqsub_op) + size);
11248         return;
11249     case 0x0c: /* SMAX, UMAX */
11250         if (u) {
11251             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umax, size);
11252         } else {
11253             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smax, size);
11254         }
11255         return;
11256     case 0x0d: /* SMIN, UMIN */
11257         if (u) {
11258             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umin, size);
11259         } else {
11260             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smin, size);
11261         }
11262         return;
11263     case 0x10: /* ADD, SUB */
11264         if (u) {
11265             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
11266         } else {
11267             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_add, size);
11268         }
11269         return;
11270     case 0x13: /* MUL, PMUL */
11271         if (!u) { /* MUL */
11272             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_mul, size);
11273             return;
11274         }
11275         break;
11276     case 0x12: /* MLA, MLS */
11277         if (u) {
11278             gen_gvec_op3(s, is_q, rd, rn, rm, &mls_op[size]);
11279         } else {
11280             gen_gvec_op3(s, is_q, rd, rn, rm, &mla_op[size]);
11281         }
11282         return;
11283     case 0x11:
11284         if (!u) { /* CMTST */
11285             gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]);
11286             return;
11287         }
11288         /* else CMEQ */
11289         cond = TCG_COND_EQ;
11290         goto do_gvec_cmp;
11291     case 0x06: /* CMGT, CMHI */
11292         cond = u ? TCG_COND_GTU : TCG_COND_GT;
11293         goto do_gvec_cmp;
11294     case 0x07: /* CMGE, CMHS */
11295         cond = u ? TCG_COND_GEU : TCG_COND_GE;
11296     do_gvec_cmp:
11297         tcg_gen_gvec_cmp(cond, size, vec_full_reg_offset(s, rd),
11298                          vec_full_reg_offset(s, rn),
11299                          vec_full_reg_offset(s, rm),
11300                          is_q ? 16 : 8, vec_full_reg_size(s));
11301         return;
11302     }
11303
11304     if (size == 3) {
11305         assert(is_q);
11306         for (pass = 0; pass < 2; pass++) {
11307             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
11308             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
11309             TCGv_i64 tcg_res = tcg_temp_new_i64();
11310
11311             read_vec_element(s, tcg_op1, rn, pass, MO_64);
11312             read_vec_element(s, tcg_op2, rm, pass, MO_64);
11313
11314             handle_3same_64(s, opcode, u, tcg_res, tcg_op1, tcg_op2);
11315
11316             write_vec_element(s, tcg_res, rd, pass, MO_64);
11317
11318             tcg_temp_free_i64(tcg_res);
11319             tcg_temp_free_i64(tcg_op1);
11320             tcg_temp_free_i64(tcg_op2);
11321         }
11322     } else {
11323         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
11324             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11325             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11326             TCGv_i32 tcg_res = tcg_temp_new_i32();
11327             NeonGenTwoOpFn *genfn = NULL;
11328             NeonGenTwoOpEnvFn *genenvfn = NULL;
11329
11330             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
11331             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
11332
11333             switch (opcode) {
11334             case 0x0: /* SHADD, UHADD */
11335             {
11336                 static NeonGenTwoOpFn * const fns[3][2] = {
11337                     { gen_helper_neon_hadd_s8, gen_helper_neon_hadd_u8 },
11338                     { gen_helper_neon_hadd_s16, gen_helper_neon_hadd_u16 },
11339                     { gen_helper_neon_hadd_s32, gen_helper_neon_hadd_u32 },
11340                 };
11341                 genfn = fns[size][u];
11342                 break;
11343             }
11344             case 0x2: /* SRHADD, URHADD */
11345             {
11346                 static NeonGenTwoOpFn * const fns[3][2] = {
11347                     { gen_helper_neon_rhadd_s8, gen_helper_neon_rhadd_u8 },
11348                     { gen_helper_neon_rhadd_s16, gen_helper_neon_rhadd_u16 },
11349                     { gen_helper_neon_rhadd_s32, gen_helper_neon_rhadd_u32 },
11350                 };
11351                 genfn = fns[size][u];
11352                 break;
11353             }
11354             case 0x4: /* SHSUB, UHSUB */
11355             {
11356                 static NeonGenTwoOpFn * const fns[3][2] = {
11357                     { gen_helper_neon_hsub_s8, gen_helper_neon_hsub_u8 },
11358                     { gen_helper_neon_hsub_s16, gen_helper_neon_hsub_u16 },
11359                     { gen_helper_neon_hsub_s32, gen_helper_neon_hsub_u32 },
11360                 };
11361                 genfn = fns[size][u];
11362                 break;
11363             }
11364             case 0x8: /* SSHL, USHL */
11365             {
11366                 static NeonGenTwoOpFn * const fns[3][2] = {
11367                     { gen_helper_neon_shl_s8, gen_helper_neon_shl_u8 },
11368                     { gen_helper_neon_shl_s16, gen_helper_neon_shl_u16 },
11369                     { gen_helper_neon_shl_s32, gen_helper_neon_shl_u32 },
11370                 };
11371                 genfn = fns[size][u];
11372                 break;
11373             }
11374             case 0x9: /* SQSHL, UQSHL */
11375             {
11376                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
11377                     { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
11378                     { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
11379                     { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
11380                 };
11381                 genenvfn = fns[size][u];
11382                 break;
11383             }
11384             case 0xa: /* SRSHL, URSHL */
11385             {
11386                 static NeonGenTwoOpFn * const fns[3][2] = {
11387                     { gen_helper_neon_rshl_s8, gen_helper_neon_rshl_u8 },
11388                     { gen_helper_neon_rshl_s16, gen_helper_neon_rshl_u16 },
11389                     { gen_helper_neon_rshl_s32, gen_helper_neon_rshl_u32 },
11390                 };
11391                 genfn = fns[size][u];
11392                 break;
11393             }
11394             case 0xb: /* SQRSHL, UQRSHL */
11395             {
11396                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
11397                     { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
11398                     { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
11399                     { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
11400                 };
11401                 genenvfn = fns[size][u];
11402                 break;
11403             }
11404             case 0xe: /* SABD, UABD */
11405             case 0xf: /* SABA, UABA */
11406             {
11407                 static NeonGenTwoOpFn * const fns[3][2] = {
11408                     { gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 },
11409                     { gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 },
11410                     { gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 },
11411                 };
11412                 genfn = fns[size][u];
11413                 break;
11414             }
11415             case 0x13: /* MUL, PMUL */
11416                 assert(u); /* PMUL */
11417                 assert(size == 0);
11418                 genfn = gen_helper_neon_mul_p8;
11419                 break;
11420             case 0x16: /* SQDMULH, SQRDMULH */
11421             {
11422                 static NeonGenTwoOpEnvFn * const fns[2][2] = {
11423                     { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
11424                     { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
11425                 };
11426                 assert(size == 1 || size == 2);
11427                 genenvfn = fns[size - 1][u];
11428                 break;
11429             }
11430             default:
11431                 g_assert_not_reached();
11432             }
11433
11434             if (genenvfn) {
11435                 genenvfn(tcg_res, cpu_env, tcg_op1, tcg_op2);
11436             } else {
11437                 genfn(tcg_res, tcg_op1, tcg_op2);
11438             }
11439
11440             if (opcode == 0xf) {
11441                 /* SABA, UABA: accumulating ops */
11442                 static NeonGenTwoOpFn * const fns[3] = {
11443                     gen_helper_neon_add_u8,
11444                     gen_helper_neon_add_u16,
11445                     tcg_gen_add_i32,
11446                 };
11447
11448                 read_vec_element_i32(s, tcg_op1, rd, pass, MO_32);
11449                 fns[size](tcg_res, tcg_op1, tcg_res);
11450             }
11451
11452             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
11453
11454             tcg_temp_free_i32(tcg_res);
11455             tcg_temp_free_i32(tcg_op1);
11456             tcg_temp_free_i32(tcg_op2);
11457         }
11458     }
11459     clear_vec_high(s, is_q, rd);
11460 }
11461
11462 /* AdvSIMD three same
11463  *  31  30  29  28       24 23  22  21 20  16 15    11  10 9    5 4    0
11464  * +---+---+---+-----------+------+---+------+--------+---+------+------+
11465  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
11466  * +---+---+---+-----------+------+---+------+--------+---+------+------+
11467  */
11468 static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
11469 {
11470     int opcode = extract32(insn, 11, 5);
11471
11472     switch (opcode) {
11473     case 0x3: /* logic ops */
11474         disas_simd_3same_logic(s, insn);
11475         break;
11476     case 0x17: /* ADDP */
11477     case 0x14: /* SMAXP, UMAXP */
11478     case 0x15: /* SMINP, UMINP */
11479     {
11480         /* Pairwise operations */
11481         int is_q = extract32(insn, 30, 1);
11482         int u = extract32(insn, 29, 1);
11483         int size = extract32(insn, 22, 2);
11484         int rm = extract32(insn, 16, 5);
11485         int rn = extract32(insn, 5, 5);
11486         int rd = extract32(insn, 0, 5);
11487         if (opcode == 0x17) {
11488             if (u || (size == 3 && !is_q)) {
11489                 unallocated_encoding(s);
11490                 return;
11491             }
11492         } else {
11493             if (size == 3) {
11494                 unallocated_encoding(s);
11495                 return;
11496             }
11497         }
11498         handle_simd_3same_pair(s, is_q, u, opcode, size, rn, rm, rd);
11499         break;
11500     }
11501     case 0x18 ... 0x31:
11502         /* floating point ops, sz[1] and U are part of opcode */
11503         disas_simd_3same_float(s, insn);
11504         break;
11505     default:
11506         disas_simd_3same_int(s, insn);
11507         break;
11508     }
11509 }
11510
11511 /*
11512  * Advanced SIMD three same (ARMv8.2 FP16 variants)
11513  *
11514  *  31  30  29  28       24 23  22 21 20  16 15 14 13    11 10  9    5 4    0
11515  * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
11516  * | 0 | Q | U | 0 1 1 1 0 | a | 1 0 |  Rm  | 0 0 | opcode | 1 |  Rn  |  Rd  |
11517  * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
11518  *
11519  * This includes FMULX, FCMEQ (register), FRECPS, FRSQRTS, FCMGE
11520  * (register), FACGE, FABD, FCMGT (register) and FACGT.
11521  *
11522  */
11523 static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
11524 {
11525     int opcode, fpopcode;
11526     int is_q, u, a, rm, rn, rd;
11527     int datasize, elements;
11528     int pass;
11529     TCGv_ptr fpst;
11530     bool pairwise = false;
11531
11532     if (!dc_isar_feature(aa64_fp16, s)) {
11533         unallocated_encoding(s);
11534         return;
11535     }
11536
11537     if (!fp_access_check(s)) {
11538         return;
11539     }
11540
11541     /* For these floating point ops, the U, a and opcode bits
11542      * together indicate the operation.
11543      */
11544     opcode = extract32(insn, 11, 3);
11545     u = extract32(insn, 29, 1);
11546     a = extract32(insn, 23, 1);
11547     is_q = extract32(insn, 30, 1);
11548     rm = extract32(insn, 16, 5);
11549     rn = extract32(insn, 5, 5);
11550     rd = extract32(insn, 0, 5);
11551
11552     fpopcode = opcode | (a << 3) |  (u << 4);
11553     datasize = is_q ? 128 : 64;
11554     elements = datasize / 16;
11555
11556     switch (fpopcode) {
11557     case 0x10: /* FMAXNMP */
11558     case 0x12: /* FADDP */
11559     case 0x16: /* FMAXP */
11560     case 0x18: /* FMINNMP */
11561     case 0x1e: /* FMINP */
11562         pairwise = true;
11563         break;
11564     }
11565
11566     fpst = get_fpstatus_ptr(true);
11567
11568     if (pairwise) {
11569         int maxpass = is_q ? 8 : 4;
11570         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11571         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11572         TCGv_i32 tcg_res[8];
11573
11574         for (pass = 0; pass < maxpass; pass++) {
11575             int passreg = pass < (maxpass / 2) ? rn : rm;
11576             int passelt = (pass << 1) & (maxpass - 1);
11577
11578             read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_16);
11579             read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_16);
11580             tcg_res[pass] = tcg_temp_new_i32();
11581
11582             switch (fpopcode) {
11583             case 0x10: /* FMAXNMP */
11584                 gen_helper_advsimd_maxnumh(tcg_res[pass], tcg_op1, tcg_op2,
11585                                            fpst);
11586                 break;
11587             case 0x12: /* FADDP */
11588                 gen_helper_advsimd_addh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11589                 break;
11590             case 0x16: /* FMAXP */
11591                 gen_helper_advsimd_maxh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11592                 break;
11593             case 0x18: /* FMINNMP */
11594                 gen_helper_advsimd_minnumh(tcg_res[pass], tcg_op1, tcg_op2,
11595                                            fpst);
11596                 break;
11597             case 0x1e: /* FMINP */
11598                 gen_helper_advsimd_minh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11599                 break;
11600             default:
11601                 g_assert_not_reached();
11602             }
11603         }
11604
11605         for (pass = 0; pass < maxpass; pass++) {
11606             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_16);
11607             tcg_temp_free_i32(tcg_res[pass]);
11608         }
11609
11610         tcg_temp_free_i32(tcg_op1);
11611         tcg_temp_free_i32(tcg_op2);
11612
11613     } else {
11614         for (pass = 0; pass < elements; pass++) {
11615             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11616             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11617             TCGv_i32 tcg_res = tcg_temp_new_i32();
11618
11619             read_vec_element_i32(s, tcg_op1, rn, pass, MO_16);
11620             read_vec_element_i32(s, tcg_op2, rm, pass, MO_16);
11621
11622             switch (fpopcode) {
11623             case 0x0: /* FMAXNM */
11624                 gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
11625                 break;
11626             case 0x1: /* FMLA */
11627                 read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11628                 gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
11629                                            fpst);
11630                 break;
11631             case 0x2: /* FADD */
11632                 gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
11633                 break;
11634             case 0x3: /* FMULX */
11635                 gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
11636                 break;
11637             case 0x4: /* FCMEQ */
11638                 gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11639                 break;
11640             case 0x6: /* FMAX */
11641                 gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
11642                 break;
11643             case 0x7: /* FRECPS */
11644                 gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11645                 break;
11646             case 0x8: /* FMINNM */
11647                 gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
11648                 break;
11649             case 0x9: /* FMLS */
11650                 /* As usual for ARM, separate negation for fused multiply-add */
11651                 tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
11652                 read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11653                 gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
11654                                            fpst);
11655                 break;
11656             case 0xa: /* FSUB */
11657                 gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
11658                 break;
11659             case 0xe: /* FMIN */
11660                 gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
11661                 break;
11662             case 0xf: /* FRSQRTS */
11663                 gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11664                 break;
11665             case 0x13: /* FMUL */
11666                 gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
11667                 break;
11668             case 0x14: /* FCMGE */
11669                 gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11670                 break;
11671             case 0x15: /* FACGE */
11672                 gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11673                 break;
11674             case 0x17: /* FDIV */
11675                 gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
11676                 break;
11677             case 0x1a: /* FABD */
11678                 gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
11679                 tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
11680                 break;
11681             case 0x1c: /* FCMGT */
11682                 gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11683                 break;
11684             case 0x1d: /* FACGT */
11685                 gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11686                 break;
11687             default:
11688                 fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n",
11689                         __func__, insn, fpopcode, s->pc);
11690                 g_assert_not_reached();
11691             }
11692
11693             write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11694             tcg_temp_free_i32(tcg_res);
11695             tcg_temp_free_i32(tcg_op1);
11696             tcg_temp_free_i32(tcg_op2);
11697         }
11698     }
11699
11700     tcg_temp_free_ptr(fpst);
11701
11702     clear_vec_high(s, is_q, rd);
11703 }
11704
11705 /* AdvSIMD three same extra
11706  *  31   30  29 28       24 23  22  21 20  16  15 14    11  10 9  5 4  0
11707  * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
11708  * | 0 | Q | U | 0 1 1 1 0 | size | 0 |  Rm  | 1 | opcode | 1 | Rn | Rd |
11709  * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
11710  */
11711 static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
11712 {
11713     int rd = extract32(insn, 0, 5);
11714     int rn = extract32(insn, 5, 5);
11715     int opcode = extract32(insn, 11, 4);
11716     int rm = extract32(insn, 16, 5);
11717     int size = extract32(insn, 22, 2);
11718     bool u = extract32(insn, 29, 1);
11719     bool is_q = extract32(insn, 30, 1);
11720     bool feature;
11721     int rot;
11722
11723     switch (u * 16 + opcode) {
11724     case 0x10: /* SQRDMLAH (vector) */
11725     case 0x11: /* SQRDMLSH (vector) */
11726         if (size != 1 && size != 2) {
11727             unallocated_encoding(s);
11728             return;
11729         }
11730         feature = dc_isar_feature(aa64_rdm, s);
11731         break;
11732     case 0x02: /* SDOT (vector) */
11733     case 0x12: /* UDOT (vector) */
11734         if (size != MO_32) {
11735             unallocated_encoding(s);
11736             return;
11737         }
11738         feature = dc_isar_feature(aa64_dp, s);
11739         break;
11740     case 0x18: /* FCMLA, #0 */
11741     case 0x19: /* FCMLA, #90 */
11742     case 0x1a: /* FCMLA, #180 */
11743     case 0x1b: /* FCMLA, #270 */
11744     case 0x1c: /* FCADD, #90 */
11745     case 0x1e: /* FCADD, #270 */
11746         if (size == 0
11747             || (size == 1 && !dc_isar_feature(aa64_fp16, s))
11748             || (size == 3 && !is_q)) {
11749             unallocated_encoding(s);
11750             return;
11751         }
11752         feature = dc_isar_feature(aa64_fcma, s);
11753         break;
11754     default:
11755         unallocated_encoding(s);
11756         return;
11757     }
11758     if (!feature) {
11759         unallocated_encoding(s);
11760         return;
11761     }
11762     if (!fp_access_check(s)) {
11763         return;
11764     }
11765
11766     switch (opcode) {
11767     case 0x0: /* SQRDMLAH (vector) */
11768         switch (size) {
11769         case 1:
11770             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
11771             break;
11772         case 2:
11773             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
11774             break;
11775         default:
11776             g_assert_not_reached();
11777         }
11778         return;
11779
11780     case 0x1: /* SQRDMLSH (vector) */
11781         switch (size) {
11782         case 1:
11783             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
11784             break;
11785         case 2:
11786             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
11787             break;
11788         default:
11789             g_assert_not_reached();
11790         }
11791         return;
11792
11793     case 0x2: /* SDOT / UDOT */
11794         gen_gvec_op3_ool(s, is_q, rd, rn, rm, 0,
11795                          u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b);
11796         return;
11797
11798     case 0x8: /* FCMLA, #0 */
11799     case 0x9: /* FCMLA, #90 */
11800     case 0xa: /* FCMLA, #180 */
11801     case 0xb: /* FCMLA, #270 */
11802         rot = extract32(opcode, 0, 2);
11803         switch (size) {
11804         case 1:
11805             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
11806                               gen_helper_gvec_fcmlah);
11807             break;
11808         case 2:
11809             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
11810                               gen_helper_gvec_fcmlas);
11811             break;
11812         case 3:
11813             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
11814                               gen_helper_gvec_fcmlad);
11815             break;
11816         default:
11817             g_assert_not_reached();
11818         }
11819         return;
11820
11821     case 0xc: /* FCADD, #90 */
11822     case 0xe: /* FCADD, #270 */
11823         rot = extract32(opcode, 1, 1);
11824         switch (size) {
11825         case 1:
11826             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11827                               gen_helper_gvec_fcaddh);
11828             break;
11829         case 2:
11830             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11831                               gen_helper_gvec_fcadds);
11832             break;
11833         case 3:
11834             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11835                               gen_helper_gvec_fcaddd);
11836             break;
11837         default:
11838             g_assert_not_reached();
11839         }
11840         return;
11841
11842     default:
11843         g_assert_not_reached();
11844     }
11845 }
11846
11847 static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
11848                                   int size, int rn, int rd)
11849 {
11850     /* Handle 2-reg-misc ops which are widening (so each size element
11851      * in the source becomes a 2*size element in the destination.
11852      * The only instruction like this is FCVTL.
11853      */
11854     int pass;
11855
11856     if (size == 3) {
11857         /* 32 -> 64 bit fp conversion */
11858         TCGv_i64 tcg_res[2];
11859         int srcelt = is_q ? 2 : 0;
11860
11861         for (pass = 0; pass < 2; pass++) {
11862             TCGv_i32 tcg_op = tcg_temp_new_i32();
11863             tcg_res[pass] = tcg_temp_new_i64();
11864
11865             read_vec_element_i32(s, tcg_op, rn, srcelt + pass, MO_32);
11866             gen_helper_vfp_fcvtds(tcg_res[pass], tcg_op, cpu_env);
11867             tcg_temp_free_i32(tcg_op);
11868         }
11869         for (pass = 0; pass < 2; pass++) {
11870             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
11871             tcg_temp_free_i64(tcg_res[pass]);
11872         }
11873     } else {
11874         /* 16 -> 32 bit fp conversion */
11875         int srcelt = is_q ? 4 : 0;
11876         TCGv_i32 tcg_res[4];
11877         TCGv_ptr fpst = get_fpstatus_ptr(false);
11878         TCGv_i32 ahp = get_ahp_flag();
11879
11880         for (pass = 0; pass < 4; pass++) {
11881             tcg_res[pass] = tcg_temp_new_i32();
11882
11883             read_vec_element_i32(s, tcg_res[pass], rn, srcelt + pass, MO_16);
11884             gen_helper_vfp_fcvt_f16_to_f32(tcg_res[pass], tcg_res[pass],
11885                                            fpst, ahp);
11886         }
11887         for (pass = 0; pass < 4; pass++) {
11888             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
11889             tcg_temp_free_i32(tcg_res[pass]);
11890         }
11891
11892         tcg_temp_free_ptr(fpst);
11893         tcg_temp_free_i32(ahp);
11894     }
11895 }
11896
11897 static void handle_rev(DisasContext *s, int opcode, bool u,
11898                        bool is_q, int size, int rn, int rd)
11899 {
11900     int op = (opcode << 1) | u;
11901     int opsz = op + size;
11902     int grp_size = 3 - opsz;
11903     int dsize = is_q ? 128 : 64;
11904     int i;
11905
11906     if (opsz >= 3) {
11907         unallocated_encoding(s);
11908         return;
11909     }
11910
11911     if (!fp_access_check(s)) {
11912         return;
11913     }
11914
11915     if (size == 0) {
11916         /* Special case bytes, use bswap op on each group of elements */
11917         int groups = dsize / (8 << grp_size);
11918
11919         for (i = 0; i < groups; i++) {
11920             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
11921
11922             read_vec_element(s, tcg_tmp, rn, i, grp_size);
11923             switch (grp_size) {
11924             case MO_16:
11925                 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
11926                 break;
11927             case MO_32:
11928                 tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
11929                 break;
11930             case MO_64:
11931                 tcg_gen_bswap64_i64(tcg_tmp, tcg_tmp);
11932                 break;
11933             default:
11934                 g_assert_not_reached();
11935             }
11936             write_vec_element(s, tcg_tmp, rd, i, grp_size);
11937             tcg_temp_free_i64(tcg_tmp);
11938         }
11939         clear_vec_high(s, is_q, rd);
11940     } else {
11941         int revmask = (1 << grp_size) - 1;
11942         int esize = 8 << size;
11943         int elements = dsize / esize;
11944         TCGv_i64 tcg_rn = tcg_temp_new_i64();
11945         TCGv_i64 tcg_rd = tcg_const_i64(0);
11946         TCGv_i64 tcg_rd_hi = tcg_const_i64(0);
11947
11948         for (i = 0; i < elements; i++) {
11949             int e_rev = (i & 0xf) ^ revmask;
11950             int off = e_rev * esize;
11951             read_vec_element(s, tcg_rn, rn, i, size);
11952             if (off >= 64) {
11953                 tcg_gen_deposit_i64(tcg_rd_hi, tcg_rd_hi,
11954                                     tcg_rn, off - 64, esize);
11955             } else {
11956                 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, off, esize);
11957             }
11958         }
11959         write_vec_element(s, tcg_rd, rd, 0, MO_64);
11960         write_vec_element(s, tcg_rd_hi, rd, 1, MO_64);
11961
11962         tcg_temp_free_i64(tcg_rd_hi);
11963         tcg_temp_free_i64(tcg_rd);
11964         tcg_temp_free_i64(tcg_rn);
11965     }
11966 }
11967
11968 static void handle_2misc_pairwise(DisasContext *s, int opcode, bool u,
11969                                   bool is_q, int size, int rn, int rd)
11970 {
11971     /* Implement the pairwise operations from 2-misc:
11972      * SADDLP, UADDLP, SADALP, UADALP.
11973      * These all add pairs of elements in the input to produce a
11974      * double-width result element in the output (possibly accumulating).
11975      */
11976     bool accum = (opcode == 0x6);
11977     int maxpass = is_q ? 2 : 1;
11978     int pass;
11979     TCGv_i64 tcg_res[2];
11980
11981     if (size == 2) {
11982         /* 32 + 32 -> 64 op */
11983         TCGMemOp memop = size + (u ? 0 : MO_SIGN);
11984
11985         for (pass = 0; pass < maxpass; pass++) {
11986             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
11987             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
11988
11989             tcg_res[pass] = tcg_temp_new_i64();
11990
11991             read_vec_element(s, tcg_op1, rn, pass * 2, memop);
11992             read_vec_element(s, tcg_op2, rn, pass * 2 + 1, memop);
11993             tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
11994             if (accum) {
11995                 read_vec_element(s, tcg_op1, rd, pass, MO_64);
11996                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
11997             }
11998
11999             tcg_temp_free_i64(tcg_op1);
12000             tcg_temp_free_i64(tcg_op2);
12001         }
12002     } else {
12003         for (pass = 0; pass < maxpass; pass++) {
12004             TCGv_i64 tcg_op = tcg_temp_new_i64();
12005             NeonGenOneOpFn *genfn;
12006             static NeonGenOneOpFn * const fns[2][2] = {
12007                 { gen_helper_neon_addlp_s8,  gen_helper_neon_addlp_u8 },
12008                 { gen_helper_neon_addlp_s16,  gen_helper_neon_addlp_u16 },
12009             };
12010
12011             genfn = fns[size][u];
12012
12013             tcg_res[pass] = tcg_temp_new_i64();
12014
12015             read_vec_element(s, tcg_op, rn, pass, MO_64);
12016             genfn(tcg_res[pass], tcg_op);
12017
12018             if (accum) {
12019                 read_vec_element(s, tcg_op, rd, pass, MO_64);
12020                 if (size == 0) {
12021                     gen_helper_neon_addl_u16(tcg_res[pass],
12022                                              tcg_res[pass], tcg_op);
12023                 } else {
12024                     gen_helper_neon_addl_u32(tcg_res[pass],
12025                                              tcg_res[pass], tcg_op);
12026                 }
12027             }
12028             tcg_temp_free_i64(tcg_op);
12029         }
12030     }
12031     if (!is_q) {
12032         tcg_res[1] = tcg_const_i64(0);
12033     }
12034     for (pass = 0; pass < 2; pass++) {
12035         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
12036         tcg_temp_free_i64(tcg_res[pass]);
12037     }
12038 }
12039
12040 static void handle_shll(DisasContext *s, bool is_q, int size, int rn, int rd)
12041 {
12042     /* Implement SHLL and SHLL2 */
12043     int pass;
12044     int part = is_q ? 2 : 0;
12045     TCGv_i64 tcg_res[2];
12046
12047     for (pass = 0; pass < 2; pass++) {
12048         static NeonGenWidenFn * const widenfns[3] = {
12049             gen_helper_neon_widen_u8,
12050             gen_helper_neon_widen_u16,
12051             tcg_gen_extu_i32_i64,
12052         };
12053         NeonGenWidenFn *widenfn = widenfns[size];
12054         TCGv_i32 tcg_op = tcg_temp_new_i32();
12055
12056         read_vec_element_i32(s, tcg_op, rn, part + pass, MO_32);
12057         tcg_res[pass] = tcg_temp_new_i64();
12058         widenfn(tcg_res[pass], tcg_op);
12059         tcg_gen_shli_i64(tcg_res[pass], tcg_res[pass], 8 << size);
12060
12061         tcg_temp_free_i32(tcg_op);
12062     }
12063
12064     for (pass = 0; pass < 2; pass++) {
12065         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
12066         tcg_temp_free_i64(tcg_res[pass]);
12067     }
12068 }
12069
12070 /* AdvSIMD two reg misc
12071  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
12072  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
12073  * | 0 | Q | U | 0 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
12074  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
12075  */
12076 static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
12077 {
12078     int size = extract32(insn, 22, 2);
12079     int opcode = extract32(insn, 12, 5);
12080     bool u = extract32(insn, 29, 1);
12081     bool is_q = extract32(insn, 30, 1);
12082     int rn = extract32(insn, 5, 5);
12083     int rd = extract32(insn, 0, 5);
12084     bool need_fpstatus = false;
12085     bool need_rmode = false;
12086     int rmode = -1;
12087     TCGv_i32 tcg_rmode;
12088     TCGv_ptr tcg_fpstatus;
12089
12090     switch (opcode) {
12091     case 0x0: /* REV64, REV32 */
12092     case 0x1: /* REV16 */
12093         handle_rev(s, opcode, u, is_q, size, rn, rd);
12094         return;
12095     case 0x5: /* CNT, NOT, RBIT */
12096         if (u && size == 0) {
12097             /* NOT */
12098             break;
12099         } else if (u && size == 1) {
12100             /* RBIT */
12101             break;
12102         } else if (!u && size == 0) {
12103             /* CNT */
12104             break;
12105         }
12106         unallocated_encoding(s);
12107         return;
12108     case 0x12: /* XTN, XTN2, SQXTUN, SQXTUN2 */
12109     case 0x14: /* SQXTN, SQXTN2, UQXTN, UQXTN2 */
12110         if (size == 3) {
12111             unallocated_encoding(s);
12112             return;
12113         }
12114         if (!fp_access_check(s)) {
12115             return;
12116         }
12117
12118         handle_2misc_narrow(s, false, opcode, u, is_q, size, rn, rd);
12119         return;
12120     case 0x4: /* CLS, CLZ */
12121         if (size == 3) {
12122             unallocated_encoding(s);
12123             return;
12124         }
12125         break;
12126     case 0x2: /* SADDLP, UADDLP */
12127     case 0x6: /* SADALP, UADALP */
12128         if (size == 3) {
12129             unallocated_encoding(s);
12130             return;
12131         }
12132         if (!fp_access_check(s)) {
12133             return;
12134         }
12135         handle_2misc_pairwise(s, opcode, u, is_q, size, rn, rd);
12136         return;
12137     case 0x13: /* SHLL, SHLL2 */
12138         if (u == 0 || size == 3) {
12139             unallocated_encoding(s);
12140             return;
12141         }
12142         if (!fp_access_check(s)) {
12143             return;
12144         }
12145         handle_shll(s, is_q, size, rn, rd);
12146         return;
12147     case 0xa: /* CMLT */
12148         if (u == 1) {
12149             unallocated_encoding(s);
12150             return;
12151         }
12152         /* fall through */
12153     case 0x8: /* CMGT, CMGE */
12154     case 0x9: /* CMEQ, CMLE */
12155     case 0xb: /* ABS, NEG */
12156         if (size == 3 && !is_q) {
12157             unallocated_encoding(s);
12158             return;
12159         }
12160         break;
12161     case 0x3: /* SUQADD, USQADD */
12162         if (size == 3 && !is_q) {
12163             unallocated_encoding(s);
12164             return;
12165         }
12166         if (!fp_access_check(s)) {
12167             return;
12168         }
12169         handle_2misc_satacc(s, false, u, is_q, size, rn, rd);
12170         return;
12171     case 0x7: /* SQABS, SQNEG */
12172         if (size == 3 && !is_q) {
12173             unallocated_encoding(s);
12174             return;
12175         }
12176         break;
12177     case 0xc ... 0xf:
12178     case 0x16 ... 0x1f:
12179     {
12180         /* Floating point: U, size[1] and opcode indicate operation;
12181          * size[0] indicates single or double precision.
12182          */
12183         int is_double = extract32(size, 0, 1);
12184         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
12185         size = is_double ? 3 : 2;
12186         switch (opcode) {
12187         case 0x2f: /* FABS */
12188         case 0x6f: /* FNEG */
12189             if (size == 3 && !is_q) {
12190                 unallocated_encoding(s);
12191                 return;
12192             }
12193             break;
12194         case 0x1d: /* SCVTF */
12195         case 0x5d: /* UCVTF */
12196         {
12197             bool is_signed = (opcode == 0x1d) ? true : false;
12198             int elements = is_double ? 2 : is_q ? 4 : 2;
12199             if (is_double && !is_q) {
12200                 unallocated_encoding(s);
12201                 return;
12202             }
12203             if (!fp_access_check(s)) {
12204                 return;
12205             }
12206             handle_simd_intfp_conv(s, rd, rn, elements, is_signed, 0, size);
12207             return;
12208         }
12209         case 0x2c: /* FCMGT (zero) */
12210         case 0x2d: /* FCMEQ (zero) */
12211         case 0x2e: /* FCMLT (zero) */
12212         case 0x6c: /* FCMGE (zero) */
12213         case 0x6d: /* FCMLE (zero) */
12214             if (size == 3 && !is_q) {
12215                 unallocated_encoding(s);
12216                 return;
12217             }
12218             handle_2misc_fcmp_zero(s, opcode, false, u, is_q, size, rn, rd);
12219             return;
12220         case 0x7f: /* FSQRT */
12221             if (size == 3 && !is_q) {
12222                 unallocated_encoding(s);
12223                 return;
12224             }
12225             break;
12226         case 0x1a: /* FCVTNS */
12227         case 0x1b: /* FCVTMS */
12228         case 0x3a: /* FCVTPS */
12229         case 0x3b: /* FCVTZS */
12230         case 0x5a: /* FCVTNU */
12231         case 0x5b: /* FCVTMU */
12232         case 0x7a: /* FCVTPU */
12233         case 0x7b: /* FCVTZU */
12234             need_fpstatus = true;
12235             need_rmode = true;
12236             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
12237             if (size == 3 && !is_q) {
12238                 unallocated_encoding(s);
12239                 return;
12240             }
12241             break;
12242         case 0x5c: /* FCVTAU */
12243         case 0x1c: /* FCVTAS */
12244             need_fpstatus = true;
12245             need_rmode = true;
12246             rmode = FPROUNDING_TIEAWAY;
12247             if (size == 3 && !is_q) {
12248                 unallocated_encoding(s);
12249                 return;
12250             }
12251             break;
12252         case 0x3c: /* URECPE */
12253             if (size == 3) {
12254                 unallocated_encoding(s);
12255                 return;
12256             }
12257             /* fall through */
12258         case 0x3d: /* FRECPE */
12259         case 0x7d: /* FRSQRTE */
12260             if (size == 3 && !is_q) {
12261                 unallocated_encoding(s);
12262                 return;
12263             }
12264             if (!fp_access_check(s)) {
12265                 return;
12266             }
12267             handle_2misc_reciprocal(s, opcode, false, u, is_q, size, rn, rd);
12268             return;
12269         case 0x56: /* FCVTXN, FCVTXN2 */
12270             if (size == 2) {
12271                 unallocated_encoding(s);
12272                 return;
12273             }
12274             /* fall through */
12275         case 0x16: /* FCVTN, FCVTN2 */
12276             /* handle_2misc_narrow does a 2*size -> size operation, but these
12277              * instructions encode the source size rather than dest size.
12278              */
12279             if (!fp_access_check(s)) {
12280                 return;
12281             }
12282             handle_2misc_narrow(s, false, opcode, 0, is_q, size - 1, rn, rd);
12283             return;
12284         case 0x17: /* FCVTL, FCVTL2 */
12285             if (!fp_access_check(s)) {
12286                 return;
12287             }
12288             handle_2misc_widening(s, opcode, is_q, size, rn, rd);
12289             return;
12290         case 0x18: /* FRINTN */
12291         case 0x19: /* FRINTM */
12292         case 0x38: /* FRINTP */
12293         case 0x39: /* FRINTZ */
12294             need_rmode = true;
12295             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
12296             /* fall through */
12297         case 0x59: /* FRINTX */
12298         case 0x79: /* FRINTI */
12299             need_fpstatus = true;
12300             if (size == 3 && !is_q) {
12301                 unallocated_encoding(s);
12302                 return;
12303             }
12304             break;
12305         case 0x58: /* FRINTA */
12306             need_rmode = true;
12307             rmode = FPROUNDING_TIEAWAY;
12308             need_fpstatus = true;
12309             if (size == 3 && !is_q) {
12310                 unallocated_encoding(s);
12311                 return;
12312             }
12313             break;
12314         case 0x7c: /* URSQRTE */
12315             if (size == 3) {
12316                 unallocated_encoding(s);
12317                 return;
12318             }
12319             need_fpstatus = true;
12320             break;
12321         case 0x1e: /* FRINT32Z */
12322         case 0x1f: /* FRINT64Z */
12323             need_rmode = true;
12324             rmode = FPROUNDING_ZERO;
12325             /* fall through */
12326         case 0x5e: /* FRINT32X */
12327         case 0x5f: /* FRINT64X */
12328             need_fpstatus = true;
12329             if ((size == 3 && !is_q) || !dc_isar_feature(aa64_frint, s)) {
12330                 unallocated_encoding(s);
12331                 return;
12332             }
12333             break;
12334         default:
12335             unallocated_encoding(s);
12336             return;
12337         }
12338         break;
12339     }
12340     default:
12341         unallocated_encoding(s);
12342         return;
12343     }
12344
12345     if (!fp_access_check(s)) {
12346         return;
12347     }
12348
12349     if (need_fpstatus || need_rmode) {
12350         tcg_fpstatus = get_fpstatus_ptr(false);
12351     } else {
12352         tcg_fpstatus = NULL;
12353     }
12354     if (need_rmode) {
12355         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
12356         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12357     } else {
12358         tcg_rmode = NULL;
12359     }
12360
12361     switch (opcode) {
12362     case 0x5:
12363         if (u && size == 0) { /* NOT */
12364             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_not, 0);
12365             return;
12366         }
12367         break;
12368     case 0xb:
12369         if (u) { /* NEG */
12370             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_neg, size);
12371             return;
12372         }
12373         break;
12374     }
12375
12376     if (size == 3) {
12377         /* All 64-bit element operations can be shared with scalar 2misc */
12378         int pass;
12379
12380         /* Coverity claims (size == 3 && !is_q) has been eliminated
12381          * from all paths leading to here.
12382          */
12383         tcg_debug_assert(is_q);
12384         for (pass = 0; pass < 2; pass++) {
12385             TCGv_i64 tcg_op = tcg_temp_new_i64();
12386             TCGv_i64 tcg_res = tcg_temp_new_i64();
12387
12388             read_vec_element(s, tcg_op, rn, pass, MO_64);
12389
12390             handle_2misc_64(s, opcode, u, tcg_res, tcg_op,
12391                             tcg_rmode, tcg_fpstatus);
12392
12393             write_vec_element(s, tcg_res, rd, pass, MO_64);
12394
12395             tcg_temp_free_i64(tcg_res);
12396             tcg_temp_free_i64(tcg_op);
12397         }
12398     } else {
12399         int pass;
12400
12401         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
12402             TCGv_i32 tcg_op = tcg_temp_new_i32();
12403             TCGv_i32 tcg_res = tcg_temp_new_i32();
12404             TCGCond cond;
12405
12406             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
12407
12408             if (size == 2) {
12409                 /* Special cases for 32 bit elements */
12410                 switch (opcode) {
12411                 case 0xa: /* CMLT */
12412                     /* 32 bit integer comparison against zero, result is
12413                      * test ? (2^32 - 1) : 0. We implement via setcond(test)
12414                      * and inverting.
12415                      */
12416                     cond = TCG_COND_LT;
12417                 do_cmop:
12418                     tcg_gen_setcondi_i32(cond, tcg_res, tcg_op, 0);
12419                     tcg_gen_neg_i32(tcg_res, tcg_res);
12420                     break;
12421                 case 0x8: /* CMGT, CMGE */
12422                     cond = u ? TCG_COND_GE : TCG_COND_GT;
12423                     goto do_cmop;
12424                 case 0x9: /* CMEQ, CMLE */
12425                     cond = u ? TCG_COND_LE : TCG_COND_EQ;
12426                     goto do_cmop;
12427                 case 0x4: /* CLS */
12428                     if (u) {
12429                         tcg_gen_clzi_i32(tcg_res, tcg_op, 32);
12430                     } else {
12431                         tcg_gen_clrsb_i32(tcg_res, tcg_op);
12432                     }
12433                     break;
12434                 case 0x7: /* SQABS, SQNEG */
12435                     if (u) {
12436                         gen_helper_neon_qneg_s32(tcg_res, cpu_env, tcg_op);
12437                     } else {
12438                         gen_helper_neon_qabs_s32(tcg_res, cpu_env, tcg_op);
12439                     }
12440                     break;
12441                 case 0xb: /* ABS, NEG */
12442                     if (u) {
12443                         tcg_gen_neg_i32(tcg_res, tcg_op);
12444                     } else {
12445                         TCGv_i32 tcg_zero = tcg_const_i32(0);
12446                         tcg_gen_neg_i32(tcg_res, tcg_op);
12447                         tcg_gen_movcond_i32(TCG_COND_GT, tcg_res, tcg_op,
12448                                             tcg_zero, tcg_op, tcg_res);
12449                         tcg_temp_free_i32(tcg_zero);
12450                     }
12451                     break;
12452                 case 0x2f: /* FABS */
12453                     gen_helper_vfp_abss(tcg_res, tcg_op);
12454                     break;
12455                 case 0x6f: /* FNEG */
12456                     gen_helper_vfp_negs(tcg_res, tcg_op);
12457                     break;
12458                 case 0x7f: /* FSQRT */
12459                     gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
12460                     break;
12461                 case 0x1a: /* FCVTNS */
12462                 case 0x1b: /* FCVTMS */
12463                 case 0x1c: /* FCVTAS */
12464                 case 0x3a: /* FCVTPS */
12465                 case 0x3b: /* FCVTZS */
12466                 {
12467                     TCGv_i32 tcg_shift = tcg_const_i32(0);
12468                     gen_helper_vfp_tosls(tcg_res, tcg_op,
12469                                          tcg_shift, tcg_fpstatus);
12470                     tcg_temp_free_i32(tcg_shift);
12471                     break;
12472                 }
12473                 case 0x5a: /* FCVTNU */
12474                 case 0x5b: /* FCVTMU */
12475                 case 0x5c: /* FCVTAU */
12476                 case 0x7a: /* FCVTPU */
12477                 case 0x7b: /* FCVTZU */
12478                 {
12479                     TCGv_i32 tcg_shift = tcg_const_i32(0);
12480                     gen_helper_vfp_touls(tcg_res, tcg_op,
12481                                          tcg_shift, tcg_fpstatus);
12482                     tcg_temp_free_i32(tcg_shift);
12483                     break;
12484                 }
12485                 case 0x18: /* FRINTN */
12486                 case 0x19: /* FRINTM */
12487                 case 0x38: /* FRINTP */
12488                 case 0x39: /* FRINTZ */
12489                 case 0x58: /* FRINTA */
12490                 case 0x79: /* FRINTI */
12491                     gen_helper_rints(tcg_res, tcg_op, tcg_fpstatus);
12492                     break;
12493                 case 0x59: /* FRINTX */
12494                     gen_helper_rints_exact(tcg_res, tcg_op, tcg_fpstatus);
12495                     break;
12496                 case 0x7c: /* URSQRTE */
12497                     gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
12498                     break;
12499                 case 0x1e: /* FRINT32Z */
12500                 case 0x5e: /* FRINT32X */
12501                     gen_helper_frint32_s(tcg_res, tcg_op, tcg_fpstatus);
12502                     break;
12503                 case 0x1f: /* FRINT64Z */
12504                 case 0x5f: /* FRINT64X */
12505                     gen_helper_frint64_s(tcg_res, tcg_op, tcg_fpstatus);
12506                     break;
12507                 default:
12508                     g_assert_not_reached();
12509                 }
12510             } else {
12511                 /* Use helpers for 8 and 16 bit elements */
12512                 switch (opcode) {
12513                 case 0x5: /* CNT, RBIT */
12514                     /* For these two insns size is part of the opcode specifier
12515                      * (handled earlier); they always operate on byte elements.
12516                      */
12517                     if (u) {
12518                         gen_helper_neon_rbit_u8(tcg_res, tcg_op);
12519                     } else {
12520                         gen_helper_neon_cnt_u8(tcg_res, tcg_op);
12521                     }
12522                     break;
12523                 case 0x7: /* SQABS, SQNEG */
12524                 {
12525                     NeonGenOneOpEnvFn *genfn;
12526                     static NeonGenOneOpEnvFn * const fns[2][2] = {
12527                         { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
12528                         { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
12529                     };
12530                     genfn = fns[size][u];
12531                     genfn(tcg_res, cpu_env, tcg_op);
12532                     break;
12533                 }
12534                 case 0x8: /* CMGT, CMGE */
12535                 case 0x9: /* CMEQ, CMLE */
12536                 case 0xa: /* CMLT */
12537                 {
12538                     static NeonGenTwoOpFn * const fns[3][2] = {
12539                         { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_s16 },
12540                         { gen_helper_neon_cge_s8, gen_helper_neon_cge_s16 },
12541                         { gen_helper_neon_ceq_u8, gen_helper_neon_ceq_u16 },
12542                     };
12543                     NeonGenTwoOpFn *genfn;
12544                     int comp;
12545                     bool reverse;
12546                     TCGv_i32 tcg_zero = tcg_const_i32(0);
12547
12548                     /* comp = index into [CMGT, CMGE, CMEQ, CMLE, CMLT] */
12549                     comp = (opcode - 0x8) * 2 + u;
12550                     /* ...but LE, LT are implemented as reverse GE, GT */
12551                     reverse = (comp > 2);
12552                     if (reverse) {
12553                         comp = 4 - comp;
12554                     }
12555                     genfn = fns[comp][size];
12556                     if (reverse) {
12557                         genfn(tcg_res, tcg_zero, tcg_op);
12558                     } else {
12559                         genfn(tcg_res, tcg_op, tcg_zero);
12560                     }
12561                     tcg_temp_free_i32(tcg_zero);
12562                     break;
12563                 }
12564                 case 0xb: /* ABS, NEG */
12565                     if (u) {
12566                         TCGv_i32 tcg_zero = tcg_const_i32(0);
12567                         if (size) {
12568                             gen_helper_neon_sub_u16(tcg_res, tcg_zero, tcg_op);
12569                         } else {
12570                             gen_helper_neon_sub_u8(tcg_res, tcg_zero, tcg_op);
12571                         }
12572                         tcg_temp_free_i32(tcg_zero);
12573                     } else {
12574                         if (size) {
12575                             gen_helper_neon_abs_s16(tcg_res, tcg_op);
12576                         } else {
12577                             gen_helper_neon_abs_s8(tcg_res, tcg_op);
12578                         }
12579                     }
12580                     break;
12581                 case 0x4: /* CLS, CLZ */
12582                     if (u) {
12583                         if (size == 0) {
12584                             gen_helper_neon_clz_u8(tcg_res, tcg_op);
12585                         } else {
12586                             gen_helper_neon_clz_u16(tcg_res, tcg_op);
12587                         }
12588                     } else {
12589                         if (size == 0) {
12590                             gen_helper_neon_cls_s8(tcg_res, tcg_op);
12591                         } else {
12592                             gen_helper_neon_cls_s16(tcg_res, tcg_op);
12593                         }
12594                     }
12595                     break;
12596                 default:
12597                     g_assert_not_reached();
12598                 }
12599             }
12600
12601             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
12602
12603             tcg_temp_free_i32(tcg_res);
12604             tcg_temp_free_i32(tcg_op);
12605         }
12606     }
12607     clear_vec_high(s, is_q, rd);
12608
12609     if (need_rmode) {
12610         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12611         tcg_temp_free_i32(tcg_rmode);
12612     }
12613     if (need_fpstatus) {
12614         tcg_temp_free_ptr(tcg_fpstatus);
12615     }
12616 }
12617
12618 /* AdvSIMD [scalar] two register miscellaneous (FP16)
12619  *
12620  *   31  30  29 28  27     24  23 22 21       17 16    12 11 10 9    5 4    0
12621  * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
12622  * | 0 | Q | U | S | 1 1 1 0 | a | 1 1 1 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
12623  * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
12624  *   mask: 1000 1111 0111 1110 0000 1100 0000 0000 0x8f7e 0c00
12625  *   val:  0000 1110 0111 1000 0000 1000 0000 0000 0x0e78 0800
12626  *
12627  * This actually covers two groups where scalar access is governed by
12628  * bit 28. A bunch of the instructions (float to integral) only exist
12629  * in the vector form and are un-allocated for the scalar decode. Also
12630  * in the scalar decode Q is always 1.
12631  */
12632 static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
12633 {
12634     int fpop, opcode, a, u;
12635     int rn, rd;
12636     bool is_q;
12637     bool is_scalar;
12638     bool only_in_vector = false;
12639
12640     int pass;
12641     TCGv_i32 tcg_rmode = NULL;
12642     TCGv_ptr tcg_fpstatus = NULL;
12643     bool need_rmode = false;
12644     bool need_fpst = true;
12645     int rmode;
12646
12647     if (!dc_isar_feature(aa64_fp16, s)) {
12648         unallocated_encoding(s);
12649         return;
12650     }
12651
12652     rd = extract32(insn, 0, 5);
12653     rn = extract32(insn, 5, 5);
12654
12655     a = extract32(insn, 23, 1);
12656     u = extract32(insn, 29, 1);
12657     is_scalar = extract32(insn, 28, 1);
12658     is_q = extract32(insn, 30, 1);
12659
12660     opcode = extract32(insn, 12, 5);
12661     fpop = deposit32(opcode, 5, 1, a);
12662     fpop = deposit32(fpop, 6, 1, u);
12663
12664     rd = extract32(insn, 0, 5);
12665     rn = extract32(insn, 5, 5);
12666
12667     switch (fpop) {
12668     case 0x1d: /* SCVTF */
12669     case 0x5d: /* UCVTF */
12670     {
12671         int elements;
12672
12673         if (is_scalar) {
12674             elements = 1;
12675         } else {
12676             elements = (is_q ? 8 : 4);
12677         }
12678
12679         if (!fp_access_check(s)) {
12680             return;
12681         }
12682         handle_simd_intfp_conv(s, rd, rn, elements, !u, 0, MO_16);
12683         return;
12684     }
12685     break;
12686     case 0x2c: /* FCMGT (zero) */
12687     case 0x2d: /* FCMEQ (zero) */
12688     case 0x2e: /* FCMLT (zero) */
12689     case 0x6c: /* FCMGE (zero) */
12690     case 0x6d: /* FCMLE (zero) */
12691         handle_2misc_fcmp_zero(s, fpop, is_scalar, 0, is_q, MO_16, rn, rd);
12692         return;
12693     case 0x3d: /* FRECPE */
12694     case 0x3f: /* FRECPX */
12695         break;
12696     case 0x18: /* FRINTN */
12697         need_rmode = true;
12698         only_in_vector = true;
12699         rmode = FPROUNDING_TIEEVEN;
12700         break;
12701     case 0x19: /* FRINTM */
12702         need_rmode = true;
12703         only_in_vector = true;
12704         rmode = FPROUNDING_NEGINF;
12705         break;
12706     case 0x38: /* FRINTP */
12707         need_rmode = true;
12708         only_in_vector = true;
12709         rmode = FPROUNDING_POSINF;
12710         break;
12711     case 0x39: /* FRINTZ */
12712         need_rmode = true;
12713         only_in_vector = true;
12714         rmode = FPROUNDING_ZERO;
12715         break;
12716     case 0x58: /* FRINTA */
12717         need_rmode = true;
12718         only_in_vector = true;
12719         rmode = FPROUNDING_TIEAWAY;
12720         break;
12721     case 0x59: /* FRINTX */
12722     case 0x79: /* FRINTI */
12723         only_in_vector = true;
12724         /* current rounding mode */
12725         break;
12726     case 0x1a: /* FCVTNS */
12727         need_rmode = true;
12728         rmode = FPROUNDING_TIEEVEN;
12729         break;
12730     case 0x1b: /* FCVTMS */
12731         need_rmode = true;
12732         rmode = FPROUNDING_NEGINF;
12733         break;
12734     case 0x1c: /* FCVTAS */
12735         need_rmode = true;
12736         rmode = FPROUNDING_TIEAWAY;
12737         break;
12738     case 0x3a: /* FCVTPS */
12739         need_rmode = true;
12740         rmode = FPROUNDING_POSINF;
12741         break;
12742     case 0x3b: /* FCVTZS */
12743         need_rmode = true;
12744         rmode = FPROUNDING_ZERO;
12745         break;
12746     case 0x5a: /* FCVTNU */
12747         need_rmode = true;
12748         rmode = FPROUNDING_TIEEVEN;
12749         break;
12750     case 0x5b: /* FCVTMU */
12751         need_rmode = true;
12752         rmode = FPROUNDING_NEGINF;
12753         break;
12754     case 0x5c: /* FCVTAU */
12755         need_rmode = true;
12756         rmode = FPROUNDING_TIEAWAY;
12757         break;
12758     case 0x7a: /* FCVTPU */
12759         need_rmode = true;
12760         rmode = FPROUNDING_POSINF;
12761         break;
12762     case 0x7b: /* FCVTZU */
12763         need_rmode = true;
12764         rmode = FPROUNDING_ZERO;
12765         break;
12766     case 0x2f: /* FABS */
12767     case 0x6f: /* FNEG */
12768         need_fpst = false;
12769         break;
12770     case 0x7d: /* FRSQRTE */
12771     case 0x7f: /* FSQRT (vector) */
12772         break;
12773     default:
12774         fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop);
12775         g_assert_not_reached();
12776     }
12777
12778
12779     /* Check additional constraints for the scalar encoding */
12780     if (is_scalar) {
12781         if (!is_q) {
12782             unallocated_encoding(s);
12783             return;
12784         }
12785         /* FRINTxx is only in the vector form */
12786         if (only_in_vector) {
12787             unallocated_encoding(s);
12788             return;
12789         }
12790     }
12791
12792     if (!fp_access_check(s)) {
12793         return;
12794     }
12795
12796     if (need_rmode || need_fpst) {
12797         tcg_fpstatus = get_fpstatus_ptr(true);
12798     }
12799
12800     if (need_rmode) {
12801         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
12802         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12803     }
12804
12805     if (is_scalar) {
12806         TCGv_i32 tcg_op = read_fp_hreg(s, rn);
12807         TCGv_i32 tcg_res = tcg_temp_new_i32();
12808
12809         switch (fpop) {
12810         case 0x1a: /* FCVTNS */
12811         case 0x1b: /* FCVTMS */
12812         case 0x1c: /* FCVTAS */
12813         case 0x3a: /* FCVTPS */
12814         case 0x3b: /* FCVTZS */
12815             gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
12816             break;
12817         case 0x3d: /* FRECPE */
12818             gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
12819             break;
12820         case 0x3f: /* FRECPX */
12821             gen_helper_frecpx_f16(tcg_res, tcg_op, tcg_fpstatus);
12822             break;
12823         case 0x5a: /* FCVTNU */
12824         case 0x5b: /* FCVTMU */
12825         case 0x5c: /* FCVTAU */
12826         case 0x7a: /* FCVTPU */
12827         case 0x7b: /* FCVTZU */
12828             gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
12829             break;
12830         case 0x6f: /* FNEG */
12831             tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
12832             break;
12833         case 0x7d: /* FRSQRTE */
12834             gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
12835             break;
12836         default:
12837             g_assert_not_reached();
12838         }
12839
12840         /* limit any sign extension going on */
12841         tcg_gen_andi_i32(tcg_res, tcg_res, 0xffff);
12842         write_fp_sreg(s, rd, tcg_res);
12843
12844         tcg_temp_free_i32(tcg_res);
12845         tcg_temp_free_i32(tcg_op);
12846     } else {
12847         for (pass = 0; pass < (is_q ? 8 : 4); pass++) {
12848             TCGv_i32 tcg_op = tcg_temp_new_i32();
12849             TCGv_i32 tcg_res = tcg_temp_new_i32();
12850
12851             read_vec_element_i32(s, tcg_op, rn, pass, MO_16);
12852
12853             switch (fpop) {
12854             case 0x1a: /* FCVTNS */
12855             case 0x1b: /* FCVTMS */
12856             case 0x1c: /* FCVTAS */
12857             case 0x3a: /* FCVTPS */
12858             case 0x3b: /* FCVTZS */
12859                 gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
12860                 break;
12861             case 0x3d: /* FRECPE */
12862                 gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
12863                 break;
12864             case 0x5a: /* FCVTNU */
12865             case 0x5b: /* FCVTMU */
12866             case 0x5c: /* FCVTAU */
12867             case 0x7a: /* FCVTPU */
12868             case 0x7b: /* FCVTZU */
12869                 gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
12870                 break;
12871             case 0x18: /* FRINTN */
12872             case 0x19: /* FRINTM */
12873             case 0x38: /* FRINTP */
12874             case 0x39: /* FRINTZ */
12875             case 0x58: /* FRINTA */
12876             case 0x79: /* FRINTI */
12877                 gen_helper_advsimd_rinth(tcg_res, tcg_op, tcg_fpstatus);
12878                 break;
12879             case 0x59: /* FRINTX */
12880                 gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, tcg_fpstatus);
12881                 break;
12882             case 0x2f: /* FABS */
12883                 tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
12884                 break;
12885             case 0x6f: /* FNEG */
12886                 tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
12887                 break;
12888             case 0x7d: /* FRSQRTE */
12889                 gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
12890                 break;
12891             case 0x7f: /* FSQRT */
12892                 gen_helper_sqrt_f16(tcg_res, tcg_op, tcg_fpstatus);
12893                 break;
12894             default:
12895                 g_assert_not_reached();
12896             }
12897
12898             write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
12899
12900             tcg_temp_free_i32(tcg_res);
12901             tcg_temp_free_i32(tcg_op);
12902         }
12903
12904         clear_vec_high(s, is_q, rd);
12905     }
12906
12907     if (tcg_rmode) {
12908         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12909         tcg_temp_free_i32(tcg_rmode);
12910     }
12911
12912     if (tcg_fpstatus) {
12913         tcg_temp_free_ptr(tcg_fpstatus);
12914     }
12915 }
12916
12917 /* AdvSIMD scalar x indexed element
12918  *  31 30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
12919  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
12920  * | 0 1 | U | 1 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
12921  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
12922  * AdvSIMD vector x indexed element
12923  *   31  30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
12924  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
12925  * | 0 | Q | U | 0 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
12926  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
12927  */
12928 static void disas_simd_indexed(DisasContext *s, uint32_t insn)
12929 {
12930     /* This encoding has two kinds of instruction:
12931      *  normal, where we perform elt x idxelt => elt for each
12932      *     element in the vector
12933      *  long, where we perform elt x idxelt and generate a result of
12934      *     double the width of the input element
12935      * The long ops have a 'part' specifier (ie come in INSN, INSN2 pairs).
12936      */
12937     bool is_scalar = extract32(insn, 28, 1);
12938     bool is_q = extract32(insn, 30, 1);
12939     bool u = extract32(insn, 29, 1);
12940     int size = extract32(insn, 22, 2);
12941     int l = extract32(insn, 21, 1);
12942     int m = extract32(insn, 20, 1);
12943     /* Note that the Rm field here is only 4 bits, not 5 as it usually is */
12944     int rm = extract32(insn, 16, 4);
12945     int opcode = extract32(insn, 12, 4);
12946     int h = extract32(insn, 11, 1);
12947     int rn = extract32(insn, 5, 5);
12948     int rd = extract32(insn, 0, 5);
12949     bool is_long = false;
12950     int is_fp = 0;
12951     bool is_fp16 = false;
12952     int index;
12953     TCGv_ptr fpst;
12954
12955     switch (16 * u + opcode) {
12956     case 0x08: /* MUL */
12957     case 0x10: /* MLA */
12958     case 0x14: /* MLS */
12959         if (is_scalar) {
12960             unallocated_encoding(s);
12961             return;
12962         }
12963         break;
12964     case 0x02: /* SMLAL, SMLAL2 */
12965     case 0x12: /* UMLAL, UMLAL2 */
12966     case 0x06: /* SMLSL, SMLSL2 */
12967     case 0x16: /* UMLSL, UMLSL2 */
12968     case 0x0a: /* SMULL, SMULL2 */
12969     case 0x1a: /* UMULL, UMULL2 */
12970         if (is_scalar) {
12971             unallocated_encoding(s);
12972             return;
12973         }
12974         is_long = true;
12975         break;
12976     case 0x03: /* SQDMLAL, SQDMLAL2 */
12977     case 0x07: /* SQDMLSL, SQDMLSL2 */
12978     case 0x0b: /* SQDMULL, SQDMULL2 */
12979         is_long = true;
12980         break;
12981     case 0x0c: /* SQDMULH */
12982     case 0x0d: /* SQRDMULH */
12983         break;
12984     case 0x01: /* FMLA */
12985     case 0x05: /* FMLS */
12986     case 0x09: /* FMUL */
12987     case 0x19: /* FMULX */
12988         is_fp = 1;
12989         break;
12990     case 0x1d: /* SQRDMLAH */
12991     case 0x1f: /* SQRDMLSH */
12992         if (!dc_isar_feature(aa64_rdm, s)) {
12993             unallocated_encoding(s);
12994             return;
12995         }
12996         break;
12997     case 0x0e: /* SDOT */
12998     case 0x1e: /* UDOT */
12999         if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_dp, s)) {
13000             unallocated_encoding(s);
13001             return;
13002         }
13003         break;
13004     case 0x11: /* FCMLA #0 */
13005     case 0x13: /* FCMLA #90 */
13006     case 0x15: /* FCMLA #180 */
13007     case 0x17: /* FCMLA #270 */
13008         if (is_scalar || !dc_isar_feature(aa64_fcma, s)) {
13009             unallocated_encoding(s);
13010             return;
13011         }
13012         is_fp = 2;
13013         break;
13014     case 0x00: /* FMLAL */
13015     case 0x04: /* FMLSL */
13016     case 0x18: /* FMLAL2 */
13017     case 0x1c: /* FMLSL2 */
13018         if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_fhm, s)) {
13019             unallocated_encoding(s);
13020             return;
13021         }
13022         size = MO_16;
13023         /* is_fp, but we pass cpu_env not fp_status.  */
13024         break;
13025     default:
13026         unallocated_encoding(s);
13027         return;
13028     }
13029
13030     switch (is_fp) {
13031     case 1: /* normal fp */
13032         /* convert insn encoded size to TCGMemOp size */
13033         switch (size) {
13034         case 0: /* half-precision */
13035             size = MO_16;
13036             is_fp16 = true;
13037             break;
13038         case MO_32: /* single precision */
13039         case MO_64: /* double precision */
13040             break;
13041         default:
13042             unallocated_encoding(s);
13043             return;
13044         }
13045         break;
13046
13047     case 2: /* complex fp */
13048         /* Each indexable element is a complex pair.  */
13049         size += 1;
13050         switch (size) {
13051         case MO_32:
13052             if (h && !is_q) {
13053                 unallocated_encoding(s);
13054                 return;
13055             }
13056             is_fp16 = true;
13057             break;
13058         case MO_64:
13059             break;
13060         default:
13061             unallocated_encoding(s);
13062             return;
13063         }
13064         break;
13065
13066     default: /* integer */
13067         switch (size) {
13068         case MO_8:
13069         case MO_64:
13070             unallocated_encoding(s);
13071             return;
13072         }
13073         break;
13074     }
13075     if (is_fp16 && !dc_isar_feature(aa64_fp16, s)) {
13076         unallocated_encoding(s);
13077         return;
13078     }
13079
13080     /* Given TCGMemOp size, adjust register and indexing.  */
13081     switch (size) {
13082     case MO_16:
13083         index = h << 2 | l << 1 | m;
13084         break;
13085     case MO_32:
13086         index = h << 1 | l;
13087         rm |= m << 4;
13088         break;
13089     case MO_64:
13090         if (l || !is_q) {
13091             unallocated_encoding(s);
13092             return;
13093         }
13094         index = h;
13095         rm |= m << 4;
13096         break;
13097     default:
13098         g_assert_not_reached();
13099     }
13100
13101     if (!fp_access_check(s)) {
13102         return;
13103     }
13104
13105     if (is_fp) {
13106         fpst = get_fpstatus_ptr(is_fp16);
13107     } else {
13108         fpst = NULL;
13109     }
13110
13111     switch (16 * u + opcode) {
13112     case 0x0e: /* SDOT */
13113     case 0x1e: /* UDOT */
13114         gen_gvec_op3_ool(s, is_q, rd, rn, rm, index,
13115                          u ? gen_helper_gvec_udot_idx_b
13116                          : gen_helper_gvec_sdot_idx_b);
13117         return;
13118     case 0x11: /* FCMLA #0 */
13119     case 0x13: /* FCMLA #90 */
13120     case 0x15: /* FCMLA #180 */
13121     case 0x17: /* FCMLA #270 */
13122         {
13123             int rot = extract32(insn, 13, 2);
13124             int data = (index << 2) | rot;
13125             tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
13126                                vec_full_reg_offset(s, rn),
13127                                vec_full_reg_offset(s, rm), fpst,
13128                                is_q ? 16 : 8, vec_full_reg_size(s), data,
13129                                size == MO_64
13130                                ? gen_helper_gvec_fcmlas_idx
13131                                : gen_helper_gvec_fcmlah_idx);
13132             tcg_temp_free_ptr(fpst);
13133         }
13134         return;
13135
13136     case 0x00: /* FMLAL */
13137     case 0x04: /* FMLSL */
13138     case 0x18: /* FMLAL2 */
13139     case 0x1c: /* FMLSL2 */
13140         {
13141             int is_s = extract32(opcode, 2, 1);
13142             int is_2 = u;
13143             int data = (index << 2) | (is_2 << 1) | is_s;
13144             tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
13145                                vec_full_reg_offset(s, rn),
13146                                vec_full_reg_offset(s, rm), cpu_env,
13147                                is_q ? 16 : 8, vec_full_reg_size(s),
13148                                data, gen_helper_gvec_fmlal_idx_a64);
13149         }
13150         return;
13151     }
13152
13153     if (size == 3) {
13154         TCGv_i64 tcg_idx = tcg_temp_new_i64();
13155         int pass;
13156
13157         assert(is_fp && is_q && !is_long);
13158
13159         read_vec_element(s, tcg_idx, rm, index, MO_64);
13160
13161         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13162             TCGv_i64 tcg_op = tcg_temp_new_i64();
13163             TCGv_i64 tcg_res = tcg_temp_new_i64();
13164
13165             read_vec_element(s, tcg_op, rn, pass, MO_64);
13166
13167             switch (16 * u + opcode) {
13168             case 0x05: /* FMLS */
13169                 /* As usual for ARM, separate negation for fused multiply-add */
13170                 gen_helper_vfp_negd(tcg_op, tcg_op);
13171                 /* fall through */
13172             case 0x01: /* FMLA */
13173                 read_vec_element(s, tcg_res, rd, pass, MO_64);
13174                 gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
13175                 break;
13176             case 0x09: /* FMUL */
13177                 gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
13178                 break;
13179             case 0x19: /* FMULX */
13180                 gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
13181                 break;
13182             default:
13183                 g_assert_not_reached();
13184             }
13185
13186             write_vec_element(s, tcg_res, rd, pass, MO_64);
13187             tcg_temp_free_i64(tcg_op);
13188             tcg_temp_free_i64(tcg_res);
13189         }
13190
13191         tcg_temp_free_i64(tcg_idx);
13192         clear_vec_high(s, !is_scalar, rd);
13193     } else if (!is_long) {
13194         /* 32 bit floating point, or 16 or 32 bit integer.
13195          * For the 16 bit scalar case we use the usual Neon helpers and
13196          * rely on the fact that 0 op 0 == 0 with no side effects.
13197          */
13198         TCGv_i32 tcg_idx = tcg_temp_new_i32();
13199         int pass, maxpasses;
13200
13201         if (is_scalar) {
13202             maxpasses = 1;
13203         } else {
13204             maxpasses = is_q ? 4 : 2;
13205         }
13206
13207         read_vec_element_i32(s, tcg_idx, rm, index, size);
13208
13209         if (size == 1 && !is_scalar) {
13210             /* The simplest way to handle the 16x16 indexed ops is to duplicate
13211              * the index into both halves of the 32 bit tcg_idx and then use
13212              * the usual Neon helpers.
13213              */
13214             tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
13215         }
13216
13217         for (pass = 0; pass < maxpasses; pass++) {
13218             TCGv_i32 tcg_op = tcg_temp_new_i32();
13219             TCGv_i32 tcg_res = tcg_temp_new_i32();
13220
13221             read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
13222
13223             switch (16 * u + opcode) {
13224             case 0x08: /* MUL */
13225             case 0x10: /* MLA */
13226             case 0x14: /* MLS */
13227             {
13228                 static NeonGenTwoOpFn * const fns[2][2] = {
13229                     { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
13230                     { tcg_gen_add_i32, tcg_gen_sub_i32 },
13231                 };
13232                 NeonGenTwoOpFn *genfn;
13233                 bool is_sub = opcode == 0x4;
13234
13235                 if (size == 1) {
13236                     gen_helper_neon_mul_u16(tcg_res, tcg_op, tcg_idx);
13237                 } else {
13238                     tcg_gen_mul_i32(tcg_res, tcg_op, tcg_idx);
13239                 }
13240                 if (opcode == 0x8) {
13241                     break;
13242                 }
13243                 read_vec_element_i32(s, tcg_op, rd, pass, MO_32);
13244                 genfn = fns[size - 1][is_sub];
13245                 genfn(tcg_res, tcg_op, tcg_res);
13246                 break;
13247             }
13248             case 0x05: /* FMLS */
13249             case 0x01: /* FMLA */
13250                 read_vec_element_i32(s, tcg_res, rd, pass,
13251                                      is_scalar ? size : MO_32);
13252                 switch (size) {
13253                 case 1:
13254                     if (opcode == 0x5) {
13255                         /* As usual for ARM, separate negation for fused
13256                          * multiply-add */
13257                         tcg_gen_xori_i32(tcg_op, tcg_op, 0x80008000);
13258                     }
13259                     if (is_scalar) {
13260                         gen_helper_advsimd_muladdh(tcg_res, tcg_op, tcg_idx,
13261                                                    tcg_res, fpst);
13262                     } else {
13263                         gen_helper_advsimd_muladd2h(tcg_res, tcg_op, tcg_idx,
13264                                                     tcg_res, fpst);
13265                     }
13266                     break;
13267                 case 2:
13268                     if (opcode == 0x5) {
13269                         /* As usual for ARM, separate negation for
13270                          * fused multiply-add */
13271                         tcg_gen_xori_i32(tcg_op, tcg_op, 0x80000000);
13272                     }
13273                     gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx,
13274                                            tcg_res, fpst);
13275                     break;
13276                 default:
13277                     g_assert_not_reached();
13278                 }
13279                 break;
13280             case 0x09: /* FMUL */
13281                 switch (size) {
13282                 case 1:
13283                     if (is_scalar) {
13284                         gen_helper_advsimd_mulh(tcg_res, tcg_op,
13285                                                 tcg_idx, fpst);
13286                     } else {
13287                         gen_helper_advsimd_mul2h(tcg_res, tcg_op,
13288                                                  tcg_idx, fpst);
13289                     }
13290                     break;
13291                 case 2:
13292                     gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
13293                     break;
13294                 default:
13295                     g_assert_not_reached();
13296                 }
13297                 break;
13298             case 0x19: /* FMULX */
13299                 switch (size) {
13300                 case 1:
13301                     if (is_scalar) {
13302                         gen_helper_advsimd_mulxh(tcg_res, tcg_op,
13303                                                  tcg_idx, fpst);
13304                     } else {
13305                         gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
13306                                                   tcg_idx, fpst);
13307                     }
13308                     break;
13309                 case 2:
13310                     gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
13311                     break;
13312                 default:
13313                     g_assert_not_reached();
13314                 }
13315                 break;
13316             case 0x0c: /* SQDMULH */
13317                 if (size == 1) {
13318                     gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
13319                                                tcg_op, tcg_idx);
13320                 } else {
13321                     gen_helper_neon_qdmulh_s32(tcg_res, cpu_env,
13322                                                tcg_op, tcg_idx);
13323                 }
13324                 break;
13325             case 0x0d: /* SQRDMULH */
13326                 if (size == 1) {
13327                     gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
13328                                                 tcg_op, tcg_idx);
13329                 } else {
13330                     gen_helper_neon_qrdmulh_s32(tcg_res, cpu_env,
13331                                                 tcg_op, tcg_idx);
13332                 }
13333                 break;
13334             case 0x1d: /* SQRDMLAH */
13335                 read_vec_element_i32(s, tcg_res, rd, pass,
13336                                      is_scalar ? size : MO_32);
13337                 if (size == 1) {
13338                     gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
13339                                                 tcg_op, tcg_idx, tcg_res);
13340                 } else {
13341                     gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
13342                                                 tcg_op, tcg_idx, tcg_res);
13343                 }
13344                 break;
13345             case 0x1f: /* SQRDMLSH */
13346                 read_vec_element_i32(s, tcg_res, rd, pass,
13347                                      is_scalar ? size : MO_32);
13348                 if (size == 1) {
13349                     gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
13350                                                 tcg_op, tcg_idx, tcg_res);
13351                 } else {
13352                     gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
13353                                                 tcg_op, tcg_idx, tcg_res);
13354                 }
13355                 break;
13356             default:
13357                 g_assert_not_reached();
13358             }
13359
13360             if (is_scalar) {
13361                 write_fp_sreg(s, rd, tcg_res);
13362             } else {
13363                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
13364             }
13365
13366             tcg_temp_free_i32(tcg_op);
13367             tcg_temp_free_i32(tcg_res);
13368         }
13369
13370         tcg_temp_free_i32(tcg_idx);
13371         clear_vec_high(s, is_q, rd);
13372     } else {
13373         /* long ops: 16x16->32 or 32x32->64 */
13374         TCGv_i64 tcg_res[2];
13375         int pass;
13376         bool satop = extract32(opcode, 0, 1);
13377         TCGMemOp memop = MO_32;
13378
13379         if (satop || !u) {
13380             memop |= MO_SIGN;
13381         }
13382
13383         if (size == 2) {
13384             TCGv_i64 tcg_idx = tcg_temp_new_i64();
13385
13386             read_vec_element(s, tcg_idx, rm, index, memop);
13387
13388             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13389                 TCGv_i64 tcg_op = tcg_temp_new_i64();
13390                 TCGv_i64 tcg_passres;
13391                 int passelt;
13392
13393                 if (is_scalar) {
13394                     passelt = 0;
13395                 } else {
13396                     passelt = pass + (is_q * 2);
13397                 }
13398
13399                 read_vec_element(s, tcg_op, rn, passelt, memop);
13400
13401                 tcg_res[pass] = tcg_temp_new_i64();
13402
13403                 if (opcode == 0xa || opcode == 0xb) {
13404                     /* Non-accumulating ops */
13405                     tcg_passres = tcg_res[pass];
13406                 } else {
13407                     tcg_passres = tcg_temp_new_i64();
13408                 }
13409
13410                 tcg_gen_mul_i64(tcg_passres, tcg_op, tcg_idx);
13411                 tcg_temp_free_i64(tcg_op);
13412
13413                 if (satop) {
13414                     /* saturating, doubling */
13415                     gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
13416                                                       tcg_passres, tcg_passres);
13417                 }
13418
13419                 if (opcode == 0xa || opcode == 0xb) {
13420                     continue;
13421                 }
13422
13423                 /* Accumulating op: handle accumulate step */
13424                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13425
13426                 switch (opcode) {
13427                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
13428                     tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
13429                     break;
13430                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
13431                     tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
13432                     break;
13433                 case 0x7: /* SQDMLSL, SQDMLSL2 */
13434                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
13435                     /* fall through */
13436                 case 0x3: /* SQDMLAL, SQDMLAL2 */
13437                     gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
13438                                                       tcg_res[pass],
13439                                                       tcg_passres);
13440                     break;
13441                 default:
13442                     g_assert_not_reached();
13443                 }
13444                 tcg_temp_free_i64(tcg_passres);
13445             }
13446             tcg_temp_free_i64(tcg_idx);
13447
13448             clear_vec_high(s, !is_scalar, rd);
13449         } else {
13450             TCGv_i32 tcg_idx = tcg_temp_new_i32();
13451
13452             assert(size == 1);
13453             read_vec_element_i32(s, tcg_idx, rm, index, size);
13454
13455             if (!is_scalar) {
13456                 /* The simplest way to handle the 16x16 indexed ops is to
13457                  * duplicate the index into both halves of the 32 bit tcg_idx
13458                  * and then use the usual Neon helpers.
13459                  */
13460                 tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
13461             }
13462
13463             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13464                 TCGv_i32 tcg_op = tcg_temp_new_i32();
13465                 TCGv_i64 tcg_passres;
13466
13467                 if (is_scalar) {
13468                     read_vec_element_i32(s, tcg_op, rn, pass, size);
13469                 } else {
13470                     read_vec_element_i32(s, tcg_op, rn,
13471                                          pass + (is_q * 2), MO_32);
13472                 }
13473
13474                 tcg_res[pass] = tcg_temp_new_i64();
13475
13476                 if (opcode == 0xa || opcode == 0xb) {
13477                     /* Non-accumulating ops */
13478                     tcg_passres = tcg_res[pass];
13479                 } else {
13480                     tcg_passres = tcg_temp_new_i64();
13481                 }
13482
13483                 if (memop & MO_SIGN) {
13484                     gen_helper_neon_mull_s16(tcg_passres, tcg_op, tcg_idx);
13485                 } else {
13486                     gen_helper_neon_mull_u16(tcg_passres, tcg_op, tcg_idx);
13487                 }
13488                 if (satop) {
13489                     gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
13490                                                       tcg_passres, tcg_passres);
13491                 }
13492                 tcg_temp_free_i32(tcg_op);
13493
13494                 if (opcode == 0xa || opcode == 0xb) {
13495                     continue;
13496                 }
13497
13498                 /* Accumulating op: handle accumulate step */
13499                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13500
13501                 switch (opcode) {
13502                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
13503                     gen_helper_neon_addl_u32(tcg_res[pass], tcg_res[pass],
13504                                              tcg_passres);
13505                     break;
13506                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
13507                     gen_helper_neon_subl_u32(tcg_res[pass], tcg_res[pass],
13508                                              tcg_passres);
13509                     break;
13510                 case 0x7: /* SQDMLSL, SQDMLSL2 */
13511                     gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
13512                     /* fall through */
13513                 case 0x3: /* SQDMLAL, SQDMLAL2 */
13514                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
13515                                                       tcg_res[pass],
13516                                                       tcg_passres);
13517                     break;
13518                 default:
13519                     g_assert_not_reached();
13520                 }
13521                 tcg_temp_free_i64(tcg_passres);
13522             }
13523             tcg_temp_free_i32(tcg_idx);
13524
13525             if (is_scalar) {
13526                 tcg_gen_ext32u_i64(tcg_res[0], tcg_res[0]);
13527             }
13528         }
13529
13530         if (is_scalar) {
13531             tcg_res[1] = tcg_const_i64(0);
13532         }
13533
13534         for (pass = 0; pass < 2; pass++) {
13535             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13536             tcg_temp_free_i64(tcg_res[pass]);
13537         }
13538     }
13539
13540     if (fpst) {
13541         tcg_temp_free_ptr(fpst);
13542     }
13543 }
13544
13545 /* Crypto AES
13546  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
13547  * +-----------------+------+-----------+--------+-----+------+------+
13548  * | 0 1 0 0 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
13549  * +-----------------+------+-----------+--------+-----+------+------+
13550  */
13551 static void disas_crypto_aes(DisasContext *s, uint32_t insn)
13552 {
13553     int size = extract32(insn, 22, 2);
13554     int opcode = extract32(insn, 12, 5);
13555     int rn = extract32(insn, 5, 5);
13556     int rd = extract32(insn, 0, 5);
13557     int decrypt;
13558     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13559     TCGv_i32 tcg_decrypt;
13560     CryptoThreeOpIntFn *genfn;
13561
13562     if (!dc_isar_feature(aa64_aes, s) || size != 0) {
13563         unallocated_encoding(s);
13564         return;
13565     }
13566
13567     switch (opcode) {
13568     case 0x4: /* AESE */
13569         decrypt = 0;
13570         genfn = gen_helper_crypto_aese;
13571         break;
13572     case 0x6: /* AESMC */
13573         decrypt = 0;
13574         genfn = gen_helper_crypto_aesmc;
13575         break;
13576     case 0x5: /* AESD */
13577         decrypt = 1;
13578         genfn = gen_helper_crypto_aese;
13579         break;
13580     case 0x7: /* AESIMC */
13581         decrypt = 1;
13582         genfn = gen_helper_crypto_aesmc;
13583         break;
13584     default:
13585         unallocated_encoding(s);
13586         return;
13587     }
13588
13589     if (!fp_access_check(s)) {
13590         return;
13591     }
13592
13593     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13594     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13595     tcg_decrypt = tcg_const_i32(decrypt);
13596
13597     genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt);
13598
13599     tcg_temp_free_ptr(tcg_rd_ptr);
13600     tcg_temp_free_ptr(tcg_rn_ptr);
13601     tcg_temp_free_i32(tcg_decrypt);
13602 }
13603
13604 /* Crypto three-reg SHA
13605  *  31             24 23  22  21 20  16  15 14    12 11 10 9    5 4    0
13606  * +-----------------+------+---+------+---+--------+-----+------+------+
13607  * | 0 1 0 1 1 1 1 0 | size | 0 |  Rm  | 0 | opcode | 0 0 |  Rn  |  Rd  |
13608  * +-----------------+------+---+------+---+--------+-----+------+------+
13609  */
13610 static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
13611 {
13612     int size = extract32(insn, 22, 2);
13613     int opcode = extract32(insn, 12, 3);
13614     int rm = extract32(insn, 16, 5);
13615     int rn = extract32(insn, 5, 5);
13616     int rd = extract32(insn, 0, 5);
13617     CryptoThreeOpFn *genfn;
13618     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
13619     bool feature;
13620
13621     if (size != 0) {
13622         unallocated_encoding(s);
13623         return;
13624     }
13625
13626     switch (opcode) {
13627     case 0: /* SHA1C */
13628     case 1: /* SHA1P */
13629     case 2: /* SHA1M */
13630     case 3: /* SHA1SU0 */
13631         genfn = NULL;
13632         feature = dc_isar_feature(aa64_sha1, s);
13633         break;
13634     case 4: /* SHA256H */
13635         genfn = gen_helper_crypto_sha256h;
13636         feature = dc_isar_feature(aa64_sha256, s);
13637         break;
13638     case 5: /* SHA256H2 */
13639         genfn = gen_helper_crypto_sha256h2;
13640         feature = dc_isar_feature(aa64_sha256, s);
13641         break;
13642     case 6: /* SHA256SU1 */
13643         genfn = gen_helper_crypto_sha256su1;
13644         feature = dc_isar_feature(aa64_sha256, s);
13645         break;
13646     default:
13647         unallocated_encoding(s);
13648         return;
13649     }
13650
13651     if (!feature) {
13652         unallocated_encoding(s);
13653         return;
13654     }
13655
13656     if (!fp_access_check(s)) {
13657         return;
13658     }
13659
13660     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13661     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13662     tcg_rm_ptr = vec_full_reg_ptr(s, rm);
13663
13664     if (genfn) {
13665         genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
13666     } else {
13667         TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
13668
13669         gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
13670                                     tcg_rm_ptr, tcg_opcode);
13671         tcg_temp_free_i32(tcg_opcode);
13672     }
13673
13674     tcg_temp_free_ptr(tcg_rd_ptr);
13675     tcg_temp_free_ptr(tcg_rn_ptr);
13676     tcg_temp_free_ptr(tcg_rm_ptr);
13677 }
13678
13679 /* Crypto two-reg SHA
13680  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
13681  * +-----------------+------+-----------+--------+-----+------+------+
13682  * | 0 1 0 1 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
13683  * +-----------------+------+-----------+--------+-----+------+------+
13684  */
13685 static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
13686 {
13687     int size = extract32(insn, 22, 2);
13688     int opcode = extract32(insn, 12, 5);
13689     int rn = extract32(insn, 5, 5);
13690     int rd = extract32(insn, 0, 5);
13691     CryptoTwoOpFn *genfn;
13692     bool feature;
13693     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13694
13695     if (size != 0) {
13696         unallocated_encoding(s);
13697         return;
13698     }
13699
13700     switch (opcode) {
13701     case 0: /* SHA1H */
13702         feature = dc_isar_feature(aa64_sha1, s);
13703         genfn = gen_helper_crypto_sha1h;
13704         break;
13705     case 1: /* SHA1SU1 */
13706         feature = dc_isar_feature(aa64_sha1, s);
13707         genfn = gen_helper_crypto_sha1su1;
13708         break;
13709     case 2: /* SHA256SU0 */
13710         feature = dc_isar_feature(aa64_sha256, s);
13711         genfn = gen_helper_crypto_sha256su0;
13712         break;
13713     default:
13714         unallocated_encoding(s);
13715         return;
13716     }
13717
13718     if (!feature) {
13719         unallocated_encoding(s);
13720         return;
13721     }
13722
13723     if (!fp_access_check(s)) {
13724         return;
13725     }
13726
13727     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13728     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13729
13730     genfn(tcg_rd_ptr, tcg_rn_ptr);
13731
13732     tcg_temp_free_ptr(tcg_rd_ptr);
13733     tcg_temp_free_ptr(tcg_rn_ptr);
13734 }
13735
13736 /* Crypto three-reg SHA512
13737  *  31                   21 20  16 15  14  13 12  11  10  9    5 4    0
13738  * +-----------------------+------+---+---+-----+--------+------+------+
13739  * | 1 1 0 0 1 1 1 0 0 1 1 |  Rm  | 1 | O | 0 0 | opcode |  Rn  |  Rd  |
13740  * +-----------------------+------+---+---+-----+--------+------+------+
13741  */
13742 static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
13743 {
13744     int opcode = extract32(insn, 10, 2);
13745     int o =  extract32(insn, 14, 1);
13746     int rm = extract32(insn, 16, 5);
13747     int rn = extract32(insn, 5, 5);
13748     int rd = extract32(insn, 0, 5);
13749     bool feature;
13750     CryptoThreeOpFn *genfn;
13751
13752     if (o == 0) {
13753         switch (opcode) {
13754         case 0: /* SHA512H */
13755             feature = dc_isar_feature(aa64_sha512, s);
13756             genfn = gen_helper_crypto_sha512h;
13757             break;
13758         case 1: /* SHA512H2 */
13759             feature = dc_isar_feature(aa64_sha512, s);
13760             genfn = gen_helper_crypto_sha512h2;
13761             break;
13762         case 2: /* SHA512SU1 */
13763             feature = dc_isar_feature(aa64_sha512, s);
13764             genfn = gen_helper_crypto_sha512su1;
13765             break;
13766         case 3: /* RAX1 */
13767             feature = dc_isar_feature(aa64_sha3, s);
13768             genfn = NULL;
13769             break;
13770         }
13771     } else {
13772         switch (opcode) {
13773         case 0: /* SM3PARTW1 */
13774             feature = dc_isar_feature(aa64_sm3, s);
13775             genfn = gen_helper_crypto_sm3partw1;
13776             break;
13777         case 1: /* SM3PARTW2 */
13778             feature = dc_isar_feature(aa64_sm3, s);
13779             genfn = gen_helper_crypto_sm3partw2;
13780             break;
13781         case 2: /* SM4EKEY */
13782             feature = dc_isar_feature(aa64_sm4, s);
13783             genfn = gen_helper_crypto_sm4ekey;
13784             break;
13785         default:
13786             unallocated_encoding(s);
13787             return;
13788         }
13789     }
13790
13791     if (!feature) {
13792         unallocated_encoding(s);
13793         return;
13794     }
13795
13796     if (!fp_access_check(s)) {
13797         return;
13798     }
13799
13800     if (genfn) {
13801         TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
13802
13803         tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13804         tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13805         tcg_rm_ptr = vec_full_reg_ptr(s, rm);
13806
13807         genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
13808
13809         tcg_temp_free_ptr(tcg_rd_ptr);
13810         tcg_temp_free_ptr(tcg_rn_ptr);
13811         tcg_temp_free_ptr(tcg_rm_ptr);
13812     } else {
13813         TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
13814         int pass;
13815
13816         tcg_op1 = tcg_temp_new_i64();
13817         tcg_op2 = tcg_temp_new_i64();
13818         tcg_res[0] = tcg_temp_new_i64();
13819         tcg_res[1] = tcg_temp_new_i64();
13820
13821         for (pass = 0; pass < 2; pass++) {
13822             read_vec_element(s, tcg_op1, rn, pass, MO_64);
13823             read_vec_element(s, tcg_op2, rm, pass, MO_64);
13824
13825             tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1);
13826             tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
13827         }
13828         write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13829         write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13830
13831         tcg_temp_free_i64(tcg_op1);
13832         tcg_temp_free_i64(tcg_op2);
13833         tcg_temp_free_i64(tcg_res[0]);
13834         tcg_temp_free_i64(tcg_res[1]);
13835     }
13836 }
13837
13838 /* Crypto two-reg SHA512
13839  *  31                                     12  11  10  9    5 4    0
13840  * +-----------------------------------------+--------+------+------+
13841  * | 1 1 0 0 1 1 1 0 1 1 0 0 0 0 0 0 1 0 0 0 | opcode |  Rn  |  Rd  |
13842  * +-----------------------------------------+--------+------+------+
13843  */
13844 static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
13845 {
13846     int opcode = extract32(insn, 10, 2);
13847     int rn = extract32(insn, 5, 5);
13848     int rd = extract32(insn, 0, 5);
13849     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13850     bool feature;
13851     CryptoTwoOpFn *genfn;
13852
13853     switch (opcode) {
13854     case 0: /* SHA512SU0 */
13855         feature = dc_isar_feature(aa64_sha512, s);
13856         genfn = gen_helper_crypto_sha512su0;
13857         break;
13858     case 1: /* SM4E */
13859         feature = dc_isar_feature(aa64_sm4, s);
13860         genfn = gen_helper_crypto_sm4e;
13861         break;
13862     default:
13863         unallocated_encoding(s);
13864         return;
13865     }
13866
13867     if (!feature) {
13868         unallocated_encoding(s);
13869         return;
13870     }
13871
13872     if (!fp_access_check(s)) {
13873         return;
13874     }
13875
13876     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13877     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13878
13879     genfn(tcg_rd_ptr, tcg_rn_ptr);
13880
13881     tcg_temp_free_ptr(tcg_rd_ptr);
13882     tcg_temp_free_ptr(tcg_rn_ptr);
13883 }
13884
13885 /* Crypto four-register
13886  *  31               23 22 21 20  16 15  14  10 9    5 4    0
13887  * +-------------------+-----+------+---+------+------+------+
13888  * | 1 1 0 0 1 1 1 0 0 | Op0 |  Rm  | 0 |  Ra  |  Rn  |  Rd  |
13889  * +-------------------+-----+------+---+------+------+------+
13890  */
13891 static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
13892 {
13893     int op0 = extract32(insn, 21, 2);
13894     int rm = extract32(insn, 16, 5);
13895     int ra = extract32(insn, 10, 5);
13896     int rn = extract32(insn, 5, 5);
13897     int rd = extract32(insn, 0, 5);
13898     bool feature;
13899
13900     switch (op0) {
13901     case 0: /* EOR3 */
13902     case 1: /* BCAX */
13903         feature = dc_isar_feature(aa64_sha3, s);
13904         break;
13905     case 2: /* SM3SS1 */
13906         feature = dc_isar_feature(aa64_sm3, s);
13907         break;
13908     default:
13909         unallocated_encoding(s);
13910         return;
13911     }
13912
13913     if (!feature) {
13914         unallocated_encoding(s);
13915         return;
13916     }
13917
13918     if (!fp_access_check(s)) {
13919         return;
13920     }
13921
13922     if (op0 < 2) {
13923         TCGv_i64 tcg_op1, tcg_op2, tcg_op3, tcg_res[2];
13924         int pass;
13925
13926         tcg_op1 = tcg_temp_new_i64();
13927         tcg_op2 = tcg_temp_new_i64();
13928         tcg_op3 = tcg_temp_new_i64();
13929         tcg_res[0] = tcg_temp_new_i64();
13930         tcg_res[1] = tcg_temp_new_i64();
13931
13932         for (pass = 0; pass < 2; pass++) {
13933             read_vec_element(s, tcg_op1, rn, pass, MO_64);
13934             read_vec_element(s, tcg_op2, rm, pass, MO_64);
13935             read_vec_element(s, tcg_op3, ra, pass, MO_64);
13936
13937             if (op0 == 0) {
13938                 /* EOR3 */
13939                 tcg_gen_xor_i64(tcg_res[pass], tcg_op2, tcg_op3);
13940             } else {
13941                 /* BCAX */
13942                 tcg_gen_andc_i64(tcg_res[pass], tcg_op2, tcg_op3);
13943             }
13944             tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
13945         }
13946         write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13947         write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13948
13949         tcg_temp_free_i64(tcg_op1);
13950         tcg_temp_free_i64(tcg_op2);
13951         tcg_temp_free_i64(tcg_op3);
13952         tcg_temp_free_i64(tcg_res[0]);
13953         tcg_temp_free_i64(tcg_res[1]);
13954     } else {
13955         TCGv_i32 tcg_op1, tcg_op2, tcg_op3, tcg_res, tcg_zero;
13956
13957         tcg_op1 = tcg_temp_new_i32();
13958         tcg_op2 = tcg_temp_new_i32();
13959         tcg_op3 = tcg_temp_new_i32();
13960         tcg_res = tcg_temp_new_i32();
13961         tcg_zero = tcg_const_i32(0);
13962
13963         read_vec_element_i32(s, tcg_op1, rn, 3, MO_32);
13964         read_vec_element_i32(s, tcg_op2, rm, 3, MO_32);
13965         read_vec_element_i32(s, tcg_op3, ra, 3, MO_32);
13966
13967         tcg_gen_rotri_i32(tcg_res, tcg_op1, 20);
13968         tcg_gen_add_i32(tcg_res, tcg_res, tcg_op2);
13969         tcg_gen_add_i32(tcg_res, tcg_res, tcg_op3);
13970         tcg_gen_rotri_i32(tcg_res, tcg_res, 25);
13971
13972         write_vec_element_i32(s, tcg_zero, rd, 0, MO_32);
13973         write_vec_element_i32(s, tcg_zero, rd, 1, MO_32);
13974         write_vec_element_i32(s, tcg_zero, rd, 2, MO_32);
13975         write_vec_element_i32(s, tcg_res, rd, 3, MO_32);
13976
13977         tcg_temp_free_i32(tcg_op1);
13978         tcg_temp_free_i32(tcg_op2);
13979         tcg_temp_free_i32(tcg_op3);
13980         tcg_temp_free_i32(tcg_res);
13981         tcg_temp_free_i32(tcg_zero);
13982     }
13983 }
13984
13985 /* Crypto XAR
13986  *  31                   21 20  16 15    10 9    5 4    0
13987  * +-----------------------+------+--------+------+------+
13988  * | 1 1 0 0 1 1 1 0 1 0 0 |  Rm  |  imm6  |  Rn  |  Rd  |
13989  * +-----------------------+------+--------+------+------+
13990  */
13991 static void disas_crypto_xar(DisasContext *s, uint32_t insn)
13992 {
13993     int rm = extract32(insn, 16, 5);
13994     int imm6 = extract32(insn, 10, 6);
13995     int rn = extract32(insn, 5, 5);
13996     int rd = extract32(insn, 0, 5);
13997     TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
13998     int pass;
13999
14000     if (!dc_isar_feature(aa64_sha3, s)) {
14001         unallocated_encoding(s);
14002         return;
14003     }
14004
14005     if (!fp_access_check(s)) {
14006         return;
14007     }
14008
14009     tcg_op1 = tcg_temp_new_i64();
14010     tcg_op2 = tcg_temp_new_i64();
14011     tcg_res[0] = tcg_temp_new_i64();
14012     tcg_res[1] = tcg_temp_new_i64();
14013
14014     for (pass = 0; pass < 2; pass++) {
14015         read_vec_element(s, tcg_op1, rn, pass, MO_64);
14016         read_vec_element(s, tcg_op2, rm, pass, MO_64);
14017
14018         tcg_gen_xor_i64(tcg_res[pass], tcg_op1, tcg_op2);
14019         tcg_gen_rotri_i64(tcg_res[pass], tcg_res[pass], imm6);
14020     }
14021     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
14022     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
14023
14024     tcg_temp_free_i64(tcg_op1);
14025     tcg_temp_free_i64(tcg_op2);
14026     tcg_temp_free_i64(tcg_res[0]);
14027     tcg_temp_free_i64(tcg_res[1]);
14028 }
14029
14030 /* Crypto three-reg imm2
14031  *  31                   21 20  16 15  14 13 12  11  10  9    5 4    0
14032  * +-----------------------+------+-----+------+--------+------+------+
14033  * | 1 1 0 0 1 1 1 0 0 1 0 |  Rm  | 1 0 | imm2 | opcode |  Rn  |  Rd  |
14034  * +-----------------------+------+-----+------+--------+------+------+
14035  */
14036 static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
14037 {
14038     int opcode = extract32(insn, 10, 2);
14039     int imm2 = extract32(insn, 12, 2);
14040     int rm = extract32(insn, 16, 5);
14041     int rn = extract32(insn, 5, 5);
14042     int rd = extract32(insn, 0, 5);
14043     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
14044     TCGv_i32 tcg_imm2, tcg_opcode;
14045
14046     if (!dc_isar_feature(aa64_sm3, s)) {
14047         unallocated_encoding(s);
14048         return;
14049     }
14050
14051     if (!fp_access_check(s)) {
14052         return;
14053     }
14054
14055     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
14056     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
14057     tcg_rm_ptr = vec_full_reg_ptr(s, rm);
14058     tcg_imm2   = tcg_const_i32(imm2);
14059     tcg_opcode = tcg_const_i32(opcode);
14060
14061     gen_helper_crypto_sm3tt(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr, tcg_imm2,
14062                             tcg_opcode);
14063
14064     tcg_temp_free_ptr(tcg_rd_ptr);
14065     tcg_temp_free_ptr(tcg_rn_ptr);
14066     tcg_temp_free_ptr(tcg_rm_ptr);
14067     tcg_temp_free_i32(tcg_imm2);
14068     tcg_temp_free_i32(tcg_opcode);
14069 }
14070
14071 /* C3.6 Data processing - SIMD, inc Crypto
14072  *
14073  * As the decode gets a little complex we are using a table based
14074  * approach for this part of the decode.
14075  */
14076 static const AArch64DecodeTable data_proc_simd[] = {
14077     /* pattern  ,  mask     ,  fn                        */
14078     { 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
14079     { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
14080     { 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
14081     { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
14082     { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
14083     { 0x0e000400, 0x9fe08400, disas_simd_copy },
14084     { 0x0f000000, 0x9f000400, disas_simd_indexed }, /* vector indexed */
14085     /* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */
14086     { 0x0f000400, 0x9ff80400, disas_simd_mod_imm },
14087     { 0x0f000400, 0x9f800400, disas_simd_shift_imm },
14088     { 0x0e000000, 0xbf208c00, disas_simd_tb },
14089     { 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
14090     { 0x2e000000, 0xbf208400, disas_simd_ext },
14091     { 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
14092     { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
14093     { 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
14094     { 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
14095     { 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
14096     { 0x5e000400, 0xdfe08400, disas_simd_scalar_copy },
14097     { 0x5f000000, 0xdf000400, disas_simd_indexed }, /* scalar indexed */
14098     { 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm },
14099     { 0x4e280800, 0xff3e0c00, disas_crypto_aes },
14100     { 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
14101     { 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
14102     { 0xce608000, 0xffe0b000, disas_crypto_three_reg_sha512 },
14103     { 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
14104     { 0xce000000, 0xff808000, disas_crypto_four_reg },
14105     { 0xce800000, 0xffe00000, disas_crypto_xar },
14106     { 0xce408000, 0xffe0c000, disas_crypto_three_reg_imm2 },
14107     { 0x0e400400, 0x9f60c400, disas_simd_three_reg_same_fp16 },
14108     { 0x0e780800, 0x8f7e0c00, disas_simd_two_reg_misc_fp16 },
14109     { 0x5e400400, 0xdf60c400, disas_simd_scalar_three_reg_same_fp16 },
14110     { 0x00000000, 0x00000000, NULL }
14111 };
14112
14113 static void disas_data_proc_simd(DisasContext *s, uint32_t insn)
14114 {
14115     /* Note that this is called with all non-FP cases from
14116      * table C3-6 so it must UNDEF for entries not specifically
14117      * allocated to instructions in that table.
14118      */
14119     AArch64DecodeFn *fn = lookup_disas_fn(&data_proc_simd[0], insn);
14120     if (fn) {
14121         fn(s, insn);
14122     } else {
14123         unallocated_encoding(s);
14124     }
14125 }
14126
14127 /* C3.6 Data processing - SIMD and floating point */
14128 static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
14129 {
14130     if (extract32(insn, 28, 1) == 1 && extract32(insn, 30, 1) == 0) {
14131         disas_data_proc_fp(s, insn);
14132     } else {
14133         /* SIMD, including crypto */
14134         disas_data_proc_simd(s, insn);
14135     }
14136 }
14137
14138 /**
14139  * is_guarded_page:
14140  * @env: The cpu environment
14141  * @s: The DisasContext
14142  *
14143  * Return true if the page is guarded.
14144  */
14145 static bool is_guarded_page(CPUARMState *env, DisasContext *s)
14146 {
14147 #ifdef CONFIG_USER_ONLY
14148     return false;  /* FIXME */
14149 #else
14150     uint64_t addr = s->base.pc_first;
14151     int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
14152     unsigned int index = tlb_index(env, mmu_idx, addr);
14153     CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
14154
14155     /*
14156      * We test this immediately after reading an insn, which means
14157      * that any normal page must be in the TLB.  The only exception
14158      * would be for executing from flash or device memory, which
14159      * does not retain the TLB entry.
14160      *
14161      * FIXME: Assume false for those, for now.  We could use
14162      * arm_cpu_get_phys_page_attrs_debug to re-read the page
14163      * table entry even for that case.
14164      */
14165     return (tlb_hit(entry->addr_code, addr) &&
14166             env->iotlb[mmu_idx][index].attrs.target_tlb_bit0);
14167 #endif
14168 }
14169
14170 /**
14171  * btype_destination_ok:
14172  * @insn: The instruction at the branch destination
14173  * @bt: SCTLR_ELx.BT
14174  * @btype: PSTATE.BTYPE, and is non-zero
14175  *
14176  * On a guarded page, there are a limited number of insns
14177  * that may be present at the branch target:
14178  *   - branch target identifiers,
14179  *   - paciasp, pacibsp,
14180  *   - BRK insn
14181  *   - HLT insn
14182  * Anything else causes a Branch Target Exception.
14183  *
14184  * Return true if the branch is compatible, false to raise BTITRAP.
14185  */
14186 static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
14187 {
14188     if ((insn & 0xfffff01fu) == 0xd503201fu) {
14189         /* HINT space */
14190         switch (extract32(insn, 5, 7)) {
14191         case 0b011001: /* PACIASP */
14192         case 0b011011: /* PACIBSP */
14193             /*
14194              * If SCTLR_ELx.BT, then PACI*SP are not compatible
14195              * with btype == 3.  Otherwise all btype are ok.
14196              */
14197             return !bt || btype != 3;
14198         case 0b100000: /* BTI */
14199             /* Not compatible with any btype.  */
14200             return false;
14201         case 0b100010: /* BTI c */
14202             /* Not compatible with btype == 3 */
14203             return btype != 3;
14204         case 0b100100: /* BTI j */
14205             /* Not compatible with btype == 2 */
14206             return btype != 2;
14207         case 0b100110: /* BTI jc */
14208             /* Compatible with any btype.  */
14209             return true;
14210         }
14211     } else {
14212         switch (insn & 0xffe0001fu) {
14213         case 0xd4200000u: /* BRK */
14214         case 0xd4400000u: /* HLT */
14215             /* Give priority to the breakpoint exception.  */
14216             return true;
14217         }
14218     }
14219     return false;
14220 }
14221
14222 /* C3.1 A64 instruction index by encoding */
14223 static void disas_a64_insn(CPUARMState *env, DisasContext *s)
14224 {
14225     uint32_t insn;
14226
14227     insn = arm_ldl_code(env, s->pc, s->sctlr_b);
14228     s->insn = insn;
14229     s->pc += 4;
14230
14231     s->fp_access_checked = false;
14232
14233     if (dc_isar_feature(aa64_bti, s)) {
14234         if (s->base.num_insns == 1) {
14235             /*
14236              * At the first insn of the TB, compute s->guarded_page.
14237              * We delayed computing this until successfully reading
14238              * the first insn of the TB, above.  This (mostly) ensures
14239              * that the softmmu tlb entry has been populated, and the
14240              * page table GP bit is available.
14241              *
14242              * Note that we need to compute this even if btype == 0,
14243              * because this value is used for BR instructions later
14244              * where ENV is not available.
14245              */
14246             s->guarded_page = is_guarded_page(env, s);
14247
14248             /* First insn can have btype set to non-zero.  */
14249             tcg_debug_assert(s->btype >= 0);
14250
14251             /*
14252              * Note that the Branch Target Exception has fairly high
14253              * priority -- below debugging exceptions but above most
14254              * everything else.  This allows us to handle this now
14255              * instead of waiting until the insn is otherwise decoded.
14256              */
14257             if (s->btype != 0
14258                 && s->guarded_page
14259                 && !btype_destination_ok(insn, s->bt, s->btype)) {
14260                 gen_exception_insn(s, 4, EXCP_UDEF, syn_btitrap(s->btype),
14261                                    default_exception_el(s));
14262                 return;
14263             }
14264         } else {
14265             /* Not the first insn: btype must be 0.  */
14266             tcg_debug_assert(s->btype == 0);
14267         }
14268     }
14269
14270     switch (extract32(insn, 25, 4)) {
14271     case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
14272         unallocated_encoding(s);
14273         break;
14274     case 0x2:
14275         if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
14276             unallocated_encoding(s);
14277         }
14278         break;
14279     case 0x8: case 0x9: /* Data processing - immediate */
14280         disas_data_proc_imm(s, insn);
14281         break;
14282     case 0xa: case 0xb: /* Branch, exception generation and system insns */
14283         disas_b_exc_sys(s, insn);
14284         break;
14285     case 0x4:
14286     case 0x6:
14287     case 0xc:
14288     case 0xe:      /* Loads and stores */
14289         disas_ldst(s, insn);
14290         break;
14291     case 0x5:
14292     case 0xd:      /* Data processing - register */
14293         disas_data_proc_reg(s, insn);
14294         break;
14295     case 0x7:
14296     case 0xf:      /* Data processing - SIMD and floating point */
14297         disas_data_proc_simd_fp(s, insn);
14298         break;
14299     default:
14300         assert(FALSE); /* all 15 cases should be handled above */
14301         break;
14302     }
14303
14304     /* if we allocated any temporaries, free them here */
14305     free_tmp_a64(s);
14306
14307     /*
14308      * After execution of most insns, btype is reset to 0.
14309      * Note that we set btype == -1 when the insn sets btype.
14310      */
14311     if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
14312         reset_btype(s);
14313     }
14314 }
14315
14316 static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
14317                                           CPUState *cpu)
14318 {
14319     DisasContext *dc = container_of(dcbase, DisasContext, base);
14320     CPUARMState *env = cpu->env_ptr;
14321     ARMCPU *arm_cpu = arm_env_get_cpu(env);
14322     uint32_t tb_flags = dc->base.tb->flags;
14323     int bound, core_mmu_idx;
14324
14325     dc->isar = &arm_cpu->isar;
14326     dc->pc = dc->base.pc_first;
14327     dc->condjmp = 0;
14328
14329     dc->aarch64 = 1;
14330     /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
14331      * there is no secure EL1, so we route exceptions to EL3.
14332      */
14333     dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
14334                                !arm_el_is_aa64(env, 3);
14335     dc->thumb = 0;
14336     dc->sctlr_b = 0;
14337     dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
14338     dc->condexec_mask = 0;
14339     dc->condexec_cond = 0;
14340     core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
14341     dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
14342     dc->tbii = FIELD_EX32(tb_flags, TBFLAG_A64, TBII);
14343     dc->tbid = FIELD_EX32(tb_flags, TBFLAG_A64, TBID);
14344     dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
14345 #if !defined(CONFIG_USER_ONLY)
14346     dc->user = (dc->current_el == 0);
14347 #endif
14348     dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
14349     dc->sve_excp_el = FIELD_EX32(tb_flags, TBFLAG_A64, SVEEXC_EL);
14350     dc->sve_len = (FIELD_EX32(tb_flags, TBFLAG_A64, ZCR_LEN) + 1) * 16;
14351     dc->pauth_active = FIELD_EX32(tb_flags, TBFLAG_A64, PAUTH_ACTIVE);
14352     dc->bt = FIELD_EX32(tb_flags, TBFLAG_A64, BT);
14353     dc->btype = FIELD_EX32(tb_flags, TBFLAG_A64, BTYPE);
14354     dc->vec_len = 0;
14355     dc->vec_stride = 0;
14356     dc->cp_regs = arm_cpu->cp_regs;
14357     dc->features = env->features;
14358
14359     /* Single step state. The code-generation logic here is:
14360      *  SS_ACTIVE == 0:
14361      *   generate code with no special handling for single-stepping (except
14362      *   that anything that can make us go to SS_ACTIVE == 1 must end the TB;
14363      *   this happens anyway because those changes are all system register or
14364      *   PSTATE writes).
14365      *  SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
14366      *   emit code for one insn
14367      *   emit code to clear PSTATE.SS
14368      *   emit code to generate software step exception for completed step
14369      *   end TB (as usual for having generated an exception)
14370      *  SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
14371      *   emit code to generate a software step exception
14372      *   end the TB
14373      */
14374     dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
14375     dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
14376     dc->is_ldex = false;
14377     dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
14378
14379     /* Bound the number of insns to execute to those left on the page.  */
14380     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
14381
14382     /* If architectural single step active, limit to 1.  */
14383     if (dc->ss_active) {
14384         bound = 1;
14385     }
14386     dc->base.max_insns = MIN(dc->base.max_insns, bound);
14387
14388     init_tmp_a64_array(dc);
14389 }
14390
14391 static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu)
14392 {
14393 }
14394
14395 static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
14396 {
14397     DisasContext *dc = container_of(dcbase, DisasContext, base);
14398
14399     tcg_gen_insn_start(dc->pc, 0, 0);
14400     dc->insn_start = tcg_last_op();
14401 }
14402
14403 static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
14404                                         const CPUBreakpoint *bp)
14405 {
14406     DisasContext *dc = container_of(dcbase, DisasContext, base);
14407
14408     if (bp->flags & BP_CPU) {
14409         gen_a64_set_pc_im(dc->pc);
14410         gen_helper_check_breakpoints(cpu_env);
14411         /* End the TB early; it likely won't be executed */
14412         dc->base.is_jmp = DISAS_TOO_MANY;
14413     } else {
14414         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
14415         /* The address covered by the breakpoint must be
14416            included in [tb->pc, tb->pc + tb->size) in order
14417            to for it to be properly cleared -- thus we
14418            increment the PC here so that the logic setting
14419            tb->size below does the right thing.  */
14420         dc->pc += 4;
14421         dc->base.is_jmp = DISAS_NORETURN;
14422     }
14423
14424     return true;
14425 }
14426
14427 static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
14428 {
14429     DisasContext *dc = container_of(dcbase, DisasContext, base);
14430     CPUARMState *env = cpu->env_ptr;
14431
14432     if (dc->ss_active && !dc->pstate_ss) {
14433         /* Singlestep state is Active-pending.
14434          * If we're in this state at the start of a TB then either
14435          *  a) we just took an exception to an EL which is being debugged
14436          *     and this is the first insn in the exception handler
14437          *  b) debug exceptions were masked and we just unmasked them
14438          *     without changing EL (eg by clearing PSTATE.D)
14439          * In either case we're going to take a swstep exception in the
14440          * "did not step an insn" case, and so the syndrome ISV and EX
14441          * bits should be zero.
14442          */
14443         assert(dc->base.num_insns == 1);
14444         gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
14445                       default_exception_el(dc));
14446         dc->base.is_jmp = DISAS_NORETURN;
14447     } else {
14448         disas_a64_insn(env, dc);
14449     }
14450
14451     dc->base.pc_next = dc->pc;
14452     translator_loop_temp_check(&dc->base);
14453 }
14454
14455 static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
14456 {
14457     DisasContext *dc = container_of(dcbase, DisasContext, base);
14458
14459     if (unlikely(dc->base.singlestep_enabled || dc->ss_active)) {
14460         /* Note that this means single stepping WFI doesn't halt the CPU.
14461          * For conditional branch insns this is harmless unreachable code as
14462          * gen_goto_tb() has already handled emitting the debug exception
14463          * (and thus a tb-jump is not possible when singlestepping).
14464          */
14465         switch (dc->base.is_jmp) {
14466         default:
14467             gen_a64_set_pc_im(dc->pc);
14468             /* fall through */
14469         case DISAS_EXIT:
14470         case DISAS_JUMP:
14471             if (dc->base.singlestep_enabled) {
14472                 gen_exception_internal(EXCP_DEBUG);
14473             } else {
14474                 gen_step_complete_exception(dc);
14475             }
14476             break;
14477         case DISAS_NORETURN:
14478             break;
14479         }
14480     } else {
14481         switch (dc->base.is_jmp) {
14482         case DISAS_NEXT:
14483         case DISAS_TOO_MANY:
14484             gen_goto_tb(dc, 1, dc->pc);
14485             break;
14486         default:
14487         case DISAS_UPDATE:
14488             gen_a64_set_pc_im(dc->pc);
14489             /* fall through */
14490         case DISAS_EXIT:
14491             tcg_gen_exit_tb(NULL, 0);
14492             break;
14493         case DISAS_JUMP:
14494             tcg_gen_lookup_and_goto_ptr();
14495             break;
14496         case DISAS_NORETURN:
14497         case DISAS_SWI:
14498             break;
14499         case DISAS_WFE:
14500             gen_a64_set_pc_im(dc->pc);
14501             gen_helper_wfe(cpu_env);
14502             break;
14503         case DISAS_YIELD:
14504             gen_a64_set_pc_im(dc->pc);
14505             gen_helper_yield(cpu_env);
14506             break;
14507         case DISAS_WFI:
14508         {
14509             /* This is a special case because we don't want to just halt the CPU
14510              * if trying to debug across a WFI.
14511              */
14512             TCGv_i32 tmp = tcg_const_i32(4);
14513
14514             gen_a64_set_pc_im(dc->pc);
14515             gen_helper_wfi(cpu_env, tmp);
14516             tcg_temp_free_i32(tmp);
14517             /* The helper doesn't necessarily throw an exception, but we
14518              * must go back to the main loop to check for interrupts anyway.
14519              */
14520             tcg_gen_exit_tb(NULL, 0);
14521             break;
14522         }
14523         }
14524     }
14525
14526     /* Functions above can change dc->pc, so re-align db->pc_next */
14527     dc->base.pc_next = dc->pc;
14528 }
14529
14530 static void aarch64_tr_disas_log(const DisasContextBase *dcbase,
14531                                       CPUState *cpu)
14532 {
14533     DisasContext *dc = container_of(dcbase, DisasContext, base);
14534
14535     qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
14536     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
14537 }
14538
14539 const TranslatorOps aarch64_translator_ops = {
14540     .init_disas_context = aarch64_tr_init_disas_context,
14541     .tb_start           = aarch64_tr_tb_start,
14542     .insn_start         = aarch64_tr_insn_start,
14543     .breakpoint_check   = aarch64_tr_breakpoint_check,
14544     .translate_insn     = aarch64_tr_translate_insn,
14545     .tb_stop            = aarch64_tr_tb_stop,
14546     .disas_log          = aarch64_tr_disas_log,
14547 };
This page took 0.80728 seconds and 4 git commands to generate.