]> Git Repo - qemu.git/blob - target/arm/translate-a64.c
target/arm: Use env_cpu, env_archcpu
[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 #include "qemu/qemu-print.h"
31
32 #include "hw/semihosting/semihost.h"
33 #include "exec/gen-icount.h"
34
35 #include "exec/helper-proto.h"
36 #include "exec/helper-gen.h"
37 #include "exec/log.h"
38
39 #include "trace-tcg.h"
40 #include "translate-a64.h"
41 #include "qemu/atomic128.h"
42
43 static TCGv_i64 cpu_X[32];
44 static TCGv_i64 cpu_pc;
45
46 /* Load/store exclusive handling */
47 static TCGv_i64 cpu_exclusive_high;
48
49 static const char *regnames[] = {
50     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
51     "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
52     "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
53     "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
54 };
55
56 enum a64_shift_type {
57     A64_SHIFT_TYPE_LSL = 0,
58     A64_SHIFT_TYPE_LSR = 1,
59     A64_SHIFT_TYPE_ASR = 2,
60     A64_SHIFT_TYPE_ROR = 3
61 };
62
63 /* Table based decoder typedefs - used when the relevant bits for decode
64  * are too awkwardly scattered across the instruction (eg SIMD).
65  */
66 typedef void AArch64DecodeFn(DisasContext *s, uint32_t insn);
67
68 typedef struct AArch64DecodeTable {
69     uint32_t pattern;
70     uint32_t mask;
71     AArch64DecodeFn *disas_fn;
72 } AArch64DecodeTable;
73
74 /* Function prototype for gen_ functions for calling Neon helpers */
75 typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
76 typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
77 typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
78 typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
79 typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
80 typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
81 typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
82 typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
83 typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
84 typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
85 typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
86 typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
87 typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
88 typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
89 typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, TCGMemOp);
90
91 /* initialize TCG globals.  */
92 void a64_translate_init(void)
93 {
94     int i;
95
96     cpu_pc = tcg_global_mem_new_i64(cpu_env,
97                                     offsetof(CPUARMState, pc),
98                                     "pc");
99     for (i = 0; i < 32; i++) {
100         cpu_X[i] = tcg_global_mem_new_i64(cpu_env,
101                                           offsetof(CPUARMState, xregs[i]),
102                                           regnames[i]);
103     }
104
105     cpu_exclusive_high = tcg_global_mem_new_i64(cpu_env,
106         offsetof(CPUARMState, exclusive_high), "exclusive_high");
107 }
108
109 static inline int get_a64_user_mem_index(DisasContext *s)
110 {
111     /* Return the core mmu_idx to use for A64 "unprivileged load/store" insns:
112      *  if EL1, access as if EL0; otherwise access at current EL
113      */
114     ARMMMUIdx useridx;
115
116     switch (s->mmu_idx) {
117     case ARMMMUIdx_S12NSE1:
118         useridx = ARMMMUIdx_S12NSE0;
119         break;
120     case ARMMMUIdx_S1SE1:
121         useridx = ARMMMUIdx_S1SE0;
122         break;
123     case ARMMMUIdx_S2NS:
124         g_assert_not_reached();
125     default:
126         useridx = s->mmu_idx;
127         break;
128     }
129     return arm_to_core_mmu_idx(useridx);
130 }
131
132 static void reset_btype(DisasContext *s)
133 {
134     if (s->btype != 0) {
135         TCGv_i32 zero = tcg_const_i32(0);
136         tcg_gen_st_i32(zero, cpu_env, offsetof(CPUARMState, btype));
137         tcg_temp_free_i32(zero);
138         s->btype = 0;
139     }
140 }
141
142 static void set_btype(DisasContext *s, int val)
143 {
144     TCGv_i32 tcg_val;
145
146     /* BTYPE is a 2-bit field, and 0 should be done with reset_btype.  */
147     tcg_debug_assert(val >= 1 && val <= 3);
148
149     tcg_val = tcg_const_i32(val);
150     tcg_gen_st_i32(tcg_val, cpu_env, offsetof(CPUARMState, btype));
151     tcg_temp_free_i32(tcg_val);
152     s->btype = -1;
153 }
154
155 void aarch64_cpu_dump_state(CPUState *cs, FILE *f, 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     qemu_fprintf(f, " PC=%016" PRIx64 " ", env->pc);
165     for (i = 0; i < 32; i++) {
166         if (i == 31) {
167             qemu_fprintf(f, " SP=%016" PRIx64 "\n", env->xregs[i]);
168         } else {
169             qemu_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     qemu_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         qemu_fprintf(f, "  BTYPE=%d", (psr & PSTATE_BTYPE) >> 10);
191     }
192     if (!(flags & CPU_DUMP_FPU)) {
193         qemu_fprintf(f, "\n");
194         return;
195     }
196     if (fp_exception_el(env, el) != 0) {
197         qemu_fprintf(f, "    FPU disabled\n");
198         return;
199     }
200     qemu_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                 qemu_fprintf(f, "FFR=");
210                 /* It's last, so end the line.  */
211                 eol = true;
212             } else {
213                 qemu_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                 qemu_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                 qemu_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                 qemu_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                         qemu_fprintf(f, "Z%02d[%x-%x]=", i, j, j - 1);
259                     } else if (!odd) {
260                         if (j > 0) {
261                             qemu_fprintf(f, "   [%x-%x]=", j, j - 1);
262                         } else {
263                             qemu_fprintf(f, "     [%x]=", j);
264                         }
265                     }
266                     qemu_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             qemu_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, BFXIL fall through to deposit */
4047         tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
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, BFXIL */
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 {
4118             tcg_rm = cpu_reg(s, rm);
4119             tcg_rn = cpu_reg(s, rn);
4120
4121             if (sf) {
4122                 /* Specialization to ROR happens in EXTRACT2.  */
4123                 tcg_gen_extract2_i64(tcg_rd, tcg_rm, tcg_rn, imm);
4124             } else {
4125                 TCGv_i32 t0 = tcg_temp_new_i32();
4126
4127                 tcg_gen_extrl_i64_i32(t0, tcg_rm);
4128                 if (rm == rn) {
4129                     tcg_gen_rotri_i32(t0, t0, imm);
4130                 } else {
4131                     TCGv_i32 t1 = tcg_temp_new_i32();
4132                     tcg_gen_extrl_i64_i32(t1, tcg_rn);
4133                     tcg_gen_extract2_i32(t0, t0, t1, imm);
4134                     tcg_temp_free_i32(t1);
4135                 }
4136                 tcg_gen_extu_i32_i64(tcg_rd, t0);
4137                 tcg_temp_free_i32(t0);
4138             }
4139         }
4140     }
4141 }
4142
4143 /* Data processing - immediate */
4144 static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
4145 {
4146     switch (extract32(insn, 23, 6)) {
4147     case 0x20: case 0x21: /* PC-rel. addressing */
4148         disas_pc_rel_adr(s, insn);
4149         break;
4150     case 0x22: case 0x23: /* Add/subtract (immediate) */
4151         disas_add_sub_imm(s, insn);
4152         break;
4153     case 0x24: /* Logical (immediate) */
4154         disas_logic_imm(s, insn);
4155         break;
4156     case 0x25: /* Move wide (immediate) */
4157         disas_movw_imm(s, insn);
4158         break;
4159     case 0x26: /* Bitfield */
4160         disas_bitfield(s, insn);
4161         break;
4162     case 0x27: /* Extract */
4163         disas_extract(s, insn);
4164         break;
4165     default:
4166         unallocated_encoding(s);
4167         break;
4168     }
4169 }
4170
4171 /* Shift a TCGv src by TCGv shift_amount, put result in dst.
4172  * Note that it is the caller's responsibility to ensure that the
4173  * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
4174  * mandated semantics for out of range shifts.
4175  */
4176 static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
4177                       enum a64_shift_type shift_type, TCGv_i64 shift_amount)
4178 {
4179     switch (shift_type) {
4180     case A64_SHIFT_TYPE_LSL:
4181         tcg_gen_shl_i64(dst, src, shift_amount);
4182         break;
4183     case A64_SHIFT_TYPE_LSR:
4184         tcg_gen_shr_i64(dst, src, shift_amount);
4185         break;
4186     case A64_SHIFT_TYPE_ASR:
4187         if (!sf) {
4188             tcg_gen_ext32s_i64(dst, src);
4189         }
4190         tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
4191         break;
4192     case A64_SHIFT_TYPE_ROR:
4193         if (sf) {
4194             tcg_gen_rotr_i64(dst, src, shift_amount);
4195         } else {
4196             TCGv_i32 t0, t1;
4197             t0 = tcg_temp_new_i32();
4198             t1 = tcg_temp_new_i32();
4199             tcg_gen_extrl_i64_i32(t0, src);
4200             tcg_gen_extrl_i64_i32(t1, shift_amount);
4201             tcg_gen_rotr_i32(t0, t0, t1);
4202             tcg_gen_extu_i32_i64(dst, t0);
4203             tcg_temp_free_i32(t0);
4204             tcg_temp_free_i32(t1);
4205         }
4206         break;
4207     default:
4208         assert(FALSE); /* all shift types should be handled */
4209         break;
4210     }
4211
4212     if (!sf) { /* zero extend final result */
4213         tcg_gen_ext32u_i64(dst, dst);
4214     }
4215 }
4216
4217 /* Shift a TCGv src by immediate, put result in dst.
4218  * The shift amount must be in range (this should always be true as the
4219  * relevant instructions will UNDEF on bad shift immediates).
4220  */
4221 static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
4222                           enum a64_shift_type shift_type, unsigned int shift_i)
4223 {
4224     assert(shift_i < (sf ? 64 : 32));
4225
4226     if (shift_i == 0) {
4227         tcg_gen_mov_i64(dst, src);
4228     } else {
4229         TCGv_i64 shift_const;
4230
4231         shift_const = tcg_const_i64(shift_i);
4232         shift_reg(dst, src, sf, shift_type, shift_const);
4233         tcg_temp_free_i64(shift_const);
4234     }
4235 }
4236
4237 /* Logical (shifted register)
4238  *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
4239  * +----+-----+-----------+-------+---+------+--------+------+------+
4240  * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
4241  * +----+-----+-----------+-------+---+------+--------+------+------+
4242  */
4243 static void disas_logic_reg(DisasContext *s, uint32_t insn)
4244 {
4245     TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
4246     unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
4247
4248     sf = extract32(insn, 31, 1);
4249     opc = extract32(insn, 29, 2);
4250     shift_type = extract32(insn, 22, 2);
4251     invert = extract32(insn, 21, 1);
4252     rm = extract32(insn, 16, 5);
4253     shift_amount = extract32(insn, 10, 6);
4254     rn = extract32(insn, 5, 5);
4255     rd = extract32(insn, 0, 5);
4256
4257     if (!sf && (shift_amount & (1 << 5))) {
4258         unallocated_encoding(s);
4259         return;
4260     }
4261
4262     tcg_rd = cpu_reg(s, rd);
4263
4264     if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
4265         /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
4266          * register-register MOV and MVN, so it is worth special casing.
4267          */
4268         tcg_rm = cpu_reg(s, rm);
4269         if (invert) {
4270             tcg_gen_not_i64(tcg_rd, tcg_rm);
4271             if (!sf) {
4272                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4273             }
4274         } else {
4275             if (sf) {
4276                 tcg_gen_mov_i64(tcg_rd, tcg_rm);
4277             } else {
4278                 tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
4279             }
4280         }
4281         return;
4282     }
4283
4284     tcg_rm = read_cpu_reg(s, rm, sf);
4285
4286     if (shift_amount) {
4287         shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
4288     }
4289
4290     tcg_rn = cpu_reg(s, rn);
4291
4292     switch (opc | (invert << 2)) {
4293     case 0: /* AND */
4294     case 3: /* ANDS */
4295         tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
4296         break;
4297     case 1: /* ORR */
4298         tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
4299         break;
4300     case 2: /* EOR */
4301         tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
4302         break;
4303     case 4: /* BIC */
4304     case 7: /* BICS */
4305         tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
4306         break;
4307     case 5: /* ORN */
4308         tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
4309         break;
4310     case 6: /* EON */
4311         tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
4312         break;
4313     default:
4314         assert(FALSE);
4315         break;
4316     }
4317
4318     if (!sf) {
4319         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4320     }
4321
4322     if (opc == 3) {
4323         gen_logic_CC(sf, tcg_rd);
4324     }
4325 }
4326
4327 /*
4328  * Add/subtract (extended register)
4329  *
4330  *  31|30|29|28       24|23 22|21|20   16|15  13|12  10|9  5|4  0|
4331  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
4332  * |sf|op| S| 0 1 0 1 1 | opt | 1|  Rm   |option| imm3 | Rn | Rd |
4333  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
4334  *
4335  *  sf: 0 -> 32bit, 1 -> 64bit
4336  *  op: 0 -> add  , 1 -> sub
4337  *   S: 1 -> set flags
4338  * opt: 00
4339  * option: extension type (see DecodeRegExtend)
4340  * imm3: optional shift to Rm
4341  *
4342  * Rd = Rn + LSL(extend(Rm), amount)
4343  */
4344 static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
4345 {
4346     int rd = extract32(insn, 0, 5);
4347     int rn = extract32(insn, 5, 5);
4348     int imm3 = extract32(insn, 10, 3);
4349     int option = extract32(insn, 13, 3);
4350     int rm = extract32(insn, 16, 5);
4351     int opt = extract32(insn, 22, 2);
4352     bool setflags = extract32(insn, 29, 1);
4353     bool sub_op = extract32(insn, 30, 1);
4354     bool sf = extract32(insn, 31, 1);
4355
4356     TCGv_i64 tcg_rm, tcg_rn; /* temps */
4357     TCGv_i64 tcg_rd;
4358     TCGv_i64 tcg_result;
4359
4360     if (imm3 > 4 || opt != 0) {
4361         unallocated_encoding(s);
4362         return;
4363     }
4364
4365     /* non-flag setting ops may use SP */
4366     if (!setflags) {
4367         tcg_rd = cpu_reg_sp(s, rd);
4368     } else {
4369         tcg_rd = cpu_reg(s, rd);
4370     }
4371     tcg_rn = read_cpu_reg_sp(s, rn, sf);
4372
4373     tcg_rm = read_cpu_reg(s, rm, sf);
4374     ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
4375
4376     tcg_result = tcg_temp_new_i64();
4377
4378     if (!setflags) {
4379         if (sub_op) {
4380             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
4381         } else {
4382             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
4383         }
4384     } else {
4385         if (sub_op) {
4386             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
4387         } else {
4388             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
4389         }
4390     }
4391
4392     if (sf) {
4393         tcg_gen_mov_i64(tcg_rd, tcg_result);
4394     } else {
4395         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
4396     }
4397
4398     tcg_temp_free_i64(tcg_result);
4399 }
4400
4401 /*
4402  * Add/subtract (shifted register)
4403  *
4404  *  31 30 29 28       24 23 22 21 20   16 15     10 9    5 4    0
4405  * +--+--+--+-----------+-----+--+-------+---------+------+------+
4406  * |sf|op| S| 0 1 0 1 1 |shift| 0|  Rm   |  imm6   |  Rn  |  Rd  |
4407  * +--+--+--+-----------+-----+--+-------+---------+------+------+
4408  *
4409  *    sf: 0 -> 32bit, 1 -> 64bit
4410  *    op: 0 -> add  , 1 -> sub
4411  *     S: 1 -> set flags
4412  * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
4413  *  imm6: Shift amount to apply to Rm before the add/sub
4414  */
4415 static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
4416 {
4417     int rd = extract32(insn, 0, 5);
4418     int rn = extract32(insn, 5, 5);
4419     int imm6 = extract32(insn, 10, 6);
4420     int rm = extract32(insn, 16, 5);
4421     int shift_type = extract32(insn, 22, 2);
4422     bool setflags = extract32(insn, 29, 1);
4423     bool sub_op = extract32(insn, 30, 1);
4424     bool sf = extract32(insn, 31, 1);
4425
4426     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4427     TCGv_i64 tcg_rn, tcg_rm;
4428     TCGv_i64 tcg_result;
4429
4430     if ((shift_type == 3) || (!sf && (imm6 > 31))) {
4431         unallocated_encoding(s);
4432         return;
4433     }
4434
4435     tcg_rn = read_cpu_reg(s, rn, sf);
4436     tcg_rm = read_cpu_reg(s, rm, sf);
4437
4438     shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
4439
4440     tcg_result = tcg_temp_new_i64();
4441
4442     if (!setflags) {
4443         if (sub_op) {
4444             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
4445         } else {
4446             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
4447         }
4448     } else {
4449         if (sub_op) {
4450             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
4451         } else {
4452             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
4453         }
4454     }
4455
4456     if (sf) {
4457         tcg_gen_mov_i64(tcg_rd, tcg_result);
4458     } else {
4459         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
4460     }
4461
4462     tcg_temp_free_i64(tcg_result);
4463 }
4464
4465 /* Data-processing (3 source)
4466  *
4467  *    31 30  29 28       24 23 21  20  16  15  14  10 9    5 4    0
4468  *  +--+------+-----------+------+------+----+------+------+------+
4469  *  |sf| op54 | 1 1 0 1 1 | op31 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
4470  *  +--+------+-----------+------+------+----+------+------+------+
4471  */
4472 static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
4473 {
4474     int rd = extract32(insn, 0, 5);
4475     int rn = extract32(insn, 5, 5);
4476     int ra = extract32(insn, 10, 5);
4477     int rm = extract32(insn, 16, 5);
4478     int op_id = (extract32(insn, 29, 3) << 4) |
4479         (extract32(insn, 21, 3) << 1) |
4480         extract32(insn, 15, 1);
4481     bool sf = extract32(insn, 31, 1);
4482     bool is_sub = extract32(op_id, 0, 1);
4483     bool is_high = extract32(op_id, 2, 1);
4484     bool is_signed = false;
4485     TCGv_i64 tcg_op1;
4486     TCGv_i64 tcg_op2;
4487     TCGv_i64 tcg_tmp;
4488
4489     /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
4490     switch (op_id) {
4491     case 0x42: /* SMADDL */
4492     case 0x43: /* SMSUBL */
4493     case 0x44: /* SMULH */
4494         is_signed = true;
4495         break;
4496     case 0x0: /* MADD (32bit) */
4497     case 0x1: /* MSUB (32bit) */
4498     case 0x40: /* MADD (64bit) */
4499     case 0x41: /* MSUB (64bit) */
4500     case 0x4a: /* UMADDL */
4501     case 0x4b: /* UMSUBL */
4502     case 0x4c: /* UMULH */
4503         break;
4504     default:
4505         unallocated_encoding(s);
4506         return;
4507     }
4508
4509     if (is_high) {
4510         TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
4511         TCGv_i64 tcg_rd = cpu_reg(s, rd);
4512         TCGv_i64 tcg_rn = cpu_reg(s, rn);
4513         TCGv_i64 tcg_rm = cpu_reg(s, rm);
4514
4515         if (is_signed) {
4516             tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
4517         } else {
4518             tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
4519         }
4520
4521         tcg_temp_free_i64(low_bits);
4522         return;
4523     }
4524
4525     tcg_op1 = tcg_temp_new_i64();
4526     tcg_op2 = tcg_temp_new_i64();
4527     tcg_tmp = tcg_temp_new_i64();
4528
4529     if (op_id < 0x42) {
4530         tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
4531         tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
4532     } else {
4533         if (is_signed) {
4534             tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
4535             tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
4536         } else {
4537             tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
4538             tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
4539         }
4540     }
4541
4542     if (ra == 31 && !is_sub) {
4543         /* Special-case MADD with rA == XZR; it is the standard MUL alias */
4544         tcg_gen_mul_i64(cpu_reg(s, rd), tcg_op1, tcg_op2);
4545     } else {
4546         tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
4547         if (is_sub) {
4548             tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
4549         } else {
4550             tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
4551         }
4552     }
4553
4554     if (!sf) {
4555         tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
4556     }
4557
4558     tcg_temp_free_i64(tcg_op1);
4559     tcg_temp_free_i64(tcg_op2);
4560     tcg_temp_free_i64(tcg_tmp);
4561 }
4562
4563 /* Add/subtract (with carry)
4564  *  31 30 29 28 27 26 25 24 23 22 21  20  16  15       10  9    5 4   0
4565  * +--+--+--+------------------------+------+-------------+------+-----+
4566  * |sf|op| S| 1  1  0  1  0  0  0  0 |  rm  | 0 0 0 0 0 0 |  Rn  |  Rd |
4567  * +--+--+--+------------------------+------+-------------+------+-----+
4568  */
4569
4570 static void disas_adc_sbc(DisasContext *s, uint32_t insn)
4571 {
4572     unsigned int sf, op, setflags, rm, rn, rd;
4573     TCGv_i64 tcg_y, tcg_rn, tcg_rd;
4574
4575     sf = extract32(insn, 31, 1);
4576     op = extract32(insn, 30, 1);
4577     setflags = extract32(insn, 29, 1);
4578     rm = extract32(insn, 16, 5);
4579     rn = extract32(insn, 5, 5);
4580     rd = extract32(insn, 0, 5);
4581
4582     tcg_rd = cpu_reg(s, rd);
4583     tcg_rn = cpu_reg(s, rn);
4584
4585     if (op) {
4586         tcg_y = new_tmp_a64(s);
4587         tcg_gen_not_i64(tcg_y, cpu_reg(s, rm));
4588     } else {
4589         tcg_y = cpu_reg(s, rm);
4590     }
4591
4592     if (setflags) {
4593         gen_adc_CC(sf, tcg_rd, tcg_rn, tcg_y);
4594     } else {
4595         gen_adc(sf, tcg_rd, tcg_rn, tcg_y);
4596     }
4597 }
4598
4599 /*
4600  * Rotate right into flags
4601  *  31 30 29                21       15          10      5  4      0
4602  * +--+--+--+-----------------+--------+-----------+------+--+------+
4603  * |sf|op| S| 1 1 0 1 0 0 0 0 |  imm6  | 0 0 0 0 1 |  Rn  |o2| mask |
4604  * +--+--+--+-----------------+--------+-----------+------+--+------+
4605  */
4606 static void disas_rotate_right_into_flags(DisasContext *s, uint32_t insn)
4607 {
4608     int mask = extract32(insn, 0, 4);
4609     int o2 = extract32(insn, 4, 1);
4610     int rn = extract32(insn, 5, 5);
4611     int imm6 = extract32(insn, 15, 6);
4612     int sf_op_s = extract32(insn, 29, 3);
4613     TCGv_i64 tcg_rn;
4614     TCGv_i32 nzcv;
4615
4616     if (sf_op_s != 5 || o2 != 0 || !dc_isar_feature(aa64_condm_4, s)) {
4617         unallocated_encoding(s);
4618         return;
4619     }
4620
4621     tcg_rn = read_cpu_reg(s, rn, 1);
4622     tcg_gen_rotri_i64(tcg_rn, tcg_rn, imm6);
4623
4624     nzcv = tcg_temp_new_i32();
4625     tcg_gen_extrl_i64_i32(nzcv, tcg_rn);
4626
4627     if (mask & 8) { /* N */
4628         tcg_gen_shli_i32(cpu_NF, nzcv, 31 - 3);
4629     }
4630     if (mask & 4) { /* Z */
4631         tcg_gen_not_i32(cpu_ZF, nzcv);
4632         tcg_gen_andi_i32(cpu_ZF, cpu_ZF, 4);
4633     }
4634     if (mask & 2) { /* C */
4635         tcg_gen_extract_i32(cpu_CF, nzcv, 1, 1);
4636     }
4637     if (mask & 1) { /* V */
4638         tcg_gen_shli_i32(cpu_VF, nzcv, 31 - 0);
4639     }
4640
4641     tcg_temp_free_i32(nzcv);
4642 }
4643
4644 /*
4645  * Evaluate into flags
4646  *  31 30 29                21        15   14        10      5  4      0
4647  * +--+--+--+-----------------+---------+----+---------+------+--+------+
4648  * |sf|op| S| 1 1 0 1 0 0 0 0 | opcode2 | sz | 0 0 1 0 |  Rn  |o3| mask |
4649  * +--+--+--+-----------------+---------+----+---------+------+--+------+
4650  */
4651 static void disas_evaluate_into_flags(DisasContext *s, uint32_t insn)
4652 {
4653     int o3_mask = extract32(insn, 0, 5);
4654     int rn = extract32(insn, 5, 5);
4655     int o2 = extract32(insn, 15, 6);
4656     int sz = extract32(insn, 14, 1);
4657     int sf_op_s = extract32(insn, 29, 3);
4658     TCGv_i32 tmp;
4659     int shift;
4660
4661     if (sf_op_s != 1 || o2 != 0 || o3_mask != 0xd ||
4662         !dc_isar_feature(aa64_condm_4, s)) {
4663         unallocated_encoding(s);
4664         return;
4665     }
4666     shift = sz ? 16 : 24;  /* SETF16 or SETF8 */
4667
4668     tmp = tcg_temp_new_i32();
4669     tcg_gen_extrl_i64_i32(tmp, cpu_reg(s, rn));
4670     tcg_gen_shli_i32(cpu_NF, tmp, shift);
4671     tcg_gen_shli_i32(cpu_VF, tmp, shift - 1);
4672     tcg_gen_mov_i32(cpu_ZF, cpu_NF);
4673     tcg_gen_xor_i32(cpu_VF, cpu_VF, cpu_NF);
4674     tcg_temp_free_i32(tmp);
4675 }
4676
4677 /* Conditional compare (immediate / register)
4678  *  31 30 29 28 27 26 25 24 23 22 21  20    16 15  12  11  10  9   5  4 3   0
4679  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
4680  * |sf|op| S| 1  1  0  1  0  0  1  0 |imm5/rm | cond |i/r |o2|  Rn  |o3|nzcv |
4681  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
4682  *        [1]                             y                [0]       [0]
4683  */
4684 static void disas_cc(DisasContext *s, uint32_t insn)
4685 {
4686     unsigned int sf, op, y, cond, rn, nzcv, is_imm;
4687     TCGv_i32 tcg_t0, tcg_t1, tcg_t2;
4688     TCGv_i64 tcg_tmp, tcg_y, tcg_rn;
4689     DisasCompare c;
4690
4691     if (!extract32(insn, 29, 1)) {
4692         unallocated_encoding(s);
4693         return;
4694     }
4695     if (insn & (1 << 10 | 1 << 4)) {
4696         unallocated_encoding(s);
4697         return;
4698     }
4699     sf = extract32(insn, 31, 1);
4700     op = extract32(insn, 30, 1);
4701     is_imm = extract32(insn, 11, 1);
4702     y = extract32(insn, 16, 5); /* y = rm (reg) or imm5 (imm) */
4703     cond = extract32(insn, 12, 4);
4704     rn = extract32(insn, 5, 5);
4705     nzcv = extract32(insn, 0, 4);
4706
4707     /* Set T0 = !COND.  */
4708     tcg_t0 = tcg_temp_new_i32();
4709     arm_test_cc(&c, cond);
4710     tcg_gen_setcondi_i32(tcg_invert_cond(c.cond), tcg_t0, c.value, 0);
4711     arm_free_cc(&c);
4712
4713     /* Load the arguments for the new comparison.  */
4714     if (is_imm) {
4715         tcg_y = new_tmp_a64(s);
4716         tcg_gen_movi_i64(tcg_y, y);
4717     } else {
4718         tcg_y = cpu_reg(s, y);
4719     }
4720     tcg_rn = cpu_reg(s, rn);
4721
4722     /* Set the flags for the new comparison.  */
4723     tcg_tmp = tcg_temp_new_i64();
4724     if (op) {
4725         gen_sub_CC(sf, tcg_tmp, tcg_rn, tcg_y);
4726     } else {
4727         gen_add_CC(sf, tcg_tmp, tcg_rn, tcg_y);
4728     }
4729     tcg_temp_free_i64(tcg_tmp);
4730
4731     /* If COND was false, force the flags to #nzcv.  Compute two masks
4732      * to help with this: T1 = (COND ? 0 : -1), T2 = (COND ? -1 : 0).
4733      * For tcg hosts that support ANDC, we can make do with just T1.
4734      * In either case, allow the tcg optimizer to delete any unused mask.
4735      */
4736     tcg_t1 = tcg_temp_new_i32();
4737     tcg_t2 = tcg_temp_new_i32();
4738     tcg_gen_neg_i32(tcg_t1, tcg_t0);
4739     tcg_gen_subi_i32(tcg_t2, tcg_t0, 1);
4740
4741     if (nzcv & 8) { /* N */
4742         tcg_gen_or_i32(cpu_NF, cpu_NF, tcg_t1);
4743     } else {
4744         if (TCG_TARGET_HAS_andc_i32) {
4745             tcg_gen_andc_i32(cpu_NF, cpu_NF, tcg_t1);
4746         } else {
4747             tcg_gen_and_i32(cpu_NF, cpu_NF, tcg_t2);
4748         }
4749     }
4750     if (nzcv & 4) { /* Z */
4751         if (TCG_TARGET_HAS_andc_i32) {
4752             tcg_gen_andc_i32(cpu_ZF, cpu_ZF, tcg_t1);
4753         } else {
4754             tcg_gen_and_i32(cpu_ZF, cpu_ZF, tcg_t2);
4755         }
4756     } else {
4757         tcg_gen_or_i32(cpu_ZF, cpu_ZF, tcg_t0);
4758     }
4759     if (nzcv & 2) { /* C */
4760         tcg_gen_or_i32(cpu_CF, cpu_CF, tcg_t0);
4761     } else {
4762         if (TCG_TARGET_HAS_andc_i32) {
4763             tcg_gen_andc_i32(cpu_CF, cpu_CF, tcg_t1);
4764         } else {
4765             tcg_gen_and_i32(cpu_CF, cpu_CF, tcg_t2);
4766         }
4767     }
4768     if (nzcv & 1) { /* V */
4769         tcg_gen_or_i32(cpu_VF, cpu_VF, tcg_t1);
4770     } else {
4771         if (TCG_TARGET_HAS_andc_i32) {
4772             tcg_gen_andc_i32(cpu_VF, cpu_VF, tcg_t1);
4773         } else {
4774             tcg_gen_and_i32(cpu_VF, cpu_VF, tcg_t2);
4775         }
4776     }
4777     tcg_temp_free_i32(tcg_t0);
4778     tcg_temp_free_i32(tcg_t1);
4779     tcg_temp_free_i32(tcg_t2);
4780 }
4781
4782 /* Conditional select
4783  *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
4784  * +----+----+---+-----------------+------+------+-----+------+------+
4785  * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
4786  * +----+----+---+-----------------+------+------+-----+------+------+
4787  */
4788 static void disas_cond_select(DisasContext *s, uint32_t insn)
4789 {
4790     unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
4791     TCGv_i64 tcg_rd, zero;
4792     DisasCompare64 c;
4793
4794     if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
4795         /* S == 1 or op2<1> == 1 */
4796         unallocated_encoding(s);
4797         return;
4798     }
4799     sf = extract32(insn, 31, 1);
4800     else_inv = extract32(insn, 30, 1);
4801     rm = extract32(insn, 16, 5);
4802     cond = extract32(insn, 12, 4);
4803     else_inc = extract32(insn, 10, 1);
4804     rn = extract32(insn, 5, 5);
4805     rd = extract32(insn, 0, 5);
4806
4807     tcg_rd = cpu_reg(s, rd);
4808
4809     a64_test_cc(&c, cond);
4810     zero = tcg_const_i64(0);
4811
4812     if (rn == 31 && rm == 31 && (else_inc ^ else_inv)) {
4813         /* CSET & CSETM.  */
4814         tcg_gen_setcond_i64(tcg_invert_cond(c.cond), tcg_rd, c.value, zero);
4815         if (else_inv) {
4816             tcg_gen_neg_i64(tcg_rd, tcg_rd);
4817         }
4818     } else {
4819         TCGv_i64 t_true = cpu_reg(s, rn);
4820         TCGv_i64 t_false = read_cpu_reg(s, rm, 1);
4821         if (else_inv && else_inc) {
4822             tcg_gen_neg_i64(t_false, t_false);
4823         } else if (else_inv) {
4824             tcg_gen_not_i64(t_false, t_false);
4825         } else if (else_inc) {
4826             tcg_gen_addi_i64(t_false, t_false, 1);
4827         }
4828         tcg_gen_movcond_i64(c.cond, tcg_rd, c.value, zero, t_true, t_false);
4829     }
4830
4831     tcg_temp_free_i64(zero);
4832     a64_free_cc(&c);
4833
4834     if (!sf) {
4835         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4836     }
4837 }
4838
4839 static void handle_clz(DisasContext *s, unsigned int sf,
4840                        unsigned int rn, unsigned int rd)
4841 {
4842     TCGv_i64 tcg_rd, tcg_rn;
4843     tcg_rd = cpu_reg(s, rd);
4844     tcg_rn = cpu_reg(s, rn);
4845
4846     if (sf) {
4847         tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
4848     } else {
4849         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4850         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4851         tcg_gen_clzi_i32(tcg_tmp32, tcg_tmp32, 32);
4852         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4853         tcg_temp_free_i32(tcg_tmp32);
4854     }
4855 }
4856
4857 static void handle_cls(DisasContext *s, unsigned int sf,
4858                        unsigned int rn, unsigned int rd)
4859 {
4860     TCGv_i64 tcg_rd, tcg_rn;
4861     tcg_rd = cpu_reg(s, rd);
4862     tcg_rn = cpu_reg(s, rn);
4863
4864     if (sf) {
4865         tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
4866     } else {
4867         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4868         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4869         tcg_gen_clrsb_i32(tcg_tmp32, tcg_tmp32);
4870         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4871         tcg_temp_free_i32(tcg_tmp32);
4872     }
4873 }
4874
4875 static void handle_rbit(DisasContext *s, unsigned int sf,
4876                         unsigned int rn, unsigned int rd)
4877 {
4878     TCGv_i64 tcg_rd, tcg_rn;
4879     tcg_rd = cpu_reg(s, rd);
4880     tcg_rn = cpu_reg(s, rn);
4881
4882     if (sf) {
4883         gen_helper_rbit64(tcg_rd, tcg_rn);
4884     } else {
4885         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4886         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4887         gen_helper_rbit(tcg_tmp32, tcg_tmp32);
4888         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4889         tcg_temp_free_i32(tcg_tmp32);
4890     }
4891 }
4892
4893 /* REV with sf==1, opcode==3 ("REV64") */
4894 static void handle_rev64(DisasContext *s, unsigned int sf,
4895                          unsigned int rn, unsigned int rd)
4896 {
4897     if (!sf) {
4898         unallocated_encoding(s);
4899         return;
4900     }
4901     tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
4902 }
4903
4904 /* REV with sf==0, opcode==2
4905  * REV32 (sf==1, opcode==2)
4906  */
4907 static void handle_rev32(DisasContext *s, unsigned int sf,
4908                          unsigned int rn, unsigned int rd)
4909 {
4910     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4911
4912     if (sf) {
4913         TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4914         TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
4915
4916         /* bswap32_i64 requires zero high word */
4917         tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
4918         tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
4919         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
4920         tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
4921         tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
4922
4923         tcg_temp_free_i64(tcg_tmp);
4924     } else {
4925         tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
4926         tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
4927     }
4928 }
4929
4930 /* REV16 (opcode==1) */
4931 static void handle_rev16(DisasContext *s, unsigned int sf,
4932                          unsigned int rn, unsigned int rd)
4933 {
4934     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4935     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4936     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
4937     TCGv_i64 mask = tcg_const_i64(sf ? 0x00ff00ff00ff00ffull : 0x00ff00ff);
4938
4939     tcg_gen_shri_i64(tcg_tmp, tcg_rn, 8);
4940     tcg_gen_and_i64(tcg_rd, tcg_rn, mask);
4941     tcg_gen_and_i64(tcg_tmp, tcg_tmp, mask);
4942     tcg_gen_shli_i64(tcg_rd, tcg_rd, 8);
4943     tcg_gen_or_i64(tcg_rd, tcg_rd, tcg_tmp);
4944
4945     tcg_temp_free_i64(mask);
4946     tcg_temp_free_i64(tcg_tmp);
4947 }
4948
4949 /* Data-processing (1 source)
4950  *   31  30  29  28             21 20     16 15    10 9    5 4    0
4951  * +----+---+---+-----------------+---------+--------+------+------+
4952  * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
4953  * +----+---+---+-----------------+---------+--------+------+------+
4954  */
4955 static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
4956 {
4957     unsigned int sf, opcode, opcode2, rn, rd;
4958     TCGv_i64 tcg_rd;
4959
4960     if (extract32(insn, 29, 1)) {
4961         unallocated_encoding(s);
4962         return;
4963     }
4964
4965     sf = extract32(insn, 31, 1);
4966     opcode = extract32(insn, 10, 6);
4967     opcode2 = extract32(insn, 16, 5);
4968     rn = extract32(insn, 5, 5);
4969     rd = extract32(insn, 0, 5);
4970
4971 #define MAP(SF, O2, O1) ((SF) | (O1 << 1) | (O2 << 7))
4972
4973     switch (MAP(sf, opcode2, opcode)) {
4974     case MAP(0, 0x00, 0x00): /* RBIT */
4975     case MAP(1, 0x00, 0x00):
4976         handle_rbit(s, sf, rn, rd);
4977         break;
4978     case MAP(0, 0x00, 0x01): /* REV16 */
4979     case MAP(1, 0x00, 0x01):
4980         handle_rev16(s, sf, rn, rd);
4981         break;
4982     case MAP(0, 0x00, 0x02): /* REV/REV32 */
4983     case MAP(1, 0x00, 0x02):
4984         handle_rev32(s, sf, rn, rd);
4985         break;
4986     case MAP(1, 0x00, 0x03): /* REV64 */
4987         handle_rev64(s, sf, rn, rd);
4988         break;
4989     case MAP(0, 0x00, 0x04): /* CLZ */
4990     case MAP(1, 0x00, 0x04):
4991         handle_clz(s, sf, rn, rd);
4992         break;
4993     case MAP(0, 0x00, 0x05): /* CLS */
4994     case MAP(1, 0x00, 0x05):
4995         handle_cls(s, sf, rn, rd);
4996         break;
4997     case MAP(1, 0x01, 0x00): /* PACIA */
4998         if (s->pauth_active) {
4999             tcg_rd = cpu_reg(s, rd);
5000             gen_helper_pacia(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5001         } else if (!dc_isar_feature(aa64_pauth, s)) {
5002             goto do_unallocated;
5003         }
5004         break;
5005     case MAP(1, 0x01, 0x01): /* PACIB */
5006         if (s->pauth_active) {
5007             tcg_rd = cpu_reg(s, rd);
5008             gen_helper_pacib(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5009         } else if (!dc_isar_feature(aa64_pauth, s)) {
5010             goto do_unallocated;
5011         }
5012         break;
5013     case MAP(1, 0x01, 0x02): /* PACDA */
5014         if (s->pauth_active) {
5015             tcg_rd = cpu_reg(s, rd);
5016             gen_helper_pacda(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5017         } else if (!dc_isar_feature(aa64_pauth, s)) {
5018             goto do_unallocated;
5019         }
5020         break;
5021     case MAP(1, 0x01, 0x03): /* PACDB */
5022         if (s->pauth_active) {
5023             tcg_rd = cpu_reg(s, rd);
5024             gen_helper_pacdb(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5025         } else if (!dc_isar_feature(aa64_pauth, s)) {
5026             goto do_unallocated;
5027         }
5028         break;
5029     case MAP(1, 0x01, 0x04): /* AUTIA */
5030         if (s->pauth_active) {
5031             tcg_rd = cpu_reg(s, rd);
5032             gen_helper_autia(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5033         } else if (!dc_isar_feature(aa64_pauth, s)) {
5034             goto do_unallocated;
5035         }
5036         break;
5037     case MAP(1, 0x01, 0x05): /* AUTIB */
5038         if (s->pauth_active) {
5039             tcg_rd = cpu_reg(s, rd);
5040             gen_helper_autib(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5041         } else if (!dc_isar_feature(aa64_pauth, s)) {
5042             goto do_unallocated;
5043         }
5044         break;
5045     case MAP(1, 0x01, 0x06): /* AUTDA */
5046         if (s->pauth_active) {
5047             tcg_rd = cpu_reg(s, rd);
5048             gen_helper_autda(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5049         } else if (!dc_isar_feature(aa64_pauth, s)) {
5050             goto do_unallocated;
5051         }
5052         break;
5053     case MAP(1, 0x01, 0x07): /* AUTDB */
5054         if (s->pauth_active) {
5055             tcg_rd = cpu_reg(s, rd);
5056             gen_helper_autdb(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5057         } else if (!dc_isar_feature(aa64_pauth, s)) {
5058             goto do_unallocated;
5059         }
5060         break;
5061     case MAP(1, 0x01, 0x08): /* PACIZA */
5062         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5063             goto do_unallocated;
5064         } else if (s->pauth_active) {
5065             tcg_rd = cpu_reg(s, rd);
5066             gen_helper_pacia(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5067         }
5068         break;
5069     case MAP(1, 0x01, 0x09): /* PACIZB */
5070         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5071             goto do_unallocated;
5072         } else if (s->pauth_active) {
5073             tcg_rd = cpu_reg(s, rd);
5074             gen_helper_pacib(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5075         }
5076         break;
5077     case MAP(1, 0x01, 0x0a): /* PACDZA */
5078         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5079             goto do_unallocated;
5080         } else if (s->pauth_active) {
5081             tcg_rd = cpu_reg(s, rd);
5082             gen_helper_pacda(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5083         }
5084         break;
5085     case MAP(1, 0x01, 0x0b): /* PACDZB */
5086         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5087             goto do_unallocated;
5088         } else if (s->pauth_active) {
5089             tcg_rd = cpu_reg(s, rd);
5090             gen_helper_pacdb(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5091         }
5092         break;
5093     case MAP(1, 0x01, 0x0c): /* AUTIZA */
5094         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5095             goto do_unallocated;
5096         } else if (s->pauth_active) {
5097             tcg_rd = cpu_reg(s, rd);
5098             gen_helper_autia(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5099         }
5100         break;
5101     case MAP(1, 0x01, 0x0d): /* AUTIZB */
5102         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5103             goto do_unallocated;
5104         } else if (s->pauth_active) {
5105             tcg_rd = cpu_reg(s, rd);
5106             gen_helper_autib(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5107         }
5108         break;
5109     case MAP(1, 0x01, 0x0e): /* AUTDZA */
5110         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5111             goto do_unallocated;
5112         } else if (s->pauth_active) {
5113             tcg_rd = cpu_reg(s, rd);
5114             gen_helper_autda(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5115         }
5116         break;
5117     case MAP(1, 0x01, 0x0f): /* AUTDZB */
5118         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5119             goto do_unallocated;
5120         } else if (s->pauth_active) {
5121             tcg_rd = cpu_reg(s, rd);
5122             gen_helper_autdb(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5123         }
5124         break;
5125     case MAP(1, 0x01, 0x10): /* XPACI */
5126         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5127             goto do_unallocated;
5128         } else if (s->pauth_active) {
5129             tcg_rd = cpu_reg(s, rd);
5130             gen_helper_xpaci(tcg_rd, cpu_env, tcg_rd);
5131         }
5132         break;
5133     case MAP(1, 0x01, 0x11): /* XPACD */
5134         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5135             goto do_unallocated;
5136         } else if (s->pauth_active) {
5137             tcg_rd = cpu_reg(s, rd);
5138             gen_helper_xpacd(tcg_rd, cpu_env, tcg_rd);
5139         }
5140         break;
5141     default:
5142     do_unallocated:
5143         unallocated_encoding(s);
5144         break;
5145     }
5146
5147 #undef MAP
5148 }
5149
5150 static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
5151                        unsigned int rm, unsigned int rn, unsigned int rd)
5152 {
5153     TCGv_i64 tcg_n, tcg_m, tcg_rd;
5154     tcg_rd = cpu_reg(s, rd);
5155
5156     if (!sf && is_signed) {
5157         tcg_n = new_tmp_a64(s);
5158         tcg_m = new_tmp_a64(s);
5159         tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
5160         tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
5161     } else {
5162         tcg_n = read_cpu_reg(s, rn, sf);
5163         tcg_m = read_cpu_reg(s, rm, sf);
5164     }
5165
5166     if (is_signed) {
5167         gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
5168     } else {
5169         gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
5170     }
5171
5172     if (!sf) { /* zero extend final result */
5173         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
5174     }
5175 }
5176
5177 /* LSLV, LSRV, ASRV, RORV */
5178 static void handle_shift_reg(DisasContext *s,
5179                              enum a64_shift_type shift_type, unsigned int sf,
5180                              unsigned int rm, unsigned int rn, unsigned int rd)
5181 {
5182     TCGv_i64 tcg_shift = tcg_temp_new_i64();
5183     TCGv_i64 tcg_rd = cpu_reg(s, rd);
5184     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
5185
5186     tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
5187     shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
5188     tcg_temp_free_i64(tcg_shift);
5189 }
5190
5191 /* CRC32[BHWX], CRC32C[BHWX] */
5192 static void handle_crc32(DisasContext *s,
5193                          unsigned int sf, unsigned int sz, bool crc32c,
5194                          unsigned int rm, unsigned int rn, unsigned int rd)
5195 {
5196     TCGv_i64 tcg_acc, tcg_val;
5197     TCGv_i32 tcg_bytes;
5198
5199     if (!dc_isar_feature(aa64_crc32, s)
5200         || (sf == 1 && sz != 3)
5201         || (sf == 0 && sz == 3)) {
5202         unallocated_encoding(s);
5203         return;
5204     }
5205
5206     if (sz == 3) {
5207         tcg_val = cpu_reg(s, rm);
5208     } else {
5209         uint64_t mask;
5210         switch (sz) {
5211         case 0:
5212             mask = 0xFF;
5213             break;
5214         case 1:
5215             mask = 0xFFFF;
5216             break;
5217         case 2:
5218             mask = 0xFFFFFFFF;
5219             break;
5220         default:
5221             g_assert_not_reached();
5222         }
5223         tcg_val = new_tmp_a64(s);
5224         tcg_gen_andi_i64(tcg_val, cpu_reg(s, rm), mask);
5225     }
5226
5227     tcg_acc = cpu_reg(s, rn);
5228     tcg_bytes = tcg_const_i32(1 << sz);
5229
5230     if (crc32c) {
5231         gen_helper_crc32c_64(cpu_reg(s, rd), tcg_acc, tcg_val, tcg_bytes);
5232     } else {
5233         gen_helper_crc32_64(cpu_reg(s, rd), tcg_acc, tcg_val, tcg_bytes);
5234     }
5235
5236     tcg_temp_free_i32(tcg_bytes);
5237 }
5238
5239 /* Data-processing (2 source)
5240  *   31   30  29 28             21 20  16 15    10 9    5 4    0
5241  * +----+---+---+-----------------+------+--------+------+------+
5242  * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
5243  * +----+---+---+-----------------+------+--------+------+------+
5244  */
5245 static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
5246 {
5247     unsigned int sf, rm, opcode, rn, rd;
5248     sf = extract32(insn, 31, 1);
5249     rm = extract32(insn, 16, 5);
5250     opcode = extract32(insn, 10, 6);
5251     rn = extract32(insn, 5, 5);
5252     rd = extract32(insn, 0, 5);
5253
5254     if (extract32(insn, 29, 1)) {
5255         unallocated_encoding(s);
5256         return;
5257     }
5258
5259     switch (opcode) {
5260     case 2: /* UDIV */
5261         handle_div(s, false, sf, rm, rn, rd);
5262         break;
5263     case 3: /* SDIV */
5264         handle_div(s, true, sf, rm, rn, rd);
5265         break;
5266     case 8: /* LSLV */
5267         handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
5268         break;
5269     case 9: /* LSRV */
5270         handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
5271         break;
5272     case 10: /* ASRV */
5273         handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
5274         break;
5275     case 11: /* RORV */
5276         handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
5277         break;
5278     case 12: /* PACGA */
5279         if (sf == 0 || !dc_isar_feature(aa64_pauth, s)) {
5280             goto do_unallocated;
5281         }
5282         gen_helper_pacga(cpu_reg(s, rd), cpu_env,
5283                          cpu_reg(s, rn), cpu_reg_sp(s, rm));
5284         break;
5285     case 16:
5286     case 17:
5287     case 18:
5288     case 19:
5289     case 20:
5290     case 21:
5291     case 22:
5292     case 23: /* CRC32 */
5293     {
5294         int sz = extract32(opcode, 0, 2);
5295         bool crc32c = extract32(opcode, 2, 1);
5296         handle_crc32(s, sf, sz, crc32c, rm, rn, rd);
5297         break;
5298     }
5299     default:
5300     do_unallocated:
5301         unallocated_encoding(s);
5302         break;
5303     }
5304 }
5305
5306 /*
5307  * Data processing - register
5308  *  31  30 29  28      25    21  20  16      10         0
5309  * +--+---+--+---+-------+-----+-------+-------+---------+
5310  * |  |op0|  |op1| 1 0 1 | op2 |       |  op3  |         |
5311  * +--+---+--+---+-------+-----+-------+-------+---------+
5312  */
5313 static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
5314 {
5315     int op0 = extract32(insn, 30, 1);
5316     int op1 = extract32(insn, 28, 1);
5317     int op2 = extract32(insn, 21, 4);
5318     int op3 = extract32(insn, 10, 6);
5319
5320     if (!op1) {
5321         if (op2 & 8) {
5322             if (op2 & 1) {
5323                 /* Add/sub (extended register) */
5324                 disas_add_sub_ext_reg(s, insn);
5325             } else {
5326                 /* Add/sub (shifted register) */
5327                 disas_add_sub_reg(s, insn);
5328             }
5329         } else {
5330             /* Logical (shifted register) */
5331             disas_logic_reg(s, insn);
5332         }
5333         return;
5334     }
5335
5336     switch (op2) {
5337     case 0x0:
5338         switch (op3) {
5339         case 0x00: /* Add/subtract (with carry) */
5340             disas_adc_sbc(s, insn);
5341             break;
5342
5343         case 0x01: /* Rotate right into flags */
5344         case 0x21:
5345             disas_rotate_right_into_flags(s, insn);
5346             break;
5347
5348         case 0x02: /* Evaluate into flags */
5349         case 0x12:
5350         case 0x22:
5351         case 0x32:
5352             disas_evaluate_into_flags(s, insn);
5353             break;
5354
5355         default:
5356             goto do_unallocated;
5357         }
5358         break;
5359
5360     case 0x2: /* Conditional compare */
5361         disas_cc(s, insn); /* both imm and reg forms */
5362         break;
5363
5364     case 0x4: /* Conditional select */
5365         disas_cond_select(s, insn);
5366         break;
5367
5368     case 0x6: /* Data-processing */
5369         if (op0) {    /* (1 source) */
5370             disas_data_proc_1src(s, insn);
5371         } else {      /* (2 source) */
5372             disas_data_proc_2src(s, insn);
5373         }
5374         break;
5375     case 0x8 ... 0xf: /* (3 source) */
5376         disas_data_proc_3src(s, insn);
5377         break;
5378
5379     default:
5380     do_unallocated:
5381         unallocated_encoding(s);
5382         break;
5383     }
5384 }
5385
5386 static void handle_fp_compare(DisasContext *s, int size,
5387                               unsigned int rn, unsigned int rm,
5388                               bool cmp_with_zero, bool signal_all_nans)
5389 {
5390     TCGv_i64 tcg_flags = tcg_temp_new_i64();
5391     TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
5392
5393     if (size == MO_64) {
5394         TCGv_i64 tcg_vn, tcg_vm;
5395
5396         tcg_vn = read_fp_dreg(s, rn);
5397         if (cmp_with_zero) {
5398             tcg_vm = tcg_const_i64(0);
5399         } else {
5400             tcg_vm = read_fp_dreg(s, rm);
5401         }
5402         if (signal_all_nans) {
5403             gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5404         } else {
5405             gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5406         }
5407         tcg_temp_free_i64(tcg_vn);
5408         tcg_temp_free_i64(tcg_vm);
5409     } else {
5410         TCGv_i32 tcg_vn = tcg_temp_new_i32();
5411         TCGv_i32 tcg_vm = tcg_temp_new_i32();
5412
5413         read_vec_element_i32(s, tcg_vn, rn, 0, size);
5414         if (cmp_with_zero) {
5415             tcg_gen_movi_i32(tcg_vm, 0);
5416         } else {
5417             read_vec_element_i32(s, tcg_vm, rm, 0, size);
5418         }
5419
5420         switch (size) {
5421         case MO_32:
5422             if (signal_all_nans) {
5423                 gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5424             } else {
5425                 gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5426             }
5427             break;
5428         case MO_16:
5429             if (signal_all_nans) {
5430                 gen_helper_vfp_cmpeh_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5431             } else {
5432                 gen_helper_vfp_cmph_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5433             }
5434             break;
5435         default:
5436             g_assert_not_reached();
5437         }
5438
5439         tcg_temp_free_i32(tcg_vn);
5440         tcg_temp_free_i32(tcg_vm);
5441     }
5442
5443     tcg_temp_free_ptr(fpst);
5444
5445     gen_set_nzcv(tcg_flags);
5446
5447     tcg_temp_free_i64(tcg_flags);
5448 }
5449
5450 /* Floating point compare
5451  *   31  30  29 28       24 23  22  21 20  16 15 14 13  10    9    5 4     0
5452  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
5453  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | op  | 1 0 0 0 |  Rn  |  op2  |
5454  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
5455  */
5456 static void disas_fp_compare(DisasContext *s, uint32_t insn)
5457 {
5458     unsigned int mos, type, rm, op, rn, opc, op2r;
5459     int size;
5460
5461     mos = extract32(insn, 29, 3);
5462     type = extract32(insn, 22, 2);
5463     rm = extract32(insn, 16, 5);
5464     op = extract32(insn, 14, 2);
5465     rn = extract32(insn, 5, 5);
5466     opc = extract32(insn, 3, 2);
5467     op2r = extract32(insn, 0, 3);
5468
5469     if (mos || op || op2r) {
5470         unallocated_encoding(s);
5471         return;
5472     }
5473
5474     switch (type) {
5475     case 0:
5476         size = MO_32;
5477         break;
5478     case 1:
5479         size = MO_64;
5480         break;
5481     case 3:
5482         size = MO_16;
5483         if (dc_isar_feature(aa64_fp16, s)) {
5484             break;
5485         }
5486         /* fallthru */
5487     default:
5488         unallocated_encoding(s);
5489         return;
5490     }
5491
5492     if (!fp_access_check(s)) {
5493         return;
5494     }
5495
5496     handle_fp_compare(s, size, rn, rm, opc & 1, opc & 2);
5497 }
5498
5499 /* Floating point conditional compare
5500  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5  4   3    0
5501  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
5502  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 0 1 |  Rn  | op | nzcv |
5503  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
5504  */
5505 static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
5506 {
5507     unsigned int mos, type, rm, cond, rn, op, nzcv;
5508     TCGv_i64 tcg_flags;
5509     TCGLabel *label_continue = NULL;
5510     int size;
5511
5512     mos = extract32(insn, 29, 3);
5513     type = extract32(insn, 22, 2);
5514     rm = extract32(insn, 16, 5);
5515     cond = extract32(insn, 12, 4);
5516     rn = extract32(insn, 5, 5);
5517     op = extract32(insn, 4, 1);
5518     nzcv = extract32(insn, 0, 4);
5519
5520     if (mos) {
5521         unallocated_encoding(s);
5522         return;
5523     }
5524
5525     switch (type) {
5526     case 0:
5527         size = MO_32;
5528         break;
5529     case 1:
5530         size = MO_64;
5531         break;
5532     case 3:
5533         size = MO_16;
5534         if (dc_isar_feature(aa64_fp16, s)) {
5535             break;
5536         }
5537         /* fallthru */
5538     default:
5539         unallocated_encoding(s);
5540         return;
5541     }
5542
5543     if (!fp_access_check(s)) {
5544         return;
5545     }
5546
5547     if (cond < 0x0e) { /* not always */
5548         TCGLabel *label_match = gen_new_label();
5549         label_continue = gen_new_label();
5550         arm_gen_test_cc(cond, label_match);
5551         /* nomatch: */
5552         tcg_flags = tcg_const_i64(nzcv << 28);
5553         gen_set_nzcv(tcg_flags);
5554         tcg_temp_free_i64(tcg_flags);
5555         tcg_gen_br(label_continue);
5556         gen_set_label(label_match);
5557     }
5558
5559     handle_fp_compare(s, size, rn, rm, false, op);
5560
5561     if (cond < 0x0e) {
5562         gen_set_label(label_continue);
5563     }
5564 }
5565
5566 /* Floating point conditional select
5567  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5 4    0
5568  * +---+---+---+-----------+------+---+------+------+-----+------+------+
5569  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 1 1 |  Rn  |  Rd  |
5570  * +---+---+---+-----------+------+---+------+------+-----+------+------+
5571  */
5572 static void disas_fp_csel(DisasContext *s, uint32_t insn)
5573 {
5574     unsigned int mos, type, rm, cond, rn, rd;
5575     TCGv_i64 t_true, t_false, t_zero;
5576     DisasCompare64 c;
5577     TCGMemOp sz;
5578
5579     mos = extract32(insn, 29, 3);
5580     type = extract32(insn, 22, 2);
5581     rm = extract32(insn, 16, 5);
5582     cond = extract32(insn, 12, 4);
5583     rn = extract32(insn, 5, 5);
5584     rd = extract32(insn, 0, 5);
5585
5586     if (mos) {
5587         unallocated_encoding(s);
5588         return;
5589     }
5590
5591     switch (type) {
5592     case 0:
5593         sz = MO_32;
5594         break;
5595     case 1:
5596         sz = MO_64;
5597         break;
5598     case 3:
5599         sz = MO_16;
5600         if (dc_isar_feature(aa64_fp16, s)) {
5601             break;
5602         }
5603         /* fallthru */
5604     default:
5605         unallocated_encoding(s);
5606         return;
5607     }
5608
5609     if (!fp_access_check(s)) {
5610         return;
5611     }
5612
5613     /* Zero extend sreg & hreg inputs to 64 bits now.  */
5614     t_true = tcg_temp_new_i64();
5615     t_false = tcg_temp_new_i64();
5616     read_vec_element(s, t_true, rn, 0, sz);
5617     read_vec_element(s, t_false, rm, 0, sz);
5618
5619     a64_test_cc(&c, cond);
5620     t_zero = tcg_const_i64(0);
5621     tcg_gen_movcond_i64(c.cond, t_true, c.value, t_zero, t_true, t_false);
5622     tcg_temp_free_i64(t_zero);
5623     tcg_temp_free_i64(t_false);
5624     a64_free_cc(&c);
5625
5626     /* Note that sregs & hregs write back zeros to the high bits,
5627        and we've already done the zero-extension.  */
5628     write_fp_dreg(s, rd, t_true);
5629     tcg_temp_free_i64(t_true);
5630 }
5631
5632 /* Floating-point data-processing (1 source) - half precision */
5633 static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
5634 {
5635     TCGv_ptr fpst = NULL;
5636     TCGv_i32 tcg_op = read_fp_hreg(s, rn);
5637     TCGv_i32 tcg_res = tcg_temp_new_i32();
5638
5639     switch (opcode) {
5640     case 0x0: /* FMOV */
5641         tcg_gen_mov_i32(tcg_res, tcg_op);
5642         break;
5643     case 0x1: /* FABS */
5644         tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
5645         break;
5646     case 0x2: /* FNEG */
5647         tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
5648         break;
5649     case 0x3: /* FSQRT */
5650         fpst = get_fpstatus_ptr(true);
5651         gen_helper_sqrt_f16(tcg_res, tcg_op, fpst);
5652         break;
5653     case 0x8: /* FRINTN */
5654     case 0x9: /* FRINTP */
5655     case 0xa: /* FRINTM */
5656     case 0xb: /* FRINTZ */
5657     case 0xc: /* FRINTA */
5658     {
5659         TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
5660         fpst = get_fpstatus_ptr(true);
5661
5662         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5663         gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
5664
5665         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5666         tcg_temp_free_i32(tcg_rmode);
5667         break;
5668     }
5669     case 0xe: /* FRINTX */
5670         fpst = get_fpstatus_ptr(true);
5671         gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, fpst);
5672         break;
5673     case 0xf: /* FRINTI */
5674         fpst = get_fpstatus_ptr(true);
5675         gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
5676         break;
5677     default:
5678         abort();
5679     }
5680
5681     write_fp_sreg(s, rd, tcg_res);
5682
5683     if (fpst) {
5684         tcg_temp_free_ptr(fpst);
5685     }
5686     tcg_temp_free_i32(tcg_op);
5687     tcg_temp_free_i32(tcg_res);
5688 }
5689
5690 /* Floating-point data-processing (1 source) - single precision */
5691 static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
5692 {
5693     void (*gen_fpst)(TCGv_i32, TCGv_i32, TCGv_ptr);
5694     TCGv_i32 tcg_op, tcg_res;
5695     TCGv_ptr fpst;
5696     int rmode = -1;
5697
5698     tcg_op = read_fp_sreg(s, rn);
5699     tcg_res = tcg_temp_new_i32();
5700
5701     switch (opcode) {
5702     case 0x0: /* FMOV */
5703         tcg_gen_mov_i32(tcg_res, tcg_op);
5704         goto done;
5705     case 0x1: /* FABS */
5706         gen_helper_vfp_abss(tcg_res, tcg_op);
5707         goto done;
5708     case 0x2: /* FNEG */
5709         gen_helper_vfp_negs(tcg_res, tcg_op);
5710         goto done;
5711     case 0x3: /* FSQRT */
5712         gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
5713         goto done;
5714     case 0x8: /* FRINTN */
5715     case 0x9: /* FRINTP */
5716     case 0xa: /* FRINTM */
5717     case 0xb: /* FRINTZ */
5718     case 0xc: /* FRINTA */
5719         rmode = arm_rmode_to_sf(opcode & 7);
5720         gen_fpst = gen_helper_rints;
5721         break;
5722     case 0xe: /* FRINTX */
5723         gen_fpst = gen_helper_rints_exact;
5724         break;
5725     case 0xf: /* FRINTI */
5726         gen_fpst = gen_helper_rints;
5727         break;
5728     case 0x10: /* FRINT32Z */
5729         rmode = float_round_to_zero;
5730         gen_fpst = gen_helper_frint32_s;
5731         break;
5732     case 0x11: /* FRINT32X */
5733         gen_fpst = gen_helper_frint32_s;
5734         break;
5735     case 0x12: /* FRINT64Z */
5736         rmode = float_round_to_zero;
5737         gen_fpst = gen_helper_frint64_s;
5738         break;
5739     case 0x13: /* FRINT64X */
5740         gen_fpst = gen_helper_frint64_s;
5741         break;
5742     default:
5743         g_assert_not_reached();
5744     }
5745
5746     fpst = get_fpstatus_ptr(false);
5747     if (rmode >= 0) {
5748         TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
5749         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5750         gen_fpst(tcg_res, tcg_op, fpst);
5751         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5752         tcg_temp_free_i32(tcg_rmode);
5753     } else {
5754         gen_fpst(tcg_res, tcg_op, fpst);
5755     }
5756     tcg_temp_free_ptr(fpst);
5757
5758  done:
5759     write_fp_sreg(s, rd, tcg_res);
5760     tcg_temp_free_i32(tcg_op);
5761     tcg_temp_free_i32(tcg_res);
5762 }
5763
5764 /* Floating-point data-processing (1 source) - double precision */
5765 static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
5766 {
5767     void (*gen_fpst)(TCGv_i64, TCGv_i64, TCGv_ptr);
5768     TCGv_i64 tcg_op, tcg_res;
5769     TCGv_ptr fpst;
5770     int rmode = -1;
5771
5772     switch (opcode) {
5773     case 0x0: /* FMOV */
5774         gen_gvec_fn2(s, false, rd, rn, tcg_gen_gvec_mov, 0);
5775         return;
5776     }
5777
5778     tcg_op = read_fp_dreg(s, rn);
5779     tcg_res = tcg_temp_new_i64();
5780
5781     switch (opcode) {
5782     case 0x1: /* FABS */
5783         gen_helper_vfp_absd(tcg_res, tcg_op);
5784         goto done;
5785     case 0x2: /* FNEG */
5786         gen_helper_vfp_negd(tcg_res, tcg_op);
5787         goto done;
5788     case 0x3: /* FSQRT */
5789         gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
5790         goto done;
5791     case 0x8: /* FRINTN */
5792     case 0x9: /* FRINTP */
5793     case 0xa: /* FRINTM */
5794     case 0xb: /* FRINTZ */
5795     case 0xc: /* FRINTA */
5796         rmode = arm_rmode_to_sf(opcode & 7);
5797         gen_fpst = gen_helper_rintd;
5798         break;
5799     case 0xe: /* FRINTX */
5800         gen_fpst = gen_helper_rintd_exact;
5801         break;
5802     case 0xf: /* FRINTI */
5803         gen_fpst = gen_helper_rintd;
5804         break;
5805     case 0x10: /* FRINT32Z */
5806         rmode = float_round_to_zero;
5807         gen_fpst = gen_helper_frint32_d;
5808         break;
5809     case 0x11: /* FRINT32X */
5810         gen_fpst = gen_helper_frint32_d;
5811         break;
5812     case 0x12: /* FRINT64Z */
5813         rmode = float_round_to_zero;
5814         gen_fpst = gen_helper_frint64_d;
5815         break;
5816     case 0x13: /* FRINT64X */
5817         gen_fpst = gen_helper_frint64_d;
5818         break;
5819     default:
5820         g_assert_not_reached();
5821     }
5822
5823     fpst = get_fpstatus_ptr(false);
5824     if (rmode >= 0) {
5825         TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
5826         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5827         gen_fpst(tcg_res, tcg_op, fpst);
5828         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5829         tcg_temp_free_i32(tcg_rmode);
5830     } else {
5831         gen_fpst(tcg_res, tcg_op, fpst);
5832     }
5833     tcg_temp_free_ptr(fpst);
5834
5835  done:
5836     write_fp_dreg(s, rd, tcg_res);
5837     tcg_temp_free_i64(tcg_op);
5838     tcg_temp_free_i64(tcg_res);
5839 }
5840
5841 static void handle_fp_fcvt(DisasContext *s, int opcode,
5842                            int rd, int rn, int dtype, int ntype)
5843 {
5844     switch (ntype) {
5845     case 0x0:
5846     {
5847         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
5848         if (dtype == 1) {
5849             /* Single to double */
5850             TCGv_i64 tcg_rd = tcg_temp_new_i64();
5851             gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
5852             write_fp_dreg(s, rd, tcg_rd);
5853             tcg_temp_free_i64(tcg_rd);
5854         } else {
5855             /* Single to half */
5856             TCGv_i32 tcg_rd = tcg_temp_new_i32();
5857             TCGv_i32 ahp = get_ahp_flag();
5858             TCGv_ptr fpst = get_fpstatus_ptr(false);
5859
5860             gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, fpst, ahp);
5861             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
5862             write_fp_sreg(s, rd, tcg_rd);
5863             tcg_temp_free_i32(tcg_rd);
5864             tcg_temp_free_i32(ahp);
5865             tcg_temp_free_ptr(fpst);
5866         }
5867         tcg_temp_free_i32(tcg_rn);
5868         break;
5869     }
5870     case 0x1:
5871     {
5872         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
5873         TCGv_i32 tcg_rd = tcg_temp_new_i32();
5874         if (dtype == 0) {
5875             /* Double to single */
5876             gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
5877         } else {
5878             TCGv_ptr fpst = get_fpstatus_ptr(false);
5879             TCGv_i32 ahp = get_ahp_flag();
5880             /* Double to half */
5881             gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, fpst, ahp);
5882             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
5883             tcg_temp_free_ptr(fpst);
5884             tcg_temp_free_i32(ahp);
5885         }
5886         write_fp_sreg(s, rd, tcg_rd);
5887         tcg_temp_free_i32(tcg_rd);
5888         tcg_temp_free_i64(tcg_rn);
5889         break;
5890     }
5891     case 0x3:
5892     {
5893         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
5894         TCGv_ptr tcg_fpst = get_fpstatus_ptr(false);
5895         TCGv_i32 tcg_ahp = get_ahp_flag();
5896         tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
5897         if (dtype == 0) {
5898             /* Half to single */
5899             TCGv_i32 tcg_rd = tcg_temp_new_i32();
5900             gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp);
5901             write_fp_sreg(s, rd, tcg_rd);
5902             tcg_temp_free_ptr(tcg_fpst);
5903             tcg_temp_free_i32(tcg_ahp);
5904             tcg_temp_free_i32(tcg_rd);
5905         } else {
5906             /* Half to double */
5907             TCGv_i64 tcg_rd = tcg_temp_new_i64();
5908             gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp);
5909             write_fp_dreg(s, rd, tcg_rd);
5910             tcg_temp_free_i64(tcg_rd);
5911         }
5912         tcg_temp_free_i32(tcg_rn);
5913         break;
5914     }
5915     default:
5916         abort();
5917     }
5918 }
5919
5920 /* Floating point data-processing (1 source)
5921  *   31  30  29 28       24 23  22  21 20    15 14       10 9    5 4    0
5922  * +---+---+---+-----------+------+---+--------+-----------+------+------+
5923  * | M | 0 | S | 1 1 1 1 0 | type | 1 | opcode | 1 0 0 0 0 |  Rn  |  Rd  |
5924  * +---+---+---+-----------+------+---+--------+-----------+------+------+
5925  */
5926 static void disas_fp_1src(DisasContext *s, uint32_t insn)
5927 {
5928     int mos = extract32(insn, 29, 3);
5929     int type = extract32(insn, 22, 2);
5930     int opcode = extract32(insn, 15, 6);
5931     int rn = extract32(insn, 5, 5);
5932     int rd = extract32(insn, 0, 5);
5933
5934     if (mos) {
5935         unallocated_encoding(s);
5936         return;
5937     }
5938
5939     switch (opcode) {
5940     case 0x4: case 0x5: case 0x7:
5941     {
5942         /* FCVT between half, single and double precision */
5943         int dtype = extract32(opcode, 0, 2);
5944         if (type == 2 || dtype == type) {
5945             unallocated_encoding(s);
5946             return;
5947         }
5948         if (!fp_access_check(s)) {
5949             return;
5950         }
5951
5952         handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
5953         break;
5954     }
5955
5956     case 0x10 ... 0x13: /* FRINT{32,64}{X,Z} */
5957         if (type > 1 || !dc_isar_feature(aa64_frint, s)) {
5958             unallocated_encoding(s);
5959             return;
5960         }
5961         /* fall through */
5962     case 0x0 ... 0x3:
5963     case 0x8 ... 0xc:
5964     case 0xe ... 0xf:
5965         /* 32-to-32 and 64-to-64 ops */
5966         switch (type) {
5967         case 0:
5968             if (!fp_access_check(s)) {
5969                 return;
5970             }
5971             handle_fp_1src_single(s, opcode, rd, rn);
5972             break;
5973         case 1:
5974             if (!fp_access_check(s)) {
5975                 return;
5976             }
5977             handle_fp_1src_double(s, opcode, rd, rn);
5978             break;
5979         case 3:
5980             if (!dc_isar_feature(aa64_fp16, s)) {
5981                 unallocated_encoding(s);
5982                 return;
5983             }
5984
5985             if (!fp_access_check(s)) {
5986                 return;
5987             }
5988             handle_fp_1src_half(s, opcode, rd, rn);
5989             break;
5990         default:
5991             unallocated_encoding(s);
5992         }
5993         break;
5994
5995     default:
5996         unallocated_encoding(s);
5997         break;
5998     }
5999 }
6000
6001 /* Floating-point data-processing (2 source) - single precision */
6002 static void handle_fp_2src_single(DisasContext *s, int opcode,
6003                                   int rd, int rn, int rm)
6004 {
6005     TCGv_i32 tcg_op1;
6006     TCGv_i32 tcg_op2;
6007     TCGv_i32 tcg_res;
6008     TCGv_ptr fpst;
6009
6010     tcg_res = tcg_temp_new_i32();
6011     fpst = get_fpstatus_ptr(false);
6012     tcg_op1 = read_fp_sreg(s, rn);
6013     tcg_op2 = read_fp_sreg(s, rm);
6014
6015     switch (opcode) {
6016     case 0x0: /* FMUL */
6017         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
6018         break;
6019     case 0x1: /* FDIV */
6020         gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
6021         break;
6022     case 0x2: /* FADD */
6023         gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
6024         break;
6025     case 0x3: /* FSUB */
6026         gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
6027         break;
6028     case 0x4: /* FMAX */
6029         gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
6030         break;
6031     case 0x5: /* FMIN */
6032         gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
6033         break;
6034     case 0x6: /* FMAXNM */
6035         gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
6036         break;
6037     case 0x7: /* FMINNM */
6038         gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
6039         break;
6040     case 0x8: /* FNMUL */
6041         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
6042         gen_helper_vfp_negs(tcg_res, tcg_res);
6043         break;
6044     }
6045
6046     write_fp_sreg(s, rd, tcg_res);
6047
6048     tcg_temp_free_ptr(fpst);
6049     tcg_temp_free_i32(tcg_op1);
6050     tcg_temp_free_i32(tcg_op2);
6051     tcg_temp_free_i32(tcg_res);
6052 }
6053
6054 /* Floating-point data-processing (2 source) - double precision */
6055 static void handle_fp_2src_double(DisasContext *s, int opcode,
6056                                   int rd, int rn, int rm)
6057 {
6058     TCGv_i64 tcg_op1;
6059     TCGv_i64 tcg_op2;
6060     TCGv_i64 tcg_res;
6061     TCGv_ptr fpst;
6062
6063     tcg_res = tcg_temp_new_i64();
6064     fpst = get_fpstatus_ptr(false);
6065     tcg_op1 = read_fp_dreg(s, rn);
6066     tcg_op2 = read_fp_dreg(s, rm);
6067
6068     switch (opcode) {
6069     case 0x0: /* FMUL */
6070         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
6071         break;
6072     case 0x1: /* FDIV */
6073         gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
6074         break;
6075     case 0x2: /* FADD */
6076         gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
6077         break;
6078     case 0x3: /* FSUB */
6079         gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
6080         break;
6081     case 0x4: /* FMAX */
6082         gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
6083         break;
6084     case 0x5: /* FMIN */
6085         gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
6086         break;
6087     case 0x6: /* FMAXNM */
6088         gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
6089         break;
6090     case 0x7: /* FMINNM */
6091         gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
6092         break;
6093     case 0x8: /* FNMUL */
6094         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
6095         gen_helper_vfp_negd(tcg_res, tcg_res);
6096         break;
6097     }
6098
6099     write_fp_dreg(s, rd, tcg_res);
6100
6101     tcg_temp_free_ptr(fpst);
6102     tcg_temp_free_i64(tcg_op1);
6103     tcg_temp_free_i64(tcg_op2);
6104     tcg_temp_free_i64(tcg_res);
6105 }
6106
6107 /* Floating-point data-processing (2 source) - half precision */
6108 static void handle_fp_2src_half(DisasContext *s, int opcode,
6109                                 int rd, int rn, int rm)
6110 {
6111     TCGv_i32 tcg_op1;
6112     TCGv_i32 tcg_op2;
6113     TCGv_i32 tcg_res;
6114     TCGv_ptr fpst;
6115
6116     tcg_res = tcg_temp_new_i32();
6117     fpst = get_fpstatus_ptr(true);
6118     tcg_op1 = read_fp_hreg(s, rn);
6119     tcg_op2 = read_fp_hreg(s, rm);
6120
6121     switch (opcode) {
6122     case 0x0: /* FMUL */
6123         gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
6124         break;
6125     case 0x1: /* FDIV */
6126         gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
6127         break;
6128     case 0x2: /* FADD */
6129         gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
6130         break;
6131     case 0x3: /* FSUB */
6132         gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
6133         break;
6134     case 0x4: /* FMAX */
6135         gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
6136         break;
6137     case 0x5: /* FMIN */
6138         gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
6139         break;
6140     case 0x6: /* FMAXNM */
6141         gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
6142         break;
6143     case 0x7: /* FMINNM */
6144         gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
6145         break;
6146     case 0x8: /* FNMUL */
6147         gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
6148         tcg_gen_xori_i32(tcg_res, tcg_res, 0x8000);
6149         break;
6150     default:
6151         g_assert_not_reached();
6152     }
6153
6154     write_fp_sreg(s, rd, tcg_res);
6155
6156     tcg_temp_free_ptr(fpst);
6157     tcg_temp_free_i32(tcg_op1);
6158     tcg_temp_free_i32(tcg_op2);
6159     tcg_temp_free_i32(tcg_res);
6160 }
6161
6162 /* Floating point data-processing (2 source)
6163  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
6164  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
6165  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | opcode | 1 0 |  Rn  |  Rd  |
6166  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
6167  */
6168 static void disas_fp_2src(DisasContext *s, uint32_t insn)
6169 {
6170     int mos = extract32(insn, 29, 3);
6171     int type = extract32(insn, 22, 2);
6172     int rd = extract32(insn, 0, 5);
6173     int rn = extract32(insn, 5, 5);
6174     int rm = extract32(insn, 16, 5);
6175     int opcode = extract32(insn, 12, 4);
6176
6177     if (opcode > 8 || mos) {
6178         unallocated_encoding(s);
6179         return;
6180     }
6181
6182     switch (type) {
6183     case 0:
6184         if (!fp_access_check(s)) {
6185             return;
6186         }
6187         handle_fp_2src_single(s, opcode, rd, rn, rm);
6188         break;
6189     case 1:
6190         if (!fp_access_check(s)) {
6191             return;
6192         }
6193         handle_fp_2src_double(s, opcode, rd, rn, rm);
6194         break;
6195     case 3:
6196         if (!dc_isar_feature(aa64_fp16, s)) {
6197             unallocated_encoding(s);
6198             return;
6199         }
6200         if (!fp_access_check(s)) {
6201             return;
6202         }
6203         handle_fp_2src_half(s, opcode, rd, rn, rm);
6204         break;
6205     default:
6206         unallocated_encoding(s);
6207     }
6208 }
6209
6210 /* Floating-point data-processing (3 source) - single precision */
6211 static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
6212                                   int rd, int rn, int rm, int ra)
6213 {
6214     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
6215     TCGv_i32 tcg_res = tcg_temp_new_i32();
6216     TCGv_ptr fpst = get_fpstatus_ptr(false);
6217
6218     tcg_op1 = read_fp_sreg(s, rn);
6219     tcg_op2 = read_fp_sreg(s, rm);
6220     tcg_op3 = read_fp_sreg(s, ra);
6221
6222     /* These are fused multiply-add, and must be done as one
6223      * floating point operation with no rounding between the
6224      * multiplication and addition steps.
6225      * NB that doing the negations here as separate steps is
6226      * correct : an input NaN should come out with its sign bit
6227      * flipped if it is a negated-input.
6228      */
6229     if (o1 == true) {
6230         gen_helper_vfp_negs(tcg_op3, tcg_op3);
6231     }
6232
6233     if (o0 != o1) {
6234         gen_helper_vfp_negs(tcg_op1, tcg_op1);
6235     }
6236
6237     gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
6238
6239     write_fp_sreg(s, rd, tcg_res);
6240
6241     tcg_temp_free_ptr(fpst);
6242     tcg_temp_free_i32(tcg_op1);
6243     tcg_temp_free_i32(tcg_op2);
6244     tcg_temp_free_i32(tcg_op3);
6245     tcg_temp_free_i32(tcg_res);
6246 }
6247
6248 /* Floating-point data-processing (3 source) - double precision */
6249 static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
6250                                   int rd, int rn, int rm, int ra)
6251 {
6252     TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
6253     TCGv_i64 tcg_res = tcg_temp_new_i64();
6254     TCGv_ptr fpst = get_fpstatus_ptr(false);
6255
6256     tcg_op1 = read_fp_dreg(s, rn);
6257     tcg_op2 = read_fp_dreg(s, rm);
6258     tcg_op3 = read_fp_dreg(s, ra);
6259
6260     /* These are fused multiply-add, and must be done as one
6261      * floating point operation with no rounding between the
6262      * multiplication and addition steps.
6263      * NB that doing the negations here as separate steps is
6264      * correct : an input NaN should come out with its sign bit
6265      * flipped if it is a negated-input.
6266      */
6267     if (o1 == true) {
6268         gen_helper_vfp_negd(tcg_op3, tcg_op3);
6269     }
6270
6271     if (o0 != o1) {
6272         gen_helper_vfp_negd(tcg_op1, tcg_op1);
6273     }
6274
6275     gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
6276
6277     write_fp_dreg(s, rd, tcg_res);
6278
6279     tcg_temp_free_ptr(fpst);
6280     tcg_temp_free_i64(tcg_op1);
6281     tcg_temp_free_i64(tcg_op2);
6282     tcg_temp_free_i64(tcg_op3);
6283     tcg_temp_free_i64(tcg_res);
6284 }
6285
6286 /* Floating-point data-processing (3 source) - half precision */
6287 static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1,
6288                                 int rd, int rn, int rm, int ra)
6289 {
6290     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
6291     TCGv_i32 tcg_res = tcg_temp_new_i32();
6292     TCGv_ptr fpst = get_fpstatus_ptr(true);
6293
6294     tcg_op1 = read_fp_hreg(s, rn);
6295     tcg_op2 = read_fp_hreg(s, rm);
6296     tcg_op3 = read_fp_hreg(s, ra);
6297
6298     /* These are fused multiply-add, and must be done as one
6299      * floating point operation with no rounding between the
6300      * multiplication and addition steps.
6301      * NB that doing the negations here as separate steps is
6302      * correct : an input NaN should come out with its sign bit
6303      * flipped if it is a negated-input.
6304      */
6305     if (o1 == true) {
6306         tcg_gen_xori_i32(tcg_op3, tcg_op3, 0x8000);
6307     }
6308
6309     if (o0 != o1) {
6310         tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
6311     }
6312
6313     gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
6314
6315     write_fp_sreg(s, rd, tcg_res);
6316
6317     tcg_temp_free_ptr(fpst);
6318     tcg_temp_free_i32(tcg_op1);
6319     tcg_temp_free_i32(tcg_op2);
6320     tcg_temp_free_i32(tcg_op3);
6321     tcg_temp_free_i32(tcg_res);
6322 }
6323
6324 /* Floating point data-processing (3 source)
6325  *   31  30  29 28       24 23  22  21  20  16  15  14  10 9    5 4    0
6326  * +---+---+---+-----------+------+----+------+----+------+------+------+
6327  * | M | 0 | S | 1 1 1 1 1 | type | o1 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
6328  * +---+---+---+-----------+------+----+------+----+------+------+------+
6329  */
6330 static void disas_fp_3src(DisasContext *s, uint32_t insn)
6331 {
6332     int mos = extract32(insn, 29, 3);
6333     int type = extract32(insn, 22, 2);
6334     int rd = extract32(insn, 0, 5);
6335     int rn = extract32(insn, 5, 5);
6336     int ra = extract32(insn, 10, 5);
6337     int rm = extract32(insn, 16, 5);
6338     bool o0 = extract32(insn, 15, 1);
6339     bool o1 = extract32(insn, 21, 1);
6340
6341     if (mos) {
6342         unallocated_encoding(s);
6343         return;
6344     }
6345
6346     switch (type) {
6347     case 0:
6348         if (!fp_access_check(s)) {
6349             return;
6350         }
6351         handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
6352         break;
6353     case 1:
6354         if (!fp_access_check(s)) {
6355             return;
6356         }
6357         handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
6358         break;
6359     case 3:
6360         if (!dc_isar_feature(aa64_fp16, s)) {
6361             unallocated_encoding(s);
6362             return;
6363         }
6364         if (!fp_access_check(s)) {
6365             return;
6366         }
6367         handle_fp_3src_half(s, o0, o1, rd, rn, rm, ra);
6368         break;
6369     default:
6370         unallocated_encoding(s);
6371     }
6372 }
6373
6374 /* The imm8 encodes the sign bit, enough bits to represent an exponent in
6375  * the range 01....1xx to 10....0xx, and the most significant 4 bits of
6376  * the mantissa; see VFPExpandImm() in the v8 ARM ARM.
6377  */
6378 uint64_t vfp_expand_imm(int size, uint8_t imm8)
6379 {
6380     uint64_t imm;
6381
6382     switch (size) {
6383     case MO_64:
6384         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
6385             (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
6386             extract32(imm8, 0, 6);
6387         imm <<= 48;
6388         break;
6389     case MO_32:
6390         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
6391             (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
6392             (extract32(imm8, 0, 6) << 3);
6393         imm <<= 16;
6394         break;
6395     case MO_16:
6396         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
6397             (extract32(imm8, 6, 1) ? 0x3000 : 0x4000) |
6398             (extract32(imm8, 0, 6) << 6);
6399         break;
6400     default:
6401         g_assert_not_reached();
6402     }
6403     return imm;
6404 }
6405
6406 /* Floating point immediate
6407  *   31  30  29 28       24 23  22  21 20        13 12   10 9    5 4    0
6408  * +---+---+---+-----------+------+---+------------+-------+------+------+
6409  * | M | 0 | S | 1 1 1 1 0 | type | 1 |    imm8    | 1 0 0 | imm5 |  Rd  |
6410  * +---+---+---+-----------+------+---+------------+-------+------+------+
6411  */
6412 static void disas_fp_imm(DisasContext *s, uint32_t insn)
6413 {
6414     int rd = extract32(insn, 0, 5);
6415     int imm5 = extract32(insn, 5, 5);
6416     int imm8 = extract32(insn, 13, 8);
6417     int type = extract32(insn, 22, 2);
6418     int mos = extract32(insn, 29, 3);
6419     uint64_t imm;
6420     TCGv_i64 tcg_res;
6421     TCGMemOp sz;
6422
6423     if (mos || imm5) {
6424         unallocated_encoding(s);
6425         return;
6426     }
6427
6428     switch (type) {
6429     case 0:
6430         sz = MO_32;
6431         break;
6432     case 1:
6433         sz = MO_64;
6434         break;
6435     case 3:
6436         sz = MO_16;
6437         if (dc_isar_feature(aa64_fp16, s)) {
6438             break;
6439         }
6440         /* fallthru */
6441     default:
6442         unallocated_encoding(s);
6443         return;
6444     }
6445
6446     if (!fp_access_check(s)) {
6447         return;
6448     }
6449
6450     imm = vfp_expand_imm(sz, imm8);
6451
6452     tcg_res = tcg_const_i64(imm);
6453     write_fp_dreg(s, rd, tcg_res);
6454     tcg_temp_free_i64(tcg_res);
6455 }
6456
6457 /* Handle floating point <=> fixed point conversions. Note that we can
6458  * also deal with fp <=> integer conversions as a special case (scale == 64)
6459  * OPTME: consider handling that special case specially or at least skipping
6460  * the call to scalbn in the helpers for zero shifts.
6461  */
6462 static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
6463                            bool itof, int rmode, int scale, int sf, int type)
6464 {
6465     bool is_signed = !(opcode & 1);
6466     TCGv_ptr tcg_fpstatus;
6467     TCGv_i32 tcg_shift, tcg_single;
6468     TCGv_i64 tcg_double;
6469
6470     tcg_fpstatus = get_fpstatus_ptr(type == 3);
6471
6472     tcg_shift = tcg_const_i32(64 - scale);
6473
6474     if (itof) {
6475         TCGv_i64 tcg_int = cpu_reg(s, rn);
6476         if (!sf) {
6477             TCGv_i64 tcg_extend = new_tmp_a64(s);
6478
6479             if (is_signed) {
6480                 tcg_gen_ext32s_i64(tcg_extend, tcg_int);
6481             } else {
6482                 tcg_gen_ext32u_i64(tcg_extend, tcg_int);
6483             }
6484
6485             tcg_int = tcg_extend;
6486         }
6487
6488         switch (type) {
6489         case 1: /* float64 */
6490             tcg_double = tcg_temp_new_i64();
6491             if (is_signed) {
6492                 gen_helper_vfp_sqtod(tcg_double, tcg_int,
6493                                      tcg_shift, tcg_fpstatus);
6494             } else {
6495                 gen_helper_vfp_uqtod(tcg_double, tcg_int,
6496                                      tcg_shift, tcg_fpstatus);
6497             }
6498             write_fp_dreg(s, rd, tcg_double);
6499             tcg_temp_free_i64(tcg_double);
6500             break;
6501
6502         case 0: /* float32 */
6503             tcg_single = tcg_temp_new_i32();
6504             if (is_signed) {
6505                 gen_helper_vfp_sqtos(tcg_single, tcg_int,
6506                                      tcg_shift, tcg_fpstatus);
6507             } else {
6508                 gen_helper_vfp_uqtos(tcg_single, tcg_int,
6509                                      tcg_shift, tcg_fpstatus);
6510             }
6511             write_fp_sreg(s, rd, tcg_single);
6512             tcg_temp_free_i32(tcg_single);
6513             break;
6514
6515         case 3: /* float16 */
6516             tcg_single = tcg_temp_new_i32();
6517             if (is_signed) {
6518                 gen_helper_vfp_sqtoh(tcg_single, tcg_int,
6519                                      tcg_shift, tcg_fpstatus);
6520             } else {
6521                 gen_helper_vfp_uqtoh(tcg_single, tcg_int,
6522                                      tcg_shift, tcg_fpstatus);
6523             }
6524             write_fp_sreg(s, rd, tcg_single);
6525             tcg_temp_free_i32(tcg_single);
6526             break;
6527
6528         default:
6529             g_assert_not_reached();
6530         }
6531     } else {
6532         TCGv_i64 tcg_int = cpu_reg(s, rd);
6533         TCGv_i32 tcg_rmode;
6534
6535         if (extract32(opcode, 2, 1)) {
6536             /* There are too many rounding modes to all fit into rmode,
6537              * so FCVTA[US] is a special case.
6538              */
6539             rmode = FPROUNDING_TIEAWAY;
6540         }
6541
6542         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6543
6544         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
6545
6546         switch (type) {
6547         case 1: /* float64 */
6548             tcg_double = read_fp_dreg(s, rn);
6549             if (is_signed) {
6550                 if (!sf) {
6551                     gen_helper_vfp_tosld(tcg_int, tcg_double,
6552                                          tcg_shift, tcg_fpstatus);
6553                 } else {
6554                     gen_helper_vfp_tosqd(tcg_int, tcg_double,
6555                                          tcg_shift, tcg_fpstatus);
6556                 }
6557             } else {
6558                 if (!sf) {
6559                     gen_helper_vfp_tould(tcg_int, tcg_double,
6560                                          tcg_shift, tcg_fpstatus);
6561                 } else {
6562                     gen_helper_vfp_touqd(tcg_int, tcg_double,
6563                                          tcg_shift, tcg_fpstatus);
6564                 }
6565             }
6566             if (!sf) {
6567                 tcg_gen_ext32u_i64(tcg_int, tcg_int);
6568             }
6569             tcg_temp_free_i64(tcg_double);
6570             break;
6571
6572         case 0: /* float32 */
6573             tcg_single = read_fp_sreg(s, rn);
6574             if (sf) {
6575                 if (is_signed) {
6576                     gen_helper_vfp_tosqs(tcg_int, tcg_single,
6577                                          tcg_shift, tcg_fpstatus);
6578                 } else {
6579                     gen_helper_vfp_touqs(tcg_int, tcg_single,
6580                                          tcg_shift, tcg_fpstatus);
6581                 }
6582             } else {
6583                 TCGv_i32 tcg_dest = tcg_temp_new_i32();
6584                 if (is_signed) {
6585                     gen_helper_vfp_tosls(tcg_dest, tcg_single,
6586                                          tcg_shift, tcg_fpstatus);
6587                 } else {
6588                     gen_helper_vfp_touls(tcg_dest, tcg_single,
6589                                          tcg_shift, tcg_fpstatus);
6590                 }
6591                 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
6592                 tcg_temp_free_i32(tcg_dest);
6593             }
6594             tcg_temp_free_i32(tcg_single);
6595             break;
6596
6597         case 3: /* float16 */
6598             tcg_single = read_fp_sreg(s, rn);
6599             if (sf) {
6600                 if (is_signed) {
6601                     gen_helper_vfp_tosqh(tcg_int, tcg_single,
6602                                          tcg_shift, tcg_fpstatus);
6603                 } else {
6604                     gen_helper_vfp_touqh(tcg_int, tcg_single,
6605                                          tcg_shift, tcg_fpstatus);
6606                 }
6607             } else {
6608                 TCGv_i32 tcg_dest = tcg_temp_new_i32();
6609                 if (is_signed) {
6610                     gen_helper_vfp_toslh(tcg_dest, tcg_single,
6611                                          tcg_shift, tcg_fpstatus);
6612                 } else {
6613                     gen_helper_vfp_toulh(tcg_dest, tcg_single,
6614                                          tcg_shift, tcg_fpstatus);
6615                 }
6616                 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
6617                 tcg_temp_free_i32(tcg_dest);
6618             }
6619             tcg_temp_free_i32(tcg_single);
6620             break;
6621
6622         default:
6623             g_assert_not_reached();
6624         }
6625
6626         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
6627         tcg_temp_free_i32(tcg_rmode);
6628     }
6629
6630     tcg_temp_free_ptr(tcg_fpstatus);
6631     tcg_temp_free_i32(tcg_shift);
6632 }
6633
6634 /* Floating point <-> fixed point conversions
6635  *   31   30  29 28       24 23  22  21 20   19 18    16 15   10 9    5 4    0
6636  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
6637  * | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opcode | scale |  Rn  |  Rd  |
6638  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
6639  */
6640 static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
6641 {
6642     int rd = extract32(insn, 0, 5);
6643     int rn = extract32(insn, 5, 5);
6644     int scale = extract32(insn, 10, 6);
6645     int opcode = extract32(insn, 16, 3);
6646     int rmode = extract32(insn, 19, 2);
6647     int type = extract32(insn, 22, 2);
6648     bool sbit = extract32(insn, 29, 1);
6649     bool sf = extract32(insn, 31, 1);
6650     bool itof;
6651
6652     if (sbit || (!sf && scale < 32)) {
6653         unallocated_encoding(s);
6654         return;
6655     }
6656
6657     switch (type) {
6658     case 0: /* float32 */
6659     case 1: /* float64 */
6660         break;
6661     case 3: /* float16 */
6662         if (dc_isar_feature(aa64_fp16, s)) {
6663             break;
6664         }
6665         /* fallthru */
6666     default:
6667         unallocated_encoding(s);
6668         return;
6669     }
6670
6671     switch ((rmode << 3) | opcode) {
6672     case 0x2: /* SCVTF */
6673     case 0x3: /* UCVTF */
6674         itof = true;
6675         break;
6676     case 0x18: /* FCVTZS */
6677     case 0x19: /* FCVTZU */
6678         itof = false;
6679         break;
6680     default:
6681         unallocated_encoding(s);
6682         return;
6683     }
6684
6685     if (!fp_access_check(s)) {
6686         return;
6687     }
6688
6689     handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
6690 }
6691
6692 static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
6693 {
6694     /* FMOV: gpr to or from float, double, or top half of quad fp reg,
6695      * without conversion.
6696      */
6697
6698     if (itof) {
6699         TCGv_i64 tcg_rn = cpu_reg(s, rn);
6700         TCGv_i64 tmp;
6701
6702         switch (type) {
6703         case 0:
6704             /* 32 bit */
6705             tmp = tcg_temp_new_i64();
6706             tcg_gen_ext32u_i64(tmp, tcg_rn);
6707             write_fp_dreg(s, rd, tmp);
6708             tcg_temp_free_i64(tmp);
6709             break;
6710         case 1:
6711             /* 64 bit */
6712             write_fp_dreg(s, rd, tcg_rn);
6713             break;
6714         case 2:
6715             /* 64 bit to top half. */
6716             tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd));
6717             clear_vec_high(s, true, rd);
6718             break;
6719         case 3:
6720             /* 16 bit */
6721             tmp = tcg_temp_new_i64();
6722             tcg_gen_ext16u_i64(tmp, tcg_rn);
6723             write_fp_dreg(s, rd, tmp);
6724             tcg_temp_free_i64(tmp);
6725             break;
6726         default:
6727             g_assert_not_reached();
6728         }
6729     } else {
6730         TCGv_i64 tcg_rd = cpu_reg(s, rd);
6731
6732         switch (type) {
6733         case 0:
6734             /* 32 bit */
6735             tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_32));
6736             break;
6737         case 1:
6738             /* 64 bit */
6739             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_64));
6740             break;
6741         case 2:
6742             /* 64 bits from top half */
6743             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(s, rn));
6744             break;
6745         case 3:
6746             /* 16 bit */
6747             tcg_gen_ld16u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_16));
6748             break;
6749         default:
6750             g_assert_not_reached();
6751         }
6752     }
6753 }
6754
6755 static void handle_fjcvtzs(DisasContext *s, int rd, int rn)
6756 {
6757     TCGv_i64 t = read_fp_dreg(s, rn);
6758     TCGv_ptr fpstatus = get_fpstatus_ptr(false);
6759
6760     gen_helper_fjcvtzs(t, t, fpstatus);
6761
6762     tcg_temp_free_ptr(fpstatus);
6763
6764     tcg_gen_ext32u_i64(cpu_reg(s, rd), t);
6765     tcg_gen_extrh_i64_i32(cpu_ZF, t);
6766     tcg_gen_movi_i32(cpu_CF, 0);
6767     tcg_gen_movi_i32(cpu_NF, 0);
6768     tcg_gen_movi_i32(cpu_VF, 0);
6769
6770     tcg_temp_free_i64(t);
6771 }
6772
6773 /* Floating point <-> integer conversions
6774  *   31   30  29 28       24 23  22  21 20   19 18 16 15         10 9  5 4  0
6775  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
6776  * | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
6777  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
6778  */
6779 static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
6780 {
6781     int rd = extract32(insn, 0, 5);
6782     int rn = extract32(insn, 5, 5);
6783     int opcode = extract32(insn, 16, 3);
6784     int rmode = extract32(insn, 19, 2);
6785     int type = extract32(insn, 22, 2);
6786     bool sbit = extract32(insn, 29, 1);
6787     bool sf = extract32(insn, 31, 1);
6788     bool itof = false;
6789
6790     if (sbit) {
6791         goto do_unallocated;
6792     }
6793
6794     switch (opcode) {
6795     case 2: /* SCVTF */
6796     case 3: /* UCVTF */
6797         itof = true;
6798         /* fallthru */
6799     case 4: /* FCVTAS */
6800     case 5: /* FCVTAU */
6801         if (rmode != 0) {
6802             goto do_unallocated;
6803         }
6804         /* fallthru */
6805     case 0: /* FCVT[NPMZ]S */
6806     case 1: /* FCVT[NPMZ]U */
6807         switch (type) {
6808         case 0: /* float32 */
6809         case 1: /* float64 */
6810             break;
6811         case 3: /* float16 */
6812             if (!dc_isar_feature(aa64_fp16, s)) {
6813                 goto do_unallocated;
6814             }
6815             break;
6816         default:
6817             goto do_unallocated;
6818         }
6819         if (!fp_access_check(s)) {
6820             return;
6821         }
6822         handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
6823         break;
6824
6825     default:
6826         switch (sf << 7 | type << 5 | rmode << 3 | opcode) {
6827         case 0b01100110: /* FMOV half <-> 32-bit int */
6828         case 0b01100111:
6829         case 0b11100110: /* FMOV half <-> 64-bit int */
6830         case 0b11100111:
6831             if (!dc_isar_feature(aa64_fp16, s)) {
6832                 goto do_unallocated;
6833             }
6834             /* fallthru */
6835         case 0b00000110: /* FMOV 32-bit */
6836         case 0b00000111:
6837         case 0b10100110: /* FMOV 64-bit */
6838         case 0b10100111:
6839         case 0b11001110: /* FMOV top half of 128-bit */
6840         case 0b11001111:
6841             if (!fp_access_check(s)) {
6842                 return;
6843             }
6844             itof = opcode & 1;
6845             handle_fmov(s, rd, rn, type, itof);
6846             break;
6847
6848         case 0b00111110: /* FJCVTZS */
6849             if (!dc_isar_feature(aa64_jscvt, s)) {
6850                 goto do_unallocated;
6851             } else if (fp_access_check(s)) {
6852                 handle_fjcvtzs(s, rd, rn);
6853             }
6854             break;
6855
6856         default:
6857         do_unallocated:
6858             unallocated_encoding(s);
6859             return;
6860         }
6861         break;
6862     }
6863 }
6864
6865 /* FP-specific subcases of table C3-6 (SIMD and FP data processing)
6866  *   31  30  29 28     25 24                          0
6867  * +---+---+---+---------+-----------------------------+
6868  * |   | 0 |   | 1 1 1 1 |                             |
6869  * +---+---+---+---------+-----------------------------+
6870  */
6871 static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
6872 {
6873     if (extract32(insn, 24, 1)) {
6874         /* Floating point data-processing (3 source) */
6875         disas_fp_3src(s, insn);
6876     } else if (extract32(insn, 21, 1) == 0) {
6877         /* Floating point to fixed point conversions */
6878         disas_fp_fixed_conv(s, insn);
6879     } else {
6880         switch (extract32(insn, 10, 2)) {
6881         case 1:
6882             /* Floating point conditional compare */
6883             disas_fp_ccomp(s, insn);
6884             break;
6885         case 2:
6886             /* Floating point data-processing (2 source) */
6887             disas_fp_2src(s, insn);
6888             break;
6889         case 3:
6890             /* Floating point conditional select */
6891             disas_fp_csel(s, insn);
6892             break;
6893         case 0:
6894             switch (ctz32(extract32(insn, 12, 4))) {
6895             case 0: /* [15:12] == xxx1 */
6896                 /* Floating point immediate */
6897                 disas_fp_imm(s, insn);
6898                 break;
6899             case 1: /* [15:12] == xx10 */
6900                 /* Floating point compare */
6901                 disas_fp_compare(s, insn);
6902                 break;
6903             case 2: /* [15:12] == x100 */
6904                 /* Floating point data-processing (1 source) */
6905                 disas_fp_1src(s, insn);
6906                 break;
6907             case 3: /* [15:12] == 1000 */
6908                 unallocated_encoding(s);
6909                 break;
6910             default: /* [15:12] == 0000 */
6911                 /* Floating point <-> integer conversions */
6912                 disas_fp_int_conv(s, insn);
6913                 break;
6914             }
6915             break;
6916         }
6917     }
6918 }
6919
6920 static void do_ext64(DisasContext *s, TCGv_i64 tcg_left, TCGv_i64 tcg_right,
6921                      int pos)
6922 {
6923     /* Extract 64 bits from the middle of two concatenated 64 bit
6924      * vector register slices left:right. The extracted bits start
6925      * at 'pos' bits into the right (least significant) side.
6926      * We return the result in tcg_right, and guarantee not to
6927      * trash tcg_left.
6928      */
6929     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
6930     assert(pos > 0 && pos < 64);
6931
6932     tcg_gen_shri_i64(tcg_right, tcg_right, pos);
6933     tcg_gen_shli_i64(tcg_tmp, tcg_left, 64 - pos);
6934     tcg_gen_or_i64(tcg_right, tcg_right, tcg_tmp);
6935
6936     tcg_temp_free_i64(tcg_tmp);
6937 }
6938
6939 /* EXT
6940  *   31  30 29         24 23 22  21 20  16 15  14  11 10  9    5 4    0
6941  * +---+---+-------------+-----+---+------+---+------+---+------+------+
6942  * | 0 | Q | 1 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | imm4 | 0 |  Rn  |  Rd  |
6943  * +---+---+-------------+-----+---+------+---+------+---+------+------+
6944  */
6945 static void disas_simd_ext(DisasContext *s, uint32_t insn)
6946 {
6947     int is_q = extract32(insn, 30, 1);
6948     int op2 = extract32(insn, 22, 2);
6949     int imm4 = extract32(insn, 11, 4);
6950     int rm = extract32(insn, 16, 5);
6951     int rn = extract32(insn, 5, 5);
6952     int rd = extract32(insn, 0, 5);
6953     int pos = imm4 << 3;
6954     TCGv_i64 tcg_resl, tcg_resh;
6955
6956     if (op2 != 0 || (!is_q && extract32(imm4, 3, 1))) {
6957         unallocated_encoding(s);
6958         return;
6959     }
6960
6961     if (!fp_access_check(s)) {
6962         return;
6963     }
6964
6965     tcg_resh = tcg_temp_new_i64();
6966     tcg_resl = tcg_temp_new_i64();
6967
6968     /* Vd gets bits starting at pos bits into Vm:Vn. This is
6969      * either extracting 128 bits from a 128:128 concatenation, or
6970      * extracting 64 bits from a 64:64 concatenation.
6971      */
6972     if (!is_q) {
6973         read_vec_element(s, tcg_resl, rn, 0, MO_64);
6974         if (pos != 0) {
6975             read_vec_element(s, tcg_resh, rm, 0, MO_64);
6976             do_ext64(s, tcg_resh, tcg_resl, pos);
6977         }
6978         tcg_gen_movi_i64(tcg_resh, 0);
6979     } else {
6980         TCGv_i64 tcg_hh;
6981         typedef struct {
6982             int reg;
6983             int elt;
6984         } EltPosns;
6985         EltPosns eltposns[] = { {rn, 0}, {rn, 1}, {rm, 0}, {rm, 1} };
6986         EltPosns *elt = eltposns;
6987
6988         if (pos >= 64) {
6989             elt++;
6990             pos -= 64;
6991         }
6992
6993         read_vec_element(s, tcg_resl, elt->reg, elt->elt, MO_64);
6994         elt++;
6995         read_vec_element(s, tcg_resh, elt->reg, elt->elt, MO_64);
6996         elt++;
6997         if (pos != 0) {
6998             do_ext64(s, tcg_resh, tcg_resl, pos);
6999             tcg_hh = tcg_temp_new_i64();
7000             read_vec_element(s, tcg_hh, elt->reg, elt->elt, MO_64);
7001             do_ext64(s, tcg_hh, tcg_resh, pos);
7002             tcg_temp_free_i64(tcg_hh);
7003         }
7004     }
7005
7006     write_vec_element(s, tcg_resl, rd, 0, MO_64);
7007     tcg_temp_free_i64(tcg_resl);
7008     write_vec_element(s, tcg_resh, rd, 1, MO_64);
7009     tcg_temp_free_i64(tcg_resh);
7010 }
7011
7012 /* TBL/TBX
7013  *   31  30 29         24 23 22  21 20  16 15  14 13  12  11 10 9    5 4    0
7014  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
7015  * | 0 | Q | 0 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | len | op | 0 0 |  Rn  |  Rd  |
7016  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
7017  */
7018 static void disas_simd_tb(DisasContext *s, uint32_t insn)
7019 {
7020     int op2 = extract32(insn, 22, 2);
7021     int is_q = extract32(insn, 30, 1);
7022     int rm = extract32(insn, 16, 5);
7023     int rn = extract32(insn, 5, 5);
7024     int rd = extract32(insn, 0, 5);
7025     int is_tblx = extract32(insn, 12, 1);
7026     int len = extract32(insn, 13, 2);
7027     TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
7028     TCGv_i32 tcg_regno, tcg_numregs;
7029
7030     if (op2 != 0) {
7031         unallocated_encoding(s);
7032         return;
7033     }
7034
7035     if (!fp_access_check(s)) {
7036         return;
7037     }
7038
7039     /* This does a table lookup: for every byte element in the input
7040      * we index into a table formed from up to four vector registers,
7041      * and then the output is the result of the lookups. Our helper
7042      * function does the lookup operation for a single 64 bit part of
7043      * the input.
7044      */
7045     tcg_resl = tcg_temp_new_i64();
7046     tcg_resh = tcg_temp_new_i64();
7047
7048     if (is_tblx) {
7049         read_vec_element(s, tcg_resl, rd, 0, MO_64);
7050     } else {
7051         tcg_gen_movi_i64(tcg_resl, 0);
7052     }
7053     if (is_tblx && is_q) {
7054         read_vec_element(s, tcg_resh, rd, 1, MO_64);
7055     } else {
7056         tcg_gen_movi_i64(tcg_resh, 0);
7057     }
7058
7059     tcg_idx = tcg_temp_new_i64();
7060     tcg_regno = tcg_const_i32(rn);
7061     tcg_numregs = tcg_const_i32(len + 1);
7062     read_vec_element(s, tcg_idx, rm, 0, MO_64);
7063     gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
7064                         tcg_regno, tcg_numregs);
7065     if (is_q) {
7066         read_vec_element(s, tcg_idx, rm, 1, MO_64);
7067         gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
7068                             tcg_regno, tcg_numregs);
7069     }
7070     tcg_temp_free_i64(tcg_idx);
7071     tcg_temp_free_i32(tcg_regno);
7072     tcg_temp_free_i32(tcg_numregs);
7073
7074     write_vec_element(s, tcg_resl, rd, 0, MO_64);
7075     tcg_temp_free_i64(tcg_resl);
7076     write_vec_element(s, tcg_resh, rd, 1, MO_64);
7077     tcg_temp_free_i64(tcg_resh);
7078 }
7079
7080 /* ZIP/UZP/TRN
7081  *   31  30 29         24 23  22  21 20   16 15 14 12 11 10 9    5 4    0
7082  * +---+---+-------------+------+---+------+---+------------------+------+
7083  * | 0 | Q | 0 0 1 1 1 0 | size | 0 |  Rm  | 0 | opc | 1 0 |  Rn  |  Rd  |
7084  * +---+---+-------------+------+---+------+---+------------------+------+
7085  */
7086 static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
7087 {
7088     int rd = extract32(insn, 0, 5);
7089     int rn = extract32(insn, 5, 5);
7090     int rm = extract32(insn, 16, 5);
7091     int size = extract32(insn, 22, 2);
7092     /* opc field bits [1:0] indicate ZIP/UZP/TRN;
7093      * bit 2 indicates 1 vs 2 variant of the insn.
7094      */
7095     int opcode = extract32(insn, 12, 2);
7096     bool part = extract32(insn, 14, 1);
7097     bool is_q = extract32(insn, 30, 1);
7098     int esize = 8 << size;
7099     int i, ofs;
7100     int datasize = is_q ? 128 : 64;
7101     int elements = datasize / esize;
7102     TCGv_i64 tcg_res, tcg_resl, tcg_resh;
7103
7104     if (opcode == 0 || (size == 3 && !is_q)) {
7105         unallocated_encoding(s);
7106         return;
7107     }
7108
7109     if (!fp_access_check(s)) {
7110         return;
7111     }
7112
7113     tcg_resl = tcg_const_i64(0);
7114     tcg_resh = tcg_const_i64(0);
7115     tcg_res = tcg_temp_new_i64();
7116
7117     for (i = 0; i < elements; i++) {
7118         switch (opcode) {
7119         case 1: /* UZP1/2 */
7120         {
7121             int midpoint = elements / 2;
7122             if (i < midpoint) {
7123                 read_vec_element(s, tcg_res, rn, 2 * i + part, size);
7124             } else {
7125                 read_vec_element(s, tcg_res, rm,
7126                                  2 * (i - midpoint) + part, size);
7127             }
7128             break;
7129         }
7130         case 2: /* TRN1/2 */
7131             if (i & 1) {
7132                 read_vec_element(s, tcg_res, rm, (i & ~1) + part, size);
7133             } else {
7134                 read_vec_element(s, tcg_res, rn, (i & ~1) + part, size);
7135             }
7136             break;
7137         case 3: /* ZIP1/2 */
7138         {
7139             int base = part * elements / 2;
7140             if (i & 1) {
7141                 read_vec_element(s, tcg_res, rm, base + (i >> 1), size);
7142             } else {
7143                 read_vec_element(s, tcg_res, rn, base + (i >> 1), size);
7144             }
7145             break;
7146         }
7147         default:
7148             g_assert_not_reached();
7149         }
7150
7151         ofs = i * esize;
7152         if (ofs < 64) {
7153             tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
7154             tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
7155         } else {
7156             tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
7157             tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
7158         }
7159     }
7160
7161     tcg_temp_free_i64(tcg_res);
7162
7163     write_vec_element(s, tcg_resl, rd, 0, MO_64);
7164     tcg_temp_free_i64(tcg_resl);
7165     write_vec_element(s, tcg_resh, rd, 1, MO_64);
7166     tcg_temp_free_i64(tcg_resh);
7167 }
7168
7169 /*
7170  * do_reduction_op helper
7171  *
7172  * This mirrors the Reduce() pseudocode in the ARM ARM. It is
7173  * important for correct NaN propagation that we do these
7174  * operations in exactly the order specified by the pseudocode.
7175  *
7176  * This is a recursive function, TCG temps should be freed by the
7177  * calling function once it is done with the values.
7178  */
7179 static TCGv_i32 do_reduction_op(DisasContext *s, int fpopcode, int rn,
7180                                 int esize, int size, int vmap, TCGv_ptr fpst)
7181 {
7182     if (esize == size) {
7183         int element;
7184         TCGMemOp msize = esize == 16 ? MO_16 : MO_32;
7185         TCGv_i32 tcg_elem;
7186
7187         /* We should have one register left here */
7188         assert(ctpop8(vmap) == 1);
7189         element = ctz32(vmap);
7190         assert(element < 8);
7191
7192         tcg_elem = tcg_temp_new_i32();
7193         read_vec_element_i32(s, tcg_elem, rn, element, msize);
7194         return tcg_elem;
7195     } else {
7196         int bits = size / 2;
7197         int shift = ctpop8(vmap) / 2;
7198         int vmap_lo = (vmap >> shift) & vmap;
7199         int vmap_hi = (vmap & ~vmap_lo);
7200         TCGv_i32 tcg_hi, tcg_lo, tcg_res;
7201
7202         tcg_hi = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_hi, fpst);
7203         tcg_lo = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_lo, fpst);
7204         tcg_res = tcg_temp_new_i32();
7205
7206         switch (fpopcode) {
7207         case 0x0c: /* fmaxnmv half-precision */
7208             gen_helper_advsimd_maxnumh(tcg_res, tcg_lo, tcg_hi, fpst);
7209             break;
7210         case 0x0f: /* fmaxv half-precision */
7211             gen_helper_advsimd_maxh(tcg_res, tcg_lo, tcg_hi, fpst);
7212             break;
7213         case 0x1c: /* fminnmv half-precision */
7214             gen_helper_advsimd_minnumh(tcg_res, tcg_lo, tcg_hi, fpst);
7215             break;
7216         case 0x1f: /* fminv half-precision */
7217             gen_helper_advsimd_minh(tcg_res, tcg_lo, tcg_hi, fpst);
7218             break;
7219         case 0x2c: /* fmaxnmv */
7220             gen_helper_vfp_maxnums(tcg_res, tcg_lo, tcg_hi, fpst);
7221             break;
7222         case 0x2f: /* fmaxv */
7223             gen_helper_vfp_maxs(tcg_res, tcg_lo, tcg_hi, fpst);
7224             break;
7225         case 0x3c: /* fminnmv */
7226             gen_helper_vfp_minnums(tcg_res, tcg_lo, tcg_hi, fpst);
7227             break;
7228         case 0x3f: /* fminv */
7229             gen_helper_vfp_mins(tcg_res, tcg_lo, tcg_hi, fpst);
7230             break;
7231         default:
7232             g_assert_not_reached();
7233         }
7234
7235         tcg_temp_free_i32(tcg_hi);
7236         tcg_temp_free_i32(tcg_lo);
7237         return tcg_res;
7238     }
7239 }
7240
7241 /* AdvSIMD across lanes
7242  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
7243  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
7244  * | 0 | Q | U | 0 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
7245  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
7246  */
7247 static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
7248 {
7249     int rd = extract32(insn, 0, 5);
7250     int rn = extract32(insn, 5, 5);
7251     int size = extract32(insn, 22, 2);
7252     int opcode = extract32(insn, 12, 5);
7253     bool is_q = extract32(insn, 30, 1);
7254     bool is_u = extract32(insn, 29, 1);
7255     bool is_fp = false;
7256     bool is_min = false;
7257     int esize;
7258     int elements;
7259     int i;
7260     TCGv_i64 tcg_res, tcg_elt;
7261
7262     switch (opcode) {
7263     case 0x1b: /* ADDV */
7264         if (is_u) {
7265             unallocated_encoding(s);
7266             return;
7267         }
7268         /* fall through */
7269     case 0x3: /* SADDLV, UADDLV */
7270     case 0xa: /* SMAXV, UMAXV */
7271     case 0x1a: /* SMINV, UMINV */
7272         if (size == 3 || (size == 2 && !is_q)) {
7273             unallocated_encoding(s);
7274             return;
7275         }
7276         break;
7277     case 0xc: /* FMAXNMV, FMINNMV */
7278     case 0xf: /* FMAXV, FMINV */
7279         /* Bit 1 of size field encodes min vs max and the actual size
7280          * depends on the encoding of the U bit. If not set (and FP16
7281          * enabled) then we do half-precision float instead of single
7282          * precision.
7283          */
7284         is_min = extract32(size, 1, 1);
7285         is_fp = true;
7286         if (!is_u && dc_isar_feature(aa64_fp16, s)) {
7287             size = 1;
7288         } else if (!is_u || !is_q || extract32(size, 0, 1)) {
7289             unallocated_encoding(s);
7290             return;
7291         } else {
7292             size = 2;
7293         }
7294         break;
7295     default:
7296         unallocated_encoding(s);
7297         return;
7298     }
7299
7300     if (!fp_access_check(s)) {
7301         return;
7302     }
7303
7304     esize = 8 << size;
7305     elements = (is_q ? 128 : 64) / esize;
7306
7307     tcg_res = tcg_temp_new_i64();
7308     tcg_elt = tcg_temp_new_i64();
7309
7310     /* These instructions operate across all lanes of a vector
7311      * to produce a single result. We can guarantee that a 64
7312      * bit intermediate is sufficient:
7313      *  + for [US]ADDLV the maximum element size is 32 bits, and
7314      *    the result type is 64 bits
7315      *  + for FMAX*V, FMIN*V, ADDV the intermediate type is the
7316      *    same as the element size, which is 32 bits at most
7317      * For the integer operations we can choose to work at 64
7318      * or 32 bits and truncate at the end; for simplicity
7319      * we use 64 bits always. The floating point
7320      * ops do require 32 bit intermediates, though.
7321      */
7322     if (!is_fp) {
7323         read_vec_element(s, tcg_res, rn, 0, size | (is_u ? 0 : MO_SIGN));
7324
7325         for (i = 1; i < elements; i++) {
7326             read_vec_element(s, tcg_elt, rn, i, size | (is_u ? 0 : MO_SIGN));
7327
7328             switch (opcode) {
7329             case 0x03: /* SADDLV / UADDLV */
7330             case 0x1b: /* ADDV */
7331                 tcg_gen_add_i64(tcg_res, tcg_res, tcg_elt);
7332                 break;
7333             case 0x0a: /* SMAXV / UMAXV */
7334                 if (is_u) {
7335                     tcg_gen_umax_i64(tcg_res, tcg_res, tcg_elt);
7336                 } else {
7337                     tcg_gen_smax_i64(tcg_res, tcg_res, tcg_elt);
7338                 }
7339                 break;
7340             case 0x1a: /* SMINV / UMINV */
7341                 if (is_u) {
7342                     tcg_gen_umin_i64(tcg_res, tcg_res, tcg_elt);
7343                 } else {
7344                     tcg_gen_smin_i64(tcg_res, tcg_res, tcg_elt);
7345                 }
7346                 break;
7347             default:
7348                 g_assert_not_reached();
7349             }
7350
7351         }
7352     } else {
7353         /* Floating point vector reduction ops which work across 32
7354          * bit (single) or 16 bit (half-precision) intermediates.
7355          * Note that correct NaN propagation requires that we do these
7356          * operations in exactly the order specified by the pseudocode.
7357          */
7358         TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
7359         int fpopcode = opcode | is_min << 4 | is_u << 5;
7360         int vmap = (1 << elements) - 1;
7361         TCGv_i32 tcg_res32 = do_reduction_op(s, fpopcode, rn, esize,
7362                                              (is_q ? 128 : 64), vmap, fpst);
7363         tcg_gen_extu_i32_i64(tcg_res, tcg_res32);
7364         tcg_temp_free_i32(tcg_res32);
7365         tcg_temp_free_ptr(fpst);
7366     }
7367
7368     tcg_temp_free_i64(tcg_elt);
7369
7370     /* Now truncate the result to the width required for the final output */
7371     if (opcode == 0x03) {
7372         /* SADDLV, UADDLV: result is 2*esize */
7373         size++;
7374     }
7375
7376     switch (size) {
7377     case 0:
7378         tcg_gen_ext8u_i64(tcg_res, tcg_res);
7379         break;
7380     case 1:
7381         tcg_gen_ext16u_i64(tcg_res, tcg_res);
7382         break;
7383     case 2:
7384         tcg_gen_ext32u_i64(tcg_res, tcg_res);
7385         break;
7386     case 3:
7387         break;
7388     default:
7389         g_assert_not_reached();
7390     }
7391
7392     write_fp_dreg(s, rd, tcg_res);
7393     tcg_temp_free_i64(tcg_res);
7394 }
7395
7396 /* DUP (Element, Vector)
7397  *
7398  *  31  30   29              21 20    16 15        10  9    5 4    0
7399  * +---+---+-------------------+--------+-------------+------+------+
7400  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
7401  * +---+---+-------------------+--------+-------------+------+------+
7402  *
7403  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7404  */
7405 static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
7406                              int imm5)
7407 {
7408     int size = ctz32(imm5);
7409     int index = imm5 >> (size + 1);
7410
7411     if (size > 3 || (size == 3 && !is_q)) {
7412         unallocated_encoding(s);
7413         return;
7414     }
7415
7416     if (!fp_access_check(s)) {
7417         return;
7418     }
7419
7420     tcg_gen_gvec_dup_mem(size, vec_full_reg_offset(s, rd),
7421                          vec_reg_offset(s, rn, index, size),
7422                          is_q ? 16 : 8, vec_full_reg_size(s));
7423 }
7424
7425 /* DUP (element, scalar)
7426  *  31                   21 20    16 15        10  9    5 4    0
7427  * +-----------------------+--------+-------------+------+------+
7428  * | 0 1 0 1 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
7429  * +-----------------------+--------+-------------+------+------+
7430  */
7431 static void handle_simd_dupes(DisasContext *s, int rd, int rn,
7432                               int imm5)
7433 {
7434     int size = ctz32(imm5);
7435     int index;
7436     TCGv_i64 tmp;
7437
7438     if (size > 3) {
7439         unallocated_encoding(s);
7440         return;
7441     }
7442
7443     if (!fp_access_check(s)) {
7444         return;
7445     }
7446
7447     index = imm5 >> (size + 1);
7448
7449     /* This instruction just extracts the specified element and
7450      * zero-extends it into the bottom of the destination register.
7451      */
7452     tmp = tcg_temp_new_i64();
7453     read_vec_element(s, tmp, rn, index, size);
7454     write_fp_dreg(s, rd, tmp);
7455     tcg_temp_free_i64(tmp);
7456 }
7457
7458 /* DUP (General)
7459  *
7460  *  31  30   29              21 20    16 15        10  9    5 4    0
7461  * +---+---+-------------------+--------+-------------+------+------+
7462  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 1 1 |  Rn  |  Rd  |
7463  * +---+---+-------------------+--------+-------------+------+------+
7464  *
7465  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7466  */
7467 static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn,
7468                              int imm5)
7469 {
7470     int size = ctz32(imm5);
7471     uint32_t dofs, oprsz, maxsz;
7472
7473     if (size > 3 || ((size == 3) && !is_q)) {
7474         unallocated_encoding(s);
7475         return;
7476     }
7477
7478     if (!fp_access_check(s)) {
7479         return;
7480     }
7481
7482     dofs = vec_full_reg_offset(s, rd);
7483     oprsz = is_q ? 16 : 8;
7484     maxsz = vec_full_reg_size(s);
7485
7486     tcg_gen_gvec_dup_i64(size, dofs, oprsz, maxsz, cpu_reg(s, rn));
7487 }
7488
7489 /* INS (Element)
7490  *
7491  *  31                   21 20    16 15  14    11  10 9    5 4    0
7492  * +-----------------------+--------+------------+---+------+------+
7493  * | 0 1 1 0 1 1 1 0 0 0 0 |  imm5  | 0 |  imm4  | 1 |  Rn  |  Rd  |
7494  * +-----------------------+--------+------------+---+------+------+
7495  *
7496  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7497  * index: encoded in imm5<4:size+1>
7498  */
7499 static void handle_simd_inse(DisasContext *s, int rd, int rn,
7500                              int imm4, int imm5)
7501 {
7502     int size = ctz32(imm5);
7503     int src_index, dst_index;
7504     TCGv_i64 tmp;
7505
7506     if (size > 3) {
7507         unallocated_encoding(s);
7508         return;
7509     }
7510
7511     if (!fp_access_check(s)) {
7512         return;
7513     }
7514
7515     dst_index = extract32(imm5, 1+size, 5);
7516     src_index = extract32(imm4, size, 4);
7517
7518     tmp = tcg_temp_new_i64();
7519
7520     read_vec_element(s, tmp, rn, src_index, size);
7521     write_vec_element(s, tmp, rd, dst_index, size);
7522
7523     tcg_temp_free_i64(tmp);
7524 }
7525
7526
7527 /* INS (General)
7528  *
7529  *  31                   21 20    16 15        10  9    5 4    0
7530  * +-----------------------+--------+-------------+------+------+
7531  * | 0 1 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 1 1 1 |  Rn  |  Rd  |
7532  * +-----------------------+--------+-------------+------+------+
7533  *
7534  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7535  * index: encoded in imm5<4:size+1>
7536  */
7537 static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
7538 {
7539     int size = ctz32(imm5);
7540     int idx;
7541
7542     if (size > 3) {
7543         unallocated_encoding(s);
7544         return;
7545     }
7546
7547     if (!fp_access_check(s)) {
7548         return;
7549     }
7550
7551     idx = extract32(imm5, 1 + size, 4 - size);
7552     write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
7553 }
7554
7555 /*
7556  * UMOV (General)
7557  * SMOV (General)
7558  *
7559  *  31  30   29              21 20    16 15    12   10 9    5 4    0
7560  * +---+---+-------------------+--------+-------------+------+------+
7561  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 1 U 1 1 |  Rn  |  Rd  |
7562  * +---+---+-------------------+--------+-------------+------+------+
7563  *
7564  * U: unsigned when set
7565  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7566  */
7567 static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed,
7568                                   int rn, int rd, int imm5)
7569 {
7570     int size = ctz32(imm5);
7571     int element;
7572     TCGv_i64 tcg_rd;
7573
7574     /* Check for UnallocatedEncodings */
7575     if (is_signed) {
7576         if (size > 2 || (size == 2 && !is_q)) {
7577             unallocated_encoding(s);
7578             return;
7579         }
7580     } else {
7581         if (size > 3
7582             || (size < 3 && is_q)
7583             || (size == 3 && !is_q)) {
7584             unallocated_encoding(s);
7585             return;
7586         }
7587     }
7588
7589     if (!fp_access_check(s)) {
7590         return;
7591     }
7592
7593     element = extract32(imm5, 1+size, 4);
7594
7595     tcg_rd = cpu_reg(s, rd);
7596     read_vec_element(s, tcg_rd, rn, element, size | (is_signed ? MO_SIGN : 0));
7597     if (is_signed && !is_q) {
7598         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
7599     }
7600 }
7601
7602 /* AdvSIMD copy
7603  *   31  30  29  28             21 20  16 15  14  11 10  9    5 4    0
7604  * +---+---+----+-----------------+------+---+------+---+------+------+
7605  * | 0 | Q | op | 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
7606  * +---+---+----+-----------------+------+---+------+---+------+------+
7607  */
7608 static void disas_simd_copy(DisasContext *s, uint32_t insn)
7609 {
7610     int rd = extract32(insn, 0, 5);
7611     int rn = extract32(insn, 5, 5);
7612     int imm4 = extract32(insn, 11, 4);
7613     int op = extract32(insn, 29, 1);
7614     int is_q = extract32(insn, 30, 1);
7615     int imm5 = extract32(insn, 16, 5);
7616
7617     if (op) {
7618         if (is_q) {
7619             /* INS (element) */
7620             handle_simd_inse(s, rd, rn, imm4, imm5);
7621         } else {
7622             unallocated_encoding(s);
7623         }
7624     } else {
7625         switch (imm4) {
7626         case 0:
7627             /* DUP (element - vector) */
7628             handle_simd_dupe(s, is_q, rd, rn, imm5);
7629             break;
7630         case 1:
7631             /* DUP (general) */
7632             handle_simd_dupg(s, is_q, rd, rn, imm5);
7633             break;
7634         case 3:
7635             if (is_q) {
7636                 /* INS (general) */
7637                 handle_simd_insg(s, rd, rn, imm5);
7638             } else {
7639                 unallocated_encoding(s);
7640             }
7641             break;
7642         case 5:
7643         case 7:
7644             /* UMOV/SMOV (is_q indicates 32/64; imm4 indicates signedness) */
7645             handle_simd_umov_smov(s, is_q, (imm4 == 5), rn, rd, imm5);
7646             break;
7647         default:
7648             unallocated_encoding(s);
7649             break;
7650         }
7651     }
7652 }
7653
7654 /* AdvSIMD modified immediate
7655  *  31  30   29  28                 19 18 16 15   12  11  10  9     5 4    0
7656  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
7657  * | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh |  Rd  |
7658  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
7659  *
7660  * There are a number of operations that can be carried out here:
7661  *   MOVI - move (shifted) imm into register
7662  *   MVNI - move inverted (shifted) imm into register
7663  *   ORR  - bitwise OR of (shifted) imm with register
7664  *   BIC  - bitwise clear of (shifted) imm with register
7665  * With ARMv8.2 we also have:
7666  *   FMOV half-precision
7667  */
7668 static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
7669 {
7670     int rd = extract32(insn, 0, 5);
7671     int cmode = extract32(insn, 12, 4);
7672     int cmode_3_1 = extract32(cmode, 1, 3);
7673     int cmode_0 = extract32(cmode, 0, 1);
7674     int o2 = extract32(insn, 11, 1);
7675     uint64_t abcdefgh = extract32(insn, 5, 5) | (extract32(insn, 16, 3) << 5);
7676     bool is_neg = extract32(insn, 29, 1);
7677     bool is_q = extract32(insn, 30, 1);
7678     uint64_t imm = 0;
7679
7680     if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {
7681         /* Check for FMOV (vector, immediate) - half-precision */
7682         if (!(dc_isar_feature(aa64_fp16, s) && o2 && cmode == 0xf)) {
7683             unallocated_encoding(s);
7684             return;
7685         }
7686     }
7687
7688     if (!fp_access_check(s)) {
7689         return;
7690     }
7691
7692     /* See AdvSIMDExpandImm() in ARM ARM */
7693     switch (cmode_3_1) {
7694     case 0: /* Replicate(Zeros(24):imm8, 2) */
7695     case 1: /* Replicate(Zeros(16):imm8:Zeros(8), 2) */
7696     case 2: /* Replicate(Zeros(8):imm8:Zeros(16), 2) */
7697     case 3: /* Replicate(imm8:Zeros(24), 2) */
7698     {
7699         int shift = cmode_3_1 * 8;
7700         imm = bitfield_replicate(abcdefgh << shift, 32);
7701         break;
7702     }
7703     case 4: /* Replicate(Zeros(8):imm8, 4) */
7704     case 5: /* Replicate(imm8:Zeros(8), 4) */
7705     {
7706         int shift = (cmode_3_1 & 0x1) * 8;
7707         imm = bitfield_replicate(abcdefgh << shift, 16);
7708         break;
7709     }
7710     case 6:
7711         if (cmode_0) {
7712             /* Replicate(Zeros(8):imm8:Ones(16), 2) */
7713             imm = (abcdefgh << 16) | 0xffff;
7714         } else {
7715             /* Replicate(Zeros(16):imm8:Ones(8), 2) */
7716             imm = (abcdefgh << 8) | 0xff;
7717         }
7718         imm = bitfield_replicate(imm, 32);
7719         break;
7720     case 7:
7721         if (!cmode_0 && !is_neg) {
7722             imm = bitfield_replicate(abcdefgh, 8);
7723         } else if (!cmode_0 && is_neg) {
7724             int i;
7725             imm = 0;
7726             for (i = 0; i < 8; i++) {
7727                 if ((abcdefgh) & (1 << i)) {
7728                     imm |= 0xffULL << (i * 8);
7729                 }
7730             }
7731         } else if (cmode_0) {
7732             if (is_neg) {
7733                 imm = (abcdefgh & 0x3f) << 48;
7734                 if (abcdefgh & 0x80) {
7735                     imm |= 0x8000000000000000ULL;
7736                 }
7737                 if (abcdefgh & 0x40) {
7738                     imm |= 0x3fc0000000000000ULL;
7739                 } else {
7740                     imm |= 0x4000000000000000ULL;
7741                 }
7742             } else {
7743                 if (o2) {
7744                     /* FMOV (vector, immediate) - half-precision */
7745                     imm = vfp_expand_imm(MO_16, abcdefgh);
7746                     /* now duplicate across the lanes */
7747                     imm = bitfield_replicate(imm, 16);
7748                 } else {
7749                     imm = (abcdefgh & 0x3f) << 19;
7750                     if (abcdefgh & 0x80) {
7751                         imm |= 0x80000000;
7752                     }
7753                     if (abcdefgh & 0x40) {
7754                         imm |= 0x3e000000;
7755                     } else {
7756                         imm |= 0x40000000;
7757                     }
7758                     imm |= (imm << 32);
7759                 }
7760             }
7761         }
7762         break;
7763     default:
7764         fprintf(stderr, "%s: cmode_3_1: %x\n", __func__, cmode_3_1);
7765         g_assert_not_reached();
7766     }
7767
7768     if (cmode_3_1 != 7 && is_neg) {
7769         imm = ~imm;
7770     }
7771
7772     if (!((cmode & 0x9) == 0x1 || (cmode & 0xd) == 0x9)) {
7773         /* MOVI or MVNI, with MVNI negation handled above.  */
7774         tcg_gen_gvec_dup64i(vec_full_reg_offset(s, rd), is_q ? 16 : 8,
7775                             vec_full_reg_size(s), imm);
7776     } else {
7777         /* ORR or BIC, with BIC negation to AND handled above.  */
7778         if (is_neg) {
7779             gen_gvec_fn2i(s, is_q, rd, rd, imm, tcg_gen_gvec_andi, MO_64);
7780         } else {
7781             gen_gvec_fn2i(s, is_q, rd, rd, imm, tcg_gen_gvec_ori, MO_64);
7782         }
7783     }
7784 }
7785
7786 /* AdvSIMD scalar copy
7787  *  31 30  29  28             21 20  16 15  14  11 10  9    5 4    0
7788  * +-----+----+-----------------+------+---+------+---+------+------+
7789  * | 0 1 | op | 1 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
7790  * +-----+----+-----------------+------+---+------+---+------+------+
7791  */
7792 static void disas_simd_scalar_copy(DisasContext *s, uint32_t insn)
7793 {
7794     int rd = extract32(insn, 0, 5);
7795     int rn = extract32(insn, 5, 5);
7796     int imm4 = extract32(insn, 11, 4);
7797     int imm5 = extract32(insn, 16, 5);
7798     int op = extract32(insn, 29, 1);
7799
7800     if (op != 0 || imm4 != 0) {
7801         unallocated_encoding(s);
7802         return;
7803     }
7804
7805     /* DUP (element, scalar) */
7806     handle_simd_dupes(s, rd, rn, imm5);
7807 }
7808
7809 /* AdvSIMD scalar pairwise
7810  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
7811  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7812  * | 0 1 | U | 1 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
7813  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7814  */
7815 static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
7816 {
7817     int u = extract32(insn, 29, 1);
7818     int size = extract32(insn, 22, 2);
7819     int opcode = extract32(insn, 12, 5);
7820     int rn = extract32(insn, 5, 5);
7821     int rd = extract32(insn, 0, 5);
7822     TCGv_ptr fpst;
7823
7824     /* For some ops (the FP ones), size[1] is part of the encoding.
7825      * For ADDP strictly it is not but size[1] is always 1 for valid
7826      * encodings.
7827      */
7828     opcode |= (extract32(size, 1, 1) << 5);
7829
7830     switch (opcode) {
7831     case 0x3b: /* ADDP */
7832         if (u || size != 3) {
7833             unallocated_encoding(s);
7834             return;
7835         }
7836         if (!fp_access_check(s)) {
7837             return;
7838         }
7839
7840         fpst = NULL;
7841         break;
7842     case 0xc: /* FMAXNMP */
7843     case 0xd: /* FADDP */
7844     case 0xf: /* FMAXP */
7845     case 0x2c: /* FMINNMP */
7846     case 0x2f: /* FMINP */
7847         /* FP op, size[0] is 32 or 64 bit*/
7848         if (!u) {
7849             if (!dc_isar_feature(aa64_fp16, s)) {
7850                 unallocated_encoding(s);
7851                 return;
7852             } else {
7853                 size = MO_16;
7854             }
7855         } else {
7856             size = extract32(size, 0, 1) ? MO_64 : MO_32;
7857         }
7858
7859         if (!fp_access_check(s)) {
7860             return;
7861         }
7862
7863         fpst = get_fpstatus_ptr(size == MO_16);
7864         break;
7865     default:
7866         unallocated_encoding(s);
7867         return;
7868     }
7869
7870     if (size == MO_64) {
7871         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
7872         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
7873         TCGv_i64 tcg_res = tcg_temp_new_i64();
7874
7875         read_vec_element(s, tcg_op1, rn, 0, MO_64);
7876         read_vec_element(s, tcg_op2, rn, 1, MO_64);
7877
7878         switch (opcode) {
7879         case 0x3b: /* ADDP */
7880             tcg_gen_add_i64(tcg_res, tcg_op1, tcg_op2);
7881             break;
7882         case 0xc: /* FMAXNMP */
7883             gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
7884             break;
7885         case 0xd: /* FADDP */
7886             gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
7887             break;
7888         case 0xf: /* FMAXP */
7889             gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
7890             break;
7891         case 0x2c: /* FMINNMP */
7892             gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
7893             break;
7894         case 0x2f: /* FMINP */
7895             gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
7896             break;
7897         default:
7898             g_assert_not_reached();
7899         }
7900
7901         write_fp_dreg(s, rd, tcg_res);
7902
7903         tcg_temp_free_i64(tcg_op1);
7904         tcg_temp_free_i64(tcg_op2);
7905         tcg_temp_free_i64(tcg_res);
7906     } else {
7907         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
7908         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
7909         TCGv_i32 tcg_res = tcg_temp_new_i32();
7910
7911         read_vec_element_i32(s, tcg_op1, rn, 0, size);
7912         read_vec_element_i32(s, tcg_op2, rn, 1, size);
7913
7914         if (size == MO_16) {
7915             switch (opcode) {
7916             case 0xc: /* FMAXNMP */
7917                 gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
7918                 break;
7919             case 0xd: /* FADDP */
7920                 gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
7921                 break;
7922             case 0xf: /* FMAXP */
7923                 gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
7924                 break;
7925             case 0x2c: /* FMINNMP */
7926                 gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
7927                 break;
7928             case 0x2f: /* FMINP */
7929                 gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
7930                 break;
7931             default:
7932                 g_assert_not_reached();
7933             }
7934         } else {
7935             switch (opcode) {
7936             case 0xc: /* FMAXNMP */
7937                 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
7938                 break;
7939             case 0xd: /* FADDP */
7940                 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
7941                 break;
7942             case 0xf: /* FMAXP */
7943                 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
7944                 break;
7945             case 0x2c: /* FMINNMP */
7946                 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
7947                 break;
7948             case 0x2f: /* FMINP */
7949                 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
7950                 break;
7951             default:
7952                 g_assert_not_reached();
7953             }
7954         }
7955
7956         write_fp_sreg(s, rd, tcg_res);
7957
7958         tcg_temp_free_i32(tcg_op1);
7959         tcg_temp_free_i32(tcg_op2);
7960         tcg_temp_free_i32(tcg_res);
7961     }
7962
7963     if (fpst) {
7964         tcg_temp_free_ptr(fpst);
7965     }
7966 }
7967
7968 /*
7969  * Common SSHR[RA]/USHR[RA] - Shift right (optional rounding/accumulate)
7970  *
7971  * This code is handles the common shifting code and is used by both
7972  * the vector and scalar code.
7973  */
7974 static void handle_shri_with_rndacc(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
7975                                     TCGv_i64 tcg_rnd, bool accumulate,
7976                                     bool is_u, int size, int shift)
7977 {
7978     bool extended_result = false;
7979     bool round = tcg_rnd != NULL;
7980     int ext_lshift = 0;
7981     TCGv_i64 tcg_src_hi;
7982
7983     if (round && size == 3) {
7984         extended_result = true;
7985         ext_lshift = 64 - shift;
7986         tcg_src_hi = tcg_temp_new_i64();
7987     } else if (shift == 64) {
7988         if (!accumulate && is_u) {
7989             /* result is zero */
7990             tcg_gen_movi_i64(tcg_res, 0);
7991             return;
7992         }
7993     }
7994
7995     /* Deal with the rounding step */
7996     if (round) {
7997         if (extended_result) {
7998             TCGv_i64 tcg_zero = tcg_const_i64(0);
7999             if (!is_u) {
8000                 /* take care of sign extending tcg_res */
8001                 tcg_gen_sari_i64(tcg_src_hi, tcg_src, 63);
8002                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
8003                                  tcg_src, tcg_src_hi,
8004                                  tcg_rnd, tcg_zero);
8005             } else {
8006                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
8007                                  tcg_src, tcg_zero,
8008                                  tcg_rnd, tcg_zero);
8009             }
8010             tcg_temp_free_i64(tcg_zero);
8011         } else {
8012             tcg_gen_add_i64(tcg_src, tcg_src, tcg_rnd);
8013         }
8014     }
8015
8016     /* Now do the shift right */
8017     if (round && extended_result) {
8018         /* extended case, >64 bit precision required */
8019         if (ext_lshift == 0) {
8020             /* special case, only high bits matter */
8021             tcg_gen_mov_i64(tcg_src, tcg_src_hi);
8022         } else {
8023             tcg_gen_shri_i64(tcg_src, tcg_src, shift);
8024             tcg_gen_shli_i64(tcg_src_hi, tcg_src_hi, ext_lshift);
8025             tcg_gen_or_i64(tcg_src, tcg_src, tcg_src_hi);
8026         }
8027     } else {
8028         if (is_u) {
8029             if (shift == 64) {
8030                 /* essentially shifting in 64 zeros */
8031                 tcg_gen_movi_i64(tcg_src, 0);
8032             } else {
8033                 tcg_gen_shri_i64(tcg_src, tcg_src, shift);
8034             }
8035         } else {
8036             if (shift == 64) {
8037                 /* effectively extending the sign-bit */
8038                 tcg_gen_sari_i64(tcg_src, tcg_src, 63);
8039             } else {
8040                 tcg_gen_sari_i64(tcg_src, tcg_src, shift);
8041             }
8042         }
8043     }
8044
8045     if (accumulate) {
8046         tcg_gen_add_i64(tcg_res, tcg_res, tcg_src);
8047     } else {
8048         tcg_gen_mov_i64(tcg_res, tcg_src);
8049     }
8050
8051     if (extended_result) {
8052         tcg_temp_free_i64(tcg_src_hi);
8053     }
8054 }
8055
8056 /* SSHR[RA]/USHR[RA] - Scalar shift right (optional rounding/accumulate) */
8057 static void handle_scalar_simd_shri(DisasContext *s,
8058                                     bool is_u, int immh, int immb,
8059                                     int opcode, int rn, int rd)
8060 {
8061     const int size = 3;
8062     int immhb = immh << 3 | immb;
8063     int shift = 2 * (8 << size) - immhb;
8064     bool accumulate = false;
8065     bool round = false;
8066     bool insert = false;
8067     TCGv_i64 tcg_rn;
8068     TCGv_i64 tcg_rd;
8069     TCGv_i64 tcg_round;
8070
8071     if (!extract32(immh, 3, 1)) {
8072         unallocated_encoding(s);
8073         return;
8074     }
8075
8076     if (!fp_access_check(s)) {
8077         return;
8078     }
8079
8080     switch (opcode) {
8081     case 0x02: /* SSRA / USRA (accumulate) */
8082         accumulate = true;
8083         break;
8084     case 0x04: /* SRSHR / URSHR (rounding) */
8085         round = true;
8086         break;
8087     case 0x06: /* SRSRA / URSRA (accum + rounding) */
8088         accumulate = round = true;
8089         break;
8090     case 0x08: /* SRI */
8091         insert = true;
8092         break;
8093     }
8094
8095     if (round) {
8096         uint64_t round_const = 1ULL << (shift - 1);
8097         tcg_round = tcg_const_i64(round_const);
8098     } else {
8099         tcg_round = NULL;
8100     }
8101
8102     tcg_rn = read_fp_dreg(s, rn);
8103     tcg_rd = (accumulate || insert) ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
8104
8105     if (insert) {
8106         /* shift count same as element size is valid but does nothing;
8107          * special case to avoid potential shift by 64.
8108          */
8109         int esize = 8 << size;
8110         if (shift != esize) {
8111             tcg_gen_shri_i64(tcg_rn, tcg_rn, shift);
8112             tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, 0, esize - shift);
8113         }
8114     } else {
8115         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
8116                                 accumulate, is_u, size, shift);
8117     }
8118
8119     write_fp_dreg(s, rd, tcg_rd);
8120
8121     tcg_temp_free_i64(tcg_rn);
8122     tcg_temp_free_i64(tcg_rd);
8123     if (round) {
8124         tcg_temp_free_i64(tcg_round);
8125     }
8126 }
8127
8128 /* SHL/SLI - Scalar shift left */
8129 static void handle_scalar_simd_shli(DisasContext *s, bool insert,
8130                                     int immh, int immb, int opcode,
8131                                     int rn, int rd)
8132 {
8133     int size = 32 - clz32(immh) - 1;
8134     int immhb = immh << 3 | immb;
8135     int shift = immhb - (8 << size);
8136     TCGv_i64 tcg_rn = new_tmp_a64(s);
8137     TCGv_i64 tcg_rd = new_tmp_a64(s);
8138
8139     if (!extract32(immh, 3, 1)) {
8140         unallocated_encoding(s);
8141         return;
8142     }
8143
8144     if (!fp_access_check(s)) {
8145         return;
8146     }
8147
8148     tcg_rn = read_fp_dreg(s, rn);
8149     tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
8150
8151     if (insert) {
8152         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, shift, 64 - shift);
8153     } else {
8154         tcg_gen_shli_i64(tcg_rd, tcg_rn, shift);
8155     }
8156
8157     write_fp_dreg(s, rd, tcg_rd);
8158
8159     tcg_temp_free_i64(tcg_rn);
8160     tcg_temp_free_i64(tcg_rd);
8161 }
8162
8163 /* SQSHRN/SQSHRUN - Saturating (signed/unsigned) shift right with
8164  * (signed/unsigned) narrowing */
8165 static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
8166                                    bool is_u_shift, bool is_u_narrow,
8167                                    int immh, int immb, int opcode,
8168                                    int rn, int rd)
8169 {
8170     int immhb = immh << 3 | immb;
8171     int size = 32 - clz32(immh) - 1;
8172     int esize = 8 << size;
8173     int shift = (2 * esize) - immhb;
8174     int elements = is_scalar ? 1 : (64 / esize);
8175     bool round = extract32(opcode, 0, 1);
8176     TCGMemOp ldop = (size + 1) | (is_u_shift ? 0 : MO_SIGN);
8177     TCGv_i64 tcg_rn, tcg_rd, tcg_round;
8178     TCGv_i32 tcg_rd_narrowed;
8179     TCGv_i64 tcg_final;
8180
8181     static NeonGenNarrowEnvFn * const signed_narrow_fns[4][2] = {
8182         { gen_helper_neon_narrow_sat_s8,
8183           gen_helper_neon_unarrow_sat8 },
8184         { gen_helper_neon_narrow_sat_s16,
8185           gen_helper_neon_unarrow_sat16 },
8186         { gen_helper_neon_narrow_sat_s32,
8187           gen_helper_neon_unarrow_sat32 },
8188         { NULL, NULL },
8189     };
8190     static NeonGenNarrowEnvFn * const unsigned_narrow_fns[4] = {
8191         gen_helper_neon_narrow_sat_u8,
8192         gen_helper_neon_narrow_sat_u16,
8193         gen_helper_neon_narrow_sat_u32,
8194         NULL
8195     };
8196     NeonGenNarrowEnvFn *narrowfn;
8197
8198     int i;
8199
8200     assert(size < 4);
8201
8202     if (extract32(immh, 3, 1)) {
8203         unallocated_encoding(s);
8204         return;
8205     }
8206
8207     if (!fp_access_check(s)) {
8208         return;
8209     }
8210
8211     if (is_u_shift) {
8212         narrowfn = unsigned_narrow_fns[size];
8213     } else {
8214         narrowfn = signed_narrow_fns[size][is_u_narrow ? 1 : 0];
8215     }
8216
8217     tcg_rn = tcg_temp_new_i64();
8218     tcg_rd = tcg_temp_new_i64();
8219     tcg_rd_narrowed = tcg_temp_new_i32();
8220     tcg_final = tcg_const_i64(0);
8221
8222     if (round) {
8223         uint64_t round_const = 1ULL << (shift - 1);
8224         tcg_round = tcg_const_i64(round_const);
8225     } else {
8226         tcg_round = NULL;
8227     }
8228
8229     for (i = 0; i < elements; i++) {
8230         read_vec_element(s, tcg_rn, rn, i, ldop);
8231         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
8232                                 false, is_u_shift, size+1, shift);
8233         narrowfn(tcg_rd_narrowed, cpu_env, tcg_rd);
8234         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd_narrowed);
8235         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
8236     }
8237
8238     if (!is_q) {
8239         write_vec_element(s, tcg_final, rd, 0, MO_64);
8240     } else {
8241         write_vec_element(s, tcg_final, rd, 1, MO_64);
8242     }
8243
8244     if (round) {
8245         tcg_temp_free_i64(tcg_round);
8246     }
8247     tcg_temp_free_i64(tcg_rn);
8248     tcg_temp_free_i64(tcg_rd);
8249     tcg_temp_free_i32(tcg_rd_narrowed);
8250     tcg_temp_free_i64(tcg_final);
8251
8252     clear_vec_high(s, is_q, rd);
8253 }
8254
8255 /* SQSHLU, UQSHL, SQSHL: saturating left shifts */
8256 static void handle_simd_qshl(DisasContext *s, bool scalar, bool is_q,
8257                              bool src_unsigned, bool dst_unsigned,
8258                              int immh, int immb, int rn, int rd)
8259 {
8260     int immhb = immh << 3 | immb;
8261     int size = 32 - clz32(immh) - 1;
8262     int shift = immhb - (8 << size);
8263     int pass;
8264
8265     assert(immh != 0);
8266     assert(!(scalar && is_q));
8267
8268     if (!scalar) {
8269         if (!is_q && extract32(immh, 3, 1)) {
8270             unallocated_encoding(s);
8271             return;
8272         }
8273
8274         /* Since we use the variable-shift helpers we must
8275          * replicate the shift count into each element of
8276          * the tcg_shift value.
8277          */
8278         switch (size) {
8279         case 0:
8280             shift |= shift << 8;
8281             /* fall through */
8282         case 1:
8283             shift |= shift << 16;
8284             break;
8285         case 2:
8286         case 3:
8287             break;
8288         default:
8289             g_assert_not_reached();
8290         }
8291     }
8292
8293     if (!fp_access_check(s)) {
8294         return;
8295     }
8296
8297     if (size == 3) {
8298         TCGv_i64 tcg_shift = tcg_const_i64(shift);
8299         static NeonGenTwo64OpEnvFn * const fns[2][2] = {
8300             { gen_helper_neon_qshl_s64, gen_helper_neon_qshlu_s64 },
8301             { NULL, gen_helper_neon_qshl_u64 },
8302         };
8303         NeonGenTwo64OpEnvFn *genfn = fns[src_unsigned][dst_unsigned];
8304         int maxpass = is_q ? 2 : 1;
8305
8306         for (pass = 0; pass < maxpass; pass++) {
8307             TCGv_i64 tcg_op = tcg_temp_new_i64();
8308
8309             read_vec_element(s, tcg_op, rn, pass, MO_64);
8310             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
8311             write_vec_element(s, tcg_op, rd, pass, MO_64);
8312
8313             tcg_temp_free_i64(tcg_op);
8314         }
8315         tcg_temp_free_i64(tcg_shift);
8316         clear_vec_high(s, is_q, rd);
8317     } else {
8318         TCGv_i32 tcg_shift = tcg_const_i32(shift);
8319         static NeonGenTwoOpEnvFn * const fns[2][2][3] = {
8320             {
8321                 { gen_helper_neon_qshl_s8,
8322                   gen_helper_neon_qshl_s16,
8323                   gen_helper_neon_qshl_s32 },
8324                 { gen_helper_neon_qshlu_s8,
8325                   gen_helper_neon_qshlu_s16,
8326                   gen_helper_neon_qshlu_s32 }
8327             }, {
8328                 { NULL, NULL, NULL },
8329                 { gen_helper_neon_qshl_u8,
8330                   gen_helper_neon_qshl_u16,
8331                   gen_helper_neon_qshl_u32 }
8332             }
8333         };
8334         NeonGenTwoOpEnvFn *genfn = fns[src_unsigned][dst_unsigned][size];
8335         TCGMemOp memop = scalar ? size : MO_32;
8336         int maxpass = scalar ? 1 : is_q ? 4 : 2;
8337
8338         for (pass = 0; pass < maxpass; pass++) {
8339             TCGv_i32 tcg_op = tcg_temp_new_i32();
8340
8341             read_vec_element_i32(s, tcg_op, rn, pass, memop);
8342             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
8343             if (scalar) {
8344                 switch (size) {
8345                 case 0:
8346                     tcg_gen_ext8u_i32(tcg_op, tcg_op);
8347                     break;
8348                 case 1:
8349                     tcg_gen_ext16u_i32(tcg_op, tcg_op);
8350                     break;
8351                 case 2:
8352                     break;
8353                 default:
8354                     g_assert_not_reached();
8355                 }
8356                 write_fp_sreg(s, rd, tcg_op);
8357             } else {
8358                 write_vec_element_i32(s, tcg_op, rd, pass, MO_32);
8359             }
8360
8361             tcg_temp_free_i32(tcg_op);
8362         }
8363         tcg_temp_free_i32(tcg_shift);
8364
8365         if (!scalar) {
8366             clear_vec_high(s, is_q, rd);
8367         }
8368     }
8369 }
8370
8371 /* Common vector code for handling integer to FP conversion */
8372 static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
8373                                    int elements, int is_signed,
8374                                    int fracbits, int size)
8375 {
8376     TCGv_ptr tcg_fpst = get_fpstatus_ptr(size == MO_16);
8377     TCGv_i32 tcg_shift = NULL;
8378
8379     TCGMemOp mop = size | (is_signed ? MO_SIGN : 0);
8380     int pass;
8381
8382     if (fracbits || size == MO_64) {
8383         tcg_shift = tcg_const_i32(fracbits);
8384     }
8385
8386     if (size == MO_64) {
8387         TCGv_i64 tcg_int64 = tcg_temp_new_i64();
8388         TCGv_i64 tcg_double = tcg_temp_new_i64();
8389
8390         for (pass = 0; pass < elements; pass++) {
8391             read_vec_element(s, tcg_int64, rn, pass, mop);
8392
8393             if (is_signed) {
8394                 gen_helper_vfp_sqtod(tcg_double, tcg_int64,
8395                                      tcg_shift, tcg_fpst);
8396             } else {
8397                 gen_helper_vfp_uqtod(tcg_double, tcg_int64,
8398                                      tcg_shift, tcg_fpst);
8399             }
8400             if (elements == 1) {
8401                 write_fp_dreg(s, rd, tcg_double);
8402             } else {
8403                 write_vec_element(s, tcg_double, rd, pass, MO_64);
8404             }
8405         }
8406
8407         tcg_temp_free_i64(tcg_int64);
8408         tcg_temp_free_i64(tcg_double);
8409
8410     } else {
8411         TCGv_i32 tcg_int32 = tcg_temp_new_i32();
8412         TCGv_i32 tcg_float = tcg_temp_new_i32();
8413
8414         for (pass = 0; pass < elements; pass++) {
8415             read_vec_element_i32(s, tcg_int32, rn, pass, mop);
8416
8417             switch (size) {
8418             case MO_32:
8419                 if (fracbits) {
8420                     if (is_signed) {
8421                         gen_helper_vfp_sltos(tcg_float, tcg_int32,
8422                                              tcg_shift, tcg_fpst);
8423                     } else {
8424                         gen_helper_vfp_ultos(tcg_float, tcg_int32,
8425                                              tcg_shift, tcg_fpst);
8426                     }
8427                 } else {
8428                     if (is_signed) {
8429                         gen_helper_vfp_sitos(tcg_float, tcg_int32, tcg_fpst);
8430                     } else {
8431                         gen_helper_vfp_uitos(tcg_float, tcg_int32, tcg_fpst);
8432                     }
8433                 }
8434                 break;
8435             case MO_16:
8436                 if (fracbits) {
8437                     if (is_signed) {
8438                         gen_helper_vfp_sltoh(tcg_float, tcg_int32,
8439                                              tcg_shift, tcg_fpst);
8440                     } else {
8441                         gen_helper_vfp_ultoh(tcg_float, tcg_int32,
8442                                              tcg_shift, tcg_fpst);
8443                     }
8444                 } else {
8445                     if (is_signed) {
8446                         gen_helper_vfp_sitoh(tcg_float, tcg_int32, tcg_fpst);
8447                     } else {
8448                         gen_helper_vfp_uitoh(tcg_float, tcg_int32, tcg_fpst);
8449                     }
8450                 }
8451                 break;
8452             default:
8453                 g_assert_not_reached();
8454             }
8455
8456             if (elements == 1) {
8457                 write_fp_sreg(s, rd, tcg_float);
8458             } else {
8459                 write_vec_element_i32(s, tcg_float, rd, pass, size);
8460             }
8461         }
8462
8463         tcg_temp_free_i32(tcg_int32);
8464         tcg_temp_free_i32(tcg_float);
8465     }
8466
8467     tcg_temp_free_ptr(tcg_fpst);
8468     if (tcg_shift) {
8469         tcg_temp_free_i32(tcg_shift);
8470     }
8471
8472     clear_vec_high(s, elements << size == 16, rd);
8473 }
8474
8475 /* UCVTF/SCVTF - Integer to FP conversion */
8476 static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
8477                                          bool is_q, bool is_u,
8478                                          int immh, int immb, int opcode,
8479                                          int rn, int rd)
8480 {
8481     int size, elements, fracbits;
8482     int immhb = immh << 3 | immb;
8483
8484     if (immh & 8) {
8485         size = MO_64;
8486         if (!is_scalar && !is_q) {
8487             unallocated_encoding(s);
8488             return;
8489         }
8490     } else if (immh & 4) {
8491         size = MO_32;
8492     } else if (immh & 2) {
8493         size = MO_16;
8494         if (!dc_isar_feature(aa64_fp16, s)) {
8495             unallocated_encoding(s);
8496             return;
8497         }
8498     } else {
8499         /* immh == 0 would be a failure of the decode logic */
8500         g_assert(immh == 1);
8501         unallocated_encoding(s);
8502         return;
8503     }
8504
8505     if (is_scalar) {
8506         elements = 1;
8507     } else {
8508         elements = (8 << is_q) >> size;
8509     }
8510     fracbits = (16 << size) - immhb;
8511
8512     if (!fp_access_check(s)) {
8513         return;
8514     }
8515
8516     handle_simd_intfp_conv(s, rd, rn, elements, !is_u, fracbits, size);
8517 }
8518
8519 /* FCVTZS, FVCVTZU - FP to fixedpoint conversion */
8520 static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
8521                                          bool is_q, bool is_u,
8522                                          int immh, int immb, int rn, int rd)
8523 {
8524     int immhb = immh << 3 | immb;
8525     int pass, size, fracbits;
8526     TCGv_ptr tcg_fpstatus;
8527     TCGv_i32 tcg_rmode, tcg_shift;
8528
8529     if (immh & 0x8) {
8530         size = MO_64;
8531         if (!is_scalar && !is_q) {
8532             unallocated_encoding(s);
8533             return;
8534         }
8535     } else if (immh & 0x4) {
8536         size = MO_32;
8537     } else if (immh & 0x2) {
8538         size = MO_16;
8539         if (!dc_isar_feature(aa64_fp16, s)) {
8540             unallocated_encoding(s);
8541             return;
8542         }
8543     } else {
8544         /* Should have split out AdvSIMD modified immediate earlier.  */
8545         assert(immh == 1);
8546         unallocated_encoding(s);
8547         return;
8548     }
8549
8550     if (!fp_access_check(s)) {
8551         return;
8552     }
8553
8554     assert(!(is_scalar && is_q));
8555
8556     tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
8557     tcg_fpstatus = get_fpstatus_ptr(size == MO_16);
8558     gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
8559     fracbits = (16 << size) - immhb;
8560     tcg_shift = tcg_const_i32(fracbits);
8561
8562     if (size == MO_64) {
8563         int maxpass = is_scalar ? 1 : 2;
8564
8565         for (pass = 0; pass < maxpass; pass++) {
8566             TCGv_i64 tcg_op = tcg_temp_new_i64();
8567
8568             read_vec_element(s, tcg_op, rn, pass, MO_64);
8569             if (is_u) {
8570                 gen_helper_vfp_touqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
8571             } else {
8572                 gen_helper_vfp_tosqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
8573             }
8574             write_vec_element(s, tcg_op, rd, pass, MO_64);
8575             tcg_temp_free_i64(tcg_op);
8576         }
8577         clear_vec_high(s, is_q, rd);
8578     } else {
8579         void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
8580         int maxpass = is_scalar ? 1 : ((8 << is_q) >> size);
8581
8582         switch (size) {
8583         case MO_16:
8584             if (is_u) {
8585                 fn = gen_helper_vfp_touhh;
8586             } else {
8587                 fn = gen_helper_vfp_toshh;
8588             }
8589             break;
8590         case MO_32:
8591             if (is_u) {
8592                 fn = gen_helper_vfp_touls;
8593             } else {
8594                 fn = gen_helper_vfp_tosls;
8595             }
8596             break;
8597         default:
8598             g_assert_not_reached();
8599         }
8600
8601         for (pass = 0; pass < maxpass; pass++) {
8602             TCGv_i32 tcg_op = tcg_temp_new_i32();
8603
8604             read_vec_element_i32(s, tcg_op, rn, pass, size);
8605             fn(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
8606             if (is_scalar) {
8607                 write_fp_sreg(s, rd, tcg_op);
8608             } else {
8609                 write_vec_element_i32(s, tcg_op, rd, pass, size);
8610             }
8611             tcg_temp_free_i32(tcg_op);
8612         }
8613         if (!is_scalar) {
8614             clear_vec_high(s, is_q, rd);
8615         }
8616     }
8617
8618     tcg_temp_free_ptr(tcg_fpstatus);
8619     tcg_temp_free_i32(tcg_shift);
8620     gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
8621     tcg_temp_free_i32(tcg_rmode);
8622 }
8623
8624 /* AdvSIMD scalar shift by immediate
8625  *  31 30  29 28         23 22  19 18  16 15    11  10 9    5 4    0
8626  * +-----+---+-------------+------+------+--------+---+------+------+
8627  * | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
8628  * +-----+---+-------------+------+------+--------+---+------+------+
8629  *
8630  * This is the scalar version so it works on a fixed sized registers
8631  */
8632 static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn)
8633 {
8634     int rd = extract32(insn, 0, 5);
8635     int rn = extract32(insn, 5, 5);
8636     int opcode = extract32(insn, 11, 5);
8637     int immb = extract32(insn, 16, 3);
8638     int immh = extract32(insn, 19, 4);
8639     bool is_u = extract32(insn, 29, 1);
8640
8641     if (immh == 0) {
8642         unallocated_encoding(s);
8643         return;
8644     }
8645
8646     switch (opcode) {
8647     case 0x08: /* SRI */
8648         if (!is_u) {
8649             unallocated_encoding(s);
8650             return;
8651         }
8652         /* fall through */
8653     case 0x00: /* SSHR / USHR */
8654     case 0x02: /* SSRA / USRA */
8655     case 0x04: /* SRSHR / URSHR */
8656     case 0x06: /* SRSRA / URSRA */
8657         handle_scalar_simd_shri(s, is_u, immh, immb, opcode, rn, rd);
8658         break;
8659     case 0x0a: /* SHL / SLI */
8660         handle_scalar_simd_shli(s, is_u, immh, immb, opcode, rn, rd);
8661         break;
8662     case 0x1c: /* SCVTF, UCVTF */
8663         handle_simd_shift_intfp_conv(s, true, false, is_u, immh, immb,
8664                                      opcode, rn, rd);
8665         break;
8666     case 0x10: /* SQSHRUN, SQSHRUN2 */
8667     case 0x11: /* SQRSHRUN, SQRSHRUN2 */
8668         if (!is_u) {
8669             unallocated_encoding(s);
8670             return;
8671         }
8672         handle_vec_simd_sqshrn(s, true, false, false, true,
8673                                immh, immb, opcode, rn, rd);
8674         break;
8675     case 0x12: /* SQSHRN, SQSHRN2, UQSHRN */
8676     case 0x13: /* SQRSHRN, SQRSHRN2, UQRSHRN, UQRSHRN2 */
8677         handle_vec_simd_sqshrn(s, true, false, is_u, is_u,
8678                                immh, immb, opcode, rn, rd);
8679         break;
8680     case 0xc: /* SQSHLU */
8681         if (!is_u) {
8682             unallocated_encoding(s);
8683             return;
8684         }
8685         handle_simd_qshl(s, true, false, false, true, immh, immb, rn, rd);
8686         break;
8687     case 0xe: /* SQSHL, UQSHL */
8688         handle_simd_qshl(s, true, false, is_u, is_u, immh, immb, rn, rd);
8689         break;
8690     case 0x1f: /* FCVTZS, FCVTZU */
8691         handle_simd_shift_fpint_conv(s, true, false, is_u, immh, immb, rn, rd);
8692         break;
8693     default:
8694         unallocated_encoding(s);
8695         break;
8696     }
8697 }
8698
8699 /* AdvSIMD scalar three different
8700  *  31 30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
8701  * +-----+---+-----------+------+---+------+--------+-----+------+------+
8702  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
8703  * +-----+---+-----------+------+---+------+--------+-----+------+------+
8704  */
8705 static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
8706 {
8707     bool is_u = extract32(insn, 29, 1);
8708     int size = extract32(insn, 22, 2);
8709     int opcode = extract32(insn, 12, 4);
8710     int rm = extract32(insn, 16, 5);
8711     int rn = extract32(insn, 5, 5);
8712     int rd = extract32(insn, 0, 5);
8713
8714     if (is_u) {
8715         unallocated_encoding(s);
8716         return;
8717     }
8718
8719     switch (opcode) {
8720     case 0x9: /* SQDMLAL, SQDMLAL2 */
8721     case 0xb: /* SQDMLSL, SQDMLSL2 */
8722     case 0xd: /* SQDMULL, SQDMULL2 */
8723         if (size == 0 || size == 3) {
8724             unallocated_encoding(s);
8725             return;
8726         }
8727         break;
8728     default:
8729         unallocated_encoding(s);
8730         return;
8731     }
8732
8733     if (!fp_access_check(s)) {
8734         return;
8735     }
8736
8737     if (size == 2) {
8738         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8739         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8740         TCGv_i64 tcg_res = tcg_temp_new_i64();
8741
8742         read_vec_element(s, tcg_op1, rn, 0, MO_32 | MO_SIGN);
8743         read_vec_element(s, tcg_op2, rm, 0, MO_32 | MO_SIGN);
8744
8745         tcg_gen_mul_i64(tcg_res, tcg_op1, tcg_op2);
8746         gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env, tcg_res, tcg_res);
8747
8748         switch (opcode) {
8749         case 0xd: /* SQDMULL, SQDMULL2 */
8750             break;
8751         case 0xb: /* SQDMLSL, SQDMLSL2 */
8752             tcg_gen_neg_i64(tcg_res, tcg_res);
8753             /* fall through */
8754         case 0x9: /* SQDMLAL, SQDMLAL2 */
8755             read_vec_element(s, tcg_op1, rd, 0, MO_64);
8756             gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env,
8757                                               tcg_res, tcg_op1);
8758             break;
8759         default:
8760             g_assert_not_reached();
8761         }
8762
8763         write_fp_dreg(s, rd, tcg_res);
8764
8765         tcg_temp_free_i64(tcg_op1);
8766         tcg_temp_free_i64(tcg_op2);
8767         tcg_temp_free_i64(tcg_res);
8768     } else {
8769         TCGv_i32 tcg_op1 = read_fp_hreg(s, rn);
8770         TCGv_i32 tcg_op2 = read_fp_hreg(s, rm);
8771         TCGv_i64 tcg_res = tcg_temp_new_i64();
8772
8773         gen_helper_neon_mull_s16(tcg_res, tcg_op1, tcg_op2);
8774         gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env, tcg_res, tcg_res);
8775
8776         switch (opcode) {
8777         case 0xd: /* SQDMULL, SQDMULL2 */
8778             break;
8779         case 0xb: /* SQDMLSL, SQDMLSL2 */
8780             gen_helper_neon_negl_u32(tcg_res, tcg_res);
8781             /* fall through */
8782         case 0x9: /* SQDMLAL, SQDMLAL2 */
8783         {
8784             TCGv_i64 tcg_op3 = tcg_temp_new_i64();
8785             read_vec_element(s, tcg_op3, rd, 0, MO_32);
8786             gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env,
8787                                               tcg_res, tcg_op3);
8788             tcg_temp_free_i64(tcg_op3);
8789             break;
8790         }
8791         default:
8792             g_assert_not_reached();
8793         }
8794
8795         tcg_gen_ext32u_i64(tcg_res, tcg_res);
8796         write_fp_dreg(s, rd, tcg_res);
8797
8798         tcg_temp_free_i32(tcg_op1);
8799         tcg_temp_free_i32(tcg_op2);
8800         tcg_temp_free_i64(tcg_res);
8801     }
8802 }
8803
8804 static void handle_3same_64(DisasContext *s, int opcode, bool u,
8805                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn, TCGv_i64 tcg_rm)
8806 {
8807     /* Handle 64x64->64 opcodes which are shared between the scalar
8808      * and vector 3-same groups. We cover every opcode where size == 3
8809      * is valid in either the three-reg-same (integer, not pairwise)
8810      * or scalar-three-reg-same groups.
8811      */
8812     TCGCond cond;
8813
8814     switch (opcode) {
8815     case 0x1: /* SQADD */
8816         if (u) {
8817             gen_helper_neon_qadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8818         } else {
8819             gen_helper_neon_qadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8820         }
8821         break;
8822     case 0x5: /* SQSUB */
8823         if (u) {
8824             gen_helper_neon_qsub_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8825         } else {
8826             gen_helper_neon_qsub_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8827         }
8828         break;
8829     case 0x6: /* CMGT, CMHI */
8830         /* 64 bit integer comparison, result = test ? (2^64 - 1) : 0.
8831          * We implement this using setcond (test) and then negating.
8832          */
8833         cond = u ? TCG_COND_GTU : TCG_COND_GT;
8834     do_cmop:
8835         tcg_gen_setcond_i64(cond, tcg_rd, tcg_rn, tcg_rm);
8836         tcg_gen_neg_i64(tcg_rd, tcg_rd);
8837         break;
8838     case 0x7: /* CMGE, CMHS */
8839         cond = u ? TCG_COND_GEU : TCG_COND_GE;
8840         goto do_cmop;
8841     case 0x11: /* CMTST, CMEQ */
8842         if (u) {
8843             cond = TCG_COND_EQ;
8844             goto do_cmop;
8845         }
8846         gen_cmtst_i64(tcg_rd, tcg_rn, tcg_rm);
8847         break;
8848     case 0x8: /* SSHL, USHL */
8849         if (u) {
8850             gen_helper_neon_shl_u64(tcg_rd, tcg_rn, tcg_rm);
8851         } else {
8852             gen_helper_neon_shl_s64(tcg_rd, tcg_rn, tcg_rm);
8853         }
8854         break;
8855     case 0x9: /* SQSHL, UQSHL */
8856         if (u) {
8857             gen_helper_neon_qshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8858         } else {
8859             gen_helper_neon_qshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8860         }
8861         break;
8862     case 0xa: /* SRSHL, URSHL */
8863         if (u) {
8864             gen_helper_neon_rshl_u64(tcg_rd, tcg_rn, tcg_rm);
8865         } else {
8866             gen_helper_neon_rshl_s64(tcg_rd, tcg_rn, tcg_rm);
8867         }
8868         break;
8869     case 0xb: /* SQRSHL, UQRSHL */
8870         if (u) {
8871             gen_helper_neon_qrshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8872         } else {
8873             gen_helper_neon_qrshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8874         }
8875         break;
8876     case 0x10: /* ADD, SUB */
8877         if (u) {
8878             tcg_gen_sub_i64(tcg_rd, tcg_rn, tcg_rm);
8879         } else {
8880             tcg_gen_add_i64(tcg_rd, tcg_rn, tcg_rm);
8881         }
8882         break;
8883     default:
8884         g_assert_not_reached();
8885     }
8886 }
8887
8888 /* Handle the 3-same-operands float operations; shared by the scalar
8889  * and vector encodings. The caller must filter out any encodings
8890  * not allocated for the encoding it is dealing with.
8891  */
8892 static void handle_3same_float(DisasContext *s, int size, int elements,
8893                                int fpopcode, int rd, int rn, int rm)
8894 {
8895     int pass;
8896     TCGv_ptr fpst = get_fpstatus_ptr(false);
8897
8898     for (pass = 0; pass < elements; pass++) {
8899         if (size) {
8900             /* Double */
8901             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8902             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8903             TCGv_i64 tcg_res = tcg_temp_new_i64();
8904
8905             read_vec_element(s, tcg_op1, rn, pass, MO_64);
8906             read_vec_element(s, tcg_op2, rm, pass, MO_64);
8907
8908             switch (fpopcode) {
8909             case 0x39: /* FMLS */
8910                 /* As usual for ARM, separate negation for fused multiply-add */
8911                 gen_helper_vfp_negd(tcg_op1, tcg_op1);
8912                 /* fall through */
8913             case 0x19: /* FMLA */
8914                 read_vec_element(s, tcg_res, rd, pass, MO_64);
8915                 gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2,
8916                                        tcg_res, fpst);
8917                 break;
8918             case 0x18: /* FMAXNM */
8919                 gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
8920                 break;
8921             case 0x1a: /* FADD */
8922                 gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
8923                 break;
8924             case 0x1b: /* FMULX */
8925                 gen_helper_vfp_mulxd(tcg_res, tcg_op1, tcg_op2, fpst);
8926                 break;
8927             case 0x1c: /* FCMEQ */
8928                 gen_helper_neon_ceq_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8929                 break;
8930             case 0x1e: /* FMAX */
8931                 gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
8932                 break;
8933             case 0x1f: /* FRECPS */
8934                 gen_helper_recpsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8935                 break;
8936             case 0x38: /* FMINNM */
8937                 gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
8938                 break;
8939             case 0x3a: /* FSUB */
8940                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
8941                 break;
8942             case 0x3e: /* FMIN */
8943                 gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
8944                 break;
8945             case 0x3f: /* FRSQRTS */
8946                 gen_helper_rsqrtsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8947                 break;
8948             case 0x5b: /* FMUL */
8949                 gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
8950                 break;
8951             case 0x5c: /* FCMGE */
8952                 gen_helper_neon_cge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8953                 break;
8954             case 0x5d: /* FACGE */
8955                 gen_helper_neon_acge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8956                 break;
8957             case 0x5f: /* FDIV */
8958                 gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
8959                 break;
8960             case 0x7a: /* FABD */
8961                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
8962                 gen_helper_vfp_absd(tcg_res, tcg_res);
8963                 break;
8964             case 0x7c: /* FCMGT */
8965                 gen_helper_neon_cgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8966                 break;
8967             case 0x7d: /* FACGT */
8968                 gen_helper_neon_acgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8969                 break;
8970             default:
8971                 g_assert_not_reached();
8972             }
8973
8974             write_vec_element(s, tcg_res, rd, pass, MO_64);
8975
8976             tcg_temp_free_i64(tcg_res);
8977             tcg_temp_free_i64(tcg_op1);
8978             tcg_temp_free_i64(tcg_op2);
8979         } else {
8980             /* Single */
8981             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
8982             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
8983             TCGv_i32 tcg_res = tcg_temp_new_i32();
8984
8985             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
8986             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
8987
8988             switch (fpopcode) {
8989             case 0x39: /* FMLS */
8990                 /* As usual for ARM, separate negation for fused multiply-add */
8991                 gen_helper_vfp_negs(tcg_op1, tcg_op1);
8992                 /* fall through */
8993             case 0x19: /* FMLA */
8994                 read_vec_element_i32(s, tcg_res, rd, pass, MO_32);
8995                 gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2,
8996                                        tcg_res, fpst);
8997                 break;
8998             case 0x1a: /* FADD */
8999                 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
9000                 break;
9001             case 0x1b: /* FMULX */
9002                 gen_helper_vfp_mulxs(tcg_res, tcg_op1, tcg_op2, fpst);
9003                 break;
9004             case 0x1c: /* FCMEQ */
9005                 gen_helper_neon_ceq_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9006                 break;
9007             case 0x1e: /* FMAX */
9008                 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
9009                 break;
9010             case 0x1f: /* FRECPS */
9011                 gen_helper_recpsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9012                 break;
9013             case 0x18: /* FMAXNM */
9014                 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
9015                 break;
9016             case 0x38: /* FMINNM */
9017                 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
9018                 break;
9019             case 0x3a: /* FSUB */
9020                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
9021                 break;
9022             case 0x3e: /* FMIN */
9023                 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
9024                 break;
9025             case 0x3f: /* FRSQRTS */
9026                 gen_helper_rsqrtsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9027                 break;
9028             case 0x5b: /* FMUL */
9029                 gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
9030                 break;
9031             case 0x5c: /* FCMGE */
9032                 gen_helper_neon_cge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9033                 break;
9034             case 0x5d: /* FACGE */
9035                 gen_helper_neon_acge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9036                 break;
9037             case 0x5f: /* FDIV */
9038                 gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
9039                 break;
9040             case 0x7a: /* FABD */
9041                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
9042                 gen_helper_vfp_abss(tcg_res, tcg_res);
9043                 break;
9044             case 0x7c: /* FCMGT */
9045                 gen_helper_neon_cgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9046                 break;
9047             case 0x7d: /* FACGT */
9048                 gen_helper_neon_acgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9049                 break;
9050             default:
9051                 g_assert_not_reached();
9052             }
9053
9054             if (elements == 1) {
9055                 /* scalar single so clear high part */
9056                 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
9057
9058                 tcg_gen_extu_i32_i64(tcg_tmp, tcg_res);
9059                 write_vec_element(s, tcg_tmp, rd, pass, MO_64);
9060                 tcg_temp_free_i64(tcg_tmp);
9061             } else {
9062                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
9063             }
9064
9065             tcg_temp_free_i32(tcg_res);
9066             tcg_temp_free_i32(tcg_op1);
9067             tcg_temp_free_i32(tcg_op2);
9068         }
9069     }
9070
9071     tcg_temp_free_ptr(fpst);
9072
9073     clear_vec_high(s, elements * (size ? 8 : 4) > 8, rd);
9074 }
9075
9076 /* AdvSIMD scalar three same
9077  *  31 30  29 28       24 23  22  21 20  16 15    11  10 9    5 4    0
9078  * +-----+---+-----------+------+---+------+--------+---+------+------+
9079  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
9080  * +-----+---+-----------+------+---+------+--------+---+------+------+
9081  */
9082 static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
9083 {
9084     int rd = extract32(insn, 0, 5);
9085     int rn = extract32(insn, 5, 5);
9086     int opcode = extract32(insn, 11, 5);
9087     int rm = extract32(insn, 16, 5);
9088     int size = extract32(insn, 22, 2);
9089     bool u = extract32(insn, 29, 1);
9090     TCGv_i64 tcg_rd;
9091
9092     if (opcode >= 0x18) {
9093         /* Floating point: U, size[1] and opcode indicate operation */
9094         int fpopcode = opcode | (extract32(size, 1, 1) << 5) | (u << 6);
9095         switch (fpopcode) {
9096         case 0x1b: /* FMULX */
9097         case 0x1f: /* FRECPS */
9098         case 0x3f: /* FRSQRTS */
9099         case 0x5d: /* FACGE */
9100         case 0x7d: /* FACGT */
9101         case 0x1c: /* FCMEQ */
9102         case 0x5c: /* FCMGE */
9103         case 0x7c: /* FCMGT */
9104         case 0x7a: /* FABD */
9105             break;
9106         default:
9107             unallocated_encoding(s);
9108             return;
9109         }
9110
9111         if (!fp_access_check(s)) {
9112             return;
9113         }
9114
9115         handle_3same_float(s, extract32(size, 0, 1), 1, fpopcode, rd, rn, rm);
9116         return;
9117     }
9118
9119     switch (opcode) {
9120     case 0x1: /* SQADD, UQADD */
9121     case 0x5: /* SQSUB, UQSUB */
9122     case 0x9: /* SQSHL, UQSHL */
9123     case 0xb: /* SQRSHL, UQRSHL */
9124         break;
9125     case 0x8: /* SSHL, USHL */
9126     case 0xa: /* SRSHL, URSHL */
9127     case 0x6: /* CMGT, CMHI */
9128     case 0x7: /* CMGE, CMHS */
9129     case 0x11: /* CMTST, CMEQ */
9130     case 0x10: /* ADD, SUB (vector) */
9131         if (size != 3) {
9132             unallocated_encoding(s);
9133             return;
9134         }
9135         break;
9136     case 0x16: /* SQDMULH, SQRDMULH (vector) */
9137         if (size != 1 && size != 2) {
9138             unallocated_encoding(s);
9139             return;
9140         }
9141         break;
9142     default:
9143         unallocated_encoding(s);
9144         return;
9145     }
9146
9147     if (!fp_access_check(s)) {
9148         return;
9149     }
9150
9151     tcg_rd = tcg_temp_new_i64();
9152
9153     if (size == 3) {
9154         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
9155         TCGv_i64 tcg_rm = read_fp_dreg(s, rm);
9156
9157         handle_3same_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rm);
9158         tcg_temp_free_i64(tcg_rn);
9159         tcg_temp_free_i64(tcg_rm);
9160     } else {
9161         /* Do a single operation on the lowest element in the vector.
9162          * We use the standard Neon helpers and rely on 0 OP 0 == 0 with
9163          * no side effects for all these operations.
9164          * OPTME: special-purpose helpers would avoid doing some
9165          * unnecessary work in the helper for the 8 and 16 bit cases.
9166          */
9167         NeonGenTwoOpEnvFn *genenvfn;
9168         TCGv_i32 tcg_rn = tcg_temp_new_i32();
9169         TCGv_i32 tcg_rm = tcg_temp_new_i32();
9170         TCGv_i32 tcg_rd32 = tcg_temp_new_i32();
9171
9172         read_vec_element_i32(s, tcg_rn, rn, 0, size);
9173         read_vec_element_i32(s, tcg_rm, rm, 0, size);
9174
9175         switch (opcode) {
9176         case 0x1: /* SQADD, UQADD */
9177         {
9178             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9179                 { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 },
9180                 { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 },
9181                 { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 },
9182             };
9183             genenvfn = fns[size][u];
9184             break;
9185         }
9186         case 0x5: /* SQSUB, UQSUB */
9187         {
9188             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9189                 { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 },
9190                 { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 },
9191                 { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 },
9192             };
9193             genenvfn = fns[size][u];
9194             break;
9195         }
9196         case 0x9: /* SQSHL, UQSHL */
9197         {
9198             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9199                 { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
9200                 { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
9201                 { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
9202             };
9203             genenvfn = fns[size][u];
9204             break;
9205         }
9206         case 0xb: /* SQRSHL, UQRSHL */
9207         {
9208             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9209                 { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
9210                 { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
9211                 { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
9212             };
9213             genenvfn = fns[size][u];
9214             break;
9215         }
9216         case 0x16: /* SQDMULH, SQRDMULH */
9217         {
9218             static NeonGenTwoOpEnvFn * const fns[2][2] = {
9219                 { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
9220                 { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
9221             };
9222             assert(size == 1 || size == 2);
9223             genenvfn = fns[size - 1][u];
9224             break;
9225         }
9226         default:
9227             g_assert_not_reached();
9228         }
9229
9230         genenvfn(tcg_rd32, cpu_env, tcg_rn, tcg_rm);
9231         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd32);
9232         tcg_temp_free_i32(tcg_rd32);
9233         tcg_temp_free_i32(tcg_rn);
9234         tcg_temp_free_i32(tcg_rm);
9235     }
9236
9237     write_fp_dreg(s, rd, tcg_rd);
9238
9239     tcg_temp_free_i64(tcg_rd);
9240 }
9241
9242 /* AdvSIMD scalar three same FP16
9243  *  31 30  29 28       24 23  22 21 20  16 15 14 13    11 10  9  5 4  0
9244  * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
9245  * | 0 1 | U | 1 1 1 1 0 | a | 1 0 |  Rm  | 0 0 | opcode | 1 | Rn | Rd |
9246  * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
9247  * v: 0101 1110 0100 0000 0000 0100 0000 0000 => 5e400400
9248  * m: 1101 1111 0110 0000 1100 0100 0000 0000 => df60c400
9249  */
9250 static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
9251                                                   uint32_t insn)
9252 {
9253     int rd = extract32(insn, 0, 5);
9254     int rn = extract32(insn, 5, 5);
9255     int opcode = extract32(insn, 11, 3);
9256     int rm = extract32(insn, 16, 5);
9257     bool u = extract32(insn, 29, 1);
9258     bool a = extract32(insn, 23, 1);
9259     int fpopcode = opcode | (a << 3) |  (u << 4);
9260     TCGv_ptr fpst;
9261     TCGv_i32 tcg_op1;
9262     TCGv_i32 tcg_op2;
9263     TCGv_i32 tcg_res;
9264
9265     switch (fpopcode) {
9266     case 0x03: /* FMULX */
9267     case 0x04: /* FCMEQ (reg) */
9268     case 0x07: /* FRECPS */
9269     case 0x0f: /* FRSQRTS */
9270     case 0x14: /* FCMGE (reg) */
9271     case 0x15: /* FACGE */
9272     case 0x1a: /* FABD */
9273     case 0x1c: /* FCMGT (reg) */
9274     case 0x1d: /* FACGT */
9275         break;
9276     default:
9277         unallocated_encoding(s);
9278         return;
9279     }
9280
9281     if (!dc_isar_feature(aa64_fp16, s)) {
9282         unallocated_encoding(s);
9283     }
9284
9285     if (!fp_access_check(s)) {
9286         return;
9287     }
9288
9289     fpst = get_fpstatus_ptr(true);
9290
9291     tcg_op1 = read_fp_hreg(s, rn);
9292     tcg_op2 = read_fp_hreg(s, rm);
9293     tcg_res = tcg_temp_new_i32();
9294
9295     switch (fpopcode) {
9296     case 0x03: /* FMULX */
9297         gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
9298         break;
9299     case 0x04: /* FCMEQ (reg) */
9300         gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9301         break;
9302     case 0x07: /* FRECPS */
9303         gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9304         break;
9305     case 0x0f: /* FRSQRTS */
9306         gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9307         break;
9308     case 0x14: /* FCMGE (reg) */
9309         gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9310         break;
9311     case 0x15: /* FACGE */
9312         gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9313         break;
9314     case 0x1a: /* FABD */
9315         gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
9316         tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
9317         break;
9318     case 0x1c: /* FCMGT (reg) */
9319         gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9320         break;
9321     case 0x1d: /* FACGT */
9322         gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9323         break;
9324     default:
9325         g_assert_not_reached();
9326     }
9327
9328     write_fp_sreg(s, rd, tcg_res);
9329
9330
9331     tcg_temp_free_i32(tcg_res);
9332     tcg_temp_free_i32(tcg_op1);
9333     tcg_temp_free_i32(tcg_op2);
9334     tcg_temp_free_ptr(fpst);
9335 }
9336
9337 /* AdvSIMD scalar three same extra
9338  *  31 30  29 28       24 23  22  21 20  16  15 14    11  10 9  5 4  0
9339  * +-----+---+-----------+------+---+------+---+--------+---+----+----+
9340  * | 0 1 | U | 1 1 1 1 0 | size | 0 |  Rm  | 1 | opcode | 1 | Rn | Rd |
9341  * +-----+---+-----------+------+---+------+---+--------+---+----+----+
9342  */
9343 static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
9344                                                    uint32_t insn)
9345 {
9346     int rd = extract32(insn, 0, 5);
9347     int rn = extract32(insn, 5, 5);
9348     int opcode = extract32(insn, 11, 4);
9349     int rm = extract32(insn, 16, 5);
9350     int size = extract32(insn, 22, 2);
9351     bool u = extract32(insn, 29, 1);
9352     TCGv_i32 ele1, ele2, ele3;
9353     TCGv_i64 res;
9354     bool feature;
9355
9356     switch (u * 16 + opcode) {
9357     case 0x10: /* SQRDMLAH (vector) */
9358     case 0x11: /* SQRDMLSH (vector) */
9359         if (size != 1 && size != 2) {
9360             unallocated_encoding(s);
9361             return;
9362         }
9363         feature = dc_isar_feature(aa64_rdm, s);
9364         break;
9365     default:
9366         unallocated_encoding(s);
9367         return;
9368     }
9369     if (!feature) {
9370         unallocated_encoding(s);
9371         return;
9372     }
9373     if (!fp_access_check(s)) {
9374         return;
9375     }
9376
9377     /* Do a single operation on the lowest element in the vector.
9378      * We use the standard Neon helpers and rely on 0 OP 0 == 0
9379      * with no side effects for all these operations.
9380      * OPTME: special-purpose helpers would avoid doing some
9381      * unnecessary work in the helper for the 16 bit cases.
9382      */
9383     ele1 = tcg_temp_new_i32();
9384     ele2 = tcg_temp_new_i32();
9385     ele3 = tcg_temp_new_i32();
9386
9387     read_vec_element_i32(s, ele1, rn, 0, size);
9388     read_vec_element_i32(s, ele2, rm, 0, size);
9389     read_vec_element_i32(s, ele3, rd, 0, size);
9390
9391     switch (opcode) {
9392     case 0x0: /* SQRDMLAH */
9393         if (size == 1) {
9394             gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
9395         } else {
9396             gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
9397         }
9398         break;
9399     case 0x1: /* SQRDMLSH */
9400         if (size == 1) {
9401             gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
9402         } else {
9403             gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
9404         }
9405         break;
9406     default:
9407         g_assert_not_reached();
9408     }
9409     tcg_temp_free_i32(ele1);
9410     tcg_temp_free_i32(ele2);
9411
9412     res = tcg_temp_new_i64();
9413     tcg_gen_extu_i32_i64(res, ele3);
9414     tcg_temp_free_i32(ele3);
9415
9416     write_fp_dreg(s, rd, res);
9417     tcg_temp_free_i64(res);
9418 }
9419
9420 static void handle_2misc_64(DisasContext *s, int opcode, bool u,
9421                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
9422                             TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
9423 {
9424     /* Handle 64->64 opcodes which are shared between the scalar and
9425      * vector 2-reg-misc groups. We cover every integer opcode where size == 3
9426      * is valid in either group and also the double-precision fp ops.
9427      * The caller only need provide tcg_rmode and tcg_fpstatus if the op
9428      * requires them.
9429      */
9430     TCGCond cond;
9431
9432     switch (opcode) {
9433     case 0x4: /* CLS, CLZ */
9434         if (u) {
9435             tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
9436         } else {
9437             tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
9438         }
9439         break;
9440     case 0x5: /* NOT */
9441         /* This opcode is shared with CNT and RBIT but we have earlier
9442          * enforced that size == 3 if and only if this is the NOT insn.
9443          */
9444         tcg_gen_not_i64(tcg_rd, tcg_rn);
9445         break;
9446     case 0x7: /* SQABS, SQNEG */
9447         if (u) {
9448             gen_helper_neon_qneg_s64(tcg_rd, cpu_env, tcg_rn);
9449         } else {
9450             gen_helper_neon_qabs_s64(tcg_rd, cpu_env, tcg_rn);
9451         }
9452         break;
9453     case 0xa: /* CMLT */
9454         /* 64 bit integer comparison against zero, result is
9455          * test ? (2^64 - 1) : 0. We implement via setcond(!test) and
9456          * subtracting 1.
9457          */
9458         cond = TCG_COND_LT;
9459     do_cmop:
9460         tcg_gen_setcondi_i64(cond, tcg_rd, tcg_rn, 0);
9461         tcg_gen_neg_i64(tcg_rd, tcg_rd);
9462         break;
9463     case 0x8: /* CMGT, CMGE */
9464         cond = u ? TCG_COND_GE : TCG_COND_GT;
9465         goto do_cmop;
9466     case 0x9: /* CMEQ, CMLE */
9467         cond = u ? TCG_COND_LE : TCG_COND_EQ;
9468         goto do_cmop;
9469     case 0xb: /* ABS, NEG */
9470         if (u) {
9471             tcg_gen_neg_i64(tcg_rd, tcg_rn);
9472         } else {
9473             tcg_gen_abs_i64(tcg_rd, tcg_rn);
9474         }
9475         break;
9476     case 0x2f: /* FABS */
9477         gen_helper_vfp_absd(tcg_rd, tcg_rn);
9478         break;
9479     case 0x6f: /* FNEG */
9480         gen_helper_vfp_negd(tcg_rd, tcg_rn);
9481         break;
9482     case 0x7f: /* FSQRT */
9483         gen_helper_vfp_sqrtd(tcg_rd, tcg_rn, cpu_env);
9484         break;
9485     case 0x1a: /* FCVTNS */
9486     case 0x1b: /* FCVTMS */
9487     case 0x1c: /* FCVTAS */
9488     case 0x3a: /* FCVTPS */
9489     case 0x3b: /* FCVTZS */
9490     {
9491         TCGv_i32 tcg_shift = tcg_const_i32(0);
9492         gen_helper_vfp_tosqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
9493         tcg_temp_free_i32(tcg_shift);
9494         break;
9495     }
9496     case 0x5a: /* FCVTNU */
9497     case 0x5b: /* FCVTMU */
9498     case 0x5c: /* FCVTAU */
9499     case 0x7a: /* FCVTPU */
9500     case 0x7b: /* FCVTZU */
9501     {
9502         TCGv_i32 tcg_shift = tcg_const_i32(0);
9503         gen_helper_vfp_touqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
9504         tcg_temp_free_i32(tcg_shift);
9505         break;
9506     }
9507     case 0x18: /* FRINTN */
9508     case 0x19: /* FRINTM */
9509     case 0x38: /* FRINTP */
9510     case 0x39: /* FRINTZ */
9511     case 0x58: /* FRINTA */
9512     case 0x79: /* FRINTI */
9513         gen_helper_rintd(tcg_rd, tcg_rn, tcg_fpstatus);
9514         break;
9515     case 0x59: /* FRINTX */
9516         gen_helper_rintd_exact(tcg_rd, tcg_rn, tcg_fpstatus);
9517         break;
9518     case 0x1e: /* FRINT32Z */
9519     case 0x5e: /* FRINT32X */
9520         gen_helper_frint32_d(tcg_rd, tcg_rn, tcg_fpstatus);
9521         break;
9522     case 0x1f: /* FRINT64Z */
9523     case 0x5f: /* FRINT64X */
9524         gen_helper_frint64_d(tcg_rd, tcg_rn, tcg_fpstatus);
9525         break;
9526     default:
9527         g_assert_not_reached();
9528     }
9529 }
9530
9531 static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
9532                                    bool is_scalar, bool is_u, bool is_q,
9533                                    int size, int rn, int rd)
9534 {
9535     bool is_double = (size == MO_64);
9536     TCGv_ptr fpst;
9537
9538     if (!fp_access_check(s)) {
9539         return;
9540     }
9541
9542     fpst = get_fpstatus_ptr(size == MO_16);
9543
9544     if (is_double) {
9545         TCGv_i64 tcg_op = tcg_temp_new_i64();
9546         TCGv_i64 tcg_zero = tcg_const_i64(0);
9547         TCGv_i64 tcg_res = tcg_temp_new_i64();
9548         NeonGenTwoDoubleOPFn *genfn;
9549         bool swap = false;
9550         int pass;
9551
9552         switch (opcode) {
9553         case 0x2e: /* FCMLT (zero) */
9554             swap = true;
9555             /* fallthrough */
9556         case 0x2c: /* FCMGT (zero) */
9557             genfn = gen_helper_neon_cgt_f64;
9558             break;
9559         case 0x2d: /* FCMEQ (zero) */
9560             genfn = gen_helper_neon_ceq_f64;
9561             break;
9562         case 0x6d: /* FCMLE (zero) */
9563             swap = true;
9564             /* fall through */
9565         case 0x6c: /* FCMGE (zero) */
9566             genfn = gen_helper_neon_cge_f64;
9567             break;
9568         default:
9569             g_assert_not_reached();
9570         }
9571
9572         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9573             read_vec_element(s, tcg_op, rn, pass, MO_64);
9574             if (swap) {
9575                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
9576             } else {
9577                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
9578             }
9579             write_vec_element(s, tcg_res, rd, pass, MO_64);
9580         }
9581         tcg_temp_free_i64(tcg_res);
9582         tcg_temp_free_i64(tcg_zero);
9583         tcg_temp_free_i64(tcg_op);
9584
9585         clear_vec_high(s, !is_scalar, rd);
9586     } else {
9587         TCGv_i32 tcg_op = tcg_temp_new_i32();
9588         TCGv_i32 tcg_zero = tcg_const_i32(0);
9589         TCGv_i32 tcg_res = tcg_temp_new_i32();
9590         NeonGenTwoSingleOPFn *genfn;
9591         bool swap = false;
9592         int pass, maxpasses;
9593
9594         if (size == MO_16) {
9595             switch (opcode) {
9596             case 0x2e: /* FCMLT (zero) */
9597                 swap = true;
9598                 /* fall through */
9599             case 0x2c: /* FCMGT (zero) */
9600                 genfn = gen_helper_advsimd_cgt_f16;
9601                 break;
9602             case 0x2d: /* FCMEQ (zero) */
9603                 genfn = gen_helper_advsimd_ceq_f16;
9604                 break;
9605             case 0x6d: /* FCMLE (zero) */
9606                 swap = true;
9607                 /* fall through */
9608             case 0x6c: /* FCMGE (zero) */
9609                 genfn = gen_helper_advsimd_cge_f16;
9610                 break;
9611             default:
9612                 g_assert_not_reached();
9613             }
9614         } else {
9615             switch (opcode) {
9616             case 0x2e: /* FCMLT (zero) */
9617                 swap = true;
9618                 /* fall through */
9619             case 0x2c: /* FCMGT (zero) */
9620                 genfn = gen_helper_neon_cgt_f32;
9621                 break;
9622             case 0x2d: /* FCMEQ (zero) */
9623                 genfn = gen_helper_neon_ceq_f32;
9624                 break;
9625             case 0x6d: /* FCMLE (zero) */
9626                 swap = true;
9627                 /* fall through */
9628             case 0x6c: /* FCMGE (zero) */
9629                 genfn = gen_helper_neon_cge_f32;
9630                 break;
9631             default:
9632                 g_assert_not_reached();
9633             }
9634         }
9635
9636         if (is_scalar) {
9637             maxpasses = 1;
9638         } else {
9639             int vector_size = 8 << is_q;
9640             maxpasses = vector_size >> size;
9641         }
9642
9643         for (pass = 0; pass < maxpasses; pass++) {
9644             read_vec_element_i32(s, tcg_op, rn, pass, size);
9645             if (swap) {
9646                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
9647             } else {
9648                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
9649             }
9650             if (is_scalar) {
9651                 write_fp_sreg(s, rd, tcg_res);
9652             } else {
9653                 write_vec_element_i32(s, tcg_res, rd, pass, size);
9654             }
9655         }
9656         tcg_temp_free_i32(tcg_res);
9657         tcg_temp_free_i32(tcg_zero);
9658         tcg_temp_free_i32(tcg_op);
9659         if (!is_scalar) {
9660             clear_vec_high(s, is_q, rd);
9661         }
9662     }
9663
9664     tcg_temp_free_ptr(fpst);
9665 }
9666
9667 static void handle_2misc_reciprocal(DisasContext *s, int opcode,
9668                                     bool is_scalar, bool is_u, bool is_q,
9669                                     int size, int rn, int rd)
9670 {
9671     bool is_double = (size == 3);
9672     TCGv_ptr fpst = get_fpstatus_ptr(false);
9673
9674     if (is_double) {
9675         TCGv_i64 tcg_op = tcg_temp_new_i64();
9676         TCGv_i64 tcg_res = tcg_temp_new_i64();
9677         int pass;
9678
9679         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9680             read_vec_element(s, tcg_op, rn, pass, MO_64);
9681             switch (opcode) {
9682             case 0x3d: /* FRECPE */
9683                 gen_helper_recpe_f64(tcg_res, tcg_op, fpst);
9684                 break;
9685             case 0x3f: /* FRECPX */
9686                 gen_helper_frecpx_f64(tcg_res, tcg_op, fpst);
9687                 break;
9688             case 0x7d: /* FRSQRTE */
9689                 gen_helper_rsqrte_f64(tcg_res, tcg_op, fpst);
9690                 break;
9691             default:
9692                 g_assert_not_reached();
9693             }
9694             write_vec_element(s, tcg_res, rd, pass, MO_64);
9695         }
9696         tcg_temp_free_i64(tcg_res);
9697         tcg_temp_free_i64(tcg_op);
9698         clear_vec_high(s, !is_scalar, rd);
9699     } else {
9700         TCGv_i32 tcg_op = tcg_temp_new_i32();
9701         TCGv_i32 tcg_res = tcg_temp_new_i32();
9702         int pass, maxpasses;
9703
9704         if (is_scalar) {
9705             maxpasses = 1;
9706         } else {
9707             maxpasses = is_q ? 4 : 2;
9708         }
9709
9710         for (pass = 0; pass < maxpasses; pass++) {
9711             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
9712
9713             switch (opcode) {
9714             case 0x3c: /* URECPE */
9715                 gen_helper_recpe_u32(tcg_res, tcg_op, fpst);
9716                 break;
9717             case 0x3d: /* FRECPE */
9718                 gen_helper_recpe_f32(tcg_res, tcg_op, fpst);
9719                 break;
9720             case 0x3f: /* FRECPX */
9721                 gen_helper_frecpx_f32(tcg_res, tcg_op, fpst);
9722                 break;
9723             case 0x7d: /* FRSQRTE */
9724                 gen_helper_rsqrte_f32(tcg_res, tcg_op, fpst);
9725                 break;
9726             default:
9727                 g_assert_not_reached();
9728             }
9729
9730             if (is_scalar) {
9731                 write_fp_sreg(s, rd, tcg_res);
9732             } else {
9733                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
9734             }
9735         }
9736         tcg_temp_free_i32(tcg_res);
9737         tcg_temp_free_i32(tcg_op);
9738         if (!is_scalar) {
9739             clear_vec_high(s, is_q, rd);
9740         }
9741     }
9742     tcg_temp_free_ptr(fpst);
9743 }
9744
9745 static void handle_2misc_narrow(DisasContext *s, bool scalar,
9746                                 int opcode, bool u, bool is_q,
9747                                 int size, int rn, int rd)
9748 {
9749     /* Handle 2-reg-misc ops which are narrowing (so each 2*size element
9750      * in the source becomes a size element in the destination).
9751      */
9752     int pass;
9753     TCGv_i32 tcg_res[2];
9754     int destelt = is_q ? 2 : 0;
9755     int passes = scalar ? 1 : 2;
9756
9757     if (scalar) {
9758         tcg_res[1] = tcg_const_i32(0);
9759     }
9760
9761     for (pass = 0; pass < passes; pass++) {
9762         TCGv_i64 tcg_op = tcg_temp_new_i64();
9763         NeonGenNarrowFn *genfn = NULL;
9764         NeonGenNarrowEnvFn *genenvfn = NULL;
9765
9766         if (scalar) {
9767             read_vec_element(s, tcg_op, rn, pass, size + 1);
9768         } else {
9769             read_vec_element(s, tcg_op, rn, pass, MO_64);
9770         }
9771         tcg_res[pass] = tcg_temp_new_i32();
9772
9773         switch (opcode) {
9774         case 0x12: /* XTN, SQXTUN */
9775         {
9776             static NeonGenNarrowFn * const xtnfns[3] = {
9777                 gen_helper_neon_narrow_u8,
9778                 gen_helper_neon_narrow_u16,
9779                 tcg_gen_extrl_i64_i32,
9780             };
9781             static NeonGenNarrowEnvFn * const sqxtunfns[3] = {
9782                 gen_helper_neon_unarrow_sat8,
9783                 gen_helper_neon_unarrow_sat16,
9784                 gen_helper_neon_unarrow_sat32,
9785             };
9786             if (u) {
9787                 genenvfn = sqxtunfns[size];
9788             } else {
9789                 genfn = xtnfns[size];
9790             }
9791             break;
9792         }
9793         case 0x14: /* SQXTN, UQXTN */
9794         {
9795             static NeonGenNarrowEnvFn * const fns[3][2] = {
9796                 { gen_helper_neon_narrow_sat_s8,
9797                   gen_helper_neon_narrow_sat_u8 },
9798                 { gen_helper_neon_narrow_sat_s16,
9799                   gen_helper_neon_narrow_sat_u16 },
9800                 { gen_helper_neon_narrow_sat_s32,
9801                   gen_helper_neon_narrow_sat_u32 },
9802             };
9803             genenvfn = fns[size][u];
9804             break;
9805         }
9806         case 0x16: /* FCVTN, FCVTN2 */
9807             /* 32 bit to 16 bit or 64 bit to 32 bit float conversion */
9808             if (size == 2) {
9809                 gen_helper_vfp_fcvtsd(tcg_res[pass], tcg_op, cpu_env);
9810             } else {
9811                 TCGv_i32 tcg_lo = tcg_temp_new_i32();
9812                 TCGv_i32 tcg_hi = tcg_temp_new_i32();
9813                 TCGv_ptr fpst = get_fpstatus_ptr(false);
9814                 TCGv_i32 ahp = get_ahp_flag();
9815
9816                 tcg_gen_extr_i64_i32(tcg_lo, tcg_hi, tcg_op);
9817                 gen_helper_vfp_fcvt_f32_to_f16(tcg_lo, tcg_lo, fpst, ahp);
9818                 gen_helper_vfp_fcvt_f32_to_f16(tcg_hi, tcg_hi, fpst, ahp);
9819                 tcg_gen_deposit_i32(tcg_res[pass], tcg_lo, tcg_hi, 16, 16);
9820                 tcg_temp_free_i32(tcg_lo);
9821                 tcg_temp_free_i32(tcg_hi);
9822                 tcg_temp_free_ptr(fpst);
9823                 tcg_temp_free_i32(ahp);
9824             }
9825             break;
9826         case 0x56:  /* FCVTXN, FCVTXN2 */
9827             /* 64 bit to 32 bit float conversion
9828              * with von Neumann rounding (round to odd)
9829              */
9830             assert(size == 2);
9831             gen_helper_fcvtx_f64_to_f32(tcg_res[pass], tcg_op, cpu_env);
9832             break;
9833         default:
9834             g_assert_not_reached();
9835         }
9836
9837         if (genfn) {
9838             genfn(tcg_res[pass], tcg_op);
9839         } else if (genenvfn) {
9840             genenvfn(tcg_res[pass], cpu_env, tcg_op);
9841         }
9842
9843         tcg_temp_free_i64(tcg_op);
9844     }
9845
9846     for (pass = 0; pass < 2; pass++) {
9847         write_vec_element_i32(s, tcg_res[pass], rd, destelt + pass, MO_32);
9848         tcg_temp_free_i32(tcg_res[pass]);
9849     }
9850     clear_vec_high(s, is_q, rd);
9851 }
9852
9853 /* Remaining saturating accumulating ops */
9854 static void handle_2misc_satacc(DisasContext *s, bool is_scalar, bool is_u,
9855                                 bool is_q, int size, int rn, int rd)
9856 {
9857     bool is_double = (size == 3);
9858
9859     if (is_double) {
9860         TCGv_i64 tcg_rn = tcg_temp_new_i64();
9861         TCGv_i64 tcg_rd = tcg_temp_new_i64();
9862         int pass;
9863
9864         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9865             read_vec_element(s, tcg_rn, rn, pass, MO_64);
9866             read_vec_element(s, tcg_rd, rd, pass, MO_64);
9867
9868             if (is_u) { /* USQADD */
9869                 gen_helper_neon_uqadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9870             } else { /* SUQADD */
9871                 gen_helper_neon_sqadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9872             }
9873             write_vec_element(s, tcg_rd, rd, pass, MO_64);
9874         }
9875         tcg_temp_free_i64(tcg_rd);
9876         tcg_temp_free_i64(tcg_rn);
9877         clear_vec_high(s, !is_scalar, rd);
9878     } else {
9879         TCGv_i32 tcg_rn = tcg_temp_new_i32();
9880         TCGv_i32 tcg_rd = tcg_temp_new_i32();
9881         int pass, maxpasses;
9882
9883         if (is_scalar) {
9884             maxpasses = 1;
9885         } else {
9886             maxpasses = is_q ? 4 : 2;
9887         }
9888
9889         for (pass = 0; pass < maxpasses; pass++) {
9890             if (is_scalar) {
9891                 read_vec_element_i32(s, tcg_rn, rn, pass, size);
9892                 read_vec_element_i32(s, tcg_rd, rd, pass, size);
9893             } else {
9894                 read_vec_element_i32(s, tcg_rn, rn, pass, MO_32);
9895                 read_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
9896             }
9897
9898             if (is_u) { /* USQADD */
9899                 switch (size) {
9900                 case 0:
9901                     gen_helper_neon_uqadd_s8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9902                     break;
9903                 case 1:
9904                     gen_helper_neon_uqadd_s16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9905                     break;
9906                 case 2:
9907                     gen_helper_neon_uqadd_s32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9908                     break;
9909                 default:
9910                     g_assert_not_reached();
9911                 }
9912             } else { /* SUQADD */
9913                 switch (size) {
9914                 case 0:
9915                     gen_helper_neon_sqadd_u8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9916                     break;
9917                 case 1:
9918                     gen_helper_neon_sqadd_u16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9919                     break;
9920                 case 2:
9921                     gen_helper_neon_sqadd_u32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9922                     break;
9923                 default:
9924                     g_assert_not_reached();
9925                 }
9926             }
9927
9928             if (is_scalar) {
9929                 TCGv_i64 tcg_zero = tcg_const_i64(0);
9930                 write_vec_element(s, tcg_zero, rd, 0, MO_64);
9931                 tcg_temp_free_i64(tcg_zero);
9932             }
9933             write_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
9934         }
9935         tcg_temp_free_i32(tcg_rd);
9936         tcg_temp_free_i32(tcg_rn);
9937         clear_vec_high(s, is_q, rd);
9938     }
9939 }
9940
9941 /* AdvSIMD scalar two reg misc
9942  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
9943  * +-----+---+-----------+------+-----------+--------+-----+------+------+
9944  * | 0 1 | U | 1 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
9945  * +-----+---+-----------+------+-----------+--------+-----+------+------+
9946  */
9947 static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
9948 {
9949     int rd = extract32(insn, 0, 5);
9950     int rn = extract32(insn, 5, 5);
9951     int opcode = extract32(insn, 12, 5);
9952     int size = extract32(insn, 22, 2);
9953     bool u = extract32(insn, 29, 1);
9954     bool is_fcvt = false;
9955     int rmode;
9956     TCGv_i32 tcg_rmode;
9957     TCGv_ptr tcg_fpstatus;
9958
9959     switch (opcode) {
9960     case 0x3: /* USQADD / SUQADD*/
9961         if (!fp_access_check(s)) {
9962             return;
9963         }
9964         handle_2misc_satacc(s, true, u, false, size, rn, rd);
9965         return;
9966     case 0x7: /* SQABS / SQNEG */
9967         break;
9968     case 0xa: /* CMLT */
9969         if (u) {
9970             unallocated_encoding(s);
9971             return;
9972         }
9973         /* fall through */
9974     case 0x8: /* CMGT, CMGE */
9975     case 0x9: /* CMEQ, CMLE */
9976     case 0xb: /* ABS, NEG */
9977         if (size != 3) {
9978             unallocated_encoding(s);
9979             return;
9980         }
9981         break;
9982     case 0x12: /* SQXTUN */
9983         if (!u) {
9984             unallocated_encoding(s);
9985             return;
9986         }
9987         /* fall through */
9988     case 0x14: /* SQXTN, UQXTN */
9989         if (size == 3) {
9990             unallocated_encoding(s);
9991             return;
9992         }
9993         if (!fp_access_check(s)) {
9994             return;
9995         }
9996         handle_2misc_narrow(s, true, opcode, u, false, size, rn, rd);
9997         return;
9998     case 0xc ... 0xf:
9999     case 0x16 ... 0x1d:
10000     case 0x1f:
10001         /* Floating point: U, size[1] and opcode indicate operation;
10002          * size[0] indicates single or double precision.
10003          */
10004         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
10005         size = extract32(size, 0, 1) ? 3 : 2;
10006         switch (opcode) {
10007         case 0x2c: /* FCMGT (zero) */
10008         case 0x2d: /* FCMEQ (zero) */
10009         case 0x2e: /* FCMLT (zero) */
10010         case 0x6c: /* FCMGE (zero) */
10011         case 0x6d: /* FCMLE (zero) */
10012             handle_2misc_fcmp_zero(s, opcode, true, u, true, size, rn, rd);
10013             return;
10014         case 0x1d: /* SCVTF */
10015         case 0x5d: /* UCVTF */
10016         {
10017             bool is_signed = (opcode == 0x1d);
10018             if (!fp_access_check(s)) {
10019                 return;
10020             }
10021             handle_simd_intfp_conv(s, rd, rn, 1, is_signed, 0, size);
10022             return;
10023         }
10024         case 0x3d: /* FRECPE */
10025         case 0x3f: /* FRECPX */
10026         case 0x7d: /* FRSQRTE */
10027             if (!fp_access_check(s)) {
10028                 return;
10029             }
10030             handle_2misc_reciprocal(s, opcode, true, u, true, size, rn, rd);
10031             return;
10032         case 0x1a: /* FCVTNS */
10033         case 0x1b: /* FCVTMS */
10034         case 0x3a: /* FCVTPS */
10035         case 0x3b: /* FCVTZS */
10036         case 0x5a: /* FCVTNU */
10037         case 0x5b: /* FCVTMU */
10038         case 0x7a: /* FCVTPU */
10039         case 0x7b: /* FCVTZU */
10040             is_fcvt = true;
10041             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
10042             break;
10043         case 0x1c: /* FCVTAS */
10044         case 0x5c: /* FCVTAU */
10045             /* TIEAWAY doesn't fit in the usual rounding mode encoding */
10046             is_fcvt = true;
10047             rmode = FPROUNDING_TIEAWAY;
10048             break;
10049         case 0x56: /* FCVTXN, FCVTXN2 */
10050             if (size == 2) {
10051                 unallocated_encoding(s);
10052                 return;
10053             }
10054             if (!fp_access_check(s)) {
10055                 return;
10056             }
10057             handle_2misc_narrow(s, true, opcode, u, false, size - 1, rn, rd);
10058             return;
10059         default:
10060             unallocated_encoding(s);
10061             return;
10062         }
10063         break;
10064     default:
10065         unallocated_encoding(s);
10066         return;
10067     }
10068
10069     if (!fp_access_check(s)) {
10070         return;
10071     }
10072
10073     if (is_fcvt) {
10074         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
10075         tcg_fpstatus = get_fpstatus_ptr(false);
10076         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
10077     } else {
10078         tcg_rmode = NULL;
10079         tcg_fpstatus = NULL;
10080     }
10081
10082     if (size == 3) {
10083         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
10084         TCGv_i64 tcg_rd = tcg_temp_new_i64();
10085
10086         handle_2misc_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rmode, tcg_fpstatus);
10087         write_fp_dreg(s, rd, tcg_rd);
10088         tcg_temp_free_i64(tcg_rd);
10089         tcg_temp_free_i64(tcg_rn);
10090     } else {
10091         TCGv_i32 tcg_rn = tcg_temp_new_i32();
10092         TCGv_i32 tcg_rd = tcg_temp_new_i32();
10093
10094         read_vec_element_i32(s, tcg_rn, rn, 0, size);
10095
10096         switch (opcode) {
10097         case 0x7: /* SQABS, SQNEG */
10098         {
10099             NeonGenOneOpEnvFn *genfn;
10100             static NeonGenOneOpEnvFn * const fns[3][2] = {
10101                 { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
10102                 { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
10103                 { gen_helper_neon_qabs_s32, gen_helper_neon_qneg_s32 },
10104             };
10105             genfn = fns[size][u];
10106             genfn(tcg_rd, cpu_env, tcg_rn);
10107             break;
10108         }
10109         case 0x1a: /* FCVTNS */
10110         case 0x1b: /* FCVTMS */
10111         case 0x1c: /* FCVTAS */
10112         case 0x3a: /* FCVTPS */
10113         case 0x3b: /* FCVTZS */
10114         {
10115             TCGv_i32 tcg_shift = tcg_const_i32(0);
10116             gen_helper_vfp_tosls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
10117             tcg_temp_free_i32(tcg_shift);
10118             break;
10119         }
10120         case 0x5a: /* FCVTNU */
10121         case 0x5b: /* FCVTMU */
10122         case 0x5c: /* FCVTAU */
10123         case 0x7a: /* FCVTPU */
10124         case 0x7b: /* FCVTZU */
10125         {
10126             TCGv_i32 tcg_shift = tcg_const_i32(0);
10127             gen_helper_vfp_touls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
10128             tcg_temp_free_i32(tcg_shift);
10129             break;
10130         }
10131         default:
10132             g_assert_not_reached();
10133         }
10134
10135         write_fp_sreg(s, rd, tcg_rd);
10136         tcg_temp_free_i32(tcg_rd);
10137         tcg_temp_free_i32(tcg_rn);
10138     }
10139
10140     if (is_fcvt) {
10141         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
10142         tcg_temp_free_i32(tcg_rmode);
10143         tcg_temp_free_ptr(tcg_fpstatus);
10144     }
10145 }
10146
10147 /* SSHR[RA]/USHR[RA] - Vector shift right (optional rounding/accumulate) */
10148 static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
10149                                  int immh, int immb, int opcode, int rn, int rd)
10150 {
10151     int size = 32 - clz32(immh) - 1;
10152     int immhb = immh << 3 | immb;
10153     int shift = 2 * (8 << size) - immhb;
10154     bool accumulate = false;
10155     int dsize = is_q ? 128 : 64;
10156     int esize = 8 << size;
10157     int elements = dsize/esize;
10158     TCGMemOp memop = size | (is_u ? 0 : MO_SIGN);
10159     TCGv_i64 tcg_rn = new_tmp_a64(s);
10160     TCGv_i64 tcg_rd = new_tmp_a64(s);
10161     TCGv_i64 tcg_round;
10162     uint64_t round_const;
10163     int i;
10164
10165     if (extract32(immh, 3, 1) && !is_q) {
10166         unallocated_encoding(s);
10167         return;
10168     }
10169     tcg_debug_assert(size <= 3);
10170
10171     if (!fp_access_check(s)) {
10172         return;
10173     }
10174
10175     switch (opcode) {
10176     case 0x02: /* SSRA / USRA (accumulate) */
10177         if (is_u) {
10178             /* Shift count same as element size produces zero to add.  */
10179             if (shift == 8 << size) {
10180                 goto done;
10181             }
10182             gen_gvec_op2i(s, is_q, rd, rn, shift, &usra_op[size]);
10183         } else {
10184             /* Shift count same as element size produces all sign to add.  */
10185             if (shift == 8 << size) {
10186                 shift -= 1;
10187             }
10188             gen_gvec_op2i(s, is_q, rd, rn, shift, &ssra_op[size]);
10189         }
10190         return;
10191     case 0x08: /* SRI */
10192         /* Shift count same as element size is valid but does nothing.  */
10193         if (shift == 8 << size) {
10194             goto done;
10195         }
10196         gen_gvec_op2i(s, is_q, rd, rn, shift, &sri_op[size]);
10197         return;
10198
10199     case 0x00: /* SSHR / USHR */
10200         if (is_u) {
10201             if (shift == 8 << size) {
10202                 /* Shift count the same size as element size produces zero.  */
10203                 tcg_gen_gvec_dup8i(vec_full_reg_offset(s, rd),
10204                                    is_q ? 16 : 8, vec_full_reg_size(s), 0);
10205             } else {
10206                 gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shri, size);
10207             }
10208         } else {
10209             /* Shift count the same size as element size produces all sign.  */
10210             if (shift == 8 << size) {
10211                 shift -= 1;
10212             }
10213             gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_sari, size);
10214         }
10215         return;
10216
10217     case 0x04: /* SRSHR / URSHR (rounding) */
10218         break;
10219     case 0x06: /* SRSRA / URSRA (accum + rounding) */
10220         accumulate = true;
10221         break;
10222     default:
10223         g_assert_not_reached();
10224     }
10225
10226     round_const = 1ULL << (shift - 1);
10227     tcg_round = tcg_const_i64(round_const);
10228
10229     for (i = 0; i < elements; i++) {
10230         read_vec_element(s, tcg_rn, rn, i, memop);
10231         if (accumulate) {
10232             read_vec_element(s, tcg_rd, rd, i, memop);
10233         }
10234
10235         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
10236                                 accumulate, is_u, size, shift);
10237
10238         write_vec_element(s, tcg_rd, rd, i, size);
10239     }
10240     tcg_temp_free_i64(tcg_round);
10241
10242  done:
10243     clear_vec_high(s, is_q, rd);
10244 }
10245
10246 /* SHL/SLI - Vector shift left */
10247 static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
10248                                  int immh, int immb, int opcode, int rn, int rd)
10249 {
10250     int size = 32 - clz32(immh) - 1;
10251     int immhb = immh << 3 | immb;
10252     int shift = immhb - (8 << size);
10253
10254     /* Range of size is limited by decode: immh is a non-zero 4 bit field */
10255     assert(size >= 0 && size <= 3);
10256
10257     if (extract32(immh, 3, 1) && !is_q) {
10258         unallocated_encoding(s);
10259         return;
10260     }
10261
10262     if (!fp_access_check(s)) {
10263         return;
10264     }
10265
10266     if (insert) {
10267         gen_gvec_op2i(s, is_q, rd, rn, shift, &sli_op[size]);
10268     } else {
10269         gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shli, size);
10270     }
10271 }
10272
10273 /* USHLL/SHLL - Vector shift left with widening */
10274 static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u,
10275                                  int immh, int immb, int opcode, int rn, int rd)
10276 {
10277     int size = 32 - clz32(immh) - 1;
10278     int immhb = immh << 3 | immb;
10279     int shift = immhb - (8 << size);
10280     int dsize = 64;
10281     int esize = 8 << size;
10282     int elements = dsize/esize;
10283     TCGv_i64 tcg_rn = new_tmp_a64(s);
10284     TCGv_i64 tcg_rd = new_tmp_a64(s);
10285     int i;
10286
10287     if (size >= 3) {
10288         unallocated_encoding(s);
10289         return;
10290     }
10291
10292     if (!fp_access_check(s)) {
10293         return;
10294     }
10295
10296     /* For the LL variants the store is larger than the load,
10297      * so if rd == rn we would overwrite parts of our input.
10298      * So load everything right now and use shifts in the main loop.
10299      */
10300     read_vec_element(s, tcg_rn, rn, is_q ? 1 : 0, MO_64);
10301
10302     for (i = 0; i < elements; i++) {
10303         tcg_gen_shri_i64(tcg_rd, tcg_rn, i * esize);
10304         ext_and_shift_reg(tcg_rd, tcg_rd, size | (!is_u << 2), 0);
10305         tcg_gen_shli_i64(tcg_rd, tcg_rd, shift);
10306         write_vec_element(s, tcg_rd, rd, i, size + 1);
10307     }
10308 }
10309
10310 /* SHRN/RSHRN - Shift right with narrowing (and potential rounding) */
10311 static void handle_vec_simd_shrn(DisasContext *s, bool is_q,
10312                                  int immh, int immb, int opcode, int rn, int rd)
10313 {
10314     int immhb = immh << 3 | immb;
10315     int size = 32 - clz32(immh) - 1;
10316     int dsize = 64;
10317     int esize = 8 << size;
10318     int elements = dsize/esize;
10319     int shift = (2 * esize) - immhb;
10320     bool round = extract32(opcode, 0, 1);
10321     TCGv_i64 tcg_rn, tcg_rd, tcg_final;
10322     TCGv_i64 tcg_round;
10323     int i;
10324
10325     if (extract32(immh, 3, 1)) {
10326         unallocated_encoding(s);
10327         return;
10328     }
10329
10330     if (!fp_access_check(s)) {
10331         return;
10332     }
10333
10334     tcg_rn = tcg_temp_new_i64();
10335     tcg_rd = tcg_temp_new_i64();
10336     tcg_final = tcg_temp_new_i64();
10337     read_vec_element(s, tcg_final, rd, is_q ? 1 : 0, MO_64);
10338
10339     if (round) {
10340         uint64_t round_const = 1ULL << (shift - 1);
10341         tcg_round = tcg_const_i64(round_const);
10342     } else {
10343         tcg_round = NULL;
10344     }
10345
10346     for (i = 0; i < elements; i++) {
10347         read_vec_element(s, tcg_rn, rn, i, size+1);
10348         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
10349                                 false, true, size+1, shift);
10350
10351         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
10352     }
10353
10354     if (!is_q) {
10355         write_vec_element(s, tcg_final, rd, 0, MO_64);
10356     } else {
10357         write_vec_element(s, tcg_final, rd, 1, MO_64);
10358     }
10359     if (round) {
10360         tcg_temp_free_i64(tcg_round);
10361     }
10362     tcg_temp_free_i64(tcg_rn);
10363     tcg_temp_free_i64(tcg_rd);
10364     tcg_temp_free_i64(tcg_final);
10365
10366     clear_vec_high(s, is_q, rd);
10367 }
10368
10369
10370 /* AdvSIMD shift by immediate
10371  *  31  30   29 28         23 22  19 18  16 15    11  10 9    5 4    0
10372  * +---+---+---+-------------+------+------+--------+---+------+------+
10373  * | 0 | Q | U | 0 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
10374  * +---+---+---+-------------+------+------+--------+---+------+------+
10375  */
10376 static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
10377 {
10378     int rd = extract32(insn, 0, 5);
10379     int rn = extract32(insn, 5, 5);
10380     int opcode = extract32(insn, 11, 5);
10381     int immb = extract32(insn, 16, 3);
10382     int immh = extract32(insn, 19, 4);
10383     bool is_u = extract32(insn, 29, 1);
10384     bool is_q = extract32(insn, 30, 1);
10385
10386     switch (opcode) {
10387     case 0x08: /* SRI */
10388         if (!is_u) {
10389             unallocated_encoding(s);
10390             return;
10391         }
10392         /* fall through */
10393     case 0x00: /* SSHR / USHR */
10394     case 0x02: /* SSRA / USRA (accumulate) */
10395     case 0x04: /* SRSHR / URSHR (rounding) */
10396     case 0x06: /* SRSRA / URSRA (accum + rounding) */
10397         handle_vec_simd_shri(s, is_q, is_u, immh, immb, opcode, rn, rd);
10398         break;
10399     case 0x0a: /* SHL / SLI */
10400         handle_vec_simd_shli(s, is_q, is_u, immh, immb, opcode, rn, rd);
10401         break;
10402     case 0x10: /* SHRN */
10403     case 0x11: /* RSHRN / SQRSHRUN */
10404         if (is_u) {
10405             handle_vec_simd_sqshrn(s, false, is_q, false, true, immh, immb,
10406                                    opcode, rn, rd);
10407         } else {
10408             handle_vec_simd_shrn(s, is_q, immh, immb, opcode, rn, rd);
10409         }
10410         break;
10411     case 0x12: /* SQSHRN / UQSHRN */
10412     case 0x13: /* SQRSHRN / UQRSHRN */
10413         handle_vec_simd_sqshrn(s, false, is_q, is_u, is_u, immh, immb,
10414                                opcode, rn, rd);
10415         break;
10416     case 0x14: /* SSHLL / USHLL */
10417         handle_vec_simd_wshli(s, is_q, is_u, immh, immb, opcode, rn, rd);
10418         break;
10419     case 0x1c: /* SCVTF / UCVTF */
10420         handle_simd_shift_intfp_conv(s, false, is_q, is_u, immh, immb,
10421                                      opcode, rn, rd);
10422         break;
10423     case 0xc: /* SQSHLU */
10424         if (!is_u) {
10425             unallocated_encoding(s);
10426             return;
10427         }
10428         handle_simd_qshl(s, false, is_q, false, true, immh, immb, rn, rd);
10429         break;
10430     case 0xe: /* SQSHL, UQSHL */
10431         handle_simd_qshl(s, false, is_q, is_u, is_u, immh, immb, rn, rd);
10432         break;
10433     case 0x1f: /* FCVTZS/ FCVTZU */
10434         handle_simd_shift_fpint_conv(s, false, is_q, is_u, immh, immb, rn, rd);
10435         return;
10436     default:
10437         unallocated_encoding(s);
10438         return;
10439     }
10440 }
10441
10442 /* Generate code to do a "long" addition or subtraction, ie one done in
10443  * TCGv_i64 on vector lanes twice the width specified by size.
10444  */
10445 static void gen_neon_addl(int size, bool is_sub, TCGv_i64 tcg_res,
10446                           TCGv_i64 tcg_op1, TCGv_i64 tcg_op2)
10447 {
10448     static NeonGenTwo64OpFn * const fns[3][2] = {
10449         { gen_helper_neon_addl_u16, gen_helper_neon_subl_u16 },
10450         { gen_helper_neon_addl_u32, gen_helper_neon_subl_u32 },
10451         { tcg_gen_add_i64, tcg_gen_sub_i64 },
10452     };
10453     NeonGenTwo64OpFn *genfn;
10454     assert(size < 3);
10455
10456     genfn = fns[size][is_sub];
10457     genfn(tcg_res, tcg_op1, tcg_op2);
10458 }
10459
10460 static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
10461                                 int opcode, int rd, int rn, int rm)
10462 {
10463     /* 3-reg-different widening insns: 64 x 64 -> 128 */
10464     TCGv_i64 tcg_res[2];
10465     int pass, accop;
10466
10467     tcg_res[0] = tcg_temp_new_i64();
10468     tcg_res[1] = tcg_temp_new_i64();
10469
10470     /* Does this op do an adding accumulate, a subtracting accumulate,
10471      * or no accumulate at all?
10472      */
10473     switch (opcode) {
10474     case 5:
10475     case 8:
10476     case 9:
10477         accop = 1;
10478         break;
10479     case 10:
10480     case 11:
10481         accop = -1;
10482         break;
10483     default:
10484         accop = 0;
10485         break;
10486     }
10487
10488     if (accop != 0) {
10489         read_vec_element(s, tcg_res[0], rd, 0, MO_64);
10490         read_vec_element(s, tcg_res[1], rd, 1, MO_64);
10491     }
10492
10493     /* size == 2 means two 32x32->64 operations; this is worth special
10494      * casing because we can generally handle it inline.
10495      */
10496     if (size == 2) {
10497         for (pass = 0; pass < 2; pass++) {
10498             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10499             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10500             TCGv_i64 tcg_passres;
10501             TCGMemOp memop = MO_32 | (is_u ? 0 : MO_SIGN);
10502
10503             int elt = pass + is_q * 2;
10504
10505             read_vec_element(s, tcg_op1, rn, elt, memop);
10506             read_vec_element(s, tcg_op2, rm, elt, memop);
10507
10508             if (accop == 0) {
10509                 tcg_passres = tcg_res[pass];
10510             } else {
10511                 tcg_passres = tcg_temp_new_i64();
10512             }
10513
10514             switch (opcode) {
10515             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10516                 tcg_gen_add_i64(tcg_passres, tcg_op1, tcg_op2);
10517                 break;
10518             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10519                 tcg_gen_sub_i64(tcg_passres, tcg_op1, tcg_op2);
10520                 break;
10521             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10522             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10523             {
10524                 TCGv_i64 tcg_tmp1 = tcg_temp_new_i64();
10525                 TCGv_i64 tcg_tmp2 = tcg_temp_new_i64();
10526
10527                 tcg_gen_sub_i64(tcg_tmp1, tcg_op1, tcg_op2);
10528                 tcg_gen_sub_i64(tcg_tmp2, tcg_op2, tcg_op1);
10529                 tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
10530                                     tcg_passres,
10531                                     tcg_op1, tcg_op2, tcg_tmp1, tcg_tmp2);
10532                 tcg_temp_free_i64(tcg_tmp1);
10533                 tcg_temp_free_i64(tcg_tmp2);
10534                 break;
10535             }
10536             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10537             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10538             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
10539                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
10540                 break;
10541             case 9: /* SQDMLAL, SQDMLAL2 */
10542             case 11: /* SQDMLSL, SQDMLSL2 */
10543             case 13: /* SQDMULL, SQDMULL2 */
10544                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
10545                 gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
10546                                                   tcg_passres, tcg_passres);
10547                 break;
10548             default:
10549                 g_assert_not_reached();
10550             }
10551
10552             if (opcode == 9 || opcode == 11) {
10553                 /* saturating accumulate ops */
10554                 if (accop < 0) {
10555                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
10556                 }
10557                 gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
10558                                                   tcg_res[pass], tcg_passres);
10559             } else if (accop > 0) {
10560                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10561             } else if (accop < 0) {
10562                 tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10563             }
10564
10565             if (accop != 0) {
10566                 tcg_temp_free_i64(tcg_passres);
10567             }
10568
10569             tcg_temp_free_i64(tcg_op1);
10570             tcg_temp_free_i64(tcg_op2);
10571         }
10572     } else {
10573         /* size 0 or 1, generally helper functions */
10574         for (pass = 0; pass < 2; pass++) {
10575             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
10576             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10577             TCGv_i64 tcg_passres;
10578             int elt = pass + is_q * 2;
10579
10580             read_vec_element_i32(s, tcg_op1, rn, elt, MO_32);
10581             read_vec_element_i32(s, tcg_op2, rm, elt, MO_32);
10582
10583             if (accop == 0) {
10584                 tcg_passres = tcg_res[pass];
10585             } else {
10586                 tcg_passres = tcg_temp_new_i64();
10587             }
10588
10589             switch (opcode) {
10590             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10591             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10592             {
10593                 TCGv_i64 tcg_op2_64 = tcg_temp_new_i64();
10594                 static NeonGenWidenFn * const widenfns[2][2] = {
10595                     { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
10596                     { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
10597                 };
10598                 NeonGenWidenFn *widenfn = widenfns[size][is_u];
10599
10600                 widenfn(tcg_op2_64, tcg_op2);
10601                 widenfn(tcg_passres, tcg_op1);
10602                 gen_neon_addl(size, (opcode == 2), tcg_passres,
10603                               tcg_passres, tcg_op2_64);
10604                 tcg_temp_free_i64(tcg_op2_64);
10605                 break;
10606             }
10607             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10608             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10609                 if (size == 0) {
10610                     if (is_u) {
10611                         gen_helper_neon_abdl_u16(tcg_passres, tcg_op1, tcg_op2);
10612                     } else {
10613                         gen_helper_neon_abdl_s16(tcg_passres, tcg_op1, tcg_op2);
10614                     }
10615                 } else {
10616                     if (is_u) {
10617                         gen_helper_neon_abdl_u32(tcg_passres, tcg_op1, tcg_op2);
10618                     } else {
10619                         gen_helper_neon_abdl_s32(tcg_passres, tcg_op1, tcg_op2);
10620                     }
10621                 }
10622                 break;
10623             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10624             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10625             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
10626                 if (size == 0) {
10627                     if (is_u) {
10628                         gen_helper_neon_mull_u8(tcg_passres, tcg_op1, tcg_op2);
10629                     } else {
10630                         gen_helper_neon_mull_s8(tcg_passres, tcg_op1, tcg_op2);
10631                     }
10632                 } else {
10633                     if (is_u) {
10634                         gen_helper_neon_mull_u16(tcg_passres, tcg_op1, tcg_op2);
10635                     } else {
10636                         gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
10637                     }
10638                 }
10639                 break;
10640             case 9: /* SQDMLAL, SQDMLAL2 */
10641             case 11: /* SQDMLSL, SQDMLSL2 */
10642             case 13: /* SQDMULL, SQDMULL2 */
10643                 assert(size == 1);
10644                 gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
10645                 gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
10646                                                   tcg_passres, tcg_passres);
10647                 break;
10648             case 14: /* PMULL */
10649                 assert(size == 0);
10650                 gen_helper_neon_mull_p8(tcg_passres, tcg_op1, tcg_op2);
10651                 break;
10652             default:
10653                 g_assert_not_reached();
10654             }
10655             tcg_temp_free_i32(tcg_op1);
10656             tcg_temp_free_i32(tcg_op2);
10657
10658             if (accop != 0) {
10659                 if (opcode == 9 || opcode == 11) {
10660                     /* saturating accumulate ops */
10661                     if (accop < 0) {
10662                         gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
10663                     }
10664                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
10665                                                       tcg_res[pass],
10666                                                       tcg_passres);
10667                 } else {
10668                     gen_neon_addl(size, (accop < 0), tcg_res[pass],
10669                                   tcg_res[pass], tcg_passres);
10670                 }
10671                 tcg_temp_free_i64(tcg_passres);
10672             }
10673         }
10674     }
10675
10676     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
10677     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
10678     tcg_temp_free_i64(tcg_res[0]);
10679     tcg_temp_free_i64(tcg_res[1]);
10680 }
10681
10682 static void handle_3rd_wide(DisasContext *s, int is_q, int is_u, int size,
10683                             int opcode, int rd, int rn, int rm)
10684 {
10685     TCGv_i64 tcg_res[2];
10686     int part = is_q ? 2 : 0;
10687     int pass;
10688
10689     for (pass = 0; pass < 2; pass++) {
10690         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10691         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10692         TCGv_i64 tcg_op2_wide = tcg_temp_new_i64();
10693         static NeonGenWidenFn * const widenfns[3][2] = {
10694             { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
10695             { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
10696             { tcg_gen_ext_i32_i64, tcg_gen_extu_i32_i64 },
10697         };
10698         NeonGenWidenFn *widenfn = widenfns[size][is_u];
10699
10700         read_vec_element(s, tcg_op1, rn, pass, MO_64);
10701         read_vec_element_i32(s, tcg_op2, rm, part + pass, MO_32);
10702         widenfn(tcg_op2_wide, tcg_op2);
10703         tcg_temp_free_i32(tcg_op2);
10704         tcg_res[pass] = tcg_temp_new_i64();
10705         gen_neon_addl(size, (opcode == 3),
10706                       tcg_res[pass], tcg_op1, tcg_op2_wide);
10707         tcg_temp_free_i64(tcg_op1);
10708         tcg_temp_free_i64(tcg_op2_wide);
10709     }
10710
10711     for (pass = 0; pass < 2; pass++) {
10712         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
10713         tcg_temp_free_i64(tcg_res[pass]);
10714     }
10715 }
10716
10717 static void do_narrow_round_high_u32(TCGv_i32 res, TCGv_i64 in)
10718 {
10719     tcg_gen_addi_i64(in, in, 1U << 31);
10720     tcg_gen_extrh_i64_i32(res, in);
10721 }
10722
10723 static void handle_3rd_narrowing(DisasContext *s, int is_q, int is_u, int size,
10724                                  int opcode, int rd, int rn, int rm)
10725 {
10726     TCGv_i32 tcg_res[2];
10727     int part = is_q ? 2 : 0;
10728     int pass;
10729
10730     for (pass = 0; pass < 2; pass++) {
10731         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10732         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10733         TCGv_i64 tcg_wideres = tcg_temp_new_i64();
10734         static NeonGenNarrowFn * const narrowfns[3][2] = {
10735             { gen_helper_neon_narrow_high_u8,
10736               gen_helper_neon_narrow_round_high_u8 },
10737             { gen_helper_neon_narrow_high_u16,
10738               gen_helper_neon_narrow_round_high_u16 },
10739             { tcg_gen_extrh_i64_i32, do_narrow_round_high_u32 },
10740         };
10741         NeonGenNarrowFn *gennarrow = narrowfns[size][is_u];
10742
10743         read_vec_element(s, tcg_op1, rn, pass, MO_64);
10744         read_vec_element(s, tcg_op2, rm, pass, MO_64);
10745
10746         gen_neon_addl(size, (opcode == 6), tcg_wideres, tcg_op1, tcg_op2);
10747
10748         tcg_temp_free_i64(tcg_op1);
10749         tcg_temp_free_i64(tcg_op2);
10750
10751         tcg_res[pass] = tcg_temp_new_i32();
10752         gennarrow(tcg_res[pass], tcg_wideres);
10753         tcg_temp_free_i64(tcg_wideres);
10754     }
10755
10756     for (pass = 0; pass < 2; pass++) {
10757         write_vec_element_i32(s, tcg_res[pass], rd, pass + part, MO_32);
10758         tcg_temp_free_i32(tcg_res[pass]);
10759     }
10760     clear_vec_high(s, is_q, rd);
10761 }
10762
10763 static void handle_pmull_64(DisasContext *s, int is_q, int rd, int rn, int rm)
10764 {
10765     /* PMULL of 64 x 64 -> 128 is an odd special case because it
10766      * is the only three-reg-diff instruction which produces a
10767      * 128-bit wide result from a single operation. However since
10768      * it's possible to calculate the two halves more or less
10769      * separately we just use two helper calls.
10770      */
10771     TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10772     TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10773     TCGv_i64 tcg_res = tcg_temp_new_i64();
10774
10775     read_vec_element(s, tcg_op1, rn, is_q, MO_64);
10776     read_vec_element(s, tcg_op2, rm, is_q, MO_64);
10777     gen_helper_neon_pmull_64_lo(tcg_res, tcg_op1, tcg_op2);
10778     write_vec_element(s, tcg_res, rd, 0, MO_64);
10779     gen_helper_neon_pmull_64_hi(tcg_res, tcg_op1, tcg_op2);
10780     write_vec_element(s, tcg_res, rd, 1, MO_64);
10781
10782     tcg_temp_free_i64(tcg_op1);
10783     tcg_temp_free_i64(tcg_op2);
10784     tcg_temp_free_i64(tcg_res);
10785 }
10786
10787 /* AdvSIMD three different
10788  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
10789  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
10790  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
10791  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
10792  */
10793 static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
10794 {
10795     /* Instructions in this group fall into three basic classes
10796      * (in each case with the operation working on each element in
10797      * the input vectors):
10798      * (1) widening 64 x 64 -> 128 (with possibly Vd as an extra
10799      *     128 bit input)
10800      * (2) wide 64 x 128 -> 128
10801      * (3) narrowing 128 x 128 -> 64
10802      * Here we do initial decode, catch unallocated cases and
10803      * dispatch to separate functions for each class.
10804      */
10805     int is_q = extract32(insn, 30, 1);
10806     int is_u = extract32(insn, 29, 1);
10807     int size = extract32(insn, 22, 2);
10808     int opcode = extract32(insn, 12, 4);
10809     int rm = extract32(insn, 16, 5);
10810     int rn = extract32(insn, 5, 5);
10811     int rd = extract32(insn, 0, 5);
10812
10813     switch (opcode) {
10814     case 1: /* SADDW, SADDW2, UADDW, UADDW2 */
10815     case 3: /* SSUBW, SSUBW2, USUBW, USUBW2 */
10816         /* 64 x 128 -> 128 */
10817         if (size == 3) {
10818             unallocated_encoding(s);
10819             return;
10820         }
10821         if (!fp_access_check(s)) {
10822             return;
10823         }
10824         handle_3rd_wide(s, is_q, is_u, size, opcode, rd, rn, rm);
10825         break;
10826     case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */
10827     case 6: /* SUBHN, SUBHN2, RSUBHN, RSUBHN2 */
10828         /* 128 x 128 -> 64 */
10829         if (size == 3) {
10830             unallocated_encoding(s);
10831             return;
10832         }
10833         if (!fp_access_check(s)) {
10834             return;
10835         }
10836         handle_3rd_narrowing(s, is_q, is_u, size, opcode, rd, rn, rm);
10837         break;
10838     case 14: /* PMULL, PMULL2 */
10839         if (is_u || size == 1 || size == 2) {
10840             unallocated_encoding(s);
10841             return;
10842         }
10843         if (size == 3) {
10844             if (!dc_isar_feature(aa64_pmull, s)) {
10845                 unallocated_encoding(s);
10846                 return;
10847             }
10848             if (!fp_access_check(s)) {
10849                 return;
10850             }
10851             handle_pmull_64(s, is_q, rd, rn, rm);
10852             return;
10853         }
10854         goto is_widening;
10855     case 9: /* SQDMLAL, SQDMLAL2 */
10856     case 11: /* SQDMLSL, SQDMLSL2 */
10857     case 13: /* SQDMULL, SQDMULL2 */
10858         if (is_u || size == 0) {
10859             unallocated_encoding(s);
10860             return;
10861         }
10862         /* fall through */
10863     case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10864     case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10865     case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10866     case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10867     case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10868     case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10869     case 12: /* SMULL, SMULL2, UMULL, UMULL2 */
10870         /* 64 x 64 -> 128 */
10871         if (size == 3) {
10872             unallocated_encoding(s);
10873             return;
10874         }
10875     is_widening:
10876         if (!fp_access_check(s)) {
10877             return;
10878         }
10879
10880         handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm);
10881         break;
10882     default:
10883         /* opcode 15 not allocated */
10884         unallocated_encoding(s);
10885         break;
10886     }
10887 }
10888
10889 /* Logic op (opcode == 3) subgroup of C3.6.16. */
10890 static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
10891 {
10892     int rd = extract32(insn, 0, 5);
10893     int rn = extract32(insn, 5, 5);
10894     int rm = extract32(insn, 16, 5);
10895     int size = extract32(insn, 22, 2);
10896     bool is_u = extract32(insn, 29, 1);
10897     bool is_q = extract32(insn, 30, 1);
10898
10899     if (!fp_access_check(s)) {
10900         return;
10901     }
10902
10903     switch (size + 4 * is_u) {
10904     case 0: /* AND */
10905         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_and, 0);
10906         return;
10907     case 1: /* BIC */
10908         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_andc, 0);
10909         return;
10910     case 2: /* ORR */
10911         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0);
10912         return;
10913     case 3: /* ORN */
10914         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_orc, 0);
10915         return;
10916     case 4: /* EOR */
10917         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_xor, 0);
10918         return;
10919
10920     case 5: /* BSL bitwise select */
10921         gen_gvec_op3(s, is_q, rd, rn, rm, &bsl_op);
10922         return;
10923     case 6: /* BIT, bitwise insert if true */
10924         gen_gvec_op3(s, is_q, rd, rn, rm, &bit_op);
10925         return;
10926     case 7: /* BIF, bitwise insert if false */
10927         gen_gvec_op3(s, is_q, rd, rn, rm, &bif_op);
10928         return;
10929
10930     default:
10931         g_assert_not_reached();
10932     }
10933 }
10934
10935 /* Pairwise op subgroup of C3.6.16.
10936  *
10937  * This is called directly or via the handle_3same_float for float pairwise
10938  * operations where the opcode and size are calculated differently.
10939  */
10940 static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
10941                                    int size, int rn, int rm, int rd)
10942 {
10943     TCGv_ptr fpst;
10944     int pass;
10945
10946     /* Floating point operations need fpst */
10947     if (opcode >= 0x58) {
10948         fpst = get_fpstatus_ptr(false);
10949     } else {
10950         fpst = NULL;
10951     }
10952
10953     if (!fp_access_check(s)) {
10954         return;
10955     }
10956
10957     /* These operations work on the concatenated rm:rn, with each pair of
10958      * adjacent elements being operated on to produce an element in the result.
10959      */
10960     if (size == 3) {
10961         TCGv_i64 tcg_res[2];
10962
10963         for (pass = 0; pass < 2; pass++) {
10964             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10965             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10966             int passreg = (pass == 0) ? rn : rm;
10967
10968             read_vec_element(s, tcg_op1, passreg, 0, MO_64);
10969             read_vec_element(s, tcg_op2, passreg, 1, MO_64);
10970             tcg_res[pass] = tcg_temp_new_i64();
10971
10972             switch (opcode) {
10973             case 0x17: /* ADDP */
10974                 tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
10975                 break;
10976             case 0x58: /* FMAXNMP */
10977                 gen_helper_vfp_maxnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10978                 break;
10979             case 0x5a: /* FADDP */
10980                 gen_helper_vfp_addd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10981                 break;
10982             case 0x5e: /* FMAXP */
10983                 gen_helper_vfp_maxd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10984                 break;
10985             case 0x78: /* FMINNMP */
10986                 gen_helper_vfp_minnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10987                 break;
10988             case 0x7e: /* FMINP */
10989                 gen_helper_vfp_mind(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10990                 break;
10991             default:
10992                 g_assert_not_reached();
10993             }
10994
10995             tcg_temp_free_i64(tcg_op1);
10996             tcg_temp_free_i64(tcg_op2);
10997         }
10998
10999         for (pass = 0; pass < 2; pass++) {
11000             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
11001             tcg_temp_free_i64(tcg_res[pass]);
11002         }
11003     } else {
11004         int maxpass = is_q ? 4 : 2;
11005         TCGv_i32 tcg_res[4];
11006
11007         for (pass = 0; pass < maxpass; pass++) {
11008             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11009             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11010             NeonGenTwoOpFn *genfn = NULL;
11011             int passreg = pass < (maxpass / 2) ? rn : rm;
11012             int passelt = (is_q && (pass & 1)) ? 2 : 0;
11013
11014             read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_32);
11015             read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_32);
11016             tcg_res[pass] = tcg_temp_new_i32();
11017
11018             switch (opcode) {
11019             case 0x17: /* ADDP */
11020             {
11021                 static NeonGenTwoOpFn * const fns[3] = {
11022                     gen_helper_neon_padd_u8,
11023                     gen_helper_neon_padd_u16,
11024                     tcg_gen_add_i32,
11025                 };
11026                 genfn = fns[size];
11027                 break;
11028             }
11029             case 0x14: /* SMAXP, UMAXP */
11030             {
11031                 static NeonGenTwoOpFn * const fns[3][2] = {
11032                     { gen_helper_neon_pmax_s8, gen_helper_neon_pmax_u8 },
11033                     { gen_helper_neon_pmax_s16, gen_helper_neon_pmax_u16 },
11034                     { tcg_gen_smax_i32, tcg_gen_umax_i32 },
11035                 };
11036                 genfn = fns[size][u];
11037                 break;
11038             }
11039             case 0x15: /* SMINP, UMINP */
11040             {
11041                 static NeonGenTwoOpFn * const fns[3][2] = {
11042                     { gen_helper_neon_pmin_s8, gen_helper_neon_pmin_u8 },
11043                     { gen_helper_neon_pmin_s16, gen_helper_neon_pmin_u16 },
11044                     { tcg_gen_smin_i32, tcg_gen_umin_i32 },
11045                 };
11046                 genfn = fns[size][u];
11047                 break;
11048             }
11049             /* The FP operations are all on single floats (32 bit) */
11050             case 0x58: /* FMAXNMP */
11051                 gen_helper_vfp_maxnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11052                 break;
11053             case 0x5a: /* FADDP */
11054                 gen_helper_vfp_adds(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11055                 break;
11056             case 0x5e: /* FMAXP */
11057                 gen_helper_vfp_maxs(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11058                 break;
11059             case 0x78: /* FMINNMP */
11060                 gen_helper_vfp_minnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11061                 break;
11062             case 0x7e: /* FMINP */
11063                 gen_helper_vfp_mins(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11064                 break;
11065             default:
11066                 g_assert_not_reached();
11067             }
11068
11069             /* FP ops called directly, otherwise call now */
11070             if (genfn) {
11071                 genfn(tcg_res[pass], tcg_op1, tcg_op2);
11072             }
11073
11074             tcg_temp_free_i32(tcg_op1);
11075             tcg_temp_free_i32(tcg_op2);
11076         }
11077
11078         for (pass = 0; pass < maxpass; pass++) {
11079             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
11080             tcg_temp_free_i32(tcg_res[pass]);
11081         }
11082         clear_vec_high(s, is_q, rd);
11083     }
11084
11085     if (fpst) {
11086         tcg_temp_free_ptr(fpst);
11087     }
11088 }
11089
11090 /* Floating point op subgroup of C3.6.16. */
11091 static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
11092 {
11093     /* For floating point ops, the U, size[1] and opcode bits
11094      * together indicate the operation. size[0] indicates single
11095      * or double.
11096      */
11097     int fpopcode = extract32(insn, 11, 5)
11098         | (extract32(insn, 23, 1) << 5)
11099         | (extract32(insn, 29, 1) << 6);
11100     int is_q = extract32(insn, 30, 1);
11101     int size = extract32(insn, 22, 1);
11102     int rm = extract32(insn, 16, 5);
11103     int rn = extract32(insn, 5, 5);
11104     int rd = extract32(insn, 0, 5);
11105
11106     int datasize = is_q ? 128 : 64;
11107     int esize = 32 << size;
11108     int elements = datasize / esize;
11109
11110     if (size == 1 && !is_q) {
11111         unallocated_encoding(s);
11112         return;
11113     }
11114
11115     switch (fpopcode) {
11116     case 0x58: /* FMAXNMP */
11117     case 0x5a: /* FADDP */
11118     case 0x5e: /* FMAXP */
11119     case 0x78: /* FMINNMP */
11120     case 0x7e: /* FMINP */
11121         if (size && !is_q) {
11122             unallocated_encoding(s);
11123             return;
11124         }
11125         handle_simd_3same_pair(s, is_q, 0, fpopcode, size ? MO_64 : MO_32,
11126                                rn, rm, rd);
11127         return;
11128     case 0x1b: /* FMULX */
11129     case 0x1f: /* FRECPS */
11130     case 0x3f: /* FRSQRTS */
11131     case 0x5d: /* FACGE */
11132     case 0x7d: /* FACGT */
11133     case 0x19: /* FMLA */
11134     case 0x39: /* FMLS */
11135     case 0x18: /* FMAXNM */
11136     case 0x1a: /* FADD */
11137     case 0x1c: /* FCMEQ */
11138     case 0x1e: /* FMAX */
11139     case 0x38: /* FMINNM */
11140     case 0x3a: /* FSUB */
11141     case 0x3e: /* FMIN */
11142     case 0x5b: /* FMUL */
11143     case 0x5c: /* FCMGE */
11144     case 0x5f: /* FDIV */
11145     case 0x7a: /* FABD */
11146     case 0x7c: /* FCMGT */
11147         if (!fp_access_check(s)) {
11148             return;
11149         }
11150         handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
11151         return;
11152
11153     case 0x1d: /* FMLAL  */
11154     case 0x3d: /* FMLSL  */
11155     case 0x59: /* FMLAL2 */
11156     case 0x79: /* FMLSL2 */
11157         if (size & 1 || !dc_isar_feature(aa64_fhm, s)) {
11158             unallocated_encoding(s);
11159             return;
11160         }
11161         if (fp_access_check(s)) {
11162             int is_s = extract32(insn, 23, 1);
11163             int is_2 = extract32(insn, 29, 1);
11164             int data = (is_2 << 1) | is_s;
11165             tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
11166                                vec_full_reg_offset(s, rn),
11167                                vec_full_reg_offset(s, rm), cpu_env,
11168                                is_q ? 16 : 8, vec_full_reg_size(s),
11169                                data, gen_helper_gvec_fmlal_a64);
11170         }
11171         return;
11172
11173     default:
11174         unallocated_encoding(s);
11175         return;
11176     }
11177 }
11178
11179 /* Integer op subgroup of C3.6.16. */
11180 static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
11181 {
11182     int is_q = extract32(insn, 30, 1);
11183     int u = extract32(insn, 29, 1);
11184     int size = extract32(insn, 22, 2);
11185     int opcode = extract32(insn, 11, 5);
11186     int rm = extract32(insn, 16, 5);
11187     int rn = extract32(insn, 5, 5);
11188     int rd = extract32(insn, 0, 5);
11189     int pass;
11190     TCGCond cond;
11191
11192     switch (opcode) {
11193     case 0x13: /* MUL, PMUL */
11194         if (u && size != 0) {
11195             unallocated_encoding(s);
11196             return;
11197         }
11198         /* fall through */
11199     case 0x0: /* SHADD, UHADD */
11200     case 0x2: /* SRHADD, URHADD */
11201     case 0x4: /* SHSUB, UHSUB */
11202     case 0xc: /* SMAX, UMAX */
11203     case 0xd: /* SMIN, UMIN */
11204     case 0xe: /* SABD, UABD */
11205     case 0xf: /* SABA, UABA */
11206     case 0x12: /* MLA, MLS */
11207         if (size == 3) {
11208             unallocated_encoding(s);
11209             return;
11210         }
11211         break;
11212     case 0x16: /* SQDMULH, SQRDMULH */
11213         if (size == 0 || size == 3) {
11214             unallocated_encoding(s);
11215             return;
11216         }
11217         break;
11218     default:
11219         if (size == 3 && !is_q) {
11220             unallocated_encoding(s);
11221             return;
11222         }
11223         break;
11224     }
11225
11226     if (!fp_access_check(s)) {
11227         return;
11228     }
11229
11230     switch (opcode) {
11231     case 0x01: /* SQADD, UQADD */
11232         tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
11233                        offsetof(CPUARMState, vfp.qc),
11234                        vec_full_reg_offset(s, rn),
11235                        vec_full_reg_offset(s, rm),
11236                        is_q ? 16 : 8, vec_full_reg_size(s),
11237                        (u ? uqadd_op : sqadd_op) + size);
11238         return;
11239     case 0x05: /* SQSUB, UQSUB */
11240         tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
11241                        offsetof(CPUARMState, vfp.qc),
11242                        vec_full_reg_offset(s, rn),
11243                        vec_full_reg_offset(s, rm),
11244                        is_q ? 16 : 8, vec_full_reg_size(s),
11245                        (u ? uqsub_op : sqsub_op) + size);
11246         return;
11247     case 0x0c: /* SMAX, UMAX */
11248         if (u) {
11249             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umax, size);
11250         } else {
11251             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smax, size);
11252         }
11253         return;
11254     case 0x0d: /* SMIN, UMIN */
11255         if (u) {
11256             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umin, size);
11257         } else {
11258             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smin, size);
11259         }
11260         return;
11261     case 0x10: /* ADD, SUB */
11262         if (u) {
11263             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
11264         } else {
11265             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_add, size);
11266         }
11267         return;
11268     case 0x13: /* MUL, PMUL */
11269         if (!u) { /* MUL */
11270             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_mul, size);
11271             return;
11272         }
11273         break;
11274     case 0x12: /* MLA, MLS */
11275         if (u) {
11276             gen_gvec_op3(s, is_q, rd, rn, rm, &mls_op[size]);
11277         } else {
11278             gen_gvec_op3(s, is_q, rd, rn, rm, &mla_op[size]);
11279         }
11280         return;
11281     case 0x11:
11282         if (!u) { /* CMTST */
11283             gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]);
11284             return;
11285         }
11286         /* else CMEQ */
11287         cond = TCG_COND_EQ;
11288         goto do_gvec_cmp;
11289     case 0x06: /* CMGT, CMHI */
11290         cond = u ? TCG_COND_GTU : TCG_COND_GT;
11291         goto do_gvec_cmp;
11292     case 0x07: /* CMGE, CMHS */
11293         cond = u ? TCG_COND_GEU : TCG_COND_GE;
11294     do_gvec_cmp:
11295         tcg_gen_gvec_cmp(cond, size, vec_full_reg_offset(s, rd),
11296                          vec_full_reg_offset(s, rn),
11297                          vec_full_reg_offset(s, rm),
11298                          is_q ? 16 : 8, vec_full_reg_size(s));
11299         return;
11300     }
11301
11302     if (size == 3) {
11303         assert(is_q);
11304         for (pass = 0; pass < 2; pass++) {
11305             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
11306             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
11307             TCGv_i64 tcg_res = tcg_temp_new_i64();
11308
11309             read_vec_element(s, tcg_op1, rn, pass, MO_64);
11310             read_vec_element(s, tcg_op2, rm, pass, MO_64);
11311
11312             handle_3same_64(s, opcode, u, tcg_res, tcg_op1, tcg_op2);
11313
11314             write_vec_element(s, tcg_res, rd, pass, MO_64);
11315
11316             tcg_temp_free_i64(tcg_res);
11317             tcg_temp_free_i64(tcg_op1);
11318             tcg_temp_free_i64(tcg_op2);
11319         }
11320     } else {
11321         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
11322             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11323             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11324             TCGv_i32 tcg_res = tcg_temp_new_i32();
11325             NeonGenTwoOpFn *genfn = NULL;
11326             NeonGenTwoOpEnvFn *genenvfn = NULL;
11327
11328             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
11329             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
11330
11331             switch (opcode) {
11332             case 0x0: /* SHADD, UHADD */
11333             {
11334                 static NeonGenTwoOpFn * const fns[3][2] = {
11335                     { gen_helper_neon_hadd_s8, gen_helper_neon_hadd_u8 },
11336                     { gen_helper_neon_hadd_s16, gen_helper_neon_hadd_u16 },
11337                     { gen_helper_neon_hadd_s32, gen_helper_neon_hadd_u32 },
11338                 };
11339                 genfn = fns[size][u];
11340                 break;
11341             }
11342             case 0x2: /* SRHADD, URHADD */
11343             {
11344                 static NeonGenTwoOpFn * const fns[3][2] = {
11345                     { gen_helper_neon_rhadd_s8, gen_helper_neon_rhadd_u8 },
11346                     { gen_helper_neon_rhadd_s16, gen_helper_neon_rhadd_u16 },
11347                     { gen_helper_neon_rhadd_s32, gen_helper_neon_rhadd_u32 },
11348                 };
11349                 genfn = fns[size][u];
11350                 break;
11351             }
11352             case 0x4: /* SHSUB, UHSUB */
11353             {
11354                 static NeonGenTwoOpFn * const fns[3][2] = {
11355                     { gen_helper_neon_hsub_s8, gen_helper_neon_hsub_u8 },
11356                     { gen_helper_neon_hsub_s16, gen_helper_neon_hsub_u16 },
11357                     { gen_helper_neon_hsub_s32, gen_helper_neon_hsub_u32 },
11358                 };
11359                 genfn = fns[size][u];
11360                 break;
11361             }
11362             case 0x8: /* SSHL, USHL */
11363             {
11364                 static NeonGenTwoOpFn * const fns[3][2] = {
11365                     { gen_helper_neon_shl_s8, gen_helper_neon_shl_u8 },
11366                     { gen_helper_neon_shl_s16, gen_helper_neon_shl_u16 },
11367                     { gen_helper_neon_shl_s32, gen_helper_neon_shl_u32 },
11368                 };
11369                 genfn = fns[size][u];
11370                 break;
11371             }
11372             case 0x9: /* SQSHL, UQSHL */
11373             {
11374                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
11375                     { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
11376                     { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
11377                     { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
11378                 };
11379                 genenvfn = fns[size][u];
11380                 break;
11381             }
11382             case 0xa: /* SRSHL, URSHL */
11383             {
11384                 static NeonGenTwoOpFn * const fns[3][2] = {
11385                     { gen_helper_neon_rshl_s8, gen_helper_neon_rshl_u8 },
11386                     { gen_helper_neon_rshl_s16, gen_helper_neon_rshl_u16 },
11387                     { gen_helper_neon_rshl_s32, gen_helper_neon_rshl_u32 },
11388                 };
11389                 genfn = fns[size][u];
11390                 break;
11391             }
11392             case 0xb: /* SQRSHL, UQRSHL */
11393             {
11394                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
11395                     { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
11396                     { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
11397                     { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
11398                 };
11399                 genenvfn = fns[size][u];
11400                 break;
11401             }
11402             case 0xe: /* SABD, UABD */
11403             case 0xf: /* SABA, UABA */
11404             {
11405                 static NeonGenTwoOpFn * const fns[3][2] = {
11406                     { gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 },
11407                     { gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 },
11408                     { gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 },
11409                 };
11410                 genfn = fns[size][u];
11411                 break;
11412             }
11413             case 0x13: /* MUL, PMUL */
11414                 assert(u); /* PMUL */
11415                 assert(size == 0);
11416                 genfn = gen_helper_neon_mul_p8;
11417                 break;
11418             case 0x16: /* SQDMULH, SQRDMULH */
11419             {
11420                 static NeonGenTwoOpEnvFn * const fns[2][2] = {
11421                     { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
11422                     { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
11423                 };
11424                 assert(size == 1 || size == 2);
11425                 genenvfn = fns[size - 1][u];
11426                 break;
11427             }
11428             default:
11429                 g_assert_not_reached();
11430             }
11431
11432             if (genenvfn) {
11433                 genenvfn(tcg_res, cpu_env, tcg_op1, tcg_op2);
11434             } else {
11435                 genfn(tcg_res, tcg_op1, tcg_op2);
11436             }
11437
11438             if (opcode == 0xf) {
11439                 /* SABA, UABA: accumulating ops */
11440                 static NeonGenTwoOpFn * const fns[3] = {
11441                     gen_helper_neon_add_u8,
11442                     gen_helper_neon_add_u16,
11443                     tcg_gen_add_i32,
11444                 };
11445
11446                 read_vec_element_i32(s, tcg_op1, rd, pass, MO_32);
11447                 fns[size](tcg_res, tcg_op1, tcg_res);
11448             }
11449
11450             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
11451
11452             tcg_temp_free_i32(tcg_res);
11453             tcg_temp_free_i32(tcg_op1);
11454             tcg_temp_free_i32(tcg_op2);
11455         }
11456     }
11457     clear_vec_high(s, is_q, rd);
11458 }
11459
11460 /* AdvSIMD three same
11461  *  31  30  29  28       24 23  22  21 20  16 15    11  10 9    5 4    0
11462  * +---+---+---+-----------+------+---+------+--------+---+------+------+
11463  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
11464  * +---+---+---+-----------+------+---+------+--------+---+------+------+
11465  */
11466 static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
11467 {
11468     int opcode = extract32(insn, 11, 5);
11469
11470     switch (opcode) {
11471     case 0x3: /* logic ops */
11472         disas_simd_3same_logic(s, insn);
11473         break;
11474     case 0x17: /* ADDP */
11475     case 0x14: /* SMAXP, UMAXP */
11476     case 0x15: /* SMINP, UMINP */
11477     {
11478         /* Pairwise operations */
11479         int is_q = extract32(insn, 30, 1);
11480         int u = extract32(insn, 29, 1);
11481         int size = extract32(insn, 22, 2);
11482         int rm = extract32(insn, 16, 5);
11483         int rn = extract32(insn, 5, 5);
11484         int rd = extract32(insn, 0, 5);
11485         if (opcode == 0x17) {
11486             if (u || (size == 3 && !is_q)) {
11487                 unallocated_encoding(s);
11488                 return;
11489             }
11490         } else {
11491             if (size == 3) {
11492                 unallocated_encoding(s);
11493                 return;
11494             }
11495         }
11496         handle_simd_3same_pair(s, is_q, u, opcode, size, rn, rm, rd);
11497         break;
11498     }
11499     case 0x18 ... 0x31:
11500         /* floating point ops, sz[1] and U are part of opcode */
11501         disas_simd_3same_float(s, insn);
11502         break;
11503     default:
11504         disas_simd_3same_int(s, insn);
11505         break;
11506     }
11507 }
11508
11509 /*
11510  * Advanced SIMD three same (ARMv8.2 FP16 variants)
11511  *
11512  *  31  30  29  28       24 23  22 21 20  16 15 14 13    11 10  9    5 4    0
11513  * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
11514  * | 0 | Q | U | 0 1 1 1 0 | a | 1 0 |  Rm  | 0 0 | opcode | 1 |  Rn  |  Rd  |
11515  * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
11516  *
11517  * This includes FMULX, FCMEQ (register), FRECPS, FRSQRTS, FCMGE
11518  * (register), FACGE, FABD, FCMGT (register) and FACGT.
11519  *
11520  */
11521 static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
11522 {
11523     int opcode, fpopcode;
11524     int is_q, u, a, rm, rn, rd;
11525     int datasize, elements;
11526     int pass;
11527     TCGv_ptr fpst;
11528     bool pairwise = false;
11529
11530     if (!dc_isar_feature(aa64_fp16, s)) {
11531         unallocated_encoding(s);
11532         return;
11533     }
11534
11535     if (!fp_access_check(s)) {
11536         return;
11537     }
11538
11539     /* For these floating point ops, the U, a and opcode bits
11540      * together indicate the operation.
11541      */
11542     opcode = extract32(insn, 11, 3);
11543     u = extract32(insn, 29, 1);
11544     a = extract32(insn, 23, 1);
11545     is_q = extract32(insn, 30, 1);
11546     rm = extract32(insn, 16, 5);
11547     rn = extract32(insn, 5, 5);
11548     rd = extract32(insn, 0, 5);
11549
11550     fpopcode = opcode | (a << 3) |  (u << 4);
11551     datasize = is_q ? 128 : 64;
11552     elements = datasize / 16;
11553
11554     switch (fpopcode) {
11555     case 0x10: /* FMAXNMP */
11556     case 0x12: /* FADDP */
11557     case 0x16: /* FMAXP */
11558     case 0x18: /* FMINNMP */
11559     case 0x1e: /* FMINP */
11560         pairwise = true;
11561         break;
11562     }
11563
11564     fpst = get_fpstatus_ptr(true);
11565
11566     if (pairwise) {
11567         int maxpass = is_q ? 8 : 4;
11568         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11569         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11570         TCGv_i32 tcg_res[8];
11571
11572         for (pass = 0; pass < maxpass; pass++) {
11573             int passreg = pass < (maxpass / 2) ? rn : rm;
11574             int passelt = (pass << 1) & (maxpass - 1);
11575
11576             read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_16);
11577             read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_16);
11578             tcg_res[pass] = tcg_temp_new_i32();
11579
11580             switch (fpopcode) {
11581             case 0x10: /* FMAXNMP */
11582                 gen_helper_advsimd_maxnumh(tcg_res[pass], tcg_op1, tcg_op2,
11583                                            fpst);
11584                 break;
11585             case 0x12: /* FADDP */
11586                 gen_helper_advsimd_addh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11587                 break;
11588             case 0x16: /* FMAXP */
11589                 gen_helper_advsimd_maxh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11590                 break;
11591             case 0x18: /* FMINNMP */
11592                 gen_helper_advsimd_minnumh(tcg_res[pass], tcg_op1, tcg_op2,
11593                                            fpst);
11594                 break;
11595             case 0x1e: /* FMINP */
11596                 gen_helper_advsimd_minh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11597                 break;
11598             default:
11599                 g_assert_not_reached();
11600             }
11601         }
11602
11603         for (pass = 0; pass < maxpass; pass++) {
11604             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_16);
11605             tcg_temp_free_i32(tcg_res[pass]);
11606         }
11607
11608         tcg_temp_free_i32(tcg_op1);
11609         tcg_temp_free_i32(tcg_op2);
11610
11611     } else {
11612         for (pass = 0; pass < elements; pass++) {
11613             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11614             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11615             TCGv_i32 tcg_res = tcg_temp_new_i32();
11616
11617             read_vec_element_i32(s, tcg_op1, rn, pass, MO_16);
11618             read_vec_element_i32(s, tcg_op2, rm, pass, MO_16);
11619
11620             switch (fpopcode) {
11621             case 0x0: /* FMAXNM */
11622                 gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
11623                 break;
11624             case 0x1: /* FMLA */
11625                 read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11626                 gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
11627                                            fpst);
11628                 break;
11629             case 0x2: /* FADD */
11630                 gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
11631                 break;
11632             case 0x3: /* FMULX */
11633                 gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
11634                 break;
11635             case 0x4: /* FCMEQ */
11636                 gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11637                 break;
11638             case 0x6: /* FMAX */
11639                 gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
11640                 break;
11641             case 0x7: /* FRECPS */
11642                 gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11643                 break;
11644             case 0x8: /* FMINNM */
11645                 gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
11646                 break;
11647             case 0x9: /* FMLS */
11648                 /* As usual for ARM, separate negation for fused multiply-add */
11649                 tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
11650                 read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11651                 gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
11652                                            fpst);
11653                 break;
11654             case 0xa: /* FSUB */
11655                 gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
11656                 break;
11657             case 0xe: /* FMIN */
11658                 gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
11659                 break;
11660             case 0xf: /* FRSQRTS */
11661                 gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11662                 break;
11663             case 0x13: /* FMUL */
11664                 gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
11665                 break;
11666             case 0x14: /* FCMGE */
11667                 gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11668                 break;
11669             case 0x15: /* FACGE */
11670                 gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11671                 break;
11672             case 0x17: /* FDIV */
11673                 gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
11674                 break;
11675             case 0x1a: /* FABD */
11676                 gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
11677                 tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
11678                 break;
11679             case 0x1c: /* FCMGT */
11680                 gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11681                 break;
11682             case 0x1d: /* FACGT */
11683                 gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11684                 break;
11685             default:
11686                 fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n",
11687                         __func__, insn, fpopcode, s->pc);
11688                 g_assert_not_reached();
11689             }
11690
11691             write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11692             tcg_temp_free_i32(tcg_res);
11693             tcg_temp_free_i32(tcg_op1);
11694             tcg_temp_free_i32(tcg_op2);
11695         }
11696     }
11697
11698     tcg_temp_free_ptr(fpst);
11699
11700     clear_vec_high(s, is_q, rd);
11701 }
11702
11703 /* AdvSIMD three same extra
11704  *  31   30  29 28       24 23  22  21 20  16  15 14    11  10 9  5 4  0
11705  * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
11706  * | 0 | Q | U | 0 1 1 1 0 | size | 0 |  Rm  | 1 | opcode | 1 | Rn | Rd |
11707  * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
11708  */
11709 static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
11710 {
11711     int rd = extract32(insn, 0, 5);
11712     int rn = extract32(insn, 5, 5);
11713     int opcode = extract32(insn, 11, 4);
11714     int rm = extract32(insn, 16, 5);
11715     int size = extract32(insn, 22, 2);
11716     bool u = extract32(insn, 29, 1);
11717     bool is_q = extract32(insn, 30, 1);
11718     bool feature;
11719     int rot;
11720
11721     switch (u * 16 + opcode) {
11722     case 0x10: /* SQRDMLAH (vector) */
11723     case 0x11: /* SQRDMLSH (vector) */
11724         if (size != 1 && size != 2) {
11725             unallocated_encoding(s);
11726             return;
11727         }
11728         feature = dc_isar_feature(aa64_rdm, s);
11729         break;
11730     case 0x02: /* SDOT (vector) */
11731     case 0x12: /* UDOT (vector) */
11732         if (size != MO_32) {
11733             unallocated_encoding(s);
11734             return;
11735         }
11736         feature = dc_isar_feature(aa64_dp, s);
11737         break;
11738     case 0x18: /* FCMLA, #0 */
11739     case 0x19: /* FCMLA, #90 */
11740     case 0x1a: /* FCMLA, #180 */
11741     case 0x1b: /* FCMLA, #270 */
11742     case 0x1c: /* FCADD, #90 */
11743     case 0x1e: /* FCADD, #270 */
11744         if (size == 0
11745             || (size == 1 && !dc_isar_feature(aa64_fp16, s))
11746             || (size == 3 && !is_q)) {
11747             unallocated_encoding(s);
11748             return;
11749         }
11750         feature = dc_isar_feature(aa64_fcma, s);
11751         break;
11752     default:
11753         unallocated_encoding(s);
11754         return;
11755     }
11756     if (!feature) {
11757         unallocated_encoding(s);
11758         return;
11759     }
11760     if (!fp_access_check(s)) {
11761         return;
11762     }
11763
11764     switch (opcode) {
11765     case 0x0: /* SQRDMLAH (vector) */
11766         switch (size) {
11767         case 1:
11768             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
11769             break;
11770         case 2:
11771             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
11772             break;
11773         default:
11774             g_assert_not_reached();
11775         }
11776         return;
11777
11778     case 0x1: /* SQRDMLSH (vector) */
11779         switch (size) {
11780         case 1:
11781             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
11782             break;
11783         case 2:
11784             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
11785             break;
11786         default:
11787             g_assert_not_reached();
11788         }
11789         return;
11790
11791     case 0x2: /* SDOT / UDOT */
11792         gen_gvec_op3_ool(s, is_q, rd, rn, rm, 0,
11793                          u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b);
11794         return;
11795
11796     case 0x8: /* FCMLA, #0 */
11797     case 0x9: /* FCMLA, #90 */
11798     case 0xa: /* FCMLA, #180 */
11799     case 0xb: /* FCMLA, #270 */
11800         rot = extract32(opcode, 0, 2);
11801         switch (size) {
11802         case 1:
11803             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
11804                               gen_helper_gvec_fcmlah);
11805             break;
11806         case 2:
11807             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
11808                               gen_helper_gvec_fcmlas);
11809             break;
11810         case 3:
11811             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
11812                               gen_helper_gvec_fcmlad);
11813             break;
11814         default:
11815             g_assert_not_reached();
11816         }
11817         return;
11818
11819     case 0xc: /* FCADD, #90 */
11820     case 0xe: /* FCADD, #270 */
11821         rot = extract32(opcode, 1, 1);
11822         switch (size) {
11823         case 1:
11824             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11825                               gen_helper_gvec_fcaddh);
11826             break;
11827         case 2:
11828             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11829                               gen_helper_gvec_fcadds);
11830             break;
11831         case 3:
11832             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11833                               gen_helper_gvec_fcaddd);
11834             break;
11835         default:
11836             g_assert_not_reached();
11837         }
11838         return;
11839
11840     default:
11841         g_assert_not_reached();
11842     }
11843 }
11844
11845 static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
11846                                   int size, int rn, int rd)
11847 {
11848     /* Handle 2-reg-misc ops which are widening (so each size element
11849      * in the source becomes a 2*size element in the destination.
11850      * The only instruction like this is FCVTL.
11851      */
11852     int pass;
11853
11854     if (size == 3) {
11855         /* 32 -> 64 bit fp conversion */
11856         TCGv_i64 tcg_res[2];
11857         int srcelt = is_q ? 2 : 0;
11858
11859         for (pass = 0; pass < 2; pass++) {
11860             TCGv_i32 tcg_op = tcg_temp_new_i32();
11861             tcg_res[pass] = tcg_temp_new_i64();
11862
11863             read_vec_element_i32(s, tcg_op, rn, srcelt + pass, MO_32);
11864             gen_helper_vfp_fcvtds(tcg_res[pass], tcg_op, cpu_env);
11865             tcg_temp_free_i32(tcg_op);
11866         }
11867         for (pass = 0; pass < 2; pass++) {
11868             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
11869             tcg_temp_free_i64(tcg_res[pass]);
11870         }
11871     } else {
11872         /* 16 -> 32 bit fp conversion */
11873         int srcelt = is_q ? 4 : 0;
11874         TCGv_i32 tcg_res[4];
11875         TCGv_ptr fpst = get_fpstatus_ptr(false);
11876         TCGv_i32 ahp = get_ahp_flag();
11877
11878         for (pass = 0; pass < 4; pass++) {
11879             tcg_res[pass] = tcg_temp_new_i32();
11880
11881             read_vec_element_i32(s, tcg_res[pass], rn, srcelt + pass, MO_16);
11882             gen_helper_vfp_fcvt_f16_to_f32(tcg_res[pass], tcg_res[pass],
11883                                            fpst, ahp);
11884         }
11885         for (pass = 0; pass < 4; pass++) {
11886             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
11887             tcg_temp_free_i32(tcg_res[pass]);
11888         }
11889
11890         tcg_temp_free_ptr(fpst);
11891         tcg_temp_free_i32(ahp);
11892     }
11893 }
11894
11895 static void handle_rev(DisasContext *s, int opcode, bool u,
11896                        bool is_q, int size, int rn, int rd)
11897 {
11898     int op = (opcode << 1) | u;
11899     int opsz = op + size;
11900     int grp_size = 3 - opsz;
11901     int dsize = is_q ? 128 : 64;
11902     int i;
11903
11904     if (opsz >= 3) {
11905         unallocated_encoding(s);
11906         return;
11907     }
11908
11909     if (!fp_access_check(s)) {
11910         return;
11911     }
11912
11913     if (size == 0) {
11914         /* Special case bytes, use bswap op on each group of elements */
11915         int groups = dsize / (8 << grp_size);
11916
11917         for (i = 0; i < groups; i++) {
11918             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
11919
11920             read_vec_element(s, tcg_tmp, rn, i, grp_size);
11921             switch (grp_size) {
11922             case MO_16:
11923                 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
11924                 break;
11925             case MO_32:
11926                 tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
11927                 break;
11928             case MO_64:
11929                 tcg_gen_bswap64_i64(tcg_tmp, tcg_tmp);
11930                 break;
11931             default:
11932                 g_assert_not_reached();
11933             }
11934             write_vec_element(s, tcg_tmp, rd, i, grp_size);
11935             tcg_temp_free_i64(tcg_tmp);
11936         }
11937         clear_vec_high(s, is_q, rd);
11938     } else {
11939         int revmask = (1 << grp_size) - 1;
11940         int esize = 8 << size;
11941         int elements = dsize / esize;
11942         TCGv_i64 tcg_rn = tcg_temp_new_i64();
11943         TCGv_i64 tcg_rd = tcg_const_i64(0);
11944         TCGv_i64 tcg_rd_hi = tcg_const_i64(0);
11945
11946         for (i = 0; i < elements; i++) {
11947             int e_rev = (i & 0xf) ^ revmask;
11948             int off = e_rev * esize;
11949             read_vec_element(s, tcg_rn, rn, i, size);
11950             if (off >= 64) {
11951                 tcg_gen_deposit_i64(tcg_rd_hi, tcg_rd_hi,
11952                                     tcg_rn, off - 64, esize);
11953             } else {
11954                 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, off, esize);
11955             }
11956         }
11957         write_vec_element(s, tcg_rd, rd, 0, MO_64);
11958         write_vec_element(s, tcg_rd_hi, rd, 1, MO_64);
11959
11960         tcg_temp_free_i64(tcg_rd_hi);
11961         tcg_temp_free_i64(tcg_rd);
11962         tcg_temp_free_i64(tcg_rn);
11963     }
11964 }
11965
11966 static void handle_2misc_pairwise(DisasContext *s, int opcode, bool u,
11967                                   bool is_q, int size, int rn, int rd)
11968 {
11969     /* Implement the pairwise operations from 2-misc:
11970      * SADDLP, UADDLP, SADALP, UADALP.
11971      * These all add pairs of elements in the input to produce a
11972      * double-width result element in the output (possibly accumulating).
11973      */
11974     bool accum = (opcode == 0x6);
11975     int maxpass = is_q ? 2 : 1;
11976     int pass;
11977     TCGv_i64 tcg_res[2];
11978
11979     if (size == 2) {
11980         /* 32 + 32 -> 64 op */
11981         TCGMemOp memop = size + (u ? 0 : MO_SIGN);
11982
11983         for (pass = 0; pass < maxpass; pass++) {
11984             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
11985             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
11986
11987             tcg_res[pass] = tcg_temp_new_i64();
11988
11989             read_vec_element(s, tcg_op1, rn, pass * 2, memop);
11990             read_vec_element(s, tcg_op2, rn, pass * 2 + 1, memop);
11991             tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
11992             if (accum) {
11993                 read_vec_element(s, tcg_op1, rd, pass, MO_64);
11994                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
11995             }
11996
11997             tcg_temp_free_i64(tcg_op1);
11998             tcg_temp_free_i64(tcg_op2);
11999         }
12000     } else {
12001         for (pass = 0; pass < maxpass; pass++) {
12002             TCGv_i64 tcg_op = tcg_temp_new_i64();
12003             NeonGenOneOpFn *genfn;
12004             static NeonGenOneOpFn * const fns[2][2] = {
12005                 { gen_helper_neon_addlp_s8,  gen_helper_neon_addlp_u8 },
12006                 { gen_helper_neon_addlp_s16,  gen_helper_neon_addlp_u16 },
12007             };
12008
12009             genfn = fns[size][u];
12010
12011             tcg_res[pass] = tcg_temp_new_i64();
12012
12013             read_vec_element(s, tcg_op, rn, pass, MO_64);
12014             genfn(tcg_res[pass], tcg_op);
12015
12016             if (accum) {
12017                 read_vec_element(s, tcg_op, rd, pass, MO_64);
12018                 if (size == 0) {
12019                     gen_helper_neon_addl_u16(tcg_res[pass],
12020                                              tcg_res[pass], tcg_op);
12021                 } else {
12022                     gen_helper_neon_addl_u32(tcg_res[pass],
12023                                              tcg_res[pass], tcg_op);
12024                 }
12025             }
12026             tcg_temp_free_i64(tcg_op);
12027         }
12028     }
12029     if (!is_q) {
12030         tcg_res[1] = tcg_const_i64(0);
12031     }
12032     for (pass = 0; pass < 2; pass++) {
12033         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
12034         tcg_temp_free_i64(tcg_res[pass]);
12035     }
12036 }
12037
12038 static void handle_shll(DisasContext *s, bool is_q, int size, int rn, int rd)
12039 {
12040     /* Implement SHLL and SHLL2 */
12041     int pass;
12042     int part = is_q ? 2 : 0;
12043     TCGv_i64 tcg_res[2];
12044
12045     for (pass = 0; pass < 2; pass++) {
12046         static NeonGenWidenFn * const widenfns[3] = {
12047             gen_helper_neon_widen_u8,
12048             gen_helper_neon_widen_u16,
12049             tcg_gen_extu_i32_i64,
12050         };
12051         NeonGenWidenFn *widenfn = widenfns[size];
12052         TCGv_i32 tcg_op = tcg_temp_new_i32();
12053
12054         read_vec_element_i32(s, tcg_op, rn, part + pass, MO_32);
12055         tcg_res[pass] = tcg_temp_new_i64();
12056         widenfn(tcg_res[pass], tcg_op);
12057         tcg_gen_shli_i64(tcg_res[pass], tcg_res[pass], 8 << size);
12058
12059         tcg_temp_free_i32(tcg_op);
12060     }
12061
12062     for (pass = 0; pass < 2; pass++) {
12063         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
12064         tcg_temp_free_i64(tcg_res[pass]);
12065     }
12066 }
12067
12068 /* AdvSIMD two reg misc
12069  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
12070  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
12071  * | 0 | Q | U | 0 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
12072  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
12073  */
12074 static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
12075 {
12076     int size = extract32(insn, 22, 2);
12077     int opcode = extract32(insn, 12, 5);
12078     bool u = extract32(insn, 29, 1);
12079     bool is_q = extract32(insn, 30, 1);
12080     int rn = extract32(insn, 5, 5);
12081     int rd = extract32(insn, 0, 5);
12082     bool need_fpstatus = false;
12083     bool need_rmode = false;
12084     int rmode = -1;
12085     TCGv_i32 tcg_rmode;
12086     TCGv_ptr tcg_fpstatus;
12087
12088     switch (opcode) {
12089     case 0x0: /* REV64, REV32 */
12090     case 0x1: /* REV16 */
12091         handle_rev(s, opcode, u, is_q, size, rn, rd);
12092         return;
12093     case 0x5: /* CNT, NOT, RBIT */
12094         if (u && size == 0) {
12095             /* NOT */
12096             break;
12097         } else if (u && size == 1) {
12098             /* RBIT */
12099             break;
12100         } else if (!u && size == 0) {
12101             /* CNT */
12102             break;
12103         }
12104         unallocated_encoding(s);
12105         return;
12106     case 0x12: /* XTN, XTN2, SQXTUN, SQXTUN2 */
12107     case 0x14: /* SQXTN, SQXTN2, UQXTN, UQXTN2 */
12108         if (size == 3) {
12109             unallocated_encoding(s);
12110             return;
12111         }
12112         if (!fp_access_check(s)) {
12113             return;
12114         }
12115
12116         handle_2misc_narrow(s, false, opcode, u, is_q, size, rn, rd);
12117         return;
12118     case 0x4: /* CLS, CLZ */
12119         if (size == 3) {
12120             unallocated_encoding(s);
12121             return;
12122         }
12123         break;
12124     case 0x2: /* SADDLP, UADDLP */
12125     case 0x6: /* SADALP, UADALP */
12126         if (size == 3) {
12127             unallocated_encoding(s);
12128             return;
12129         }
12130         if (!fp_access_check(s)) {
12131             return;
12132         }
12133         handle_2misc_pairwise(s, opcode, u, is_q, size, rn, rd);
12134         return;
12135     case 0x13: /* SHLL, SHLL2 */
12136         if (u == 0 || size == 3) {
12137             unallocated_encoding(s);
12138             return;
12139         }
12140         if (!fp_access_check(s)) {
12141             return;
12142         }
12143         handle_shll(s, is_q, size, rn, rd);
12144         return;
12145     case 0xa: /* CMLT */
12146         if (u == 1) {
12147             unallocated_encoding(s);
12148             return;
12149         }
12150         /* fall through */
12151     case 0x8: /* CMGT, CMGE */
12152     case 0x9: /* CMEQ, CMLE */
12153     case 0xb: /* ABS, NEG */
12154         if (size == 3 && !is_q) {
12155             unallocated_encoding(s);
12156             return;
12157         }
12158         break;
12159     case 0x3: /* SUQADD, USQADD */
12160         if (size == 3 && !is_q) {
12161             unallocated_encoding(s);
12162             return;
12163         }
12164         if (!fp_access_check(s)) {
12165             return;
12166         }
12167         handle_2misc_satacc(s, false, u, is_q, size, rn, rd);
12168         return;
12169     case 0x7: /* SQABS, SQNEG */
12170         if (size == 3 && !is_q) {
12171             unallocated_encoding(s);
12172             return;
12173         }
12174         break;
12175     case 0xc ... 0xf:
12176     case 0x16 ... 0x1f:
12177     {
12178         /* Floating point: U, size[1] and opcode indicate operation;
12179          * size[0] indicates single or double precision.
12180          */
12181         int is_double = extract32(size, 0, 1);
12182         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
12183         size = is_double ? 3 : 2;
12184         switch (opcode) {
12185         case 0x2f: /* FABS */
12186         case 0x6f: /* FNEG */
12187             if (size == 3 && !is_q) {
12188                 unallocated_encoding(s);
12189                 return;
12190             }
12191             break;
12192         case 0x1d: /* SCVTF */
12193         case 0x5d: /* UCVTF */
12194         {
12195             bool is_signed = (opcode == 0x1d) ? true : false;
12196             int elements = is_double ? 2 : is_q ? 4 : 2;
12197             if (is_double && !is_q) {
12198                 unallocated_encoding(s);
12199                 return;
12200             }
12201             if (!fp_access_check(s)) {
12202                 return;
12203             }
12204             handle_simd_intfp_conv(s, rd, rn, elements, is_signed, 0, size);
12205             return;
12206         }
12207         case 0x2c: /* FCMGT (zero) */
12208         case 0x2d: /* FCMEQ (zero) */
12209         case 0x2e: /* FCMLT (zero) */
12210         case 0x6c: /* FCMGE (zero) */
12211         case 0x6d: /* FCMLE (zero) */
12212             if (size == 3 && !is_q) {
12213                 unallocated_encoding(s);
12214                 return;
12215             }
12216             handle_2misc_fcmp_zero(s, opcode, false, u, is_q, size, rn, rd);
12217             return;
12218         case 0x7f: /* FSQRT */
12219             if (size == 3 && !is_q) {
12220                 unallocated_encoding(s);
12221                 return;
12222             }
12223             break;
12224         case 0x1a: /* FCVTNS */
12225         case 0x1b: /* FCVTMS */
12226         case 0x3a: /* FCVTPS */
12227         case 0x3b: /* FCVTZS */
12228         case 0x5a: /* FCVTNU */
12229         case 0x5b: /* FCVTMU */
12230         case 0x7a: /* FCVTPU */
12231         case 0x7b: /* FCVTZU */
12232             need_fpstatus = true;
12233             need_rmode = true;
12234             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
12235             if (size == 3 && !is_q) {
12236                 unallocated_encoding(s);
12237                 return;
12238             }
12239             break;
12240         case 0x5c: /* FCVTAU */
12241         case 0x1c: /* FCVTAS */
12242             need_fpstatus = true;
12243             need_rmode = true;
12244             rmode = FPROUNDING_TIEAWAY;
12245             if (size == 3 && !is_q) {
12246                 unallocated_encoding(s);
12247                 return;
12248             }
12249             break;
12250         case 0x3c: /* URECPE */
12251             if (size == 3) {
12252                 unallocated_encoding(s);
12253                 return;
12254             }
12255             /* fall through */
12256         case 0x3d: /* FRECPE */
12257         case 0x7d: /* FRSQRTE */
12258             if (size == 3 && !is_q) {
12259                 unallocated_encoding(s);
12260                 return;
12261             }
12262             if (!fp_access_check(s)) {
12263                 return;
12264             }
12265             handle_2misc_reciprocal(s, opcode, false, u, is_q, size, rn, rd);
12266             return;
12267         case 0x56: /* FCVTXN, FCVTXN2 */
12268             if (size == 2) {
12269                 unallocated_encoding(s);
12270                 return;
12271             }
12272             /* fall through */
12273         case 0x16: /* FCVTN, FCVTN2 */
12274             /* handle_2misc_narrow does a 2*size -> size operation, but these
12275              * instructions encode the source size rather than dest size.
12276              */
12277             if (!fp_access_check(s)) {
12278                 return;
12279             }
12280             handle_2misc_narrow(s, false, opcode, 0, is_q, size - 1, rn, rd);
12281             return;
12282         case 0x17: /* FCVTL, FCVTL2 */
12283             if (!fp_access_check(s)) {
12284                 return;
12285             }
12286             handle_2misc_widening(s, opcode, is_q, size, rn, rd);
12287             return;
12288         case 0x18: /* FRINTN */
12289         case 0x19: /* FRINTM */
12290         case 0x38: /* FRINTP */
12291         case 0x39: /* FRINTZ */
12292             need_rmode = true;
12293             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
12294             /* fall through */
12295         case 0x59: /* FRINTX */
12296         case 0x79: /* FRINTI */
12297             need_fpstatus = true;
12298             if (size == 3 && !is_q) {
12299                 unallocated_encoding(s);
12300                 return;
12301             }
12302             break;
12303         case 0x58: /* FRINTA */
12304             need_rmode = true;
12305             rmode = FPROUNDING_TIEAWAY;
12306             need_fpstatus = true;
12307             if (size == 3 && !is_q) {
12308                 unallocated_encoding(s);
12309                 return;
12310             }
12311             break;
12312         case 0x7c: /* URSQRTE */
12313             if (size == 3) {
12314                 unallocated_encoding(s);
12315                 return;
12316             }
12317             need_fpstatus = true;
12318             break;
12319         case 0x1e: /* FRINT32Z */
12320         case 0x1f: /* FRINT64Z */
12321             need_rmode = true;
12322             rmode = FPROUNDING_ZERO;
12323             /* fall through */
12324         case 0x5e: /* FRINT32X */
12325         case 0x5f: /* FRINT64X */
12326             need_fpstatus = true;
12327             if ((size == 3 && !is_q) || !dc_isar_feature(aa64_frint, s)) {
12328                 unallocated_encoding(s);
12329                 return;
12330             }
12331             break;
12332         default:
12333             unallocated_encoding(s);
12334             return;
12335         }
12336         break;
12337     }
12338     default:
12339         unallocated_encoding(s);
12340         return;
12341     }
12342
12343     if (!fp_access_check(s)) {
12344         return;
12345     }
12346
12347     if (need_fpstatus || need_rmode) {
12348         tcg_fpstatus = get_fpstatus_ptr(false);
12349     } else {
12350         tcg_fpstatus = NULL;
12351     }
12352     if (need_rmode) {
12353         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
12354         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12355     } else {
12356         tcg_rmode = NULL;
12357     }
12358
12359     switch (opcode) {
12360     case 0x5:
12361         if (u && size == 0) { /* NOT */
12362             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_not, 0);
12363             return;
12364         }
12365         break;
12366     case 0xb:
12367         if (u) { /* ABS, NEG */
12368             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_neg, size);
12369         } else {
12370             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_abs, size);
12371         }
12372         return;
12373     }
12374
12375     if (size == 3) {
12376         /* All 64-bit element operations can be shared with scalar 2misc */
12377         int pass;
12378
12379         /* Coverity claims (size == 3 && !is_q) has been eliminated
12380          * from all paths leading to here.
12381          */
12382         tcg_debug_assert(is_q);
12383         for (pass = 0; pass < 2; pass++) {
12384             TCGv_i64 tcg_op = tcg_temp_new_i64();
12385             TCGv_i64 tcg_res = tcg_temp_new_i64();
12386
12387             read_vec_element(s, tcg_op, rn, pass, MO_64);
12388
12389             handle_2misc_64(s, opcode, u, tcg_res, tcg_op,
12390                             tcg_rmode, tcg_fpstatus);
12391
12392             write_vec_element(s, tcg_res, rd, pass, MO_64);
12393
12394             tcg_temp_free_i64(tcg_res);
12395             tcg_temp_free_i64(tcg_op);
12396         }
12397     } else {
12398         int pass;
12399
12400         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
12401             TCGv_i32 tcg_op = tcg_temp_new_i32();
12402             TCGv_i32 tcg_res = tcg_temp_new_i32();
12403             TCGCond cond;
12404
12405             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
12406
12407             if (size == 2) {
12408                 /* Special cases for 32 bit elements */
12409                 switch (opcode) {
12410                 case 0xa: /* CMLT */
12411                     /* 32 bit integer comparison against zero, result is
12412                      * test ? (2^32 - 1) : 0. We implement via setcond(test)
12413                      * and inverting.
12414                      */
12415                     cond = TCG_COND_LT;
12416                 do_cmop:
12417                     tcg_gen_setcondi_i32(cond, tcg_res, tcg_op, 0);
12418                     tcg_gen_neg_i32(tcg_res, tcg_res);
12419                     break;
12420                 case 0x8: /* CMGT, CMGE */
12421                     cond = u ? TCG_COND_GE : TCG_COND_GT;
12422                     goto do_cmop;
12423                 case 0x9: /* CMEQ, CMLE */
12424                     cond = u ? TCG_COND_LE : TCG_COND_EQ;
12425                     goto do_cmop;
12426                 case 0x4: /* CLS */
12427                     if (u) {
12428                         tcg_gen_clzi_i32(tcg_res, tcg_op, 32);
12429                     } else {
12430                         tcg_gen_clrsb_i32(tcg_res, tcg_op);
12431                     }
12432                     break;
12433                 case 0x7: /* SQABS, SQNEG */
12434                     if (u) {
12435                         gen_helper_neon_qneg_s32(tcg_res, cpu_env, tcg_op);
12436                     } else {
12437                         gen_helper_neon_qabs_s32(tcg_res, cpu_env, tcg_op);
12438                     }
12439                     break;
12440                 case 0x2f: /* FABS */
12441                     gen_helper_vfp_abss(tcg_res, tcg_op);
12442                     break;
12443                 case 0x6f: /* FNEG */
12444                     gen_helper_vfp_negs(tcg_res, tcg_op);
12445                     break;
12446                 case 0x7f: /* FSQRT */
12447                     gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
12448                     break;
12449                 case 0x1a: /* FCVTNS */
12450                 case 0x1b: /* FCVTMS */
12451                 case 0x1c: /* FCVTAS */
12452                 case 0x3a: /* FCVTPS */
12453                 case 0x3b: /* FCVTZS */
12454                 {
12455                     TCGv_i32 tcg_shift = tcg_const_i32(0);
12456                     gen_helper_vfp_tosls(tcg_res, tcg_op,
12457                                          tcg_shift, tcg_fpstatus);
12458                     tcg_temp_free_i32(tcg_shift);
12459                     break;
12460                 }
12461                 case 0x5a: /* FCVTNU */
12462                 case 0x5b: /* FCVTMU */
12463                 case 0x5c: /* FCVTAU */
12464                 case 0x7a: /* FCVTPU */
12465                 case 0x7b: /* FCVTZU */
12466                 {
12467                     TCGv_i32 tcg_shift = tcg_const_i32(0);
12468                     gen_helper_vfp_touls(tcg_res, tcg_op,
12469                                          tcg_shift, tcg_fpstatus);
12470                     tcg_temp_free_i32(tcg_shift);
12471                     break;
12472                 }
12473                 case 0x18: /* FRINTN */
12474                 case 0x19: /* FRINTM */
12475                 case 0x38: /* FRINTP */
12476                 case 0x39: /* FRINTZ */
12477                 case 0x58: /* FRINTA */
12478                 case 0x79: /* FRINTI */
12479                     gen_helper_rints(tcg_res, tcg_op, tcg_fpstatus);
12480                     break;
12481                 case 0x59: /* FRINTX */
12482                     gen_helper_rints_exact(tcg_res, tcg_op, tcg_fpstatus);
12483                     break;
12484                 case 0x7c: /* URSQRTE */
12485                     gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
12486                     break;
12487                 case 0x1e: /* FRINT32Z */
12488                 case 0x5e: /* FRINT32X */
12489                     gen_helper_frint32_s(tcg_res, tcg_op, tcg_fpstatus);
12490                     break;
12491                 case 0x1f: /* FRINT64Z */
12492                 case 0x5f: /* FRINT64X */
12493                     gen_helper_frint64_s(tcg_res, tcg_op, tcg_fpstatus);
12494                     break;
12495                 default:
12496                     g_assert_not_reached();
12497                 }
12498             } else {
12499                 /* Use helpers for 8 and 16 bit elements */
12500                 switch (opcode) {
12501                 case 0x5: /* CNT, RBIT */
12502                     /* For these two insns size is part of the opcode specifier
12503                      * (handled earlier); they always operate on byte elements.
12504                      */
12505                     if (u) {
12506                         gen_helper_neon_rbit_u8(tcg_res, tcg_op);
12507                     } else {
12508                         gen_helper_neon_cnt_u8(tcg_res, tcg_op);
12509                     }
12510                     break;
12511                 case 0x7: /* SQABS, SQNEG */
12512                 {
12513                     NeonGenOneOpEnvFn *genfn;
12514                     static NeonGenOneOpEnvFn * const fns[2][2] = {
12515                         { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
12516                         { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
12517                     };
12518                     genfn = fns[size][u];
12519                     genfn(tcg_res, cpu_env, tcg_op);
12520                     break;
12521                 }
12522                 case 0x8: /* CMGT, CMGE */
12523                 case 0x9: /* CMEQ, CMLE */
12524                 case 0xa: /* CMLT */
12525                 {
12526                     static NeonGenTwoOpFn * const fns[3][2] = {
12527                         { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_s16 },
12528                         { gen_helper_neon_cge_s8, gen_helper_neon_cge_s16 },
12529                         { gen_helper_neon_ceq_u8, gen_helper_neon_ceq_u16 },
12530                     };
12531                     NeonGenTwoOpFn *genfn;
12532                     int comp;
12533                     bool reverse;
12534                     TCGv_i32 tcg_zero = tcg_const_i32(0);
12535
12536                     /* comp = index into [CMGT, CMGE, CMEQ, CMLE, CMLT] */
12537                     comp = (opcode - 0x8) * 2 + u;
12538                     /* ...but LE, LT are implemented as reverse GE, GT */
12539                     reverse = (comp > 2);
12540                     if (reverse) {
12541                         comp = 4 - comp;
12542                     }
12543                     genfn = fns[comp][size];
12544                     if (reverse) {
12545                         genfn(tcg_res, tcg_zero, tcg_op);
12546                     } else {
12547                         genfn(tcg_res, tcg_op, tcg_zero);
12548                     }
12549                     tcg_temp_free_i32(tcg_zero);
12550                     break;
12551                 }
12552                 case 0x4: /* CLS, CLZ */
12553                     if (u) {
12554                         if (size == 0) {
12555                             gen_helper_neon_clz_u8(tcg_res, tcg_op);
12556                         } else {
12557                             gen_helper_neon_clz_u16(tcg_res, tcg_op);
12558                         }
12559                     } else {
12560                         if (size == 0) {
12561                             gen_helper_neon_cls_s8(tcg_res, tcg_op);
12562                         } else {
12563                             gen_helper_neon_cls_s16(tcg_res, tcg_op);
12564                         }
12565                     }
12566                     break;
12567                 default:
12568                     g_assert_not_reached();
12569                 }
12570             }
12571
12572             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
12573
12574             tcg_temp_free_i32(tcg_res);
12575             tcg_temp_free_i32(tcg_op);
12576         }
12577     }
12578     clear_vec_high(s, is_q, rd);
12579
12580     if (need_rmode) {
12581         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12582         tcg_temp_free_i32(tcg_rmode);
12583     }
12584     if (need_fpstatus) {
12585         tcg_temp_free_ptr(tcg_fpstatus);
12586     }
12587 }
12588
12589 /* AdvSIMD [scalar] two register miscellaneous (FP16)
12590  *
12591  *   31  30  29 28  27     24  23 22 21       17 16    12 11 10 9    5 4    0
12592  * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
12593  * | 0 | Q | U | S | 1 1 1 0 | a | 1 1 1 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
12594  * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
12595  *   mask: 1000 1111 0111 1110 0000 1100 0000 0000 0x8f7e 0c00
12596  *   val:  0000 1110 0111 1000 0000 1000 0000 0000 0x0e78 0800
12597  *
12598  * This actually covers two groups where scalar access is governed by
12599  * bit 28. A bunch of the instructions (float to integral) only exist
12600  * in the vector form and are un-allocated for the scalar decode. Also
12601  * in the scalar decode Q is always 1.
12602  */
12603 static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
12604 {
12605     int fpop, opcode, a, u;
12606     int rn, rd;
12607     bool is_q;
12608     bool is_scalar;
12609     bool only_in_vector = false;
12610
12611     int pass;
12612     TCGv_i32 tcg_rmode = NULL;
12613     TCGv_ptr tcg_fpstatus = NULL;
12614     bool need_rmode = false;
12615     bool need_fpst = true;
12616     int rmode;
12617
12618     if (!dc_isar_feature(aa64_fp16, s)) {
12619         unallocated_encoding(s);
12620         return;
12621     }
12622
12623     rd = extract32(insn, 0, 5);
12624     rn = extract32(insn, 5, 5);
12625
12626     a = extract32(insn, 23, 1);
12627     u = extract32(insn, 29, 1);
12628     is_scalar = extract32(insn, 28, 1);
12629     is_q = extract32(insn, 30, 1);
12630
12631     opcode = extract32(insn, 12, 5);
12632     fpop = deposit32(opcode, 5, 1, a);
12633     fpop = deposit32(fpop, 6, 1, u);
12634
12635     rd = extract32(insn, 0, 5);
12636     rn = extract32(insn, 5, 5);
12637
12638     switch (fpop) {
12639     case 0x1d: /* SCVTF */
12640     case 0x5d: /* UCVTF */
12641     {
12642         int elements;
12643
12644         if (is_scalar) {
12645             elements = 1;
12646         } else {
12647             elements = (is_q ? 8 : 4);
12648         }
12649
12650         if (!fp_access_check(s)) {
12651             return;
12652         }
12653         handle_simd_intfp_conv(s, rd, rn, elements, !u, 0, MO_16);
12654         return;
12655     }
12656     break;
12657     case 0x2c: /* FCMGT (zero) */
12658     case 0x2d: /* FCMEQ (zero) */
12659     case 0x2e: /* FCMLT (zero) */
12660     case 0x6c: /* FCMGE (zero) */
12661     case 0x6d: /* FCMLE (zero) */
12662         handle_2misc_fcmp_zero(s, fpop, is_scalar, 0, is_q, MO_16, rn, rd);
12663         return;
12664     case 0x3d: /* FRECPE */
12665     case 0x3f: /* FRECPX */
12666         break;
12667     case 0x18: /* FRINTN */
12668         need_rmode = true;
12669         only_in_vector = true;
12670         rmode = FPROUNDING_TIEEVEN;
12671         break;
12672     case 0x19: /* FRINTM */
12673         need_rmode = true;
12674         only_in_vector = true;
12675         rmode = FPROUNDING_NEGINF;
12676         break;
12677     case 0x38: /* FRINTP */
12678         need_rmode = true;
12679         only_in_vector = true;
12680         rmode = FPROUNDING_POSINF;
12681         break;
12682     case 0x39: /* FRINTZ */
12683         need_rmode = true;
12684         only_in_vector = true;
12685         rmode = FPROUNDING_ZERO;
12686         break;
12687     case 0x58: /* FRINTA */
12688         need_rmode = true;
12689         only_in_vector = true;
12690         rmode = FPROUNDING_TIEAWAY;
12691         break;
12692     case 0x59: /* FRINTX */
12693     case 0x79: /* FRINTI */
12694         only_in_vector = true;
12695         /* current rounding mode */
12696         break;
12697     case 0x1a: /* FCVTNS */
12698         need_rmode = true;
12699         rmode = FPROUNDING_TIEEVEN;
12700         break;
12701     case 0x1b: /* FCVTMS */
12702         need_rmode = true;
12703         rmode = FPROUNDING_NEGINF;
12704         break;
12705     case 0x1c: /* FCVTAS */
12706         need_rmode = true;
12707         rmode = FPROUNDING_TIEAWAY;
12708         break;
12709     case 0x3a: /* FCVTPS */
12710         need_rmode = true;
12711         rmode = FPROUNDING_POSINF;
12712         break;
12713     case 0x3b: /* FCVTZS */
12714         need_rmode = true;
12715         rmode = FPROUNDING_ZERO;
12716         break;
12717     case 0x5a: /* FCVTNU */
12718         need_rmode = true;
12719         rmode = FPROUNDING_TIEEVEN;
12720         break;
12721     case 0x5b: /* FCVTMU */
12722         need_rmode = true;
12723         rmode = FPROUNDING_NEGINF;
12724         break;
12725     case 0x5c: /* FCVTAU */
12726         need_rmode = true;
12727         rmode = FPROUNDING_TIEAWAY;
12728         break;
12729     case 0x7a: /* FCVTPU */
12730         need_rmode = true;
12731         rmode = FPROUNDING_POSINF;
12732         break;
12733     case 0x7b: /* FCVTZU */
12734         need_rmode = true;
12735         rmode = FPROUNDING_ZERO;
12736         break;
12737     case 0x2f: /* FABS */
12738     case 0x6f: /* FNEG */
12739         need_fpst = false;
12740         break;
12741     case 0x7d: /* FRSQRTE */
12742     case 0x7f: /* FSQRT (vector) */
12743         break;
12744     default:
12745         fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop);
12746         g_assert_not_reached();
12747     }
12748
12749
12750     /* Check additional constraints for the scalar encoding */
12751     if (is_scalar) {
12752         if (!is_q) {
12753             unallocated_encoding(s);
12754             return;
12755         }
12756         /* FRINTxx is only in the vector form */
12757         if (only_in_vector) {
12758             unallocated_encoding(s);
12759             return;
12760         }
12761     }
12762
12763     if (!fp_access_check(s)) {
12764         return;
12765     }
12766
12767     if (need_rmode || need_fpst) {
12768         tcg_fpstatus = get_fpstatus_ptr(true);
12769     }
12770
12771     if (need_rmode) {
12772         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
12773         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12774     }
12775
12776     if (is_scalar) {
12777         TCGv_i32 tcg_op = read_fp_hreg(s, rn);
12778         TCGv_i32 tcg_res = tcg_temp_new_i32();
12779
12780         switch (fpop) {
12781         case 0x1a: /* FCVTNS */
12782         case 0x1b: /* FCVTMS */
12783         case 0x1c: /* FCVTAS */
12784         case 0x3a: /* FCVTPS */
12785         case 0x3b: /* FCVTZS */
12786             gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
12787             break;
12788         case 0x3d: /* FRECPE */
12789             gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
12790             break;
12791         case 0x3f: /* FRECPX */
12792             gen_helper_frecpx_f16(tcg_res, tcg_op, tcg_fpstatus);
12793             break;
12794         case 0x5a: /* FCVTNU */
12795         case 0x5b: /* FCVTMU */
12796         case 0x5c: /* FCVTAU */
12797         case 0x7a: /* FCVTPU */
12798         case 0x7b: /* FCVTZU */
12799             gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
12800             break;
12801         case 0x6f: /* FNEG */
12802             tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
12803             break;
12804         case 0x7d: /* FRSQRTE */
12805             gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
12806             break;
12807         default:
12808             g_assert_not_reached();
12809         }
12810
12811         /* limit any sign extension going on */
12812         tcg_gen_andi_i32(tcg_res, tcg_res, 0xffff);
12813         write_fp_sreg(s, rd, tcg_res);
12814
12815         tcg_temp_free_i32(tcg_res);
12816         tcg_temp_free_i32(tcg_op);
12817     } else {
12818         for (pass = 0; pass < (is_q ? 8 : 4); pass++) {
12819             TCGv_i32 tcg_op = tcg_temp_new_i32();
12820             TCGv_i32 tcg_res = tcg_temp_new_i32();
12821
12822             read_vec_element_i32(s, tcg_op, rn, pass, MO_16);
12823
12824             switch (fpop) {
12825             case 0x1a: /* FCVTNS */
12826             case 0x1b: /* FCVTMS */
12827             case 0x1c: /* FCVTAS */
12828             case 0x3a: /* FCVTPS */
12829             case 0x3b: /* FCVTZS */
12830                 gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
12831                 break;
12832             case 0x3d: /* FRECPE */
12833                 gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
12834                 break;
12835             case 0x5a: /* FCVTNU */
12836             case 0x5b: /* FCVTMU */
12837             case 0x5c: /* FCVTAU */
12838             case 0x7a: /* FCVTPU */
12839             case 0x7b: /* FCVTZU */
12840                 gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
12841                 break;
12842             case 0x18: /* FRINTN */
12843             case 0x19: /* FRINTM */
12844             case 0x38: /* FRINTP */
12845             case 0x39: /* FRINTZ */
12846             case 0x58: /* FRINTA */
12847             case 0x79: /* FRINTI */
12848                 gen_helper_advsimd_rinth(tcg_res, tcg_op, tcg_fpstatus);
12849                 break;
12850             case 0x59: /* FRINTX */
12851                 gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, tcg_fpstatus);
12852                 break;
12853             case 0x2f: /* FABS */
12854                 tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
12855                 break;
12856             case 0x6f: /* FNEG */
12857                 tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
12858                 break;
12859             case 0x7d: /* FRSQRTE */
12860                 gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
12861                 break;
12862             case 0x7f: /* FSQRT */
12863                 gen_helper_sqrt_f16(tcg_res, tcg_op, tcg_fpstatus);
12864                 break;
12865             default:
12866                 g_assert_not_reached();
12867             }
12868
12869             write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
12870
12871             tcg_temp_free_i32(tcg_res);
12872             tcg_temp_free_i32(tcg_op);
12873         }
12874
12875         clear_vec_high(s, is_q, rd);
12876     }
12877
12878     if (tcg_rmode) {
12879         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12880         tcg_temp_free_i32(tcg_rmode);
12881     }
12882
12883     if (tcg_fpstatus) {
12884         tcg_temp_free_ptr(tcg_fpstatus);
12885     }
12886 }
12887
12888 /* AdvSIMD scalar x indexed element
12889  *  31 30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
12890  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
12891  * | 0 1 | U | 1 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
12892  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
12893  * AdvSIMD vector x indexed element
12894  *   31  30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
12895  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
12896  * | 0 | Q | U | 0 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
12897  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
12898  */
12899 static void disas_simd_indexed(DisasContext *s, uint32_t insn)
12900 {
12901     /* This encoding has two kinds of instruction:
12902      *  normal, where we perform elt x idxelt => elt for each
12903      *     element in the vector
12904      *  long, where we perform elt x idxelt and generate a result of
12905      *     double the width of the input element
12906      * The long ops have a 'part' specifier (ie come in INSN, INSN2 pairs).
12907      */
12908     bool is_scalar = extract32(insn, 28, 1);
12909     bool is_q = extract32(insn, 30, 1);
12910     bool u = extract32(insn, 29, 1);
12911     int size = extract32(insn, 22, 2);
12912     int l = extract32(insn, 21, 1);
12913     int m = extract32(insn, 20, 1);
12914     /* Note that the Rm field here is only 4 bits, not 5 as it usually is */
12915     int rm = extract32(insn, 16, 4);
12916     int opcode = extract32(insn, 12, 4);
12917     int h = extract32(insn, 11, 1);
12918     int rn = extract32(insn, 5, 5);
12919     int rd = extract32(insn, 0, 5);
12920     bool is_long = false;
12921     int is_fp = 0;
12922     bool is_fp16 = false;
12923     int index;
12924     TCGv_ptr fpst;
12925
12926     switch (16 * u + opcode) {
12927     case 0x08: /* MUL */
12928     case 0x10: /* MLA */
12929     case 0x14: /* MLS */
12930         if (is_scalar) {
12931             unallocated_encoding(s);
12932             return;
12933         }
12934         break;
12935     case 0x02: /* SMLAL, SMLAL2 */
12936     case 0x12: /* UMLAL, UMLAL2 */
12937     case 0x06: /* SMLSL, SMLSL2 */
12938     case 0x16: /* UMLSL, UMLSL2 */
12939     case 0x0a: /* SMULL, SMULL2 */
12940     case 0x1a: /* UMULL, UMULL2 */
12941         if (is_scalar) {
12942             unallocated_encoding(s);
12943             return;
12944         }
12945         is_long = true;
12946         break;
12947     case 0x03: /* SQDMLAL, SQDMLAL2 */
12948     case 0x07: /* SQDMLSL, SQDMLSL2 */
12949     case 0x0b: /* SQDMULL, SQDMULL2 */
12950         is_long = true;
12951         break;
12952     case 0x0c: /* SQDMULH */
12953     case 0x0d: /* SQRDMULH */
12954         break;
12955     case 0x01: /* FMLA */
12956     case 0x05: /* FMLS */
12957     case 0x09: /* FMUL */
12958     case 0x19: /* FMULX */
12959         is_fp = 1;
12960         break;
12961     case 0x1d: /* SQRDMLAH */
12962     case 0x1f: /* SQRDMLSH */
12963         if (!dc_isar_feature(aa64_rdm, s)) {
12964             unallocated_encoding(s);
12965             return;
12966         }
12967         break;
12968     case 0x0e: /* SDOT */
12969     case 0x1e: /* UDOT */
12970         if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_dp, s)) {
12971             unallocated_encoding(s);
12972             return;
12973         }
12974         break;
12975     case 0x11: /* FCMLA #0 */
12976     case 0x13: /* FCMLA #90 */
12977     case 0x15: /* FCMLA #180 */
12978     case 0x17: /* FCMLA #270 */
12979         if (is_scalar || !dc_isar_feature(aa64_fcma, s)) {
12980             unallocated_encoding(s);
12981             return;
12982         }
12983         is_fp = 2;
12984         break;
12985     case 0x00: /* FMLAL */
12986     case 0x04: /* FMLSL */
12987     case 0x18: /* FMLAL2 */
12988     case 0x1c: /* FMLSL2 */
12989         if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_fhm, s)) {
12990             unallocated_encoding(s);
12991             return;
12992         }
12993         size = MO_16;
12994         /* is_fp, but we pass cpu_env not fp_status.  */
12995         break;
12996     default:
12997         unallocated_encoding(s);
12998         return;
12999     }
13000
13001     switch (is_fp) {
13002     case 1: /* normal fp */
13003         /* convert insn encoded size to TCGMemOp size */
13004         switch (size) {
13005         case 0: /* half-precision */
13006             size = MO_16;
13007             is_fp16 = true;
13008             break;
13009         case MO_32: /* single precision */
13010         case MO_64: /* double precision */
13011             break;
13012         default:
13013             unallocated_encoding(s);
13014             return;
13015         }
13016         break;
13017
13018     case 2: /* complex fp */
13019         /* Each indexable element is a complex pair.  */
13020         size += 1;
13021         switch (size) {
13022         case MO_32:
13023             if (h && !is_q) {
13024                 unallocated_encoding(s);
13025                 return;
13026             }
13027             is_fp16 = true;
13028             break;
13029         case MO_64:
13030             break;
13031         default:
13032             unallocated_encoding(s);
13033             return;
13034         }
13035         break;
13036
13037     default: /* integer */
13038         switch (size) {
13039         case MO_8:
13040         case MO_64:
13041             unallocated_encoding(s);
13042             return;
13043         }
13044         break;
13045     }
13046     if (is_fp16 && !dc_isar_feature(aa64_fp16, s)) {
13047         unallocated_encoding(s);
13048         return;
13049     }
13050
13051     /* Given TCGMemOp size, adjust register and indexing.  */
13052     switch (size) {
13053     case MO_16:
13054         index = h << 2 | l << 1 | m;
13055         break;
13056     case MO_32:
13057         index = h << 1 | l;
13058         rm |= m << 4;
13059         break;
13060     case MO_64:
13061         if (l || !is_q) {
13062             unallocated_encoding(s);
13063             return;
13064         }
13065         index = h;
13066         rm |= m << 4;
13067         break;
13068     default:
13069         g_assert_not_reached();
13070     }
13071
13072     if (!fp_access_check(s)) {
13073         return;
13074     }
13075
13076     if (is_fp) {
13077         fpst = get_fpstatus_ptr(is_fp16);
13078     } else {
13079         fpst = NULL;
13080     }
13081
13082     switch (16 * u + opcode) {
13083     case 0x0e: /* SDOT */
13084     case 0x1e: /* UDOT */
13085         gen_gvec_op3_ool(s, is_q, rd, rn, rm, index,
13086                          u ? gen_helper_gvec_udot_idx_b
13087                          : gen_helper_gvec_sdot_idx_b);
13088         return;
13089     case 0x11: /* FCMLA #0 */
13090     case 0x13: /* FCMLA #90 */
13091     case 0x15: /* FCMLA #180 */
13092     case 0x17: /* FCMLA #270 */
13093         {
13094             int rot = extract32(insn, 13, 2);
13095             int data = (index << 2) | rot;
13096             tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
13097                                vec_full_reg_offset(s, rn),
13098                                vec_full_reg_offset(s, rm), fpst,
13099                                is_q ? 16 : 8, vec_full_reg_size(s), data,
13100                                size == MO_64
13101                                ? gen_helper_gvec_fcmlas_idx
13102                                : gen_helper_gvec_fcmlah_idx);
13103             tcg_temp_free_ptr(fpst);
13104         }
13105         return;
13106
13107     case 0x00: /* FMLAL */
13108     case 0x04: /* FMLSL */
13109     case 0x18: /* FMLAL2 */
13110     case 0x1c: /* FMLSL2 */
13111         {
13112             int is_s = extract32(opcode, 2, 1);
13113             int is_2 = u;
13114             int data = (index << 2) | (is_2 << 1) | is_s;
13115             tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
13116                                vec_full_reg_offset(s, rn),
13117                                vec_full_reg_offset(s, rm), cpu_env,
13118                                is_q ? 16 : 8, vec_full_reg_size(s),
13119                                data, gen_helper_gvec_fmlal_idx_a64);
13120         }
13121         return;
13122     }
13123
13124     if (size == 3) {
13125         TCGv_i64 tcg_idx = tcg_temp_new_i64();
13126         int pass;
13127
13128         assert(is_fp && is_q && !is_long);
13129
13130         read_vec_element(s, tcg_idx, rm, index, MO_64);
13131
13132         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13133             TCGv_i64 tcg_op = tcg_temp_new_i64();
13134             TCGv_i64 tcg_res = tcg_temp_new_i64();
13135
13136             read_vec_element(s, tcg_op, rn, pass, MO_64);
13137
13138             switch (16 * u + opcode) {
13139             case 0x05: /* FMLS */
13140                 /* As usual for ARM, separate negation for fused multiply-add */
13141                 gen_helper_vfp_negd(tcg_op, tcg_op);
13142                 /* fall through */
13143             case 0x01: /* FMLA */
13144                 read_vec_element(s, tcg_res, rd, pass, MO_64);
13145                 gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
13146                 break;
13147             case 0x09: /* FMUL */
13148                 gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
13149                 break;
13150             case 0x19: /* FMULX */
13151                 gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
13152                 break;
13153             default:
13154                 g_assert_not_reached();
13155             }
13156
13157             write_vec_element(s, tcg_res, rd, pass, MO_64);
13158             tcg_temp_free_i64(tcg_op);
13159             tcg_temp_free_i64(tcg_res);
13160         }
13161
13162         tcg_temp_free_i64(tcg_idx);
13163         clear_vec_high(s, !is_scalar, rd);
13164     } else if (!is_long) {
13165         /* 32 bit floating point, or 16 or 32 bit integer.
13166          * For the 16 bit scalar case we use the usual Neon helpers and
13167          * rely on the fact that 0 op 0 == 0 with no side effects.
13168          */
13169         TCGv_i32 tcg_idx = tcg_temp_new_i32();
13170         int pass, maxpasses;
13171
13172         if (is_scalar) {
13173             maxpasses = 1;
13174         } else {
13175             maxpasses = is_q ? 4 : 2;
13176         }
13177
13178         read_vec_element_i32(s, tcg_idx, rm, index, size);
13179
13180         if (size == 1 && !is_scalar) {
13181             /* The simplest way to handle the 16x16 indexed ops is to duplicate
13182              * the index into both halves of the 32 bit tcg_idx and then use
13183              * the usual Neon helpers.
13184              */
13185             tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
13186         }
13187
13188         for (pass = 0; pass < maxpasses; pass++) {
13189             TCGv_i32 tcg_op = tcg_temp_new_i32();
13190             TCGv_i32 tcg_res = tcg_temp_new_i32();
13191
13192             read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
13193
13194             switch (16 * u + opcode) {
13195             case 0x08: /* MUL */
13196             case 0x10: /* MLA */
13197             case 0x14: /* MLS */
13198             {
13199                 static NeonGenTwoOpFn * const fns[2][2] = {
13200                     { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
13201                     { tcg_gen_add_i32, tcg_gen_sub_i32 },
13202                 };
13203                 NeonGenTwoOpFn *genfn;
13204                 bool is_sub = opcode == 0x4;
13205
13206                 if (size == 1) {
13207                     gen_helper_neon_mul_u16(tcg_res, tcg_op, tcg_idx);
13208                 } else {
13209                     tcg_gen_mul_i32(tcg_res, tcg_op, tcg_idx);
13210                 }
13211                 if (opcode == 0x8) {
13212                     break;
13213                 }
13214                 read_vec_element_i32(s, tcg_op, rd, pass, MO_32);
13215                 genfn = fns[size - 1][is_sub];
13216                 genfn(tcg_res, tcg_op, tcg_res);
13217                 break;
13218             }
13219             case 0x05: /* FMLS */
13220             case 0x01: /* FMLA */
13221                 read_vec_element_i32(s, tcg_res, rd, pass,
13222                                      is_scalar ? size : MO_32);
13223                 switch (size) {
13224                 case 1:
13225                     if (opcode == 0x5) {
13226                         /* As usual for ARM, separate negation for fused
13227                          * multiply-add */
13228                         tcg_gen_xori_i32(tcg_op, tcg_op, 0x80008000);
13229                     }
13230                     if (is_scalar) {
13231                         gen_helper_advsimd_muladdh(tcg_res, tcg_op, tcg_idx,
13232                                                    tcg_res, fpst);
13233                     } else {
13234                         gen_helper_advsimd_muladd2h(tcg_res, tcg_op, tcg_idx,
13235                                                     tcg_res, fpst);
13236                     }
13237                     break;
13238                 case 2:
13239                     if (opcode == 0x5) {
13240                         /* As usual for ARM, separate negation for
13241                          * fused multiply-add */
13242                         tcg_gen_xori_i32(tcg_op, tcg_op, 0x80000000);
13243                     }
13244                     gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx,
13245                                            tcg_res, fpst);
13246                     break;
13247                 default:
13248                     g_assert_not_reached();
13249                 }
13250                 break;
13251             case 0x09: /* FMUL */
13252                 switch (size) {
13253                 case 1:
13254                     if (is_scalar) {
13255                         gen_helper_advsimd_mulh(tcg_res, tcg_op,
13256                                                 tcg_idx, fpst);
13257                     } else {
13258                         gen_helper_advsimd_mul2h(tcg_res, tcg_op,
13259                                                  tcg_idx, fpst);
13260                     }
13261                     break;
13262                 case 2:
13263                     gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
13264                     break;
13265                 default:
13266                     g_assert_not_reached();
13267                 }
13268                 break;
13269             case 0x19: /* FMULX */
13270                 switch (size) {
13271                 case 1:
13272                     if (is_scalar) {
13273                         gen_helper_advsimd_mulxh(tcg_res, tcg_op,
13274                                                  tcg_idx, fpst);
13275                     } else {
13276                         gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
13277                                                   tcg_idx, fpst);
13278                     }
13279                     break;
13280                 case 2:
13281                     gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
13282                     break;
13283                 default:
13284                     g_assert_not_reached();
13285                 }
13286                 break;
13287             case 0x0c: /* SQDMULH */
13288                 if (size == 1) {
13289                     gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
13290                                                tcg_op, tcg_idx);
13291                 } else {
13292                     gen_helper_neon_qdmulh_s32(tcg_res, cpu_env,
13293                                                tcg_op, tcg_idx);
13294                 }
13295                 break;
13296             case 0x0d: /* SQRDMULH */
13297                 if (size == 1) {
13298                     gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
13299                                                 tcg_op, tcg_idx);
13300                 } else {
13301                     gen_helper_neon_qrdmulh_s32(tcg_res, cpu_env,
13302                                                 tcg_op, tcg_idx);
13303                 }
13304                 break;
13305             case 0x1d: /* SQRDMLAH */
13306                 read_vec_element_i32(s, tcg_res, rd, pass,
13307                                      is_scalar ? size : MO_32);
13308                 if (size == 1) {
13309                     gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
13310                                                 tcg_op, tcg_idx, tcg_res);
13311                 } else {
13312                     gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
13313                                                 tcg_op, tcg_idx, tcg_res);
13314                 }
13315                 break;
13316             case 0x1f: /* SQRDMLSH */
13317                 read_vec_element_i32(s, tcg_res, rd, pass,
13318                                      is_scalar ? size : MO_32);
13319                 if (size == 1) {
13320                     gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
13321                                                 tcg_op, tcg_idx, tcg_res);
13322                 } else {
13323                     gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
13324                                                 tcg_op, tcg_idx, tcg_res);
13325                 }
13326                 break;
13327             default:
13328                 g_assert_not_reached();
13329             }
13330
13331             if (is_scalar) {
13332                 write_fp_sreg(s, rd, tcg_res);
13333             } else {
13334                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
13335             }
13336
13337             tcg_temp_free_i32(tcg_op);
13338             tcg_temp_free_i32(tcg_res);
13339         }
13340
13341         tcg_temp_free_i32(tcg_idx);
13342         clear_vec_high(s, is_q, rd);
13343     } else {
13344         /* long ops: 16x16->32 or 32x32->64 */
13345         TCGv_i64 tcg_res[2];
13346         int pass;
13347         bool satop = extract32(opcode, 0, 1);
13348         TCGMemOp memop = MO_32;
13349
13350         if (satop || !u) {
13351             memop |= MO_SIGN;
13352         }
13353
13354         if (size == 2) {
13355             TCGv_i64 tcg_idx = tcg_temp_new_i64();
13356
13357             read_vec_element(s, tcg_idx, rm, index, memop);
13358
13359             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13360                 TCGv_i64 tcg_op = tcg_temp_new_i64();
13361                 TCGv_i64 tcg_passres;
13362                 int passelt;
13363
13364                 if (is_scalar) {
13365                     passelt = 0;
13366                 } else {
13367                     passelt = pass + (is_q * 2);
13368                 }
13369
13370                 read_vec_element(s, tcg_op, rn, passelt, memop);
13371
13372                 tcg_res[pass] = tcg_temp_new_i64();
13373
13374                 if (opcode == 0xa || opcode == 0xb) {
13375                     /* Non-accumulating ops */
13376                     tcg_passres = tcg_res[pass];
13377                 } else {
13378                     tcg_passres = tcg_temp_new_i64();
13379                 }
13380
13381                 tcg_gen_mul_i64(tcg_passres, tcg_op, tcg_idx);
13382                 tcg_temp_free_i64(tcg_op);
13383
13384                 if (satop) {
13385                     /* saturating, doubling */
13386                     gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
13387                                                       tcg_passres, tcg_passres);
13388                 }
13389
13390                 if (opcode == 0xa || opcode == 0xb) {
13391                     continue;
13392                 }
13393
13394                 /* Accumulating op: handle accumulate step */
13395                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13396
13397                 switch (opcode) {
13398                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
13399                     tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
13400                     break;
13401                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
13402                     tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
13403                     break;
13404                 case 0x7: /* SQDMLSL, SQDMLSL2 */
13405                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
13406                     /* fall through */
13407                 case 0x3: /* SQDMLAL, SQDMLAL2 */
13408                     gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
13409                                                       tcg_res[pass],
13410                                                       tcg_passres);
13411                     break;
13412                 default:
13413                     g_assert_not_reached();
13414                 }
13415                 tcg_temp_free_i64(tcg_passres);
13416             }
13417             tcg_temp_free_i64(tcg_idx);
13418
13419             clear_vec_high(s, !is_scalar, rd);
13420         } else {
13421             TCGv_i32 tcg_idx = tcg_temp_new_i32();
13422
13423             assert(size == 1);
13424             read_vec_element_i32(s, tcg_idx, rm, index, size);
13425
13426             if (!is_scalar) {
13427                 /* The simplest way to handle the 16x16 indexed ops is to
13428                  * duplicate the index into both halves of the 32 bit tcg_idx
13429                  * and then use the usual Neon helpers.
13430                  */
13431                 tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
13432             }
13433
13434             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13435                 TCGv_i32 tcg_op = tcg_temp_new_i32();
13436                 TCGv_i64 tcg_passres;
13437
13438                 if (is_scalar) {
13439                     read_vec_element_i32(s, tcg_op, rn, pass, size);
13440                 } else {
13441                     read_vec_element_i32(s, tcg_op, rn,
13442                                          pass + (is_q * 2), MO_32);
13443                 }
13444
13445                 tcg_res[pass] = tcg_temp_new_i64();
13446
13447                 if (opcode == 0xa || opcode == 0xb) {
13448                     /* Non-accumulating ops */
13449                     tcg_passres = tcg_res[pass];
13450                 } else {
13451                     tcg_passres = tcg_temp_new_i64();
13452                 }
13453
13454                 if (memop & MO_SIGN) {
13455                     gen_helper_neon_mull_s16(tcg_passres, tcg_op, tcg_idx);
13456                 } else {
13457                     gen_helper_neon_mull_u16(tcg_passres, tcg_op, tcg_idx);
13458                 }
13459                 if (satop) {
13460                     gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
13461                                                       tcg_passres, tcg_passres);
13462                 }
13463                 tcg_temp_free_i32(tcg_op);
13464
13465                 if (opcode == 0xa || opcode == 0xb) {
13466                     continue;
13467                 }
13468
13469                 /* Accumulating op: handle accumulate step */
13470                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13471
13472                 switch (opcode) {
13473                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
13474                     gen_helper_neon_addl_u32(tcg_res[pass], tcg_res[pass],
13475                                              tcg_passres);
13476                     break;
13477                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
13478                     gen_helper_neon_subl_u32(tcg_res[pass], tcg_res[pass],
13479                                              tcg_passres);
13480                     break;
13481                 case 0x7: /* SQDMLSL, SQDMLSL2 */
13482                     gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
13483                     /* fall through */
13484                 case 0x3: /* SQDMLAL, SQDMLAL2 */
13485                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
13486                                                       tcg_res[pass],
13487                                                       tcg_passres);
13488                     break;
13489                 default:
13490                     g_assert_not_reached();
13491                 }
13492                 tcg_temp_free_i64(tcg_passres);
13493             }
13494             tcg_temp_free_i32(tcg_idx);
13495
13496             if (is_scalar) {
13497                 tcg_gen_ext32u_i64(tcg_res[0], tcg_res[0]);
13498             }
13499         }
13500
13501         if (is_scalar) {
13502             tcg_res[1] = tcg_const_i64(0);
13503         }
13504
13505         for (pass = 0; pass < 2; pass++) {
13506             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13507             tcg_temp_free_i64(tcg_res[pass]);
13508         }
13509     }
13510
13511     if (fpst) {
13512         tcg_temp_free_ptr(fpst);
13513     }
13514 }
13515
13516 /* Crypto AES
13517  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
13518  * +-----------------+------+-----------+--------+-----+------+------+
13519  * | 0 1 0 0 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
13520  * +-----------------+------+-----------+--------+-----+------+------+
13521  */
13522 static void disas_crypto_aes(DisasContext *s, uint32_t insn)
13523 {
13524     int size = extract32(insn, 22, 2);
13525     int opcode = extract32(insn, 12, 5);
13526     int rn = extract32(insn, 5, 5);
13527     int rd = extract32(insn, 0, 5);
13528     int decrypt;
13529     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13530     TCGv_i32 tcg_decrypt;
13531     CryptoThreeOpIntFn *genfn;
13532
13533     if (!dc_isar_feature(aa64_aes, s) || size != 0) {
13534         unallocated_encoding(s);
13535         return;
13536     }
13537
13538     switch (opcode) {
13539     case 0x4: /* AESE */
13540         decrypt = 0;
13541         genfn = gen_helper_crypto_aese;
13542         break;
13543     case 0x6: /* AESMC */
13544         decrypt = 0;
13545         genfn = gen_helper_crypto_aesmc;
13546         break;
13547     case 0x5: /* AESD */
13548         decrypt = 1;
13549         genfn = gen_helper_crypto_aese;
13550         break;
13551     case 0x7: /* AESIMC */
13552         decrypt = 1;
13553         genfn = gen_helper_crypto_aesmc;
13554         break;
13555     default:
13556         unallocated_encoding(s);
13557         return;
13558     }
13559
13560     if (!fp_access_check(s)) {
13561         return;
13562     }
13563
13564     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13565     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13566     tcg_decrypt = tcg_const_i32(decrypt);
13567
13568     genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt);
13569
13570     tcg_temp_free_ptr(tcg_rd_ptr);
13571     tcg_temp_free_ptr(tcg_rn_ptr);
13572     tcg_temp_free_i32(tcg_decrypt);
13573 }
13574
13575 /* Crypto three-reg SHA
13576  *  31             24 23  22  21 20  16  15 14    12 11 10 9    5 4    0
13577  * +-----------------+------+---+------+---+--------+-----+------+------+
13578  * | 0 1 0 1 1 1 1 0 | size | 0 |  Rm  | 0 | opcode | 0 0 |  Rn  |  Rd  |
13579  * +-----------------+------+---+------+---+--------+-----+------+------+
13580  */
13581 static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
13582 {
13583     int size = extract32(insn, 22, 2);
13584     int opcode = extract32(insn, 12, 3);
13585     int rm = extract32(insn, 16, 5);
13586     int rn = extract32(insn, 5, 5);
13587     int rd = extract32(insn, 0, 5);
13588     CryptoThreeOpFn *genfn;
13589     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
13590     bool feature;
13591
13592     if (size != 0) {
13593         unallocated_encoding(s);
13594         return;
13595     }
13596
13597     switch (opcode) {
13598     case 0: /* SHA1C */
13599     case 1: /* SHA1P */
13600     case 2: /* SHA1M */
13601     case 3: /* SHA1SU0 */
13602         genfn = NULL;
13603         feature = dc_isar_feature(aa64_sha1, s);
13604         break;
13605     case 4: /* SHA256H */
13606         genfn = gen_helper_crypto_sha256h;
13607         feature = dc_isar_feature(aa64_sha256, s);
13608         break;
13609     case 5: /* SHA256H2 */
13610         genfn = gen_helper_crypto_sha256h2;
13611         feature = dc_isar_feature(aa64_sha256, s);
13612         break;
13613     case 6: /* SHA256SU1 */
13614         genfn = gen_helper_crypto_sha256su1;
13615         feature = dc_isar_feature(aa64_sha256, s);
13616         break;
13617     default:
13618         unallocated_encoding(s);
13619         return;
13620     }
13621
13622     if (!feature) {
13623         unallocated_encoding(s);
13624         return;
13625     }
13626
13627     if (!fp_access_check(s)) {
13628         return;
13629     }
13630
13631     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13632     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13633     tcg_rm_ptr = vec_full_reg_ptr(s, rm);
13634
13635     if (genfn) {
13636         genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
13637     } else {
13638         TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
13639
13640         gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
13641                                     tcg_rm_ptr, tcg_opcode);
13642         tcg_temp_free_i32(tcg_opcode);
13643     }
13644
13645     tcg_temp_free_ptr(tcg_rd_ptr);
13646     tcg_temp_free_ptr(tcg_rn_ptr);
13647     tcg_temp_free_ptr(tcg_rm_ptr);
13648 }
13649
13650 /* Crypto two-reg SHA
13651  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
13652  * +-----------------+------+-----------+--------+-----+------+------+
13653  * | 0 1 0 1 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
13654  * +-----------------+------+-----------+--------+-----+------+------+
13655  */
13656 static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
13657 {
13658     int size = extract32(insn, 22, 2);
13659     int opcode = extract32(insn, 12, 5);
13660     int rn = extract32(insn, 5, 5);
13661     int rd = extract32(insn, 0, 5);
13662     CryptoTwoOpFn *genfn;
13663     bool feature;
13664     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13665
13666     if (size != 0) {
13667         unallocated_encoding(s);
13668         return;
13669     }
13670
13671     switch (opcode) {
13672     case 0: /* SHA1H */
13673         feature = dc_isar_feature(aa64_sha1, s);
13674         genfn = gen_helper_crypto_sha1h;
13675         break;
13676     case 1: /* SHA1SU1 */
13677         feature = dc_isar_feature(aa64_sha1, s);
13678         genfn = gen_helper_crypto_sha1su1;
13679         break;
13680     case 2: /* SHA256SU0 */
13681         feature = dc_isar_feature(aa64_sha256, s);
13682         genfn = gen_helper_crypto_sha256su0;
13683         break;
13684     default:
13685         unallocated_encoding(s);
13686         return;
13687     }
13688
13689     if (!feature) {
13690         unallocated_encoding(s);
13691         return;
13692     }
13693
13694     if (!fp_access_check(s)) {
13695         return;
13696     }
13697
13698     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13699     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13700
13701     genfn(tcg_rd_ptr, tcg_rn_ptr);
13702
13703     tcg_temp_free_ptr(tcg_rd_ptr);
13704     tcg_temp_free_ptr(tcg_rn_ptr);
13705 }
13706
13707 /* Crypto three-reg SHA512
13708  *  31                   21 20  16 15  14  13 12  11  10  9    5 4    0
13709  * +-----------------------+------+---+---+-----+--------+------+------+
13710  * | 1 1 0 0 1 1 1 0 0 1 1 |  Rm  | 1 | O | 0 0 | opcode |  Rn  |  Rd  |
13711  * +-----------------------+------+---+---+-----+--------+------+------+
13712  */
13713 static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
13714 {
13715     int opcode = extract32(insn, 10, 2);
13716     int o =  extract32(insn, 14, 1);
13717     int rm = extract32(insn, 16, 5);
13718     int rn = extract32(insn, 5, 5);
13719     int rd = extract32(insn, 0, 5);
13720     bool feature;
13721     CryptoThreeOpFn *genfn;
13722
13723     if (o == 0) {
13724         switch (opcode) {
13725         case 0: /* SHA512H */
13726             feature = dc_isar_feature(aa64_sha512, s);
13727             genfn = gen_helper_crypto_sha512h;
13728             break;
13729         case 1: /* SHA512H2 */
13730             feature = dc_isar_feature(aa64_sha512, s);
13731             genfn = gen_helper_crypto_sha512h2;
13732             break;
13733         case 2: /* SHA512SU1 */
13734             feature = dc_isar_feature(aa64_sha512, s);
13735             genfn = gen_helper_crypto_sha512su1;
13736             break;
13737         case 3: /* RAX1 */
13738             feature = dc_isar_feature(aa64_sha3, s);
13739             genfn = NULL;
13740             break;
13741         }
13742     } else {
13743         switch (opcode) {
13744         case 0: /* SM3PARTW1 */
13745             feature = dc_isar_feature(aa64_sm3, s);
13746             genfn = gen_helper_crypto_sm3partw1;
13747             break;
13748         case 1: /* SM3PARTW2 */
13749             feature = dc_isar_feature(aa64_sm3, s);
13750             genfn = gen_helper_crypto_sm3partw2;
13751             break;
13752         case 2: /* SM4EKEY */
13753             feature = dc_isar_feature(aa64_sm4, s);
13754             genfn = gen_helper_crypto_sm4ekey;
13755             break;
13756         default:
13757             unallocated_encoding(s);
13758             return;
13759         }
13760     }
13761
13762     if (!feature) {
13763         unallocated_encoding(s);
13764         return;
13765     }
13766
13767     if (!fp_access_check(s)) {
13768         return;
13769     }
13770
13771     if (genfn) {
13772         TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
13773
13774         tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13775         tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13776         tcg_rm_ptr = vec_full_reg_ptr(s, rm);
13777
13778         genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
13779
13780         tcg_temp_free_ptr(tcg_rd_ptr);
13781         tcg_temp_free_ptr(tcg_rn_ptr);
13782         tcg_temp_free_ptr(tcg_rm_ptr);
13783     } else {
13784         TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
13785         int pass;
13786
13787         tcg_op1 = tcg_temp_new_i64();
13788         tcg_op2 = tcg_temp_new_i64();
13789         tcg_res[0] = tcg_temp_new_i64();
13790         tcg_res[1] = tcg_temp_new_i64();
13791
13792         for (pass = 0; pass < 2; pass++) {
13793             read_vec_element(s, tcg_op1, rn, pass, MO_64);
13794             read_vec_element(s, tcg_op2, rm, pass, MO_64);
13795
13796             tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1);
13797             tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
13798         }
13799         write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13800         write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13801
13802         tcg_temp_free_i64(tcg_op1);
13803         tcg_temp_free_i64(tcg_op2);
13804         tcg_temp_free_i64(tcg_res[0]);
13805         tcg_temp_free_i64(tcg_res[1]);
13806     }
13807 }
13808
13809 /* Crypto two-reg SHA512
13810  *  31                                     12  11  10  9    5 4    0
13811  * +-----------------------------------------+--------+------+------+
13812  * | 1 1 0 0 1 1 1 0 1 1 0 0 0 0 0 0 1 0 0 0 | opcode |  Rn  |  Rd  |
13813  * +-----------------------------------------+--------+------+------+
13814  */
13815 static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
13816 {
13817     int opcode = extract32(insn, 10, 2);
13818     int rn = extract32(insn, 5, 5);
13819     int rd = extract32(insn, 0, 5);
13820     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13821     bool feature;
13822     CryptoTwoOpFn *genfn;
13823
13824     switch (opcode) {
13825     case 0: /* SHA512SU0 */
13826         feature = dc_isar_feature(aa64_sha512, s);
13827         genfn = gen_helper_crypto_sha512su0;
13828         break;
13829     case 1: /* SM4E */
13830         feature = dc_isar_feature(aa64_sm4, s);
13831         genfn = gen_helper_crypto_sm4e;
13832         break;
13833     default:
13834         unallocated_encoding(s);
13835         return;
13836     }
13837
13838     if (!feature) {
13839         unallocated_encoding(s);
13840         return;
13841     }
13842
13843     if (!fp_access_check(s)) {
13844         return;
13845     }
13846
13847     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13848     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13849
13850     genfn(tcg_rd_ptr, tcg_rn_ptr);
13851
13852     tcg_temp_free_ptr(tcg_rd_ptr);
13853     tcg_temp_free_ptr(tcg_rn_ptr);
13854 }
13855
13856 /* Crypto four-register
13857  *  31               23 22 21 20  16 15  14  10 9    5 4    0
13858  * +-------------------+-----+------+---+------+------+------+
13859  * | 1 1 0 0 1 1 1 0 0 | Op0 |  Rm  | 0 |  Ra  |  Rn  |  Rd  |
13860  * +-------------------+-----+------+---+------+------+------+
13861  */
13862 static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
13863 {
13864     int op0 = extract32(insn, 21, 2);
13865     int rm = extract32(insn, 16, 5);
13866     int ra = extract32(insn, 10, 5);
13867     int rn = extract32(insn, 5, 5);
13868     int rd = extract32(insn, 0, 5);
13869     bool feature;
13870
13871     switch (op0) {
13872     case 0: /* EOR3 */
13873     case 1: /* BCAX */
13874         feature = dc_isar_feature(aa64_sha3, s);
13875         break;
13876     case 2: /* SM3SS1 */
13877         feature = dc_isar_feature(aa64_sm3, s);
13878         break;
13879     default:
13880         unallocated_encoding(s);
13881         return;
13882     }
13883
13884     if (!feature) {
13885         unallocated_encoding(s);
13886         return;
13887     }
13888
13889     if (!fp_access_check(s)) {
13890         return;
13891     }
13892
13893     if (op0 < 2) {
13894         TCGv_i64 tcg_op1, tcg_op2, tcg_op3, tcg_res[2];
13895         int pass;
13896
13897         tcg_op1 = tcg_temp_new_i64();
13898         tcg_op2 = tcg_temp_new_i64();
13899         tcg_op3 = tcg_temp_new_i64();
13900         tcg_res[0] = tcg_temp_new_i64();
13901         tcg_res[1] = tcg_temp_new_i64();
13902
13903         for (pass = 0; pass < 2; pass++) {
13904             read_vec_element(s, tcg_op1, rn, pass, MO_64);
13905             read_vec_element(s, tcg_op2, rm, pass, MO_64);
13906             read_vec_element(s, tcg_op3, ra, pass, MO_64);
13907
13908             if (op0 == 0) {
13909                 /* EOR3 */
13910                 tcg_gen_xor_i64(tcg_res[pass], tcg_op2, tcg_op3);
13911             } else {
13912                 /* BCAX */
13913                 tcg_gen_andc_i64(tcg_res[pass], tcg_op2, tcg_op3);
13914             }
13915             tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
13916         }
13917         write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13918         write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13919
13920         tcg_temp_free_i64(tcg_op1);
13921         tcg_temp_free_i64(tcg_op2);
13922         tcg_temp_free_i64(tcg_op3);
13923         tcg_temp_free_i64(tcg_res[0]);
13924         tcg_temp_free_i64(tcg_res[1]);
13925     } else {
13926         TCGv_i32 tcg_op1, tcg_op2, tcg_op3, tcg_res, tcg_zero;
13927
13928         tcg_op1 = tcg_temp_new_i32();
13929         tcg_op2 = tcg_temp_new_i32();
13930         tcg_op3 = tcg_temp_new_i32();
13931         tcg_res = tcg_temp_new_i32();
13932         tcg_zero = tcg_const_i32(0);
13933
13934         read_vec_element_i32(s, tcg_op1, rn, 3, MO_32);
13935         read_vec_element_i32(s, tcg_op2, rm, 3, MO_32);
13936         read_vec_element_i32(s, tcg_op3, ra, 3, MO_32);
13937
13938         tcg_gen_rotri_i32(tcg_res, tcg_op1, 20);
13939         tcg_gen_add_i32(tcg_res, tcg_res, tcg_op2);
13940         tcg_gen_add_i32(tcg_res, tcg_res, tcg_op3);
13941         tcg_gen_rotri_i32(tcg_res, tcg_res, 25);
13942
13943         write_vec_element_i32(s, tcg_zero, rd, 0, MO_32);
13944         write_vec_element_i32(s, tcg_zero, rd, 1, MO_32);
13945         write_vec_element_i32(s, tcg_zero, rd, 2, MO_32);
13946         write_vec_element_i32(s, tcg_res, rd, 3, MO_32);
13947
13948         tcg_temp_free_i32(tcg_op1);
13949         tcg_temp_free_i32(tcg_op2);
13950         tcg_temp_free_i32(tcg_op3);
13951         tcg_temp_free_i32(tcg_res);
13952         tcg_temp_free_i32(tcg_zero);
13953     }
13954 }
13955
13956 /* Crypto XAR
13957  *  31                   21 20  16 15    10 9    5 4    0
13958  * +-----------------------+------+--------+------+------+
13959  * | 1 1 0 0 1 1 1 0 1 0 0 |  Rm  |  imm6  |  Rn  |  Rd  |
13960  * +-----------------------+------+--------+------+------+
13961  */
13962 static void disas_crypto_xar(DisasContext *s, uint32_t insn)
13963 {
13964     int rm = extract32(insn, 16, 5);
13965     int imm6 = extract32(insn, 10, 6);
13966     int rn = extract32(insn, 5, 5);
13967     int rd = extract32(insn, 0, 5);
13968     TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
13969     int pass;
13970
13971     if (!dc_isar_feature(aa64_sha3, s)) {
13972         unallocated_encoding(s);
13973         return;
13974     }
13975
13976     if (!fp_access_check(s)) {
13977         return;
13978     }
13979
13980     tcg_op1 = tcg_temp_new_i64();
13981     tcg_op2 = tcg_temp_new_i64();
13982     tcg_res[0] = tcg_temp_new_i64();
13983     tcg_res[1] = tcg_temp_new_i64();
13984
13985     for (pass = 0; pass < 2; pass++) {
13986         read_vec_element(s, tcg_op1, rn, pass, MO_64);
13987         read_vec_element(s, tcg_op2, rm, pass, MO_64);
13988
13989         tcg_gen_xor_i64(tcg_res[pass], tcg_op1, tcg_op2);
13990         tcg_gen_rotri_i64(tcg_res[pass], tcg_res[pass], imm6);
13991     }
13992     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13993     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13994
13995     tcg_temp_free_i64(tcg_op1);
13996     tcg_temp_free_i64(tcg_op2);
13997     tcg_temp_free_i64(tcg_res[0]);
13998     tcg_temp_free_i64(tcg_res[1]);
13999 }
14000
14001 /* Crypto three-reg imm2
14002  *  31                   21 20  16 15  14 13 12  11  10  9    5 4    0
14003  * +-----------------------+------+-----+------+--------+------+------+
14004  * | 1 1 0 0 1 1 1 0 0 1 0 |  Rm  | 1 0 | imm2 | opcode |  Rn  |  Rd  |
14005  * +-----------------------+------+-----+------+--------+------+------+
14006  */
14007 static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
14008 {
14009     int opcode = extract32(insn, 10, 2);
14010     int imm2 = extract32(insn, 12, 2);
14011     int rm = extract32(insn, 16, 5);
14012     int rn = extract32(insn, 5, 5);
14013     int rd = extract32(insn, 0, 5);
14014     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
14015     TCGv_i32 tcg_imm2, tcg_opcode;
14016
14017     if (!dc_isar_feature(aa64_sm3, s)) {
14018         unallocated_encoding(s);
14019         return;
14020     }
14021
14022     if (!fp_access_check(s)) {
14023         return;
14024     }
14025
14026     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
14027     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
14028     tcg_rm_ptr = vec_full_reg_ptr(s, rm);
14029     tcg_imm2   = tcg_const_i32(imm2);
14030     tcg_opcode = tcg_const_i32(opcode);
14031
14032     gen_helper_crypto_sm3tt(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr, tcg_imm2,
14033                             tcg_opcode);
14034
14035     tcg_temp_free_ptr(tcg_rd_ptr);
14036     tcg_temp_free_ptr(tcg_rn_ptr);
14037     tcg_temp_free_ptr(tcg_rm_ptr);
14038     tcg_temp_free_i32(tcg_imm2);
14039     tcg_temp_free_i32(tcg_opcode);
14040 }
14041
14042 /* C3.6 Data processing - SIMD, inc Crypto
14043  *
14044  * As the decode gets a little complex we are using a table based
14045  * approach for this part of the decode.
14046  */
14047 static const AArch64DecodeTable data_proc_simd[] = {
14048     /* pattern  ,  mask     ,  fn                        */
14049     { 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
14050     { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
14051     { 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
14052     { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
14053     { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
14054     { 0x0e000400, 0x9fe08400, disas_simd_copy },
14055     { 0x0f000000, 0x9f000400, disas_simd_indexed }, /* vector indexed */
14056     /* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */
14057     { 0x0f000400, 0x9ff80400, disas_simd_mod_imm },
14058     { 0x0f000400, 0x9f800400, disas_simd_shift_imm },
14059     { 0x0e000000, 0xbf208c00, disas_simd_tb },
14060     { 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
14061     { 0x2e000000, 0xbf208400, disas_simd_ext },
14062     { 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
14063     { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
14064     { 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
14065     { 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
14066     { 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
14067     { 0x5e000400, 0xdfe08400, disas_simd_scalar_copy },
14068     { 0x5f000000, 0xdf000400, disas_simd_indexed }, /* scalar indexed */
14069     { 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm },
14070     { 0x4e280800, 0xff3e0c00, disas_crypto_aes },
14071     { 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
14072     { 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
14073     { 0xce608000, 0xffe0b000, disas_crypto_three_reg_sha512 },
14074     { 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
14075     { 0xce000000, 0xff808000, disas_crypto_four_reg },
14076     { 0xce800000, 0xffe00000, disas_crypto_xar },
14077     { 0xce408000, 0xffe0c000, disas_crypto_three_reg_imm2 },
14078     { 0x0e400400, 0x9f60c400, disas_simd_three_reg_same_fp16 },
14079     { 0x0e780800, 0x8f7e0c00, disas_simd_two_reg_misc_fp16 },
14080     { 0x5e400400, 0xdf60c400, disas_simd_scalar_three_reg_same_fp16 },
14081     { 0x00000000, 0x00000000, NULL }
14082 };
14083
14084 static void disas_data_proc_simd(DisasContext *s, uint32_t insn)
14085 {
14086     /* Note that this is called with all non-FP cases from
14087      * table C3-6 so it must UNDEF for entries not specifically
14088      * allocated to instructions in that table.
14089      */
14090     AArch64DecodeFn *fn = lookup_disas_fn(&data_proc_simd[0], insn);
14091     if (fn) {
14092         fn(s, insn);
14093     } else {
14094         unallocated_encoding(s);
14095     }
14096 }
14097
14098 /* C3.6 Data processing - SIMD and floating point */
14099 static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
14100 {
14101     if (extract32(insn, 28, 1) == 1 && extract32(insn, 30, 1) == 0) {
14102         disas_data_proc_fp(s, insn);
14103     } else {
14104         /* SIMD, including crypto */
14105         disas_data_proc_simd(s, insn);
14106     }
14107 }
14108
14109 /**
14110  * is_guarded_page:
14111  * @env: The cpu environment
14112  * @s: The DisasContext
14113  *
14114  * Return true if the page is guarded.
14115  */
14116 static bool is_guarded_page(CPUARMState *env, DisasContext *s)
14117 {
14118 #ifdef CONFIG_USER_ONLY
14119     return false;  /* FIXME */
14120 #else
14121     uint64_t addr = s->base.pc_first;
14122     int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
14123     unsigned int index = tlb_index(env, mmu_idx, addr);
14124     CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
14125
14126     /*
14127      * We test this immediately after reading an insn, which means
14128      * that any normal page must be in the TLB.  The only exception
14129      * would be for executing from flash or device memory, which
14130      * does not retain the TLB entry.
14131      *
14132      * FIXME: Assume false for those, for now.  We could use
14133      * arm_cpu_get_phys_page_attrs_debug to re-read the page
14134      * table entry even for that case.
14135      */
14136     return (tlb_hit(entry->addr_code, addr) &&
14137             env_tlb(env)->d[mmu_idx].iotlb[index].attrs.target_tlb_bit0);
14138 #endif
14139 }
14140
14141 /**
14142  * btype_destination_ok:
14143  * @insn: The instruction at the branch destination
14144  * @bt: SCTLR_ELx.BT
14145  * @btype: PSTATE.BTYPE, and is non-zero
14146  *
14147  * On a guarded page, there are a limited number of insns
14148  * that may be present at the branch target:
14149  *   - branch target identifiers,
14150  *   - paciasp, pacibsp,
14151  *   - BRK insn
14152  *   - HLT insn
14153  * Anything else causes a Branch Target Exception.
14154  *
14155  * Return true if the branch is compatible, false to raise BTITRAP.
14156  */
14157 static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
14158 {
14159     if ((insn & 0xfffff01fu) == 0xd503201fu) {
14160         /* HINT space */
14161         switch (extract32(insn, 5, 7)) {
14162         case 0b011001: /* PACIASP */
14163         case 0b011011: /* PACIBSP */
14164             /*
14165              * If SCTLR_ELx.BT, then PACI*SP are not compatible
14166              * with btype == 3.  Otherwise all btype are ok.
14167              */
14168             return !bt || btype != 3;
14169         case 0b100000: /* BTI */
14170             /* Not compatible with any btype.  */
14171             return false;
14172         case 0b100010: /* BTI c */
14173             /* Not compatible with btype == 3 */
14174             return btype != 3;
14175         case 0b100100: /* BTI j */
14176             /* Not compatible with btype == 2 */
14177             return btype != 2;
14178         case 0b100110: /* BTI jc */
14179             /* Compatible with any btype.  */
14180             return true;
14181         }
14182     } else {
14183         switch (insn & 0xffe0001fu) {
14184         case 0xd4200000u: /* BRK */
14185         case 0xd4400000u: /* HLT */
14186             /* Give priority to the breakpoint exception.  */
14187             return true;
14188         }
14189     }
14190     return false;
14191 }
14192
14193 /* C3.1 A64 instruction index by encoding */
14194 static void disas_a64_insn(CPUARMState *env, DisasContext *s)
14195 {
14196     uint32_t insn;
14197
14198     insn = arm_ldl_code(env, s->pc, s->sctlr_b);
14199     s->insn = insn;
14200     s->pc += 4;
14201
14202     s->fp_access_checked = false;
14203
14204     if (dc_isar_feature(aa64_bti, s)) {
14205         if (s->base.num_insns == 1) {
14206             /*
14207              * At the first insn of the TB, compute s->guarded_page.
14208              * We delayed computing this until successfully reading
14209              * the first insn of the TB, above.  This (mostly) ensures
14210              * that the softmmu tlb entry has been populated, and the
14211              * page table GP bit is available.
14212              *
14213              * Note that we need to compute this even if btype == 0,
14214              * because this value is used for BR instructions later
14215              * where ENV is not available.
14216              */
14217             s->guarded_page = is_guarded_page(env, s);
14218
14219             /* First insn can have btype set to non-zero.  */
14220             tcg_debug_assert(s->btype >= 0);
14221
14222             /*
14223              * Note that the Branch Target Exception has fairly high
14224              * priority -- below debugging exceptions but above most
14225              * everything else.  This allows us to handle this now
14226              * instead of waiting until the insn is otherwise decoded.
14227              */
14228             if (s->btype != 0
14229                 && s->guarded_page
14230                 && !btype_destination_ok(insn, s->bt, s->btype)) {
14231                 gen_exception_insn(s, 4, EXCP_UDEF, syn_btitrap(s->btype),
14232                                    default_exception_el(s));
14233                 return;
14234             }
14235         } else {
14236             /* Not the first insn: btype must be 0.  */
14237             tcg_debug_assert(s->btype == 0);
14238         }
14239     }
14240
14241     switch (extract32(insn, 25, 4)) {
14242     case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
14243         unallocated_encoding(s);
14244         break;
14245     case 0x2:
14246         if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
14247             unallocated_encoding(s);
14248         }
14249         break;
14250     case 0x8: case 0x9: /* Data processing - immediate */
14251         disas_data_proc_imm(s, insn);
14252         break;
14253     case 0xa: case 0xb: /* Branch, exception generation and system insns */
14254         disas_b_exc_sys(s, insn);
14255         break;
14256     case 0x4:
14257     case 0x6:
14258     case 0xc:
14259     case 0xe:      /* Loads and stores */
14260         disas_ldst(s, insn);
14261         break;
14262     case 0x5:
14263     case 0xd:      /* Data processing - register */
14264         disas_data_proc_reg(s, insn);
14265         break;
14266     case 0x7:
14267     case 0xf:      /* Data processing - SIMD and floating point */
14268         disas_data_proc_simd_fp(s, insn);
14269         break;
14270     default:
14271         assert(FALSE); /* all 15 cases should be handled above */
14272         break;
14273     }
14274
14275     /* if we allocated any temporaries, free them here */
14276     free_tmp_a64(s);
14277
14278     /*
14279      * After execution of most insns, btype is reset to 0.
14280      * Note that we set btype == -1 when the insn sets btype.
14281      */
14282     if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
14283         reset_btype(s);
14284     }
14285 }
14286
14287 static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
14288                                           CPUState *cpu)
14289 {
14290     DisasContext *dc = container_of(dcbase, DisasContext, base);
14291     CPUARMState *env = cpu->env_ptr;
14292     ARMCPU *arm_cpu = env_archcpu(env);
14293     uint32_t tb_flags = dc->base.tb->flags;
14294     int bound, core_mmu_idx;
14295
14296     dc->isar = &arm_cpu->isar;
14297     dc->pc = dc->base.pc_first;
14298     dc->condjmp = 0;
14299
14300     dc->aarch64 = 1;
14301     /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
14302      * there is no secure EL1, so we route exceptions to EL3.
14303      */
14304     dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
14305                                !arm_el_is_aa64(env, 3);
14306     dc->thumb = 0;
14307     dc->sctlr_b = 0;
14308     dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
14309     dc->condexec_mask = 0;
14310     dc->condexec_cond = 0;
14311     core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
14312     dc->mmu_idx = core_to_arm_mmu_idx(env, core_mmu_idx);
14313     dc->tbii = FIELD_EX32(tb_flags, TBFLAG_A64, TBII);
14314     dc->tbid = FIELD_EX32(tb_flags, TBFLAG_A64, TBID);
14315     dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
14316 #if !defined(CONFIG_USER_ONLY)
14317     dc->user = (dc->current_el == 0);
14318 #endif
14319     dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
14320     dc->sve_excp_el = FIELD_EX32(tb_flags, TBFLAG_A64, SVEEXC_EL);
14321     dc->sve_len = (FIELD_EX32(tb_flags, TBFLAG_A64, ZCR_LEN) + 1) * 16;
14322     dc->pauth_active = FIELD_EX32(tb_flags, TBFLAG_A64, PAUTH_ACTIVE);
14323     dc->bt = FIELD_EX32(tb_flags, TBFLAG_A64, BT);
14324     dc->btype = FIELD_EX32(tb_flags, TBFLAG_A64, BTYPE);
14325     dc->vec_len = 0;
14326     dc->vec_stride = 0;
14327     dc->cp_regs = arm_cpu->cp_regs;
14328     dc->features = env->features;
14329
14330     /* Single step state. The code-generation logic here is:
14331      *  SS_ACTIVE == 0:
14332      *   generate code with no special handling for single-stepping (except
14333      *   that anything that can make us go to SS_ACTIVE == 1 must end the TB;
14334      *   this happens anyway because those changes are all system register or
14335      *   PSTATE writes).
14336      *  SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
14337      *   emit code for one insn
14338      *   emit code to clear PSTATE.SS
14339      *   emit code to generate software step exception for completed step
14340      *   end TB (as usual for having generated an exception)
14341      *  SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
14342      *   emit code to generate a software step exception
14343      *   end the TB
14344      */
14345     dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
14346     dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
14347     dc->is_ldex = false;
14348     dc->ss_same_el = (arm_debug_target_el(env) == dc->current_el);
14349
14350     /* Bound the number of insns to execute to those left on the page.  */
14351     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
14352
14353     /* If architectural single step active, limit to 1.  */
14354     if (dc->ss_active) {
14355         bound = 1;
14356     }
14357     dc->base.max_insns = MIN(dc->base.max_insns, bound);
14358
14359     init_tmp_a64_array(dc);
14360 }
14361
14362 static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu)
14363 {
14364 }
14365
14366 static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
14367 {
14368     DisasContext *dc = container_of(dcbase, DisasContext, base);
14369
14370     tcg_gen_insn_start(dc->pc, 0, 0);
14371     dc->insn_start = tcg_last_op();
14372 }
14373
14374 static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
14375                                         const CPUBreakpoint *bp)
14376 {
14377     DisasContext *dc = container_of(dcbase, DisasContext, base);
14378
14379     if (bp->flags & BP_CPU) {
14380         gen_a64_set_pc_im(dc->pc);
14381         gen_helper_check_breakpoints(cpu_env);
14382         /* End the TB early; it likely won't be executed */
14383         dc->base.is_jmp = DISAS_TOO_MANY;
14384     } else {
14385         gen_exception_internal_insn(dc, 0, EXCP_DEBUG);
14386         /* The address covered by the breakpoint must be
14387            included in [tb->pc, tb->pc + tb->size) in order
14388            to for it to be properly cleared -- thus we
14389            increment the PC here so that the logic setting
14390            tb->size below does the right thing.  */
14391         dc->pc += 4;
14392         dc->base.is_jmp = DISAS_NORETURN;
14393     }
14394
14395     return true;
14396 }
14397
14398 static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
14399 {
14400     DisasContext *dc = container_of(dcbase, DisasContext, base);
14401     CPUARMState *env = cpu->env_ptr;
14402
14403     if (dc->ss_active && !dc->pstate_ss) {
14404         /* Singlestep state is Active-pending.
14405          * If we're in this state at the start of a TB then either
14406          *  a) we just took an exception to an EL which is being debugged
14407          *     and this is the first insn in the exception handler
14408          *  b) debug exceptions were masked and we just unmasked them
14409          *     without changing EL (eg by clearing PSTATE.D)
14410          * In either case we're going to take a swstep exception in the
14411          * "did not step an insn" case, and so the syndrome ISV and EX
14412          * bits should be zero.
14413          */
14414         assert(dc->base.num_insns == 1);
14415         gen_exception(EXCP_UDEF, syn_swstep(dc->ss_same_el, 0, 0),
14416                       default_exception_el(dc));
14417         dc->base.is_jmp = DISAS_NORETURN;
14418     } else {
14419         disas_a64_insn(env, dc);
14420     }
14421
14422     dc->base.pc_next = dc->pc;
14423     translator_loop_temp_check(&dc->base);
14424 }
14425
14426 static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
14427 {
14428     DisasContext *dc = container_of(dcbase, DisasContext, base);
14429
14430     if (unlikely(dc->base.singlestep_enabled || dc->ss_active)) {
14431         /* Note that this means single stepping WFI doesn't halt the CPU.
14432          * For conditional branch insns this is harmless unreachable code as
14433          * gen_goto_tb() has already handled emitting the debug exception
14434          * (and thus a tb-jump is not possible when singlestepping).
14435          */
14436         switch (dc->base.is_jmp) {
14437         default:
14438             gen_a64_set_pc_im(dc->pc);
14439             /* fall through */
14440         case DISAS_EXIT:
14441         case DISAS_JUMP:
14442             if (dc->base.singlestep_enabled) {
14443                 gen_exception_internal(EXCP_DEBUG);
14444             } else {
14445                 gen_step_complete_exception(dc);
14446             }
14447             break;
14448         case DISAS_NORETURN:
14449             break;
14450         }
14451     } else {
14452         switch (dc->base.is_jmp) {
14453         case DISAS_NEXT:
14454         case DISAS_TOO_MANY:
14455             gen_goto_tb(dc, 1, dc->pc);
14456             break;
14457         default:
14458         case DISAS_UPDATE:
14459             gen_a64_set_pc_im(dc->pc);
14460             /* fall through */
14461         case DISAS_EXIT:
14462             tcg_gen_exit_tb(NULL, 0);
14463             break;
14464         case DISAS_JUMP:
14465             tcg_gen_lookup_and_goto_ptr();
14466             break;
14467         case DISAS_NORETURN:
14468         case DISAS_SWI:
14469             break;
14470         case DISAS_WFE:
14471             gen_a64_set_pc_im(dc->pc);
14472             gen_helper_wfe(cpu_env);
14473             break;
14474         case DISAS_YIELD:
14475             gen_a64_set_pc_im(dc->pc);
14476             gen_helper_yield(cpu_env);
14477             break;
14478         case DISAS_WFI:
14479         {
14480             /* This is a special case because we don't want to just halt the CPU
14481              * if trying to debug across a WFI.
14482              */
14483             TCGv_i32 tmp = tcg_const_i32(4);
14484
14485             gen_a64_set_pc_im(dc->pc);
14486             gen_helper_wfi(cpu_env, tmp);
14487             tcg_temp_free_i32(tmp);
14488             /* The helper doesn't necessarily throw an exception, but we
14489              * must go back to the main loop to check for interrupts anyway.
14490              */
14491             tcg_gen_exit_tb(NULL, 0);
14492             break;
14493         }
14494         }
14495     }
14496
14497     /* Functions above can change dc->pc, so re-align db->pc_next */
14498     dc->base.pc_next = dc->pc;
14499 }
14500
14501 static void aarch64_tr_disas_log(const DisasContextBase *dcbase,
14502                                       CPUState *cpu)
14503 {
14504     DisasContext *dc = container_of(dcbase, DisasContext, base);
14505
14506     qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
14507     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
14508 }
14509
14510 const TranslatorOps aarch64_translator_ops = {
14511     .init_disas_context = aarch64_tr_init_disas_context,
14512     .tb_start           = aarch64_tr_tb_start,
14513     .insn_start         = aarch64_tr_insn_start,
14514     .breakpoint_check   = aarch64_tr_breakpoint_check,
14515     .translate_insn     = aarch64_tr_translate_insn,
14516     .tb_stop            = aarch64_tr_tb_stop,
14517     .disas_log          = aarch64_tr_disas_log,
14518 };
This page took 0.800251 seconds and 4 git commands to generate.