]> Git Repo - qemu.git/blob - target/arm/translate-a64.c
Merge remote-tracking branch 'remotes/mst/tags/for_upstream' into staging
[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/tcg-op.h"
24 #include "tcg/tcg-op-gvec.h"
25 #include "qemu/log.h"
26 #include "arm_ldst.h"
27 #include "translate.h"
28 #include "internals.h"
29 #include "qemu/host-utils.h"
30
31 #include "hw/semihosting/semihost.h"
32 #include "exec/gen-icount.h"
33
34 #include "exec/helper-proto.h"
35 #include "exec/helper-gen.h"
36 #include "exec/log.h"
37
38 #include "trace-tcg.h"
39 #include "translate-a64.h"
40 #include "qemu/atomic128.h"
41
42 static TCGv_i64 cpu_X[32];
43 static TCGv_i64 cpu_pc;
44
45 /* Load/store exclusive handling */
46 static TCGv_i64 cpu_exclusive_high;
47
48 static const char *regnames[] = {
49     "x0", "x1", "x2", "x3", "x4", "x5", "x6", "x7",
50     "x8", "x9", "x10", "x11", "x12", "x13", "x14", "x15",
51     "x16", "x17", "x18", "x19", "x20", "x21", "x22", "x23",
52     "x24", "x25", "x26", "x27", "x28", "x29", "lr", "sp"
53 };
54
55 enum a64_shift_type {
56     A64_SHIFT_TYPE_LSL = 0,
57     A64_SHIFT_TYPE_LSR = 1,
58     A64_SHIFT_TYPE_ASR = 2,
59     A64_SHIFT_TYPE_ROR = 3
60 };
61
62 /* Table based decoder typedefs - used when the relevant bits for decode
63  * are too awkwardly scattered across the instruction (eg SIMD).
64  */
65 typedef void AArch64DecodeFn(DisasContext *s, uint32_t insn);
66
67 typedef struct AArch64DecodeTable {
68     uint32_t pattern;
69     uint32_t mask;
70     AArch64DecodeFn *disas_fn;
71 } AArch64DecodeTable;
72
73 /* Function prototype for gen_ functions for calling Neon helpers */
74 typedef void NeonGenOneOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32);
75 typedef void NeonGenTwoOpFn(TCGv_i32, TCGv_i32, TCGv_i32);
76 typedef void NeonGenTwoOpEnvFn(TCGv_i32, TCGv_ptr, TCGv_i32, TCGv_i32);
77 typedef void NeonGenTwo64OpFn(TCGv_i64, TCGv_i64, TCGv_i64);
78 typedef void NeonGenTwo64OpEnvFn(TCGv_i64, TCGv_ptr, TCGv_i64, TCGv_i64);
79 typedef void NeonGenNarrowFn(TCGv_i32, TCGv_i64);
80 typedef void NeonGenNarrowEnvFn(TCGv_i32, TCGv_ptr, TCGv_i64);
81 typedef void NeonGenWidenFn(TCGv_i64, TCGv_i32);
82 typedef void NeonGenTwoSingleOPFn(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
83 typedef void NeonGenTwoDoubleOPFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGv_ptr);
84 typedef void NeonGenOneOpFn(TCGv_i64, TCGv_i64);
85 typedef void CryptoTwoOpFn(TCGv_ptr, TCGv_ptr);
86 typedef void CryptoThreeOpIntFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
87 typedef void CryptoThreeOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
88 typedef void AtomicThreeOpFn(TCGv_i64, TCGv_i64, TCGv_i64, TCGArg, MemOp);
89
90 /* initialize TCG globals.  */
91 void a64_translate_init(void)
92 {
93     int i;
94
95     cpu_pc = tcg_global_mem_new_i64(cpu_env,
96                                     offsetof(CPUARMState, pc),
97                                     "pc");
98     for (i = 0; i < 32; i++) {
99         cpu_X[i] = tcg_global_mem_new_i64(cpu_env,
100                                           offsetof(CPUARMState, xregs[i]),
101                                           regnames[i]);
102     }
103
104     cpu_exclusive_high = tcg_global_mem_new_i64(cpu_env,
105         offsetof(CPUARMState, exclusive_high), "exclusive_high");
106 }
107
108 /*
109  * Return the core mmu_idx to use for A64 "unprivileged load/store" insns
110  */
111 static int get_a64_user_mem_index(DisasContext *s)
112 {
113     /*
114      * If AccType_UNPRIV is not used, the insn uses AccType_NORMAL,
115      * which is the usual mmu_idx for this cpu state.
116      */
117     ARMMMUIdx useridx = s->mmu_idx;
118
119     if (s->unpriv) {
120         /*
121          * We have pre-computed the condition for AccType_UNPRIV.
122          * Therefore we should never get here with a mmu_idx for
123          * which we do not know the corresponding user mmu_idx.
124          */
125         switch (useridx) {
126         case ARMMMUIdx_E10_1:
127         case ARMMMUIdx_E10_1_PAN:
128             useridx = ARMMMUIdx_E10_0;
129             break;
130         case ARMMMUIdx_E20_2:
131         case ARMMMUIdx_E20_2_PAN:
132             useridx = ARMMMUIdx_E20_0;
133             break;
134         case ARMMMUIdx_SE10_1:
135         case ARMMMUIdx_SE10_1_PAN:
136             useridx = ARMMMUIdx_SE10_0;
137             break;
138         default:
139             g_assert_not_reached();
140         }
141     }
142     return arm_to_core_mmu_idx(useridx);
143 }
144
145 static void reset_btype(DisasContext *s)
146 {
147     if (s->btype != 0) {
148         TCGv_i32 zero = tcg_const_i32(0);
149         tcg_gen_st_i32(zero, cpu_env, offsetof(CPUARMState, btype));
150         tcg_temp_free_i32(zero);
151         s->btype = 0;
152     }
153 }
154
155 static void set_btype(DisasContext *s, int val)
156 {
157     TCGv_i32 tcg_val;
158
159     /* BTYPE is a 2-bit field, and 0 should be done with reset_btype.  */
160     tcg_debug_assert(val >= 1 && val <= 3);
161
162     tcg_val = tcg_const_i32(val);
163     tcg_gen_st_i32(tcg_val, cpu_env, offsetof(CPUARMState, btype));
164     tcg_temp_free_i32(tcg_val);
165     s->btype = -1;
166 }
167
168 void gen_a64_set_pc_im(uint64_t val)
169 {
170     tcg_gen_movi_i64(cpu_pc, val);
171 }
172
173 /*
174  * Handle Top Byte Ignore (TBI) bits.
175  *
176  * If address tagging is enabled via the TCR TBI bits:
177  *  + for EL2 and EL3 there is only one TBI bit, and if it is set
178  *    then the address is zero-extended, clearing bits [63:56]
179  *  + for EL0 and EL1, TBI0 controls addresses with bit 55 == 0
180  *    and TBI1 controls addressses with bit 55 == 1.
181  *    If the appropriate TBI bit is set for the address then
182  *    the address is sign-extended from bit 55 into bits [63:56]
183  *
184  * Here We have concatenated TBI{1,0} into tbi.
185  */
186 static void gen_top_byte_ignore(DisasContext *s, TCGv_i64 dst,
187                                 TCGv_i64 src, int tbi)
188 {
189     if (tbi == 0) {
190         /* Load unmodified address */
191         tcg_gen_mov_i64(dst, src);
192     } else if (!regime_has_2_ranges(s->mmu_idx)) {
193         /* Force tag byte to all zero */
194         tcg_gen_extract_i64(dst, src, 0, 56);
195     } else {
196         /* Sign-extend from bit 55.  */
197         tcg_gen_sextract_i64(dst, src, 0, 56);
198
199         if (tbi != 3) {
200             TCGv_i64 tcg_zero = tcg_const_i64(0);
201
202             /*
203              * The two TBI bits differ.
204              * If tbi0, then !tbi1: only use the extension if positive.
205              * if !tbi0, then tbi1: only use the extension if negative.
206              */
207             tcg_gen_movcond_i64(tbi == 1 ? TCG_COND_GE : TCG_COND_LT,
208                                 dst, dst, tcg_zero, dst, src);
209             tcg_temp_free_i64(tcg_zero);
210         }
211     }
212 }
213
214 static void gen_a64_set_pc(DisasContext *s, TCGv_i64 src)
215 {
216     /*
217      * If address tagging is enabled for instructions via the TCR TBI bits,
218      * then loading an address into the PC will clear out any tag.
219      */
220     gen_top_byte_ignore(s, cpu_pc, src, s->tbii);
221 }
222
223 /*
224  * Return a "clean" address for ADDR according to TBID.
225  * This is always a fresh temporary, as we need to be able to
226  * increment this independently of a dirty write-back address.
227  */
228 static TCGv_i64 clean_data_tbi(DisasContext *s, TCGv_i64 addr)
229 {
230     TCGv_i64 clean = new_tmp_a64(s);
231     /*
232      * In order to get the correct value in the FAR_ELx register,
233      * we must present the memory subsystem with the "dirty" address
234      * including the TBI.  In system mode we can make this work via
235      * the TLB, dropping the TBI during translation.  But for user-only
236      * mode we don't have that option, and must remove the top byte now.
237      */
238 #ifdef CONFIG_USER_ONLY
239     gen_top_byte_ignore(s, clean, addr, s->tbid);
240 #else
241     tcg_gen_mov_i64(clean, addr);
242 #endif
243     return clean;
244 }
245
246 typedef struct DisasCompare64 {
247     TCGCond cond;
248     TCGv_i64 value;
249 } DisasCompare64;
250
251 static void a64_test_cc(DisasCompare64 *c64, int cc)
252 {
253     DisasCompare c32;
254
255     arm_test_cc(&c32, cc);
256
257     /* Sign-extend the 32-bit value so that the GE/LT comparisons work
258        * properly.  The NE/EQ comparisons are also fine with this choice.  */
259     c64->cond = c32.cond;
260     c64->value = tcg_temp_new_i64();
261     tcg_gen_ext_i32_i64(c64->value, c32.value);
262
263     arm_free_cc(&c32);
264 }
265
266 static void a64_free_cc(DisasCompare64 *c64)
267 {
268     tcg_temp_free_i64(c64->value);
269 }
270
271 static void gen_exception_internal(int excp)
272 {
273     TCGv_i32 tcg_excp = tcg_const_i32(excp);
274
275     assert(excp_is_internal(excp));
276     gen_helper_exception_internal(cpu_env, tcg_excp);
277     tcg_temp_free_i32(tcg_excp);
278 }
279
280 static void gen_exception_internal_insn(DisasContext *s, uint64_t pc, int excp)
281 {
282     gen_a64_set_pc_im(pc);
283     gen_exception_internal(excp);
284     s->base.is_jmp = DISAS_NORETURN;
285 }
286
287 static void gen_exception_insn(DisasContext *s, uint64_t pc, int excp,
288                                uint32_t syndrome, uint32_t target_el)
289 {
290     gen_a64_set_pc_im(pc);
291     gen_exception(excp, syndrome, target_el);
292     s->base.is_jmp = DISAS_NORETURN;
293 }
294
295 static void gen_exception_bkpt_insn(DisasContext *s, uint32_t syndrome)
296 {
297     TCGv_i32 tcg_syn;
298
299     gen_a64_set_pc_im(s->pc_curr);
300     tcg_syn = tcg_const_i32(syndrome);
301     gen_helper_exception_bkpt_insn(cpu_env, tcg_syn);
302     tcg_temp_free_i32(tcg_syn);
303     s->base.is_jmp = DISAS_NORETURN;
304 }
305
306 static void gen_step_complete_exception(DisasContext *s)
307 {
308     /* We just completed step of an insn. Move from Active-not-pending
309      * to Active-pending, and then also take the swstep exception.
310      * This corresponds to making the (IMPDEF) choice to prioritize
311      * swstep exceptions over asynchronous exceptions taken to an exception
312      * level where debug is disabled. This choice has the advantage that
313      * we do not need to maintain internal state corresponding to the
314      * ISV/EX syndrome bits between completion of the step and generation
315      * of the exception, and our syndrome information is always correct.
316      */
317     gen_ss_advance(s);
318     gen_swstep_exception(s, 1, s->is_ldex);
319     s->base.is_jmp = DISAS_NORETURN;
320 }
321
322 static inline bool use_goto_tb(DisasContext *s, int n, uint64_t dest)
323 {
324     /* No direct tb linking with singlestep (either QEMU's or the ARM
325      * debug architecture kind) or deterministic io
326      */
327     if (s->base.singlestep_enabled || s->ss_active ||
328         (tb_cflags(s->base.tb) & CF_LAST_IO)) {
329         return false;
330     }
331
332 #ifndef CONFIG_USER_ONLY
333     /* Only link tbs from inside the same guest page */
334     if ((s->base.tb->pc & TARGET_PAGE_MASK) != (dest & TARGET_PAGE_MASK)) {
335         return false;
336     }
337 #endif
338
339     return true;
340 }
341
342 static inline void gen_goto_tb(DisasContext *s, int n, uint64_t dest)
343 {
344     TranslationBlock *tb;
345
346     tb = s->base.tb;
347     if (use_goto_tb(s, n, dest)) {
348         tcg_gen_goto_tb(n);
349         gen_a64_set_pc_im(dest);
350         tcg_gen_exit_tb(tb, n);
351         s->base.is_jmp = DISAS_NORETURN;
352     } else {
353         gen_a64_set_pc_im(dest);
354         if (s->ss_active) {
355             gen_step_complete_exception(s);
356         } else if (s->base.singlestep_enabled) {
357             gen_exception_internal(EXCP_DEBUG);
358         } else {
359             tcg_gen_lookup_and_goto_ptr();
360             s->base.is_jmp = DISAS_NORETURN;
361         }
362     }
363 }
364
365 void unallocated_encoding(DisasContext *s)
366 {
367     /* Unallocated and reserved encodings are uncategorized */
368     gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_uncategorized(),
369                        default_exception_el(s));
370 }
371
372 static void init_tmp_a64_array(DisasContext *s)
373 {
374 #ifdef CONFIG_DEBUG_TCG
375     memset(s->tmp_a64, 0, sizeof(s->tmp_a64));
376 #endif
377     s->tmp_a64_count = 0;
378 }
379
380 static void free_tmp_a64(DisasContext *s)
381 {
382     int i;
383     for (i = 0; i < s->tmp_a64_count; i++) {
384         tcg_temp_free_i64(s->tmp_a64[i]);
385     }
386     init_tmp_a64_array(s);
387 }
388
389 TCGv_i64 new_tmp_a64(DisasContext *s)
390 {
391     assert(s->tmp_a64_count < TMP_A64_MAX);
392     return s->tmp_a64[s->tmp_a64_count++] = tcg_temp_new_i64();
393 }
394
395 TCGv_i64 new_tmp_a64_zero(DisasContext *s)
396 {
397     TCGv_i64 t = new_tmp_a64(s);
398     tcg_gen_movi_i64(t, 0);
399     return t;
400 }
401
402 /*
403  * Register access functions
404  *
405  * These functions are used for directly accessing a register in where
406  * changes to the final register value are likely to be made. If you
407  * need to use a register for temporary calculation (e.g. index type
408  * operations) use the read_* form.
409  *
410  * B1.2.1 Register mappings
411  *
412  * In instruction register encoding 31 can refer to ZR (zero register) or
413  * the SP (stack pointer) depending on context. In QEMU's case we map SP
414  * to cpu_X[31] and ZR accesses to a temporary which can be discarded.
415  * This is the point of the _sp forms.
416  */
417 TCGv_i64 cpu_reg(DisasContext *s, int reg)
418 {
419     if (reg == 31) {
420         return new_tmp_a64_zero(s);
421     } else {
422         return cpu_X[reg];
423     }
424 }
425
426 /* register access for when 31 == SP */
427 TCGv_i64 cpu_reg_sp(DisasContext *s, int reg)
428 {
429     return cpu_X[reg];
430 }
431
432 /* read a cpu register in 32bit/64bit mode. Returns a TCGv_i64
433  * representing the register contents. This TCGv is an auto-freed
434  * temporary so it need not be explicitly freed, and may be modified.
435  */
436 TCGv_i64 read_cpu_reg(DisasContext *s, int reg, int sf)
437 {
438     TCGv_i64 v = new_tmp_a64(s);
439     if (reg != 31) {
440         if (sf) {
441             tcg_gen_mov_i64(v, cpu_X[reg]);
442         } else {
443             tcg_gen_ext32u_i64(v, cpu_X[reg]);
444         }
445     } else {
446         tcg_gen_movi_i64(v, 0);
447     }
448     return v;
449 }
450
451 TCGv_i64 read_cpu_reg_sp(DisasContext *s, int reg, int sf)
452 {
453     TCGv_i64 v = new_tmp_a64(s);
454     if (sf) {
455         tcg_gen_mov_i64(v, cpu_X[reg]);
456     } else {
457         tcg_gen_ext32u_i64(v, cpu_X[reg]);
458     }
459     return v;
460 }
461
462 /* Return the offset into CPUARMState of a slice (from
463  * the least significant end) of FP register Qn (ie
464  * Dn, Sn, Hn or Bn).
465  * (Note that this is not the same mapping as for A32; see cpu.h)
466  */
467 static inline int fp_reg_offset(DisasContext *s, int regno, MemOp size)
468 {
469     return vec_reg_offset(s, regno, 0, size);
470 }
471
472 /* Offset of the high half of the 128 bit vector Qn */
473 static inline int fp_reg_hi_offset(DisasContext *s, int regno)
474 {
475     return vec_reg_offset(s, regno, 1, MO_64);
476 }
477
478 /* Convenience accessors for reading and writing single and double
479  * FP registers. Writing clears the upper parts of the associated
480  * 128 bit vector register, as required by the architecture.
481  * Note that unlike the GP register accessors, the values returned
482  * by the read functions must be manually freed.
483  */
484 static TCGv_i64 read_fp_dreg(DisasContext *s, int reg)
485 {
486     TCGv_i64 v = tcg_temp_new_i64();
487
488     tcg_gen_ld_i64(v, cpu_env, fp_reg_offset(s, reg, MO_64));
489     return v;
490 }
491
492 static TCGv_i32 read_fp_sreg(DisasContext *s, int reg)
493 {
494     TCGv_i32 v = tcg_temp_new_i32();
495
496     tcg_gen_ld_i32(v, cpu_env, fp_reg_offset(s, reg, MO_32));
497     return v;
498 }
499
500 static TCGv_i32 read_fp_hreg(DisasContext *s, int reg)
501 {
502     TCGv_i32 v = tcg_temp_new_i32();
503
504     tcg_gen_ld16u_i32(v, cpu_env, fp_reg_offset(s, reg, MO_16));
505     return v;
506 }
507
508 /* Clear the bits above an N-bit vector, for N = (is_q ? 128 : 64).
509  * If SVE is not enabled, then there are only 128 bits in the vector.
510  */
511 static void clear_vec_high(DisasContext *s, bool is_q, int rd)
512 {
513     unsigned ofs = fp_reg_offset(s, rd, MO_64);
514     unsigned vsz = vec_full_reg_size(s);
515
516     if (!is_q) {
517         TCGv_i64 tcg_zero = tcg_const_i64(0);
518         tcg_gen_st_i64(tcg_zero, cpu_env, ofs + 8);
519         tcg_temp_free_i64(tcg_zero);
520     }
521     if (vsz > 16) {
522         tcg_gen_gvec_dup8i(ofs + 16, vsz - 16, vsz - 16, 0);
523     }
524 }
525
526 void write_fp_dreg(DisasContext *s, int reg, TCGv_i64 v)
527 {
528     unsigned ofs = fp_reg_offset(s, reg, MO_64);
529
530     tcg_gen_st_i64(v, cpu_env, ofs);
531     clear_vec_high(s, false, reg);
532 }
533
534 static void write_fp_sreg(DisasContext *s, int reg, TCGv_i32 v)
535 {
536     TCGv_i64 tmp = tcg_temp_new_i64();
537
538     tcg_gen_extu_i32_i64(tmp, v);
539     write_fp_dreg(s, reg, tmp);
540     tcg_temp_free_i64(tmp);
541 }
542
543 TCGv_ptr get_fpstatus_ptr(bool is_f16)
544 {
545     TCGv_ptr statusptr = tcg_temp_new_ptr();
546     int offset;
547
548     /* In A64 all instructions (both FP and Neon) use the FPCR; there
549      * is no equivalent of the A32 Neon "standard FPSCR value".
550      * However half-precision operations operate under a different
551      * FZ16 flag and use vfp.fp_status_f16 instead of vfp.fp_status.
552      */
553     if (is_f16) {
554         offset = offsetof(CPUARMState, vfp.fp_status_f16);
555     } else {
556         offset = offsetof(CPUARMState, vfp.fp_status);
557     }
558     tcg_gen_addi_ptr(statusptr, cpu_env, offset);
559     return statusptr;
560 }
561
562 /* Expand a 2-operand AdvSIMD vector operation using an expander function.  */
563 static void gen_gvec_fn2(DisasContext *s, bool is_q, int rd, int rn,
564                          GVecGen2Fn *gvec_fn, int vece)
565 {
566     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
567             is_q ? 16 : 8, vec_full_reg_size(s));
568 }
569
570 /* Expand a 2-operand + immediate AdvSIMD vector operation using
571  * an expander function.
572  */
573 static void gen_gvec_fn2i(DisasContext *s, bool is_q, int rd, int rn,
574                           int64_t imm, GVecGen2iFn *gvec_fn, int vece)
575 {
576     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
577             imm, is_q ? 16 : 8, vec_full_reg_size(s));
578 }
579
580 /* Expand a 3-operand AdvSIMD vector operation using an expander function.  */
581 static void gen_gvec_fn3(DisasContext *s, bool is_q, int rd, int rn, int rm,
582                          GVecGen3Fn *gvec_fn, int vece)
583 {
584     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
585             vec_full_reg_offset(s, rm), is_q ? 16 : 8, vec_full_reg_size(s));
586 }
587
588 /* Expand a 4-operand AdvSIMD vector operation using an expander function.  */
589 static void gen_gvec_fn4(DisasContext *s, bool is_q, int rd, int rn, int rm,
590                          int rx, GVecGen4Fn *gvec_fn, int vece)
591 {
592     gvec_fn(vece, vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
593             vec_full_reg_offset(s, rm), vec_full_reg_offset(s, rx),
594             is_q ? 16 : 8, vec_full_reg_size(s));
595 }
596
597 /* Expand a 2-operand + immediate AdvSIMD vector operation using
598  * an op descriptor.
599  */
600 static void gen_gvec_op2i(DisasContext *s, bool is_q, int rd,
601                           int rn, int64_t imm, const GVecGen2i *gvec_op)
602 {
603     tcg_gen_gvec_2i(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
604                     is_q ? 16 : 8, vec_full_reg_size(s), imm, gvec_op);
605 }
606
607 /* Expand a 3-operand AdvSIMD vector operation using an op descriptor.  */
608 static void gen_gvec_op3(DisasContext *s, bool is_q, int rd,
609                          int rn, int rm, const GVecGen3 *gvec_op)
610 {
611     tcg_gen_gvec_3(vec_full_reg_offset(s, rd), vec_full_reg_offset(s, rn),
612                    vec_full_reg_offset(s, rm), is_q ? 16 : 8,
613                    vec_full_reg_size(s), gvec_op);
614 }
615
616 /* Expand a 3-operand operation using an out-of-line helper.  */
617 static void gen_gvec_op3_ool(DisasContext *s, bool is_q, int rd,
618                              int rn, int rm, int data, gen_helper_gvec_3 *fn)
619 {
620     tcg_gen_gvec_3_ool(vec_full_reg_offset(s, rd),
621                        vec_full_reg_offset(s, rn),
622                        vec_full_reg_offset(s, rm),
623                        is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
624 }
625
626 /* Expand a 3-operand + env pointer operation using
627  * an out-of-line helper.
628  */
629 static void gen_gvec_op3_env(DisasContext *s, bool is_q, int rd,
630                              int rn, int rm, gen_helper_gvec_3_ptr *fn)
631 {
632     tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
633                        vec_full_reg_offset(s, rn),
634                        vec_full_reg_offset(s, rm), cpu_env,
635                        is_q ? 16 : 8, vec_full_reg_size(s), 0, fn);
636 }
637
638 /* Expand a 3-operand + fpstatus pointer + simd data value operation using
639  * an out-of-line helper.
640  */
641 static void gen_gvec_op3_fpst(DisasContext *s, bool is_q, int rd, int rn,
642                               int rm, bool is_fp16, int data,
643                               gen_helper_gvec_3_ptr *fn)
644 {
645     TCGv_ptr fpst = get_fpstatus_ptr(is_fp16);
646     tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
647                        vec_full_reg_offset(s, rn),
648                        vec_full_reg_offset(s, rm), fpst,
649                        is_q ? 16 : 8, vec_full_reg_size(s), data, fn);
650     tcg_temp_free_ptr(fpst);
651 }
652
653 /* Set ZF and NF based on a 64 bit result. This is alas fiddlier
654  * than the 32 bit equivalent.
655  */
656 static inline void gen_set_NZ64(TCGv_i64 result)
657 {
658     tcg_gen_extr_i64_i32(cpu_ZF, cpu_NF, result);
659     tcg_gen_or_i32(cpu_ZF, cpu_ZF, cpu_NF);
660 }
661
662 /* Set NZCV as for a logical operation: NZ as per result, CV cleared. */
663 static inline void gen_logic_CC(int sf, TCGv_i64 result)
664 {
665     if (sf) {
666         gen_set_NZ64(result);
667     } else {
668         tcg_gen_extrl_i64_i32(cpu_ZF, result);
669         tcg_gen_mov_i32(cpu_NF, cpu_ZF);
670     }
671     tcg_gen_movi_i32(cpu_CF, 0);
672     tcg_gen_movi_i32(cpu_VF, 0);
673 }
674
675 /* dest = T0 + T1; compute C, N, V and Z flags */
676 static void gen_add_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
677 {
678     if (sf) {
679         TCGv_i64 result, flag, tmp;
680         result = tcg_temp_new_i64();
681         flag = tcg_temp_new_i64();
682         tmp = tcg_temp_new_i64();
683
684         tcg_gen_movi_i64(tmp, 0);
685         tcg_gen_add2_i64(result, flag, t0, tmp, t1, tmp);
686
687         tcg_gen_extrl_i64_i32(cpu_CF, flag);
688
689         gen_set_NZ64(result);
690
691         tcg_gen_xor_i64(flag, result, t0);
692         tcg_gen_xor_i64(tmp, t0, t1);
693         tcg_gen_andc_i64(flag, flag, tmp);
694         tcg_temp_free_i64(tmp);
695         tcg_gen_extrh_i64_i32(cpu_VF, flag);
696
697         tcg_gen_mov_i64(dest, result);
698         tcg_temp_free_i64(result);
699         tcg_temp_free_i64(flag);
700     } else {
701         /* 32 bit arithmetic */
702         TCGv_i32 t0_32 = tcg_temp_new_i32();
703         TCGv_i32 t1_32 = tcg_temp_new_i32();
704         TCGv_i32 tmp = tcg_temp_new_i32();
705
706         tcg_gen_movi_i32(tmp, 0);
707         tcg_gen_extrl_i64_i32(t0_32, t0);
708         tcg_gen_extrl_i64_i32(t1_32, t1);
709         tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, t1_32, tmp);
710         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
711         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
712         tcg_gen_xor_i32(tmp, t0_32, t1_32);
713         tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
714         tcg_gen_extu_i32_i64(dest, cpu_NF);
715
716         tcg_temp_free_i32(tmp);
717         tcg_temp_free_i32(t0_32);
718         tcg_temp_free_i32(t1_32);
719     }
720 }
721
722 /* dest = T0 - T1; compute C, N, V and Z flags */
723 static void gen_sub_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
724 {
725     if (sf) {
726         /* 64 bit arithmetic */
727         TCGv_i64 result, flag, tmp;
728
729         result = tcg_temp_new_i64();
730         flag = tcg_temp_new_i64();
731         tcg_gen_sub_i64(result, t0, t1);
732
733         gen_set_NZ64(result);
734
735         tcg_gen_setcond_i64(TCG_COND_GEU, flag, t0, t1);
736         tcg_gen_extrl_i64_i32(cpu_CF, flag);
737
738         tcg_gen_xor_i64(flag, result, t0);
739         tmp = tcg_temp_new_i64();
740         tcg_gen_xor_i64(tmp, t0, t1);
741         tcg_gen_and_i64(flag, flag, tmp);
742         tcg_temp_free_i64(tmp);
743         tcg_gen_extrh_i64_i32(cpu_VF, flag);
744         tcg_gen_mov_i64(dest, result);
745         tcg_temp_free_i64(flag);
746         tcg_temp_free_i64(result);
747     } else {
748         /* 32 bit arithmetic */
749         TCGv_i32 t0_32 = tcg_temp_new_i32();
750         TCGv_i32 t1_32 = tcg_temp_new_i32();
751         TCGv_i32 tmp;
752
753         tcg_gen_extrl_i64_i32(t0_32, t0);
754         tcg_gen_extrl_i64_i32(t1_32, t1);
755         tcg_gen_sub_i32(cpu_NF, t0_32, t1_32);
756         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
757         tcg_gen_setcond_i32(TCG_COND_GEU, cpu_CF, t0_32, t1_32);
758         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
759         tmp = tcg_temp_new_i32();
760         tcg_gen_xor_i32(tmp, t0_32, t1_32);
761         tcg_temp_free_i32(t0_32);
762         tcg_temp_free_i32(t1_32);
763         tcg_gen_and_i32(cpu_VF, cpu_VF, tmp);
764         tcg_temp_free_i32(tmp);
765         tcg_gen_extu_i32_i64(dest, cpu_NF);
766     }
767 }
768
769 /* dest = T0 + T1 + CF; do not compute flags. */
770 static void gen_adc(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
771 {
772     TCGv_i64 flag = tcg_temp_new_i64();
773     tcg_gen_extu_i32_i64(flag, cpu_CF);
774     tcg_gen_add_i64(dest, t0, t1);
775     tcg_gen_add_i64(dest, dest, flag);
776     tcg_temp_free_i64(flag);
777
778     if (!sf) {
779         tcg_gen_ext32u_i64(dest, dest);
780     }
781 }
782
783 /* dest = T0 + T1 + CF; compute C, N, V and Z flags. */
784 static void gen_adc_CC(int sf, TCGv_i64 dest, TCGv_i64 t0, TCGv_i64 t1)
785 {
786     if (sf) {
787         TCGv_i64 result, cf_64, vf_64, tmp;
788         result = tcg_temp_new_i64();
789         cf_64 = tcg_temp_new_i64();
790         vf_64 = tcg_temp_new_i64();
791         tmp = tcg_const_i64(0);
792
793         tcg_gen_extu_i32_i64(cf_64, cpu_CF);
794         tcg_gen_add2_i64(result, cf_64, t0, tmp, cf_64, tmp);
795         tcg_gen_add2_i64(result, cf_64, result, cf_64, t1, tmp);
796         tcg_gen_extrl_i64_i32(cpu_CF, cf_64);
797         gen_set_NZ64(result);
798
799         tcg_gen_xor_i64(vf_64, result, t0);
800         tcg_gen_xor_i64(tmp, t0, t1);
801         tcg_gen_andc_i64(vf_64, vf_64, tmp);
802         tcg_gen_extrh_i64_i32(cpu_VF, vf_64);
803
804         tcg_gen_mov_i64(dest, result);
805
806         tcg_temp_free_i64(tmp);
807         tcg_temp_free_i64(vf_64);
808         tcg_temp_free_i64(cf_64);
809         tcg_temp_free_i64(result);
810     } else {
811         TCGv_i32 t0_32, t1_32, tmp;
812         t0_32 = tcg_temp_new_i32();
813         t1_32 = tcg_temp_new_i32();
814         tmp = tcg_const_i32(0);
815
816         tcg_gen_extrl_i64_i32(t0_32, t0);
817         tcg_gen_extrl_i64_i32(t1_32, t1);
818         tcg_gen_add2_i32(cpu_NF, cpu_CF, t0_32, tmp, cpu_CF, tmp);
819         tcg_gen_add2_i32(cpu_NF, cpu_CF, cpu_NF, cpu_CF, t1_32, tmp);
820
821         tcg_gen_mov_i32(cpu_ZF, cpu_NF);
822         tcg_gen_xor_i32(cpu_VF, cpu_NF, t0_32);
823         tcg_gen_xor_i32(tmp, t0_32, t1_32);
824         tcg_gen_andc_i32(cpu_VF, cpu_VF, tmp);
825         tcg_gen_extu_i32_i64(dest, cpu_NF);
826
827         tcg_temp_free_i32(tmp);
828         tcg_temp_free_i32(t1_32);
829         tcg_temp_free_i32(t0_32);
830     }
831 }
832
833 /*
834  * Load/Store generators
835  */
836
837 /*
838  * Store from GPR register to memory.
839  */
840 static void do_gpr_st_memidx(DisasContext *s, TCGv_i64 source,
841                              TCGv_i64 tcg_addr, int size, int memidx,
842                              bool iss_valid,
843                              unsigned int iss_srt,
844                              bool iss_sf, bool iss_ar)
845 {
846     g_assert(size <= 3);
847     tcg_gen_qemu_st_i64(source, tcg_addr, memidx, s->be_data + size);
848
849     if (iss_valid) {
850         uint32_t syn;
851
852         syn = syn_data_abort_with_iss(0,
853                                       size,
854                                       false,
855                                       iss_srt,
856                                       iss_sf,
857                                       iss_ar,
858                                       0, 0, 0, 0, 0, false);
859         disas_set_insn_syndrome(s, syn);
860     }
861 }
862
863 static void do_gpr_st(DisasContext *s, TCGv_i64 source,
864                       TCGv_i64 tcg_addr, int size,
865                       bool iss_valid,
866                       unsigned int iss_srt,
867                       bool iss_sf, bool iss_ar)
868 {
869     do_gpr_st_memidx(s, source, tcg_addr, size, get_mem_index(s),
870                      iss_valid, iss_srt, iss_sf, iss_ar);
871 }
872
873 /*
874  * Load from memory to GPR register
875  */
876 static void do_gpr_ld_memidx(DisasContext *s,
877                              TCGv_i64 dest, TCGv_i64 tcg_addr,
878                              int size, bool is_signed,
879                              bool extend, int memidx,
880                              bool iss_valid, unsigned int iss_srt,
881                              bool iss_sf, bool iss_ar)
882 {
883     MemOp memop = s->be_data + size;
884
885     g_assert(size <= 3);
886
887     if (is_signed) {
888         memop += MO_SIGN;
889     }
890
891     tcg_gen_qemu_ld_i64(dest, tcg_addr, memidx, memop);
892
893     if (extend && is_signed) {
894         g_assert(size < 3);
895         tcg_gen_ext32u_i64(dest, dest);
896     }
897
898     if (iss_valid) {
899         uint32_t syn;
900
901         syn = syn_data_abort_with_iss(0,
902                                       size,
903                                       is_signed,
904                                       iss_srt,
905                                       iss_sf,
906                                       iss_ar,
907                                       0, 0, 0, 0, 0, false);
908         disas_set_insn_syndrome(s, syn);
909     }
910 }
911
912 static void do_gpr_ld(DisasContext *s,
913                       TCGv_i64 dest, TCGv_i64 tcg_addr,
914                       int size, bool is_signed, bool extend,
915                       bool iss_valid, unsigned int iss_srt,
916                       bool iss_sf, bool iss_ar)
917 {
918     do_gpr_ld_memidx(s, dest, tcg_addr, size, is_signed, extend,
919                      get_mem_index(s),
920                      iss_valid, iss_srt, iss_sf, iss_ar);
921 }
922
923 /*
924  * Store from FP register to memory
925  */
926 static void do_fp_st(DisasContext *s, int srcidx, TCGv_i64 tcg_addr, int size)
927 {
928     /* This writes the bottom N bits of a 128 bit wide vector to memory */
929     TCGv_i64 tmp = tcg_temp_new_i64();
930     tcg_gen_ld_i64(tmp, cpu_env, fp_reg_offset(s, srcidx, MO_64));
931     if (size < 4) {
932         tcg_gen_qemu_st_i64(tmp, tcg_addr, get_mem_index(s),
933                             s->be_data + size);
934     } else {
935         bool be = s->be_data == MO_BE;
936         TCGv_i64 tcg_hiaddr = tcg_temp_new_i64();
937
938         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
939         tcg_gen_qemu_st_i64(tmp, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
940                             s->be_data | MO_Q);
941         tcg_gen_ld_i64(tmp, cpu_env, fp_reg_hi_offset(s, srcidx));
942         tcg_gen_qemu_st_i64(tmp, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
943                             s->be_data | MO_Q);
944         tcg_temp_free_i64(tcg_hiaddr);
945     }
946
947     tcg_temp_free_i64(tmp);
948 }
949
950 /*
951  * Load from memory to FP register
952  */
953 static void do_fp_ld(DisasContext *s, int destidx, TCGv_i64 tcg_addr, int size)
954 {
955     /* This always zero-extends and writes to a full 128 bit wide vector */
956     TCGv_i64 tmplo = tcg_temp_new_i64();
957     TCGv_i64 tmphi;
958
959     if (size < 4) {
960         MemOp memop = s->be_data + size;
961         tmphi = tcg_const_i64(0);
962         tcg_gen_qemu_ld_i64(tmplo, tcg_addr, get_mem_index(s), memop);
963     } else {
964         bool be = s->be_data == MO_BE;
965         TCGv_i64 tcg_hiaddr;
966
967         tmphi = tcg_temp_new_i64();
968         tcg_hiaddr = tcg_temp_new_i64();
969
970         tcg_gen_addi_i64(tcg_hiaddr, tcg_addr, 8);
971         tcg_gen_qemu_ld_i64(tmplo, be ? tcg_hiaddr : tcg_addr, get_mem_index(s),
972                             s->be_data | MO_Q);
973         tcg_gen_qemu_ld_i64(tmphi, be ? tcg_addr : tcg_hiaddr, get_mem_index(s),
974                             s->be_data | MO_Q);
975         tcg_temp_free_i64(tcg_hiaddr);
976     }
977
978     tcg_gen_st_i64(tmplo, cpu_env, fp_reg_offset(s, destidx, MO_64));
979     tcg_gen_st_i64(tmphi, cpu_env, fp_reg_hi_offset(s, destidx));
980
981     tcg_temp_free_i64(tmplo);
982     tcg_temp_free_i64(tmphi);
983
984     clear_vec_high(s, true, destidx);
985 }
986
987 /*
988  * Vector load/store helpers.
989  *
990  * The principal difference between this and a FP load is that we don't
991  * zero extend as we are filling a partial chunk of the vector register.
992  * These functions don't support 128 bit loads/stores, which would be
993  * normal load/store operations.
994  *
995  * The _i32 versions are useful when operating on 32 bit quantities
996  * (eg for floating point single or using Neon helper functions).
997  */
998
999 /* Get value of an element within a vector register */
1000 static void read_vec_element(DisasContext *s, TCGv_i64 tcg_dest, int srcidx,
1001                              int element, MemOp memop)
1002 {
1003     int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
1004     switch (memop) {
1005     case MO_8:
1006         tcg_gen_ld8u_i64(tcg_dest, cpu_env, vect_off);
1007         break;
1008     case MO_16:
1009         tcg_gen_ld16u_i64(tcg_dest, cpu_env, vect_off);
1010         break;
1011     case MO_32:
1012         tcg_gen_ld32u_i64(tcg_dest, cpu_env, vect_off);
1013         break;
1014     case MO_8|MO_SIGN:
1015         tcg_gen_ld8s_i64(tcg_dest, cpu_env, vect_off);
1016         break;
1017     case MO_16|MO_SIGN:
1018         tcg_gen_ld16s_i64(tcg_dest, cpu_env, vect_off);
1019         break;
1020     case MO_32|MO_SIGN:
1021         tcg_gen_ld32s_i64(tcg_dest, cpu_env, vect_off);
1022         break;
1023     case MO_64:
1024     case MO_64|MO_SIGN:
1025         tcg_gen_ld_i64(tcg_dest, cpu_env, vect_off);
1026         break;
1027     default:
1028         g_assert_not_reached();
1029     }
1030 }
1031
1032 static void read_vec_element_i32(DisasContext *s, TCGv_i32 tcg_dest, int srcidx,
1033                                  int element, MemOp memop)
1034 {
1035     int vect_off = vec_reg_offset(s, srcidx, element, memop & MO_SIZE);
1036     switch (memop) {
1037     case MO_8:
1038         tcg_gen_ld8u_i32(tcg_dest, cpu_env, vect_off);
1039         break;
1040     case MO_16:
1041         tcg_gen_ld16u_i32(tcg_dest, cpu_env, vect_off);
1042         break;
1043     case MO_8|MO_SIGN:
1044         tcg_gen_ld8s_i32(tcg_dest, cpu_env, vect_off);
1045         break;
1046     case MO_16|MO_SIGN:
1047         tcg_gen_ld16s_i32(tcg_dest, cpu_env, vect_off);
1048         break;
1049     case MO_32:
1050     case MO_32|MO_SIGN:
1051         tcg_gen_ld_i32(tcg_dest, cpu_env, vect_off);
1052         break;
1053     default:
1054         g_assert_not_reached();
1055     }
1056 }
1057
1058 /* Set value of an element within a vector register */
1059 static void write_vec_element(DisasContext *s, TCGv_i64 tcg_src, int destidx,
1060                               int element, MemOp memop)
1061 {
1062     int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
1063     switch (memop) {
1064     case MO_8:
1065         tcg_gen_st8_i64(tcg_src, cpu_env, vect_off);
1066         break;
1067     case MO_16:
1068         tcg_gen_st16_i64(tcg_src, cpu_env, vect_off);
1069         break;
1070     case MO_32:
1071         tcg_gen_st32_i64(tcg_src, cpu_env, vect_off);
1072         break;
1073     case MO_64:
1074         tcg_gen_st_i64(tcg_src, cpu_env, vect_off);
1075         break;
1076     default:
1077         g_assert_not_reached();
1078     }
1079 }
1080
1081 static void write_vec_element_i32(DisasContext *s, TCGv_i32 tcg_src,
1082                                   int destidx, int element, MemOp memop)
1083 {
1084     int vect_off = vec_reg_offset(s, destidx, element, memop & MO_SIZE);
1085     switch (memop) {
1086     case MO_8:
1087         tcg_gen_st8_i32(tcg_src, cpu_env, vect_off);
1088         break;
1089     case MO_16:
1090         tcg_gen_st16_i32(tcg_src, cpu_env, vect_off);
1091         break;
1092     case MO_32:
1093         tcg_gen_st_i32(tcg_src, cpu_env, vect_off);
1094         break;
1095     default:
1096         g_assert_not_reached();
1097     }
1098 }
1099
1100 /* Store from vector register to memory */
1101 static void do_vec_st(DisasContext *s, int srcidx, int element,
1102                       TCGv_i64 tcg_addr, int size, MemOp endian)
1103 {
1104     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1105
1106     read_vec_element(s, tcg_tmp, srcidx, element, size);
1107     tcg_gen_qemu_st_i64(tcg_tmp, tcg_addr, get_mem_index(s), endian | size);
1108
1109     tcg_temp_free_i64(tcg_tmp);
1110 }
1111
1112 /* Load from memory to vector register */
1113 static void do_vec_ld(DisasContext *s, int destidx, int element,
1114                       TCGv_i64 tcg_addr, int size, MemOp endian)
1115 {
1116     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
1117
1118     tcg_gen_qemu_ld_i64(tcg_tmp, tcg_addr, get_mem_index(s), endian | size);
1119     write_vec_element(s, tcg_tmp, destidx, element, size);
1120
1121     tcg_temp_free_i64(tcg_tmp);
1122 }
1123
1124 /* Check that FP/Neon access is enabled. If it is, return
1125  * true. If not, emit code to generate an appropriate exception,
1126  * and return false; the caller should not emit any code for
1127  * the instruction. Note that this check must happen after all
1128  * unallocated-encoding checks (otherwise the syndrome information
1129  * for the resulting exception will be incorrect).
1130  */
1131 static inline bool fp_access_check(DisasContext *s)
1132 {
1133     assert(!s->fp_access_checked);
1134     s->fp_access_checked = true;
1135
1136     if (!s->fp_excp_el) {
1137         return true;
1138     }
1139
1140     gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
1141                        syn_fp_access_trap(1, 0xe, false), s->fp_excp_el);
1142     return false;
1143 }
1144
1145 /* Check that SVE access is enabled.  If it is, return true.
1146  * If not, emit code to generate an appropriate exception and return false.
1147  */
1148 bool sve_access_check(DisasContext *s)
1149 {
1150     if (s->sve_excp_el) {
1151         gen_exception_insn(s, s->pc_curr, EXCP_UDEF, syn_sve_access_trap(),
1152                            s->sve_excp_el);
1153         return false;
1154     }
1155     return fp_access_check(s);
1156 }
1157
1158 /*
1159  * This utility function is for doing register extension with an
1160  * optional shift. You will likely want to pass a temporary for the
1161  * destination register. See DecodeRegExtend() in the ARM ARM.
1162  */
1163 static void ext_and_shift_reg(TCGv_i64 tcg_out, TCGv_i64 tcg_in,
1164                               int option, unsigned int shift)
1165 {
1166     int extsize = extract32(option, 0, 2);
1167     bool is_signed = extract32(option, 2, 1);
1168
1169     if (is_signed) {
1170         switch (extsize) {
1171         case 0:
1172             tcg_gen_ext8s_i64(tcg_out, tcg_in);
1173             break;
1174         case 1:
1175             tcg_gen_ext16s_i64(tcg_out, tcg_in);
1176             break;
1177         case 2:
1178             tcg_gen_ext32s_i64(tcg_out, tcg_in);
1179             break;
1180         case 3:
1181             tcg_gen_mov_i64(tcg_out, tcg_in);
1182             break;
1183         }
1184     } else {
1185         switch (extsize) {
1186         case 0:
1187             tcg_gen_ext8u_i64(tcg_out, tcg_in);
1188             break;
1189         case 1:
1190             tcg_gen_ext16u_i64(tcg_out, tcg_in);
1191             break;
1192         case 2:
1193             tcg_gen_ext32u_i64(tcg_out, tcg_in);
1194             break;
1195         case 3:
1196             tcg_gen_mov_i64(tcg_out, tcg_in);
1197             break;
1198         }
1199     }
1200
1201     if (shift) {
1202         tcg_gen_shli_i64(tcg_out, tcg_out, shift);
1203     }
1204 }
1205
1206 static inline void gen_check_sp_alignment(DisasContext *s)
1207 {
1208     /* The AArch64 architecture mandates that (if enabled via PSTATE
1209      * or SCTLR bits) there is a check that SP is 16-aligned on every
1210      * SP-relative load or store (with an exception generated if it is not).
1211      * In line with general QEMU practice regarding misaligned accesses,
1212      * we omit these checks for the sake of guest program performance.
1213      * This function is provided as a hook so we can more easily add these
1214      * checks in future (possibly as a "favour catching guest program bugs
1215      * over speed" user selectable option).
1216      */
1217 }
1218
1219 /*
1220  * This provides a simple table based table lookup decoder. It is
1221  * intended to be used when the relevant bits for decode are too
1222  * awkwardly placed and switch/if based logic would be confusing and
1223  * deeply nested. Since it's a linear search through the table, tables
1224  * should be kept small.
1225  *
1226  * It returns the first handler where insn & mask == pattern, or
1227  * NULL if there is no match.
1228  * The table is terminated by an empty mask (i.e. 0)
1229  */
1230 static inline AArch64DecodeFn *lookup_disas_fn(const AArch64DecodeTable *table,
1231                                                uint32_t insn)
1232 {
1233     const AArch64DecodeTable *tptr = table;
1234
1235     while (tptr->mask) {
1236         if ((insn & tptr->mask) == tptr->pattern) {
1237             return tptr->disas_fn;
1238         }
1239         tptr++;
1240     }
1241     return NULL;
1242 }
1243
1244 /*
1245  * The instruction disassembly implemented here matches
1246  * the instruction encoding classifications in chapter C4
1247  * of the ARM Architecture Reference Manual (DDI0487B_a);
1248  * classification names and decode diagrams here should generally
1249  * match up with those in the manual.
1250  */
1251
1252 /* Unconditional branch (immediate)
1253  *   31  30       26 25                                  0
1254  * +----+-----------+-------------------------------------+
1255  * | op | 0 0 1 0 1 |                 imm26               |
1256  * +----+-----------+-------------------------------------+
1257  */
1258 static void disas_uncond_b_imm(DisasContext *s, uint32_t insn)
1259 {
1260     uint64_t addr = s->pc_curr + sextract32(insn, 0, 26) * 4;
1261
1262     if (insn & (1U << 31)) {
1263         /* BL Branch with link */
1264         tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
1265     }
1266
1267     /* B Branch / BL Branch with link */
1268     reset_btype(s);
1269     gen_goto_tb(s, 0, addr);
1270 }
1271
1272 /* Compare and branch (immediate)
1273  *   31  30         25  24  23                  5 4      0
1274  * +----+-------------+----+---------------------+--------+
1275  * | sf | 0 1 1 0 1 0 | op |         imm19       |   Rt   |
1276  * +----+-------------+----+---------------------+--------+
1277  */
1278 static void disas_comp_b_imm(DisasContext *s, uint32_t insn)
1279 {
1280     unsigned int sf, op, rt;
1281     uint64_t addr;
1282     TCGLabel *label_match;
1283     TCGv_i64 tcg_cmp;
1284
1285     sf = extract32(insn, 31, 1);
1286     op = extract32(insn, 24, 1); /* 0: CBZ; 1: CBNZ */
1287     rt = extract32(insn, 0, 5);
1288     addr = s->pc_curr + sextract32(insn, 5, 19) * 4;
1289
1290     tcg_cmp = read_cpu_reg(s, rt, sf);
1291     label_match = gen_new_label();
1292
1293     reset_btype(s);
1294     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1295                         tcg_cmp, 0, label_match);
1296
1297     gen_goto_tb(s, 0, s->base.pc_next);
1298     gen_set_label(label_match);
1299     gen_goto_tb(s, 1, addr);
1300 }
1301
1302 /* Test and branch (immediate)
1303  *   31  30         25  24  23   19 18          5 4    0
1304  * +----+-------------+----+-------+-------------+------+
1305  * | b5 | 0 1 1 0 1 1 | op |  b40  |    imm14    |  Rt  |
1306  * +----+-------------+----+-------+-------------+------+
1307  */
1308 static void disas_test_b_imm(DisasContext *s, uint32_t insn)
1309 {
1310     unsigned int bit_pos, op, rt;
1311     uint64_t addr;
1312     TCGLabel *label_match;
1313     TCGv_i64 tcg_cmp;
1314
1315     bit_pos = (extract32(insn, 31, 1) << 5) | extract32(insn, 19, 5);
1316     op = extract32(insn, 24, 1); /* 0: TBZ; 1: TBNZ */
1317     addr = s->pc_curr + sextract32(insn, 5, 14) * 4;
1318     rt = extract32(insn, 0, 5);
1319
1320     tcg_cmp = tcg_temp_new_i64();
1321     tcg_gen_andi_i64(tcg_cmp, cpu_reg(s, rt), (1ULL << bit_pos));
1322     label_match = gen_new_label();
1323
1324     reset_btype(s);
1325     tcg_gen_brcondi_i64(op ? TCG_COND_NE : TCG_COND_EQ,
1326                         tcg_cmp, 0, label_match);
1327     tcg_temp_free_i64(tcg_cmp);
1328     gen_goto_tb(s, 0, s->base.pc_next);
1329     gen_set_label(label_match);
1330     gen_goto_tb(s, 1, addr);
1331 }
1332
1333 /* Conditional branch (immediate)
1334  *  31           25  24  23                  5   4  3    0
1335  * +---------------+----+---------------------+----+------+
1336  * | 0 1 0 1 0 1 0 | o1 |         imm19       | o0 | cond |
1337  * +---------------+----+---------------------+----+------+
1338  */
1339 static void disas_cond_b_imm(DisasContext *s, uint32_t insn)
1340 {
1341     unsigned int cond;
1342     uint64_t addr;
1343
1344     if ((insn & (1 << 4)) || (insn & (1 << 24))) {
1345         unallocated_encoding(s);
1346         return;
1347     }
1348     addr = s->pc_curr + sextract32(insn, 5, 19) * 4;
1349     cond = extract32(insn, 0, 4);
1350
1351     reset_btype(s);
1352     if (cond < 0x0e) {
1353         /* genuinely conditional branches */
1354         TCGLabel *label_match = gen_new_label();
1355         arm_gen_test_cc(cond, label_match);
1356         gen_goto_tb(s, 0, s->base.pc_next);
1357         gen_set_label(label_match);
1358         gen_goto_tb(s, 1, addr);
1359     } else {
1360         /* 0xe and 0xf are both "always" conditions */
1361         gen_goto_tb(s, 0, addr);
1362     }
1363 }
1364
1365 /* HINT instruction group, including various allocated HINTs */
1366 static void handle_hint(DisasContext *s, uint32_t insn,
1367                         unsigned int op1, unsigned int op2, unsigned int crm)
1368 {
1369     unsigned int selector = crm << 3 | op2;
1370
1371     if (op1 != 3) {
1372         unallocated_encoding(s);
1373         return;
1374     }
1375
1376     switch (selector) {
1377     case 0b00000: /* NOP */
1378         break;
1379     case 0b00011: /* WFI */
1380         s->base.is_jmp = DISAS_WFI;
1381         break;
1382     case 0b00001: /* YIELD */
1383         /* When running in MTTCG we don't generate jumps to the yield and
1384          * WFE helpers as it won't affect the scheduling of other vCPUs.
1385          * If we wanted to more completely model WFE/SEV so we don't busy
1386          * spin unnecessarily we would need to do something more involved.
1387          */
1388         if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
1389             s->base.is_jmp = DISAS_YIELD;
1390         }
1391         break;
1392     case 0b00010: /* WFE */
1393         if (!(tb_cflags(s->base.tb) & CF_PARALLEL)) {
1394             s->base.is_jmp = DISAS_WFE;
1395         }
1396         break;
1397     case 0b00100: /* SEV */
1398     case 0b00101: /* SEVL */
1399         /* we treat all as NOP at least for now */
1400         break;
1401     case 0b00111: /* XPACLRI */
1402         if (s->pauth_active) {
1403             gen_helper_xpaci(cpu_X[30], cpu_env, cpu_X[30]);
1404         }
1405         break;
1406     case 0b01000: /* PACIA1716 */
1407         if (s->pauth_active) {
1408             gen_helper_pacia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
1409         }
1410         break;
1411     case 0b01010: /* PACIB1716 */
1412         if (s->pauth_active) {
1413             gen_helper_pacib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
1414         }
1415         break;
1416     case 0b01100: /* AUTIA1716 */
1417         if (s->pauth_active) {
1418             gen_helper_autia(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
1419         }
1420         break;
1421     case 0b01110: /* AUTIB1716 */
1422         if (s->pauth_active) {
1423             gen_helper_autib(cpu_X[17], cpu_env, cpu_X[17], cpu_X[16]);
1424         }
1425         break;
1426     case 0b11000: /* PACIAZ */
1427         if (s->pauth_active) {
1428             gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30],
1429                                 new_tmp_a64_zero(s));
1430         }
1431         break;
1432     case 0b11001: /* PACIASP */
1433         if (s->pauth_active) {
1434             gen_helper_pacia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
1435         }
1436         break;
1437     case 0b11010: /* PACIBZ */
1438         if (s->pauth_active) {
1439             gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30],
1440                                 new_tmp_a64_zero(s));
1441         }
1442         break;
1443     case 0b11011: /* PACIBSP */
1444         if (s->pauth_active) {
1445             gen_helper_pacib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
1446         }
1447         break;
1448     case 0b11100: /* AUTIAZ */
1449         if (s->pauth_active) {
1450             gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30],
1451                               new_tmp_a64_zero(s));
1452         }
1453         break;
1454     case 0b11101: /* AUTIASP */
1455         if (s->pauth_active) {
1456             gen_helper_autia(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
1457         }
1458         break;
1459     case 0b11110: /* AUTIBZ */
1460         if (s->pauth_active) {
1461             gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30],
1462                               new_tmp_a64_zero(s));
1463         }
1464         break;
1465     case 0b11111: /* AUTIBSP */
1466         if (s->pauth_active) {
1467             gen_helper_autib(cpu_X[30], cpu_env, cpu_X[30], cpu_X[31]);
1468         }
1469         break;
1470     default:
1471         /* default specified as NOP equivalent */
1472         break;
1473     }
1474 }
1475
1476 static void gen_clrex(DisasContext *s, uint32_t insn)
1477 {
1478     tcg_gen_movi_i64(cpu_exclusive_addr, -1);
1479 }
1480
1481 /* CLREX, DSB, DMB, ISB */
1482 static void handle_sync(DisasContext *s, uint32_t insn,
1483                         unsigned int op1, unsigned int op2, unsigned int crm)
1484 {
1485     TCGBar bar;
1486
1487     if (op1 != 3) {
1488         unallocated_encoding(s);
1489         return;
1490     }
1491
1492     switch (op2) {
1493     case 2: /* CLREX */
1494         gen_clrex(s, insn);
1495         return;
1496     case 4: /* DSB */
1497     case 5: /* DMB */
1498         switch (crm & 3) {
1499         case 1: /* MBReqTypes_Reads */
1500             bar = TCG_BAR_SC | TCG_MO_LD_LD | TCG_MO_LD_ST;
1501             break;
1502         case 2: /* MBReqTypes_Writes */
1503             bar = TCG_BAR_SC | TCG_MO_ST_ST;
1504             break;
1505         default: /* MBReqTypes_All */
1506             bar = TCG_BAR_SC | TCG_MO_ALL;
1507             break;
1508         }
1509         tcg_gen_mb(bar);
1510         return;
1511     case 6: /* ISB */
1512         /* We need to break the TB after this insn to execute
1513          * a self-modified code correctly and also to take
1514          * any pending interrupts immediately.
1515          */
1516         reset_btype(s);
1517         gen_goto_tb(s, 0, s->base.pc_next);
1518         return;
1519
1520     case 7: /* SB */
1521         if (crm != 0 || !dc_isar_feature(aa64_sb, s)) {
1522             goto do_unallocated;
1523         }
1524         /*
1525          * TODO: There is no speculation barrier opcode for TCG;
1526          * MB and end the TB instead.
1527          */
1528         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_SC);
1529         gen_goto_tb(s, 0, s->base.pc_next);
1530         return;
1531
1532     default:
1533     do_unallocated:
1534         unallocated_encoding(s);
1535         return;
1536     }
1537 }
1538
1539 static void gen_xaflag(void)
1540 {
1541     TCGv_i32 z = tcg_temp_new_i32();
1542
1543     tcg_gen_setcondi_i32(TCG_COND_EQ, z, cpu_ZF, 0);
1544
1545     /*
1546      * (!C & !Z) << 31
1547      * (!(C | Z)) << 31
1548      * ~((C | Z) << 31)
1549      * ~-(C | Z)
1550      * (C | Z) - 1
1551      */
1552     tcg_gen_or_i32(cpu_NF, cpu_CF, z);
1553     tcg_gen_subi_i32(cpu_NF, cpu_NF, 1);
1554
1555     /* !(Z & C) */
1556     tcg_gen_and_i32(cpu_ZF, z, cpu_CF);
1557     tcg_gen_xori_i32(cpu_ZF, cpu_ZF, 1);
1558
1559     /* (!C & Z) << 31 -> -(Z & ~C) */
1560     tcg_gen_andc_i32(cpu_VF, z, cpu_CF);
1561     tcg_gen_neg_i32(cpu_VF, cpu_VF);
1562
1563     /* C | Z */
1564     tcg_gen_or_i32(cpu_CF, cpu_CF, z);
1565
1566     tcg_temp_free_i32(z);
1567 }
1568
1569 static void gen_axflag(void)
1570 {
1571     tcg_gen_sari_i32(cpu_VF, cpu_VF, 31);         /* V ? -1 : 0 */
1572     tcg_gen_andc_i32(cpu_CF, cpu_CF, cpu_VF);     /* C & !V */
1573
1574     /* !(Z | V) -> !(!ZF | V) -> ZF & !V -> ZF & ~VF */
1575     tcg_gen_andc_i32(cpu_ZF, cpu_ZF, cpu_VF);
1576
1577     tcg_gen_movi_i32(cpu_NF, 0);
1578     tcg_gen_movi_i32(cpu_VF, 0);
1579 }
1580
1581 /* MSR (immediate) - move immediate to processor state field */
1582 static void handle_msr_i(DisasContext *s, uint32_t insn,
1583                          unsigned int op1, unsigned int op2, unsigned int crm)
1584 {
1585     TCGv_i32 t1;
1586     int op = op1 << 3 | op2;
1587
1588     /* End the TB by default, chaining is ok.  */
1589     s->base.is_jmp = DISAS_TOO_MANY;
1590
1591     switch (op) {
1592     case 0x00: /* CFINV */
1593         if (crm != 0 || !dc_isar_feature(aa64_condm_4, s)) {
1594             goto do_unallocated;
1595         }
1596         tcg_gen_xori_i32(cpu_CF, cpu_CF, 1);
1597         s->base.is_jmp = DISAS_NEXT;
1598         break;
1599
1600     case 0x01: /* XAFlag */
1601         if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
1602             goto do_unallocated;
1603         }
1604         gen_xaflag();
1605         s->base.is_jmp = DISAS_NEXT;
1606         break;
1607
1608     case 0x02: /* AXFlag */
1609         if (crm != 0 || !dc_isar_feature(aa64_condm_5, s)) {
1610             goto do_unallocated;
1611         }
1612         gen_axflag();
1613         s->base.is_jmp = DISAS_NEXT;
1614         break;
1615
1616     case 0x03: /* UAO */
1617         if (!dc_isar_feature(aa64_uao, s) || s->current_el == 0) {
1618             goto do_unallocated;
1619         }
1620         if (crm & 1) {
1621             set_pstate_bits(PSTATE_UAO);
1622         } else {
1623             clear_pstate_bits(PSTATE_UAO);
1624         }
1625         t1 = tcg_const_i32(s->current_el);
1626         gen_helper_rebuild_hflags_a64(cpu_env, t1);
1627         tcg_temp_free_i32(t1);
1628         break;
1629
1630     case 0x04: /* PAN */
1631         if (!dc_isar_feature(aa64_pan, s) || s->current_el == 0) {
1632             goto do_unallocated;
1633         }
1634         if (crm & 1) {
1635             set_pstate_bits(PSTATE_PAN);
1636         } else {
1637             clear_pstate_bits(PSTATE_PAN);
1638         }
1639         t1 = tcg_const_i32(s->current_el);
1640         gen_helper_rebuild_hflags_a64(cpu_env, t1);
1641         tcg_temp_free_i32(t1);
1642         break;
1643
1644     case 0x05: /* SPSel */
1645         if (s->current_el == 0) {
1646             goto do_unallocated;
1647         }
1648         t1 = tcg_const_i32(crm & PSTATE_SP);
1649         gen_helper_msr_i_spsel(cpu_env, t1);
1650         tcg_temp_free_i32(t1);
1651         break;
1652
1653     case 0x1e: /* DAIFSet */
1654         t1 = tcg_const_i32(crm);
1655         gen_helper_msr_i_daifset(cpu_env, t1);
1656         tcg_temp_free_i32(t1);
1657         break;
1658
1659     case 0x1f: /* DAIFClear */
1660         t1 = tcg_const_i32(crm);
1661         gen_helper_msr_i_daifclear(cpu_env, t1);
1662         tcg_temp_free_i32(t1);
1663         /* For DAIFClear, exit the cpu loop to re-evaluate pending IRQs.  */
1664         s->base.is_jmp = DISAS_UPDATE;
1665         break;
1666
1667     default:
1668     do_unallocated:
1669         unallocated_encoding(s);
1670         return;
1671     }
1672 }
1673
1674 static void gen_get_nzcv(TCGv_i64 tcg_rt)
1675 {
1676     TCGv_i32 tmp = tcg_temp_new_i32();
1677     TCGv_i32 nzcv = tcg_temp_new_i32();
1678
1679     /* build bit 31, N */
1680     tcg_gen_andi_i32(nzcv, cpu_NF, (1U << 31));
1681     /* build bit 30, Z */
1682     tcg_gen_setcondi_i32(TCG_COND_EQ, tmp, cpu_ZF, 0);
1683     tcg_gen_deposit_i32(nzcv, nzcv, tmp, 30, 1);
1684     /* build bit 29, C */
1685     tcg_gen_deposit_i32(nzcv, nzcv, cpu_CF, 29, 1);
1686     /* build bit 28, V */
1687     tcg_gen_shri_i32(tmp, cpu_VF, 31);
1688     tcg_gen_deposit_i32(nzcv, nzcv, tmp, 28, 1);
1689     /* generate result */
1690     tcg_gen_extu_i32_i64(tcg_rt, nzcv);
1691
1692     tcg_temp_free_i32(nzcv);
1693     tcg_temp_free_i32(tmp);
1694 }
1695
1696 static void gen_set_nzcv(TCGv_i64 tcg_rt)
1697 {
1698     TCGv_i32 nzcv = tcg_temp_new_i32();
1699
1700     /* take NZCV from R[t] */
1701     tcg_gen_extrl_i64_i32(nzcv, tcg_rt);
1702
1703     /* bit 31, N */
1704     tcg_gen_andi_i32(cpu_NF, nzcv, (1U << 31));
1705     /* bit 30, Z */
1706     tcg_gen_andi_i32(cpu_ZF, nzcv, (1 << 30));
1707     tcg_gen_setcondi_i32(TCG_COND_EQ, cpu_ZF, cpu_ZF, 0);
1708     /* bit 29, C */
1709     tcg_gen_andi_i32(cpu_CF, nzcv, (1 << 29));
1710     tcg_gen_shri_i32(cpu_CF, cpu_CF, 29);
1711     /* bit 28, V */
1712     tcg_gen_andi_i32(cpu_VF, nzcv, (1 << 28));
1713     tcg_gen_shli_i32(cpu_VF, cpu_VF, 3);
1714     tcg_temp_free_i32(nzcv);
1715 }
1716
1717 /* MRS - move from system register
1718  * MSR (register) - move to system register
1719  * SYS
1720  * SYSL
1721  * These are all essentially the same insn in 'read' and 'write'
1722  * versions, with varying op0 fields.
1723  */
1724 static void handle_sys(DisasContext *s, uint32_t insn, bool isread,
1725                        unsigned int op0, unsigned int op1, unsigned int op2,
1726                        unsigned int crn, unsigned int crm, unsigned int rt)
1727 {
1728     const ARMCPRegInfo *ri;
1729     TCGv_i64 tcg_rt;
1730
1731     ri = get_arm_cp_reginfo(s->cp_regs,
1732                             ENCODE_AA64_CP_REG(CP_REG_ARM64_SYSREG_CP,
1733                                                crn, crm, op0, op1, op2));
1734
1735     if (!ri) {
1736         /* Unknown register; this might be a guest error or a QEMU
1737          * unimplemented feature.
1738          */
1739         qemu_log_mask(LOG_UNIMP, "%s access to unsupported AArch64 "
1740                       "system register op0:%d op1:%d crn:%d crm:%d op2:%d\n",
1741                       isread ? "read" : "write", op0, op1, crn, crm, op2);
1742         unallocated_encoding(s);
1743         return;
1744     }
1745
1746     /* Check access permissions */
1747     if (!cp_access_ok(s->current_el, ri, isread)) {
1748         unallocated_encoding(s);
1749         return;
1750     }
1751
1752     if (ri->accessfn) {
1753         /* Emit code to perform further access permissions checks at
1754          * runtime; this may result in an exception.
1755          */
1756         TCGv_ptr tmpptr;
1757         TCGv_i32 tcg_syn, tcg_isread;
1758         uint32_t syndrome;
1759
1760         gen_a64_set_pc_im(s->pc_curr);
1761         tmpptr = tcg_const_ptr(ri);
1762         syndrome = syn_aa64_sysregtrap(op0, op1, op2, crn, crm, rt, isread);
1763         tcg_syn = tcg_const_i32(syndrome);
1764         tcg_isread = tcg_const_i32(isread);
1765         gen_helper_access_check_cp_reg(cpu_env, tmpptr, tcg_syn, tcg_isread);
1766         tcg_temp_free_ptr(tmpptr);
1767         tcg_temp_free_i32(tcg_syn);
1768         tcg_temp_free_i32(tcg_isread);
1769     } else if (ri->type & ARM_CP_RAISES_EXC) {
1770         /*
1771          * The readfn or writefn might raise an exception;
1772          * synchronize the CPU state in case it does.
1773          */
1774         gen_a64_set_pc_im(s->pc_curr);
1775     }
1776
1777     /* Handle special cases first */
1778     switch (ri->type & ~(ARM_CP_FLAG_MASK & ~ARM_CP_SPECIAL)) {
1779     case ARM_CP_NOP:
1780         return;
1781     case ARM_CP_NZCV:
1782         tcg_rt = cpu_reg(s, rt);
1783         if (isread) {
1784             gen_get_nzcv(tcg_rt);
1785         } else {
1786             gen_set_nzcv(tcg_rt);
1787         }
1788         return;
1789     case ARM_CP_CURRENTEL:
1790         /* Reads as current EL value from pstate, which is
1791          * guaranteed to be constant by the tb flags.
1792          */
1793         tcg_rt = cpu_reg(s, rt);
1794         tcg_gen_movi_i64(tcg_rt, s->current_el << 2);
1795         return;
1796     case ARM_CP_DC_ZVA:
1797         /* Writes clear the aligned block of memory which rt points into. */
1798         tcg_rt = clean_data_tbi(s, cpu_reg(s, rt));
1799         gen_helper_dc_zva(cpu_env, tcg_rt);
1800         return;
1801     default:
1802         break;
1803     }
1804     if ((ri->type & ARM_CP_FPU) && !fp_access_check(s)) {
1805         return;
1806     } else if ((ri->type & ARM_CP_SVE) && !sve_access_check(s)) {
1807         return;
1808     }
1809
1810     if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
1811         gen_io_start();
1812     }
1813
1814     tcg_rt = cpu_reg(s, rt);
1815
1816     if (isread) {
1817         if (ri->type & ARM_CP_CONST) {
1818             tcg_gen_movi_i64(tcg_rt, ri->resetvalue);
1819         } else if (ri->readfn) {
1820             TCGv_ptr tmpptr;
1821             tmpptr = tcg_const_ptr(ri);
1822             gen_helper_get_cp_reg64(tcg_rt, cpu_env, tmpptr);
1823             tcg_temp_free_ptr(tmpptr);
1824         } else {
1825             tcg_gen_ld_i64(tcg_rt, cpu_env, ri->fieldoffset);
1826         }
1827     } else {
1828         if (ri->type & ARM_CP_CONST) {
1829             /* If not forbidden by access permissions, treat as WI */
1830             return;
1831         } else if (ri->writefn) {
1832             TCGv_ptr tmpptr;
1833             tmpptr = tcg_const_ptr(ri);
1834             gen_helper_set_cp_reg64(cpu_env, tmpptr, tcg_rt);
1835             tcg_temp_free_ptr(tmpptr);
1836         } else {
1837             tcg_gen_st_i64(tcg_rt, cpu_env, ri->fieldoffset);
1838         }
1839     }
1840
1841     if ((tb_cflags(s->base.tb) & CF_USE_ICOUNT) && (ri->type & ARM_CP_IO)) {
1842         /* I/O operations must end the TB here (whether read or write) */
1843         s->base.is_jmp = DISAS_UPDATE;
1844     }
1845     if (!isread && !(ri->type & ARM_CP_SUPPRESS_TB_END)) {
1846         /*
1847          * A write to any coprocessor regiser that ends a TB
1848          * must rebuild the hflags for the next TB.
1849          */
1850         TCGv_i32 tcg_el = tcg_const_i32(s->current_el);
1851         gen_helper_rebuild_hflags_a64(cpu_env, tcg_el);
1852         tcg_temp_free_i32(tcg_el);
1853         /*
1854          * We default to ending the TB on a coprocessor register write,
1855          * but allow this to be suppressed by the register definition
1856          * (usually only necessary to work around guest bugs).
1857          */
1858         s->base.is_jmp = DISAS_UPDATE;
1859     }
1860 }
1861
1862 /* System
1863  *  31                 22 21  20 19 18 16 15   12 11    8 7   5 4    0
1864  * +---------------------+---+-----+-----+-------+-------+-----+------+
1865  * | 1 1 0 1 0 1 0 1 0 0 | L | op0 | op1 |  CRn  |  CRm  | op2 |  Rt  |
1866  * +---------------------+---+-----+-----+-------+-------+-----+------+
1867  */
1868 static void disas_system(DisasContext *s, uint32_t insn)
1869 {
1870     unsigned int l, op0, op1, crn, crm, op2, rt;
1871     l = extract32(insn, 21, 1);
1872     op0 = extract32(insn, 19, 2);
1873     op1 = extract32(insn, 16, 3);
1874     crn = extract32(insn, 12, 4);
1875     crm = extract32(insn, 8, 4);
1876     op2 = extract32(insn, 5, 3);
1877     rt = extract32(insn, 0, 5);
1878
1879     if (op0 == 0) {
1880         if (l || rt != 31) {
1881             unallocated_encoding(s);
1882             return;
1883         }
1884         switch (crn) {
1885         case 2: /* HINT (including allocated hints like NOP, YIELD, etc) */
1886             handle_hint(s, insn, op1, op2, crm);
1887             break;
1888         case 3: /* CLREX, DSB, DMB, ISB */
1889             handle_sync(s, insn, op1, op2, crm);
1890             break;
1891         case 4: /* MSR (immediate) */
1892             handle_msr_i(s, insn, op1, op2, crm);
1893             break;
1894         default:
1895             unallocated_encoding(s);
1896             break;
1897         }
1898         return;
1899     }
1900     handle_sys(s, insn, l, op0, op1, op2, crn, crm, rt);
1901 }
1902
1903 /* Exception generation
1904  *
1905  *  31             24 23 21 20                     5 4   2 1  0
1906  * +-----------------+-----+------------------------+-----+----+
1907  * | 1 1 0 1 0 1 0 0 | opc |          imm16         | op2 | LL |
1908  * +-----------------------+------------------------+----------+
1909  */
1910 static void disas_exc(DisasContext *s, uint32_t insn)
1911 {
1912     int opc = extract32(insn, 21, 3);
1913     int op2_ll = extract32(insn, 0, 5);
1914     int imm16 = extract32(insn, 5, 16);
1915     TCGv_i32 tmp;
1916
1917     switch (opc) {
1918     case 0:
1919         /* For SVC, HVC and SMC we advance the single-step state
1920          * machine before taking the exception. This is architecturally
1921          * mandated, to ensure that single-stepping a system call
1922          * instruction works properly.
1923          */
1924         switch (op2_ll) {
1925         case 1:                                                     /* SVC */
1926             gen_ss_advance(s);
1927             gen_exception_insn(s, s->base.pc_next, EXCP_SWI,
1928                                syn_aa64_svc(imm16), default_exception_el(s));
1929             break;
1930         case 2:                                                     /* HVC */
1931             if (s->current_el == 0) {
1932                 unallocated_encoding(s);
1933                 break;
1934             }
1935             /* The pre HVC helper handles cases when HVC gets trapped
1936              * as an undefined insn by runtime configuration.
1937              */
1938             gen_a64_set_pc_im(s->pc_curr);
1939             gen_helper_pre_hvc(cpu_env);
1940             gen_ss_advance(s);
1941             gen_exception_insn(s, s->base.pc_next, EXCP_HVC,
1942                                syn_aa64_hvc(imm16), 2);
1943             break;
1944         case 3:                                                     /* SMC */
1945             if (s->current_el == 0) {
1946                 unallocated_encoding(s);
1947                 break;
1948             }
1949             gen_a64_set_pc_im(s->pc_curr);
1950             tmp = tcg_const_i32(syn_aa64_smc(imm16));
1951             gen_helper_pre_smc(cpu_env, tmp);
1952             tcg_temp_free_i32(tmp);
1953             gen_ss_advance(s);
1954             gen_exception_insn(s, s->base.pc_next, EXCP_SMC,
1955                                syn_aa64_smc(imm16), 3);
1956             break;
1957         default:
1958             unallocated_encoding(s);
1959             break;
1960         }
1961         break;
1962     case 1:
1963         if (op2_ll != 0) {
1964             unallocated_encoding(s);
1965             break;
1966         }
1967         /* BRK */
1968         gen_exception_bkpt_insn(s, syn_aa64_bkpt(imm16));
1969         break;
1970     case 2:
1971         if (op2_ll != 0) {
1972             unallocated_encoding(s);
1973             break;
1974         }
1975         /* HLT. This has two purposes.
1976          * Architecturally, it is an external halting debug instruction.
1977          * Since QEMU doesn't implement external debug, we treat this as
1978          * it is required for halting debug disabled: it will UNDEF.
1979          * Secondly, "HLT 0xf000" is the A64 semihosting syscall instruction.
1980          */
1981         if (semihosting_enabled() && imm16 == 0xf000) {
1982 #ifndef CONFIG_USER_ONLY
1983             /* In system mode, don't allow userspace access to semihosting,
1984              * to provide some semblance of security (and for consistency
1985              * with our 32-bit semihosting).
1986              */
1987             if (s->current_el == 0) {
1988                 unsupported_encoding(s, insn);
1989                 break;
1990             }
1991 #endif
1992             gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
1993         } else {
1994             unsupported_encoding(s, insn);
1995         }
1996         break;
1997     case 5:
1998         if (op2_ll < 1 || op2_ll > 3) {
1999             unallocated_encoding(s);
2000             break;
2001         }
2002         /* DCPS1, DCPS2, DCPS3 */
2003         unsupported_encoding(s, insn);
2004         break;
2005     default:
2006         unallocated_encoding(s);
2007         break;
2008     }
2009 }
2010
2011 /* Unconditional branch (register)
2012  *  31           25 24   21 20   16 15   10 9    5 4     0
2013  * +---------------+-------+-------+-------+------+-------+
2014  * | 1 1 0 1 0 1 1 |  opc  |  op2  |  op3  |  Rn  |  op4  |
2015  * +---------------+-------+-------+-------+------+-------+
2016  */
2017 static void disas_uncond_b_reg(DisasContext *s, uint32_t insn)
2018 {
2019     unsigned int opc, op2, op3, rn, op4;
2020     unsigned btype_mod = 2;   /* 0: BR, 1: BLR, 2: other */
2021     TCGv_i64 dst;
2022     TCGv_i64 modifier;
2023
2024     opc = extract32(insn, 21, 4);
2025     op2 = extract32(insn, 16, 5);
2026     op3 = extract32(insn, 10, 6);
2027     rn = extract32(insn, 5, 5);
2028     op4 = extract32(insn, 0, 5);
2029
2030     if (op2 != 0x1f) {
2031         goto do_unallocated;
2032     }
2033
2034     switch (opc) {
2035     case 0: /* BR */
2036     case 1: /* BLR */
2037     case 2: /* RET */
2038         btype_mod = opc;
2039         switch (op3) {
2040         case 0:
2041             /* BR, BLR, RET */
2042             if (op4 != 0) {
2043                 goto do_unallocated;
2044             }
2045             dst = cpu_reg(s, rn);
2046             break;
2047
2048         case 2:
2049         case 3:
2050             if (!dc_isar_feature(aa64_pauth, s)) {
2051                 goto do_unallocated;
2052             }
2053             if (opc == 2) {
2054                 /* RETAA, RETAB */
2055                 if (rn != 0x1f || op4 != 0x1f) {
2056                     goto do_unallocated;
2057                 }
2058                 rn = 30;
2059                 modifier = cpu_X[31];
2060             } else {
2061                 /* BRAAZ, BRABZ, BLRAAZ, BLRABZ */
2062                 if (op4 != 0x1f) {
2063                     goto do_unallocated;
2064                 }
2065                 modifier = new_tmp_a64_zero(s);
2066             }
2067             if (s->pauth_active) {
2068                 dst = new_tmp_a64(s);
2069                 if (op3 == 2) {
2070                     gen_helper_autia(dst, cpu_env, cpu_reg(s, rn), modifier);
2071                 } else {
2072                     gen_helper_autib(dst, cpu_env, cpu_reg(s, rn), modifier);
2073                 }
2074             } else {
2075                 dst = cpu_reg(s, rn);
2076             }
2077             break;
2078
2079         default:
2080             goto do_unallocated;
2081         }
2082         gen_a64_set_pc(s, dst);
2083         /* BLR also needs to load return address */
2084         if (opc == 1) {
2085             tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
2086         }
2087         break;
2088
2089     case 8: /* BRAA */
2090     case 9: /* BLRAA */
2091         if (!dc_isar_feature(aa64_pauth, s)) {
2092             goto do_unallocated;
2093         }
2094         if ((op3 & ~1) != 2) {
2095             goto do_unallocated;
2096         }
2097         btype_mod = opc & 1;
2098         if (s->pauth_active) {
2099             dst = new_tmp_a64(s);
2100             modifier = cpu_reg_sp(s, op4);
2101             if (op3 == 2) {
2102                 gen_helper_autia(dst, cpu_env, cpu_reg(s, rn), modifier);
2103             } else {
2104                 gen_helper_autib(dst, cpu_env, cpu_reg(s, rn), modifier);
2105             }
2106         } else {
2107             dst = cpu_reg(s, rn);
2108         }
2109         gen_a64_set_pc(s, dst);
2110         /* BLRAA also needs to load return address */
2111         if (opc == 9) {
2112             tcg_gen_movi_i64(cpu_reg(s, 30), s->base.pc_next);
2113         }
2114         break;
2115
2116     case 4: /* ERET */
2117         if (s->current_el == 0) {
2118             goto do_unallocated;
2119         }
2120         switch (op3) {
2121         case 0: /* ERET */
2122             if (op4 != 0) {
2123                 goto do_unallocated;
2124             }
2125             dst = tcg_temp_new_i64();
2126             tcg_gen_ld_i64(dst, cpu_env,
2127                            offsetof(CPUARMState, elr_el[s->current_el]));
2128             break;
2129
2130         case 2: /* ERETAA */
2131         case 3: /* ERETAB */
2132             if (!dc_isar_feature(aa64_pauth, s)) {
2133                 goto do_unallocated;
2134             }
2135             if (rn != 0x1f || op4 != 0x1f) {
2136                 goto do_unallocated;
2137             }
2138             dst = tcg_temp_new_i64();
2139             tcg_gen_ld_i64(dst, cpu_env,
2140                            offsetof(CPUARMState, elr_el[s->current_el]));
2141             if (s->pauth_active) {
2142                 modifier = cpu_X[31];
2143                 if (op3 == 2) {
2144                     gen_helper_autia(dst, cpu_env, dst, modifier);
2145                 } else {
2146                     gen_helper_autib(dst, cpu_env, dst, modifier);
2147                 }
2148             }
2149             break;
2150
2151         default:
2152             goto do_unallocated;
2153         }
2154         if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
2155             gen_io_start();
2156         }
2157
2158         gen_helper_exception_return(cpu_env, dst);
2159         tcg_temp_free_i64(dst);
2160         /* Must exit loop to check un-masked IRQs */
2161         s->base.is_jmp = DISAS_EXIT;
2162         return;
2163
2164     case 5: /* DRPS */
2165         if (op3 != 0 || op4 != 0 || rn != 0x1f) {
2166             goto do_unallocated;
2167         } else {
2168             unsupported_encoding(s, insn);
2169         }
2170         return;
2171
2172     default:
2173     do_unallocated:
2174         unallocated_encoding(s);
2175         return;
2176     }
2177
2178     switch (btype_mod) {
2179     case 0: /* BR */
2180         if (dc_isar_feature(aa64_bti, s)) {
2181             /* BR to {x16,x17} or !guard -> 1, else 3.  */
2182             set_btype(s, rn == 16 || rn == 17 || !s->guarded_page ? 1 : 3);
2183         }
2184         break;
2185
2186     case 1: /* BLR */
2187         if (dc_isar_feature(aa64_bti, s)) {
2188             /* BLR sets BTYPE to 2, regardless of source guarded page.  */
2189             set_btype(s, 2);
2190         }
2191         break;
2192
2193     default: /* RET or none of the above.  */
2194         /* BTYPE will be set to 0 by normal end-of-insn processing.  */
2195         break;
2196     }
2197
2198     s->base.is_jmp = DISAS_JUMP;
2199 }
2200
2201 /* Branches, exception generating and system instructions */
2202 static void disas_b_exc_sys(DisasContext *s, uint32_t insn)
2203 {
2204     switch (extract32(insn, 25, 7)) {
2205     case 0x0a: case 0x0b:
2206     case 0x4a: case 0x4b: /* Unconditional branch (immediate) */
2207         disas_uncond_b_imm(s, insn);
2208         break;
2209     case 0x1a: case 0x5a: /* Compare & branch (immediate) */
2210         disas_comp_b_imm(s, insn);
2211         break;
2212     case 0x1b: case 0x5b: /* Test & branch (immediate) */
2213         disas_test_b_imm(s, insn);
2214         break;
2215     case 0x2a: /* Conditional branch (immediate) */
2216         disas_cond_b_imm(s, insn);
2217         break;
2218     case 0x6a: /* Exception generation / System */
2219         if (insn & (1 << 24)) {
2220             if (extract32(insn, 22, 2) == 0) {
2221                 disas_system(s, insn);
2222             } else {
2223                 unallocated_encoding(s);
2224             }
2225         } else {
2226             disas_exc(s, insn);
2227         }
2228         break;
2229     case 0x6b: /* Unconditional branch (register) */
2230         disas_uncond_b_reg(s, insn);
2231         break;
2232     default:
2233         unallocated_encoding(s);
2234         break;
2235     }
2236 }
2237
2238 /*
2239  * Load/Store exclusive instructions are implemented by remembering
2240  * the value/address loaded, and seeing if these are the same
2241  * when the store is performed. This is not actually the architecturally
2242  * mandated semantics, but it works for typical guest code sequences
2243  * and avoids having to monitor regular stores.
2244  *
2245  * The store exclusive uses the atomic cmpxchg primitives to avoid
2246  * races in multi-threaded linux-user and when MTTCG softmmu is
2247  * enabled.
2248  */
2249 static void gen_load_exclusive(DisasContext *s, int rt, int rt2,
2250                                TCGv_i64 addr, int size, bool is_pair)
2251 {
2252     int idx = get_mem_index(s);
2253     MemOp memop = s->be_data;
2254
2255     g_assert(size <= 3);
2256     if (is_pair) {
2257         g_assert(size >= 2);
2258         if (size == 2) {
2259             /* The pair must be single-copy atomic for the doubleword.  */
2260             memop |= MO_64 | MO_ALIGN;
2261             tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
2262             if (s->be_data == MO_LE) {
2263                 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 0, 32);
2264                 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 32, 32);
2265             } else {
2266                 tcg_gen_extract_i64(cpu_reg(s, rt), cpu_exclusive_val, 32, 32);
2267                 tcg_gen_extract_i64(cpu_reg(s, rt2), cpu_exclusive_val, 0, 32);
2268             }
2269         } else {
2270             /* The pair must be single-copy atomic for *each* doubleword, not
2271                the entire quadword, however it must be quadword aligned.  */
2272             memop |= MO_64;
2273             tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx,
2274                                 memop | MO_ALIGN_16);
2275
2276             TCGv_i64 addr2 = tcg_temp_new_i64();
2277             tcg_gen_addi_i64(addr2, addr, 8);
2278             tcg_gen_qemu_ld_i64(cpu_exclusive_high, addr2, idx, memop);
2279             tcg_temp_free_i64(addr2);
2280
2281             tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
2282             tcg_gen_mov_i64(cpu_reg(s, rt2), cpu_exclusive_high);
2283         }
2284     } else {
2285         memop |= size | MO_ALIGN;
2286         tcg_gen_qemu_ld_i64(cpu_exclusive_val, addr, idx, memop);
2287         tcg_gen_mov_i64(cpu_reg(s, rt), cpu_exclusive_val);
2288     }
2289     tcg_gen_mov_i64(cpu_exclusive_addr, addr);
2290 }
2291
2292 static void gen_store_exclusive(DisasContext *s, int rd, int rt, int rt2,
2293                                 TCGv_i64 addr, int size, int is_pair)
2294 {
2295     /* if (env->exclusive_addr == addr && env->exclusive_val == [addr]
2296      *     && (!is_pair || env->exclusive_high == [addr + datasize])) {
2297      *     [addr] = {Rt};
2298      *     if (is_pair) {
2299      *         [addr + datasize] = {Rt2};
2300      *     }
2301      *     {Rd} = 0;
2302      * } else {
2303      *     {Rd} = 1;
2304      * }
2305      * env->exclusive_addr = -1;
2306      */
2307     TCGLabel *fail_label = gen_new_label();
2308     TCGLabel *done_label = gen_new_label();
2309     TCGv_i64 tmp;
2310
2311     tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_exclusive_addr, fail_label);
2312
2313     tmp = tcg_temp_new_i64();
2314     if (is_pair) {
2315         if (size == 2) {
2316             if (s->be_data == MO_LE) {
2317                 tcg_gen_concat32_i64(tmp, cpu_reg(s, rt), cpu_reg(s, rt2));
2318             } else {
2319                 tcg_gen_concat32_i64(tmp, cpu_reg(s, rt2), cpu_reg(s, rt));
2320             }
2321             tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr,
2322                                        cpu_exclusive_val, tmp,
2323                                        get_mem_index(s),
2324                                        MO_64 | MO_ALIGN | s->be_data);
2325             tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
2326         } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2327             if (!HAVE_CMPXCHG128) {
2328                 gen_helper_exit_atomic(cpu_env);
2329                 s->base.is_jmp = DISAS_NORETURN;
2330             } else if (s->be_data == MO_LE) {
2331                 gen_helper_paired_cmpxchg64_le_parallel(tmp, cpu_env,
2332                                                         cpu_exclusive_addr,
2333                                                         cpu_reg(s, rt),
2334                                                         cpu_reg(s, rt2));
2335             } else {
2336                 gen_helper_paired_cmpxchg64_be_parallel(tmp, cpu_env,
2337                                                         cpu_exclusive_addr,
2338                                                         cpu_reg(s, rt),
2339                                                         cpu_reg(s, rt2));
2340             }
2341         } else if (s->be_data == MO_LE) {
2342             gen_helper_paired_cmpxchg64_le(tmp, cpu_env, cpu_exclusive_addr,
2343                                            cpu_reg(s, rt), cpu_reg(s, rt2));
2344         } else {
2345             gen_helper_paired_cmpxchg64_be(tmp, cpu_env, cpu_exclusive_addr,
2346                                            cpu_reg(s, rt), cpu_reg(s, rt2));
2347         }
2348     } else {
2349         tcg_gen_atomic_cmpxchg_i64(tmp, cpu_exclusive_addr, cpu_exclusive_val,
2350                                    cpu_reg(s, rt), get_mem_index(s),
2351                                    size | MO_ALIGN | s->be_data);
2352         tcg_gen_setcond_i64(TCG_COND_NE, tmp, tmp, cpu_exclusive_val);
2353     }
2354     tcg_gen_mov_i64(cpu_reg(s, rd), tmp);
2355     tcg_temp_free_i64(tmp);
2356     tcg_gen_br(done_label);
2357
2358     gen_set_label(fail_label);
2359     tcg_gen_movi_i64(cpu_reg(s, rd), 1);
2360     gen_set_label(done_label);
2361     tcg_gen_movi_i64(cpu_exclusive_addr, -1);
2362 }
2363
2364 static void gen_compare_and_swap(DisasContext *s, int rs, int rt,
2365                                  int rn, int size)
2366 {
2367     TCGv_i64 tcg_rs = cpu_reg(s, rs);
2368     TCGv_i64 tcg_rt = cpu_reg(s, rt);
2369     int memidx = get_mem_index(s);
2370     TCGv_i64 clean_addr;
2371
2372     if (rn == 31) {
2373         gen_check_sp_alignment(s);
2374     }
2375     clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2376     tcg_gen_atomic_cmpxchg_i64(tcg_rs, clean_addr, tcg_rs, tcg_rt, memidx,
2377                                size | MO_ALIGN | s->be_data);
2378 }
2379
2380 static void gen_compare_and_swap_pair(DisasContext *s, int rs, int rt,
2381                                       int rn, int size)
2382 {
2383     TCGv_i64 s1 = cpu_reg(s, rs);
2384     TCGv_i64 s2 = cpu_reg(s, rs + 1);
2385     TCGv_i64 t1 = cpu_reg(s, rt);
2386     TCGv_i64 t2 = cpu_reg(s, rt + 1);
2387     TCGv_i64 clean_addr;
2388     int memidx = get_mem_index(s);
2389
2390     if (rn == 31) {
2391         gen_check_sp_alignment(s);
2392     }
2393     clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2394
2395     if (size == 2) {
2396         TCGv_i64 cmp = tcg_temp_new_i64();
2397         TCGv_i64 val = tcg_temp_new_i64();
2398
2399         if (s->be_data == MO_LE) {
2400             tcg_gen_concat32_i64(val, t1, t2);
2401             tcg_gen_concat32_i64(cmp, s1, s2);
2402         } else {
2403             tcg_gen_concat32_i64(val, t2, t1);
2404             tcg_gen_concat32_i64(cmp, s2, s1);
2405         }
2406
2407         tcg_gen_atomic_cmpxchg_i64(cmp, clean_addr, cmp, val, memidx,
2408                                    MO_64 | MO_ALIGN | s->be_data);
2409         tcg_temp_free_i64(val);
2410
2411         if (s->be_data == MO_LE) {
2412             tcg_gen_extr32_i64(s1, s2, cmp);
2413         } else {
2414             tcg_gen_extr32_i64(s2, s1, cmp);
2415         }
2416         tcg_temp_free_i64(cmp);
2417     } else if (tb_cflags(s->base.tb) & CF_PARALLEL) {
2418         if (HAVE_CMPXCHG128) {
2419             TCGv_i32 tcg_rs = tcg_const_i32(rs);
2420             if (s->be_data == MO_LE) {
2421                 gen_helper_casp_le_parallel(cpu_env, tcg_rs,
2422                                             clean_addr, t1, t2);
2423             } else {
2424                 gen_helper_casp_be_parallel(cpu_env, tcg_rs,
2425                                             clean_addr, t1, t2);
2426             }
2427             tcg_temp_free_i32(tcg_rs);
2428         } else {
2429             gen_helper_exit_atomic(cpu_env);
2430             s->base.is_jmp = DISAS_NORETURN;
2431         }
2432     } else {
2433         TCGv_i64 d1 = tcg_temp_new_i64();
2434         TCGv_i64 d2 = tcg_temp_new_i64();
2435         TCGv_i64 a2 = tcg_temp_new_i64();
2436         TCGv_i64 c1 = tcg_temp_new_i64();
2437         TCGv_i64 c2 = tcg_temp_new_i64();
2438         TCGv_i64 zero = tcg_const_i64(0);
2439
2440         /* Load the two words, in memory order.  */
2441         tcg_gen_qemu_ld_i64(d1, clean_addr, memidx,
2442                             MO_64 | MO_ALIGN_16 | s->be_data);
2443         tcg_gen_addi_i64(a2, clean_addr, 8);
2444         tcg_gen_qemu_ld_i64(d2, a2, memidx, MO_64 | s->be_data);
2445
2446         /* Compare the two words, also in memory order.  */
2447         tcg_gen_setcond_i64(TCG_COND_EQ, c1, d1, s1);
2448         tcg_gen_setcond_i64(TCG_COND_EQ, c2, d2, s2);
2449         tcg_gen_and_i64(c2, c2, c1);
2450
2451         /* If compare equal, write back new data, else write back old data.  */
2452         tcg_gen_movcond_i64(TCG_COND_NE, c1, c2, zero, t1, d1);
2453         tcg_gen_movcond_i64(TCG_COND_NE, c2, c2, zero, t2, d2);
2454         tcg_gen_qemu_st_i64(c1, clean_addr, memidx, MO_64 | s->be_data);
2455         tcg_gen_qemu_st_i64(c2, a2, memidx, MO_64 | s->be_data);
2456         tcg_temp_free_i64(a2);
2457         tcg_temp_free_i64(c1);
2458         tcg_temp_free_i64(c2);
2459         tcg_temp_free_i64(zero);
2460
2461         /* Write back the data from memory to Rs.  */
2462         tcg_gen_mov_i64(s1, d1);
2463         tcg_gen_mov_i64(s2, d2);
2464         tcg_temp_free_i64(d1);
2465         tcg_temp_free_i64(d2);
2466     }
2467 }
2468
2469 /* Update the Sixty-Four bit (SF) registersize. This logic is derived
2470  * from the ARMv8 specs for LDR (Shared decode for all encodings).
2471  */
2472 static bool disas_ldst_compute_iss_sf(int size, bool is_signed, int opc)
2473 {
2474     int opc0 = extract32(opc, 0, 1);
2475     int regsize;
2476
2477     if (is_signed) {
2478         regsize = opc0 ? 32 : 64;
2479     } else {
2480         regsize = size == 3 ? 64 : 32;
2481     }
2482     return regsize == 64;
2483 }
2484
2485 /* Load/store exclusive
2486  *
2487  *  31 30 29         24  23  22   21  20  16  15  14   10 9    5 4    0
2488  * +-----+-------------+----+---+----+------+----+-------+------+------+
2489  * | sz  | 0 0 1 0 0 0 | o2 | L | o1 |  Rs  | o0 |  Rt2  |  Rn  | Rt   |
2490  * +-----+-------------+----+---+----+------+----+-------+------+------+
2491  *
2492  *  sz: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64 bit
2493  *   L: 0 -> store, 1 -> load
2494  *  o2: 0 -> exclusive, 1 -> not
2495  *  o1: 0 -> single register, 1 -> register pair
2496  *  o0: 1 -> load-acquire/store-release, 0 -> not
2497  */
2498 static void disas_ldst_excl(DisasContext *s, uint32_t insn)
2499 {
2500     int rt = extract32(insn, 0, 5);
2501     int rn = extract32(insn, 5, 5);
2502     int rt2 = extract32(insn, 10, 5);
2503     int rs = extract32(insn, 16, 5);
2504     int is_lasr = extract32(insn, 15, 1);
2505     int o2_L_o1_o0 = extract32(insn, 21, 3) * 2 | is_lasr;
2506     int size = extract32(insn, 30, 2);
2507     TCGv_i64 clean_addr;
2508
2509     switch (o2_L_o1_o0) {
2510     case 0x0: /* STXR */
2511     case 0x1: /* STLXR */
2512         if (rn == 31) {
2513             gen_check_sp_alignment(s);
2514         }
2515         if (is_lasr) {
2516             tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2517         }
2518         clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2519         gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, false);
2520         return;
2521
2522     case 0x4: /* LDXR */
2523     case 0x5: /* LDAXR */
2524         if (rn == 31) {
2525             gen_check_sp_alignment(s);
2526         }
2527         clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2528         s->is_ldex = true;
2529         gen_load_exclusive(s, rt, rt2, clean_addr, size, false);
2530         if (is_lasr) {
2531             tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2532         }
2533         return;
2534
2535     case 0x8: /* STLLR */
2536         if (!dc_isar_feature(aa64_lor, s)) {
2537             break;
2538         }
2539         /* StoreLORelease is the same as Store-Release for QEMU.  */
2540         /* fall through */
2541     case 0x9: /* STLR */
2542         /* Generate ISS for non-exclusive accesses including LASR.  */
2543         if (rn == 31) {
2544             gen_check_sp_alignment(s);
2545         }
2546         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2547         clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2548         do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt,
2549                   disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
2550         return;
2551
2552     case 0xc: /* LDLAR */
2553         if (!dc_isar_feature(aa64_lor, s)) {
2554             break;
2555         }
2556         /* LoadLOAcquire is the same as Load-Acquire for QEMU.  */
2557         /* fall through */
2558     case 0xd: /* LDAR */
2559         /* Generate ISS for non-exclusive accesses including LASR.  */
2560         if (rn == 31) {
2561             gen_check_sp_alignment(s);
2562         }
2563         clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2564         do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false, false, true, rt,
2565                   disas_ldst_compute_iss_sf(size, false, 0), is_lasr);
2566         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2567         return;
2568
2569     case 0x2: case 0x3: /* CASP / STXP */
2570         if (size & 2) { /* STXP / STLXP */
2571             if (rn == 31) {
2572                 gen_check_sp_alignment(s);
2573             }
2574             if (is_lasr) {
2575                 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
2576             }
2577             clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2578             gen_store_exclusive(s, rs, rt, rt2, clean_addr, size, true);
2579             return;
2580         }
2581         if (rt2 == 31
2582             && ((rt | rs) & 1) == 0
2583             && dc_isar_feature(aa64_atomics, s)) {
2584             /* CASP / CASPL */
2585             gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
2586             return;
2587         }
2588         break;
2589
2590     case 0x6: case 0x7: /* CASPA / LDXP */
2591         if (size & 2) { /* LDXP / LDAXP */
2592             if (rn == 31) {
2593                 gen_check_sp_alignment(s);
2594             }
2595             clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
2596             s->is_ldex = true;
2597             gen_load_exclusive(s, rt, rt2, clean_addr, size, true);
2598             if (is_lasr) {
2599                 tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
2600             }
2601             return;
2602         }
2603         if (rt2 == 31
2604             && ((rt | rs) & 1) == 0
2605             && dc_isar_feature(aa64_atomics, s)) {
2606             /* CASPA / CASPAL */
2607             gen_compare_and_swap_pair(s, rs, rt, rn, size | 2);
2608             return;
2609         }
2610         break;
2611
2612     case 0xa: /* CAS */
2613     case 0xb: /* CASL */
2614     case 0xe: /* CASA */
2615     case 0xf: /* CASAL */
2616         if (rt2 == 31 && dc_isar_feature(aa64_atomics, s)) {
2617             gen_compare_and_swap(s, rs, rt, rn, size);
2618             return;
2619         }
2620         break;
2621     }
2622     unallocated_encoding(s);
2623 }
2624
2625 /*
2626  * Load register (literal)
2627  *
2628  *  31 30 29   27  26 25 24 23                5 4     0
2629  * +-----+-------+---+-----+-------------------+-------+
2630  * | opc | 0 1 1 | V | 0 0 |     imm19         |  Rt   |
2631  * +-----+-------+---+-----+-------------------+-------+
2632  *
2633  * V: 1 -> vector (simd/fp)
2634  * opc (non-vector): 00 -> 32 bit, 01 -> 64 bit,
2635  *                   10-> 32 bit signed, 11 -> prefetch
2636  * opc (vector): 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit (11 unallocated)
2637  */
2638 static void disas_ld_lit(DisasContext *s, uint32_t insn)
2639 {
2640     int rt = extract32(insn, 0, 5);
2641     int64_t imm = sextract32(insn, 5, 19) << 2;
2642     bool is_vector = extract32(insn, 26, 1);
2643     int opc = extract32(insn, 30, 2);
2644     bool is_signed = false;
2645     int size = 2;
2646     TCGv_i64 tcg_rt, clean_addr;
2647
2648     if (is_vector) {
2649         if (opc == 3) {
2650             unallocated_encoding(s);
2651             return;
2652         }
2653         size = 2 + opc;
2654         if (!fp_access_check(s)) {
2655             return;
2656         }
2657     } else {
2658         if (opc == 3) {
2659             /* PRFM (literal) : prefetch */
2660             return;
2661         }
2662         size = 2 + extract32(opc, 0, 1);
2663         is_signed = extract32(opc, 1, 1);
2664     }
2665
2666     tcg_rt = cpu_reg(s, rt);
2667
2668     clean_addr = tcg_const_i64(s->pc_curr + imm);
2669     if (is_vector) {
2670         do_fp_ld(s, rt, clean_addr, size);
2671     } else {
2672         /* Only unsigned 32bit loads target 32bit registers.  */
2673         bool iss_sf = opc != 0;
2674
2675         do_gpr_ld(s, tcg_rt, clean_addr, size, is_signed, false,
2676                   true, rt, iss_sf, false);
2677     }
2678     tcg_temp_free_i64(clean_addr);
2679 }
2680
2681 /*
2682  * LDNP (Load Pair - non-temporal hint)
2683  * LDP (Load Pair - non vector)
2684  * LDPSW (Load Pair Signed Word - non vector)
2685  * STNP (Store Pair - non-temporal hint)
2686  * STP (Store Pair - non vector)
2687  * LDNP (Load Pair of SIMD&FP - non-temporal hint)
2688  * LDP (Load Pair of SIMD&FP)
2689  * STNP (Store Pair of SIMD&FP - non-temporal hint)
2690  * STP (Store Pair of SIMD&FP)
2691  *
2692  *  31 30 29   27  26  25 24   23  22 21   15 14   10 9    5 4    0
2693  * +-----+-------+---+---+-------+---+-----------------------------+
2694  * | opc | 1 0 1 | V | 0 | index | L |  imm7 |  Rt2  |  Rn  | Rt   |
2695  * +-----+-------+---+---+-------+---+-------+-------+------+------+
2696  *
2697  * opc: LDP/STP/LDNP/STNP        00 -> 32 bit, 10 -> 64 bit
2698  *      LDPSW                    01
2699  *      LDP/STP/LDNP/STNP (SIMD) 00 -> 32 bit, 01 -> 64 bit, 10 -> 128 bit
2700  *   V: 0 -> GPR, 1 -> Vector
2701  * idx: 00 -> signed offset with non-temporal hint, 01 -> post-index,
2702  *      10 -> signed offset, 11 -> pre-index
2703  *   L: 0 -> Store 1 -> Load
2704  *
2705  * Rt, Rt2 = GPR or SIMD registers to be stored
2706  * Rn = general purpose register containing address
2707  * imm7 = signed offset (multiple of 4 or 8 depending on size)
2708  */
2709 static void disas_ldst_pair(DisasContext *s, uint32_t insn)
2710 {
2711     int rt = extract32(insn, 0, 5);
2712     int rn = extract32(insn, 5, 5);
2713     int rt2 = extract32(insn, 10, 5);
2714     uint64_t offset = sextract64(insn, 15, 7);
2715     int index = extract32(insn, 23, 2);
2716     bool is_vector = extract32(insn, 26, 1);
2717     bool is_load = extract32(insn, 22, 1);
2718     int opc = extract32(insn, 30, 2);
2719
2720     bool is_signed = false;
2721     bool postindex = false;
2722     bool wback = false;
2723
2724     TCGv_i64 clean_addr, dirty_addr;
2725
2726     int size;
2727
2728     if (opc == 3) {
2729         unallocated_encoding(s);
2730         return;
2731     }
2732
2733     if (is_vector) {
2734         size = 2 + opc;
2735     } else {
2736         size = 2 + extract32(opc, 1, 1);
2737         is_signed = extract32(opc, 0, 1);
2738         if (!is_load && is_signed) {
2739             unallocated_encoding(s);
2740             return;
2741         }
2742     }
2743
2744     switch (index) {
2745     case 1: /* post-index */
2746         postindex = true;
2747         wback = true;
2748         break;
2749     case 0:
2750         /* signed offset with "non-temporal" hint. Since we don't emulate
2751          * caches we don't care about hints to the cache system about
2752          * data access patterns, and handle this identically to plain
2753          * signed offset.
2754          */
2755         if (is_signed) {
2756             /* There is no non-temporal-hint version of LDPSW */
2757             unallocated_encoding(s);
2758             return;
2759         }
2760         postindex = false;
2761         break;
2762     case 2: /* signed offset, rn not updated */
2763         postindex = false;
2764         break;
2765     case 3: /* pre-index */
2766         postindex = false;
2767         wback = true;
2768         break;
2769     }
2770
2771     if (is_vector && !fp_access_check(s)) {
2772         return;
2773     }
2774
2775     offset <<= size;
2776
2777     if (rn == 31) {
2778         gen_check_sp_alignment(s);
2779     }
2780
2781     dirty_addr = read_cpu_reg_sp(s, rn, 1);
2782     if (!postindex) {
2783         tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
2784     }
2785     clean_addr = clean_data_tbi(s, dirty_addr);
2786
2787     if (is_vector) {
2788         if (is_load) {
2789             do_fp_ld(s, rt, clean_addr, size);
2790         } else {
2791             do_fp_st(s, rt, clean_addr, size);
2792         }
2793         tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
2794         if (is_load) {
2795             do_fp_ld(s, rt2, clean_addr, size);
2796         } else {
2797             do_fp_st(s, rt2, clean_addr, size);
2798         }
2799     } else {
2800         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2801         TCGv_i64 tcg_rt2 = cpu_reg(s, rt2);
2802
2803         if (is_load) {
2804             TCGv_i64 tmp = tcg_temp_new_i64();
2805
2806             /* Do not modify tcg_rt before recognizing any exception
2807              * from the second load.
2808              */
2809             do_gpr_ld(s, tmp, clean_addr, size, is_signed, false,
2810                       false, 0, false, false);
2811             tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
2812             do_gpr_ld(s, tcg_rt2, clean_addr, size, is_signed, false,
2813                       false, 0, false, false);
2814
2815             tcg_gen_mov_i64(tcg_rt, tmp);
2816             tcg_temp_free_i64(tmp);
2817         } else {
2818             do_gpr_st(s, tcg_rt, clean_addr, size,
2819                       false, 0, false, false);
2820             tcg_gen_addi_i64(clean_addr, clean_addr, 1 << size);
2821             do_gpr_st(s, tcg_rt2, clean_addr, size,
2822                       false, 0, false, false);
2823         }
2824     }
2825
2826     if (wback) {
2827         if (postindex) {
2828             tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
2829         }
2830         tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
2831     }
2832 }
2833
2834 /*
2835  * Load/store (immediate post-indexed)
2836  * Load/store (immediate pre-indexed)
2837  * Load/store (unscaled immediate)
2838  *
2839  * 31 30 29   27  26 25 24 23 22 21  20    12 11 10 9    5 4    0
2840  * +----+-------+---+-----+-----+---+--------+-----+------+------+
2841  * |size| 1 1 1 | V | 0 0 | opc | 0 |  imm9  | idx |  Rn  |  Rt  |
2842  * +----+-------+---+-----+-----+---+--------+-----+------+------+
2843  *
2844  * idx = 01 -> post-indexed, 11 pre-indexed, 00 unscaled imm. (no writeback)
2845          10 -> unprivileged
2846  * V = 0 -> non-vector
2847  * size: 00 -> 8 bit, 01 -> 16 bit, 10 -> 32 bit, 11 -> 64bit
2848  * opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2849  */
2850 static void disas_ldst_reg_imm9(DisasContext *s, uint32_t insn,
2851                                 int opc,
2852                                 int size,
2853                                 int rt,
2854                                 bool is_vector)
2855 {
2856     int rn = extract32(insn, 5, 5);
2857     int imm9 = sextract32(insn, 12, 9);
2858     int idx = extract32(insn, 10, 2);
2859     bool is_signed = false;
2860     bool is_store = false;
2861     bool is_extended = false;
2862     bool is_unpriv = (idx == 2);
2863     bool iss_valid = !is_vector;
2864     bool post_index;
2865     bool writeback;
2866
2867     TCGv_i64 clean_addr, dirty_addr;
2868
2869     if (is_vector) {
2870         size |= (opc & 2) << 1;
2871         if (size > 4 || is_unpriv) {
2872             unallocated_encoding(s);
2873             return;
2874         }
2875         is_store = ((opc & 1) == 0);
2876         if (!fp_access_check(s)) {
2877             return;
2878         }
2879     } else {
2880         if (size == 3 && opc == 2) {
2881             /* PRFM - prefetch */
2882             if (idx != 0) {
2883                 unallocated_encoding(s);
2884                 return;
2885             }
2886             return;
2887         }
2888         if (opc == 3 && size > 1) {
2889             unallocated_encoding(s);
2890             return;
2891         }
2892         is_store = (opc == 0);
2893         is_signed = extract32(opc, 1, 1);
2894         is_extended = (size < 3) && extract32(opc, 0, 1);
2895     }
2896
2897     switch (idx) {
2898     case 0:
2899     case 2:
2900         post_index = false;
2901         writeback = false;
2902         break;
2903     case 1:
2904         post_index = true;
2905         writeback = true;
2906         break;
2907     case 3:
2908         post_index = false;
2909         writeback = true;
2910         break;
2911     default:
2912         g_assert_not_reached();
2913     }
2914
2915     if (rn == 31) {
2916         gen_check_sp_alignment(s);
2917     }
2918
2919     dirty_addr = read_cpu_reg_sp(s, rn, 1);
2920     if (!post_index) {
2921         tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
2922     }
2923     clean_addr = clean_data_tbi(s, dirty_addr);
2924
2925     if (is_vector) {
2926         if (is_store) {
2927             do_fp_st(s, rt, clean_addr, size);
2928         } else {
2929             do_fp_ld(s, rt, clean_addr, size);
2930         }
2931     } else {
2932         TCGv_i64 tcg_rt = cpu_reg(s, rt);
2933         int memidx = is_unpriv ? get_a64_user_mem_index(s) : get_mem_index(s);
2934         bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
2935
2936         if (is_store) {
2937             do_gpr_st_memidx(s, tcg_rt, clean_addr, size, memidx,
2938                              iss_valid, rt, iss_sf, false);
2939         } else {
2940             do_gpr_ld_memidx(s, tcg_rt, clean_addr, size,
2941                              is_signed, is_extended, memidx,
2942                              iss_valid, rt, iss_sf, false);
2943         }
2944     }
2945
2946     if (writeback) {
2947         TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
2948         if (post_index) {
2949             tcg_gen_addi_i64(dirty_addr, dirty_addr, imm9);
2950         }
2951         tcg_gen_mov_i64(tcg_rn, dirty_addr);
2952     }
2953 }
2954
2955 /*
2956  * Load/store (register offset)
2957  *
2958  * 31 30 29   27  26 25 24 23 22 21  20  16 15 13 12 11 10 9  5 4  0
2959  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2960  * |size| 1 1 1 | V | 0 0 | opc | 1 |  Rm  | opt | S| 1 0 | Rn | Rt |
2961  * +----+-------+---+-----+-----+---+------+-----+--+-----+----+----+
2962  *
2963  * For non-vector:
2964  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
2965  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
2966  * For vector:
2967  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
2968  *   opc<0>: 0 -> store, 1 -> load
2969  * V: 1 -> vector/simd
2970  * opt: extend encoding (see DecodeRegExtend)
2971  * S: if S=1 then scale (essentially index by sizeof(size))
2972  * Rt: register to transfer into/out of
2973  * Rn: address register or SP for base
2974  * Rm: offset register or ZR for offset
2975  */
2976 static void disas_ldst_reg_roffset(DisasContext *s, uint32_t insn,
2977                                    int opc,
2978                                    int size,
2979                                    int rt,
2980                                    bool is_vector)
2981 {
2982     int rn = extract32(insn, 5, 5);
2983     int shift = extract32(insn, 12, 1);
2984     int rm = extract32(insn, 16, 5);
2985     int opt = extract32(insn, 13, 3);
2986     bool is_signed = false;
2987     bool is_store = false;
2988     bool is_extended = false;
2989
2990     TCGv_i64 tcg_rm, clean_addr, dirty_addr;
2991
2992     if (extract32(opt, 1, 1) == 0) {
2993         unallocated_encoding(s);
2994         return;
2995     }
2996
2997     if (is_vector) {
2998         size |= (opc & 2) << 1;
2999         if (size > 4) {
3000             unallocated_encoding(s);
3001             return;
3002         }
3003         is_store = !extract32(opc, 0, 1);
3004         if (!fp_access_check(s)) {
3005             return;
3006         }
3007     } else {
3008         if (size == 3 && opc == 2) {
3009             /* PRFM - prefetch */
3010             return;
3011         }
3012         if (opc == 3 && size > 1) {
3013             unallocated_encoding(s);
3014             return;
3015         }
3016         is_store = (opc == 0);
3017         is_signed = extract32(opc, 1, 1);
3018         is_extended = (size < 3) && extract32(opc, 0, 1);
3019     }
3020
3021     if (rn == 31) {
3022         gen_check_sp_alignment(s);
3023     }
3024     dirty_addr = read_cpu_reg_sp(s, rn, 1);
3025
3026     tcg_rm = read_cpu_reg(s, rm, 1);
3027     ext_and_shift_reg(tcg_rm, tcg_rm, opt, shift ? size : 0);
3028
3029     tcg_gen_add_i64(dirty_addr, dirty_addr, tcg_rm);
3030     clean_addr = clean_data_tbi(s, dirty_addr);
3031
3032     if (is_vector) {
3033         if (is_store) {
3034             do_fp_st(s, rt, clean_addr, size);
3035         } else {
3036             do_fp_ld(s, rt, clean_addr, size);
3037         }
3038     } else {
3039         TCGv_i64 tcg_rt = cpu_reg(s, rt);
3040         bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
3041         if (is_store) {
3042             do_gpr_st(s, tcg_rt, clean_addr, size,
3043                       true, rt, iss_sf, false);
3044         } else {
3045             do_gpr_ld(s, tcg_rt, clean_addr, size,
3046                       is_signed, is_extended,
3047                       true, rt, iss_sf, false);
3048         }
3049     }
3050 }
3051
3052 /*
3053  * Load/store (unsigned immediate)
3054  *
3055  * 31 30 29   27  26 25 24 23 22 21        10 9     5
3056  * +----+-------+---+-----+-----+------------+-------+------+
3057  * |size| 1 1 1 | V | 0 1 | opc |   imm12    |  Rn   |  Rt  |
3058  * +----+-------+---+-----+-----+------------+-------+------+
3059  *
3060  * For non-vector:
3061  *   size: 00-> byte, 01 -> 16 bit, 10 -> 32bit, 11 -> 64bit
3062  *   opc: 00 -> store, 01 -> loadu, 10 -> loads 64, 11 -> loads 32
3063  * For vector:
3064  *   size is opc<1>:size<1:0> so 100 -> 128 bit; 110 and 111 unallocated
3065  *   opc<0>: 0 -> store, 1 -> load
3066  * Rn: base address register (inc SP)
3067  * Rt: target register
3068  */
3069 static void disas_ldst_reg_unsigned_imm(DisasContext *s, uint32_t insn,
3070                                         int opc,
3071                                         int size,
3072                                         int rt,
3073                                         bool is_vector)
3074 {
3075     int rn = extract32(insn, 5, 5);
3076     unsigned int imm12 = extract32(insn, 10, 12);
3077     unsigned int offset;
3078
3079     TCGv_i64 clean_addr, dirty_addr;
3080
3081     bool is_store;
3082     bool is_signed = false;
3083     bool is_extended = false;
3084
3085     if (is_vector) {
3086         size |= (opc & 2) << 1;
3087         if (size > 4) {
3088             unallocated_encoding(s);
3089             return;
3090         }
3091         is_store = !extract32(opc, 0, 1);
3092         if (!fp_access_check(s)) {
3093             return;
3094         }
3095     } else {
3096         if (size == 3 && opc == 2) {
3097             /* PRFM - prefetch */
3098             return;
3099         }
3100         if (opc == 3 && size > 1) {
3101             unallocated_encoding(s);
3102             return;
3103         }
3104         is_store = (opc == 0);
3105         is_signed = extract32(opc, 1, 1);
3106         is_extended = (size < 3) && extract32(opc, 0, 1);
3107     }
3108
3109     if (rn == 31) {
3110         gen_check_sp_alignment(s);
3111     }
3112     dirty_addr = read_cpu_reg_sp(s, rn, 1);
3113     offset = imm12 << size;
3114     tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
3115     clean_addr = clean_data_tbi(s, dirty_addr);
3116
3117     if (is_vector) {
3118         if (is_store) {
3119             do_fp_st(s, rt, clean_addr, size);
3120         } else {
3121             do_fp_ld(s, rt, clean_addr, size);
3122         }
3123     } else {
3124         TCGv_i64 tcg_rt = cpu_reg(s, rt);
3125         bool iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
3126         if (is_store) {
3127             do_gpr_st(s, tcg_rt, clean_addr, size,
3128                       true, rt, iss_sf, false);
3129         } else {
3130             do_gpr_ld(s, tcg_rt, clean_addr, size, is_signed, is_extended,
3131                       true, rt, iss_sf, false);
3132         }
3133     }
3134 }
3135
3136 /* Atomic memory operations
3137  *
3138  *  31  30      27  26    24    22  21   16   15    12    10    5     0
3139  * +------+-------+---+-----+-----+---+----+----+-----+-----+----+-----+
3140  * | size | 1 1 1 | V | 0 0 | A R | 1 | Rs | o3 | opc | 0 0 | Rn |  Rt |
3141  * +------+-------+---+-----+-----+--------+----+-----+-----+----+-----+
3142  *
3143  * Rt: the result register
3144  * Rn: base address or SP
3145  * Rs: the source register for the operation
3146  * V: vector flag (always 0 as of v8.3)
3147  * A: acquire flag
3148  * R: release flag
3149  */
3150 static void disas_ldst_atomic(DisasContext *s, uint32_t insn,
3151                               int size, int rt, bool is_vector)
3152 {
3153     int rs = extract32(insn, 16, 5);
3154     int rn = extract32(insn, 5, 5);
3155     int o3_opc = extract32(insn, 12, 4);
3156     bool r = extract32(insn, 22, 1);
3157     bool a = extract32(insn, 23, 1);
3158     TCGv_i64 tcg_rs, clean_addr;
3159     AtomicThreeOpFn *fn;
3160
3161     if (is_vector || !dc_isar_feature(aa64_atomics, s)) {
3162         unallocated_encoding(s);
3163         return;
3164     }
3165     switch (o3_opc) {
3166     case 000: /* LDADD */
3167         fn = tcg_gen_atomic_fetch_add_i64;
3168         break;
3169     case 001: /* LDCLR */
3170         fn = tcg_gen_atomic_fetch_and_i64;
3171         break;
3172     case 002: /* LDEOR */
3173         fn = tcg_gen_atomic_fetch_xor_i64;
3174         break;
3175     case 003: /* LDSET */
3176         fn = tcg_gen_atomic_fetch_or_i64;
3177         break;
3178     case 004: /* LDSMAX */
3179         fn = tcg_gen_atomic_fetch_smax_i64;
3180         break;
3181     case 005: /* LDSMIN */
3182         fn = tcg_gen_atomic_fetch_smin_i64;
3183         break;
3184     case 006: /* LDUMAX */
3185         fn = tcg_gen_atomic_fetch_umax_i64;
3186         break;
3187     case 007: /* LDUMIN */
3188         fn = tcg_gen_atomic_fetch_umin_i64;
3189         break;
3190     case 010: /* SWP */
3191         fn = tcg_gen_atomic_xchg_i64;
3192         break;
3193     case 014: /* LDAPR, LDAPRH, LDAPRB */
3194         if (!dc_isar_feature(aa64_rcpc_8_3, s) ||
3195             rs != 31 || a != 1 || r != 0) {
3196             unallocated_encoding(s);
3197             return;
3198         }
3199         break;
3200     default:
3201         unallocated_encoding(s);
3202         return;
3203     }
3204
3205     if (rn == 31) {
3206         gen_check_sp_alignment(s);
3207     }
3208     clean_addr = clean_data_tbi(s, cpu_reg_sp(s, rn));
3209
3210     if (o3_opc == 014) {
3211         /*
3212          * LDAPR* are a special case because they are a simple load, not a
3213          * fetch-and-do-something op.
3214          * The architectural consistency requirements here are weaker than
3215          * full load-acquire (we only need "load-acquire processor consistent"),
3216          * but we choose to implement them as full LDAQ.
3217          */
3218         do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, false, false,
3219                   true, rt, disas_ldst_compute_iss_sf(size, false, 0), true);
3220         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
3221         return;
3222     }
3223
3224     tcg_rs = read_cpu_reg(s, rs, true);
3225
3226     if (o3_opc == 1) { /* LDCLR */
3227         tcg_gen_not_i64(tcg_rs, tcg_rs);
3228     }
3229
3230     /* The tcg atomic primitives are all full barriers.  Therefore we
3231      * can ignore the Acquire and Release bits of this instruction.
3232      */
3233     fn(cpu_reg(s, rt), clean_addr, tcg_rs, get_mem_index(s),
3234        s->be_data | size | MO_ALIGN);
3235 }
3236
3237 /*
3238  * PAC memory operations
3239  *
3240  *  31  30      27  26    24    22  21       12  11  10    5     0
3241  * +------+-------+---+-----+-----+---+--------+---+---+----+-----+
3242  * | size | 1 1 1 | V | 0 0 | M S | 1 |  imm9  | W | 1 | Rn |  Rt |
3243  * +------+-------+---+-----+-----+---+--------+---+---+----+-----+
3244  *
3245  * Rt: the result register
3246  * Rn: base address or SP
3247  * V: vector flag (always 0 as of v8.3)
3248  * M: clear for key DA, set for key DB
3249  * W: pre-indexing flag
3250  * S: sign for imm9.
3251  */
3252 static void disas_ldst_pac(DisasContext *s, uint32_t insn,
3253                            int size, int rt, bool is_vector)
3254 {
3255     int rn = extract32(insn, 5, 5);
3256     bool is_wback = extract32(insn, 11, 1);
3257     bool use_key_a = !extract32(insn, 23, 1);
3258     int offset;
3259     TCGv_i64 clean_addr, dirty_addr, tcg_rt;
3260
3261     if (size != 3 || is_vector || !dc_isar_feature(aa64_pauth, s)) {
3262         unallocated_encoding(s);
3263         return;
3264     }
3265
3266     if (rn == 31) {
3267         gen_check_sp_alignment(s);
3268     }
3269     dirty_addr = read_cpu_reg_sp(s, rn, 1);
3270
3271     if (s->pauth_active) {
3272         if (use_key_a) {
3273             gen_helper_autda(dirty_addr, cpu_env, dirty_addr, cpu_X[31]);
3274         } else {
3275             gen_helper_autdb(dirty_addr, cpu_env, dirty_addr, cpu_X[31]);
3276         }
3277     }
3278
3279     /* Form the 10-bit signed, scaled offset.  */
3280     offset = (extract32(insn, 22, 1) << 9) | extract32(insn, 12, 9);
3281     offset = sextract32(offset << size, 0, 10 + size);
3282     tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
3283
3284     /* Note that "clean" and "dirty" here refer to TBI not PAC.  */
3285     clean_addr = clean_data_tbi(s, dirty_addr);
3286
3287     tcg_rt = cpu_reg(s, rt);
3288     do_gpr_ld(s, tcg_rt, clean_addr, size, /* is_signed */ false,
3289               /* extend */ false, /* iss_valid */ !is_wback,
3290               /* iss_srt */ rt, /* iss_sf */ true, /* iss_ar */ false);
3291
3292     if (is_wback) {
3293         tcg_gen_mov_i64(cpu_reg_sp(s, rn), dirty_addr);
3294     }
3295 }
3296
3297 /*
3298  * LDAPR/STLR (unscaled immediate)
3299  *
3300  *  31  30            24    22  21       12    10    5     0
3301  * +------+-------------+-----+---+--------+-----+----+-----+
3302  * | size | 0 1 1 0 0 1 | opc | 0 |  imm9  | 0 0 | Rn |  Rt |
3303  * +------+-------------+-----+---+--------+-----+----+-----+
3304  *
3305  * Rt: source or destination register
3306  * Rn: base register
3307  * imm9: unscaled immediate offset
3308  * opc: 00: STLUR*, 01/10/11: various LDAPUR*
3309  * size: size of load/store
3310  */
3311 static void disas_ldst_ldapr_stlr(DisasContext *s, uint32_t insn)
3312 {
3313     int rt = extract32(insn, 0, 5);
3314     int rn = extract32(insn, 5, 5);
3315     int offset = sextract32(insn, 12, 9);
3316     int opc = extract32(insn, 22, 2);
3317     int size = extract32(insn, 30, 2);
3318     TCGv_i64 clean_addr, dirty_addr;
3319     bool is_store = false;
3320     bool is_signed = false;
3321     bool extend = false;
3322     bool iss_sf;
3323
3324     if (!dc_isar_feature(aa64_rcpc_8_4, s)) {
3325         unallocated_encoding(s);
3326         return;
3327     }
3328
3329     switch (opc) {
3330     case 0: /* STLURB */
3331         is_store = true;
3332         break;
3333     case 1: /* LDAPUR* */
3334         break;
3335     case 2: /* LDAPURS* 64-bit variant */
3336         if (size == 3) {
3337             unallocated_encoding(s);
3338             return;
3339         }
3340         is_signed = true;
3341         break;
3342     case 3: /* LDAPURS* 32-bit variant */
3343         if (size > 1) {
3344             unallocated_encoding(s);
3345             return;
3346         }
3347         is_signed = true;
3348         extend = true; /* zero-extend 32->64 after signed load */
3349         break;
3350     default:
3351         g_assert_not_reached();
3352     }
3353
3354     iss_sf = disas_ldst_compute_iss_sf(size, is_signed, opc);
3355
3356     if (rn == 31) {
3357         gen_check_sp_alignment(s);
3358     }
3359
3360     dirty_addr = read_cpu_reg_sp(s, rn, 1);
3361     tcg_gen_addi_i64(dirty_addr, dirty_addr, offset);
3362     clean_addr = clean_data_tbi(s, dirty_addr);
3363
3364     if (is_store) {
3365         /* Store-Release semantics */
3366         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_STRL);
3367         do_gpr_st(s, cpu_reg(s, rt), clean_addr, size, true, rt, iss_sf, true);
3368     } else {
3369         /*
3370          * Load-AcquirePC semantics; we implement as the slightly more
3371          * restrictive Load-Acquire.
3372          */
3373         do_gpr_ld(s, cpu_reg(s, rt), clean_addr, size, is_signed, extend,
3374                   true, rt, iss_sf, true);
3375         tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ);
3376     }
3377 }
3378
3379 /* Load/store register (all forms) */
3380 static void disas_ldst_reg(DisasContext *s, uint32_t insn)
3381 {
3382     int rt = extract32(insn, 0, 5);
3383     int opc = extract32(insn, 22, 2);
3384     bool is_vector = extract32(insn, 26, 1);
3385     int size = extract32(insn, 30, 2);
3386
3387     switch (extract32(insn, 24, 2)) {
3388     case 0:
3389         if (extract32(insn, 21, 1) == 0) {
3390             /* Load/store register (unscaled immediate)
3391              * Load/store immediate pre/post-indexed
3392              * Load/store register unprivileged
3393              */
3394             disas_ldst_reg_imm9(s, insn, opc, size, rt, is_vector);
3395             return;
3396         }
3397         switch (extract32(insn, 10, 2)) {
3398         case 0:
3399             disas_ldst_atomic(s, insn, size, rt, is_vector);
3400             return;
3401         case 2:
3402             disas_ldst_reg_roffset(s, insn, opc, size, rt, is_vector);
3403             return;
3404         default:
3405             disas_ldst_pac(s, insn, size, rt, is_vector);
3406             return;
3407         }
3408         break;
3409     case 1:
3410         disas_ldst_reg_unsigned_imm(s, insn, opc, size, rt, is_vector);
3411         return;
3412     }
3413     unallocated_encoding(s);
3414 }
3415
3416 /* AdvSIMD load/store multiple structures
3417  *
3418  *  31  30  29           23 22  21         16 15    12 11  10 9    5 4    0
3419  * +---+---+---------------+---+-------------+--------+------+------+------+
3420  * | 0 | Q | 0 0 1 1 0 0 0 | L | 0 0 0 0 0 0 | opcode | size |  Rn  |  Rt  |
3421  * +---+---+---------------+---+-------------+--------+------+------+------+
3422  *
3423  * AdvSIMD load/store multiple structures (post-indexed)
3424  *
3425  *  31  30  29           23 22  21  20     16 15    12 11  10 9    5 4    0
3426  * +---+---+---------------+---+---+---------+--------+------+------+------+
3427  * | 0 | Q | 0 0 1 1 0 0 1 | L | 0 |   Rm    | opcode | size |  Rn  |  Rt  |
3428  * +---+---+---------------+---+---+---------+--------+------+------+------+
3429  *
3430  * Rt: first (or only) SIMD&FP register to be transferred
3431  * Rn: base address or SP
3432  * Rm (post-index only): post-index register (when !31) or size dependent #imm
3433  */
3434 static void disas_ldst_multiple_struct(DisasContext *s, uint32_t insn)
3435 {
3436     int rt = extract32(insn, 0, 5);
3437     int rn = extract32(insn, 5, 5);
3438     int rm = extract32(insn, 16, 5);
3439     int size = extract32(insn, 10, 2);
3440     int opcode = extract32(insn, 12, 4);
3441     bool is_store = !extract32(insn, 22, 1);
3442     bool is_postidx = extract32(insn, 23, 1);
3443     bool is_q = extract32(insn, 30, 1);
3444     TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
3445     MemOp endian = s->be_data;
3446
3447     int ebytes;   /* bytes per element */
3448     int elements; /* elements per vector */
3449     int rpt;    /* num iterations */
3450     int selem;  /* structure elements */
3451     int r;
3452
3453     if (extract32(insn, 31, 1) || extract32(insn, 21, 1)) {
3454         unallocated_encoding(s);
3455         return;
3456     }
3457
3458     if (!is_postidx && rm != 0) {
3459         unallocated_encoding(s);
3460         return;
3461     }
3462
3463     /* From the shared decode logic */
3464     switch (opcode) {
3465     case 0x0:
3466         rpt = 1;
3467         selem = 4;
3468         break;
3469     case 0x2:
3470         rpt = 4;
3471         selem = 1;
3472         break;
3473     case 0x4:
3474         rpt = 1;
3475         selem = 3;
3476         break;
3477     case 0x6:
3478         rpt = 3;
3479         selem = 1;
3480         break;
3481     case 0x7:
3482         rpt = 1;
3483         selem = 1;
3484         break;
3485     case 0x8:
3486         rpt = 1;
3487         selem = 2;
3488         break;
3489     case 0xa:
3490         rpt = 2;
3491         selem = 1;
3492         break;
3493     default:
3494         unallocated_encoding(s);
3495         return;
3496     }
3497
3498     if (size == 3 && !is_q && selem != 1) {
3499         /* reserved */
3500         unallocated_encoding(s);
3501         return;
3502     }
3503
3504     if (!fp_access_check(s)) {
3505         return;
3506     }
3507
3508     if (rn == 31) {
3509         gen_check_sp_alignment(s);
3510     }
3511
3512     /* For our purposes, bytes are always little-endian.  */
3513     if (size == 0) {
3514         endian = MO_LE;
3515     }
3516
3517     /* Consecutive little-endian elements from a single register
3518      * can be promoted to a larger little-endian operation.
3519      */
3520     if (selem == 1 && endian == MO_LE) {
3521         size = 3;
3522     }
3523     ebytes = 1 << size;
3524     elements = (is_q ? 16 : 8) / ebytes;
3525
3526     tcg_rn = cpu_reg_sp(s, rn);
3527     clean_addr = clean_data_tbi(s, tcg_rn);
3528     tcg_ebytes = tcg_const_i64(ebytes);
3529
3530     for (r = 0; r < rpt; r++) {
3531         int e;
3532         for (e = 0; e < elements; e++) {
3533             int xs;
3534             for (xs = 0; xs < selem; xs++) {
3535                 int tt = (rt + r + xs) % 32;
3536                 if (is_store) {
3537                     do_vec_st(s, tt, e, clean_addr, size, endian);
3538                 } else {
3539                     do_vec_ld(s, tt, e, clean_addr, size, endian);
3540                 }
3541                 tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
3542             }
3543         }
3544     }
3545     tcg_temp_free_i64(tcg_ebytes);
3546
3547     if (!is_store) {
3548         /* For non-quad operations, setting a slice of the low
3549          * 64 bits of the register clears the high 64 bits (in
3550          * the ARM ARM pseudocode this is implicit in the fact
3551          * that 'rval' is a 64 bit wide variable).
3552          * For quad operations, we might still need to zero the
3553          * high bits of SVE.
3554          */
3555         for (r = 0; r < rpt * selem; r++) {
3556             int tt = (rt + r) % 32;
3557             clear_vec_high(s, is_q, tt);
3558         }
3559     }
3560
3561     if (is_postidx) {
3562         if (rm == 31) {
3563             tcg_gen_addi_i64(tcg_rn, tcg_rn, rpt * elements * selem * ebytes);
3564         } else {
3565             tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
3566         }
3567     }
3568 }
3569
3570 /* AdvSIMD load/store single structure
3571  *
3572  *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
3573  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3574  * | 0 | Q | 0 0 1 1 0 1 0 | L R | 0 0 0 0 0 | opc | S | size |  Rn  |  Rt  |
3575  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3576  *
3577  * AdvSIMD load/store single structure (post-indexed)
3578  *
3579  *  31  30  29           23 22 21 20       16 15 13 12  11  10 9    5 4    0
3580  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3581  * | 0 | Q | 0 0 1 1 0 1 1 | L R |     Rm    | opc | S | size |  Rn  |  Rt  |
3582  * +---+---+---------------+-----+-----------+-----+---+------+------+------+
3583  *
3584  * Rt: first (or only) SIMD&FP register to be transferred
3585  * Rn: base address or SP
3586  * Rm (post-index only): post-index register (when !31) or size dependent #imm
3587  * index = encoded in Q:S:size dependent on size
3588  *
3589  * lane_size = encoded in R, opc
3590  * transfer width = encoded in opc, S, size
3591  */
3592 static void disas_ldst_single_struct(DisasContext *s, uint32_t insn)
3593 {
3594     int rt = extract32(insn, 0, 5);
3595     int rn = extract32(insn, 5, 5);
3596     int rm = extract32(insn, 16, 5);
3597     int size = extract32(insn, 10, 2);
3598     int S = extract32(insn, 12, 1);
3599     int opc = extract32(insn, 13, 3);
3600     int R = extract32(insn, 21, 1);
3601     int is_load = extract32(insn, 22, 1);
3602     int is_postidx = extract32(insn, 23, 1);
3603     int is_q = extract32(insn, 30, 1);
3604
3605     int scale = extract32(opc, 1, 2);
3606     int selem = (extract32(opc, 0, 1) << 1 | R) + 1;
3607     bool replicate = false;
3608     int index = is_q << 3 | S << 2 | size;
3609     int ebytes, xs;
3610     TCGv_i64 clean_addr, tcg_rn, tcg_ebytes;
3611
3612     if (extract32(insn, 31, 1)) {
3613         unallocated_encoding(s);
3614         return;
3615     }
3616     if (!is_postidx && rm != 0) {
3617         unallocated_encoding(s);
3618         return;
3619     }
3620
3621     switch (scale) {
3622     case 3:
3623         if (!is_load || S) {
3624             unallocated_encoding(s);
3625             return;
3626         }
3627         scale = size;
3628         replicate = true;
3629         break;
3630     case 0:
3631         break;
3632     case 1:
3633         if (extract32(size, 0, 1)) {
3634             unallocated_encoding(s);
3635             return;
3636         }
3637         index >>= 1;
3638         break;
3639     case 2:
3640         if (extract32(size, 1, 1)) {
3641             unallocated_encoding(s);
3642             return;
3643         }
3644         if (!extract32(size, 0, 1)) {
3645             index >>= 2;
3646         } else {
3647             if (S) {
3648                 unallocated_encoding(s);
3649                 return;
3650             }
3651             index >>= 3;
3652             scale = 3;
3653         }
3654         break;
3655     default:
3656         g_assert_not_reached();
3657     }
3658
3659     if (!fp_access_check(s)) {
3660         return;
3661     }
3662
3663     ebytes = 1 << scale;
3664
3665     if (rn == 31) {
3666         gen_check_sp_alignment(s);
3667     }
3668
3669     tcg_rn = cpu_reg_sp(s, rn);
3670     clean_addr = clean_data_tbi(s, tcg_rn);
3671     tcg_ebytes = tcg_const_i64(ebytes);
3672
3673     for (xs = 0; xs < selem; xs++) {
3674         if (replicate) {
3675             /* Load and replicate to all elements */
3676             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
3677
3678             tcg_gen_qemu_ld_i64(tcg_tmp, clean_addr,
3679                                 get_mem_index(s), s->be_data + scale);
3680             tcg_gen_gvec_dup_i64(scale, vec_full_reg_offset(s, rt),
3681                                  (is_q + 1) * 8, vec_full_reg_size(s),
3682                                  tcg_tmp);
3683             tcg_temp_free_i64(tcg_tmp);
3684         } else {
3685             /* Load/store one element per register */
3686             if (is_load) {
3687                 do_vec_ld(s, rt, index, clean_addr, scale, s->be_data);
3688             } else {
3689                 do_vec_st(s, rt, index, clean_addr, scale, s->be_data);
3690             }
3691         }
3692         tcg_gen_add_i64(clean_addr, clean_addr, tcg_ebytes);
3693         rt = (rt + 1) % 32;
3694     }
3695     tcg_temp_free_i64(tcg_ebytes);
3696
3697     if (is_postidx) {
3698         if (rm == 31) {
3699             tcg_gen_addi_i64(tcg_rn, tcg_rn, selem * ebytes);
3700         } else {
3701             tcg_gen_add_i64(tcg_rn, tcg_rn, cpu_reg(s, rm));
3702         }
3703     }
3704 }
3705
3706 /* Loads and stores */
3707 static void disas_ldst(DisasContext *s, uint32_t insn)
3708 {
3709     switch (extract32(insn, 24, 6)) {
3710     case 0x08: /* Load/store exclusive */
3711         disas_ldst_excl(s, insn);
3712         break;
3713     case 0x18: case 0x1c: /* Load register (literal) */
3714         disas_ld_lit(s, insn);
3715         break;
3716     case 0x28: case 0x29:
3717     case 0x2c: case 0x2d: /* Load/store pair (all forms) */
3718         disas_ldst_pair(s, insn);
3719         break;
3720     case 0x38: case 0x39:
3721     case 0x3c: case 0x3d: /* Load/store register (all forms) */
3722         disas_ldst_reg(s, insn);
3723         break;
3724     case 0x0c: /* AdvSIMD load/store multiple structures */
3725         disas_ldst_multiple_struct(s, insn);
3726         break;
3727     case 0x0d: /* AdvSIMD load/store single structure */
3728         disas_ldst_single_struct(s, insn);
3729         break;
3730     case 0x19: /* LDAPR/STLR (unscaled immediate) */
3731         if (extract32(insn, 10, 2) != 0 ||
3732             extract32(insn, 21, 1) != 0) {
3733             unallocated_encoding(s);
3734             break;
3735         }
3736         disas_ldst_ldapr_stlr(s, insn);
3737         break;
3738     default:
3739         unallocated_encoding(s);
3740         break;
3741     }
3742 }
3743
3744 /* PC-rel. addressing
3745  *   31  30   29 28       24 23                5 4    0
3746  * +----+-------+-----------+-------------------+------+
3747  * | op | immlo | 1 0 0 0 0 |       immhi       |  Rd  |
3748  * +----+-------+-----------+-------------------+------+
3749  */
3750 static void disas_pc_rel_adr(DisasContext *s, uint32_t insn)
3751 {
3752     unsigned int page, rd;
3753     uint64_t base;
3754     uint64_t offset;
3755
3756     page = extract32(insn, 31, 1);
3757     /* SignExtend(immhi:immlo) -> offset */
3758     offset = sextract64(insn, 5, 19);
3759     offset = offset << 2 | extract32(insn, 29, 2);
3760     rd = extract32(insn, 0, 5);
3761     base = s->pc_curr;
3762
3763     if (page) {
3764         /* ADRP (page based) */
3765         base &= ~0xfff;
3766         offset <<= 12;
3767     }
3768
3769     tcg_gen_movi_i64(cpu_reg(s, rd), base + offset);
3770 }
3771
3772 /*
3773  * Add/subtract (immediate)
3774  *
3775  *  31 30 29 28       24 23 22 21         10 9   5 4   0
3776  * +--+--+--+-----------+-----+-------------+-----+-----+
3777  * |sf|op| S| 1 0 0 0 1 |shift|    imm12    |  Rn | Rd  |
3778  * +--+--+--+-----------+-----+-------------+-----+-----+
3779  *
3780  *    sf: 0 -> 32bit, 1 -> 64bit
3781  *    op: 0 -> add  , 1 -> sub
3782  *     S: 1 -> set flags
3783  * shift: 00 -> LSL imm by 0, 01 -> LSL imm by 12
3784  */
3785 static void disas_add_sub_imm(DisasContext *s, uint32_t insn)
3786 {
3787     int rd = extract32(insn, 0, 5);
3788     int rn = extract32(insn, 5, 5);
3789     uint64_t imm = extract32(insn, 10, 12);
3790     int shift = extract32(insn, 22, 2);
3791     bool setflags = extract32(insn, 29, 1);
3792     bool sub_op = extract32(insn, 30, 1);
3793     bool is_64bit = extract32(insn, 31, 1);
3794
3795     TCGv_i64 tcg_rn = cpu_reg_sp(s, rn);
3796     TCGv_i64 tcg_rd = setflags ? cpu_reg(s, rd) : cpu_reg_sp(s, rd);
3797     TCGv_i64 tcg_result;
3798
3799     switch (shift) {
3800     case 0x0:
3801         break;
3802     case 0x1:
3803         imm <<= 12;
3804         break;
3805     default:
3806         unallocated_encoding(s);
3807         return;
3808     }
3809
3810     tcg_result = tcg_temp_new_i64();
3811     if (!setflags) {
3812         if (sub_op) {
3813             tcg_gen_subi_i64(tcg_result, tcg_rn, imm);
3814         } else {
3815             tcg_gen_addi_i64(tcg_result, tcg_rn, imm);
3816         }
3817     } else {
3818         TCGv_i64 tcg_imm = tcg_const_i64(imm);
3819         if (sub_op) {
3820             gen_sub_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
3821         } else {
3822             gen_add_CC(is_64bit, tcg_result, tcg_rn, tcg_imm);
3823         }
3824         tcg_temp_free_i64(tcg_imm);
3825     }
3826
3827     if (is_64bit) {
3828         tcg_gen_mov_i64(tcg_rd, tcg_result);
3829     } else {
3830         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
3831     }
3832
3833     tcg_temp_free_i64(tcg_result);
3834 }
3835
3836 /* The input should be a value in the bottom e bits (with higher
3837  * bits zero); returns that value replicated into every element
3838  * of size e in a 64 bit integer.
3839  */
3840 static uint64_t bitfield_replicate(uint64_t mask, unsigned int e)
3841 {
3842     assert(e != 0);
3843     while (e < 64) {
3844         mask |= mask << e;
3845         e *= 2;
3846     }
3847     return mask;
3848 }
3849
3850 /* Return a value with the bottom len bits set (where 0 < len <= 64) */
3851 static inline uint64_t bitmask64(unsigned int length)
3852 {
3853     assert(length > 0 && length <= 64);
3854     return ~0ULL >> (64 - length);
3855 }
3856
3857 /* Simplified variant of pseudocode DecodeBitMasks() for the case where we
3858  * only require the wmask. Returns false if the imms/immr/immn are a reserved
3859  * value (ie should cause a guest UNDEF exception), and true if they are
3860  * valid, in which case the decoded bit pattern is written to result.
3861  */
3862 bool logic_imm_decode_wmask(uint64_t *result, unsigned int immn,
3863                             unsigned int imms, unsigned int immr)
3864 {
3865     uint64_t mask;
3866     unsigned e, levels, s, r;
3867     int len;
3868
3869     assert(immn < 2 && imms < 64 && immr < 64);
3870
3871     /* The bit patterns we create here are 64 bit patterns which
3872      * are vectors of identical elements of size e = 2, 4, 8, 16, 32 or
3873      * 64 bits each. Each element contains the same value: a run
3874      * of between 1 and e-1 non-zero bits, rotated within the
3875      * element by between 0 and e-1 bits.
3876      *
3877      * The element size and run length are encoded into immn (1 bit)
3878      * and imms (6 bits) as follows:
3879      * 64 bit elements: immn = 1, imms = <length of run - 1>
3880      * 32 bit elements: immn = 0, imms = 0 : <length of run - 1>
3881      * 16 bit elements: immn = 0, imms = 10 : <length of run - 1>
3882      *  8 bit elements: immn = 0, imms = 110 : <length of run - 1>
3883      *  4 bit elements: immn = 0, imms = 1110 : <length of run - 1>
3884      *  2 bit elements: immn = 0, imms = 11110 : <length of run - 1>
3885      * Notice that immn = 0, imms = 11111x is the only combination
3886      * not covered by one of the above options; this is reserved.
3887      * Further, <length of run - 1> all-ones is a reserved pattern.
3888      *
3889      * In all cases the rotation is by immr % e (and immr is 6 bits).
3890      */
3891
3892     /* First determine the element size */
3893     len = 31 - clz32((immn << 6) | (~imms & 0x3f));
3894     if (len < 1) {
3895         /* This is the immn == 0, imms == 0x11111x case */
3896         return false;
3897     }
3898     e = 1 << len;
3899
3900     levels = e - 1;
3901     s = imms & levels;
3902     r = immr & levels;
3903
3904     if (s == levels) {
3905         /* <length of run - 1> mustn't be all-ones. */
3906         return false;
3907     }
3908
3909     /* Create the value of one element: s+1 set bits rotated
3910      * by r within the element (which is e bits wide)...
3911      */
3912     mask = bitmask64(s + 1);
3913     if (r) {
3914         mask = (mask >> r) | (mask << (e - r));
3915         mask &= bitmask64(e);
3916     }
3917     /* ...then replicate the element over the whole 64 bit value */
3918     mask = bitfield_replicate(mask, e);
3919     *result = mask;
3920     return true;
3921 }
3922
3923 /* Logical (immediate)
3924  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
3925  * +----+-----+-------------+---+------+------+------+------+
3926  * | sf | opc | 1 0 0 1 0 0 | N | immr | imms |  Rn  |  Rd  |
3927  * +----+-----+-------------+---+------+------+------+------+
3928  */
3929 static void disas_logic_imm(DisasContext *s, uint32_t insn)
3930 {
3931     unsigned int sf, opc, is_n, immr, imms, rn, rd;
3932     TCGv_i64 tcg_rd, tcg_rn;
3933     uint64_t wmask;
3934     bool is_and = false;
3935
3936     sf = extract32(insn, 31, 1);
3937     opc = extract32(insn, 29, 2);
3938     is_n = extract32(insn, 22, 1);
3939     immr = extract32(insn, 16, 6);
3940     imms = extract32(insn, 10, 6);
3941     rn = extract32(insn, 5, 5);
3942     rd = extract32(insn, 0, 5);
3943
3944     if (!sf && is_n) {
3945         unallocated_encoding(s);
3946         return;
3947     }
3948
3949     if (opc == 0x3) { /* ANDS */
3950         tcg_rd = cpu_reg(s, rd);
3951     } else {
3952         tcg_rd = cpu_reg_sp(s, rd);
3953     }
3954     tcg_rn = cpu_reg(s, rn);
3955
3956     if (!logic_imm_decode_wmask(&wmask, is_n, imms, immr)) {
3957         /* some immediate field values are reserved */
3958         unallocated_encoding(s);
3959         return;
3960     }
3961
3962     if (!sf) {
3963         wmask &= 0xffffffff;
3964     }
3965
3966     switch (opc) {
3967     case 0x3: /* ANDS */
3968     case 0x0: /* AND */
3969         tcg_gen_andi_i64(tcg_rd, tcg_rn, wmask);
3970         is_and = true;
3971         break;
3972     case 0x1: /* ORR */
3973         tcg_gen_ori_i64(tcg_rd, tcg_rn, wmask);
3974         break;
3975     case 0x2: /* EOR */
3976         tcg_gen_xori_i64(tcg_rd, tcg_rn, wmask);
3977         break;
3978     default:
3979         assert(FALSE); /* must handle all above */
3980         break;
3981     }
3982
3983     if (!sf && !is_and) {
3984         /* zero extend final result; we know we can skip this for AND
3985          * since the immediate had the high 32 bits clear.
3986          */
3987         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
3988     }
3989
3990     if (opc == 3) { /* ANDS */
3991         gen_logic_CC(sf, tcg_rd);
3992     }
3993 }
3994
3995 /*
3996  * Move wide (immediate)
3997  *
3998  *  31 30 29 28         23 22 21 20             5 4    0
3999  * +--+-----+-------------+-----+----------------+------+
4000  * |sf| opc | 1 0 0 1 0 1 |  hw |  imm16         |  Rd  |
4001  * +--+-----+-------------+-----+----------------+------+
4002  *
4003  * sf: 0 -> 32 bit, 1 -> 64 bit
4004  * opc: 00 -> N, 10 -> Z, 11 -> K
4005  * hw: shift/16 (0,16, and sf only 32, 48)
4006  */
4007 static void disas_movw_imm(DisasContext *s, uint32_t insn)
4008 {
4009     int rd = extract32(insn, 0, 5);
4010     uint64_t imm = extract32(insn, 5, 16);
4011     int sf = extract32(insn, 31, 1);
4012     int opc = extract32(insn, 29, 2);
4013     int pos = extract32(insn, 21, 2) << 4;
4014     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4015     TCGv_i64 tcg_imm;
4016
4017     if (!sf && (pos >= 32)) {
4018         unallocated_encoding(s);
4019         return;
4020     }
4021
4022     switch (opc) {
4023     case 0: /* MOVN */
4024     case 2: /* MOVZ */
4025         imm <<= pos;
4026         if (opc == 0) {
4027             imm = ~imm;
4028         }
4029         if (!sf) {
4030             imm &= 0xffffffffu;
4031         }
4032         tcg_gen_movi_i64(tcg_rd, imm);
4033         break;
4034     case 3: /* MOVK */
4035         tcg_imm = tcg_const_i64(imm);
4036         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_imm, pos, 16);
4037         tcg_temp_free_i64(tcg_imm);
4038         if (!sf) {
4039             tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4040         }
4041         break;
4042     default:
4043         unallocated_encoding(s);
4044         break;
4045     }
4046 }
4047
4048 /* Bitfield
4049  *   31  30 29 28         23 22  21  16 15  10 9    5 4    0
4050  * +----+-----+-------------+---+------+------+------+------+
4051  * | sf | opc | 1 0 0 1 1 0 | N | immr | imms |  Rn  |  Rd  |
4052  * +----+-----+-------------+---+------+------+------+------+
4053  */
4054 static void disas_bitfield(DisasContext *s, uint32_t insn)
4055 {
4056     unsigned int sf, n, opc, ri, si, rn, rd, bitsize, pos, len;
4057     TCGv_i64 tcg_rd, tcg_tmp;
4058
4059     sf = extract32(insn, 31, 1);
4060     opc = extract32(insn, 29, 2);
4061     n = extract32(insn, 22, 1);
4062     ri = extract32(insn, 16, 6);
4063     si = extract32(insn, 10, 6);
4064     rn = extract32(insn, 5, 5);
4065     rd = extract32(insn, 0, 5);
4066     bitsize = sf ? 64 : 32;
4067
4068     if (sf != n || ri >= bitsize || si >= bitsize || opc > 2) {
4069         unallocated_encoding(s);
4070         return;
4071     }
4072
4073     tcg_rd = cpu_reg(s, rd);
4074
4075     /* Suppress the zero-extend for !sf.  Since RI and SI are constrained
4076        to be smaller than bitsize, we'll never reference data outside the
4077        low 32-bits anyway.  */
4078     tcg_tmp = read_cpu_reg(s, rn, 1);
4079
4080     /* Recognize simple(r) extractions.  */
4081     if (si >= ri) {
4082         /* Wd<s-r:0> = Wn<s:r> */
4083         len = (si - ri) + 1;
4084         if (opc == 0) { /* SBFM: ASR, SBFX, SXTB, SXTH, SXTW */
4085             tcg_gen_sextract_i64(tcg_rd, tcg_tmp, ri, len);
4086             goto done;
4087         } else if (opc == 2) { /* UBFM: UBFX, LSR, UXTB, UXTH */
4088             tcg_gen_extract_i64(tcg_rd, tcg_tmp, ri, len);
4089             return;
4090         }
4091         /* opc == 1, BFXIL fall through to deposit */
4092         tcg_gen_shri_i64(tcg_tmp, tcg_tmp, ri);
4093         pos = 0;
4094     } else {
4095         /* Handle the ri > si case with a deposit
4096          * Wd<32+s-r,32-r> = Wn<s:0>
4097          */
4098         len = si + 1;
4099         pos = (bitsize - ri) & (bitsize - 1);
4100     }
4101
4102     if (opc == 0 && len < ri) {
4103         /* SBFM: sign extend the destination field from len to fill
4104            the balance of the word.  Let the deposit below insert all
4105            of those sign bits.  */
4106         tcg_gen_sextract_i64(tcg_tmp, tcg_tmp, 0, len);
4107         len = ri;
4108     }
4109
4110     if (opc == 1) { /* BFM, BFXIL */
4111         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_tmp, pos, len);
4112     } else {
4113         /* SBFM or UBFM: We start with zero, and we haven't modified
4114            any bits outside bitsize, therefore the zero-extension
4115            below is unneeded.  */
4116         tcg_gen_deposit_z_i64(tcg_rd, tcg_tmp, pos, len);
4117         return;
4118     }
4119
4120  done:
4121     if (!sf) { /* zero extend final result */
4122         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4123     }
4124 }
4125
4126 /* Extract
4127  *   31  30  29 28         23 22   21  20  16 15    10 9    5 4    0
4128  * +----+------+-------------+---+----+------+--------+------+------+
4129  * | sf | op21 | 1 0 0 1 1 1 | N | o0 |  Rm  |  imms  |  Rn  |  Rd  |
4130  * +----+------+-------------+---+----+------+--------+------+------+
4131  */
4132 static void disas_extract(DisasContext *s, uint32_t insn)
4133 {
4134     unsigned int sf, n, rm, imm, rn, rd, bitsize, op21, op0;
4135
4136     sf = extract32(insn, 31, 1);
4137     n = extract32(insn, 22, 1);
4138     rm = extract32(insn, 16, 5);
4139     imm = extract32(insn, 10, 6);
4140     rn = extract32(insn, 5, 5);
4141     rd = extract32(insn, 0, 5);
4142     op21 = extract32(insn, 29, 2);
4143     op0 = extract32(insn, 21, 1);
4144     bitsize = sf ? 64 : 32;
4145
4146     if (sf != n || op21 || op0 || imm >= bitsize) {
4147         unallocated_encoding(s);
4148     } else {
4149         TCGv_i64 tcg_rd, tcg_rm, tcg_rn;
4150
4151         tcg_rd = cpu_reg(s, rd);
4152
4153         if (unlikely(imm == 0)) {
4154             /* tcg shl_i32/shl_i64 is undefined for 32/64 bit shifts,
4155              * so an extract from bit 0 is a special case.
4156              */
4157             if (sf) {
4158                 tcg_gen_mov_i64(tcg_rd, cpu_reg(s, rm));
4159             } else {
4160                 tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rm));
4161             }
4162         } else {
4163             tcg_rm = cpu_reg(s, rm);
4164             tcg_rn = cpu_reg(s, rn);
4165
4166             if (sf) {
4167                 /* Specialization to ROR happens in EXTRACT2.  */
4168                 tcg_gen_extract2_i64(tcg_rd, tcg_rm, tcg_rn, imm);
4169             } else {
4170                 TCGv_i32 t0 = tcg_temp_new_i32();
4171
4172                 tcg_gen_extrl_i64_i32(t0, tcg_rm);
4173                 if (rm == rn) {
4174                     tcg_gen_rotri_i32(t0, t0, imm);
4175                 } else {
4176                     TCGv_i32 t1 = tcg_temp_new_i32();
4177                     tcg_gen_extrl_i64_i32(t1, tcg_rn);
4178                     tcg_gen_extract2_i32(t0, t0, t1, imm);
4179                     tcg_temp_free_i32(t1);
4180                 }
4181                 tcg_gen_extu_i32_i64(tcg_rd, t0);
4182                 tcg_temp_free_i32(t0);
4183             }
4184         }
4185     }
4186 }
4187
4188 /* Data processing - immediate */
4189 static void disas_data_proc_imm(DisasContext *s, uint32_t insn)
4190 {
4191     switch (extract32(insn, 23, 6)) {
4192     case 0x20: case 0x21: /* PC-rel. addressing */
4193         disas_pc_rel_adr(s, insn);
4194         break;
4195     case 0x22: case 0x23: /* Add/subtract (immediate) */
4196         disas_add_sub_imm(s, insn);
4197         break;
4198     case 0x24: /* Logical (immediate) */
4199         disas_logic_imm(s, insn);
4200         break;
4201     case 0x25: /* Move wide (immediate) */
4202         disas_movw_imm(s, insn);
4203         break;
4204     case 0x26: /* Bitfield */
4205         disas_bitfield(s, insn);
4206         break;
4207     case 0x27: /* Extract */
4208         disas_extract(s, insn);
4209         break;
4210     default:
4211         unallocated_encoding(s);
4212         break;
4213     }
4214 }
4215
4216 /* Shift a TCGv src by TCGv shift_amount, put result in dst.
4217  * Note that it is the caller's responsibility to ensure that the
4218  * shift amount is in range (ie 0..31 or 0..63) and provide the ARM
4219  * mandated semantics for out of range shifts.
4220  */
4221 static void shift_reg(TCGv_i64 dst, TCGv_i64 src, int sf,
4222                       enum a64_shift_type shift_type, TCGv_i64 shift_amount)
4223 {
4224     switch (shift_type) {
4225     case A64_SHIFT_TYPE_LSL:
4226         tcg_gen_shl_i64(dst, src, shift_amount);
4227         break;
4228     case A64_SHIFT_TYPE_LSR:
4229         tcg_gen_shr_i64(dst, src, shift_amount);
4230         break;
4231     case A64_SHIFT_TYPE_ASR:
4232         if (!sf) {
4233             tcg_gen_ext32s_i64(dst, src);
4234         }
4235         tcg_gen_sar_i64(dst, sf ? src : dst, shift_amount);
4236         break;
4237     case A64_SHIFT_TYPE_ROR:
4238         if (sf) {
4239             tcg_gen_rotr_i64(dst, src, shift_amount);
4240         } else {
4241             TCGv_i32 t0, t1;
4242             t0 = tcg_temp_new_i32();
4243             t1 = tcg_temp_new_i32();
4244             tcg_gen_extrl_i64_i32(t0, src);
4245             tcg_gen_extrl_i64_i32(t1, shift_amount);
4246             tcg_gen_rotr_i32(t0, t0, t1);
4247             tcg_gen_extu_i32_i64(dst, t0);
4248             tcg_temp_free_i32(t0);
4249             tcg_temp_free_i32(t1);
4250         }
4251         break;
4252     default:
4253         assert(FALSE); /* all shift types should be handled */
4254         break;
4255     }
4256
4257     if (!sf) { /* zero extend final result */
4258         tcg_gen_ext32u_i64(dst, dst);
4259     }
4260 }
4261
4262 /* Shift a TCGv src by immediate, put result in dst.
4263  * The shift amount must be in range (this should always be true as the
4264  * relevant instructions will UNDEF on bad shift immediates).
4265  */
4266 static void shift_reg_imm(TCGv_i64 dst, TCGv_i64 src, int sf,
4267                           enum a64_shift_type shift_type, unsigned int shift_i)
4268 {
4269     assert(shift_i < (sf ? 64 : 32));
4270
4271     if (shift_i == 0) {
4272         tcg_gen_mov_i64(dst, src);
4273     } else {
4274         TCGv_i64 shift_const;
4275
4276         shift_const = tcg_const_i64(shift_i);
4277         shift_reg(dst, src, sf, shift_type, shift_const);
4278         tcg_temp_free_i64(shift_const);
4279     }
4280 }
4281
4282 /* Logical (shifted register)
4283  *   31  30 29 28       24 23   22 21  20  16 15    10 9    5 4    0
4284  * +----+-----+-----------+-------+---+------+--------+------+------+
4285  * | sf | opc | 0 1 0 1 0 | shift | N |  Rm  |  imm6  |  Rn  |  Rd  |
4286  * +----+-----+-----------+-------+---+------+--------+------+------+
4287  */
4288 static void disas_logic_reg(DisasContext *s, uint32_t insn)
4289 {
4290     TCGv_i64 tcg_rd, tcg_rn, tcg_rm;
4291     unsigned int sf, opc, shift_type, invert, rm, shift_amount, rn, rd;
4292
4293     sf = extract32(insn, 31, 1);
4294     opc = extract32(insn, 29, 2);
4295     shift_type = extract32(insn, 22, 2);
4296     invert = extract32(insn, 21, 1);
4297     rm = extract32(insn, 16, 5);
4298     shift_amount = extract32(insn, 10, 6);
4299     rn = extract32(insn, 5, 5);
4300     rd = extract32(insn, 0, 5);
4301
4302     if (!sf && (shift_amount & (1 << 5))) {
4303         unallocated_encoding(s);
4304         return;
4305     }
4306
4307     tcg_rd = cpu_reg(s, rd);
4308
4309     if (opc == 1 && shift_amount == 0 && shift_type == 0 && rn == 31) {
4310         /* Unshifted ORR and ORN with WZR/XZR is the standard encoding for
4311          * register-register MOV and MVN, so it is worth special casing.
4312          */
4313         tcg_rm = cpu_reg(s, rm);
4314         if (invert) {
4315             tcg_gen_not_i64(tcg_rd, tcg_rm);
4316             if (!sf) {
4317                 tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4318             }
4319         } else {
4320             if (sf) {
4321                 tcg_gen_mov_i64(tcg_rd, tcg_rm);
4322             } else {
4323                 tcg_gen_ext32u_i64(tcg_rd, tcg_rm);
4324             }
4325         }
4326         return;
4327     }
4328
4329     tcg_rm = read_cpu_reg(s, rm, sf);
4330
4331     if (shift_amount) {
4332         shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, shift_amount);
4333     }
4334
4335     tcg_rn = cpu_reg(s, rn);
4336
4337     switch (opc | (invert << 2)) {
4338     case 0: /* AND */
4339     case 3: /* ANDS */
4340         tcg_gen_and_i64(tcg_rd, tcg_rn, tcg_rm);
4341         break;
4342     case 1: /* ORR */
4343         tcg_gen_or_i64(tcg_rd, tcg_rn, tcg_rm);
4344         break;
4345     case 2: /* EOR */
4346         tcg_gen_xor_i64(tcg_rd, tcg_rn, tcg_rm);
4347         break;
4348     case 4: /* BIC */
4349     case 7: /* BICS */
4350         tcg_gen_andc_i64(tcg_rd, tcg_rn, tcg_rm);
4351         break;
4352     case 5: /* ORN */
4353         tcg_gen_orc_i64(tcg_rd, tcg_rn, tcg_rm);
4354         break;
4355     case 6: /* EON */
4356         tcg_gen_eqv_i64(tcg_rd, tcg_rn, tcg_rm);
4357         break;
4358     default:
4359         assert(FALSE);
4360         break;
4361     }
4362
4363     if (!sf) {
4364         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4365     }
4366
4367     if (opc == 3) {
4368         gen_logic_CC(sf, tcg_rd);
4369     }
4370 }
4371
4372 /*
4373  * Add/subtract (extended register)
4374  *
4375  *  31|30|29|28       24|23 22|21|20   16|15  13|12  10|9  5|4  0|
4376  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
4377  * |sf|op| S| 0 1 0 1 1 | opt | 1|  Rm   |option| imm3 | Rn | Rd |
4378  * +--+--+--+-----------+-----+--+-------+------+------+----+----+
4379  *
4380  *  sf: 0 -> 32bit, 1 -> 64bit
4381  *  op: 0 -> add  , 1 -> sub
4382  *   S: 1 -> set flags
4383  * opt: 00
4384  * option: extension type (see DecodeRegExtend)
4385  * imm3: optional shift to Rm
4386  *
4387  * Rd = Rn + LSL(extend(Rm), amount)
4388  */
4389 static void disas_add_sub_ext_reg(DisasContext *s, uint32_t insn)
4390 {
4391     int rd = extract32(insn, 0, 5);
4392     int rn = extract32(insn, 5, 5);
4393     int imm3 = extract32(insn, 10, 3);
4394     int option = extract32(insn, 13, 3);
4395     int rm = extract32(insn, 16, 5);
4396     int opt = extract32(insn, 22, 2);
4397     bool setflags = extract32(insn, 29, 1);
4398     bool sub_op = extract32(insn, 30, 1);
4399     bool sf = extract32(insn, 31, 1);
4400
4401     TCGv_i64 tcg_rm, tcg_rn; /* temps */
4402     TCGv_i64 tcg_rd;
4403     TCGv_i64 tcg_result;
4404
4405     if (imm3 > 4 || opt != 0) {
4406         unallocated_encoding(s);
4407         return;
4408     }
4409
4410     /* non-flag setting ops may use SP */
4411     if (!setflags) {
4412         tcg_rd = cpu_reg_sp(s, rd);
4413     } else {
4414         tcg_rd = cpu_reg(s, rd);
4415     }
4416     tcg_rn = read_cpu_reg_sp(s, rn, sf);
4417
4418     tcg_rm = read_cpu_reg(s, rm, sf);
4419     ext_and_shift_reg(tcg_rm, tcg_rm, option, imm3);
4420
4421     tcg_result = tcg_temp_new_i64();
4422
4423     if (!setflags) {
4424         if (sub_op) {
4425             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
4426         } else {
4427             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
4428         }
4429     } else {
4430         if (sub_op) {
4431             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
4432         } else {
4433             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
4434         }
4435     }
4436
4437     if (sf) {
4438         tcg_gen_mov_i64(tcg_rd, tcg_result);
4439     } else {
4440         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
4441     }
4442
4443     tcg_temp_free_i64(tcg_result);
4444 }
4445
4446 /*
4447  * Add/subtract (shifted register)
4448  *
4449  *  31 30 29 28       24 23 22 21 20   16 15     10 9    5 4    0
4450  * +--+--+--+-----------+-----+--+-------+---------+------+------+
4451  * |sf|op| S| 0 1 0 1 1 |shift| 0|  Rm   |  imm6   |  Rn  |  Rd  |
4452  * +--+--+--+-----------+-----+--+-------+---------+------+------+
4453  *
4454  *    sf: 0 -> 32bit, 1 -> 64bit
4455  *    op: 0 -> add  , 1 -> sub
4456  *     S: 1 -> set flags
4457  * shift: 00 -> LSL, 01 -> LSR, 10 -> ASR, 11 -> RESERVED
4458  *  imm6: Shift amount to apply to Rm before the add/sub
4459  */
4460 static void disas_add_sub_reg(DisasContext *s, uint32_t insn)
4461 {
4462     int rd = extract32(insn, 0, 5);
4463     int rn = extract32(insn, 5, 5);
4464     int imm6 = extract32(insn, 10, 6);
4465     int rm = extract32(insn, 16, 5);
4466     int shift_type = extract32(insn, 22, 2);
4467     bool setflags = extract32(insn, 29, 1);
4468     bool sub_op = extract32(insn, 30, 1);
4469     bool sf = extract32(insn, 31, 1);
4470
4471     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4472     TCGv_i64 tcg_rn, tcg_rm;
4473     TCGv_i64 tcg_result;
4474
4475     if ((shift_type == 3) || (!sf && (imm6 > 31))) {
4476         unallocated_encoding(s);
4477         return;
4478     }
4479
4480     tcg_rn = read_cpu_reg(s, rn, sf);
4481     tcg_rm = read_cpu_reg(s, rm, sf);
4482
4483     shift_reg_imm(tcg_rm, tcg_rm, sf, shift_type, imm6);
4484
4485     tcg_result = tcg_temp_new_i64();
4486
4487     if (!setflags) {
4488         if (sub_op) {
4489             tcg_gen_sub_i64(tcg_result, tcg_rn, tcg_rm);
4490         } else {
4491             tcg_gen_add_i64(tcg_result, tcg_rn, tcg_rm);
4492         }
4493     } else {
4494         if (sub_op) {
4495             gen_sub_CC(sf, tcg_result, tcg_rn, tcg_rm);
4496         } else {
4497             gen_add_CC(sf, tcg_result, tcg_rn, tcg_rm);
4498         }
4499     }
4500
4501     if (sf) {
4502         tcg_gen_mov_i64(tcg_rd, tcg_result);
4503     } else {
4504         tcg_gen_ext32u_i64(tcg_rd, tcg_result);
4505     }
4506
4507     tcg_temp_free_i64(tcg_result);
4508 }
4509
4510 /* Data-processing (3 source)
4511  *
4512  *    31 30  29 28       24 23 21  20  16  15  14  10 9    5 4    0
4513  *  +--+------+-----------+------+------+----+------+------+------+
4514  *  |sf| op54 | 1 1 0 1 1 | op31 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
4515  *  +--+------+-----------+------+------+----+------+------+------+
4516  */
4517 static void disas_data_proc_3src(DisasContext *s, uint32_t insn)
4518 {
4519     int rd = extract32(insn, 0, 5);
4520     int rn = extract32(insn, 5, 5);
4521     int ra = extract32(insn, 10, 5);
4522     int rm = extract32(insn, 16, 5);
4523     int op_id = (extract32(insn, 29, 3) << 4) |
4524         (extract32(insn, 21, 3) << 1) |
4525         extract32(insn, 15, 1);
4526     bool sf = extract32(insn, 31, 1);
4527     bool is_sub = extract32(op_id, 0, 1);
4528     bool is_high = extract32(op_id, 2, 1);
4529     bool is_signed = false;
4530     TCGv_i64 tcg_op1;
4531     TCGv_i64 tcg_op2;
4532     TCGv_i64 tcg_tmp;
4533
4534     /* Note that op_id is sf:op54:op31:o0 so it includes the 32/64 size flag */
4535     switch (op_id) {
4536     case 0x42: /* SMADDL */
4537     case 0x43: /* SMSUBL */
4538     case 0x44: /* SMULH */
4539         is_signed = true;
4540         break;
4541     case 0x0: /* MADD (32bit) */
4542     case 0x1: /* MSUB (32bit) */
4543     case 0x40: /* MADD (64bit) */
4544     case 0x41: /* MSUB (64bit) */
4545     case 0x4a: /* UMADDL */
4546     case 0x4b: /* UMSUBL */
4547     case 0x4c: /* UMULH */
4548         break;
4549     default:
4550         unallocated_encoding(s);
4551         return;
4552     }
4553
4554     if (is_high) {
4555         TCGv_i64 low_bits = tcg_temp_new_i64(); /* low bits discarded */
4556         TCGv_i64 tcg_rd = cpu_reg(s, rd);
4557         TCGv_i64 tcg_rn = cpu_reg(s, rn);
4558         TCGv_i64 tcg_rm = cpu_reg(s, rm);
4559
4560         if (is_signed) {
4561             tcg_gen_muls2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
4562         } else {
4563             tcg_gen_mulu2_i64(low_bits, tcg_rd, tcg_rn, tcg_rm);
4564         }
4565
4566         tcg_temp_free_i64(low_bits);
4567         return;
4568     }
4569
4570     tcg_op1 = tcg_temp_new_i64();
4571     tcg_op2 = tcg_temp_new_i64();
4572     tcg_tmp = tcg_temp_new_i64();
4573
4574     if (op_id < 0x42) {
4575         tcg_gen_mov_i64(tcg_op1, cpu_reg(s, rn));
4576         tcg_gen_mov_i64(tcg_op2, cpu_reg(s, rm));
4577     } else {
4578         if (is_signed) {
4579             tcg_gen_ext32s_i64(tcg_op1, cpu_reg(s, rn));
4580             tcg_gen_ext32s_i64(tcg_op2, cpu_reg(s, rm));
4581         } else {
4582             tcg_gen_ext32u_i64(tcg_op1, cpu_reg(s, rn));
4583             tcg_gen_ext32u_i64(tcg_op2, cpu_reg(s, rm));
4584         }
4585     }
4586
4587     if (ra == 31 && !is_sub) {
4588         /* Special-case MADD with rA == XZR; it is the standard MUL alias */
4589         tcg_gen_mul_i64(cpu_reg(s, rd), tcg_op1, tcg_op2);
4590     } else {
4591         tcg_gen_mul_i64(tcg_tmp, tcg_op1, tcg_op2);
4592         if (is_sub) {
4593             tcg_gen_sub_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
4594         } else {
4595             tcg_gen_add_i64(cpu_reg(s, rd), cpu_reg(s, ra), tcg_tmp);
4596         }
4597     }
4598
4599     if (!sf) {
4600         tcg_gen_ext32u_i64(cpu_reg(s, rd), cpu_reg(s, rd));
4601     }
4602
4603     tcg_temp_free_i64(tcg_op1);
4604     tcg_temp_free_i64(tcg_op2);
4605     tcg_temp_free_i64(tcg_tmp);
4606 }
4607
4608 /* Add/subtract (with carry)
4609  *  31 30 29 28 27 26 25 24 23 22 21  20  16  15       10  9    5 4   0
4610  * +--+--+--+------------------------+------+-------------+------+-----+
4611  * |sf|op| S| 1  1  0  1  0  0  0  0 |  rm  | 0 0 0 0 0 0 |  Rn  |  Rd |
4612  * +--+--+--+------------------------+------+-------------+------+-----+
4613  */
4614
4615 static void disas_adc_sbc(DisasContext *s, uint32_t insn)
4616 {
4617     unsigned int sf, op, setflags, rm, rn, rd;
4618     TCGv_i64 tcg_y, tcg_rn, tcg_rd;
4619
4620     sf = extract32(insn, 31, 1);
4621     op = extract32(insn, 30, 1);
4622     setflags = extract32(insn, 29, 1);
4623     rm = extract32(insn, 16, 5);
4624     rn = extract32(insn, 5, 5);
4625     rd = extract32(insn, 0, 5);
4626
4627     tcg_rd = cpu_reg(s, rd);
4628     tcg_rn = cpu_reg(s, rn);
4629
4630     if (op) {
4631         tcg_y = new_tmp_a64(s);
4632         tcg_gen_not_i64(tcg_y, cpu_reg(s, rm));
4633     } else {
4634         tcg_y = cpu_reg(s, rm);
4635     }
4636
4637     if (setflags) {
4638         gen_adc_CC(sf, tcg_rd, tcg_rn, tcg_y);
4639     } else {
4640         gen_adc(sf, tcg_rd, tcg_rn, tcg_y);
4641     }
4642 }
4643
4644 /*
4645  * Rotate right into flags
4646  *  31 30 29                21       15          10      5  4      0
4647  * +--+--+--+-----------------+--------+-----------+------+--+------+
4648  * |sf|op| S| 1 1 0 1 0 0 0 0 |  imm6  | 0 0 0 0 1 |  Rn  |o2| mask |
4649  * +--+--+--+-----------------+--------+-----------+------+--+------+
4650  */
4651 static void disas_rotate_right_into_flags(DisasContext *s, uint32_t insn)
4652 {
4653     int mask = extract32(insn, 0, 4);
4654     int o2 = extract32(insn, 4, 1);
4655     int rn = extract32(insn, 5, 5);
4656     int imm6 = extract32(insn, 15, 6);
4657     int sf_op_s = extract32(insn, 29, 3);
4658     TCGv_i64 tcg_rn;
4659     TCGv_i32 nzcv;
4660
4661     if (sf_op_s != 5 || o2 != 0 || !dc_isar_feature(aa64_condm_4, s)) {
4662         unallocated_encoding(s);
4663         return;
4664     }
4665
4666     tcg_rn = read_cpu_reg(s, rn, 1);
4667     tcg_gen_rotri_i64(tcg_rn, tcg_rn, imm6);
4668
4669     nzcv = tcg_temp_new_i32();
4670     tcg_gen_extrl_i64_i32(nzcv, tcg_rn);
4671
4672     if (mask & 8) { /* N */
4673         tcg_gen_shli_i32(cpu_NF, nzcv, 31 - 3);
4674     }
4675     if (mask & 4) { /* Z */
4676         tcg_gen_not_i32(cpu_ZF, nzcv);
4677         tcg_gen_andi_i32(cpu_ZF, cpu_ZF, 4);
4678     }
4679     if (mask & 2) { /* C */
4680         tcg_gen_extract_i32(cpu_CF, nzcv, 1, 1);
4681     }
4682     if (mask & 1) { /* V */
4683         tcg_gen_shli_i32(cpu_VF, nzcv, 31 - 0);
4684     }
4685
4686     tcg_temp_free_i32(nzcv);
4687 }
4688
4689 /*
4690  * Evaluate into flags
4691  *  31 30 29                21        15   14        10      5  4      0
4692  * +--+--+--+-----------------+---------+----+---------+------+--+------+
4693  * |sf|op| S| 1 1 0 1 0 0 0 0 | opcode2 | sz | 0 0 1 0 |  Rn  |o3| mask |
4694  * +--+--+--+-----------------+---------+----+---------+------+--+------+
4695  */
4696 static void disas_evaluate_into_flags(DisasContext *s, uint32_t insn)
4697 {
4698     int o3_mask = extract32(insn, 0, 5);
4699     int rn = extract32(insn, 5, 5);
4700     int o2 = extract32(insn, 15, 6);
4701     int sz = extract32(insn, 14, 1);
4702     int sf_op_s = extract32(insn, 29, 3);
4703     TCGv_i32 tmp;
4704     int shift;
4705
4706     if (sf_op_s != 1 || o2 != 0 || o3_mask != 0xd ||
4707         !dc_isar_feature(aa64_condm_4, s)) {
4708         unallocated_encoding(s);
4709         return;
4710     }
4711     shift = sz ? 16 : 24;  /* SETF16 or SETF8 */
4712
4713     tmp = tcg_temp_new_i32();
4714     tcg_gen_extrl_i64_i32(tmp, cpu_reg(s, rn));
4715     tcg_gen_shli_i32(cpu_NF, tmp, shift);
4716     tcg_gen_shli_i32(cpu_VF, tmp, shift - 1);
4717     tcg_gen_mov_i32(cpu_ZF, cpu_NF);
4718     tcg_gen_xor_i32(cpu_VF, cpu_VF, cpu_NF);
4719     tcg_temp_free_i32(tmp);
4720 }
4721
4722 /* Conditional compare (immediate / register)
4723  *  31 30 29 28 27 26 25 24 23 22 21  20    16 15  12  11  10  9   5  4 3   0
4724  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
4725  * |sf|op| S| 1  1  0  1  0  0  1  0 |imm5/rm | cond |i/r |o2|  Rn  |o3|nzcv |
4726  * +--+--+--+------------------------+--------+------+----+--+------+--+-----+
4727  *        [1]                             y                [0]       [0]
4728  */
4729 static void disas_cc(DisasContext *s, uint32_t insn)
4730 {
4731     unsigned int sf, op, y, cond, rn, nzcv, is_imm;
4732     TCGv_i32 tcg_t0, tcg_t1, tcg_t2;
4733     TCGv_i64 tcg_tmp, tcg_y, tcg_rn;
4734     DisasCompare c;
4735
4736     if (!extract32(insn, 29, 1)) {
4737         unallocated_encoding(s);
4738         return;
4739     }
4740     if (insn & (1 << 10 | 1 << 4)) {
4741         unallocated_encoding(s);
4742         return;
4743     }
4744     sf = extract32(insn, 31, 1);
4745     op = extract32(insn, 30, 1);
4746     is_imm = extract32(insn, 11, 1);
4747     y = extract32(insn, 16, 5); /* y = rm (reg) or imm5 (imm) */
4748     cond = extract32(insn, 12, 4);
4749     rn = extract32(insn, 5, 5);
4750     nzcv = extract32(insn, 0, 4);
4751
4752     /* Set T0 = !COND.  */
4753     tcg_t0 = tcg_temp_new_i32();
4754     arm_test_cc(&c, cond);
4755     tcg_gen_setcondi_i32(tcg_invert_cond(c.cond), tcg_t0, c.value, 0);
4756     arm_free_cc(&c);
4757
4758     /* Load the arguments for the new comparison.  */
4759     if (is_imm) {
4760         tcg_y = new_tmp_a64(s);
4761         tcg_gen_movi_i64(tcg_y, y);
4762     } else {
4763         tcg_y = cpu_reg(s, y);
4764     }
4765     tcg_rn = cpu_reg(s, rn);
4766
4767     /* Set the flags for the new comparison.  */
4768     tcg_tmp = tcg_temp_new_i64();
4769     if (op) {
4770         gen_sub_CC(sf, tcg_tmp, tcg_rn, tcg_y);
4771     } else {
4772         gen_add_CC(sf, tcg_tmp, tcg_rn, tcg_y);
4773     }
4774     tcg_temp_free_i64(tcg_tmp);
4775
4776     /* If COND was false, force the flags to #nzcv.  Compute two masks
4777      * to help with this: T1 = (COND ? 0 : -1), T2 = (COND ? -1 : 0).
4778      * For tcg hosts that support ANDC, we can make do with just T1.
4779      * In either case, allow the tcg optimizer to delete any unused mask.
4780      */
4781     tcg_t1 = tcg_temp_new_i32();
4782     tcg_t2 = tcg_temp_new_i32();
4783     tcg_gen_neg_i32(tcg_t1, tcg_t0);
4784     tcg_gen_subi_i32(tcg_t2, tcg_t0, 1);
4785
4786     if (nzcv & 8) { /* N */
4787         tcg_gen_or_i32(cpu_NF, cpu_NF, tcg_t1);
4788     } else {
4789         if (TCG_TARGET_HAS_andc_i32) {
4790             tcg_gen_andc_i32(cpu_NF, cpu_NF, tcg_t1);
4791         } else {
4792             tcg_gen_and_i32(cpu_NF, cpu_NF, tcg_t2);
4793         }
4794     }
4795     if (nzcv & 4) { /* Z */
4796         if (TCG_TARGET_HAS_andc_i32) {
4797             tcg_gen_andc_i32(cpu_ZF, cpu_ZF, tcg_t1);
4798         } else {
4799             tcg_gen_and_i32(cpu_ZF, cpu_ZF, tcg_t2);
4800         }
4801     } else {
4802         tcg_gen_or_i32(cpu_ZF, cpu_ZF, tcg_t0);
4803     }
4804     if (nzcv & 2) { /* C */
4805         tcg_gen_or_i32(cpu_CF, cpu_CF, tcg_t0);
4806     } else {
4807         if (TCG_TARGET_HAS_andc_i32) {
4808             tcg_gen_andc_i32(cpu_CF, cpu_CF, tcg_t1);
4809         } else {
4810             tcg_gen_and_i32(cpu_CF, cpu_CF, tcg_t2);
4811         }
4812     }
4813     if (nzcv & 1) { /* V */
4814         tcg_gen_or_i32(cpu_VF, cpu_VF, tcg_t1);
4815     } else {
4816         if (TCG_TARGET_HAS_andc_i32) {
4817             tcg_gen_andc_i32(cpu_VF, cpu_VF, tcg_t1);
4818         } else {
4819             tcg_gen_and_i32(cpu_VF, cpu_VF, tcg_t2);
4820         }
4821     }
4822     tcg_temp_free_i32(tcg_t0);
4823     tcg_temp_free_i32(tcg_t1);
4824     tcg_temp_free_i32(tcg_t2);
4825 }
4826
4827 /* Conditional select
4828  *   31   30  29  28             21 20  16 15  12 11 10 9    5 4    0
4829  * +----+----+---+-----------------+------+------+-----+------+------+
4830  * | sf | op | S | 1 1 0 1 0 1 0 0 |  Rm  | cond | op2 |  Rn  |  Rd  |
4831  * +----+----+---+-----------------+------+------+-----+------+------+
4832  */
4833 static void disas_cond_select(DisasContext *s, uint32_t insn)
4834 {
4835     unsigned int sf, else_inv, rm, cond, else_inc, rn, rd;
4836     TCGv_i64 tcg_rd, zero;
4837     DisasCompare64 c;
4838
4839     if (extract32(insn, 29, 1) || extract32(insn, 11, 1)) {
4840         /* S == 1 or op2<1> == 1 */
4841         unallocated_encoding(s);
4842         return;
4843     }
4844     sf = extract32(insn, 31, 1);
4845     else_inv = extract32(insn, 30, 1);
4846     rm = extract32(insn, 16, 5);
4847     cond = extract32(insn, 12, 4);
4848     else_inc = extract32(insn, 10, 1);
4849     rn = extract32(insn, 5, 5);
4850     rd = extract32(insn, 0, 5);
4851
4852     tcg_rd = cpu_reg(s, rd);
4853
4854     a64_test_cc(&c, cond);
4855     zero = tcg_const_i64(0);
4856
4857     if (rn == 31 && rm == 31 && (else_inc ^ else_inv)) {
4858         /* CSET & CSETM.  */
4859         tcg_gen_setcond_i64(tcg_invert_cond(c.cond), tcg_rd, c.value, zero);
4860         if (else_inv) {
4861             tcg_gen_neg_i64(tcg_rd, tcg_rd);
4862         }
4863     } else {
4864         TCGv_i64 t_true = cpu_reg(s, rn);
4865         TCGv_i64 t_false = read_cpu_reg(s, rm, 1);
4866         if (else_inv && else_inc) {
4867             tcg_gen_neg_i64(t_false, t_false);
4868         } else if (else_inv) {
4869             tcg_gen_not_i64(t_false, t_false);
4870         } else if (else_inc) {
4871             tcg_gen_addi_i64(t_false, t_false, 1);
4872         }
4873         tcg_gen_movcond_i64(c.cond, tcg_rd, c.value, zero, t_true, t_false);
4874     }
4875
4876     tcg_temp_free_i64(zero);
4877     a64_free_cc(&c);
4878
4879     if (!sf) {
4880         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
4881     }
4882 }
4883
4884 static void handle_clz(DisasContext *s, unsigned int sf,
4885                        unsigned int rn, unsigned int rd)
4886 {
4887     TCGv_i64 tcg_rd, tcg_rn;
4888     tcg_rd = cpu_reg(s, rd);
4889     tcg_rn = cpu_reg(s, rn);
4890
4891     if (sf) {
4892         tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
4893     } else {
4894         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4895         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4896         tcg_gen_clzi_i32(tcg_tmp32, tcg_tmp32, 32);
4897         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4898         tcg_temp_free_i32(tcg_tmp32);
4899     }
4900 }
4901
4902 static void handle_cls(DisasContext *s, unsigned int sf,
4903                        unsigned int rn, unsigned int rd)
4904 {
4905     TCGv_i64 tcg_rd, tcg_rn;
4906     tcg_rd = cpu_reg(s, rd);
4907     tcg_rn = cpu_reg(s, rn);
4908
4909     if (sf) {
4910         tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
4911     } else {
4912         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4913         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4914         tcg_gen_clrsb_i32(tcg_tmp32, tcg_tmp32);
4915         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4916         tcg_temp_free_i32(tcg_tmp32);
4917     }
4918 }
4919
4920 static void handle_rbit(DisasContext *s, unsigned int sf,
4921                         unsigned int rn, unsigned int rd)
4922 {
4923     TCGv_i64 tcg_rd, tcg_rn;
4924     tcg_rd = cpu_reg(s, rd);
4925     tcg_rn = cpu_reg(s, rn);
4926
4927     if (sf) {
4928         gen_helper_rbit64(tcg_rd, tcg_rn);
4929     } else {
4930         TCGv_i32 tcg_tmp32 = tcg_temp_new_i32();
4931         tcg_gen_extrl_i64_i32(tcg_tmp32, tcg_rn);
4932         gen_helper_rbit(tcg_tmp32, tcg_tmp32);
4933         tcg_gen_extu_i32_i64(tcg_rd, tcg_tmp32);
4934         tcg_temp_free_i32(tcg_tmp32);
4935     }
4936 }
4937
4938 /* REV with sf==1, opcode==3 ("REV64") */
4939 static void handle_rev64(DisasContext *s, unsigned int sf,
4940                          unsigned int rn, unsigned int rd)
4941 {
4942     if (!sf) {
4943         unallocated_encoding(s);
4944         return;
4945     }
4946     tcg_gen_bswap64_i64(cpu_reg(s, rd), cpu_reg(s, rn));
4947 }
4948
4949 /* REV with sf==0, opcode==2
4950  * REV32 (sf==1, opcode==2)
4951  */
4952 static void handle_rev32(DisasContext *s, unsigned int sf,
4953                          unsigned int rn, unsigned int rd)
4954 {
4955     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4956
4957     if (sf) {
4958         TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4959         TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
4960
4961         /* bswap32_i64 requires zero high word */
4962         tcg_gen_ext32u_i64(tcg_tmp, tcg_rn);
4963         tcg_gen_bswap32_i64(tcg_rd, tcg_tmp);
4964         tcg_gen_shri_i64(tcg_tmp, tcg_rn, 32);
4965         tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
4966         tcg_gen_concat32_i64(tcg_rd, tcg_rd, tcg_tmp);
4967
4968         tcg_temp_free_i64(tcg_tmp);
4969     } else {
4970         tcg_gen_ext32u_i64(tcg_rd, cpu_reg(s, rn));
4971         tcg_gen_bswap32_i64(tcg_rd, tcg_rd);
4972     }
4973 }
4974
4975 /* REV16 (opcode==1) */
4976 static void handle_rev16(DisasContext *s, unsigned int sf,
4977                          unsigned int rn, unsigned int rd)
4978 {
4979     TCGv_i64 tcg_rd = cpu_reg(s, rd);
4980     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
4981     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
4982     TCGv_i64 mask = tcg_const_i64(sf ? 0x00ff00ff00ff00ffull : 0x00ff00ff);
4983
4984     tcg_gen_shri_i64(tcg_tmp, tcg_rn, 8);
4985     tcg_gen_and_i64(tcg_rd, tcg_rn, mask);
4986     tcg_gen_and_i64(tcg_tmp, tcg_tmp, mask);
4987     tcg_gen_shli_i64(tcg_rd, tcg_rd, 8);
4988     tcg_gen_or_i64(tcg_rd, tcg_rd, tcg_tmp);
4989
4990     tcg_temp_free_i64(mask);
4991     tcg_temp_free_i64(tcg_tmp);
4992 }
4993
4994 /* Data-processing (1 source)
4995  *   31  30  29  28             21 20     16 15    10 9    5 4    0
4996  * +----+---+---+-----------------+---------+--------+------+------+
4997  * | sf | 1 | S | 1 1 0 1 0 1 1 0 | opcode2 | opcode |  Rn  |  Rd  |
4998  * +----+---+---+-----------------+---------+--------+------+------+
4999  */
5000 static void disas_data_proc_1src(DisasContext *s, uint32_t insn)
5001 {
5002     unsigned int sf, opcode, opcode2, rn, rd;
5003     TCGv_i64 tcg_rd;
5004
5005     if (extract32(insn, 29, 1)) {
5006         unallocated_encoding(s);
5007         return;
5008     }
5009
5010     sf = extract32(insn, 31, 1);
5011     opcode = extract32(insn, 10, 6);
5012     opcode2 = extract32(insn, 16, 5);
5013     rn = extract32(insn, 5, 5);
5014     rd = extract32(insn, 0, 5);
5015
5016 #define MAP(SF, O2, O1) ((SF) | (O1 << 1) | (O2 << 7))
5017
5018     switch (MAP(sf, opcode2, opcode)) {
5019     case MAP(0, 0x00, 0x00): /* RBIT */
5020     case MAP(1, 0x00, 0x00):
5021         handle_rbit(s, sf, rn, rd);
5022         break;
5023     case MAP(0, 0x00, 0x01): /* REV16 */
5024     case MAP(1, 0x00, 0x01):
5025         handle_rev16(s, sf, rn, rd);
5026         break;
5027     case MAP(0, 0x00, 0x02): /* REV/REV32 */
5028     case MAP(1, 0x00, 0x02):
5029         handle_rev32(s, sf, rn, rd);
5030         break;
5031     case MAP(1, 0x00, 0x03): /* REV64 */
5032         handle_rev64(s, sf, rn, rd);
5033         break;
5034     case MAP(0, 0x00, 0x04): /* CLZ */
5035     case MAP(1, 0x00, 0x04):
5036         handle_clz(s, sf, rn, rd);
5037         break;
5038     case MAP(0, 0x00, 0x05): /* CLS */
5039     case MAP(1, 0x00, 0x05):
5040         handle_cls(s, sf, rn, rd);
5041         break;
5042     case MAP(1, 0x01, 0x00): /* PACIA */
5043         if (s->pauth_active) {
5044             tcg_rd = cpu_reg(s, rd);
5045             gen_helper_pacia(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5046         } else if (!dc_isar_feature(aa64_pauth, s)) {
5047             goto do_unallocated;
5048         }
5049         break;
5050     case MAP(1, 0x01, 0x01): /* PACIB */
5051         if (s->pauth_active) {
5052             tcg_rd = cpu_reg(s, rd);
5053             gen_helper_pacib(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5054         } else if (!dc_isar_feature(aa64_pauth, s)) {
5055             goto do_unallocated;
5056         }
5057         break;
5058     case MAP(1, 0x01, 0x02): /* PACDA */
5059         if (s->pauth_active) {
5060             tcg_rd = cpu_reg(s, rd);
5061             gen_helper_pacda(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5062         } else if (!dc_isar_feature(aa64_pauth, s)) {
5063             goto do_unallocated;
5064         }
5065         break;
5066     case MAP(1, 0x01, 0x03): /* PACDB */
5067         if (s->pauth_active) {
5068             tcg_rd = cpu_reg(s, rd);
5069             gen_helper_pacdb(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5070         } else if (!dc_isar_feature(aa64_pauth, s)) {
5071             goto do_unallocated;
5072         }
5073         break;
5074     case MAP(1, 0x01, 0x04): /* AUTIA */
5075         if (s->pauth_active) {
5076             tcg_rd = cpu_reg(s, rd);
5077             gen_helper_autia(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5078         } else if (!dc_isar_feature(aa64_pauth, s)) {
5079             goto do_unallocated;
5080         }
5081         break;
5082     case MAP(1, 0x01, 0x05): /* AUTIB */
5083         if (s->pauth_active) {
5084             tcg_rd = cpu_reg(s, rd);
5085             gen_helper_autib(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5086         } else if (!dc_isar_feature(aa64_pauth, s)) {
5087             goto do_unallocated;
5088         }
5089         break;
5090     case MAP(1, 0x01, 0x06): /* AUTDA */
5091         if (s->pauth_active) {
5092             tcg_rd = cpu_reg(s, rd);
5093             gen_helper_autda(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5094         } else if (!dc_isar_feature(aa64_pauth, s)) {
5095             goto do_unallocated;
5096         }
5097         break;
5098     case MAP(1, 0x01, 0x07): /* AUTDB */
5099         if (s->pauth_active) {
5100             tcg_rd = cpu_reg(s, rd);
5101             gen_helper_autdb(tcg_rd, cpu_env, tcg_rd, cpu_reg_sp(s, rn));
5102         } else if (!dc_isar_feature(aa64_pauth, s)) {
5103             goto do_unallocated;
5104         }
5105         break;
5106     case MAP(1, 0x01, 0x08): /* PACIZA */
5107         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5108             goto do_unallocated;
5109         } else if (s->pauth_active) {
5110             tcg_rd = cpu_reg(s, rd);
5111             gen_helper_pacia(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5112         }
5113         break;
5114     case MAP(1, 0x01, 0x09): /* PACIZB */
5115         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5116             goto do_unallocated;
5117         } else if (s->pauth_active) {
5118             tcg_rd = cpu_reg(s, rd);
5119             gen_helper_pacib(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5120         }
5121         break;
5122     case MAP(1, 0x01, 0x0a): /* PACDZA */
5123         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5124             goto do_unallocated;
5125         } else if (s->pauth_active) {
5126             tcg_rd = cpu_reg(s, rd);
5127             gen_helper_pacda(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5128         }
5129         break;
5130     case MAP(1, 0x01, 0x0b): /* PACDZB */
5131         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5132             goto do_unallocated;
5133         } else if (s->pauth_active) {
5134             tcg_rd = cpu_reg(s, rd);
5135             gen_helper_pacdb(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5136         }
5137         break;
5138     case MAP(1, 0x01, 0x0c): /* AUTIZA */
5139         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5140             goto do_unallocated;
5141         } else if (s->pauth_active) {
5142             tcg_rd = cpu_reg(s, rd);
5143             gen_helper_autia(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5144         }
5145         break;
5146     case MAP(1, 0x01, 0x0d): /* AUTIZB */
5147         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5148             goto do_unallocated;
5149         } else if (s->pauth_active) {
5150             tcg_rd = cpu_reg(s, rd);
5151             gen_helper_autib(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5152         }
5153         break;
5154     case MAP(1, 0x01, 0x0e): /* AUTDZA */
5155         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5156             goto do_unallocated;
5157         } else if (s->pauth_active) {
5158             tcg_rd = cpu_reg(s, rd);
5159             gen_helper_autda(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5160         }
5161         break;
5162     case MAP(1, 0x01, 0x0f): /* AUTDZB */
5163         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5164             goto do_unallocated;
5165         } else if (s->pauth_active) {
5166             tcg_rd = cpu_reg(s, rd);
5167             gen_helper_autdb(tcg_rd, cpu_env, tcg_rd, new_tmp_a64_zero(s));
5168         }
5169         break;
5170     case MAP(1, 0x01, 0x10): /* XPACI */
5171         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5172             goto do_unallocated;
5173         } else if (s->pauth_active) {
5174             tcg_rd = cpu_reg(s, rd);
5175             gen_helper_xpaci(tcg_rd, cpu_env, tcg_rd);
5176         }
5177         break;
5178     case MAP(1, 0x01, 0x11): /* XPACD */
5179         if (!dc_isar_feature(aa64_pauth, s) || rn != 31) {
5180             goto do_unallocated;
5181         } else if (s->pauth_active) {
5182             tcg_rd = cpu_reg(s, rd);
5183             gen_helper_xpacd(tcg_rd, cpu_env, tcg_rd);
5184         }
5185         break;
5186     default:
5187     do_unallocated:
5188         unallocated_encoding(s);
5189         break;
5190     }
5191
5192 #undef MAP
5193 }
5194
5195 static void handle_div(DisasContext *s, bool is_signed, unsigned int sf,
5196                        unsigned int rm, unsigned int rn, unsigned int rd)
5197 {
5198     TCGv_i64 tcg_n, tcg_m, tcg_rd;
5199     tcg_rd = cpu_reg(s, rd);
5200
5201     if (!sf && is_signed) {
5202         tcg_n = new_tmp_a64(s);
5203         tcg_m = new_tmp_a64(s);
5204         tcg_gen_ext32s_i64(tcg_n, cpu_reg(s, rn));
5205         tcg_gen_ext32s_i64(tcg_m, cpu_reg(s, rm));
5206     } else {
5207         tcg_n = read_cpu_reg(s, rn, sf);
5208         tcg_m = read_cpu_reg(s, rm, sf);
5209     }
5210
5211     if (is_signed) {
5212         gen_helper_sdiv64(tcg_rd, tcg_n, tcg_m);
5213     } else {
5214         gen_helper_udiv64(tcg_rd, tcg_n, tcg_m);
5215     }
5216
5217     if (!sf) { /* zero extend final result */
5218         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
5219     }
5220 }
5221
5222 /* LSLV, LSRV, ASRV, RORV */
5223 static void handle_shift_reg(DisasContext *s,
5224                              enum a64_shift_type shift_type, unsigned int sf,
5225                              unsigned int rm, unsigned int rn, unsigned int rd)
5226 {
5227     TCGv_i64 tcg_shift = tcg_temp_new_i64();
5228     TCGv_i64 tcg_rd = cpu_reg(s, rd);
5229     TCGv_i64 tcg_rn = read_cpu_reg(s, rn, sf);
5230
5231     tcg_gen_andi_i64(tcg_shift, cpu_reg(s, rm), sf ? 63 : 31);
5232     shift_reg(tcg_rd, tcg_rn, sf, shift_type, tcg_shift);
5233     tcg_temp_free_i64(tcg_shift);
5234 }
5235
5236 /* CRC32[BHWX], CRC32C[BHWX] */
5237 static void handle_crc32(DisasContext *s,
5238                          unsigned int sf, unsigned int sz, bool crc32c,
5239                          unsigned int rm, unsigned int rn, unsigned int rd)
5240 {
5241     TCGv_i64 tcg_acc, tcg_val;
5242     TCGv_i32 tcg_bytes;
5243
5244     if (!dc_isar_feature(aa64_crc32, s)
5245         || (sf == 1 && sz != 3)
5246         || (sf == 0 && sz == 3)) {
5247         unallocated_encoding(s);
5248         return;
5249     }
5250
5251     if (sz == 3) {
5252         tcg_val = cpu_reg(s, rm);
5253     } else {
5254         uint64_t mask;
5255         switch (sz) {
5256         case 0:
5257             mask = 0xFF;
5258             break;
5259         case 1:
5260             mask = 0xFFFF;
5261             break;
5262         case 2:
5263             mask = 0xFFFFFFFF;
5264             break;
5265         default:
5266             g_assert_not_reached();
5267         }
5268         tcg_val = new_tmp_a64(s);
5269         tcg_gen_andi_i64(tcg_val, cpu_reg(s, rm), mask);
5270     }
5271
5272     tcg_acc = cpu_reg(s, rn);
5273     tcg_bytes = tcg_const_i32(1 << sz);
5274
5275     if (crc32c) {
5276         gen_helper_crc32c_64(cpu_reg(s, rd), tcg_acc, tcg_val, tcg_bytes);
5277     } else {
5278         gen_helper_crc32_64(cpu_reg(s, rd), tcg_acc, tcg_val, tcg_bytes);
5279     }
5280
5281     tcg_temp_free_i32(tcg_bytes);
5282 }
5283
5284 /* Data-processing (2 source)
5285  *   31   30  29 28             21 20  16 15    10 9    5 4    0
5286  * +----+---+---+-----------------+------+--------+------+------+
5287  * | sf | 0 | S | 1 1 0 1 0 1 1 0 |  Rm  | opcode |  Rn  |  Rd  |
5288  * +----+---+---+-----------------+------+--------+------+------+
5289  */
5290 static void disas_data_proc_2src(DisasContext *s, uint32_t insn)
5291 {
5292     unsigned int sf, rm, opcode, rn, rd;
5293     sf = extract32(insn, 31, 1);
5294     rm = extract32(insn, 16, 5);
5295     opcode = extract32(insn, 10, 6);
5296     rn = extract32(insn, 5, 5);
5297     rd = extract32(insn, 0, 5);
5298
5299     if (extract32(insn, 29, 1)) {
5300         unallocated_encoding(s);
5301         return;
5302     }
5303
5304     switch (opcode) {
5305     case 2: /* UDIV */
5306         handle_div(s, false, sf, rm, rn, rd);
5307         break;
5308     case 3: /* SDIV */
5309         handle_div(s, true, sf, rm, rn, rd);
5310         break;
5311     case 8: /* LSLV */
5312         handle_shift_reg(s, A64_SHIFT_TYPE_LSL, sf, rm, rn, rd);
5313         break;
5314     case 9: /* LSRV */
5315         handle_shift_reg(s, A64_SHIFT_TYPE_LSR, sf, rm, rn, rd);
5316         break;
5317     case 10: /* ASRV */
5318         handle_shift_reg(s, A64_SHIFT_TYPE_ASR, sf, rm, rn, rd);
5319         break;
5320     case 11: /* RORV */
5321         handle_shift_reg(s, A64_SHIFT_TYPE_ROR, sf, rm, rn, rd);
5322         break;
5323     case 12: /* PACGA */
5324         if (sf == 0 || !dc_isar_feature(aa64_pauth, s)) {
5325             goto do_unallocated;
5326         }
5327         gen_helper_pacga(cpu_reg(s, rd), cpu_env,
5328                          cpu_reg(s, rn), cpu_reg_sp(s, rm));
5329         break;
5330     case 16:
5331     case 17:
5332     case 18:
5333     case 19:
5334     case 20:
5335     case 21:
5336     case 22:
5337     case 23: /* CRC32 */
5338     {
5339         int sz = extract32(opcode, 0, 2);
5340         bool crc32c = extract32(opcode, 2, 1);
5341         handle_crc32(s, sf, sz, crc32c, rm, rn, rd);
5342         break;
5343     }
5344     default:
5345     do_unallocated:
5346         unallocated_encoding(s);
5347         break;
5348     }
5349 }
5350
5351 /*
5352  * Data processing - register
5353  *  31  30 29  28      25    21  20  16      10         0
5354  * +--+---+--+---+-------+-----+-------+-------+---------+
5355  * |  |op0|  |op1| 1 0 1 | op2 |       |  op3  |         |
5356  * +--+---+--+---+-------+-----+-------+-------+---------+
5357  */
5358 static void disas_data_proc_reg(DisasContext *s, uint32_t insn)
5359 {
5360     int op0 = extract32(insn, 30, 1);
5361     int op1 = extract32(insn, 28, 1);
5362     int op2 = extract32(insn, 21, 4);
5363     int op3 = extract32(insn, 10, 6);
5364
5365     if (!op1) {
5366         if (op2 & 8) {
5367             if (op2 & 1) {
5368                 /* Add/sub (extended register) */
5369                 disas_add_sub_ext_reg(s, insn);
5370             } else {
5371                 /* Add/sub (shifted register) */
5372                 disas_add_sub_reg(s, insn);
5373             }
5374         } else {
5375             /* Logical (shifted register) */
5376             disas_logic_reg(s, insn);
5377         }
5378         return;
5379     }
5380
5381     switch (op2) {
5382     case 0x0:
5383         switch (op3) {
5384         case 0x00: /* Add/subtract (with carry) */
5385             disas_adc_sbc(s, insn);
5386             break;
5387
5388         case 0x01: /* Rotate right into flags */
5389         case 0x21:
5390             disas_rotate_right_into_flags(s, insn);
5391             break;
5392
5393         case 0x02: /* Evaluate into flags */
5394         case 0x12:
5395         case 0x22:
5396         case 0x32:
5397             disas_evaluate_into_flags(s, insn);
5398             break;
5399
5400         default:
5401             goto do_unallocated;
5402         }
5403         break;
5404
5405     case 0x2: /* Conditional compare */
5406         disas_cc(s, insn); /* both imm and reg forms */
5407         break;
5408
5409     case 0x4: /* Conditional select */
5410         disas_cond_select(s, insn);
5411         break;
5412
5413     case 0x6: /* Data-processing */
5414         if (op0) {    /* (1 source) */
5415             disas_data_proc_1src(s, insn);
5416         } else {      /* (2 source) */
5417             disas_data_proc_2src(s, insn);
5418         }
5419         break;
5420     case 0x8 ... 0xf: /* (3 source) */
5421         disas_data_proc_3src(s, insn);
5422         break;
5423
5424     default:
5425     do_unallocated:
5426         unallocated_encoding(s);
5427         break;
5428     }
5429 }
5430
5431 static void handle_fp_compare(DisasContext *s, int size,
5432                               unsigned int rn, unsigned int rm,
5433                               bool cmp_with_zero, bool signal_all_nans)
5434 {
5435     TCGv_i64 tcg_flags = tcg_temp_new_i64();
5436     TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
5437
5438     if (size == MO_64) {
5439         TCGv_i64 tcg_vn, tcg_vm;
5440
5441         tcg_vn = read_fp_dreg(s, rn);
5442         if (cmp_with_zero) {
5443             tcg_vm = tcg_const_i64(0);
5444         } else {
5445             tcg_vm = read_fp_dreg(s, rm);
5446         }
5447         if (signal_all_nans) {
5448             gen_helper_vfp_cmped_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5449         } else {
5450             gen_helper_vfp_cmpd_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5451         }
5452         tcg_temp_free_i64(tcg_vn);
5453         tcg_temp_free_i64(tcg_vm);
5454     } else {
5455         TCGv_i32 tcg_vn = tcg_temp_new_i32();
5456         TCGv_i32 tcg_vm = tcg_temp_new_i32();
5457
5458         read_vec_element_i32(s, tcg_vn, rn, 0, size);
5459         if (cmp_with_zero) {
5460             tcg_gen_movi_i32(tcg_vm, 0);
5461         } else {
5462             read_vec_element_i32(s, tcg_vm, rm, 0, size);
5463         }
5464
5465         switch (size) {
5466         case MO_32:
5467             if (signal_all_nans) {
5468                 gen_helper_vfp_cmpes_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5469             } else {
5470                 gen_helper_vfp_cmps_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5471             }
5472             break;
5473         case MO_16:
5474             if (signal_all_nans) {
5475                 gen_helper_vfp_cmpeh_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5476             } else {
5477                 gen_helper_vfp_cmph_a64(tcg_flags, tcg_vn, tcg_vm, fpst);
5478             }
5479             break;
5480         default:
5481             g_assert_not_reached();
5482         }
5483
5484         tcg_temp_free_i32(tcg_vn);
5485         tcg_temp_free_i32(tcg_vm);
5486     }
5487
5488     tcg_temp_free_ptr(fpst);
5489
5490     gen_set_nzcv(tcg_flags);
5491
5492     tcg_temp_free_i64(tcg_flags);
5493 }
5494
5495 /* Floating point compare
5496  *   31  30  29 28       24 23  22  21 20  16 15 14 13  10    9    5 4     0
5497  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
5498  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | op  | 1 0 0 0 |  Rn  |  op2  |
5499  * +---+---+---+-----------+------+---+------+-----+---------+------+-------+
5500  */
5501 static void disas_fp_compare(DisasContext *s, uint32_t insn)
5502 {
5503     unsigned int mos, type, rm, op, rn, opc, op2r;
5504     int size;
5505
5506     mos = extract32(insn, 29, 3);
5507     type = extract32(insn, 22, 2);
5508     rm = extract32(insn, 16, 5);
5509     op = extract32(insn, 14, 2);
5510     rn = extract32(insn, 5, 5);
5511     opc = extract32(insn, 3, 2);
5512     op2r = extract32(insn, 0, 3);
5513
5514     if (mos || op || op2r) {
5515         unallocated_encoding(s);
5516         return;
5517     }
5518
5519     switch (type) {
5520     case 0:
5521         size = MO_32;
5522         break;
5523     case 1:
5524         size = MO_64;
5525         break;
5526     case 3:
5527         size = MO_16;
5528         if (dc_isar_feature(aa64_fp16, s)) {
5529             break;
5530         }
5531         /* fallthru */
5532     default:
5533         unallocated_encoding(s);
5534         return;
5535     }
5536
5537     if (!fp_access_check(s)) {
5538         return;
5539     }
5540
5541     handle_fp_compare(s, size, rn, rm, opc & 1, opc & 2);
5542 }
5543
5544 /* Floating point conditional compare
5545  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5  4   3    0
5546  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
5547  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 0 1 |  Rn  | op | nzcv |
5548  * +---+---+---+-----------+------+---+------+------+-----+------+----+------+
5549  */
5550 static void disas_fp_ccomp(DisasContext *s, uint32_t insn)
5551 {
5552     unsigned int mos, type, rm, cond, rn, op, nzcv;
5553     TCGv_i64 tcg_flags;
5554     TCGLabel *label_continue = NULL;
5555     int size;
5556
5557     mos = extract32(insn, 29, 3);
5558     type = extract32(insn, 22, 2);
5559     rm = extract32(insn, 16, 5);
5560     cond = extract32(insn, 12, 4);
5561     rn = extract32(insn, 5, 5);
5562     op = extract32(insn, 4, 1);
5563     nzcv = extract32(insn, 0, 4);
5564
5565     if (mos) {
5566         unallocated_encoding(s);
5567         return;
5568     }
5569
5570     switch (type) {
5571     case 0:
5572         size = MO_32;
5573         break;
5574     case 1:
5575         size = MO_64;
5576         break;
5577     case 3:
5578         size = MO_16;
5579         if (dc_isar_feature(aa64_fp16, s)) {
5580             break;
5581         }
5582         /* fallthru */
5583     default:
5584         unallocated_encoding(s);
5585         return;
5586     }
5587
5588     if (!fp_access_check(s)) {
5589         return;
5590     }
5591
5592     if (cond < 0x0e) { /* not always */
5593         TCGLabel *label_match = gen_new_label();
5594         label_continue = gen_new_label();
5595         arm_gen_test_cc(cond, label_match);
5596         /* nomatch: */
5597         tcg_flags = tcg_const_i64(nzcv << 28);
5598         gen_set_nzcv(tcg_flags);
5599         tcg_temp_free_i64(tcg_flags);
5600         tcg_gen_br(label_continue);
5601         gen_set_label(label_match);
5602     }
5603
5604     handle_fp_compare(s, size, rn, rm, false, op);
5605
5606     if (cond < 0x0e) {
5607         gen_set_label(label_continue);
5608     }
5609 }
5610
5611 /* Floating point conditional select
5612  *   31  30  29 28       24 23  22  21 20  16 15  12 11 10 9    5 4    0
5613  * +---+---+---+-----------+------+---+------+------+-----+------+------+
5614  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | cond | 1 1 |  Rn  |  Rd  |
5615  * +---+---+---+-----------+------+---+------+------+-----+------+------+
5616  */
5617 static void disas_fp_csel(DisasContext *s, uint32_t insn)
5618 {
5619     unsigned int mos, type, rm, cond, rn, rd;
5620     TCGv_i64 t_true, t_false, t_zero;
5621     DisasCompare64 c;
5622     MemOp sz;
5623
5624     mos = extract32(insn, 29, 3);
5625     type = extract32(insn, 22, 2);
5626     rm = extract32(insn, 16, 5);
5627     cond = extract32(insn, 12, 4);
5628     rn = extract32(insn, 5, 5);
5629     rd = extract32(insn, 0, 5);
5630
5631     if (mos) {
5632         unallocated_encoding(s);
5633         return;
5634     }
5635
5636     switch (type) {
5637     case 0:
5638         sz = MO_32;
5639         break;
5640     case 1:
5641         sz = MO_64;
5642         break;
5643     case 3:
5644         sz = MO_16;
5645         if (dc_isar_feature(aa64_fp16, s)) {
5646             break;
5647         }
5648         /* fallthru */
5649     default:
5650         unallocated_encoding(s);
5651         return;
5652     }
5653
5654     if (!fp_access_check(s)) {
5655         return;
5656     }
5657
5658     /* Zero extend sreg & hreg inputs to 64 bits now.  */
5659     t_true = tcg_temp_new_i64();
5660     t_false = tcg_temp_new_i64();
5661     read_vec_element(s, t_true, rn, 0, sz);
5662     read_vec_element(s, t_false, rm, 0, sz);
5663
5664     a64_test_cc(&c, cond);
5665     t_zero = tcg_const_i64(0);
5666     tcg_gen_movcond_i64(c.cond, t_true, c.value, t_zero, t_true, t_false);
5667     tcg_temp_free_i64(t_zero);
5668     tcg_temp_free_i64(t_false);
5669     a64_free_cc(&c);
5670
5671     /* Note that sregs & hregs write back zeros to the high bits,
5672        and we've already done the zero-extension.  */
5673     write_fp_dreg(s, rd, t_true);
5674     tcg_temp_free_i64(t_true);
5675 }
5676
5677 /* Floating-point data-processing (1 source) - half precision */
5678 static void handle_fp_1src_half(DisasContext *s, int opcode, int rd, int rn)
5679 {
5680     TCGv_ptr fpst = NULL;
5681     TCGv_i32 tcg_op = read_fp_hreg(s, rn);
5682     TCGv_i32 tcg_res = tcg_temp_new_i32();
5683
5684     switch (opcode) {
5685     case 0x0: /* FMOV */
5686         tcg_gen_mov_i32(tcg_res, tcg_op);
5687         break;
5688     case 0x1: /* FABS */
5689         tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
5690         break;
5691     case 0x2: /* FNEG */
5692         tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
5693         break;
5694     case 0x3: /* FSQRT */
5695         fpst = get_fpstatus_ptr(true);
5696         gen_helper_sqrt_f16(tcg_res, tcg_op, fpst);
5697         break;
5698     case 0x8: /* FRINTN */
5699     case 0x9: /* FRINTP */
5700     case 0xa: /* FRINTM */
5701     case 0xb: /* FRINTZ */
5702     case 0xc: /* FRINTA */
5703     {
5704         TCGv_i32 tcg_rmode = tcg_const_i32(arm_rmode_to_sf(opcode & 7));
5705         fpst = get_fpstatus_ptr(true);
5706
5707         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5708         gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
5709
5710         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5711         tcg_temp_free_i32(tcg_rmode);
5712         break;
5713     }
5714     case 0xe: /* FRINTX */
5715         fpst = get_fpstatus_ptr(true);
5716         gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, fpst);
5717         break;
5718     case 0xf: /* FRINTI */
5719         fpst = get_fpstatus_ptr(true);
5720         gen_helper_advsimd_rinth(tcg_res, tcg_op, fpst);
5721         break;
5722     default:
5723         abort();
5724     }
5725
5726     write_fp_sreg(s, rd, tcg_res);
5727
5728     if (fpst) {
5729         tcg_temp_free_ptr(fpst);
5730     }
5731     tcg_temp_free_i32(tcg_op);
5732     tcg_temp_free_i32(tcg_res);
5733 }
5734
5735 /* Floating-point data-processing (1 source) - single precision */
5736 static void handle_fp_1src_single(DisasContext *s, int opcode, int rd, int rn)
5737 {
5738     void (*gen_fpst)(TCGv_i32, TCGv_i32, TCGv_ptr);
5739     TCGv_i32 tcg_op, tcg_res;
5740     TCGv_ptr fpst;
5741     int rmode = -1;
5742
5743     tcg_op = read_fp_sreg(s, rn);
5744     tcg_res = tcg_temp_new_i32();
5745
5746     switch (opcode) {
5747     case 0x0: /* FMOV */
5748         tcg_gen_mov_i32(tcg_res, tcg_op);
5749         goto done;
5750     case 0x1: /* FABS */
5751         gen_helper_vfp_abss(tcg_res, tcg_op);
5752         goto done;
5753     case 0x2: /* FNEG */
5754         gen_helper_vfp_negs(tcg_res, tcg_op);
5755         goto done;
5756     case 0x3: /* FSQRT */
5757         gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
5758         goto done;
5759     case 0x8: /* FRINTN */
5760     case 0x9: /* FRINTP */
5761     case 0xa: /* FRINTM */
5762     case 0xb: /* FRINTZ */
5763     case 0xc: /* FRINTA */
5764         rmode = arm_rmode_to_sf(opcode & 7);
5765         gen_fpst = gen_helper_rints;
5766         break;
5767     case 0xe: /* FRINTX */
5768         gen_fpst = gen_helper_rints_exact;
5769         break;
5770     case 0xf: /* FRINTI */
5771         gen_fpst = gen_helper_rints;
5772         break;
5773     case 0x10: /* FRINT32Z */
5774         rmode = float_round_to_zero;
5775         gen_fpst = gen_helper_frint32_s;
5776         break;
5777     case 0x11: /* FRINT32X */
5778         gen_fpst = gen_helper_frint32_s;
5779         break;
5780     case 0x12: /* FRINT64Z */
5781         rmode = float_round_to_zero;
5782         gen_fpst = gen_helper_frint64_s;
5783         break;
5784     case 0x13: /* FRINT64X */
5785         gen_fpst = gen_helper_frint64_s;
5786         break;
5787     default:
5788         g_assert_not_reached();
5789     }
5790
5791     fpst = get_fpstatus_ptr(false);
5792     if (rmode >= 0) {
5793         TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
5794         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5795         gen_fpst(tcg_res, tcg_op, fpst);
5796         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5797         tcg_temp_free_i32(tcg_rmode);
5798     } else {
5799         gen_fpst(tcg_res, tcg_op, fpst);
5800     }
5801     tcg_temp_free_ptr(fpst);
5802
5803  done:
5804     write_fp_sreg(s, rd, tcg_res);
5805     tcg_temp_free_i32(tcg_op);
5806     tcg_temp_free_i32(tcg_res);
5807 }
5808
5809 /* Floating-point data-processing (1 source) - double precision */
5810 static void handle_fp_1src_double(DisasContext *s, int opcode, int rd, int rn)
5811 {
5812     void (*gen_fpst)(TCGv_i64, TCGv_i64, TCGv_ptr);
5813     TCGv_i64 tcg_op, tcg_res;
5814     TCGv_ptr fpst;
5815     int rmode = -1;
5816
5817     switch (opcode) {
5818     case 0x0: /* FMOV */
5819         gen_gvec_fn2(s, false, rd, rn, tcg_gen_gvec_mov, 0);
5820         return;
5821     }
5822
5823     tcg_op = read_fp_dreg(s, rn);
5824     tcg_res = tcg_temp_new_i64();
5825
5826     switch (opcode) {
5827     case 0x1: /* FABS */
5828         gen_helper_vfp_absd(tcg_res, tcg_op);
5829         goto done;
5830     case 0x2: /* FNEG */
5831         gen_helper_vfp_negd(tcg_res, tcg_op);
5832         goto done;
5833     case 0x3: /* FSQRT */
5834         gen_helper_vfp_sqrtd(tcg_res, tcg_op, cpu_env);
5835         goto done;
5836     case 0x8: /* FRINTN */
5837     case 0x9: /* FRINTP */
5838     case 0xa: /* FRINTM */
5839     case 0xb: /* FRINTZ */
5840     case 0xc: /* FRINTA */
5841         rmode = arm_rmode_to_sf(opcode & 7);
5842         gen_fpst = gen_helper_rintd;
5843         break;
5844     case 0xe: /* FRINTX */
5845         gen_fpst = gen_helper_rintd_exact;
5846         break;
5847     case 0xf: /* FRINTI */
5848         gen_fpst = gen_helper_rintd;
5849         break;
5850     case 0x10: /* FRINT32Z */
5851         rmode = float_round_to_zero;
5852         gen_fpst = gen_helper_frint32_d;
5853         break;
5854     case 0x11: /* FRINT32X */
5855         gen_fpst = gen_helper_frint32_d;
5856         break;
5857     case 0x12: /* FRINT64Z */
5858         rmode = float_round_to_zero;
5859         gen_fpst = gen_helper_frint64_d;
5860         break;
5861     case 0x13: /* FRINT64X */
5862         gen_fpst = gen_helper_frint64_d;
5863         break;
5864     default:
5865         g_assert_not_reached();
5866     }
5867
5868     fpst = get_fpstatus_ptr(false);
5869     if (rmode >= 0) {
5870         TCGv_i32 tcg_rmode = tcg_const_i32(rmode);
5871         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5872         gen_fpst(tcg_res, tcg_op, fpst);
5873         gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
5874         tcg_temp_free_i32(tcg_rmode);
5875     } else {
5876         gen_fpst(tcg_res, tcg_op, fpst);
5877     }
5878     tcg_temp_free_ptr(fpst);
5879
5880  done:
5881     write_fp_dreg(s, rd, tcg_res);
5882     tcg_temp_free_i64(tcg_op);
5883     tcg_temp_free_i64(tcg_res);
5884 }
5885
5886 static void handle_fp_fcvt(DisasContext *s, int opcode,
5887                            int rd, int rn, int dtype, int ntype)
5888 {
5889     switch (ntype) {
5890     case 0x0:
5891     {
5892         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
5893         if (dtype == 1) {
5894             /* Single to double */
5895             TCGv_i64 tcg_rd = tcg_temp_new_i64();
5896             gen_helper_vfp_fcvtds(tcg_rd, tcg_rn, cpu_env);
5897             write_fp_dreg(s, rd, tcg_rd);
5898             tcg_temp_free_i64(tcg_rd);
5899         } else {
5900             /* Single to half */
5901             TCGv_i32 tcg_rd = tcg_temp_new_i32();
5902             TCGv_i32 ahp = get_ahp_flag();
5903             TCGv_ptr fpst = get_fpstatus_ptr(false);
5904
5905             gen_helper_vfp_fcvt_f32_to_f16(tcg_rd, tcg_rn, fpst, ahp);
5906             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
5907             write_fp_sreg(s, rd, tcg_rd);
5908             tcg_temp_free_i32(tcg_rd);
5909             tcg_temp_free_i32(ahp);
5910             tcg_temp_free_ptr(fpst);
5911         }
5912         tcg_temp_free_i32(tcg_rn);
5913         break;
5914     }
5915     case 0x1:
5916     {
5917         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
5918         TCGv_i32 tcg_rd = tcg_temp_new_i32();
5919         if (dtype == 0) {
5920             /* Double to single */
5921             gen_helper_vfp_fcvtsd(tcg_rd, tcg_rn, cpu_env);
5922         } else {
5923             TCGv_ptr fpst = get_fpstatus_ptr(false);
5924             TCGv_i32 ahp = get_ahp_flag();
5925             /* Double to half */
5926             gen_helper_vfp_fcvt_f64_to_f16(tcg_rd, tcg_rn, fpst, ahp);
5927             /* write_fp_sreg is OK here because top half of tcg_rd is zero */
5928             tcg_temp_free_ptr(fpst);
5929             tcg_temp_free_i32(ahp);
5930         }
5931         write_fp_sreg(s, rd, tcg_rd);
5932         tcg_temp_free_i32(tcg_rd);
5933         tcg_temp_free_i64(tcg_rn);
5934         break;
5935     }
5936     case 0x3:
5937     {
5938         TCGv_i32 tcg_rn = read_fp_sreg(s, rn);
5939         TCGv_ptr tcg_fpst = get_fpstatus_ptr(false);
5940         TCGv_i32 tcg_ahp = get_ahp_flag();
5941         tcg_gen_ext16u_i32(tcg_rn, tcg_rn);
5942         if (dtype == 0) {
5943             /* Half to single */
5944             TCGv_i32 tcg_rd = tcg_temp_new_i32();
5945             gen_helper_vfp_fcvt_f16_to_f32(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp);
5946             write_fp_sreg(s, rd, tcg_rd);
5947             tcg_temp_free_i32(tcg_rd);
5948         } else {
5949             /* Half to double */
5950             TCGv_i64 tcg_rd = tcg_temp_new_i64();
5951             gen_helper_vfp_fcvt_f16_to_f64(tcg_rd, tcg_rn, tcg_fpst, tcg_ahp);
5952             write_fp_dreg(s, rd, tcg_rd);
5953             tcg_temp_free_i64(tcg_rd);
5954         }
5955         tcg_temp_free_i32(tcg_rn);
5956         tcg_temp_free_ptr(tcg_fpst);
5957         tcg_temp_free_i32(tcg_ahp);
5958         break;
5959     }
5960     default:
5961         abort();
5962     }
5963 }
5964
5965 /* Floating point data-processing (1 source)
5966  *   31  30  29 28       24 23  22  21 20    15 14       10 9    5 4    0
5967  * +---+---+---+-----------+------+---+--------+-----------+------+------+
5968  * | M | 0 | S | 1 1 1 1 0 | type | 1 | opcode | 1 0 0 0 0 |  Rn  |  Rd  |
5969  * +---+---+---+-----------+------+---+--------+-----------+------+------+
5970  */
5971 static void disas_fp_1src(DisasContext *s, uint32_t insn)
5972 {
5973     int mos = extract32(insn, 29, 3);
5974     int type = extract32(insn, 22, 2);
5975     int opcode = extract32(insn, 15, 6);
5976     int rn = extract32(insn, 5, 5);
5977     int rd = extract32(insn, 0, 5);
5978
5979     if (mos) {
5980         unallocated_encoding(s);
5981         return;
5982     }
5983
5984     switch (opcode) {
5985     case 0x4: case 0x5: case 0x7:
5986     {
5987         /* FCVT between half, single and double precision */
5988         int dtype = extract32(opcode, 0, 2);
5989         if (type == 2 || dtype == type) {
5990             unallocated_encoding(s);
5991             return;
5992         }
5993         if (!fp_access_check(s)) {
5994             return;
5995         }
5996
5997         handle_fp_fcvt(s, opcode, rd, rn, dtype, type);
5998         break;
5999     }
6000
6001     case 0x10 ... 0x13: /* FRINT{32,64}{X,Z} */
6002         if (type > 1 || !dc_isar_feature(aa64_frint, s)) {
6003             unallocated_encoding(s);
6004             return;
6005         }
6006         /* fall through */
6007     case 0x0 ... 0x3:
6008     case 0x8 ... 0xc:
6009     case 0xe ... 0xf:
6010         /* 32-to-32 and 64-to-64 ops */
6011         switch (type) {
6012         case 0:
6013             if (!fp_access_check(s)) {
6014                 return;
6015             }
6016             handle_fp_1src_single(s, opcode, rd, rn);
6017             break;
6018         case 1:
6019             if (!fp_access_check(s)) {
6020                 return;
6021             }
6022             handle_fp_1src_double(s, opcode, rd, rn);
6023             break;
6024         case 3:
6025             if (!dc_isar_feature(aa64_fp16, s)) {
6026                 unallocated_encoding(s);
6027                 return;
6028             }
6029
6030             if (!fp_access_check(s)) {
6031                 return;
6032             }
6033             handle_fp_1src_half(s, opcode, rd, rn);
6034             break;
6035         default:
6036             unallocated_encoding(s);
6037         }
6038         break;
6039
6040     default:
6041         unallocated_encoding(s);
6042         break;
6043     }
6044 }
6045
6046 /* Floating-point data-processing (2 source) - single precision */
6047 static void handle_fp_2src_single(DisasContext *s, int opcode,
6048                                   int rd, int rn, int rm)
6049 {
6050     TCGv_i32 tcg_op1;
6051     TCGv_i32 tcg_op2;
6052     TCGv_i32 tcg_res;
6053     TCGv_ptr fpst;
6054
6055     tcg_res = tcg_temp_new_i32();
6056     fpst = get_fpstatus_ptr(false);
6057     tcg_op1 = read_fp_sreg(s, rn);
6058     tcg_op2 = read_fp_sreg(s, rm);
6059
6060     switch (opcode) {
6061     case 0x0: /* FMUL */
6062         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
6063         break;
6064     case 0x1: /* FDIV */
6065         gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
6066         break;
6067     case 0x2: /* FADD */
6068         gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
6069         break;
6070     case 0x3: /* FSUB */
6071         gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
6072         break;
6073     case 0x4: /* FMAX */
6074         gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
6075         break;
6076     case 0x5: /* FMIN */
6077         gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
6078         break;
6079     case 0x6: /* FMAXNM */
6080         gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
6081         break;
6082     case 0x7: /* FMINNM */
6083         gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
6084         break;
6085     case 0x8: /* FNMUL */
6086         gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
6087         gen_helper_vfp_negs(tcg_res, tcg_res);
6088         break;
6089     }
6090
6091     write_fp_sreg(s, rd, tcg_res);
6092
6093     tcg_temp_free_ptr(fpst);
6094     tcg_temp_free_i32(tcg_op1);
6095     tcg_temp_free_i32(tcg_op2);
6096     tcg_temp_free_i32(tcg_res);
6097 }
6098
6099 /* Floating-point data-processing (2 source) - double precision */
6100 static void handle_fp_2src_double(DisasContext *s, int opcode,
6101                                   int rd, int rn, int rm)
6102 {
6103     TCGv_i64 tcg_op1;
6104     TCGv_i64 tcg_op2;
6105     TCGv_i64 tcg_res;
6106     TCGv_ptr fpst;
6107
6108     tcg_res = tcg_temp_new_i64();
6109     fpst = get_fpstatus_ptr(false);
6110     tcg_op1 = read_fp_dreg(s, rn);
6111     tcg_op2 = read_fp_dreg(s, rm);
6112
6113     switch (opcode) {
6114     case 0x0: /* FMUL */
6115         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
6116         break;
6117     case 0x1: /* FDIV */
6118         gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
6119         break;
6120     case 0x2: /* FADD */
6121         gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
6122         break;
6123     case 0x3: /* FSUB */
6124         gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
6125         break;
6126     case 0x4: /* FMAX */
6127         gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
6128         break;
6129     case 0x5: /* FMIN */
6130         gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
6131         break;
6132     case 0x6: /* FMAXNM */
6133         gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
6134         break;
6135     case 0x7: /* FMINNM */
6136         gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
6137         break;
6138     case 0x8: /* FNMUL */
6139         gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
6140         gen_helper_vfp_negd(tcg_res, tcg_res);
6141         break;
6142     }
6143
6144     write_fp_dreg(s, rd, tcg_res);
6145
6146     tcg_temp_free_ptr(fpst);
6147     tcg_temp_free_i64(tcg_op1);
6148     tcg_temp_free_i64(tcg_op2);
6149     tcg_temp_free_i64(tcg_res);
6150 }
6151
6152 /* Floating-point data-processing (2 source) - half precision */
6153 static void handle_fp_2src_half(DisasContext *s, int opcode,
6154                                 int rd, int rn, int rm)
6155 {
6156     TCGv_i32 tcg_op1;
6157     TCGv_i32 tcg_op2;
6158     TCGv_i32 tcg_res;
6159     TCGv_ptr fpst;
6160
6161     tcg_res = tcg_temp_new_i32();
6162     fpst = get_fpstatus_ptr(true);
6163     tcg_op1 = read_fp_hreg(s, rn);
6164     tcg_op2 = read_fp_hreg(s, rm);
6165
6166     switch (opcode) {
6167     case 0x0: /* FMUL */
6168         gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
6169         break;
6170     case 0x1: /* FDIV */
6171         gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
6172         break;
6173     case 0x2: /* FADD */
6174         gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
6175         break;
6176     case 0x3: /* FSUB */
6177         gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
6178         break;
6179     case 0x4: /* FMAX */
6180         gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
6181         break;
6182     case 0x5: /* FMIN */
6183         gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
6184         break;
6185     case 0x6: /* FMAXNM */
6186         gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
6187         break;
6188     case 0x7: /* FMINNM */
6189         gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
6190         break;
6191     case 0x8: /* FNMUL */
6192         gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
6193         tcg_gen_xori_i32(tcg_res, tcg_res, 0x8000);
6194         break;
6195     default:
6196         g_assert_not_reached();
6197     }
6198
6199     write_fp_sreg(s, rd, tcg_res);
6200
6201     tcg_temp_free_ptr(fpst);
6202     tcg_temp_free_i32(tcg_op1);
6203     tcg_temp_free_i32(tcg_op2);
6204     tcg_temp_free_i32(tcg_res);
6205 }
6206
6207 /* Floating point data-processing (2 source)
6208  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
6209  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
6210  * | M | 0 | S | 1 1 1 1 0 | type | 1 |  Rm  | opcode | 1 0 |  Rn  |  Rd  |
6211  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
6212  */
6213 static void disas_fp_2src(DisasContext *s, uint32_t insn)
6214 {
6215     int mos = extract32(insn, 29, 3);
6216     int type = extract32(insn, 22, 2);
6217     int rd = extract32(insn, 0, 5);
6218     int rn = extract32(insn, 5, 5);
6219     int rm = extract32(insn, 16, 5);
6220     int opcode = extract32(insn, 12, 4);
6221
6222     if (opcode > 8 || mos) {
6223         unallocated_encoding(s);
6224         return;
6225     }
6226
6227     switch (type) {
6228     case 0:
6229         if (!fp_access_check(s)) {
6230             return;
6231         }
6232         handle_fp_2src_single(s, opcode, rd, rn, rm);
6233         break;
6234     case 1:
6235         if (!fp_access_check(s)) {
6236             return;
6237         }
6238         handle_fp_2src_double(s, opcode, rd, rn, rm);
6239         break;
6240     case 3:
6241         if (!dc_isar_feature(aa64_fp16, s)) {
6242             unallocated_encoding(s);
6243             return;
6244         }
6245         if (!fp_access_check(s)) {
6246             return;
6247         }
6248         handle_fp_2src_half(s, opcode, rd, rn, rm);
6249         break;
6250     default:
6251         unallocated_encoding(s);
6252     }
6253 }
6254
6255 /* Floating-point data-processing (3 source) - single precision */
6256 static void handle_fp_3src_single(DisasContext *s, bool o0, bool o1,
6257                                   int rd, int rn, int rm, int ra)
6258 {
6259     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
6260     TCGv_i32 tcg_res = tcg_temp_new_i32();
6261     TCGv_ptr fpst = get_fpstatus_ptr(false);
6262
6263     tcg_op1 = read_fp_sreg(s, rn);
6264     tcg_op2 = read_fp_sreg(s, rm);
6265     tcg_op3 = read_fp_sreg(s, ra);
6266
6267     /* These are fused multiply-add, and must be done as one
6268      * floating point operation with no rounding between the
6269      * multiplication and addition steps.
6270      * NB that doing the negations here as separate steps is
6271      * correct : an input NaN should come out with its sign bit
6272      * flipped if it is a negated-input.
6273      */
6274     if (o1 == true) {
6275         gen_helper_vfp_negs(tcg_op3, tcg_op3);
6276     }
6277
6278     if (o0 != o1) {
6279         gen_helper_vfp_negs(tcg_op1, tcg_op1);
6280     }
6281
6282     gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
6283
6284     write_fp_sreg(s, rd, tcg_res);
6285
6286     tcg_temp_free_ptr(fpst);
6287     tcg_temp_free_i32(tcg_op1);
6288     tcg_temp_free_i32(tcg_op2);
6289     tcg_temp_free_i32(tcg_op3);
6290     tcg_temp_free_i32(tcg_res);
6291 }
6292
6293 /* Floating-point data-processing (3 source) - double precision */
6294 static void handle_fp_3src_double(DisasContext *s, bool o0, bool o1,
6295                                   int rd, int rn, int rm, int ra)
6296 {
6297     TCGv_i64 tcg_op1, tcg_op2, tcg_op3;
6298     TCGv_i64 tcg_res = tcg_temp_new_i64();
6299     TCGv_ptr fpst = get_fpstatus_ptr(false);
6300
6301     tcg_op1 = read_fp_dreg(s, rn);
6302     tcg_op2 = read_fp_dreg(s, rm);
6303     tcg_op3 = read_fp_dreg(s, ra);
6304
6305     /* These are fused multiply-add, and must be done as one
6306      * floating point operation with no rounding between the
6307      * multiplication and addition steps.
6308      * NB that doing the negations here as separate steps is
6309      * correct : an input NaN should come out with its sign bit
6310      * flipped if it is a negated-input.
6311      */
6312     if (o1 == true) {
6313         gen_helper_vfp_negd(tcg_op3, tcg_op3);
6314     }
6315
6316     if (o0 != o1) {
6317         gen_helper_vfp_negd(tcg_op1, tcg_op1);
6318     }
6319
6320     gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
6321
6322     write_fp_dreg(s, rd, tcg_res);
6323
6324     tcg_temp_free_ptr(fpst);
6325     tcg_temp_free_i64(tcg_op1);
6326     tcg_temp_free_i64(tcg_op2);
6327     tcg_temp_free_i64(tcg_op3);
6328     tcg_temp_free_i64(tcg_res);
6329 }
6330
6331 /* Floating-point data-processing (3 source) - half precision */
6332 static void handle_fp_3src_half(DisasContext *s, bool o0, bool o1,
6333                                 int rd, int rn, int rm, int ra)
6334 {
6335     TCGv_i32 tcg_op1, tcg_op2, tcg_op3;
6336     TCGv_i32 tcg_res = tcg_temp_new_i32();
6337     TCGv_ptr fpst = get_fpstatus_ptr(true);
6338
6339     tcg_op1 = read_fp_hreg(s, rn);
6340     tcg_op2 = read_fp_hreg(s, rm);
6341     tcg_op3 = read_fp_hreg(s, ra);
6342
6343     /* These are fused multiply-add, and must be done as one
6344      * floating point operation with no rounding between the
6345      * multiplication and addition steps.
6346      * NB that doing the negations here as separate steps is
6347      * correct : an input NaN should come out with its sign bit
6348      * flipped if it is a negated-input.
6349      */
6350     if (o1 == true) {
6351         tcg_gen_xori_i32(tcg_op3, tcg_op3, 0x8000);
6352     }
6353
6354     if (o0 != o1) {
6355         tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
6356     }
6357
6358     gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_op3, fpst);
6359
6360     write_fp_sreg(s, rd, tcg_res);
6361
6362     tcg_temp_free_ptr(fpst);
6363     tcg_temp_free_i32(tcg_op1);
6364     tcg_temp_free_i32(tcg_op2);
6365     tcg_temp_free_i32(tcg_op3);
6366     tcg_temp_free_i32(tcg_res);
6367 }
6368
6369 /* Floating point data-processing (3 source)
6370  *   31  30  29 28       24 23  22  21  20  16  15  14  10 9    5 4    0
6371  * +---+---+---+-----------+------+----+------+----+------+------+------+
6372  * | M | 0 | S | 1 1 1 1 1 | type | o1 |  Rm  | o0 |  Ra  |  Rn  |  Rd  |
6373  * +---+---+---+-----------+------+----+------+----+------+------+------+
6374  */
6375 static void disas_fp_3src(DisasContext *s, uint32_t insn)
6376 {
6377     int mos = extract32(insn, 29, 3);
6378     int type = extract32(insn, 22, 2);
6379     int rd = extract32(insn, 0, 5);
6380     int rn = extract32(insn, 5, 5);
6381     int ra = extract32(insn, 10, 5);
6382     int rm = extract32(insn, 16, 5);
6383     bool o0 = extract32(insn, 15, 1);
6384     bool o1 = extract32(insn, 21, 1);
6385
6386     if (mos) {
6387         unallocated_encoding(s);
6388         return;
6389     }
6390
6391     switch (type) {
6392     case 0:
6393         if (!fp_access_check(s)) {
6394             return;
6395         }
6396         handle_fp_3src_single(s, o0, o1, rd, rn, rm, ra);
6397         break;
6398     case 1:
6399         if (!fp_access_check(s)) {
6400             return;
6401         }
6402         handle_fp_3src_double(s, o0, o1, rd, rn, rm, ra);
6403         break;
6404     case 3:
6405         if (!dc_isar_feature(aa64_fp16, s)) {
6406             unallocated_encoding(s);
6407             return;
6408         }
6409         if (!fp_access_check(s)) {
6410             return;
6411         }
6412         handle_fp_3src_half(s, o0, o1, rd, rn, rm, ra);
6413         break;
6414     default:
6415         unallocated_encoding(s);
6416     }
6417 }
6418
6419 /* Floating point immediate
6420  *   31  30  29 28       24 23  22  21 20        13 12   10 9    5 4    0
6421  * +---+---+---+-----------+------+---+------------+-------+------+------+
6422  * | M | 0 | S | 1 1 1 1 0 | type | 1 |    imm8    | 1 0 0 | imm5 |  Rd  |
6423  * +---+---+---+-----------+------+---+------------+-------+------+------+
6424  */
6425 static void disas_fp_imm(DisasContext *s, uint32_t insn)
6426 {
6427     int rd = extract32(insn, 0, 5);
6428     int imm5 = extract32(insn, 5, 5);
6429     int imm8 = extract32(insn, 13, 8);
6430     int type = extract32(insn, 22, 2);
6431     int mos = extract32(insn, 29, 3);
6432     uint64_t imm;
6433     TCGv_i64 tcg_res;
6434     MemOp sz;
6435
6436     if (mos || imm5) {
6437         unallocated_encoding(s);
6438         return;
6439     }
6440
6441     switch (type) {
6442     case 0:
6443         sz = MO_32;
6444         break;
6445     case 1:
6446         sz = MO_64;
6447         break;
6448     case 3:
6449         sz = MO_16;
6450         if (dc_isar_feature(aa64_fp16, s)) {
6451             break;
6452         }
6453         /* fallthru */
6454     default:
6455         unallocated_encoding(s);
6456         return;
6457     }
6458
6459     if (!fp_access_check(s)) {
6460         return;
6461     }
6462
6463     imm = vfp_expand_imm(sz, imm8);
6464
6465     tcg_res = tcg_const_i64(imm);
6466     write_fp_dreg(s, rd, tcg_res);
6467     tcg_temp_free_i64(tcg_res);
6468 }
6469
6470 /* Handle floating point <=> fixed point conversions. Note that we can
6471  * also deal with fp <=> integer conversions as a special case (scale == 64)
6472  * OPTME: consider handling that special case specially or at least skipping
6473  * the call to scalbn in the helpers for zero shifts.
6474  */
6475 static void handle_fpfpcvt(DisasContext *s, int rd, int rn, int opcode,
6476                            bool itof, int rmode, int scale, int sf, int type)
6477 {
6478     bool is_signed = !(opcode & 1);
6479     TCGv_ptr tcg_fpstatus;
6480     TCGv_i32 tcg_shift, tcg_single;
6481     TCGv_i64 tcg_double;
6482
6483     tcg_fpstatus = get_fpstatus_ptr(type == 3);
6484
6485     tcg_shift = tcg_const_i32(64 - scale);
6486
6487     if (itof) {
6488         TCGv_i64 tcg_int = cpu_reg(s, rn);
6489         if (!sf) {
6490             TCGv_i64 tcg_extend = new_tmp_a64(s);
6491
6492             if (is_signed) {
6493                 tcg_gen_ext32s_i64(tcg_extend, tcg_int);
6494             } else {
6495                 tcg_gen_ext32u_i64(tcg_extend, tcg_int);
6496             }
6497
6498             tcg_int = tcg_extend;
6499         }
6500
6501         switch (type) {
6502         case 1: /* float64 */
6503             tcg_double = tcg_temp_new_i64();
6504             if (is_signed) {
6505                 gen_helper_vfp_sqtod(tcg_double, tcg_int,
6506                                      tcg_shift, tcg_fpstatus);
6507             } else {
6508                 gen_helper_vfp_uqtod(tcg_double, tcg_int,
6509                                      tcg_shift, tcg_fpstatus);
6510             }
6511             write_fp_dreg(s, rd, tcg_double);
6512             tcg_temp_free_i64(tcg_double);
6513             break;
6514
6515         case 0: /* float32 */
6516             tcg_single = tcg_temp_new_i32();
6517             if (is_signed) {
6518                 gen_helper_vfp_sqtos(tcg_single, tcg_int,
6519                                      tcg_shift, tcg_fpstatus);
6520             } else {
6521                 gen_helper_vfp_uqtos(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         case 3: /* float16 */
6529             tcg_single = tcg_temp_new_i32();
6530             if (is_signed) {
6531                 gen_helper_vfp_sqtoh(tcg_single, tcg_int,
6532                                      tcg_shift, tcg_fpstatus);
6533             } else {
6534                 gen_helper_vfp_uqtoh(tcg_single, tcg_int,
6535                                      tcg_shift, tcg_fpstatus);
6536             }
6537             write_fp_sreg(s, rd, tcg_single);
6538             tcg_temp_free_i32(tcg_single);
6539             break;
6540
6541         default:
6542             g_assert_not_reached();
6543         }
6544     } else {
6545         TCGv_i64 tcg_int = cpu_reg(s, rd);
6546         TCGv_i32 tcg_rmode;
6547
6548         if (extract32(opcode, 2, 1)) {
6549             /* There are too many rounding modes to all fit into rmode,
6550              * so FCVTA[US] is a special case.
6551              */
6552             rmode = FPROUNDING_TIEAWAY;
6553         }
6554
6555         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
6556
6557         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
6558
6559         switch (type) {
6560         case 1: /* float64 */
6561             tcg_double = read_fp_dreg(s, rn);
6562             if (is_signed) {
6563                 if (!sf) {
6564                     gen_helper_vfp_tosld(tcg_int, tcg_double,
6565                                          tcg_shift, tcg_fpstatus);
6566                 } else {
6567                     gen_helper_vfp_tosqd(tcg_int, tcg_double,
6568                                          tcg_shift, tcg_fpstatus);
6569                 }
6570             } else {
6571                 if (!sf) {
6572                     gen_helper_vfp_tould(tcg_int, tcg_double,
6573                                          tcg_shift, tcg_fpstatus);
6574                 } else {
6575                     gen_helper_vfp_touqd(tcg_int, tcg_double,
6576                                          tcg_shift, tcg_fpstatus);
6577                 }
6578             }
6579             if (!sf) {
6580                 tcg_gen_ext32u_i64(tcg_int, tcg_int);
6581             }
6582             tcg_temp_free_i64(tcg_double);
6583             break;
6584
6585         case 0: /* float32 */
6586             tcg_single = read_fp_sreg(s, rn);
6587             if (sf) {
6588                 if (is_signed) {
6589                     gen_helper_vfp_tosqs(tcg_int, tcg_single,
6590                                          tcg_shift, tcg_fpstatus);
6591                 } else {
6592                     gen_helper_vfp_touqs(tcg_int, tcg_single,
6593                                          tcg_shift, tcg_fpstatus);
6594                 }
6595             } else {
6596                 TCGv_i32 tcg_dest = tcg_temp_new_i32();
6597                 if (is_signed) {
6598                     gen_helper_vfp_tosls(tcg_dest, tcg_single,
6599                                          tcg_shift, tcg_fpstatus);
6600                 } else {
6601                     gen_helper_vfp_touls(tcg_dest, tcg_single,
6602                                          tcg_shift, tcg_fpstatus);
6603                 }
6604                 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
6605                 tcg_temp_free_i32(tcg_dest);
6606             }
6607             tcg_temp_free_i32(tcg_single);
6608             break;
6609
6610         case 3: /* float16 */
6611             tcg_single = read_fp_sreg(s, rn);
6612             if (sf) {
6613                 if (is_signed) {
6614                     gen_helper_vfp_tosqh(tcg_int, tcg_single,
6615                                          tcg_shift, tcg_fpstatus);
6616                 } else {
6617                     gen_helper_vfp_touqh(tcg_int, tcg_single,
6618                                          tcg_shift, tcg_fpstatus);
6619                 }
6620             } else {
6621                 TCGv_i32 tcg_dest = tcg_temp_new_i32();
6622                 if (is_signed) {
6623                     gen_helper_vfp_toslh(tcg_dest, tcg_single,
6624                                          tcg_shift, tcg_fpstatus);
6625                 } else {
6626                     gen_helper_vfp_toulh(tcg_dest, tcg_single,
6627                                          tcg_shift, tcg_fpstatus);
6628                 }
6629                 tcg_gen_extu_i32_i64(tcg_int, tcg_dest);
6630                 tcg_temp_free_i32(tcg_dest);
6631             }
6632             tcg_temp_free_i32(tcg_single);
6633             break;
6634
6635         default:
6636             g_assert_not_reached();
6637         }
6638
6639         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
6640         tcg_temp_free_i32(tcg_rmode);
6641     }
6642
6643     tcg_temp_free_ptr(tcg_fpstatus);
6644     tcg_temp_free_i32(tcg_shift);
6645 }
6646
6647 /* Floating point <-> fixed point conversions
6648  *   31   30  29 28       24 23  22  21 20   19 18    16 15   10 9    5 4    0
6649  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
6650  * | sf | 0 | S | 1 1 1 1 0 | type | 0 | rmode | opcode | scale |  Rn  |  Rd  |
6651  * +----+---+---+-----------+------+---+-------+--------+-------+------+------+
6652  */
6653 static void disas_fp_fixed_conv(DisasContext *s, uint32_t insn)
6654 {
6655     int rd = extract32(insn, 0, 5);
6656     int rn = extract32(insn, 5, 5);
6657     int scale = extract32(insn, 10, 6);
6658     int opcode = extract32(insn, 16, 3);
6659     int rmode = extract32(insn, 19, 2);
6660     int type = extract32(insn, 22, 2);
6661     bool sbit = extract32(insn, 29, 1);
6662     bool sf = extract32(insn, 31, 1);
6663     bool itof;
6664
6665     if (sbit || (!sf && scale < 32)) {
6666         unallocated_encoding(s);
6667         return;
6668     }
6669
6670     switch (type) {
6671     case 0: /* float32 */
6672     case 1: /* float64 */
6673         break;
6674     case 3: /* float16 */
6675         if (dc_isar_feature(aa64_fp16, s)) {
6676             break;
6677         }
6678         /* fallthru */
6679     default:
6680         unallocated_encoding(s);
6681         return;
6682     }
6683
6684     switch ((rmode << 3) | opcode) {
6685     case 0x2: /* SCVTF */
6686     case 0x3: /* UCVTF */
6687         itof = true;
6688         break;
6689     case 0x18: /* FCVTZS */
6690     case 0x19: /* FCVTZU */
6691         itof = false;
6692         break;
6693     default:
6694         unallocated_encoding(s);
6695         return;
6696     }
6697
6698     if (!fp_access_check(s)) {
6699         return;
6700     }
6701
6702     handle_fpfpcvt(s, rd, rn, opcode, itof, FPROUNDING_ZERO, scale, sf, type);
6703 }
6704
6705 static void handle_fmov(DisasContext *s, int rd, int rn, int type, bool itof)
6706 {
6707     /* FMOV: gpr to or from float, double, or top half of quad fp reg,
6708      * without conversion.
6709      */
6710
6711     if (itof) {
6712         TCGv_i64 tcg_rn = cpu_reg(s, rn);
6713         TCGv_i64 tmp;
6714
6715         switch (type) {
6716         case 0:
6717             /* 32 bit */
6718             tmp = tcg_temp_new_i64();
6719             tcg_gen_ext32u_i64(tmp, tcg_rn);
6720             write_fp_dreg(s, rd, tmp);
6721             tcg_temp_free_i64(tmp);
6722             break;
6723         case 1:
6724             /* 64 bit */
6725             write_fp_dreg(s, rd, tcg_rn);
6726             break;
6727         case 2:
6728             /* 64 bit to top half. */
6729             tcg_gen_st_i64(tcg_rn, cpu_env, fp_reg_hi_offset(s, rd));
6730             clear_vec_high(s, true, rd);
6731             break;
6732         case 3:
6733             /* 16 bit */
6734             tmp = tcg_temp_new_i64();
6735             tcg_gen_ext16u_i64(tmp, tcg_rn);
6736             write_fp_dreg(s, rd, tmp);
6737             tcg_temp_free_i64(tmp);
6738             break;
6739         default:
6740             g_assert_not_reached();
6741         }
6742     } else {
6743         TCGv_i64 tcg_rd = cpu_reg(s, rd);
6744
6745         switch (type) {
6746         case 0:
6747             /* 32 bit */
6748             tcg_gen_ld32u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_32));
6749             break;
6750         case 1:
6751             /* 64 bit */
6752             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_64));
6753             break;
6754         case 2:
6755             /* 64 bits from top half */
6756             tcg_gen_ld_i64(tcg_rd, cpu_env, fp_reg_hi_offset(s, rn));
6757             break;
6758         case 3:
6759             /* 16 bit */
6760             tcg_gen_ld16u_i64(tcg_rd, cpu_env, fp_reg_offset(s, rn, MO_16));
6761             break;
6762         default:
6763             g_assert_not_reached();
6764         }
6765     }
6766 }
6767
6768 static void handle_fjcvtzs(DisasContext *s, int rd, int rn)
6769 {
6770     TCGv_i64 t = read_fp_dreg(s, rn);
6771     TCGv_ptr fpstatus = get_fpstatus_ptr(false);
6772
6773     gen_helper_fjcvtzs(t, t, fpstatus);
6774
6775     tcg_temp_free_ptr(fpstatus);
6776
6777     tcg_gen_ext32u_i64(cpu_reg(s, rd), t);
6778     tcg_gen_extrh_i64_i32(cpu_ZF, t);
6779     tcg_gen_movi_i32(cpu_CF, 0);
6780     tcg_gen_movi_i32(cpu_NF, 0);
6781     tcg_gen_movi_i32(cpu_VF, 0);
6782
6783     tcg_temp_free_i64(t);
6784 }
6785
6786 /* Floating point <-> integer conversions
6787  *   31   30  29 28       24 23  22  21 20   19 18 16 15         10 9  5 4  0
6788  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
6789  * | sf | 0 | S | 1 1 1 1 0 | type | 1 | rmode | opc | 0 0 0 0 0 0 | Rn | Rd |
6790  * +----+---+---+-----------+------+---+-------+-----+-------------+----+----+
6791  */
6792 static void disas_fp_int_conv(DisasContext *s, uint32_t insn)
6793 {
6794     int rd = extract32(insn, 0, 5);
6795     int rn = extract32(insn, 5, 5);
6796     int opcode = extract32(insn, 16, 3);
6797     int rmode = extract32(insn, 19, 2);
6798     int type = extract32(insn, 22, 2);
6799     bool sbit = extract32(insn, 29, 1);
6800     bool sf = extract32(insn, 31, 1);
6801     bool itof = false;
6802
6803     if (sbit) {
6804         goto do_unallocated;
6805     }
6806
6807     switch (opcode) {
6808     case 2: /* SCVTF */
6809     case 3: /* UCVTF */
6810         itof = true;
6811         /* fallthru */
6812     case 4: /* FCVTAS */
6813     case 5: /* FCVTAU */
6814         if (rmode != 0) {
6815             goto do_unallocated;
6816         }
6817         /* fallthru */
6818     case 0: /* FCVT[NPMZ]S */
6819     case 1: /* FCVT[NPMZ]U */
6820         switch (type) {
6821         case 0: /* float32 */
6822         case 1: /* float64 */
6823             break;
6824         case 3: /* float16 */
6825             if (!dc_isar_feature(aa64_fp16, s)) {
6826                 goto do_unallocated;
6827             }
6828             break;
6829         default:
6830             goto do_unallocated;
6831         }
6832         if (!fp_access_check(s)) {
6833             return;
6834         }
6835         handle_fpfpcvt(s, rd, rn, opcode, itof, rmode, 64, sf, type);
6836         break;
6837
6838     default:
6839         switch (sf << 7 | type << 5 | rmode << 3 | opcode) {
6840         case 0b01100110: /* FMOV half <-> 32-bit int */
6841         case 0b01100111:
6842         case 0b11100110: /* FMOV half <-> 64-bit int */
6843         case 0b11100111:
6844             if (!dc_isar_feature(aa64_fp16, s)) {
6845                 goto do_unallocated;
6846             }
6847             /* fallthru */
6848         case 0b00000110: /* FMOV 32-bit */
6849         case 0b00000111:
6850         case 0b10100110: /* FMOV 64-bit */
6851         case 0b10100111:
6852         case 0b11001110: /* FMOV top half of 128-bit */
6853         case 0b11001111:
6854             if (!fp_access_check(s)) {
6855                 return;
6856             }
6857             itof = opcode & 1;
6858             handle_fmov(s, rd, rn, type, itof);
6859             break;
6860
6861         case 0b00111110: /* FJCVTZS */
6862             if (!dc_isar_feature(aa64_jscvt, s)) {
6863                 goto do_unallocated;
6864             } else if (fp_access_check(s)) {
6865                 handle_fjcvtzs(s, rd, rn);
6866             }
6867             break;
6868
6869         default:
6870         do_unallocated:
6871             unallocated_encoding(s);
6872             return;
6873         }
6874         break;
6875     }
6876 }
6877
6878 /* FP-specific subcases of table C3-6 (SIMD and FP data processing)
6879  *   31  30  29 28     25 24                          0
6880  * +---+---+---+---------+-----------------------------+
6881  * |   | 0 |   | 1 1 1 1 |                             |
6882  * +---+---+---+---------+-----------------------------+
6883  */
6884 static void disas_data_proc_fp(DisasContext *s, uint32_t insn)
6885 {
6886     if (extract32(insn, 24, 1)) {
6887         /* Floating point data-processing (3 source) */
6888         disas_fp_3src(s, insn);
6889     } else if (extract32(insn, 21, 1) == 0) {
6890         /* Floating point to fixed point conversions */
6891         disas_fp_fixed_conv(s, insn);
6892     } else {
6893         switch (extract32(insn, 10, 2)) {
6894         case 1:
6895             /* Floating point conditional compare */
6896             disas_fp_ccomp(s, insn);
6897             break;
6898         case 2:
6899             /* Floating point data-processing (2 source) */
6900             disas_fp_2src(s, insn);
6901             break;
6902         case 3:
6903             /* Floating point conditional select */
6904             disas_fp_csel(s, insn);
6905             break;
6906         case 0:
6907             switch (ctz32(extract32(insn, 12, 4))) {
6908             case 0: /* [15:12] == xxx1 */
6909                 /* Floating point immediate */
6910                 disas_fp_imm(s, insn);
6911                 break;
6912             case 1: /* [15:12] == xx10 */
6913                 /* Floating point compare */
6914                 disas_fp_compare(s, insn);
6915                 break;
6916             case 2: /* [15:12] == x100 */
6917                 /* Floating point data-processing (1 source) */
6918                 disas_fp_1src(s, insn);
6919                 break;
6920             case 3: /* [15:12] == 1000 */
6921                 unallocated_encoding(s);
6922                 break;
6923             default: /* [15:12] == 0000 */
6924                 /* Floating point <-> integer conversions */
6925                 disas_fp_int_conv(s, insn);
6926                 break;
6927             }
6928             break;
6929         }
6930     }
6931 }
6932
6933 static void do_ext64(DisasContext *s, TCGv_i64 tcg_left, TCGv_i64 tcg_right,
6934                      int pos)
6935 {
6936     /* Extract 64 bits from the middle of two concatenated 64 bit
6937      * vector register slices left:right. The extracted bits start
6938      * at 'pos' bits into the right (least significant) side.
6939      * We return the result in tcg_right, and guarantee not to
6940      * trash tcg_left.
6941      */
6942     TCGv_i64 tcg_tmp = tcg_temp_new_i64();
6943     assert(pos > 0 && pos < 64);
6944
6945     tcg_gen_shri_i64(tcg_right, tcg_right, pos);
6946     tcg_gen_shli_i64(tcg_tmp, tcg_left, 64 - pos);
6947     tcg_gen_or_i64(tcg_right, tcg_right, tcg_tmp);
6948
6949     tcg_temp_free_i64(tcg_tmp);
6950 }
6951
6952 /* EXT
6953  *   31  30 29         24 23 22  21 20  16 15  14  11 10  9    5 4    0
6954  * +---+---+-------------+-----+---+------+---+------+---+------+------+
6955  * | 0 | Q | 1 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | imm4 | 0 |  Rn  |  Rd  |
6956  * +---+---+-------------+-----+---+------+---+------+---+------+------+
6957  */
6958 static void disas_simd_ext(DisasContext *s, uint32_t insn)
6959 {
6960     int is_q = extract32(insn, 30, 1);
6961     int op2 = extract32(insn, 22, 2);
6962     int imm4 = extract32(insn, 11, 4);
6963     int rm = extract32(insn, 16, 5);
6964     int rn = extract32(insn, 5, 5);
6965     int rd = extract32(insn, 0, 5);
6966     int pos = imm4 << 3;
6967     TCGv_i64 tcg_resl, tcg_resh;
6968
6969     if (op2 != 0 || (!is_q && extract32(imm4, 3, 1))) {
6970         unallocated_encoding(s);
6971         return;
6972     }
6973
6974     if (!fp_access_check(s)) {
6975         return;
6976     }
6977
6978     tcg_resh = tcg_temp_new_i64();
6979     tcg_resl = tcg_temp_new_i64();
6980
6981     /* Vd gets bits starting at pos bits into Vm:Vn. This is
6982      * either extracting 128 bits from a 128:128 concatenation, or
6983      * extracting 64 bits from a 64:64 concatenation.
6984      */
6985     if (!is_q) {
6986         read_vec_element(s, tcg_resl, rn, 0, MO_64);
6987         if (pos != 0) {
6988             read_vec_element(s, tcg_resh, rm, 0, MO_64);
6989             do_ext64(s, tcg_resh, tcg_resl, pos);
6990         }
6991         tcg_gen_movi_i64(tcg_resh, 0);
6992     } else {
6993         TCGv_i64 tcg_hh;
6994         typedef struct {
6995             int reg;
6996             int elt;
6997         } EltPosns;
6998         EltPosns eltposns[] = { {rn, 0}, {rn, 1}, {rm, 0}, {rm, 1} };
6999         EltPosns *elt = eltposns;
7000
7001         if (pos >= 64) {
7002             elt++;
7003             pos -= 64;
7004         }
7005
7006         read_vec_element(s, tcg_resl, elt->reg, elt->elt, MO_64);
7007         elt++;
7008         read_vec_element(s, tcg_resh, elt->reg, elt->elt, MO_64);
7009         elt++;
7010         if (pos != 0) {
7011             do_ext64(s, tcg_resh, tcg_resl, pos);
7012             tcg_hh = tcg_temp_new_i64();
7013             read_vec_element(s, tcg_hh, elt->reg, elt->elt, MO_64);
7014             do_ext64(s, tcg_hh, tcg_resh, pos);
7015             tcg_temp_free_i64(tcg_hh);
7016         }
7017     }
7018
7019     write_vec_element(s, tcg_resl, rd, 0, MO_64);
7020     tcg_temp_free_i64(tcg_resl);
7021     write_vec_element(s, tcg_resh, rd, 1, MO_64);
7022     tcg_temp_free_i64(tcg_resh);
7023     clear_vec_high(s, true, rd);
7024 }
7025
7026 /* TBL/TBX
7027  *   31  30 29         24 23 22  21 20  16 15  14 13  12  11 10 9    5 4    0
7028  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
7029  * | 0 | Q | 0 0 1 1 1 0 | op2 | 0 |  Rm  | 0 | len | op | 0 0 |  Rn  |  Rd  |
7030  * +---+---+-------------+-----+---+------+---+-----+----+-----+------+------+
7031  */
7032 static void disas_simd_tb(DisasContext *s, uint32_t insn)
7033 {
7034     int op2 = extract32(insn, 22, 2);
7035     int is_q = extract32(insn, 30, 1);
7036     int rm = extract32(insn, 16, 5);
7037     int rn = extract32(insn, 5, 5);
7038     int rd = extract32(insn, 0, 5);
7039     int is_tblx = extract32(insn, 12, 1);
7040     int len = extract32(insn, 13, 2);
7041     TCGv_i64 tcg_resl, tcg_resh, tcg_idx;
7042     TCGv_i32 tcg_regno, tcg_numregs;
7043
7044     if (op2 != 0) {
7045         unallocated_encoding(s);
7046         return;
7047     }
7048
7049     if (!fp_access_check(s)) {
7050         return;
7051     }
7052
7053     /* This does a table lookup: for every byte element in the input
7054      * we index into a table formed from up to four vector registers,
7055      * and then the output is the result of the lookups. Our helper
7056      * function does the lookup operation for a single 64 bit part of
7057      * the input.
7058      */
7059     tcg_resl = tcg_temp_new_i64();
7060     tcg_resh = tcg_temp_new_i64();
7061
7062     if (is_tblx) {
7063         read_vec_element(s, tcg_resl, rd, 0, MO_64);
7064     } else {
7065         tcg_gen_movi_i64(tcg_resl, 0);
7066     }
7067     if (is_tblx && is_q) {
7068         read_vec_element(s, tcg_resh, rd, 1, MO_64);
7069     } else {
7070         tcg_gen_movi_i64(tcg_resh, 0);
7071     }
7072
7073     tcg_idx = tcg_temp_new_i64();
7074     tcg_regno = tcg_const_i32(rn);
7075     tcg_numregs = tcg_const_i32(len + 1);
7076     read_vec_element(s, tcg_idx, rm, 0, MO_64);
7077     gen_helper_simd_tbl(tcg_resl, cpu_env, tcg_resl, tcg_idx,
7078                         tcg_regno, tcg_numregs);
7079     if (is_q) {
7080         read_vec_element(s, tcg_idx, rm, 1, MO_64);
7081         gen_helper_simd_tbl(tcg_resh, cpu_env, tcg_resh, tcg_idx,
7082                             tcg_regno, tcg_numregs);
7083     }
7084     tcg_temp_free_i64(tcg_idx);
7085     tcg_temp_free_i32(tcg_regno);
7086     tcg_temp_free_i32(tcg_numregs);
7087
7088     write_vec_element(s, tcg_resl, rd, 0, MO_64);
7089     tcg_temp_free_i64(tcg_resl);
7090     write_vec_element(s, tcg_resh, rd, 1, MO_64);
7091     tcg_temp_free_i64(tcg_resh);
7092     clear_vec_high(s, true, rd);
7093 }
7094
7095 /* ZIP/UZP/TRN
7096  *   31  30 29         24 23  22  21 20   16 15 14 12 11 10 9    5 4    0
7097  * +---+---+-------------+------+---+------+---+------------------+------+
7098  * | 0 | Q | 0 0 1 1 1 0 | size | 0 |  Rm  | 0 | opc | 1 0 |  Rn  |  Rd  |
7099  * +---+---+-------------+------+---+------+---+------------------+------+
7100  */
7101 static void disas_simd_zip_trn(DisasContext *s, uint32_t insn)
7102 {
7103     int rd = extract32(insn, 0, 5);
7104     int rn = extract32(insn, 5, 5);
7105     int rm = extract32(insn, 16, 5);
7106     int size = extract32(insn, 22, 2);
7107     /* opc field bits [1:0] indicate ZIP/UZP/TRN;
7108      * bit 2 indicates 1 vs 2 variant of the insn.
7109      */
7110     int opcode = extract32(insn, 12, 2);
7111     bool part = extract32(insn, 14, 1);
7112     bool is_q = extract32(insn, 30, 1);
7113     int esize = 8 << size;
7114     int i, ofs;
7115     int datasize = is_q ? 128 : 64;
7116     int elements = datasize / esize;
7117     TCGv_i64 tcg_res, tcg_resl, tcg_resh;
7118
7119     if (opcode == 0 || (size == 3 && !is_q)) {
7120         unallocated_encoding(s);
7121         return;
7122     }
7123
7124     if (!fp_access_check(s)) {
7125         return;
7126     }
7127
7128     tcg_resl = tcg_const_i64(0);
7129     tcg_resh = tcg_const_i64(0);
7130     tcg_res = tcg_temp_new_i64();
7131
7132     for (i = 0; i < elements; i++) {
7133         switch (opcode) {
7134         case 1: /* UZP1/2 */
7135         {
7136             int midpoint = elements / 2;
7137             if (i < midpoint) {
7138                 read_vec_element(s, tcg_res, rn, 2 * i + part, size);
7139             } else {
7140                 read_vec_element(s, tcg_res, rm,
7141                                  2 * (i - midpoint) + part, size);
7142             }
7143             break;
7144         }
7145         case 2: /* TRN1/2 */
7146             if (i & 1) {
7147                 read_vec_element(s, tcg_res, rm, (i & ~1) + part, size);
7148             } else {
7149                 read_vec_element(s, tcg_res, rn, (i & ~1) + part, size);
7150             }
7151             break;
7152         case 3: /* ZIP1/2 */
7153         {
7154             int base = part * elements / 2;
7155             if (i & 1) {
7156                 read_vec_element(s, tcg_res, rm, base + (i >> 1), size);
7157             } else {
7158                 read_vec_element(s, tcg_res, rn, base + (i >> 1), size);
7159             }
7160             break;
7161         }
7162         default:
7163             g_assert_not_reached();
7164         }
7165
7166         ofs = i * esize;
7167         if (ofs < 64) {
7168             tcg_gen_shli_i64(tcg_res, tcg_res, ofs);
7169             tcg_gen_or_i64(tcg_resl, tcg_resl, tcg_res);
7170         } else {
7171             tcg_gen_shli_i64(tcg_res, tcg_res, ofs - 64);
7172             tcg_gen_or_i64(tcg_resh, tcg_resh, tcg_res);
7173         }
7174     }
7175
7176     tcg_temp_free_i64(tcg_res);
7177
7178     write_vec_element(s, tcg_resl, rd, 0, MO_64);
7179     tcg_temp_free_i64(tcg_resl);
7180     write_vec_element(s, tcg_resh, rd, 1, MO_64);
7181     tcg_temp_free_i64(tcg_resh);
7182     clear_vec_high(s, true, rd);
7183 }
7184
7185 /*
7186  * do_reduction_op helper
7187  *
7188  * This mirrors the Reduce() pseudocode in the ARM ARM. It is
7189  * important for correct NaN propagation that we do these
7190  * operations in exactly the order specified by the pseudocode.
7191  *
7192  * This is a recursive function, TCG temps should be freed by the
7193  * calling function once it is done with the values.
7194  */
7195 static TCGv_i32 do_reduction_op(DisasContext *s, int fpopcode, int rn,
7196                                 int esize, int size, int vmap, TCGv_ptr fpst)
7197 {
7198     if (esize == size) {
7199         int element;
7200         MemOp msize = esize == 16 ? MO_16 : MO_32;
7201         TCGv_i32 tcg_elem;
7202
7203         /* We should have one register left here */
7204         assert(ctpop8(vmap) == 1);
7205         element = ctz32(vmap);
7206         assert(element < 8);
7207
7208         tcg_elem = tcg_temp_new_i32();
7209         read_vec_element_i32(s, tcg_elem, rn, element, msize);
7210         return tcg_elem;
7211     } else {
7212         int bits = size / 2;
7213         int shift = ctpop8(vmap) / 2;
7214         int vmap_lo = (vmap >> shift) & vmap;
7215         int vmap_hi = (vmap & ~vmap_lo);
7216         TCGv_i32 tcg_hi, tcg_lo, tcg_res;
7217
7218         tcg_hi = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_hi, fpst);
7219         tcg_lo = do_reduction_op(s, fpopcode, rn, esize, bits, vmap_lo, fpst);
7220         tcg_res = tcg_temp_new_i32();
7221
7222         switch (fpopcode) {
7223         case 0x0c: /* fmaxnmv half-precision */
7224             gen_helper_advsimd_maxnumh(tcg_res, tcg_lo, tcg_hi, fpst);
7225             break;
7226         case 0x0f: /* fmaxv half-precision */
7227             gen_helper_advsimd_maxh(tcg_res, tcg_lo, tcg_hi, fpst);
7228             break;
7229         case 0x1c: /* fminnmv half-precision */
7230             gen_helper_advsimd_minnumh(tcg_res, tcg_lo, tcg_hi, fpst);
7231             break;
7232         case 0x1f: /* fminv half-precision */
7233             gen_helper_advsimd_minh(tcg_res, tcg_lo, tcg_hi, fpst);
7234             break;
7235         case 0x2c: /* fmaxnmv */
7236             gen_helper_vfp_maxnums(tcg_res, tcg_lo, tcg_hi, fpst);
7237             break;
7238         case 0x2f: /* fmaxv */
7239             gen_helper_vfp_maxs(tcg_res, tcg_lo, tcg_hi, fpst);
7240             break;
7241         case 0x3c: /* fminnmv */
7242             gen_helper_vfp_minnums(tcg_res, tcg_lo, tcg_hi, fpst);
7243             break;
7244         case 0x3f: /* fminv */
7245             gen_helper_vfp_mins(tcg_res, tcg_lo, tcg_hi, fpst);
7246             break;
7247         default:
7248             g_assert_not_reached();
7249         }
7250
7251         tcg_temp_free_i32(tcg_hi);
7252         tcg_temp_free_i32(tcg_lo);
7253         return tcg_res;
7254     }
7255 }
7256
7257 /* AdvSIMD across lanes
7258  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
7259  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
7260  * | 0 | Q | U | 0 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
7261  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
7262  */
7263 static void disas_simd_across_lanes(DisasContext *s, uint32_t insn)
7264 {
7265     int rd = extract32(insn, 0, 5);
7266     int rn = extract32(insn, 5, 5);
7267     int size = extract32(insn, 22, 2);
7268     int opcode = extract32(insn, 12, 5);
7269     bool is_q = extract32(insn, 30, 1);
7270     bool is_u = extract32(insn, 29, 1);
7271     bool is_fp = false;
7272     bool is_min = false;
7273     int esize;
7274     int elements;
7275     int i;
7276     TCGv_i64 tcg_res, tcg_elt;
7277
7278     switch (opcode) {
7279     case 0x1b: /* ADDV */
7280         if (is_u) {
7281             unallocated_encoding(s);
7282             return;
7283         }
7284         /* fall through */
7285     case 0x3: /* SADDLV, UADDLV */
7286     case 0xa: /* SMAXV, UMAXV */
7287     case 0x1a: /* SMINV, UMINV */
7288         if (size == 3 || (size == 2 && !is_q)) {
7289             unallocated_encoding(s);
7290             return;
7291         }
7292         break;
7293     case 0xc: /* FMAXNMV, FMINNMV */
7294     case 0xf: /* FMAXV, FMINV */
7295         /* Bit 1 of size field encodes min vs max and the actual size
7296          * depends on the encoding of the U bit. If not set (and FP16
7297          * enabled) then we do half-precision float instead of single
7298          * precision.
7299          */
7300         is_min = extract32(size, 1, 1);
7301         is_fp = true;
7302         if (!is_u && dc_isar_feature(aa64_fp16, s)) {
7303             size = 1;
7304         } else if (!is_u || !is_q || extract32(size, 0, 1)) {
7305             unallocated_encoding(s);
7306             return;
7307         } else {
7308             size = 2;
7309         }
7310         break;
7311     default:
7312         unallocated_encoding(s);
7313         return;
7314     }
7315
7316     if (!fp_access_check(s)) {
7317         return;
7318     }
7319
7320     esize = 8 << size;
7321     elements = (is_q ? 128 : 64) / esize;
7322
7323     tcg_res = tcg_temp_new_i64();
7324     tcg_elt = tcg_temp_new_i64();
7325
7326     /* These instructions operate across all lanes of a vector
7327      * to produce a single result. We can guarantee that a 64
7328      * bit intermediate is sufficient:
7329      *  + for [US]ADDLV the maximum element size is 32 bits, and
7330      *    the result type is 64 bits
7331      *  + for FMAX*V, FMIN*V, ADDV the intermediate type is the
7332      *    same as the element size, which is 32 bits at most
7333      * For the integer operations we can choose to work at 64
7334      * or 32 bits and truncate at the end; for simplicity
7335      * we use 64 bits always. The floating point
7336      * ops do require 32 bit intermediates, though.
7337      */
7338     if (!is_fp) {
7339         read_vec_element(s, tcg_res, rn, 0, size | (is_u ? 0 : MO_SIGN));
7340
7341         for (i = 1; i < elements; i++) {
7342             read_vec_element(s, tcg_elt, rn, i, size | (is_u ? 0 : MO_SIGN));
7343
7344             switch (opcode) {
7345             case 0x03: /* SADDLV / UADDLV */
7346             case 0x1b: /* ADDV */
7347                 tcg_gen_add_i64(tcg_res, tcg_res, tcg_elt);
7348                 break;
7349             case 0x0a: /* SMAXV / UMAXV */
7350                 if (is_u) {
7351                     tcg_gen_umax_i64(tcg_res, tcg_res, tcg_elt);
7352                 } else {
7353                     tcg_gen_smax_i64(tcg_res, tcg_res, tcg_elt);
7354                 }
7355                 break;
7356             case 0x1a: /* SMINV / UMINV */
7357                 if (is_u) {
7358                     tcg_gen_umin_i64(tcg_res, tcg_res, tcg_elt);
7359                 } else {
7360                     tcg_gen_smin_i64(tcg_res, tcg_res, tcg_elt);
7361                 }
7362                 break;
7363             default:
7364                 g_assert_not_reached();
7365             }
7366
7367         }
7368     } else {
7369         /* Floating point vector reduction ops which work across 32
7370          * bit (single) or 16 bit (half-precision) intermediates.
7371          * Note that correct NaN propagation requires that we do these
7372          * operations in exactly the order specified by the pseudocode.
7373          */
7374         TCGv_ptr fpst = get_fpstatus_ptr(size == MO_16);
7375         int fpopcode = opcode | is_min << 4 | is_u << 5;
7376         int vmap = (1 << elements) - 1;
7377         TCGv_i32 tcg_res32 = do_reduction_op(s, fpopcode, rn, esize,
7378                                              (is_q ? 128 : 64), vmap, fpst);
7379         tcg_gen_extu_i32_i64(tcg_res, tcg_res32);
7380         tcg_temp_free_i32(tcg_res32);
7381         tcg_temp_free_ptr(fpst);
7382     }
7383
7384     tcg_temp_free_i64(tcg_elt);
7385
7386     /* Now truncate the result to the width required for the final output */
7387     if (opcode == 0x03) {
7388         /* SADDLV, UADDLV: result is 2*esize */
7389         size++;
7390     }
7391
7392     switch (size) {
7393     case 0:
7394         tcg_gen_ext8u_i64(tcg_res, tcg_res);
7395         break;
7396     case 1:
7397         tcg_gen_ext16u_i64(tcg_res, tcg_res);
7398         break;
7399     case 2:
7400         tcg_gen_ext32u_i64(tcg_res, tcg_res);
7401         break;
7402     case 3:
7403         break;
7404     default:
7405         g_assert_not_reached();
7406     }
7407
7408     write_fp_dreg(s, rd, tcg_res);
7409     tcg_temp_free_i64(tcg_res);
7410 }
7411
7412 /* DUP (Element, Vector)
7413  *
7414  *  31  30   29              21 20    16 15        10  9    5 4    0
7415  * +---+---+-------------------+--------+-------------+------+------+
7416  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
7417  * +---+---+-------------------+--------+-------------+------+------+
7418  *
7419  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7420  */
7421 static void handle_simd_dupe(DisasContext *s, int is_q, int rd, int rn,
7422                              int imm5)
7423 {
7424     int size = ctz32(imm5);
7425     int index;
7426
7427     if (size > 3 || (size == 3 && !is_q)) {
7428         unallocated_encoding(s);
7429         return;
7430     }
7431
7432     if (!fp_access_check(s)) {
7433         return;
7434     }
7435
7436     index = imm5 >> (size + 1);
7437     tcg_gen_gvec_dup_mem(size, vec_full_reg_offset(s, rd),
7438                          vec_reg_offset(s, rn, index, size),
7439                          is_q ? 16 : 8, vec_full_reg_size(s));
7440 }
7441
7442 /* DUP (element, scalar)
7443  *  31                   21 20    16 15        10  9    5 4    0
7444  * +-----------------------+--------+-------------+------+------+
7445  * | 0 1 0 1 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 0 1 |  Rn  |  Rd  |
7446  * +-----------------------+--------+-------------+------+------+
7447  */
7448 static void handle_simd_dupes(DisasContext *s, int rd, int rn,
7449                               int imm5)
7450 {
7451     int size = ctz32(imm5);
7452     int index;
7453     TCGv_i64 tmp;
7454
7455     if (size > 3) {
7456         unallocated_encoding(s);
7457         return;
7458     }
7459
7460     if (!fp_access_check(s)) {
7461         return;
7462     }
7463
7464     index = imm5 >> (size + 1);
7465
7466     /* This instruction just extracts the specified element and
7467      * zero-extends it into the bottom of the destination register.
7468      */
7469     tmp = tcg_temp_new_i64();
7470     read_vec_element(s, tmp, rn, index, size);
7471     write_fp_dreg(s, rd, tmp);
7472     tcg_temp_free_i64(tmp);
7473 }
7474
7475 /* DUP (General)
7476  *
7477  *  31  30   29              21 20    16 15        10  9    5 4    0
7478  * +---+---+-------------------+--------+-------------+------+------+
7479  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 0 1 1 |  Rn  |  Rd  |
7480  * +---+---+-------------------+--------+-------------+------+------+
7481  *
7482  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7483  */
7484 static void handle_simd_dupg(DisasContext *s, int is_q, int rd, int rn,
7485                              int imm5)
7486 {
7487     int size = ctz32(imm5);
7488     uint32_t dofs, oprsz, maxsz;
7489
7490     if (size > 3 || ((size == 3) && !is_q)) {
7491         unallocated_encoding(s);
7492         return;
7493     }
7494
7495     if (!fp_access_check(s)) {
7496         return;
7497     }
7498
7499     dofs = vec_full_reg_offset(s, rd);
7500     oprsz = is_q ? 16 : 8;
7501     maxsz = vec_full_reg_size(s);
7502
7503     tcg_gen_gvec_dup_i64(size, dofs, oprsz, maxsz, cpu_reg(s, rn));
7504 }
7505
7506 /* INS (Element)
7507  *
7508  *  31                   21 20    16 15  14    11  10 9    5 4    0
7509  * +-----------------------+--------+------------+---+------+------+
7510  * | 0 1 1 0 1 1 1 0 0 0 0 |  imm5  | 0 |  imm4  | 1 |  Rn  |  Rd  |
7511  * +-----------------------+--------+------------+---+------+------+
7512  *
7513  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7514  * index: encoded in imm5<4:size+1>
7515  */
7516 static void handle_simd_inse(DisasContext *s, int rd, int rn,
7517                              int imm4, int imm5)
7518 {
7519     int size = ctz32(imm5);
7520     int src_index, dst_index;
7521     TCGv_i64 tmp;
7522
7523     if (size > 3) {
7524         unallocated_encoding(s);
7525         return;
7526     }
7527
7528     if (!fp_access_check(s)) {
7529         return;
7530     }
7531
7532     dst_index = extract32(imm5, 1+size, 5);
7533     src_index = extract32(imm4, size, 4);
7534
7535     tmp = tcg_temp_new_i64();
7536
7537     read_vec_element(s, tmp, rn, src_index, size);
7538     write_vec_element(s, tmp, rd, dst_index, size);
7539
7540     tcg_temp_free_i64(tmp);
7541
7542     /* INS is considered a 128-bit write for SVE. */
7543     clear_vec_high(s, true, rd);
7544 }
7545
7546
7547 /* INS (General)
7548  *
7549  *  31                   21 20    16 15        10  9    5 4    0
7550  * +-----------------------+--------+-------------+------+------+
7551  * | 0 1 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 0 1 1 1 |  Rn  |  Rd  |
7552  * +-----------------------+--------+-------------+------+------+
7553  *
7554  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7555  * index: encoded in imm5<4:size+1>
7556  */
7557 static void handle_simd_insg(DisasContext *s, int rd, int rn, int imm5)
7558 {
7559     int size = ctz32(imm5);
7560     int idx;
7561
7562     if (size > 3) {
7563         unallocated_encoding(s);
7564         return;
7565     }
7566
7567     if (!fp_access_check(s)) {
7568         return;
7569     }
7570
7571     idx = extract32(imm5, 1 + size, 4 - size);
7572     write_vec_element(s, cpu_reg(s, rn), rd, idx, size);
7573
7574     /* INS is considered a 128-bit write for SVE. */
7575     clear_vec_high(s, true, rd);
7576 }
7577
7578 /*
7579  * UMOV (General)
7580  * SMOV (General)
7581  *
7582  *  31  30   29              21 20    16 15    12   10 9    5 4    0
7583  * +---+---+-------------------+--------+-------------+------+------+
7584  * | 0 | Q | 0 0 1 1 1 0 0 0 0 |  imm5  | 0 0 1 U 1 1 |  Rn  |  Rd  |
7585  * +---+---+-------------------+--------+-------------+------+------+
7586  *
7587  * U: unsigned when set
7588  * size: encoded in imm5 (see ARM ARM LowestSetBit())
7589  */
7590 static void handle_simd_umov_smov(DisasContext *s, int is_q, int is_signed,
7591                                   int rn, int rd, int imm5)
7592 {
7593     int size = ctz32(imm5);
7594     int element;
7595     TCGv_i64 tcg_rd;
7596
7597     /* Check for UnallocatedEncodings */
7598     if (is_signed) {
7599         if (size > 2 || (size == 2 && !is_q)) {
7600             unallocated_encoding(s);
7601             return;
7602         }
7603     } else {
7604         if (size > 3
7605             || (size < 3 && is_q)
7606             || (size == 3 && !is_q)) {
7607             unallocated_encoding(s);
7608             return;
7609         }
7610     }
7611
7612     if (!fp_access_check(s)) {
7613         return;
7614     }
7615
7616     element = extract32(imm5, 1+size, 4);
7617
7618     tcg_rd = cpu_reg(s, rd);
7619     read_vec_element(s, tcg_rd, rn, element, size | (is_signed ? MO_SIGN : 0));
7620     if (is_signed && !is_q) {
7621         tcg_gen_ext32u_i64(tcg_rd, tcg_rd);
7622     }
7623 }
7624
7625 /* AdvSIMD copy
7626  *   31  30  29  28             21 20  16 15  14  11 10  9    5 4    0
7627  * +---+---+----+-----------------+------+---+------+---+------+------+
7628  * | 0 | Q | op | 0 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
7629  * +---+---+----+-----------------+------+---+------+---+------+------+
7630  */
7631 static void disas_simd_copy(DisasContext *s, uint32_t insn)
7632 {
7633     int rd = extract32(insn, 0, 5);
7634     int rn = extract32(insn, 5, 5);
7635     int imm4 = extract32(insn, 11, 4);
7636     int op = extract32(insn, 29, 1);
7637     int is_q = extract32(insn, 30, 1);
7638     int imm5 = extract32(insn, 16, 5);
7639
7640     if (op) {
7641         if (is_q) {
7642             /* INS (element) */
7643             handle_simd_inse(s, rd, rn, imm4, imm5);
7644         } else {
7645             unallocated_encoding(s);
7646         }
7647     } else {
7648         switch (imm4) {
7649         case 0:
7650             /* DUP (element - vector) */
7651             handle_simd_dupe(s, is_q, rd, rn, imm5);
7652             break;
7653         case 1:
7654             /* DUP (general) */
7655             handle_simd_dupg(s, is_q, rd, rn, imm5);
7656             break;
7657         case 3:
7658             if (is_q) {
7659                 /* INS (general) */
7660                 handle_simd_insg(s, rd, rn, imm5);
7661             } else {
7662                 unallocated_encoding(s);
7663             }
7664             break;
7665         case 5:
7666         case 7:
7667             /* UMOV/SMOV (is_q indicates 32/64; imm4 indicates signedness) */
7668             handle_simd_umov_smov(s, is_q, (imm4 == 5), rn, rd, imm5);
7669             break;
7670         default:
7671             unallocated_encoding(s);
7672             break;
7673         }
7674     }
7675 }
7676
7677 /* AdvSIMD modified immediate
7678  *  31  30   29  28                 19 18 16 15   12  11  10  9     5 4    0
7679  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
7680  * | 0 | Q | op | 0 1 1 1 1 0 0 0 0 0 | abc | cmode | o2 | 1 | defgh |  Rd  |
7681  * +---+---+----+---------------------+-----+-------+----+---+-------+------+
7682  *
7683  * There are a number of operations that can be carried out here:
7684  *   MOVI - move (shifted) imm into register
7685  *   MVNI - move inverted (shifted) imm into register
7686  *   ORR  - bitwise OR of (shifted) imm with register
7687  *   BIC  - bitwise clear of (shifted) imm with register
7688  * With ARMv8.2 we also have:
7689  *   FMOV half-precision
7690  */
7691 static void disas_simd_mod_imm(DisasContext *s, uint32_t insn)
7692 {
7693     int rd = extract32(insn, 0, 5);
7694     int cmode = extract32(insn, 12, 4);
7695     int cmode_3_1 = extract32(cmode, 1, 3);
7696     int cmode_0 = extract32(cmode, 0, 1);
7697     int o2 = extract32(insn, 11, 1);
7698     uint64_t abcdefgh = extract32(insn, 5, 5) | (extract32(insn, 16, 3) << 5);
7699     bool is_neg = extract32(insn, 29, 1);
7700     bool is_q = extract32(insn, 30, 1);
7701     uint64_t imm = 0;
7702
7703     if (o2 != 0 || ((cmode == 0xf) && is_neg && !is_q)) {
7704         /* Check for FMOV (vector, immediate) - half-precision */
7705         if (!(dc_isar_feature(aa64_fp16, s) && o2 && cmode == 0xf)) {
7706             unallocated_encoding(s);
7707             return;
7708         }
7709     }
7710
7711     if (!fp_access_check(s)) {
7712         return;
7713     }
7714
7715     /* See AdvSIMDExpandImm() in ARM ARM */
7716     switch (cmode_3_1) {
7717     case 0: /* Replicate(Zeros(24):imm8, 2) */
7718     case 1: /* Replicate(Zeros(16):imm8:Zeros(8), 2) */
7719     case 2: /* Replicate(Zeros(8):imm8:Zeros(16), 2) */
7720     case 3: /* Replicate(imm8:Zeros(24), 2) */
7721     {
7722         int shift = cmode_3_1 * 8;
7723         imm = bitfield_replicate(abcdefgh << shift, 32);
7724         break;
7725     }
7726     case 4: /* Replicate(Zeros(8):imm8, 4) */
7727     case 5: /* Replicate(imm8:Zeros(8), 4) */
7728     {
7729         int shift = (cmode_3_1 & 0x1) * 8;
7730         imm = bitfield_replicate(abcdefgh << shift, 16);
7731         break;
7732     }
7733     case 6:
7734         if (cmode_0) {
7735             /* Replicate(Zeros(8):imm8:Ones(16), 2) */
7736             imm = (abcdefgh << 16) | 0xffff;
7737         } else {
7738             /* Replicate(Zeros(16):imm8:Ones(8), 2) */
7739             imm = (abcdefgh << 8) | 0xff;
7740         }
7741         imm = bitfield_replicate(imm, 32);
7742         break;
7743     case 7:
7744         if (!cmode_0 && !is_neg) {
7745             imm = bitfield_replicate(abcdefgh, 8);
7746         } else if (!cmode_0 && is_neg) {
7747             int i;
7748             imm = 0;
7749             for (i = 0; i < 8; i++) {
7750                 if ((abcdefgh) & (1 << i)) {
7751                     imm |= 0xffULL << (i * 8);
7752                 }
7753             }
7754         } else if (cmode_0) {
7755             if (is_neg) {
7756                 imm = (abcdefgh & 0x3f) << 48;
7757                 if (abcdefgh & 0x80) {
7758                     imm |= 0x8000000000000000ULL;
7759                 }
7760                 if (abcdefgh & 0x40) {
7761                     imm |= 0x3fc0000000000000ULL;
7762                 } else {
7763                     imm |= 0x4000000000000000ULL;
7764                 }
7765             } else {
7766                 if (o2) {
7767                     /* FMOV (vector, immediate) - half-precision */
7768                     imm = vfp_expand_imm(MO_16, abcdefgh);
7769                     /* now duplicate across the lanes */
7770                     imm = bitfield_replicate(imm, 16);
7771                 } else {
7772                     imm = (abcdefgh & 0x3f) << 19;
7773                     if (abcdefgh & 0x80) {
7774                         imm |= 0x80000000;
7775                     }
7776                     if (abcdefgh & 0x40) {
7777                         imm |= 0x3e000000;
7778                     } else {
7779                         imm |= 0x40000000;
7780                     }
7781                     imm |= (imm << 32);
7782                 }
7783             }
7784         }
7785         break;
7786     default:
7787         fprintf(stderr, "%s: cmode_3_1: %x\n", __func__, cmode_3_1);
7788         g_assert_not_reached();
7789     }
7790
7791     if (cmode_3_1 != 7 && is_neg) {
7792         imm = ~imm;
7793     }
7794
7795     if (!((cmode & 0x9) == 0x1 || (cmode & 0xd) == 0x9)) {
7796         /* MOVI or MVNI, with MVNI negation handled above.  */
7797         tcg_gen_gvec_dup64i(vec_full_reg_offset(s, rd), is_q ? 16 : 8,
7798                             vec_full_reg_size(s), imm);
7799     } else {
7800         /* ORR or BIC, with BIC negation to AND handled above.  */
7801         if (is_neg) {
7802             gen_gvec_fn2i(s, is_q, rd, rd, imm, tcg_gen_gvec_andi, MO_64);
7803         } else {
7804             gen_gvec_fn2i(s, is_q, rd, rd, imm, tcg_gen_gvec_ori, MO_64);
7805         }
7806     }
7807 }
7808
7809 /* AdvSIMD scalar copy
7810  *  31 30  29  28             21 20  16 15  14  11 10  9    5 4    0
7811  * +-----+----+-----------------+------+---+------+---+------+------+
7812  * | 0 1 | op | 1 1 1 1 0 0 0 0 | imm5 | 0 | imm4 | 1 |  Rn  |  Rd  |
7813  * +-----+----+-----------------+------+---+------+---+------+------+
7814  */
7815 static void disas_simd_scalar_copy(DisasContext *s, uint32_t insn)
7816 {
7817     int rd = extract32(insn, 0, 5);
7818     int rn = extract32(insn, 5, 5);
7819     int imm4 = extract32(insn, 11, 4);
7820     int imm5 = extract32(insn, 16, 5);
7821     int op = extract32(insn, 29, 1);
7822
7823     if (op != 0 || imm4 != 0) {
7824         unallocated_encoding(s);
7825         return;
7826     }
7827
7828     /* DUP (element, scalar) */
7829     handle_simd_dupes(s, rd, rn, imm5);
7830 }
7831
7832 /* AdvSIMD scalar pairwise
7833  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
7834  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7835  * | 0 1 | U | 1 1 1 1 0 | size | 1 1 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
7836  * +-----+---+-----------+------+-----------+--------+-----+------+------+
7837  */
7838 static void disas_simd_scalar_pairwise(DisasContext *s, uint32_t insn)
7839 {
7840     int u = extract32(insn, 29, 1);
7841     int size = extract32(insn, 22, 2);
7842     int opcode = extract32(insn, 12, 5);
7843     int rn = extract32(insn, 5, 5);
7844     int rd = extract32(insn, 0, 5);
7845     TCGv_ptr fpst;
7846
7847     /* For some ops (the FP ones), size[1] is part of the encoding.
7848      * For ADDP strictly it is not but size[1] is always 1 for valid
7849      * encodings.
7850      */
7851     opcode |= (extract32(size, 1, 1) << 5);
7852
7853     switch (opcode) {
7854     case 0x3b: /* ADDP */
7855         if (u || size != 3) {
7856             unallocated_encoding(s);
7857             return;
7858         }
7859         if (!fp_access_check(s)) {
7860             return;
7861         }
7862
7863         fpst = NULL;
7864         break;
7865     case 0xc: /* FMAXNMP */
7866     case 0xd: /* FADDP */
7867     case 0xf: /* FMAXP */
7868     case 0x2c: /* FMINNMP */
7869     case 0x2f: /* FMINP */
7870         /* FP op, size[0] is 32 or 64 bit*/
7871         if (!u) {
7872             if (!dc_isar_feature(aa64_fp16, s)) {
7873                 unallocated_encoding(s);
7874                 return;
7875             } else {
7876                 size = MO_16;
7877             }
7878         } else {
7879             size = extract32(size, 0, 1) ? MO_64 : MO_32;
7880         }
7881
7882         if (!fp_access_check(s)) {
7883             return;
7884         }
7885
7886         fpst = get_fpstatus_ptr(size == MO_16);
7887         break;
7888     default:
7889         unallocated_encoding(s);
7890         return;
7891     }
7892
7893     if (size == MO_64) {
7894         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
7895         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
7896         TCGv_i64 tcg_res = tcg_temp_new_i64();
7897
7898         read_vec_element(s, tcg_op1, rn, 0, MO_64);
7899         read_vec_element(s, tcg_op2, rn, 1, MO_64);
7900
7901         switch (opcode) {
7902         case 0x3b: /* ADDP */
7903             tcg_gen_add_i64(tcg_res, tcg_op1, tcg_op2);
7904             break;
7905         case 0xc: /* FMAXNMP */
7906             gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
7907             break;
7908         case 0xd: /* FADDP */
7909             gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
7910             break;
7911         case 0xf: /* FMAXP */
7912             gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
7913             break;
7914         case 0x2c: /* FMINNMP */
7915             gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
7916             break;
7917         case 0x2f: /* FMINP */
7918             gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
7919             break;
7920         default:
7921             g_assert_not_reached();
7922         }
7923
7924         write_fp_dreg(s, rd, tcg_res);
7925
7926         tcg_temp_free_i64(tcg_op1);
7927         tcg_temp_free_i64(tcg_op2);
7928         tcg_temp_free_i64(tcg_res);
7929     } else {
7930         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
7931         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
7932         TCGv_i32 tcg_res = tcg_temp_new_i32();
7933
7934         read_vec_element_i32(s, tcg_op1, rn, 0, size);
7935         read_vec_element_i32(s, tcg_op2, rn, 1, size);
7936
7937         if (size == MO_16) {
7938             switch (opcode) {
7939             case 0xc: /* FMAXNMP */
7940                 gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
7941                 break;
7942             case 0xd: /* FADDP */
7943                 gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
7944                 break;
7945             case 0xf: /* FMAXP */
7946                 gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
7947                 break;
7948             case 0x2c: /* FMINNMP */
7949                 gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
7950                 break;
7951             case 0x2f: /* FMINP */
7952                 gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
7953                 break;
7954             default:
7955                 g_assert_not_reached();
7956             }
7957         } else {
7958             switch (opcode) {
7959             case 0xc: /* FMAXNMP */
7960                 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
7961                 break;
7962             case 0xd: /* FADDP */
7963                 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
7964                 break;
7965             case 0xf: /* FMAXP */
7966                 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
7967                 break;
7968             case 0x2c: /* FMINNMP */
7969                 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
7970                 break;
7971             case 0x2f: /* FMINP */
7972                 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
7973                 break;
7974             default:
7975                 g_assert_not_reached();
7976             }
7977         }
7978
7979         write_fp_sreg(s, rd, tcg_res);
7980
7981         tcg_temp_free_i32(tcg_op1);
7982         tcg_temp_free_i32(tcg_op2);
7983         tcg_temp_free_i32(tcg_res);
7984     }
7985
7986     if (fpst) {
7987         tcg_temp_free_ptr(fpst);
7988     }
7989 }
7990
7991 /*
7992  * Common SSHR[RA]/USHR[RA] - Shift right (optional rounding/accumulate)
7993  *
7994  * This code is handles the common shifting code and is used by both
7995  * the vector and scalar code.
7996  */
7997 static void handle_shri_with_rndacc(TCGv_i64 tcg_res, TCGv_i64 tcg_src,
7998                                     TCGv_i64 tcg_rnd, bool accumulate,
7999                                     bool is_u, int size, int shift)
8000 {
8001     bool extended_result = false;
8002     bool round = tcg_rnd != NULL;
8003     int ext_lshift = 0;
8004     TCGv_i64 tcg_src_hi;
8005
8006     if (round && size == 3) {
8007         extended_result = true;
8008         ext_lshift = 64 - shift;
8009         tcg_src_hi = tcg_temp_new_i64();
8010     } else if (shift == 64) {
8011         if (!accumulate && is_u) {
8012             /* result is zero */
8013             tcg_gen_movi_i64(tcg_res, 0);
8014             return;
8015         }
8016     }
8017
8018     /* Deal with the rounding step */
8019     if (round) {
8020         if (extended_result) {
8021             TCGv_i64 tcg_zero = tcg_const_i64(0);
8022             if (!is_u) {
8023                 /* take care of sign extending tcg_res */
8024                 tcg_gen_sari_i64(tcg_src_hi, tcg_src, 63);
8025                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
8026                                  tcg_src, tcg_src_hi,
8027                                  tcg_rnd, tcg_zero);
8028             } else {
8029                 tcg_gen_add2_i64(tcg_src, tcg_src_hi,
8030                                  tcg_src, tcg_zero,
8031                                  tcg_rnd, tcg_zero);
8032             }
8033             tcg_temp_free_i64(tcg_zero);
8034         } else {
8035             tcg_gen_add_i64(tcg_src, tcg_src, tcg_rnd);
8036         }
8037     }
8038
8039     /* Now do the shift right */
8040     if (round && extended_result) {
8041         /* extended case, >64 bit precision required */
8042         if (ext_lshift == 0) {
8043             /* special case, only high bits matter */
8044             tcg_gen_mov_i64(tcg_src, tcg_src_hi);
8045         } else {
8046             tcg_gen_shri_i64(tcg_src, tcg_src, shift);
8047             tcg_gen_shli_i64(tcg_src_hi, tcg_src_hi, ext_lshift);
8048             tcg_gen_or_i64(tcg_src, tcg_src, tcg_src_hi);
8049         }
8050     } else {
8051         if (is_u) {
8052             if (shift == 64) {
8053                 /* essentially shifting in 64 zeros */
8054                 tcg_gen_movi_i64(tcg_src, 0);
8055             } else {
8056                 tcg_gen_shri_i64(tcg_src, tcg_src, shift);
8057             }
8058         } else {
8059             if (shift == 64) {
8060                 /* effectively extending the sign-bit */
8061                 tcg_gen_sari_i64(tcg_src, tcg_src, 63);
8062             } else {
8063                 tcg_gen_sari_i64(tcg_src, tcg_src, shift);
8064             }
8065         }
8066     }
8067
8068     if (accumulate) {
8069         tcg_gen_add_i64(tcg_res, tcg_res, tcg_src);
8070     } else {
8071         tcg_gen_mov_i64(tcg_res, tcg_src);
8072     }
8073
8074     if (extended_result) {
8075         tcg_temp_free_i64(tcg_src_hi);
8076     }
8077 }
8078
8079 /* SSHR[RA]/USHR[RA] - Scalar shift right (optional rounding/accumulate) */
8080 static void handle_scalar_simd_shri(DisasContext *s,
8081                                     bool is_u, int immh, int immb,
8082                                     int opcode, int rn, int rd)
8083 {
8084     const int size = 3;
8085     int immhb = immh << 3 | immb;
8086     int shift = 2 * (8 << size) - immhb;
8087     bool accumulate = false;
8088     bool round = false;
8089     bool insert = false;
8090     TCGv_i64 tcg_rn;
8091     TCGv_i64 tcg_rd;
8092     TCGv_i64 tcg_round;
8093
8094     if (!extract32(immh, 3, 1)) {
8095         unallocated_encoding(s);
8096         return;
8097     }
8098
8099     if (!fp_access_check(s)) {
8100         return;
8101     }
8102
8103     switch (opcode) {
8104     case 0x02: /* SSRA / USRA (accumulate) */
8105         accumulate = true;
8106         break;
8107     case 0x04: /* SRSHR / URSHR (rounding) */
8108         round = true;
8109         break;
8110     case 0x06: /* SRSRA / URSRA (accum + rounding) */
8111         accumulate = round = true;
8112         break;
8113     case 0x08: /* SRI */
8114         insert = true;
8115         break;
8116     }
8117
8118     if (round) {
8119         uint64_t round_const = 1ULL << (shift - 1);
8120         tcg_round = tcg_const_i64(round_const);
8121     } else {
8122         tcg_round = NULL;
8123     }
8124
8125     tcg_rn = read_fp_dreg(s, rn);
8126     tcg_rd = (accumulate || insert) ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
8127
8128     if (insert) {
8129         /* shift count same as element size is valid but does nothing;
8130          * special case to avoid potential shift by 64.
8131          */
8132         int esize = 8 << size;
8133         if (shift != esize) {
8134             tcg_gen_shri_i64(tcg_rn, tcg_rn, shift);
8135             tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, 0, esize - shift);
8136         }
8137     } else {
8138         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
8139                                 accumulate, is_u, size, shift);
8140     }
8141
8142     write_fp_dreg(s, rd, tcg_rd);
8143
8144     tcg_temp_free_i64(tcg_rn);
8145     tcg_temp_free_i64(tcg_rd);
8146     if (round) {
8147         tcg_temp_free_i64(tcg_round);
8148     }
8149 }
8150
8151 /* SHL/SLI - Scalar shift left */
8152 static void handle_scalar_simd_shli(DisasContext *s, bool insert,
8153                                     int immh, int immb, int opcode,
8154                                     int rn, int rd)
8155 {
8156     int size = 32 - clz32(immh) - 1;
8157     int immhb = immh << 3 | immb;
8158     int shift = immhb - (8 << size);
8159     TCGv_i64 tcg_rn = new_tmp_a64(s);
8160     TCGv_i64 tcg_rd = new_tmp_a64(s);
8161
8162     if (!extract32(immh, 3, 1)) {
8163         unallocated_encoding(s);
8164         return;
8165     }
8166
8167     if (!fp_access_check(s)) {
8168         return;
8169     }
8170
8171     tcg_rn = read_fp_dreg(s, rn);
8172     tcg_rd = insert ? read_fp_dreg(s, rd) : tcg_temp_new_i64();
8173
8174     if (insert) {
8175         tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, shift, 64 - shift);
8176     } else {
8177         tcg_gen_shli_i64(tcg_rd, tcg_rn, shift);
8178     }
8179
8180     write_fp_dreg(s, rd, tcg_rd);
8181
8182     tcg_temp_free_i64(tcg_rn);
8183     tcg_temp_free_i64(tcg_rd);
8184 }
8185
8186 /* SQSHRN/SQSHRUN - Saturating (signed/unsigned) shift right with
8187  * (signed/unsigned) narrowing */
8188 static void handle_vec_simd_sqshrn(DisasContext *s, bool is_scalar, bool is_q,
8189                                    bool is_u_shift, bool is_u_narrow,
8190                                    int immh, int immb, int opcode,
8191                                    int rn, int rd)
8192 {
8193     int immhb = immh << 3 | immb;
8194     int size = 32 - clz32(immh) - 1;
8195     int esize = 8 << size;
8196     int shift = (2 * esize) - immhb;
8197     int elements = is_scalar ? 1 : (64 / esize);
8198     bool round = extract32(opcode, 0, 1);
8199     MemOp ldop = (size + 1) | (is_u_shift ? 0 : MO_SIGN);
8200     TCGv_i64 tcg_rn, tcg_rd, tcg_round;
8201     TCGv_i32 tcg_rd_narrowed;
8202     TCGv_i64 tcg_final;
8203
8204     static NeonGenNarrowEnvFn * const signed_narrow_fns[4][2] = {
8205         { gen_helper_neon_narrow_sat_s8,
8206           gen_helper_neon_unarrow_sat8 },
8207         { gen_helper_neon_narrow_sat_s16,
8208           gen_helper_neon_unarrow_sat16 },
8209         { gen_helper_neon_narrow_sat_s32,
8210           gen_helper_neon_unarrow_sat32 },
8211         { NULL, NULL },
8212     };
8213     static NeonGenNarrowEnvFn * const unsigned_narrow_fns[4] = {
8214         gen_helper_neon_narrow_sat_u8,
8215         gen_helper_neon_narrow_sat_u16,
8216         gen_helper_neon_narrow_sat_u32,
8217         NULL
8218     };
8219     NeonGenNarrowEnvFn *narrowfn;
8220
8221     int i;
8222
8223     assert(size < 4);
8224
8225     if (extract32(immh, 3, 1)) {
8226         unallocated_encoding(s);
8227         return;
8228     }
8229
8230     if (!fp_access_check(s)) {
8231         return;
8232     }
8233
8234     if (is_u_shift) {
8235         narrowfn = unsigned_narrow_fns[size];
8236     } else {
8237         narrowfn = signed_narrow_fns[size][is_u_narrow ? 1 : 0];
8238     }
8239
8240     tcg_rn = tcg_temp_new_i64();
8241     tcg_rd = tcg_temp_new_i64();
8242     tcg_rd_narrowed = tcg_temp_new_i32();
8243     tcg_final = tcg_const_i64(0);
8244
8245     if (round) {
8246         uint64_t round_const = 1ULL << (shift - 1);
8247         tcg_round = tcg_const_i64(round_const);
8248     } else {
8249         tcg_round = NULL;
8250     }
8251
8252     for (i = 0; i < elements; i++) {
8253         read_vec_element(s, tcg_rn, rn, i, ldop);
8254         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
8255                                 false, is_u_shift, size+1, shift);
8256         narrowfn(tcg_rd_narrowed, cpu_env, tcg_rd);
8257         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd_narrowed);
8258         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
8259     }
8260
8261     if (!is_q) {
8262         write_vec_element(s, tcg_final, rd, 0, MO_64);
8263     } else {
8264         write_vec_element(s, tcg_final, rd, 1, MO_64);
8265     }
8266
8267     if (round) {
8268         tcg_temp_free_i64(tcg_round);
8269     }
8270     tcg_temp_free_i64(tcg_rn);
8271     tcg_temp_free_i64(tcg_rd);
8272     tcg_temp_free_i32(tcg_rd_narrowed);
8273     tcg_temp_free_i64(tcg_final);
8274
8275     clear_vec_high(s, is_q, rd);
8276 }
8277
8278 /* SQSHLU, UQSHL, SQSHL: saturating left shifts */
8279 static void handle_simd_qshl(DisasContext *s, bool scalar, bool is_q,
8280                              bool src_unsigned, bool dst_unsigned,
8281                              int immh, int immb, int rn, int rd)
8282 {
8283     int immhb = immh << 3 | immb;
8284     int size = 32 - clz32(immh) - 1;
8285     int shift = immhb - (8 << size);
8286     int pass;
8287
8288     assert(immh != 0);
8289     assert(!(scalar && is_q));
8290
8291     if (!scalar) {
8292         if (!is_q && extract32(immh, 3, 1)) {
8293             unallocated_encoding(s);
8294             return;
8295         }
8296
8297         /* Since we use the variable-shift helpers we must
8298          * replicate the shift count into each element of
8299          * the tcg_shift value.
8300          */
8301         switch (size) {
8302         case 0:
8303             shift |= shift << 8;
8304             /* fall through */
8305         case 1:
8306             shift |= shift << 16;
8307             break;
8308         case 2:
8309         case 3:
8310             break;
8311         default:
8312             g_assert_not_reached();
8313         }
8314     }
8315
8316     if (!fp_access_check(s)) {
8317         return;
8318     }
8319
8320     if (size == 3) {
8321         TCGv_i64 tcg_shift = tcg_const_i64(shift);
8322         static NeonGenTwo64OpEnvFn * const fns[2][2] = {
8323             { gen_helper_neon_qshl_s64, gen_helper_neon_qshlu_s64 },
8324             { NULL, gen_helper_neon_qshl_u64 },
8325         };
8326         NeonGenTwo64OpEnvFn *genfn = fns[src_unsigned][dst_unsigned];
8327         int maxpass = is_q ? 2 : 1;
8328
8329         for (pass = 0; pass < maxpass; pass++) {
8330             TCGv_i64 tcg_op = tcg_temp_new_i64();
8331
8332             read_vec_element(s, tcg_op, rn, pass, MO_64);
8333             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
8334             write_vec_element(s, tcg_op, rd, pass, MO_64);
8335
8336             tcg_temp_free_i64(tcg_op);
8337         }
8338         tcg_temp_free_i64(tcg_shift);
8339         clear_vec_high(s, is_q, rd);
8340     } else {
8341         TCGv_i32 tcg_shift = tcg_const_i32(shift);
8342         static NeonGenTwoOpEnvFn * const fns[2][2][3] = {
8343             {
8344                 { gen_helper_neon_qshl_s8,
8345                   gen_helper_neon_qshl_s16,
8346                   gen_helper_neon_qshl_s32 },
8347                 { gen_helper_neon_qshlu_s8,
8348                   gen_helper_neon_qshlu_s16,
8349                   gen_helper_neon_qshlu_s32 }
8350             }, {
8351                 { NULL, NULL, NULL },
8352                 { gen_helper_neon_qshl_u8,
8353                   gen_helper_neon_qshl_u16,
8354                   gen_helper_neon_qshl_u32 }
8355             }
8356         };
8357         NeonGenTwoOpEnvFn *genfn = fns[src_unsigned][dst_unsigned][size];
8358         MemOp memop = scalar ? size : MO_32;
8359         int maxpass = scalar ? 1 : is_q ? 4 : 2;
8360
8361         for (pass = 0; pass < maxpass; pass++) {
8362             TCGv_i32 tcg_op = tcg_temp_new_i32();
8363
8364             read_vec_element_i32(s, tcg_op, rn, pass, memop);
8365             genfn(tcg_op, cpu_env, tcg_op, tcg_shift);
8366             if (scalar) {
8367                 switch (size) {
8368                 case 0:
8369                     tcg_gen_ext8u_i32(tcg_op, tcg_op);
8370                     break;
8371                 case 1:
8372                     tcg_gen_ext16u_i32(tcg_op, tcg_op);
8373                     break;
8374                 case 2:
8375                     break;
8376                 default:
8377                     g_assert_not_reached();
8378                 }
8379                 write_fp_sreg(s, rd, tcg_op);
8380             } else {
8381                 write_vec_element_i32(s, tcg_op, rd, pass, MO_32);
8382             }
8383
8384             tcg_temp_free_i32(tcg_op);
8385         }
8386         tcg_temp_free_i32(tcg_shift);
8387
8388         if (!scalar) {
8389             clear_vec_high(s, is_q, rd);
8390         }
8391     }
8392 }
8393
8394 /* Common vector code for handling integer to FP conversion */
8395 static void handle_simd_intfp_conv(DisasContext *s, int rd, int rn,
8396                                    int elements, int is_signed,
8397                                    int fracbits, int size)
8398 {
8399     TCGv_ptr tcg_fpst = get_fpstatus_ptr(size == MO_16);
8400     TCGv_i32 tcg_shift = NULL;
8401
8402     MemOp mop = size | (is_signed ? MO_SIGN : 0);
8403     int pass;
8404
8405     if (fracbits || size == MO_64) {
8406         tcg_shift = tcg_const_i32(fracbits);
8407     }
8408
8409     if (size == MO_64) {
8410         TCGv_i64 tcg_int64 = tcg_temp_new_i64();
8411         TCGv_i64 tcg_double = tcg_temp_new_i64();
8412
8413         for (pass = 0; pass < elements; pass++) {
8414             read_vec_element(s, tcg_int64, rn, pass, mop);
8415
8416             if (is_signed) {
8417                 gen_helper_vfp_sqtod(tcg_double, tcg_int64,
8418                                      tcg_shift, tcg_fpst);
8419             } else {
8420                 gen_helper_vfp_uqtod(tcg_double, tcg_int64,
8421                                      tcg_shift, tcg_fpst);
8422             }
8423             if (elements == 1) {
8424                 write_fp_dreg(s, rd, tcg_double);
8425             } else {
8426                 write_vec_element(s, tcg_double, rd, pass, MO_64);
8427             }
8428         }
8429
8430         tcg_temp_free_i64(tcg_int64);
8431         tcg_temp_free_i64(tcg_double);
8432
8433     } else {
8434         TCGv_i32 tcg_int32 = tcg_temp_new_i32();
8435         TCGv_i32 tcg_float = tcg_temp_new_i32();
8436
8437         for (pass = 0; pass < elements; pass++) {
8438             read_vec_element_i32(s, tcg_int32, rn, pass, mop);
8439
8440             switch (size) {
8441             case MO_32:
8442                 if (fracbits) {
8443                     if (is_signed) {
8444                         gen_helper_vfp_sltos(tcg_float, tcg_int32,
8445                                              tcg_shift, tcg_fpst);
8446                     } else {
8447                         gen_helper_vfp_ultos(tcg_float, tcg_int32,
8448                                              tcg_shift, tcg_fpst);
8449                     }
8450                 } else {
8451                     if (is_signed) {
8452                         gen_helper_vfp_sitos(tcg_float, tcg_int32, tcg_fpst);
8453                     } else {
8454                         gen_helper_vfp_uitos(tcg_float, tcg_int32, tcg_fpst);
8455                     }
8456                 }
8457                 break;
8458             case MO_16:
8459                 if (fracbits) {
8460                     if (is_signed) {
8461                         gen_helper_vfp_sltoh(tcg_float, tcg_int32,
8462                                              tcg_shift, tcg_fpst);
8463                     } else {
8464                         gen_helper_vfp_ultoh(tcg_float, tcg_int32,
8465                                              tcg_shift, tcg_fpst);
8466                     }
8467                 } else {
8468                     if (is_signed) {
8469                         gen_helper_vfp_sitoh(tcg_float, tcg_int32, tcg_fpst);
8470                     } else {
8471                         gen_helper_vfp_uitoh(tcg_float, tcg_int32, tcg_fpst);
8472                     }
8473                 }
8474                 break;
8475             default:
8476                 g_assert_not_reached();
8477             }
8478
8479             if (elements == 1) {
8480                 write_fp_sreg(s, rd, tcg_float);
8481             } else {
8482                 write_vec_element_i32(s, tcg_float, rd, pass, size);
8483             }
8484         }
8485
8486         tcg_temp_free_i32(tcg_int32);
8487         tcg_temp_free_i32(tcg_float);
8488     }
8489
8490     tcg_temp_free_ptr(tcg_fpst);
8491     if (tcg_shift) {
8492         tcg_temp_free_i32(tcg_shift);
8493     }
8494
8495     clear_vec_high(s, elements << size == 16, rd);
8496 }
8497
8498 /* UCVTF/SCVTF - Integer to FP conversion */
8499 static void handle_simd_shift_intfp_conv(DisasContext *s, bool is_scalar,
8500                                          bool is_q, bool is_u,
8501                                          int immh, int immb, int opcode,
8502                                          int rn, int rd)
8503 {
8504     int size, elements, fracbits;
8505     int immhb = immh << 3 | immb;
8506
8507     if (immh & 8) {
8508         size = MO_64;
8509         if (!is_scalar && !is_q) {
8510             unallocated_encoding(s);
8511             return;
8512         }
8513     } else if (immh & 4) {
8514         size = MO_32;
8515     } else if (immh & 2) {
8516         size = MO_16;
8517         if (!dc_isar_feature(aa64_fp16, s)) {
8518             unallocated_encoding(s);
8519             return;
8520         }
8521     } else {
8522         /* immh == 0 would be a failure of the decode logic */
8523         g_assert(immh == 1);
8524         unallocated_encoding(s);
8525         return;
8526     }
8527
8528     if (is_scalar) {
8529         elements = 1;
8530     } else {
8531         elements = (8 << is_q) >> size;
8532     }
8533     fracbits = (16 << size) - immhb;
8534
8535     if (!fp_access_check(s)) {
8536         return;
8537     }
8538
8539     handle_simd_intfp_conv(s, rd, rn, elements, !is_u, fracbits, size);
8540 }
8541
8542 /* FCVTZS, FVCVTZU - FP to fixedpoint conversion */
8543 static void handle_simd_shift_fpint_conv(DisasContext *s, bool is_scalar,
8544                                          bool is_q, bool is_u,
8545                                          int immh, int immb, int rn, int rd)
8546 {
8547     int immhb = immh << 3 | immb;
8548     int pass, size, fracbits;
8549     TCGv_ptr tcg_fpstatus;
8550     TCGv_i32 tcg_rmode, tcg_shift;
8551
8552     if (immh & 0x8) {
8553         size = MO_64;
8554         if (!is_scalar && !is_q) {
8555             unallocated_encoding(s);
8556             return;
8557         }
8558     } else if (immh & 0x4) {
8559         size = MO_32;
8560     } else if (immh & 0x2) {
8561         size = MO_16;
8562         if (!dc_isar_feature(aa64_fp16, s)) {
8563             unallocated_encoding(s);
8564             return;
8565         }
8566     } else {
8567         /* Should have split out AdvSIMD modified immediate earlier.  */
8568         assert(immh == 1);
8569         unallocated_encoding(s);
8570         return;
8571     }
8572
8573     if (!fp_access_check(s)) {
8574         return;
8575     }
8576
8577     assert(!(is_scalar && is_q));
8578
8579     tcg_rmode = tcg_const_i32(arm_rmode_to_sf(FPROUNDING_ZERO));
8580     tcg_fpstatus = get_fpstatus_ptr(size == MO_16);
8581     gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
8582     fracbits = (16 << size) - immhb;
8583     tcg_shift = tcg_const_i32(fracbits);
8584
8585     if (size == MO_64) {
8586         int maxpass = is_scalar ? 1 : 2;
8587
8588         for (pass = 0; pass < maxpass; pass++) {
8589             TCGv_i64 tcg_op = tcg_temp_new_i64();
8590
8591             read_vec_element(s, tcg_op, rn, pass, MO_64);
8592             if (is_u) {
8593                 gen_helper_vfp_touqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
8594             } else {
8595                 gen_helper_vfp_tosqd(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
8596             }
8597             write_vec_element(s, tcg_op, rd, pass, MO_64);
8598             tcg_temp_free_i64(tcg_op);
8599         }
8600         clear_vec_high(s, is_q, rd);
8601     } else {
8602         void (*fn)(TCGv_i32, TCGv_i32, TCGv_i32, TCGv_ptr);
8603         int maxpass = is_scalar ? 1 : ((8 << is_q) >> size);
8604
8605         switch (size) {
8606         case MO_16:
8607             if (is_u) {
8608                 fn = gen_helper_vfp_touhh;
8609             } else {
8610                 fn = gen_helper_vfp_toshh;
8611             }
8612             break;
8613         case MO_32:
8614             if (is_u) {
8615                 fn = gen_helper_vfp_touls;
8616             } else {
8617                 fn = gen_helper_vfp_tosls;
8618             }
8619             break;
8620         default:
8621             g_assert_not_reached();
8622         }
8623
8624         for (pass = 0; pass < maxpass; pass++) {
8625             TCGv_i32 tcg_op = tcg_temp_new_i32();
8626
8627             read_vec_element_i32(s, tcg_op, rn, pass, size);
8628             fn(tcg_op, tcg_op, tcg_shift, tcg_fpstatus);
8629             if (is_scalar) {
8630                 write_fp_sreg(s, rd, tcg_op);
8631             } else {
8632                 write_vec_element_i32(s, tcg_op, rd, pass, size);
8633             }
8634             tcg_temp_free_i32(tcg_op);
8635         }
8636         if (!is_scalar) {
8637             clear_vec_high(s, is_q, rd);
8638         }
8639     }
8640
8641     tcg_temp_free_ptr(tcg_fpstatus);
8642     tcg_temp_free_i32(tcg_shift);
8643     gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
8644     tcg_temp_free_i32(tcg_rmode);
8645 }
8646
8647 /* AdvSIMD scalar shift by immediate
8648  *  31 30  29 28         23 22  19 18  16 15    11  10 9    5 4    0
8649  * +-----+---+-------------+------+------+--------+---+------+------+
8650  * | 0 1 | U | 1 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
8651  * +-----+---+-------------+------+------+--------+---+------+------+
8652  *
8653  * This is the scalar version so it works on a fixed sized registers
8654  */
8655 static void disas_simd_scalar_shift_imm(DisasContext *s, uint32_t insn)
8656 {
8657     int rd = extract32(insn, 0, 5);
8658     int rn = extract32(insn, 5, 5);
8659     int opcode = extract32(insn, 11, 5);
8660     int immb = extract32(insn, 16, 3);
8661     int immh = extract32(insn, 19, 4);
8662     bool is_u = extract32(insn, 29, 1);
8663
8664     if (immh == 0) {
8665         unallocated_encoding(s);
8666         return;
8667     }
8668
8669     switch (opcode) {
8670     case 0x08: /* SRI */
8671         if (!is_u) {
8672             unallocated_encoding(s);
8673             return;
8674         }
8675         /* fall through */
8676     case 0x00: /* SSHR / USHR */
8677     case 0x02: /* SSRA / USRA */
8678     case 0x04: /* SRSHR / URSHR */
8679     case 0x06: /* SRSRA / URSRA */
8680         handle_scalar_simd_shri(s, is_u, immh, immb, opcode, rn, rd);
8681         break;
8682     case 0x0a: /* SHL / SLI */
8683         handle_scalar_simd_shli(s, is_u, immh, immb, opcode, rn, rd);
8684         break;
8685     case 0x1c: /* SCVTF, UCVTF */
8686         handle_simd_shift_intfp_conv(s, true, false, is_u, immh, immb,
8687                                      opcode, rn, rd);
8688         break;
8689     case 0x10: /* SQSHRUN, SQSHRUN2 */
8690     case 0x11: /* SQRSHRUN, SQRSHRUN2 */
8691         if (!is_u) {
8692             unallocated_encoding(s);
8693             return;
8694         }
8695         handle_vec_simd_sqshrn(s, true, false, false, true,
8696                                immh, immb, opcode, rn, rd);
8697         break;
8698     case 0x12: /* SQSHRN, SQSHRN2, UQSHRN */
8699     case 0x13: /* SQRSHRN, SQRSHRN2, UQRSHRN, UQRSHRN2 */
8700         handle_vec_simd_sqshrn(s, true, false, is_u, is_u,
8701                                immh, immb, opcode, rn, rd);
8702         break;
8703     case 0xc: /* SQSHLU */
8704         if (!is_u) {
8705             unallocated_encoding(s);
8706             return;
8707         }
8708         handle_simd_qshl(s, true, false, false, true, immh, immb, rn, rd);
8709         break;
8710     case 0xe: /* SQSHL, UQSHL */
8711         handle_simd_qshl(s, true, false, is_u, is_u, immh, immb, rn, rd);
8712         break;
8713     case 0x1f: /* FCVTZS, FCVTZU */
8714         handle_simd_shift_fpint_conv(s, true, false, is_u, immh, immb, rn, rd);
8715         break;
8716     default:
8717         unallocated_encoding(s);
8718         break;
8719     }
8720 }
8721
8722 /* AdvSIMD scalar three different
8723  *  31 30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
8724  * +-----+---+-----------+------+---+------+--------+-----+------+------+
8725  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
8726  * +-----+---+-----------+------+---+------+--------+-----+------+------+
8727  */
8728 static void disas_simd_scalar_three_reg_diff(DisasContext *s, uint32_t insn)
8729 {
8730     bool is_u = extract32(insn, 29, 1);
8731     int size = extract32(insn, 22, 2);
8732     int opcode = extract32(insn, 12, 4);
8733     int rm = extract32(insn, 16, 5);
8734     int rn = extract32(insn, 5, 5);
8735     int rd = extract32(insn, 0, 5);
8736
8737     if (is_u) {
8738         unallocated_encoding(s);
8739         return;
8740     }
8741
8742     switch (opcode) {
8743     case 0x9: /* SQDMLAL, SQDMLAL2 */
8744     case 0xb: /* SQDMLSL, SQDMLSL2 */
8745     case 0xd: /* SQDMULL, SQDMULL2 */
8746         if (size == 0 || size == 3) {
8747             unallocated_encoding(s);
8748             return;
8749         }
8750         break;
8751     default:
8752         unallocated_encoding(s);
8753         return;
8754     }
8755
8756     if (!fp_access_check(s)) {
8757         return;
8758     }
8759
8760     if (size == 2) {
8761         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8762         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8763         TCGv_i64 tcg_res = tcg_temp_new_i64();
8764
8765         read_vec_element(s, tcg_op1, rn, 0, MO_32 | MO_SIGN);
8766         read_vec_element(s, tcg_op2, rm, 0, MO_32 | MO_SIGN);
8767
8768         tcg_gen_mul_i64(tcg_res, tcg_op1, tcg_op2);
8769         gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env, tcg_res, tcg_res);
8770
8771         switch (opcode) {
8772         case 0xd: /* SQDMULL, SQDMULL2 */
8773             break;
8774         case 0xb: /* SQDMLSL, SQDMLSL2 */
8775             tcg_gen_neg_i64(tcg_res, tcg_res);
8776             /* fall through */
8777         case 0x9: /* SQDMLAL, SQDMLAL2 */
8778             read_vec_element(s, tcg_op1, rd, 0, MO_64);
8779             gen_helper_neon_addl_saturate_s64(tcg_res, cpu_env,
8780                                               tcg_res, tcg_op1);
8781             break;
8782         default:
8783             g_assert_not_reached();
8784         }
8785
8786         write_fp_dreg(s, rd, tcg_res);
8787
8788         tcg_temp_free_i64(tcg_op1);
8789         tcg_temp_free_i64(tcg_op2);
8790         tcg_temp_free_i64(tcg_res);
8791     } else {
8792         TCGv_i32 tcg_op1 = read_fp_hreg(s, rn);
8793         TCGv_i32 tcg_op2 = read_fp_hreg(s, rm);
8794         TCGv_i64 tcg_res = tcg_temp_new_i64();
8795
8796         gen_helper_neon_mull_s16(tcg_res, tcg_op1, tcg_op2);
8797         gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env, tcg_res, tcg_res);
8798
8799         switch (opcode) {
8800         case 0xd: /* SQDMULL, SQDMULL2 */
8801             break;
8802         case 0xb: /* SQDMLSL, SQDMLSL2 */
8803             gen_helper_neon_negl_u32(tcg_res, tcg_res);
8804             /* fall through */
8805         case 0x9: /* SQDMLAL, SQDMLAL2 */
8806         {
8807             TCGv_i64 tcg_op3 = tcg_temp_new_i64();
8808             read_vec_element(s, tcg_op3, rd, 0, MO_32);
8809             gen_helper_neon_addl_saturate_s32(tcg_res, cpu_env,
8810                                               tcg_res, tcg_op3);
8811             tcg_temp_free_i64(tcg_op3);
8812             break;
8813         }
8814         default:
8815             g_assert_not_reached();
8816         }
8817
8818         tcg_gen_ext32u_i64(tcg_res, tcg_res);
8819         write_fp_dreg(s, rd, tcg_res);
8820
8821         tcg_temp_free_i32(tcg_op1);
8822         tcg_temp_free_i32(tcg_op2);
8823         tcg_temp_free_i64(tcg_res);
8824     }
8825 }
8826
8827 static void handle_3same_64(DisasContext *s, int opcode, bool u,
8828                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn, TCGv_i64 tcg_rm)
8829 {
8830     /* Handle 64x64->64 opcodes which are shared between the scalar
8831      * and vector 3-same groups. We cover every opcode where size == 3
8832      * is valid in either the three-reg-same (integer, not pairwise)
8833      * or scalar-three-reg-same groups.
8834      */
8835     TCGCond cond;
8836
8837     switch (opcode) {
8838     case 0x1: /* SQADD */
8839         if (u) {
8840             gen_helper_neon_qadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8841         } else {
8842             gen_helper_neon_qadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8843         }
8844         break;
8845     case 0x5: /* SQSUB */
8846         if (u) {
8847             gen_helper_neon_qsub_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8848         } else {
8849             gen_helper_neon_qsub_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8850         }
8851         break;
8852     case 0x6: /* CMGT, CMHI */
8853         /* 64 bit integer comparison, result = test ? (2^64 - 1) : 0.
8854          * We implement this using setcond (test) and then negating.
8855          */
8856         cond = u ? TCG_COND_GTU : TCG_COND_GT;
8857     do_cmop:
8858         tcg_gen_setcond_i64(cond, tcg_rd, tcg_rn, tcg_rm);
8859         tcg_gen_neg_i64(tcg_rd, tcg_rd);
8860         break;
8861     case 0x7: /* CMGE, CMHS */
8862         cond = u ? TCG_COND_GEU : TCG_COND_GE;
8863         goto do_cmop;
8864     case 0x11: /* CMTST, CMEQ */
8865         if (u) {
8866             cond = TCG_COND_EQ;
8867             goto do_cmop;
8868         }
8869         gen_cmtst_i64(tcg_rd, tcg_rn, tcg_rm);
8870         break;
8871     case 0x8: /* SSHL, USHL */
8872         if (u) {
8873             gen_ushl_i64(tcg_rd, tcg_rn, tcg_rm);
8874         } else {
8875             gen_sshl_i64(tcg_rd, tcg_rn, tcg_rm);
8876         }
8877         break;
8878     case 0x9: /* SQSHL, UQSHL */
8879         if (u) {
8880             gen_helper_neon_qshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8881         } else {
8882             gen_helper_neon_qshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8883         }
8884         break;
8885     case 0xa: /* SRSHL, URSHL */
8886         if (u) {
8887             gen_helper_neon_rshl_u64(tcg_rd, tcg_rn, tcg_rm);
8888         } else {
8889             gen_helper_neon_rshl_s64(tcg_rd, tcg_rn, tcg_rm);
8890         }
8891         break;
8892     case 0xb: /* SQRSHL, UQRSHL */
8893         if (u) {
8894             gen_helper_neon_qrshl_u64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8895         } else {
8896             gen_helper_neon_qrshl_s64(tcg_rd, cpu_env, tcg_rn, tcg_rm);
8897         }
8898         break;
8899     case 0x10: /* ADD, SUB */
8900         if (u) {
8901             tcg_gen_sub_i64(tcg_rd, tcg_rn, tcg_rm);
8902         } else {
8903             tcg_gen_add_i64(tcg_rd, tcg_rn, tcg_rm);
8904         }
8905         break;
8906     default:
8907         g_assert_not_reached();
8908     }
8909 }
8910
8911 /* Handle the 3-same-operands float operations; shared by the scalar
8912  * and vector encodings. The caller must filter out any encodings
8913  * not allocated for the encoding it is dealing with.
8914  */
8915 static void handle_3same_float(DisasContext *s, int size, int elements,
8916                                int fpopcode, int rd, int rn, int rm)
8917 {
8918     int pass;
8919     TCGv_ptr fpst = get_fpstatus_ptr(false);
8920
8921     for (pass = 0; pass < elements; pass++) {
8922         if (size) {
8923             /* Double */
8924             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
8925             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
8926             TCGv_i64 tcg_res = tcg_temp_new_i64();
8927
8928             read_vec_element(s, tcg_op1, rn, pass, MO_64);
8929             read_vec_element(s, tcg_op2, rm, pass, MO_64);
8930
8931             switch (fpopcode) {
8932             case 0x39: /* FMLS */
8933                 /* As usual for ARM, separate negation for fused multiply-add */
8934                 gen_helper_vfp_negd(tcg_op1, tcg_op1);
8935                 /* fall through */
8936             case 0x19: /* FMLA */
8937                 read_vec_element(s, tcg_res, rd, pass, MO_64);
8938                 gen_helper_vfp_muladdd(tcg_res, tcg_op1, tcg_op2,
8939                                        tcg_res, fpst);
8940                 break;
8941             case 0x18: /* FMAXNM */
8942                 gen_helper_vfp_maxnumd(tcg_res, tcg_op1, tcg_op2, fpst);
8943                 break;
8944             case 0x1a: /* FADD */
8945                 gen_helper_vfp_addd(tcg_res, tcg_op1, tcg_op2, fpst);
8946                 break;
8947             case 0x1b: /* FMULX */
8948                 gen_helper_vfp_mulxd(tcg_res, tcg_op1, tcg_op2, fpst);
8949                 break;
8950             case 0x1c: /* FCMEQ */
8951                 gen_helper_neon_ceq_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8952                 break;
8953             case 0x1e: /* FMAX */
8954                 gen_helper_vfp_maxd(tcg_res, tcg_op1, tcg_op2, fpst);
8955                 break;
8956             case 0x1f: /* FRECPS */
8957                 gen_helper_recpsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8958                 break;
8959             case 0x38: /* FMINNM */
8960                 gen_helper_vfp_minnumd(tcg_res, tcg_op1, tcg_op2, fpst);
8961                 break;
8962             case 0x3a: /* FSUB */
8963                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
8964                 break;
8965             case 0x3e: /* FMIN */
8966                 gen_helper_vfp_mind(tcg_res, tcg_op1, tcg_op2, fpst);
8967                 break;
8968             case 0x3f: /* FRSQRTS */
8969                 gen_helper_rsqrtsf_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8970                 break;
8971             case 0x5b: /* FMUL */
8972                 gen_helper_vfp_muld(tcg_res, tcg_op1, tcg_op2, fpst);
8973                 break;
8974             case 0x5c: /* FCMGE */
8975                 gen_helper_neon_cge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8976                 break;
8977             case 0x5d: /* FACGE */
8978                 gen_helper_neon_acge_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8979                 break;
8980             case 0x5f: /* FDIV */
8981                 gen_helper_vfp_divd(tcg_res, tcg_op1, tcg_op2, fpst);
8982                 break;
8983             case 0x7a: /* FABD */
8984                 gen_helper_vfp_subd(tcg_res, tcg_op1, tcg_op2, fpst);
8985                 gen_helper_vfp_absd(tcg_res, tcg_res);
8986                 break;
8987             case 0x7c: /* FCMGT */
8988                 gen_helper_neon_cgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8989                 break;
8990             case 0x7d: /* FACGT */
8991                 gen_helper_neon_acgt_f64(tcg_res, tcg_op1, tcg_op2, fpst);
8992                 break;
8993             default:
8994                 g_assert_not_reached();
8995             }
8996
8997             write_vec_element(s, tcg_res, rd, pass, MO_64);
8998
8999             tcg_temp_free_i64(tcg_res);
9000             tcg_temp_free_i64(tcg_op1);
9001             tcg_temp_free_i64(tcg_op2);
9002         } else {
9003             /* Single */
9004             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
9005             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
9006             TCGv_i32 tcg_res = tcg_temp_new_i32();
9007
9008             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
9009             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
9010
9011             switch (fpopcode) {
9012             case 0x39: /* FMLS */
9013                 /* As usual for ARM, separate negation for fused multiply-add */
9014                 gen_helper_vfp_negs(tcg_op1, tcg_op1);
9015                 /* fall through */
9016             case 0x19: /* FMLA */
9017                 read_vec_element_i32(s, tcg_res, rd, pass, MO_32);
9018                 gen_helper_vfp_muladds(tcg_res, tcg_op1, tcg_op2,
9019                                        tcg_res, fpst);
9020                 break;
9021             case 0x1a: /* FADD */
9022                 gen_helper_vfp_adds(tcg_res, tcg_op1, tcg_op2, fpst);
9023                 break;
9024             case 0x1b: /* FMULX */
9025                 gen_helper_vfp_mulxs(tcg_res, tcg_op1, tcg_op2, fpst);
9026                 break;
9027             case 0x1c: /* FCMEQ */
9028                 gen_helper_neon_ceq_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9029                 break;
9030             case 0x1e: /* FMAX */
9031                 gen_helper_vfp_maxs(tcg_res, tcg_op1, tcg_op2, fpst);
9032                 break;
9033             case 0x1f: /* FRECPS */
9034                 gen_helper_recpsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9035                 break;
9036             case 0x18: /* FMAXNM */
9037                 gen_helper_vfp_maxnums(tcg_res, tcg_op1, tcg_op2, fpst);
9038                 break;
9039             case 0x38: /* FMINNM */
9040                 gen_helper_vfp_minnums(tcg_res, tcg_op1, tcg_op2, fpst);
9041                 break;
9042             case 0x3a: /* FSUB */
9043                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
9044                 break;
9045             case 0x3e: /* FMIN */
9046                 gen_helper_vfp_mins(tcg_res, tcg_op1, tcg_op2, fpst);
9047                 break;
9048             case 0x3f: /* FRSQRTS */
9049                 gen_helper_rsqrtsf_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9050                 break;
9051             case 0x5b: /* FMUL */
9052                 gen_helper_vfp_muls(tcg_res, tcg_op1, tcg_op2, fpst);
9053                 break;
9054             case 0x5c: /* FCMGE */
9055                 gen_helper_neon_cge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9056                 break;
9057             case 0x5d: /* FACGE */
9058                 gen_helper_neon_acge_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9059                 break;
9060             case 0x5f: /* FDIV */
9061                 gen_helper_vfp_divs(tcg_res, tcg_op1, tcg_op2, fpst);
9062                 break;
9063             case 0x7a: /* FABD */
9064                 gen_helper_vfp_subs(tcg_res, tcg_op1, tcg_op2, fpst);
9065                 gen_helper_vfp_abss(tcg_res, tcg_res);
9066                 break;
9067             case 0x7c: /* FCMGT */
9068                 gen_helper_neon_cgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9069                 break;
9070             case 0x7d: /* FACGT */
9071                 gen_helper_neon_acgt_f32(tcg_res, tcg_op1, tcg_op2, fpst);
9072                 break;
9073             default:
9074                 g_assert_not_reached();
9075             }
9076
9077             if (elements == 1) {
9078                 /* scalar single so clear high part */
9079                 TCGv_i64 tcg_tmp = tcg_temp_new_i64();
9080
9081                 tcg_gen_extu_i32_i64(tcg_tmp, tcg_res);
9082                 write_vec_element(s, tcg_tmp, rd, pass, MO_64);
9083                 tcg_temp_free_i64(tcg_tmp);
9084             } else {
9085                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
9086             }
9087
9088             tcg_temp_free_i32(tcg_res);
9089             tcg_temp_free_i32(tcg_op1);
9090             tcg_temp_free_i32(tcg_op2);
9091         }
9092     }
9093
9094     tcg_temp_free_ptr(fpst);
9095
9096     clear_vec_high(s, elements * (size ? 8 : 4) > 8, rd);
9097 }
9098
9099 /* AdvSIMD scalar three same
9100  *  31 30  29 28       24 23  22  21 20  16 15    11  10 9    5 4    0
9101  * +-----+---+-----------+------+---+------+--------+---+------+------+
9102  * | 0 1 | U | 1 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
9103  * +-----+---+-----------+------+---+------+--------+---+------+------+
9104  */
9105 static void disas_simd_scalar_three_reg_same(DisasContext *s, uint32_t insn)
9106 {
9107     int rd = extract32(insn, 0, 5);
9108     int rn = extract32(insn, 5, 5);
9109     int opcode = extract32(insn, 11, 5);
9110     int rm = extract32(insn, 16, 5);
9111     int size = extract32(insn, 22, 2);
9112     bool u = extract32(insn, 29, 1);
9113     TCGv_i64 tcg_rd;
9114
9115     if (opcode >= 0x18) {
9116         /* Floating point: U, size[1] and opcode indicate operation */
9117         int fpopcode = opcode | (extract32(size, 1, 1) << 5) | (u << 6);
9118         switch (fpopcode) {
9119         case 0x1b: /* FMULX */
9120         case 0x1f: /* FRECPS */
9121         case 0x3f: /* FRSQRTS */
9122         case 0x5d: /* FACGE */
9123         case 0x7d: /* FACGT */
9124         case 0x1c: /* FCMEQ */
9125         case 0x5c: /* FCMGE */
9126         case 0x7c: /* FCMGT */
9127         case 0x7a: /* FABD */
9128             break;
9129         default:
9130             unallocated_encoding(s);
9131             return;
9132         }
9133
9134         if (!fp_access_check(s)) {
9135             return;
9136         }
9137
9138         handle_3same_float(s, extract32(size, 0, 1), 1, fpopcode, rd, rn, rm);
9139         return;
9140     }
9141
9142     switch (opcode) {
9143     case 0x1: /* SQADD, UQADD */
9144     case 0x5: /* SQSUB, UQSUB */
9145     case 0x9: /* SQSHL, UQSHL */
9146     case 0xb: /* SQRSHL, UQRSHL */
9147         break;
9148     case 0x8: /* SSHL, USHL */
9149     case 0xa: /* SRSHL, URSHL */
9150     case 0x6: /* CMGT, CMHI */
9151     case 0x7: /* CMGE, CMHS */
9152     case 0x11: /* CMTST, CMEQ */
9153     case 0x10: /* ADD, SUB (vector) */
9154         if (size != 3) {
9155             unallocated_encoding(s);
9156             return;
9157         }
9158         break;
9159     case 0x16: /* SQDMULH, SQRDMULH (vector) */
9160         if (size != 1 && size != 2) {
9161             unallocated_encoding(s);
9162             return;
9163         }
9164         break;
9165     default:
9166         unallocated_encoding(s);
9167         return;
9168     }
9169
9170     if (!fp_access_check(s)) {
9171         return;
9172     }
9173
9174     tcg_rd = tcg_temp_new_i64();
9175
9176     if (size == 3) {
9177         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
9178         TCGv_i64 tcg_rm = read_fp_dreg(s, rm);
9179
9180         handle_3same_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rm);
9181         tcg_temp_free_i64(tcg_rn);
9182         tcg_temp_free_i64(tcg_rm);
9183     } else {
9184         /* Do a single operation on the lowest element in the vector.
9185          * We use the standard Neon helpers and rely on 0 OP 0 == 0 with
9186          * no side effects for all these operations.
9187          * OPTME: special-purpose helpers would avoid doing some
9188          * unnecessary work in the helper for the 8 and 16 bit cases.
9189          */
9190         NeonGenTwoOpEnvFn *genenvfn;
9191         TCGv_i32 tcg_rn = tcg_temp_new_i32();
9192         TCGv_i32 tcg_rm = tcg_temp_new_i32();
9193         TCGv_i32 tcg_rd32 = tcg_temp_new_i32();
9194
9195         read_vec_element_i32(s, tcg_rn, rn, 0, size);
9196         read_vec_element_i32(s, tcg_rm, rm, 0, size);
9197
9198         switch (opcode) {
9199         case 0x1: /* SQADD, UQADD */
9200         {
9201             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9202                 { gen_helper_neon_qadd_s8, gen_helper_neon_qadd_u8 },
9203                 { gen_helper_neon_qadd_s16, gen_helper_neon_qadd_u16 },
9204                 { gen_helper_neon_qadd_s32, gen_helper_neon_qadd_u32 },
9205             };
9206             genenvfn = fns[size][u];
9207             break;
9208         }
9209         case 0x5: /* SQSUB, UQSUB */
9210         {
9211             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9212                 { gen_helper_neon_qsub_s8, gen_helper_neon_qsub_u8 },
9213                 { gen_helper_neon_qsub_s16, gen_helper_neon_qsub_u16 },
9214                 { gen_helper_neon_qsub_s32, gen_helper_neon_qsub_u32 },
9215             };
9216             genenvfn = fns[size][u];
9217             break;
9218         }
9219         case 0x9: /* SQSHL, UQSHL */
9220         {
9221             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9222                 { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
9223                 { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
9224                 { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
9225             };
9226             genenvfn = fns[size][u];
9227             break;
9228         }
9229         case 0xb: /* SQRSHL, UQRSHL */
9230         {
9231             static NeonGenTwoOpEnvFn * const fns[3][2] = {
9232                 { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
9233                 { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
9234                 { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
9235             };
9236             genenvfn = fns[size][u];
9237             break;
9238         }
9239         case 0x16: /* SQDMULH, SQRDMULH */
9240         {
9241             static NeonGenTwoOpEnvFn * const fns[2][2] = {
9242                 { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
9243                 { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
9244             };
9245             assert(size == 1 || size == 2);
9246             genenvfn = fns[size - 1][u];
9247             break;
9248         }
9249         default:
9250             g_assert_not_reached();
9251         }
9252
9253         genenvfn(tcg_rd32, cpu_env, tcg_rn, tcg_rm);
9254         tcg_gen_extu_i32_i64(tcg_rd, tcg_rd32);
9255         tcg_temp_free_i32(tcg_rd32);
9256         tcg_temp_free_i32(tcg_rn);
9257         tcg_temp_free_i32(tcg_rm);
9258     }
9259
9260     write_fp_dreg(s, rd, tcg_rd);
9261
9262     tcg_temp_free_i64(tcg_rd);
9263 }
9264
9265 /* AdvSIMD scalar three same FP16
9266  *  31 30  29 28       24 23  22 21 20  16 15 14 13    11 10  9  5 4  0
9267  * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
9268  * | 0 1 | U | 1 1 1 1 0 | a | 1 0 |  Rm  | 0 0 | opcode | 1 | Rn | Rd |
9269  * +-----+---+-----------+---+-----+------+-----+--------+---+----+----+
9270  * v: 0101 1110 0100 0000 0000 0100 0000 0000 => 5e400400
9271  * m: 1101 1111 0110 0000 1100 0100 0000 0000 => df60c400
9272  */
9273 static void disas_simd_scalar_three_reg_same_fp16(DisasContext *s,
9274                                                   uint32_t insn)
9275 {
9276     int rd = extract32(insn, 0, 5);
9277     int rn = extract32(insn, 5, 5);
9278     int opcode = extract32(insn, 11, 3);
9279     int rm = extract32(insn, 16, 5);
9280     bool u = extract32(insn, 29, 1);
9281     bool a = extract32(insn, 23, 1);
9282     int fpopcode = opcode | (a << 3) |  (u << 4);
9283     TCGv_ptr fpst;
9284     TCGv_i32 tcg_op1;
9285     TCGv_i32 tcg_op2;
9286     TCGv_i32 tcg_res;
9287
9288     switch (fpopcode) {
9289     case 0x03: /* FMULX */
9290     case 0x04: /* FCMEQ (reg) */
9291     case 0x07: /* FRECPS */
9292     case 0x0f: /* FRSQRTS */
9293     case 0x14: /* FCMGE (reg) */
9294     case 0x15: /* FACGE */
9295     case 0x1a: /* FABD */
9296     case 0x1c: /* FCMGT (reg) */
9297     case 0x1d: /* FACGT */
9298         break;
9299     default:
9300         unallocated_encoding(s);
9301         return;
9302     }
9303
9304     if (!dc_isar_feature(aa64_fp16, s)) {
9305         unallocated_encoding(s);
9306     }
9307
9308     if (!fp_access_check(s)) {
9309         return;
9310     }
9311
9312     fpst = get_fpstatus_ptr(true);
9313
9314     tcg_op1 = read_fp_hreg(s, rn);
9315     tcg_op2 = read_fp_hreg(s, rm);
9316     tcg_res = tcg_temp_new_i32();
9317
9318     switch (fpopcode) {
9319     case 0x03: /* FMULX */
9320         gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
9321         break;
9322     case 0x04: /* FCMEQ (reg) */
9323         gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9324         break;
9325     case 0x07: /* FRECPS */
9326         gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9327         break;
9328     case 0x0f: /* FRSQRTS */
9329         gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9330         break;
9331     case 0x14: /* FCMGE (reg) */
9332         gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9333         break;
9334     case 0x15: /* FACGE */
9335         gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9336         break;
9337     case 0x1a: /* FABD */
9338         gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
9339         tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
9340         break;
9341     case 0x1c: /* FCMGT (reg) */
9342         gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9343         break;
9344     case 0x1d: /* FACGT */
9345         gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
9346         break;
9347     default:
9348         g_assert_not_reached();
9349     }
9350
9351     write_fp_sreg(s, rd, tcg_res);
9352
9353
9354     tcg_temp_free_i32(tcg_res);
9355     tcg_temp_free_i32(tcg_op1);
9356     tcg_temp_free_i32(tcg_op2);
9357     tcg_temp_free_ptr(fpst);
9358 }
9359
9360 /* AdvSIMD scalar three same extra
9361  *  31 30  29 28       24 23  22  21 20  16  15 14    11  10 9  5 4  0
9362  * +-----+---+-----------+------+---+------+---+--------+---+----+----+
9363  * | 0 1 | U | 1 1 1 1 0 | size | 0 |  Rm  | 1 | opcode | 1 | Rn | Rd |
9364  * +-----+---+-----------+------+---+------+---+--------+---+----+----+
9365  */
9366 static void disas_simd_scalar_three_reg_same_extra(DisasContext *s,
9367                                                    uint32_t insn)
9368 {
9369     int rd = extract32(insn, 0, 5);
9370     int rn = extract32(insn, 5, 5);
9371     int opcode = extract32(insn, 11, 4);
9372     int rm = extract32(insn, 16, 5);
9373     int size = extract32(insn, 22, 2);
9374     bool u = extract32(insn, 29, 1);
9375     TCGv_i32 ele1, ele2, ele3;
9376     TCGv_i64 res;
9377     bool feature;
9378
9379     switch (u * 16 + opcode) {
9380     case 0x10: /* SQRDMLAH (vector) */
9381     case 0x11: /* SQRDMLSH (vector) */
9382         if (size != 1 && size != 2) {
9383             unallocated_encoding(s);
9384             return;
9385         }
9386         feature = dc_isar_feature(aa64_rdm, s);
9387         break;
9388     default:
9389         unallocated_encoding(s);
9390         return;
9391     }
9392     if (!feature) {
9393         unallocated_encoding(s);
9394         return;
9395     }
9396     if (!fp_access_check(s)) {
9397         return;
9398     }
9399
9400     /* Do a single operation on the lowest element in the vector.
9401      * We use the standard Neon helpers and rely on 0 OP 0 == 0
9402      * with no side effects for all these operations.
9403      * OPTME: special-purpose helpers would avoid doing some
9404      * unnecessary work in the helper for the 16 bit cases.
9405      */
9406     ele1 = tcg_temp_new_i32();
9407     ele2 = tcg_temp_new_i32();
9408     ele3 = tcg_temp_new_i32();
9409
9410     read_vec_element_i32(s, ele1, rn, 0, size);
9411     read_vec_element_i32(s, ele2, rm, 0, size);
9412     read_vec_element_i32(s, ele3, rd, 0, size);
9413
9414     switch (opcode) {
9415     case 0x0: /* SQRDMLAH */
9416         if (size == 1) {
9417             gen_helper_neon_qrdmlah_s16(ele3, cpu_env, ele1, ele2, ele3);
9418         } else {
9419             gen_helper_neon_qrdmlah_s32(ele3, cpu_env, ele1, ele2, ele3);
9420         }
9421         break;
9422     case 0x1: /* SQRDMLSH */
9423         if (size == 1) {
9424             gen_helper_neon_qrdmlsh_s16(ele3, cpu_env, ele1, ele2, ele3);
9425         } else {
9426             gen_helper_neon_qrdmlsh_s32(ele3, cpu_env, ele1, ele2, ele3);
9427         }
9428         break;
9429     default:
9430         g_assert_not_reached();
9431     }
9432     tcg_temp_free_i32(ele1);
9433     tcg_temp_free_i32(ele2);
9434
9435     res = tcg_temp_new_i64();
9436     tcg_gen_extu_i32_i64(res, ele3);
9437     tcg_temp_free_i32(ele3);
9438
9439     write_fp_dreg(s, rd, res);
9440     tcg_temp_free_i64(res);
9441 }
9442
9443 static void handle_2misc_64(DisasContext *s, int opcode, bool u,
9444                             TCGv_i64 tcg_rd, TCGv_i64 tcg_rn,
9445                             TCGv_i32 tcg_rmode, TCGv_ptr tcg_fpstatus)
9446 {
9447     /* Handle 64->64 opcodes which are shared between the scalar and
9448      * vector 2-reg-misc groups. We cover every integer opcode where size == 3
9449      * is valid in either group and also the double-precision fp ops.
9450      * The caller only need provide tcg_rmode and tcg_fpstatus if the op
9451      * requires them.
9452      */
9453     TCGCond cond;
9454
9455     switch (opcode) {
9456     case 0x4: /* CLS, CLZ */
9457         if (u) {
9458             tcg_gen_clzi_i64(tcg_rd, tcg_rn, 64);
9459         } else {
9460             tcg_gen_clrsb_i64(tcg_rd, tcg_rn);
9461         }
9462         break;
9463     case 0x5: /* NOT */
9464         /* This opcode is shared with CNT and RBIT but we have earlier
9465          * enforced that size == 3 if and only if this is the NOT insn.
9466          */
9467         tcg_gen_not_i64(tcg_rd, tcg_rn);
9468         break;
9469     case 0x7: /* SQABS, SQNEG */
9470         if (u) {
9471             gen_helper_neon_qneg_s64(tcg_rd, cpu_env, tcg_rn);
9472         } else {
9473             gen_helper_neon_qabs_s64(tcg_rd, cpu_env, tcg_rn);
9474         }
9475         break;
9476     case 0xa: /* CMLT */
9477         /* 64 bit integer comparison against zero, result is
9478          * test ? (2^64 - 1) : 0. We implement via setcond(!test) and
9479          * subtracting 1.
9480          */
9481         cond = TCG_COND_LT;
9482     do_cmop:
9483         tcg_gen_setcondi_i64(cond, tcg_rd, tcg_rn, 0);
9484         tcg_gen_neg_i64(tcg_rd, tcg_rd);
9485         break;
9486     case 0x8: /* CMGT, CMGE */
9487         cond = u ? TCG_COND_GE : TCG_COND_GT;
9488         goto do_cmop;
9489     case 0x9: /* CMEQ, CMLE */
9490         cond = u ? TCG_COND_LE : TCG_COND_EQ;
9491         goto do_cmop;
9492     case 0xb: /* ABS, NEG */
9493         if (u) {
9494             tcg_gen_neg_i64(tcg_rd, tcg_rn);
9495         } else {
9496             tcg_gen_abs_i64(tcg_rd, tcg_rn);
9497         }
9498         break;
9499     case 0x2f: /* FABS */
9500         gen_helper_vfp_absd(tcg_rd, tcg_rn);
9501         break;
9502     case 0x6f: /* FNEG */
9503         gen_helper_vfp_negd(tcg_rd, tcg_rn);
9504         break;
9505     case 0x7f: /* FSQRT */
9506         gen_helper_vfp_sqrtd(tcg_rd, tcg_rn, cpu_env);
9507         break;
9508     case 0x1a: /* FCVTNS */
9509     case 0x1b: /* FCVTMS */
9510     case 0x1c: /* FCVTAS */
9511     case 0x3a: /* FCVTPS */
9512     case 0x3b: /* FCVTZS */
9513     {
9514         TCGv_i32 tcg_shift = tcg_const_i32(0);
9515         gen_helper_vfp_tosqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
9516         tcg_temp_free_i32(tcg_shift);
9517         break;
9518     }
9519     case 0x5a: /* FCVTNU */
9520     case 0x5b: /* FCVTMU */
9521     case 0x5c: /* FCVTAU */
9522     case 0x7a: /* FCVTPU */
9523     case 0x7b: /* FCVTZU */
9524     {
9525         TCGv_i32 tcg_shift = tcg_const_i32(0);
9526         gen_helper_vfp_touqd(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
9527         tcg_temp_free_i32(tcg_shift);
9528         break;
9529     }
9530     case 0x18: /* FRINTN */
9531     case 0x19: /* FRINTM */
9532     case 0x38: /* FRINTP */
9533     case 0x39: /* FRINTZ */
9534     case 0x58: /* FRINTA */
9535     case 0x79: /* FRINTI */
9536         gen_helper_rintd(tcg_rd, tcg_rn, tcg_fpstatus);
9537         break;
9538     case 0x59: /* FRINTX */
9539         gen_helper_rintd_exact(tcg_rd, tcg_rn, tcg_fpstatus);
9540         break;
9541     case 0x1e: /* FRINT32Z */
9542     case 0x5e: /* FRINT32X */
9543         gen_helper_frint32_d(tcg_rd, tcg_rn, tcg_fpstatus);
9544         break;
9545     case 0x1f: /* FRINT64Z */
9546     case 0x5f: /* FRINT64X */
9547         gen_helper_frint64_d(tcg_rd, tcg_rn, tcg_fpstatus);
9548         break;
9549     default:
9550         g_assert_not_reached();
9551     }
9552 }
9553
9554 static void handle_2misc_fcmp_zero(DisasContext *s, int opcode,
9555                                    bool is_scalar, bool is_u, bool is_q,
9556                                    int size, int rn, int rd)
9557 {
9558     bool is_double = (size == MO_64);
9559     TCGv_ptr fpst;
9560
9561     if (!fp_access_check(s)) {
9562         return;
9563     }
9564
9565     fpst = get_fpstatus_ptr(size == MO_16);
9566
9567     if (is_double) {
9568         TCGv_i64 tcg_op = tcg_temp_new_i64();
9569         TCGv_i64 tcg_zero = tcg_const_i64(0);
9570         TCGv_i64 tcg_res = tcg_temp_new_i64();
9571         NeonGenTwoDoubleOPFn *genfn;
9572         bool swap = false;
9573         int pass;
9574
9575         switch (opcode) {
9576         case 0x2e: /* FCMLT (zero) */
9577             swap = true;
9578             /* fallthrough */
9579         case 0x2c: /* FCMGT (zero) */
9580             genfn = gen_helper_neon_cgt_f64;
9581             break;
9582         case 0x2d: /* FCMEQ (zero) */
9583             genfn = gen_helper_neon_ceq_f64;
9584             break;
9585         case 0x6d: /* FCMLE (zero) */
9586             swap = true;
9587             /* fall through */
9588         case 0x6c: /* FCMGE (zero) */
9589             genfn = gen_helper_neon_cge_f64;
9590             break;
9591         default:
9592             g_assert_not_reached();
9593         }
9594
9595         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9596             read_vec_element(s, tcg_op, rn, pass, MO_64);
9597             if (swap) {
9598                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
9599             } else {
9600                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
9601             }
9602             write_vec_element(s, tcg_res, rd, pass, MO_64);
9603         }
9604         tcg_temp_free_i64(tcg_res);
9605         tcg_temp_free_i64(tcg_zero);
9606         tcg_temp_free_i64(tcg_op);
9607
9608         clear_vec_high(s, !is_scalar, rd);
9609     } else {
9610         TCGv_i32 tcg_op = tcg_temp_new_i32();
9611         TCGv_i32 tcg_zero = tcg_const_i32(0);
9612         TCGv_i32 tcg_res = tcg_temp_new_i32();
9613         NeonGenTwoSingleOPFn *genfn;
9614         bool swap = false;
9615         int pass, maxpasses;
9616
9617         if (size == MO_16) {
9618             switch (opcode) {
9619             case 0x2e: /* FCMLT (zero) */
9620                 swap = true;
9621                 /* fall through */
9622             case 0x2c: /* FCMGT (zero) */
9623                 genfn = gen_helper_advsimd_cgt_f16;
9624                 break;
9625             case 0x2d: /* FCMEQ (zero) */
9626                 genfn = gen_helper_advsimd_ceq_f16;
9627                 break;
9628             case 0x6d: /* FCMLE (zero) */
9629                 swap = true;
9630                 /* fall through */
9631             case 0x6c: /* FCMGE (zero) */
9632                 genfn = gen_helper_advsimd_cge_f16;
9633                 break;
9634             default:
9635                 g_assert_not_reached();
9636             }
9637         } else {
9638             switch (opcode) {
9639             case 0x2e: /* FCMLT (zero) */
9640                 swap = true;
9641                 /* fall through */
9642             case 0x2c: /* FCMGT (zero) */
9643                 genfn = gen_helper_neon_cgt_f32;
9644                 break;
9645             case 0x2d: /* FCMEQ (zero) */
9646                 genfn = gen_helper_neon_ceq_f32;
9647                 break;
9648             case 0x6d: /* FCMLE (zero) */
9649                 swap = true;
9650                 /* fall through */
9651             case 0x6c: /* FCMGE (zero) */
9652                 genfn = gen_helper_neon_cge_f32;
9653                 break;
9654             default:
9655                 g_assert_not_reached();
9656             }
9657         }
9658
9659         if (is_scalar) {
9660             maxpasses = 1;
9661         } else {
9662             int vector_size = 8 << is_q;
9663             maxpasses = vector_size >> size;
9664         }
9665
9666         for (pass = 0; pass < maxpasses; pass++) {
9667             read_vec_element_i32(s, tcg_op, rn, pass, size);
9668             if (swap) {
9669                 genfn(tcg_res, tcg_zero, tcg_op, fpst);
9670             } else {
9671                 genfn(tcg_res, tcg_op, tcg_zero, fpst);
9672             }
9673             if (is_scalar) {
9674                 write_fp_sreg(s, rd, tcg_res);
9675             } else {
9676                 write_vec_element_i32(s, tcg_res, rd, pass, size);
9677             }
9678         }
9679         tcg_temp_free_i32(tcg_res);
9680         tcg_temp_free_i32(tcg_zero);
9681         tcg_temp_free_i32(tcg_op);
9682         if (!is_scalar) {
9683             clear_vec_high(s, is_q, rd);
9684         }
9685     }
9686
9687     tcg_temp_free_ptr(fpst);
9688 }
9689
9690 static void handle_2misc_reciprocal(DisasContext *s, int opcode,
9691                                     bool is_scalar, bool is_u, bool is_q,
9692                                     int size, int rn, int rd)
9693 {
9694     bool is_double = (size == 3);
9695     TCGv_ptr fpst = get_fpstatus_ptr(false);
9696
9697     if (is_double) {
9698         TCGv_i64 tcg_op = tcg_temp_new_i64();
9699         TCGv_i64 tcg_res = tcg_temp_new_i64();
9700         int pass;
9701
9702         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9703             read_vec_element(s, tcg_op, rn, pass, MO_64);
9704             switch (opcode) {
9705             case 0x3d: /* FRECPE */
9706                 gen_helper_recpe_f64(tcg_res, tcg_op, fpst);
9707                 break;
9708             case 0x3f: /* FRECPX */
9709                 gen_helper_frecpx_f64(tcg_res, tcg_op, fpst);
9710                 break;
9711             case 0x7d: /* FRSQRTE */
9712                 gen_helper_rsqrte_f64(tcg_res, tcg_op, fpst);
9713                 break;
9714             default:
9715                 g_assert_not_reached();
9716             }
9717             write_vec_element(s, tcg_res, rd, pass, MO_64);
9718         }
9719         tcg_temp_free_i64(tcg_res);
9720         tcg_temp_free_i64(tcg_op);
9721         clear_vec_high(s, !is_scalar, rd);
9722     } else {
9723         TCGv_i32 tcg_op = tcg_temp_new_i32();
9724         TCGv_i32 tcg_res = tcg_temp_new_i32();
9725         int pass, maxpasses;
9726
9727         if (is_scalar) {
9728             maxpasses = 1;
9729         } else {
9730             maxpasses = is_q ? 4 : 2;
9731         }
9732
9733         for (pass = 0; pass < maxpasses; pass++) {
9734             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
9735
9736             switch (opcode) {
9737             case 0x3c: /* URECPE */
9738                 gen_helper_recpe_u32(tcg_res, tcg_op, fpst);
9739                 break;
9740             case 0x3d: /* FRECPE */
9741                 gen_helper_recpe_f32(tcg_res, tcg_op, fpst);
9742                 break;
9743             case 0x3f: /* FRECPX */
9744                 gen_helper_frecpx_f32(tcg_res, tcg_op, fpst);
9745                 break;
9746             case 0x7d: /* FRSQRTE */
9747                 gen_helper_rsqrte_f32(tcg_res, tcg_op, fpst);
9748                 break;
9749             default:
9750                 g_assert_not_reached();
9751             }
9752
9753             if (is_scalar) {
9754                 write_fp_sreg(s, rd, tcg_res);
9755             } else {
9756                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
9757             }
9758         }
9759         tcg_temp_free_i32(tcg_res);
9760         tcg_temp_free_i32(tcg_op);
9761         if (!is_scalar) {
9762             clear_vec_high(s, is_q, rd);
9763         }
9764     }
9765     tcg_temp_free_ptr(fpst);
9766 }
9767
9768 static void handle_2misc_narrow(DisasContext *s, bool scalar,
9769                                 int opcode, bool u, bool is_q,
9770                                 int size, int rn, int rd)
9771 {
9772     /* Handle 2-reg-misc ops which are narrowing (so each 2*size element
9773      * in the source becomes a size element in the destination).
9774      */
9775     int pass;
9776     TCGv_i32 tcg_res[2];
9777     int destelt = is_q ? 2 : 0;
9778     int passes = scalar ? 1 : 2;
9779
9780     if (scalar) {
9781         tcg_res[1] = tcg_const_i32(0);
9782     }
9783
9784     for (pass = 0; pass < passes; pass++) {
9785         TCGv_i64 tcg_op = tcg_temp_new_i64();
9786         NeonGenNarrowFn *genfn = NULL;
9787         NeonGenNarrowEnvFn *genenvfn = NULL;
9788
9789         if (scalar) {
9790             read_vec_element(s, tcg_op, rn, pass, size + 1);
9791         } else {
9792             read_vec_element(s, tcg_op, rn, pass, MO_64);
9793         }
9794         tcg_res[pass] = tcg_temp_new_i32();
9795
9796         switch (opcode) {
9797         case 0x12: /* XTN, SQXTUN */
9798         {
9799             static NeonGenNarrowFn * const xtnfns[3] = {
9800                 gen_helper_neon_narrow_u8,
9801                 gen_helper_neon_narrow_u16,
9802                 tcg_gen_extrl_i64_i32,
9803             };
9804             static NeonGenNarrowEnvFn * const sqxtunfns[3] = {
9805                 gen_helper_neon_unarrow_sat8,
9806                 gen_helper_neon_unarrow_sat16,
9807                 gen_helper_neon_unarrow_sat32,
9808             };
9809             if (u) {
9810                 genenvfn = sqxtunfns[size];
9811             } else {
9812                 genfn = xtnfns[size];
9813             }
9814             break;
9815         }
9816         case 0x14: /* SQXTN, UQXTN */
9817         {
9818             static NeonGenNarrowEnvFn * const fns[3][2] = {
9819                 { gen_helper_neon_narrow_sat_s8,
9820                   gen_helper_neon_narrow_sat_u8 },
9821                 { gen_helper_neon_narrow_sat_s16,
9822                   gen_helper_neon_narrow_sat_u16 },
9823                 { gen_helper_neon_narrow_sat_s32,
9824                   gen_helper_neon_narrow_sat_u32 },
9825             };
9826             genenvfn = fns[size][u];
9827             break;
9828         }
9829         case 0x16: /* FCVTN, FCVTN2 */
9830             /* 32 bit to 16 bit or 64 bit to 32 bit float conversion */
9831             if (size == 2) {
9832                 gen_helper_vfp_fcvtsd(tcg_res[pass], tcg_op, cpu_env);
9833             } else {
9834                 TCGv_i32 tcg_lo = tcg_temp_new_i32();
9835                 TCGv_i32 tcg_hi = tcg_temp_new_i32();
9836                 TCGv_ptr fpst = get_fpstatus_ptr(false);
9837                 TCGv_i32 ahp = get_ahp_flag();
9838
9839                 tcg_gen_extr_i64_i32(tcg_lo, tcg_hi, tcg_op);
9840                 gen_helper_vfp_fcvt_f32_to_f16(tcg_lo, tcg_lo, fpst, ahp);
9841                 gen_helper_vfp_fcvt_f32_to_f16(tcg_hi, tcg_hi, fpst, ahp);
9842                 tcg_gen_deposit_i32(tcg_res[pass], tcg_lo, tcg_hi, 16, 16);
9843                 tcg_temp_free_i32(tcg_lo);
9844                 tcg_temp_free_i32(tcg_hi);
9845                 tcg_temp_free_ptr(fpst);
9846                 tcg_temp_free_i32(ahp);
9847             }
9848             break;
9849         case 0x56:  /* FCVTXN, FCVTXN2 */
9850             /* 64 bit to 32 bit float conversion
9851              * with von Neumann rounding (round to odd)
9852              */
9853             assert(size == 2);
9854             gen_helper_fcvtx_f64_to_f32(tcg_res[pass], tcg_op, cpu_env);
9855             break;
9856         default:
9857             g_assert_not_reached();
9858         }
9859
9860         if (genfn) {
9861             genfn(tcg_res[pass], tcg_op);
9862         } else if (genenvfn) {
9863             genenvfn(tcg_res[pass], cpu_env, tcg_op);
9864         }
9865
9866         tcg_temp_free_i64(tcg_op);
9867     }
9868
9869     for (pass = 0; pass < 2; pass++) {
9870         write_vec_element_i32(s, tcg_res[pass], rd, destelt + pass, MO_32);
9871         tcg_temp_free_i32(tcg_res[pass]);
9872     }
9873     clear_vec_high(s, is_q, rd);
9874 }
9875
9876 /* Remaining saturating accumulating ops */
9877 static void handle_2misc_satacc(DisasContext *s, bool is_scalar, bool is_u,
9878                                 bool is_q, int size, int rn, int rd)
9879 {
9880     bool is_double = (size == 3);
9881
9882     if (is_double) {
9883         TCGv_i64 tcg_rn = tcg_temp_new_i64();
9884         TCGv_i64 tcg_rd = tcg_temp_new_i64();
9885         int pass;
9886
9887         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
9888             read_vec_element(s, tcg_rn, rn, pass, MO_64);
9889             read_vec_element(s, tcg_rd, rd, pass, MO_64);
9890
9891             if (is_u) { /* USQADD */
9892                 gen_helper_neon_uqadd_s64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9893             } else { /* SUQADD */
9894                 gen_helper_neon_sqadd_u64(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9895             }
9896             write_vec_element(s, tcg_rd, rd, pass, MO_64);
9897         }
9898         tcg_temp_free_i64(tcg_rd);
9899         tcg_temp_free_i64(tcg_rn);
9900         clear_vec_high(s, !is_scalar, rd);
9901     } else {
9902         TCGv_i32 tcg_rn = tcg_temp_new_i32();
9903         TCGv_i32 tcg_rd = tcg_temp_new_i32();
9904         int pass, maxpasses;
9905
9906         if (is_scalar) {
9907             maxpasses = 1;
9908         } else {
9909             maxpasses = is_q ? 4 : 2;
9910         }
9911
9912         for (pass = 0; pass < maxpasses; pass++) {
9913             if (is_scalar) {
9914                 read_vec_element_i32(s, tcg_rn, rn, pass, size);
9915                 read_vec_element_i32(s, tcg_rd, rd, pass, size);
9916             } else {
9917                 read_vec_element_i32(s, tcg_rn, rn, pass, MO_32);
9918                 read_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
9919             }
9920
9921             if (is_u) { /* USQADD */
9922                 switch (size) {
9923                 case 0:
9924                     gen_helper_neon_uqadd_s8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9925                     break;
9926                 case 1:
9927                     gen_helper_neon_uqadd_s16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9928                     break;
9929                 case 2:
9930                     gen_helper_neon_uqadd_s32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9931                     break;
9932                 default:
9933                     g_assert_not_reached();
9934                 }
9935             } else { /* SUQADD */
9936                 switch (size) {
9937                 case 0:
9938                     gen_helper_neon_sqadd_u8(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9939                     break;
9940                 case 1:
9941                     gen_helper_neon_sqadd_u16(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9942                     break;
9943                 case 2:
9944                     gen_helper_neon_sqadd_u32(tcg_rd, cpu_env, tcg_rn, tcg_rd);
9945                     break;
9946                 default:
9947                     g_assert_not_reached();
9948                 }
9949             }
9950
9951             if (is_scalar) {
9952                 TCGv_i64 tcg_zero = tcg_const_i64(0);
9953                 write_vec_element(s, tcg_zero, rd, 0, MO_64);
9954                 tcg_temp_free_i64(tcg_zero);
9955             }
9956             write_vec_element_i32(s, tcg_rd, rd, pass, MO_32);
9957         }
9958         tcg_temp_free_i32(tcg_rd);
9959         tcg_temp_free_i32(tcg_rn);
9960         clear_vec_high(s, is_q, rd);
9961     }
9962 }
9963
9964 /* AdvSIMD scalar two reg misc
9965  *  31 30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
9966  * +-----+---+-----------+------+-----------+--------+-----+------+------+
9967  * | 0 1 | U | 1 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
9968  * +-----+---+-----------+------+-----------+--------+-----+------+------+
9969  */
9970 static void disas_simd_scalar_two_reg_misc(DisasContext *s, uint32_t insn)
9971 {
9972     int rd = extract32(insn, 0, 5);
9973     int rn = extract32(insn, 5, 5);
9974     int opcode = extract32(insn, 12, 5);
9975     int size = extract32(insn, 22, 2);
9976     bool u = extract32(insn, 29, 1);
9977     bool is_fcvt = false;
9978     int rmode;
9979     TCGv_i32 tcg_rmode;
9980     TCGv_ptr tcg_fpstatus;
9981
9982     switch (opcode) {
9983     case 0x3: /* USQADD / SUQADD*/
9984         if (!fp_access_check(s)) {
9985             return;
9986         }
9987         handle_2misc_satacc(s, true, u, false, size, rn, rd);
9988         return;
9989     case 0x7: /* SQABS / SQNEG */
9990         break;
9991     case 0xa: /* CMLT */
9992         if (u) {
9993             unallocated_encoding(s);
9994             return;
9995         }
9996         /* fall through */
9997     case 0x8: /* CMGT, CMGE */
9998     case 0x9: /* CMEQ, CMLE */
9999     case 0xb: /* ABS, NEG */
10000         if (size != 3) {
10001             unallocated_encoding(s);
10002             return;
10003         }
10004         break;
10005     case 0x12: /* SQXTUN */
10006         if (!u) {
10007             unallocated_encoding(s);
10008             return;
10009         }
10010         /* fall through */
10011     case 0x14: /* SQXTN, UQXTN */
10012         if (size == 3) {
10013             unallocated_encoding(s);
10014             return;
10015         }
10016         if (!fp_access_check(s)) {
10017             return;
10018         }
10019         handle_2misc_narrow(s, true, opcode, u, false, size, rn, rd);
10020         return;
10021     case 0xc ... 0xf:
10022     case 0x16 ... 0x1d:
10023     case 0x1f:
10024         /* Floating point: U, size[1] and opcode indicate operation;
10025          * size[0] indicates single or double precision.
10026          */
10027         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
10028         size = extract32(size, 0, 1) ? 3 : 2;
10029         switch (opcode) {
10030         case 0x2c: /* FCMGT (zero) */
10031         case 0x2d: /* FCMEQ (zero) */
10032         case 0x2e: /* FCMLT (zero) */
10033         case 0x6c: /* FCMGE (zero) */
10034         case 0x6d: /* FCMLE (zero) */
10035             handle_2misc_fcmp_zero(s, opcode, true, u, true, size, rn, rd);
10036             return;
10037         case 0x1d: /* SCVTF */
10038         case 0x5d: /* UCVTF */
10039         {
10040             bool is_signed = (opcode == 0x1d);
10041             if (!fp_access_check(s)) {
10042                 return;
10043             }
10044             handle_simd_intfp_conv(s, rd, rn, 1, is_signed, 0, size);
10045             return;
10046         }
10047         case 0x3d: /* FRECPE */
10048         case 0x3f: /* FRECPX */
10049         case 0x7d: /* FRSQRTE */
10050             if (!fp_access_check(s)) {
10051                 return;
10052             }
10053             handle_2misc_reciprocal(s, opcode, true, u, true, size, rn, rd);
10054             return;
10055         case 0x1a: /* FCVTNS */
10056         case 0x1b: /* FCVTMS */
10057         case 0x3a: /* FCVTPS */
10058         case 0x3b: /* FCVTZS */
10059         case 0x5a: /* FCVTNU */
10060         case 0x5b: /* FCVTMU */
10061         case 0x7a: /* FCVTPU */
10062         case 0x7b: /* FCVTZU */
10063             is_fcvt = true;
10064             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
10065             break;
10066         case 0x1c: /* FCVTAS */
10067         case 0x5c: /* FCVTAU */
10068             /* TIEAWAY doesn't fit in the usual rounding mode encoding */
10069             is_fcvt = true;
10070             rmode = FPROUNDING_TIEAWAY;
10071             break;
10072         case 0x56: /* FCVTXN, FCVTXN2 */
10073             if (size == 2) {
10074                 unallocated_encoding(s);
10075                 return;
10076             }
10077             if (!fp_access_check(s)) {
10078                 return;
10079             }
10080             handle_2misc_narrow(s, true, opcode, u, false, size - 1, rn, rd);
10081             return;
10082         default:
10083             unallocated_encoding(s);
10084             return;
10085         }
10086         break;
10087     default:
10088         unallocated_encoding(s);
10089         return;
10090     }
10091
10092     if (!fp_access_check(s)) {
10093         return;
10094     }
10095
10096     if (is_fcvt) {
10097         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
10098         tcg_fpstatus = get_fpstatus_ptr(false);
10099         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
10100     } else {
10101         tcg_rmode = NULL;
10102         tcg_fpstatus = NULL;
10103     }
10104
10105     if (size == 3) {
10106         TCGv_i64 tcg_rn = read_fp_dreg(s, rn);
10107         TCGv_i64 tcg_rd = tcg_temp_new_i64();
10108
10109         handle_2misc_64(s, opcode, u, tcg_rd, tcg_rn, tcg_rmode, tcg_fpstatus);
10110         write_fp_dreg(s, rd, tcg_rd);
10111         tcg_temp_free_i64(tcg_rd);
10112         tcg_temp_free_i64(tcg_rn);
10113     } else {
10114         TCGv_i32 tcg_rn = tcg_temp_new_i32();
10115         TCGv_i32 tcg_rd = tcg_temp_new_i32();
10116
10117         read_vec_element_i32(s, tcg_rn, rn, 0, size);
10118
10119         switch (opcode) {
10120         case 0x7: /* SQABS, SQNEG */
10121         {
10122             NeonGenOneOpEnvFn *genfn;
10123             static NeonGenOneOpEnvFn * const fns[3][2] = {
10124                 { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
10125                 { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
10126                 { gen_helper_neon_qabs_s32, gen_helper_neon_qneg_s32 },
10127             };
10128             genfn = fns[size][u];
10129             genfn(tcg_rd, cpu_env, tcg_rn);
10130             break;
10131         }
10132         case 0x1a: /* FCVTNS */
10133         case 0x1b: /* FCVTMS */
10134         case 0x1c: /* FCVTAS */
10135         case 0x3a: /* FCVTPS */
10136         case 0x3b: /* FCVTZS */
10137         {
10138             TCGv_i32 tcg_shift = tcg_const_i32(0);
10139             gen_helper_vfp_tosls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
10140             tcg_temp_free_i32(tcg_shift);
10141             break;
10142         }
10143         case 0x5a: /* FCVTNU */
10144         case 0x5b: /* FCVTMU */
10145         case 0x5c: /* FCVTAU */
10146         case 0x7a: /* FCVTPU */
10147         case 0x7b: /* FCVTZU */
10148         {
10149             TCGv_i32 tcg_shift = tcg_const_i32(0);
10150             gen_helper_vfp_touls(tcg_rd, tcg_rn, tcg_shift, tcg_fpstatus);
10151             tcg_temp_free_i32(tcg_shift);
10152             break;
10153         }
10154         default:
10155             g_assert_not_reached();
10156         }
10157
10158         write_fp_sreg(s, rd, tcg_rd);
10159         tcg_temp_free_i32(tcg_rd);
10160         tcg_temp_free_i32(tcg_rn);
10161     }
10162
10163     if (is_fcvt) {
10164         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
10165         tcg_temp_free_i32(tcg_rmode);
10166         tcg_temp_free_ptr(tcg_fpstatus);
10167     }
10168 }
10169
10170 /* SSHR[RA]/USHR[RA] - Vector shift right (optional rounding/accumulate) */
10171 static void handle_vec_simd_shri(DisasContext *s, bool is_q, bool is_u,
10172                                  int immh, int immb, int opcode, int rn, int rd)
10173 {
10174     int size = 32 - clz32(immh) - 1;
10175     int immhb = immh << 3 | immb;
10176     int shift = 2 * (8 << size) - immhb;
10177     bool accumulate = false;
10178     int dsize = is_q ? 128 : 64;
10179     int esize = 8 << size;
10180     int elements = dsize/esize;
10181     MemOp memop = size | (is_u ? 0 : MO_SIGN);
10182     TCGv_i64 tcg_rn = new_tmp_a64(s);
10183     TCGv_i64 tcg_rd = new_tmp_a64(s);
10184     TCGv_i64 tcg_round;
10185     uint64_t round_const;
10186     int i;
10187
10188     if (extract32(immh, 3, 1) && !is_q) {
10189         unallocated_encoding(s);
10190         return;
10191     }
10192     tcg_debug_assert(size <= 3);
10193
10194     if (!fp_access_check(s)) {
10195         return;
10196     }
10197
10198     switch (opcode) {
10199     case 0x02: /* SSRA / USRA (accumulate) */
10200         if (is_u) {
10201             /* Shift count same as element size produces zero to add.  */
10202             if (shift == 8 << size) {
10203                 goto done;
10204             }
10205             gen_gvec_op2i(s, is_q, rd, rn, shift, &usra_op[size]);
10206         } else {
10207             /* Shift count same as element size produces all sign to add.  */
10208             if (shift == 8 << size) {
10209                 shift -= 1;
10210             }
10211             gen_gvec_op2i(s, is_q, rd, rn, shift, &ssra_op[size]);
10212         }
10213         return;
10214     case 0x08: /* SRI */
10215         /* Shift count same as element size is valid but does nothing.  */
10216         if (shift == 8 << size) {
10217             goto done;
10218         }
10219         gen_gvec_op2i(s, is_q, rd, rn, shift, &sri_op[size]);
10220         return;
10221
10222     case 0x00: /* SSHR / USHR */
10223         if (is_u) {
10224             if (shift == 8 << size) {
10225                 /* Shift count the same size as element size produces zero.  */
10226                 tcg_gen_gvec_dup8i(vec_full_reg_offset(s, rd),
10227                                    is_q ? 16 : 8, vec_full_reg_size(s), 0);
10228             } else {
10229                 gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shri, size);
10230             }
10231         } else {
10232             /* Shift count the same size as element size produces all sign.  */
10233             if (shift == 8 << size) {
10234                 shift -= 1;
10235             }
10236             gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_sari, size);
10237         }
10238         return;
10239
10240     case 0x04: /* SRSHR / URSHR (rounding) */
10241         break;
10242     case 0x06: /* SRSRA / URSRA (accum + rounding) */
10243         accumulate = true;
10244         break;
10245     default:
10246         g_assert_not_reached();
10247     }
10248
10249     round_const = 1ULL << (shift - 1);
10250     tcg_round = tcg_const_i64(round_const);
10251
10252     for (i = 0; i < elements; i++) {
10253         read_vec_element(s, tcg_rn, rn, i, memop);
10254         if (accumulate) {
10255             read_vec_element(s, tcg_rd, rd, i, memop);
10256         }
10257
10258         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
10259                                 accumulate, is_u, size, shift);
10260
10261         write_vec_element(s, tcg_rd, rd, i, size);
10262     }
10263     tcg_temp_free_i64(tcg_round);
10264
10265  done:
10266     clear_vec_high(s, is_q, rd);
10267 }
10268
10269 /* SHL/SLI - Vector shift left */
10270 static void handle_vec_simd_shli(DisasContext *s, bool is_q, bool insert,
10271                                  int immh, int immb, int opcode, int rn, int rd)
10272 {
10273     int size = 32 - clz32(immh) - 1;
10274     int immhb = immh << 3 | immb;
10275     int shift = immhb - (8 << size);
10276
10277     /* Range of size is limited by decode: immh is a non-zero 4 bit field */
10278     assert(size >= 0 && size <= 3);
10279
10280     if (extract32(immh, 3, 1) && !is_q) {
10281         unallocated_encoding(s);
10282         return;
10283     }
10284
10285     if (!fp_access_check(s)) {
10286         return;
10287     }
10288
10289     if (insert) {
10290         gen_gvec_op2i(s, is_q, rd, rn, shift, &sli_op[size]);
10291     } else {
10292         gen_gvec_fn2i(s, is_q, rd, rn, shift, tcg_gen_gvec_shli, size);
10293     }
10294 }
10295
10296 /* USHLL/SHLL - Vector shift left with widening */
10297 static void handle_vec_simd_wshli(DisasContext *s, bool is_q, bool is_u,
10298                                  int immh, int immb, int opcode, int rn, int rd)
10299 {
10300     int size = 32 - clz32(immh) - 1;
10301     int immhb = immh << 3 | immb;
10302     int shift = immhb - (8 << size);
10303     int dsize = 64;
10304     int esize = 8 << size;
10305     int elements = dsize/esize;
10306     TCGv_i64 tcg_rn = new_tmp_a64(s);
10307     TCGv_i64 tcg_rd = new_tmp_a64(s);
10308     int i;
10309
10310     if (size >= 3) {
10311         unallocated_encoding(s);
10312         return;
10313     }
10314
10315     if (!fp_access_check(s)) {
10316         return;
10317     }
10318
10319     /* For the LL variants the store is larger than the load,
10320      * so if rd == rn we would overwrite parts of our input.
10321      * So load everything right now and use shifts in the main loop.
10322      */
10323     read_vec_element(s, tcg_rn, rn, is_q ? 1 : 0, MO_64);
10324
10325     for (i = 0; i < elements; i++) {
10326         tcg_gen_shri_i64(tcg_rd, tcg_rn, i * esize);
10327         ext_and_shift_reg(tcg_rd, tcg_rd, size | (!is_u << 2), 0);
10328         tcg_gen_shli_i64(tcg_rd, tcg_rd, shift);
10329         write_vec_element(s, tcg_rd, rd, i, size + 1);
10330     }
10331 }
10332
10333 /* SHRN/RSHRN - Shift right with narrowing (and potential rounding) */
10334 static void handle_vec_simd_shrn(DisasContext *s, bool is_q,
10335                                  int immh, int immb, int opcode, int rn, int rd)
10336 {
10337     int immhb = immh << 3 | immb;
10338     int size = 32 - clz32(immh) - 1;
10339     int dsize = 64;
10340     int esize = 8 << size;
10341     int elements = dsize/esize;
10342     int shift = (2 * esize) - immhb;
10343     bool round = extract32(opcode, 0, 1);
10344     TCGv_i64 tcg_rn, tcg_rd, tcg_final;
10345     TCGv_i64 tcg_round;
10346     int i;
10347
10348     if (extract32(immh, 3, 1)) {
10349         unallocated_encoding(s);
10350         return;
10351     }
10352
10353     if (!fp_access_check(s)) {
10354         return;
10355     }
10356
10357     tcg_rn = tcg_temp_new_i64();
10358     tcg_rd = tcg_temp_new_i64();
10359     tcg_final = tcg_temp_new_i64();
10360     read_vec_element(s, tcg_final, rd, is_q ? 1 : 0, MO_64);
10361
10362     if (round) {
10363         uint64_t round_const = 1ULL << (shift - 1);
10364         tcg_round = tcg_const_i64(round_const);
10365     } else {
10366         tcg_round = NULL;
10367     }
10368
10369     for (i = 0; i < elements; i++) {
10370         read_vec_element(s, tcg_rn, rn, i, size+1);
10371         handle_shri_with_rndacc(tcg_rd, tcg_rn, tcg_round,
10372                                 false, true, size+1, shift);
10373
10374         tcg_gen_deposit_i64(tcg_final, tcg_final, tcg_rd, esize * i, esize);
10375     }
10376
10377     if (!is_q) {
10378         write_vec_element(s, tcg_final, rd, 0, MO_64);
10379     } else {
10380         write_vec_element(s, tcg_final, rd, 1, MO_64);
10381     }
10382     if (round) {
10383         tcg_temp_free_i64(tcg_round);
10384     }
10385     tcg_temp_free_i64(tcg_rn);
10386     tcg_temp_free_i64(tcg_rd);
10387     tcg_temp_free_i64(tcg_final);
10388
10389     clear_vec_high(s, is_q, rd);
10390 }
10391
10392
10393 /* AdvSIMD shift by immediate
10394  *  31  30   29 28         23 22  19 18  16 15    11  10 9    5 4    0
10395  * +---+---+---+-------------+------+------+--------+---+------+------+
10396  * | 0 | Q | U | 0 1 1 1 1 0 | immh | immb | opcode | 1 |  Rn  |  Rd  |
10397  * +---+---+---+-------------+------+------+--------+---+------+------+
10398  */
10399 static void disas_simd_shift_imm(DisasContext *s, uint32_t insn)
10400 {
10401     int rd = extract32(insn, 0, 5);
10402     int rn = extract32(insn, 5, 5);
10403     int opcode = extract32(insn, 11, 5);
10404     int immb = extract32(insn, 16, 3);
10405     int immh = extract32(insn, 19, 4);
10406     bool is_u = extract32(insn, 29, 1);
10407     bool is_q = extract32(insn, 30, 1);
10408
10409     /* data_proc_simd[] has sent immh == 0 to disas_simd_mod_imm. */
10410     assert(immh != 0);
10411
10412     switch (opcode) {
10413     case 0x08: /* SRI */
10414         if (!is_u) {
10415             unallocated_encoding(s);
10416             return;
10417         }
10418         /* fall through */
10419     case 0x00: /* SSHR / USHR */
10420     case 0x02: /* SSRA / USRA (accumulate) */
10421     case 0x04: /* SRSHR / URSHR (rounding) */
10422     case 0x06: /* SRSRA / URSRA (accum + rounding) */
10423         handle_vec_simd_shri(s, is_q, is_u, immh, immb, opcode, rn, rd);
10424         break;
10425     case 0x0a: /* SHL / SLI */
10426         handle_vec_simd_shli(s, is_q, is_u, immh, immb, opcode, rn, rd);
10427         break;
10428     case 0x10: /* SHRN */
10429     case 0x11: /* RSHRN / SQRSHRUN */
10430         if (is_u) {
10431             handle_vec_simd_sqshrn(s, false, is_q, false, true, immh, immb,
10432                                    opcode, rn, rd);
10433         } else {
10434             handle_vec_simd_shrn(s, is_q, immh, immb, opcode, rn, rd);
10435         }
10436         break;
10437     case 0x12: /* SQSHRN / UQSHRN */
10438     case 0x13: /* SQRSHRN / UQRSHRN */
10439         handle_vec_simd_sqshrn(s, false, is_q, is_u, is_u, immh, immb,
10440                                opcode, rn, rd);
10441         break;
10442     case 0x14: /* SSHLL / USHLL */
10443         handle_vec_simd_wshli(s, is_q, is_u, immh, immb, opcode, rn, rd);
10444         break;
10445     case 0x1c: /* SCVTF / UCVTF */
10446         handle_simd_shift_intfp_conv(s, false, is_q, is_u, immh, immb,
10447                                      opcode, rn, rd);
10448         break;
10449     case 0xc: /* SQSHLU */
10450         if (!is_u) {
10451             unallocated_encoding(s);
10452             return;
10453         }
10454         handle_simd_qshl(s, false, is_q, false, true, immh, immb, rn, rd);
10455         break;
10456     case 0xe: /* SQSHL, UQSHL */
10457         handle_simd_qshl(s, false, is_q, is_u, is_u, immh, immb, rn, rd);
10458         break;
10459     case 0x1f: /* FCVTZS/ FCVTZU */
10460         handle_simd_shift_fpint_conv(s, false, is_q, is_u, immh, immb, rn, rd);
10461         return;
10462     default:
10463         unallocated_encoding(s);
10464         return;
10465     }
10466 }
10467
10468 /* Generate code to do a "long" addition or subtraction, ie one done in
10469  * TCGv_i64 on vector lanes twice the width specified by size.
10470  */
10471 static void gen_neon_addl(int size, bool is_sub, TCGv_i64 tcg_res,
10472                           TCGv_i64 tcg_op1, TCGv_i64 tcg_op2)
10473 {
10474     static NeonGenTwo64OpFn * const fns[3][2] = {
10475         { gen_helper_neon_addl_u16, gen_helper_neon_subl_u16 },
10476         { gen_helper_neon_addl_u32, gen_helper_neon_subl_u32 },
10477         { tcg_gen_add_i64, tcg_gen_sub_i64 },
10478     };
10479     NeonGenTwo64OpFn *genfn;
10480     assert(size < 3);
10481
10482     genfn = fns[size][is_sub];
10483     genfn(tcg_res, tcg_op1, tcg_op2);
10484 }
10485
10486 static void handle_3rd_widening(DisasContext *s, int is_q, int is_u, int size,
10487                                 int opcode, int rd, int rn, int rm)
10488 {
10489     /* 3-reg-different widening insns: 64 x 64 -> 128 */
10490     TCGv_i64 tcg_res[2];
10491     int pass, accop;
10492
10493     tcg_res[0] = tcg_temp_new_i64();
10494     tcg_res[1] = tcg_temp_new_i64();
10495
10496     /* Does this op do an adding accumulate, a subtracting accumulate,
10497      * or no accumulate at all?
10498      */
10499     switch (opcode) {
10500     case 5:
10501     case 8:
10502     case 9:
10503         accop = 1;
10504         break;
10505     case 10:
10506     case 11:
10507         accop = -1;
10508         break;
10509     default:
10510         accop = 0;
10511         break;
10512     }
10513
10514     if (accop != 0) {
10515         read_vec_element(s, tcg_res[0], rd, 0, MO_64);
10516         read_vec_element(s, tcg_res[1], rd, 1, MO_64);
10517     }
10518
10519     /* size == 2 means two 32x32->64 operations; this is worth special
10520      * casing because we can generally handle it inline.
10521      */
10522     if (size == 2) {
10523         for (pass = 0; pass < 2; pass++) {
10524             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10525             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10526             TCGv_i64 tcg_passres;
10527             MemOp memop = MO_32 | (is_u ? 0 : MO_SIGN);
10528
10529             int elt = pass + is_q * 2;
10530
10531             read_vec_element(s, tcg_op1, rn, elt, memop);
10532             read_vec_element(s, tcg_op2, rm, elt, memop);
10533
10534             if (accop == 0) {
10535                 tcg_passres = tcg_res[pass];
10536             } else {
10537                 tcg_passres = tcg_temp_new_i64();
10538             }
10539
10540             switch (opcode) {
10541             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10542                 tcg_gen_add_i64(tcg_passres, tcg_op1, tcg_op2);
10543                 break;
10544             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10545                 tcg_gen_sub_i64(tcg_passres, tcg_op1, tcg_op2);
10546                 break;
10547             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10548             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10549             {
10550                 TCGv_i64 tcg_tmp1 = tcg_temp_new_i64();
10551                 TCGv_i64 tcg_tmp2 = tcg_temp_new_i64();
10552
10553                 tcg_gen_sub_i64(tcg_tmp1, tcg_op1, tcg_op2);
10554                 tcg_gen_sub_i64(tcg_tmp2, tcg_op2, tcg_op1);
10555                 tcg_gen_movcond_i64(is_u ? TCG_COND_GEU : TCG_COND_GE,
10556                                     tcg_passres,
10557                                     tcg_op1, tcg_op2, tcg_tmp1, tcg_tmp2);
10558                 tcg_temp_free_i64(tcg_tmp1);
10559                 tcg_temp_free_i64(tcg_tmp2);
10560                 break;
10561             }
10562             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10563             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10564             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
10565                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
10566                 break;
10567             case 9: /* SQDMLAL, SQDMLAL2 */
10568             case 11: /* SQDMLSL, SQDMLSL2 */
10569             case 13: /* SQDMULL, SQDMULL2 */
10570                 tcg_gen_mul_i64(tcg_passres, tcg_op1, tcg_op2);
10571                 gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
10572                                                   tcg_passres, tcg_passres);
10573                 break;
10574             default:
10575                 g_assert_not_reached();
10576             }
10577
10578             if (opcode == 9 || opcode == 11) {
10579                 /* saturating accumulate ops */
10580                 if (accop < 0) {
10581                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
10582                 }
10583                 gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
10584                                                   tcg_res[pass], tcg_passres);
10585             } else if (accop > 0) {
10586                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10587             } else if (accop < 0) {
10588                 tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
10589             }
10590
10591             if (accop != 0) {
10592                 tcg_temp_free_i64(tcg_passres);
10593             }
10594
10595             tcg_temp_free_i64(tcg_op1);
10596             tcg_temp_free_i64(tcg_op2);
10597         }
10598     } else {
10599         /* size 0 or 1, generally helper functions */
10600         for (pass = 0; pass < 2; pass++) {
10601             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
10602             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10603             TCGv_i64 tcg_passres;
10604             int elt = pass + is_q * 2;
10605
10606             read_vec_element_i32(s, tcg_op1, rn, elt, MO_32);
10607             read_vec_element_i32(s, tcg_op2, rm, elt, MO_32);
10608
10609             if (accop == 0) {
10610                 tcg_passres = tcg_res[pass];
10611             } else {
10612                 tcg_passres = tcg_temp_new_i64();
10613             }
10614
10615             switch (opcode) {
10616             case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10617             case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10618             {
10619                 TCGv_i64 tcg_op2_64 = tcg_temp_new_i64();
10620                 static NeonGenWidenFn * const widenfns[2][2] = {
10621                     { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
10622                     { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
10623                 };
10624                 NeonGenWidenFn *widenfn = widenfns[size][is_u];
10625
10626                 widenfn(tcg_op2_64, tcg_op2);
10627                 widenfn(tcg_passres, tcg_op1);
10628                 gen_neon_addl(size, (opcode == 2), tcg_passres,
10629                               tcg_passres, tcg_op2_64);
10630                 tcg_temp_free_i64(tcg_op2_64);
10631                 break;
10632             }
10633             case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10634             case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10635                 if (size == 0) {
10636                     if (is_u) {
10637                         gen_helper_neon_abdl_u16(tcg_passres, tcg_op1, tcg_op2);
10638                     } else {
10639                         gen_helper_neon_abdl_s16(tcg_passres, tcg_op1, tcg_op2);
10640                     }
10641                 } else {
10642                     if (is_u) {
10643                         gen_helper_neon_abdl_u32(tcg_passres, tcg_op1, tcg_op2);
10644                     } else {
10645                         gen_helper_neon_abdl_s32(tcg_passres, tcg_op1, tcg_op2);
10646                     }
10647                 }
10648                 break;
10649             case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10650             case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10651             case 12: /* UMULL, UMULL2, SMULL, SMULL2 */
10652                 if (size == 0) {
10653                     if (is_u) {
10654                         gen_helper_neon_mull_u8(tcg_passres, tcg_op1, tcg_op2);
10655                     } else {
10656                         gen_helper_neon_mull_s8(tcg_passres, tcg_op1, tcg_op2);
10657                     }
10658                 } else {
10659                     if (is_u) {
10660                         gen_helper_neon_mull_u16(tcg_passres, tcg_op1, tcg_op2);
10661                     } else {
10662                         gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
10663                     }
10664                 }
10665                 break;
10666             case 9: /* SQDMLAL, SQDMLAL2 */
10667             case 11: /* SQDMLSL, SQDMLSL2 */
10668             case 13: /* SQDMULL, SQDMULL2 */
10669                 assert(size == 1);
10670                 gen_helper_neon_mull_s16(tcg_passres, tcg_op1, tcg_op2);
10671                 gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
10672                                                   tcg_passres, tcg_passres);
10673                 break;
10674             default:
10675                 g_assert_not_reached();
10676             }
10677             tcg_temp_free_i32(tcg_op1);
10678             tcg_temp_free_i32(tcg_op2);
10679
10680             if (accop != 0) {
10681                 if (opcode == 9 || opcode == 11) {
10682                     /* saturating accumulate ops */
10683                     if (accop < 0) {
10684                         gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
10685                     }
10686                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
10687                                                       tcg_res[pass],
10688                                                       tcg_passres);
10689                 } else {
10690                     gen_neon_addl(size, (accop < 0), tcg_res[pass],
10691                                   tcg_res[pass], tcg_passres);
10692                 }
10693                 tcg_temp_free_i64(tcg_passres);
10694             }
10695         }
10696     }
10697
10698     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
10699     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
10700     tcg_temp_free_i64(tcg_res[0]);
10701     tcg_temp_free_i64(tcg_res[1]);
10702 }
10703
10704 static void handle_3rd_wide(DisasContext *s, int is_q, int is_u, int size,
10705                             int opcode, int rd, int rn, int rm)
10706 {
10707     TCGv_i64 tcg_res[2];
10708     int part = is_q ? 2 : 0;
10709     int pass;
10710
10711     for (pass = 0; pass < 2; pass++) {
10712         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10713         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
10714         TCGv_i64 tcg_op2_wide = tcg_temp_new_i64();
10715         static NeonGenWidenFn * const widenfns[3][2] = {
10716             { gen_helper_neon_widen_s8, gen_helper_neon_widen_u8 },
10717             { gen_helper_neon_widen_s16, gen_helper_neon_widen_u16 },
10718             { tcg_gen_ext_i32_i64, tcg_gen_extu_i32_i64 },
10719         };
10720         NeonGenWidenFn *widenfn = widenfns[size][is_u];
10721
10722         read_vec_element(s, tcg_op1, rn, pass, MO_64);
10723         read_vec_element_i32(s, tcg_op2, rm, part + pass, MO_32);
10724         widenfn(tcg_op2_wide, tcg_op2);
10725         tcg_temp_free_i32(tcg_op2);
10726         tcg_res[pass] = tcg_temp_new_i64();
10727         gen_neon_addl(size, (opcode == 3),
10728                       tcg_res[pass], tcg_op1, tcg_op2_wide);
10729         tcg_temp_free_i64(tcg_op1);
10730         tcg_temp_free_i64(tcg_op2_wide);
10731     }
10732
10733     for (pass = 0; pass < 2; pass++) {
10734         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
10735         tcg_temp_free_i64(tcg_res[pass]);
10736     }
10737 }
10738
10739 static void do_narrow_round_high_u32(TCGv_i32 res, TCGv_i64 in)
10740 {
10741     tcg_gen_addi_i64(in, in, 1U << 31);
10742     tcg_gen_extrh_i64_i32(res, in);
10743 }
10744
10745 static void handle_3rd_narrowing(DisasContext *s, int is_q, int is_u, int size,
10746                                  int opcode, int rd, int rn, int rm)
10747 {
10748     TCGv_i32 tcg_res[2];
10749     int part = is_q ? 2 : 0;
10750     int pass;
10751
10752     for (pass = 0; pass < 2; pass++) {
10753         TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10754         TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10755         TCGv_i64 tcg_wideres = tcg_temp_new_i64();
10756         static NeonGenNarrowFn * const narrowfns[3][2] = {
10757             { gen_helper_neon_narrow_high_u8,
10758               gen_helper_neon_narrow_round_high_u8 },
10759             { gen_helper_neon_narrow_high_u16,
10760               gen_helper_neon_narrow_round_high_u16 },
10761             { tcg_gen_extrh_i64_i32, do_narrow_round_high_u32 },
10762         };
10763         NeonGenNarrowFn *gennarrow = narrowfns[size][is_u];
10764
10765         read_vec_element(s, tcg_op1, rn, pass, MO_64);
10766         read_vec_element(s, tcg_op2, rm, pass, MO_64);
10767
10768         gen_neon_addl(size, (opcode == 6), tcg_wideres, tcg_op1, tcg_op2);
10769
10770         tcg_temp_free_i64(tcg_op1);
10771         tcg_temp_free_i64(tcg_op2);
10772
10773         tcg_res[pass] = tcg_temp_new_i32();
10774         gennarrow(tcg_res[pass], tcg_wideres);
10775         tcg_temp_free_i64(tcg_wideres);
10776     }
10777
10778     for (pass = 0; pass < 2; pass++) {
10779         write_vec_element_i32(s, tcg_res[pass], rd, pass + part, MO_32);
10780         tcg_temp_free_i32(tcg_res[pass]);
10781     }
10782     clear_vec_high(s, is_q, rd);
10783 }
10784
10785 /* AdvSIMD three different
10786  *   31  30  29 28       24 23  22  21 20  16 15    12 11 10 9    5 4    0
10787  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
10788  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 0 0 |  Rn  |  Rd  |
10789  * +---+---+---+-----------+------+---+------+--------+-----+------+------+
10790  */
10791 static void disas_simd_three_reg_diff(DisasContext *s, uint32_t insn)
10792 {
10793     /* Instructions in this group fall into three basic classes
10794      * (in each case with the operation working on each element in
10795      * the input vectors):
10796      * (1) widening 64 x 64 -> 128 (with possibly Vd as an extra
10797      *     128 bit input)
10798      * (2) wide 64 x 128 -> 128
10799      * (3) narrowing 128 x 128 -> 64
10800      * Here we do initial decode, catch unallocated cases and
10801      * dispatch to separate functions for each class.
10802      */
10803     int is_q = extract32(insn, 30, 1);
10804     int is_u = extract32(insn, 29, 1);
10805     int size = extract32(insn, 22, 2);
10806     int opcode = extract32(insn, 12, 4);
10807     int rm = extract32(insn, 16, 5);
10808     int rn = extract32(insn, 5, 5);
10809     int rd = extract32(insn, 0, 5);
10810
10811     switch (opcode) {
10812     case 1: /* SADDW, SADDW2, UADDW, UADDW2 */
10813     case 3: /* SSUBW, SSUBW2, USUBW, USUBW2 */
10814         /* 64 x 128 -> 128 */
10815         if (size == 3) {
10816             unallocated_encoding(s);
10817             return;
10818         }
10819         if (!fp_access_check(s)) {
10820             return;
10821         }
10822         handle_3rd_wide(s, is_q, is_u, size, opcode, rd, rn, rm);
10823         break;
10824     case 4: /* ADDHN, ADDHN2, RADDHN, RADDHN2 */
10825     case 6: /* SUBHN, SUBHN2, RSUBHN, RSUBHN2 */
10826         /* 128 x 128 -> 64 */
10827         if (size == 3) {
10828             unallocated_encoding(s);
10829             return;
10830         }
10831         if (!fp_access_check(s)) {
10832             return;
10833         }
10834         handle_3rd_narrowing(s, is_q, is_u, size, opcode, rd, rn, rm);
10835         break;
10836     case 14: /* PMULL, PMULL2 */
10837         if (is_u) {
10838             unallocated_encoding(s);
10839             return;
10840         }
10841         switch (size) {
10842         case 0: /* PMULL.P8 */
10843             if (!fp_access_check(s)) {
10844                 return;
10845             }
10846             /* The Q field specifies lo/hi half input for this insn.  */
10847             gen_gvec_op3_ool(s, true, rd, rn, rm, is_q,
10848                              gen_helper_neon_pmull_h);
10849             break;
10850
10851         case 3: /* PMULL.P64 */
10852             if (!dc_isar_feature(aa64_pmull, s)) {
10853                 unallocated_encoding(s);
10854                 return;
10855             }
10856             if (!fp_access_check(s)) {
10857                 return;
10858             }
10859             /* The Q field specifies lo/hi half input for this insn.  */
10860             gen_gvec_op3_ool(s, true, rd, rn, rm, is_q,
10861                              gen_helper_gvec_pmull_q);
10862             break;
10863
10864         default:
10865             unallocated_encoding(s);
10866             break;
10867         }
10868         return;
10869     case 9: /* SQDMLAL, SQDMLAL2 */
10870     case 11: /* SQDMLSL, SQDMLSL2 */
10871     case 13: /* SQDMULL, SQDMULL2 */
10872         if (is_u || size == 0) {
10873             unallocated_encoding(s);
10874             return;
10875         }
10876         /* fall through */
10877     case 0: /* SADDL, SADDL2, UADDL, UADDL2 */
10878     case 2: /* SSUBL, SSUBL2, USUBL, USUBL2 */
10879     case 5: /* SABAL, SABAL2, UABAL, UABAL2 */
10880     case 7: /* SABDL, SABDL2, UABDL, UABDL2 */
10881     case 8: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
10882     case 10: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
10883     case 12: /* SMULL, SMULL2, UMULL, UMULL2 */
10884         /* 64 x 64 -> 128 */
10885         if (size == 3) {
10886             unallocated_encoding(s);
10887             return;
10888         }
10889         if (!fp_access_check(s)) {
10890             return;
10891         }
10892
10893         handle_3rd_widening(s, is_q, is_u, size, opcode, rd, rn, rm);
10894         break;
10895     default:
10896         /* opcode 15 not allocated */
10897         unallocated_encoding(s);
10898         break;
10899     }
10900 }
10901
10902 /* Logic op (opcode == 3) subgroup of C3.6.16. */
10903 static void disas_simd_3same_logic(DisasContext *s, uint32_t insn)
10904 {
10905     int rd = extract32(insn, 0, 5);
10906     int rn = extract32(insn, 5, 5);
10907     int rm = extract32(insn, 16, 5);
10908     int size = extract32(insn, 22, 2);
10909     bool is_u = extract32(insn, 29, 1);
10910     bool is_q = extract32(insn, 30, 1);
10911
10912     if (!fp_access_check(s)) {
10913         return;
10914     }
10915
10916     switch (size + 4 * is_u) {
10917     case 0: /* AND */
10918         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_and, 0);
10919         return;
10920     case 1: /* BIC */
10921         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_andc, 0);
10922         return;
10923     case 2: /* ORR */
10924         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_or, 0);
10925         return;
10926     case 3: /* ORN */
10927         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_orc, 0);
10928         return;
10929     case 4: /* EOR */
10930         gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_xor, 0);
10931         return;
10932
10933     case 5: /* BSL bitwise select */
10934         gen_gvec_fn4(s, is_q, rd, rd, rn, rm, tcg_gen_gvec_bitsel, 0);
10935         return;
10936     case 6: /* BIT, bitwise insert if true */
10937         gen_gvec_fn4(s, is_q, rd, rm, rn, rd, tcg_gen_gvec_bitsel, 0);
10938         return;
10939     case 7: /* BIF, bitwise insert if false */
10940         gen_gvec_fn4(s, is_q, rd, rm, rd, rn, tcg_gen_gvec_bitsel, 0);
10941         return;
10942
10943     default:
10944         g_assert_not_reached();
10945     }
10946 }
10947
10948 /* Pairwise op subgroup of C3.6.16.
10949  *
10950  * This is called directly or via the handle_3same_float for float pairwise
10951  * operations where the opcode and size are calculated differently.
10952  */
10953 static void handle_simd_3same_pair(DisasContext *s, int is_q, int u, int opcode,
10954                                    int size, int rn, int rm, int rd)
10955 {
10956     TCGv_ptr fpst;
10957     int pass;
10958
10959     /* Floating point operations need fpst */
10960     if (opcode >= 0x58) {
10961         fpst = get_fpstatus_ptr(false);
10962     } else {
10963         fpst = NULL;
10964     }
10965
10966     if (!fp_access_check(s)) {
10967         return;
10968     }
10969
10970     /* These operations work on the concatenated rm:rn, with each pair of
10971      * adjacent elements being operated on to produce an element in the result.
10972      */
10973     if (size == 3) {
10974         TCGv_i64 tcg_res[2];
10975
10976         for (pass = 0; pass < 2; pass++) {
10977             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
10978             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
10979             int passreg = (pass == 0) ? rn : rm;
10980
10981             read_vec_element(s, tcg_op1, passreg, 0, MO_64);
10982             read_vec_element(s, tcg_op2, passreg, 1, MO_64);
10983             tcg_res[pass] = tcg_temp_new_i64();
10984
10985             switch (opcode) {
10986             case 0x17: /* ADDP */
10987                 tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
10988                 break;
10989             case 0x58: /* FMAXNMP */
10990                 gen_helper_vfp_maxnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10991                 break;
10992             case 0x5a: /* FADDP */
10993                 gen_helper_vfp_addd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10994                 break;
10995             case 0x5e: /* FMAXP */
10996                 gen_helper_vfp_maxd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
10997                 break;
10998             case 0x78: /* FMINNMP */
10999                 gen_helper_vfp_minnumd(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11000                 break;
11001             case 0x7e: /* FMINP */
11002                 gen_helper_vfp_mind(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11003                 break;
11004             default:
11005                 g_assert_not_reached();
11006             }
11007
11008             tcg_temp_free_i64(tcg_op1);
11009             tcg_temp_free_i64(tcg_op2);
11010         }
11011
11012         for (pass = 0; pass < 2; pass++) {
11013             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
11014             tcg_temp_free_i64(tcg_res[pass]);
11015         }
11016     } else {
11017         int maxpass = is_q ? 4 : 2;
11018         TCGv_i32 tcg_res[4];
11019
11020         for (pass = 0; pass < maxpass; pass++) {
11021             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11022             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11023             NeonGenTwoOpFn *genfn = NULL;
11024             int passreg = pass < (maxpass / 2) ? rn : rm;
11025             int passelt = (is_q && (pass & 1)) ? 2 : 0;
11026
11027             read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_32);
11028             read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_32);
11029             tcg_res[pass] = tcg_temp_new_i32();
11030
11031             switch (opcode) {
11032             case 0x17: /* ADDP */
11033             {
11034                 static NeonGenTwoOpFn * const fns[3] = {
11035                     gen_helper_neon_padd_u8,
11036                     gen_helper_neon_padd_u16,
11037                     tcg_gen_add_i32,
11038                 };
11039                 genfn = fns[size];
11040                 break;
11041             }
11042             case 0x14: /* SMAXP, UMAXP */
11043             {
11044                 static NeonGenTwoOpFn * const fns[3][2] = {
11045                     { gen_helper_neon_pmax_s8, gen_helper_neon_pmax_u8 },
11046                     { gen_helper_neon_pmax_s16, gen_helper_neon_pmax_u16 },
11047                     { tcg_gen_smax_i32, tcg_gen_umax_i32 },
11048                 };
11049                 genfn = fns[size][u];
11050                 break;
11051             }
11052             case 0x15: /* SMINP, UMINP */
11053             {
11054                 static NeonGenTwoOpFn * const fns[3][2] = {
11055                     { gen_helper_neon_pmin_s8, gen_helper_neon_pmin_u8 },
11056                     { gen_helper_neon_pmin_s16, gen_helper_neon_pmin_u16 },
11057                     { tcg_gen_smin_i32, tcg_gen_umin_i32 },
11058                 };
11059                 genfn = fns[size][u];
11060                 break;
11061             }
11062             /* The FP operations are all on single floats (32 bit) */
11063             case 0x58: /* FMAXNMP */
11064                 gen_helper_vfp_maxnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11065                 break;
11066             case 0x5a: /* FADDP */
11067                 gen_helper_vfp_adds(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11068                 break;
11069             case 0x5e: /* FMAXP */
11070                 gen_helper_vfp_maxs(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11071                 break;
11072             case 0x78: /* FMINNMP */
11073                 gen_helper_vfp_minnums(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11074                 break;
11075             case 0x7e: /* FMINP */
11076                 gen_helper_vfp_mins(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11077                 break;
11078             default:
11079                 g_assert_not_reached();
11080             }
11081
11082             /* FP ops called directly, otherwise call now */
11083             if (genfn) {
11084                 genfn(tcg_res[pass], tcg_op1, tcg_op2);
11085             }
11086
11087             tcg_temp_free_i32(tcg_op1);
11088             tcg_temp_free_i32(tcg_op2);
11089         }
11090
11091         for (pass = 0; pass < maxpass; pass++) {
11092             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
11093             tcg_temp_free_i32(tcg_res[pass]);
11094         }
11095         clear_vec_high(s, is_q, rd);
11096     }
11097
11098     if (fpst) {
11099         tcg_temp_free_ptr(fpst);
11100     }
11101 }
11102
11103 /* Floating point op subgroup of C3.6.16. */
11104 static void disas_simd_3same_float(DisasContext *s, uint32_t insn)
11105 {
11106     /* For floating point ops, the U, size[1] and opcode bits
11107      * together indicate the operation. size[0] indicates single
11108      * or double.
11109      */
11110     int fpopcode = extract32(insn, 11, 5)
11111         | (extract32(insn, 23, 1) << 5)
11112         | (extract32(insn, 29, 1) << 6);
11113     int is_q = extract32(insn, 30, 1);
11114     int size = extract32(insn, 22, 1);
11115     int rm = extract32(insn, 16, 5);
11116     int rn = extract32(insn, 5, 5);
11117     int rd = extract32(insn, 0, 5);
11118
11119     int datasize = is_q ? 128 : 64;
11120     int esize = 32 << size;
11121     int elements = datasize / esize;
11122
11123     if (size == 1 && !is_q) {
11124         unallocated_encoding(s);
11125         return;
11126     }
11127
11128     switch (fpopcode) {
11129     case 0x58: /* FMAXNMP */
11130     case 0x5a: /* FADDP */
11131     case 0x5e: /* FMAXP */
11132     case 0x78: /* FMINNMP */
11133     case 0x7e: /* FMINP */
11134         if (size && !is_q) {
11135             unallocated_encoding(s);
11136             return;
11137         }
11138         handle_simd_3same_pair(s, is_q, 0, fpopcode, size ? MO_64 : MO_32,
11139                                rn, rm, rd);
11140         return;
11141     case 0x1b: /* FMULX */
11142     case 0x1f: /* FRECPS */
11143     case 0x3f: /* FRSQRTS */
11144     case 0x5d: /* FACGE */
11145     case 0x7d: /* FACGT */
11146     case 0x19: /* FMLA */
11147     case 0x39: /* FMLS */
11148     case 0x18: /* FMAXNM */
11149     case 0x1a: /* FADD */
11150     case 0x1c: /* FCMEQ */
11151     case 0x1e: /* FMAX */
11152     case 0x38: /* FMINNM */
11153     case 0x3a: /* FSUB */
11154     case 0x3e: /* FMIN */
11155     case 0x5b: /* FMUL */
11156     case 0x5c: /* FCMGE */
11157     case 0x5f: /* FDIV */
11158     case 0x7a: /* FABD */
11159     case 0x7c: /* FCMGT */
11160         if (!fp_access_check(s)) {
11161             return;
11162         }
11163         handle_3same_float(s, size, elements, fpopcode, rd, rn, rm);
11164         return;
11165
11166     case 0x1d: /* FMLAL  */
11167     case 0x3d: /* FMLSL  */
11168     case 0x59: /* FMLAL2 */
11169     case 0x79: /* FMLSL2 */
11170         if (size & 1 || !dc_isar_feature(aa64_fhm, s)) {
11171             unallocated_encoding(s);
11172             return;
11173         }
11174         if (fp_access_check(s)) {
11175             int is_s = extract32(insn, 23, 1);
11176             int is_2 = extract32(insn, 29, 1);
11177             int data = (is_2 << 1) | is_s;
11178             tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
11179                                vec_full_reg_offset(s, rn),
11180                                vec_full_reg_offset(s, rm), cpu_env,
11181                                is_q ? 16 : 8, vec_full_reg_size(s),
11182                                data, gen_helper_gvec_fmlal_a64);
11183         }
11184         return;
11185
11186     default:
11187         unallocated_encoding(s);
11188         return;
11189     }
11190 }
11191
11192 /* Integer op subgroup of C3.6.16. */
11193 static void disas_simd_3same_int(DisasContext *s, uint32_t insn)
11194 {
11195     int is_q = extract32(insn, 30, 1);
11196     int u = extract32(insn, 29, 1);
11197     int size = extract32(insn, 22, 2);
11198     int opcode = extract32(insn, 11, 5);
11199     int rm = extract32(insn, 16, 5);
11200     int rn = extract32(insn, 5, 5);
11201     int rd = extract32(insn, 0, 5);
11202     int pass;
11203     TCGCond cond;
11204
11205     switch (opcode) {
11206     case 0x13: /* MUL, PMUL */
11207         if (u && size != 0) {
11208             unallocated_encoding(s);
11209             return;
11210         }
11211         /* fall through */
11212     case 0x0: /* SHADD, UHADD */
11213     case 0x2: /* SRHADD, URHADD */
11214     case 0x4: /* SHSUB, UHSUB */
11215     case 0xc: /* SMAX, UMAX */
11216     case 0xd: /* SMIN, UMIN */
11217     case 0xe: /* SABD, UABD */
11218     case 0xf: /* SABA, UABA */
11219     case 0x12: /* MLA, MLS */
11220         if (size == 3) {
11221             unallocated_encoding(s);
11222             return;
11223         }
11224         break;
11225     case 0x16: /* SQDMULH, SQRDMULH */
11226         if (size == 0 || size == 3) {
11227             unallocated_encoding(s);
11228             return;
11229         }
11230         break;
11231     default:
11232         if (size == 3 && !is_q) {
11233             unallocated_encoding(s);
11234             return;
11235         }
11236         break;
11237     }
11238
11239     if (!fp_access_check(s)) {
11240         return;
11241     }
11242
11243     switch (opcode) {
11244     case 0x01: /* SQADD, UQADD */
11245         tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
11246                        offsetof(CPUARMState, vfp.qc),
11247                        vec_full_reg_offset(s, rn),
11248                        vec_full_reg_offset(s, rm),
11249                        is_q ? 16 : 8, vec_full_reg_size(s),
11250                        (u ? uqadd_op : sqadd_op) + size);
11251         return;
11252     case 0x05: /* SQSUB, UQSUB */
11253         tcg_gen_gvec_4(vec_full_reg_offset(s, rd),
11254                        offsetof(CPUARMState, vfp.qc),
11255                        vec_full_reg_offset(s, rn),
11256                        vec_full_reg_offset(s, rm),
11257                        is_q ? 16 : 8, vec_full_reg_size(s),
11258                        (u ? uqsub_op : sqsub_op) + size);
11259         return;
11260     case 0x08: /* SSHL, USHL */
11261         gen_gvec_op3(s, is_q, rd, rn, rm,
11262                      u ? &ushl_op[size] : &sshl_op[size]);
11263         return;
11264     case 0x0c: /* SMAX, UMAX */
11265         if (u) {
11266             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umax, size);
11267         } else {
11268             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smax, size);
11269         }
11270         return;
11271     case 0x0d: /* SMIN, UMIN */
11272         if (u) {
11273             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_umin, size);
11274         } else {
11275             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_smin, size);
11276         }
11277         return;
11278     case 0x10: /* ADD, SUB */
11279         if (u) {
11280             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_sub, size);
11281         } else {
11282             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_add, size);
11283         }
11284         return;
11285     case 0x13: /* MUL, PMUL */
11286         if (!u) { /* MUL */
11287             gen_gvec_fn3(s, is_q, rd, rn, rm, tcg_gen_gvec_mul, size);
11288         } else {  /* PMUL */
11289             gen_gvec_op3_ool(s, is_q, rd, rn, rm, 0, gen_helper_gvec_pmul_b);
11290         }
11291         return;
11292     case 0x12: /* MLA, MLS */
11293         if (u) {
11294             gen_gvec_op3(s, is_q, rd, rn, rm, &mls_op[size]);
11295         } else {
11296             gen_gvec_op3(s, is_q, rd, rn, rm, &mla_op[size]);
11297         }
11298         return;
11299     case 0x11:
11300         if (!u) { /* CMTST */
11301             gen_gvec_op3(s, is_q, rd, rn, rm, &cmtst_op[size]);
11302             return;
11303         }
11304         /* else CMEQ */
11305         cond = TCG_COND_EQ;
11306         goto do_gvec_cmp;
11307     case 0x06: /* CMGT, CMHI */
11308         cond = u ? TCG_COND_GTU : TCG_COND_GT;
11309         goto do_gvec_cmp;
11310     case 0x07: /* CMGE, CMHS */
11311         cond = u ? TCG_COND_GEU : TCG_COND_GE;
11312     do_gvec_cmp:
11313         tcg_gen_gvec_cmp(cond, size, vec_full_reg_offset(s, rd),
11314                          vec_full_reg_offset(s, rn),
11315                          vec_full_reg_offset(s, rm),
11316                          is_q ? 16 : 8, vec_full_reg_size(s));
11317         return;
11318     }
11319
11320     if (size == 3) {
11321         assert(is_q);
11322         for (pass = 0; pass < 2; pass++) {
11323             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
11324             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
11325             TCGv_i64 tcg_res = tcg_temp_new_i64();
11326
11327             read_vec_element(s, tcg_op1, rn, pass, MO_64);
11328             read_vec_element(s, tcg_op2, rm, pass, MO_64);
11329
11330             handle_3same_64(s, opcode, u, tcg_res, tcg_op1, tcg_op2);
11331
11332             write_vec_element(s, tcg_res, rd, pass, MO_64);
11333
11334             tcg_temp_free_i64(tcg_res);
11335             tcg_temp_free_i64(tcg_op1);
11336             tcg_temp_free_i64(tcg_op2);
11337         }
11338     } else {
11339         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
11340             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11341             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11342             TCGv_i32 tcg_res = tcg_temp_new_i32();
11343             NeonGenTwoOpFn *genfn = NULL;
11344             NeonGenTwoOpEnvFn *genenvfn = NULL;
11345
11346             read_vec_element_i32(s, tcg_op1, rn, pass, MO_32);
11347             read_vec_element_i32(s, tcg_op2, rm, pass, MO_32);
11348
11349             switch (opcode) {
11350             case 0x0: /* SHADD, UHADD */
11351             {
11352                 static NeonGenTwoOpFn * const fns[3][2] = {
11353                     { gen_helper_neon_hadd_s8, gen_helper_neon_hadd_u8 },
11354                     { gen_helper_neon_hadd_s16, gen_helper_neon_hadd_u16 },
11355                     { gen_helper_neon_hadd_s32, gen_helper_neon_hadd_u32 },
11356                 };
11357                 genfn = fns[size][u];
11358                 break;
11359             }
11360             case 0x2: /* SRHADD, URHADD */
11361             {
11362                 static NeonGenTwoOpFn * const fns[3][2] = {
11363                     { gen_helper_neon_rhadd_s8, gen_helper_neon_rhadd_u8 },
11364                     { gen_helper_neon_rhadd_s16, gen_helper_neon_rhadd_u16 },
11365                     { gen_helper_neon_rhadd_s32, gen_helper_neon_rhadd_u32 },
11366                 };
11367                 genfn = fns[size][u];
11368                 break;
11369             }
11370             case 0x4: /* SHSUB, UHSUB */
11371             {
11372                 static NeonGenTwoOpFn * const fns[3][2] = {
11373                     { gen_helper_neon_hsub_s8, gen_helper_neon_hsub_u8 },
11374                     { gen_helper_neon_hsub_s16, gen_helper_neon_hsub_u16 },
11375                     { gen_helper_neon_hsub_s32, gen_helper_neon_hsub_u32 },
11376                 };
11377                 genfn = fns[size][u];
11378                 break;
11379             }
11380             case 0x9: /* SQSHL, UQSHL */
11381             {
11382                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
11383                     { gen_helper_neon_qshl_s8, gen_helper_neon_qshl_u8 },
11384                     { gen_helper_neon_qshl_s16, gen_helper_neon_qshl_u16 },
11385                     { gen_helper_neon_qshl_s32, gen_helper_neon_qshl_u32 },
11386                 };
11387                 genenvfn = fns[size][u];
11388                 break;
11389             }
11390             case 0xa: /* SRSHL, URSHL */
11391             {
11392                 static NeonGenTwoOpFn * const fns[3][2] = {
11393                     { gen_helper_neon_rshl_s8, gen_helper_neon_rshl_u8 },
11394                     { gen_helper_neon_rshl_s16, gen_helper_neon_rshl_u16 },
11395                     { gen_helper_neon_rshl_s32, gen_helper_neon_rshl_u32 },
11396                 };
11397                 genfn = fns[size][u];
11398                 break;
11399             }
11400             case 0xb: /* SQRSHL, UQRSHL */
11401             {
11402                 static NeonGenTwoOpEnvFn * const fns[3][2] = {
11403                     { gen_helper_neon_qrshl_s8, gen_helper_neon_qrshl_u8 },
11404                     { gen_helper_neon_qrshl_s16, gen_helper_neon_qrshl_u16 },
11405                     { gen_helper_neon_qrshl_s32, gen_helper_neon_qrshl_u32 },
11406                 };
11407                 genenvfn = fns[size][u];
11408                 break;
11409             }
11410             case 0xe: /* SABD, UABD */
11411             case 0xf: /* SABA, UABA */
11412             {
11413                 static NeonGenTwoOpFn * const fns[3][2] = {
11414                     { gen_helper_neon_abd_s8, gen_helper_neon_abd_u8 },
11415                     { gen_helper_neon_abd_s16, gen_helper_neon_abd_u16 },
11416                     { gen_helper_neon_abd_s32, gen_helper_neon_abd_u32 },
11417                 };
11418                 genfn = fns[size][u];
11419                 break;
11420             }
11421             case 0x16: /* SQDMULH, SQRDMULH */
11422             {
11423                 static NeonGenTwoOpEnvFn * const fns[2][2] = {
11424                     { gen_helper_neon_qdmulh_s16, gen_helper_neon_qrdmulh_s16 },
11425                     { gen_helper_neon_qdmulh_s32, gen_helper_neon_qrdmulh_s32 },
11426                 };
11427                 assert(size == 1 || size == 2);
11428                 genenvfn = fns[size - 1][u];
11429                 break;
11430             }
11431             default:
11432                 g_assert_not_reached();
11433             }
11434
11435             if (genenvfn) {
11436                 genenvfn(tcg_res, cpu_env, tcg_op1, tcg_op2);
11437             } else {
11438                 genfn(tcg_res, tcg_op1, tcg_op2);
11439             }
11440
11441             if (opcode == 0xf) {
11442                 /* SABA, UABA: accumulating ops */
11443                 static NeonGenTwoOpFn * const fns[3] = {
11444                     gen_helper_neon_add_u8,
11445                     gen_helper_neon_add_u16,
11446                     tcg_gen_add_i32,
11447                 };
11448
11449                 read_vec_element_i32(s, tcg_op1, rd, pass, MO_32);
11450                 fns[size](tcg_res, tcg_op1, tcg_res);
11451             }
11452
11453             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
11454
11455             tcg_temp_free_i32(tcg_res);
11456             tcg_temp_free_i32(tcg_op1);
11457             tcg_temp_free_i32(tcg_op2);
11458         }
11459     }
11460     clear_vec_high(s, is_q, rd);
11461 }
11462
11463 /* AdvSIMD three same
11464  *  31  30  29  28       24 23  22  21 20  16 15    11  10 9    5 4    0
11465  * +---+---+---+-----------+------+---+------+--------+---+------+------+
11466  * | 0 | Q | U | 0 1 1 1 0 | size | 1 |  Rm  | opcode | 1 |  Rn  |  Rd  |
11467  * +---+---+---+-----------+------+---+------+--------+---+------+------+
11468  */
11469 static void disas_simd_three_reg_same(DisasContext *s, uint32_t insn)
11470 {
11471     int opcode = extract32(insn, 11, 5);
11472
11473     switch (opcode) {
11474     case 0x3: /* logic ops */
11475         disas_simd_3same_logic(s, insn);
11476         break;
11477     case 0x17: /* ADDP */
11478     case 0x14: /* SMAXP, UMAXP */
11479     case 0x15: /* SMINP, UMINP */
11480     {
11481         /* Pairwise operations */
11482         int is_q = extract32(insn, 30, 1);
11483         int u = extract32(insn, 29, 1);
11484         int size = extract32(insn, 22, 2);
11485         int rm = extract32(insn, 16, 5);
11486         int rn = extract32(insn, 5, 5);
11487         int rd = extract32(insn, 0, 5);
11488         if (opcode == 0x17) {
11489             if (u || (size == 3 && !is_q)) {
11490                 unallocated_encoding(s);
11491                 return;
11492             }
11493         } else {
11494             if (size == 3) {
11495                 unallocated_encoding(s);
11496                 return;
11497             }
11498         }
11499         handle_simd_3same_pair(s, is_q, u, opcode, size, rn, rm, rd);
11500         break;
11501     }
11502     case 0x18 ... 0x31:
11503         /* floating point ops, sz[1] and U are part of opcode */
11504         disas_simd_3same_float(s, insn);
11505         break;
11506     default:
11507         disas_simd_3same_int(s, insn);
11508         break;
11509     }
11510 }
11511
11512 /*
11513  * Advanced SIMD three same (ARMv8.2 FP16 variants)
11514  *
11515  *  31  30  29  28       24 23  22 21 20  16 15 14 13    11 10  9    5 4    0
11516  * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
11517  * | 0 | Q | U | 0 1 1 1 0 | a | 1 0 |  Rm  | 0 0 | opcode | 1 |  Rn  |  Rd  |
11518  * +---+---+---+-----------+---------+------+-----+--------+---+------+------+
11519  *
11520  * This includes FMULX, FCMEQ (register), FRECPS, FRSQRTS, FCMGE
11521  * (register), FACGE, FABD, FCMGT (register) and FACGT.
11522  *
11523  */
11524 static void disas_simd_three_reg_same_fp16(DisasContext *s, uint32_t insn)
11525 {
11526     int opcode, fpopcode;
11527     int is_q, u, a, rm, rn, rd;
11528     int datasize, elements;
11529     int pass;
11530     TCGv_ptr fpst;
11531     bool pairwise = false;
11532
11533     if (!dc_isar_feature(aa64_fp16, s)) {
11534         unallocated_encoding(s);
11535         return;
11536     }
11537
11538     if (!fp_access_check(s)) {
11539         return;
11540     }
11541
11542     /* For these floating point ops, the U, a and opcode bits
11543      * together indicate the operation.
11544      */
11545     opcode = extract32(insn, 11, 3);
11546     u = extract32(insn, 29, 1);
11547     a = extract32(insn, 23, 1);
11548     is_q = extract32(insn, 30, 1);
11549     rm = extract32(insn, 16, 5);
11550     rn = extract32(insn, 5, 5);
11551     rd = extract32(insn, 0, 5);
11552
11553     fpopcode = opcode | (a << 3) |  (u << 4);
11554     datasize = is_q ? 128 : 64;
11555     elements = datasize / 16;
11556
11557     switch (fpopcode) {
11558     case 0x10: /* FMAXNMP */
11559     case 0x12: /* FADDP */
11560     case 0x16: /* FMAXP */
11561     case 0x18: /* FMINNMP */
11562     case 0x1e: /* FMINP */
11563         pairwise = true;
11564         break;
11565     }
11566
11567     fpst = get_fpstatus_ptr(true);
11568
11569     if (pairwise) {
11570         int maxpass = is_q ? 8 : 4;
11571         TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11572         TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11573         TCGv_i32 tcg_res[8];
11574
11575         for (pass = 0; pass < maxpass; pass++) {
11576             int passreg = pass < (maxpass / 2) ? rn : rm;
11577             int passelt = (pass << 1) & (maxpass - 1);
11578
11579             read_vec_element_i32(s, tcg_op1, passreg, passelt, MO_16);
11580             read_vec_element_i32(s, tcg_op2, passreg, passelt + 1, MO_16);
11581             tcg_res[pass] = tcg_temp_new_i32();
11582
11583             switch (fpopcode) {
11584             case 0x10: /* FMAXNMP */
11585                 gen_helper_advsimd_maxnumh(tcg_res[pass], tcg_op1, tcg_op2,
11586                                            fpst);
11587                 break;
11588             case 0x12: /* FADDP */
11589                 gen_helper_advsimd_addh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11590                 break;
11591             case 0x16: /* FMAXP */
11592                 gen_helper_advsimd_maxh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11593                 break;
11594             case 0x18: /* FMINNMP */
11595                 gen_helper_advsimd_minnumh(tcg_res[pass], tcg_op1, tcg_op2,
11596                                            fpst);
11597                 break;
11598             case 0x1e: /* FMINP */
11599                 gen_helper_advsimd_minh(tcg_res[pass], tcg_op1, tcg_op2, fpst);
11600                 break;
11601             default:
11602                 g_assert_not_reached();
11603             }
11604         }
11605
11606         for (pass = 0; pass < maxpass; pass++) {
11607             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_16);
11608             tcg_temp_free_i32(tcg_res[pass]);
11609         }
11610
11611         tcg_temp_free_i32(tcg_op1);
11612         tcg_temp_free_i32(tcg_op2);
11613
11614     } else {
11615         for (pass = 0; pass < elements; pass++) {
11616             TCGv_i32 tcg_op1 = tcg_temp_new_i32();
11617             TCGv_i32 tcg_op2 = tcg_temp_new_i32();
11618             TCGv_i32 tcg_res = tcg_temp_new_i32();
11619
11620             read_vec_element_i32(s, tcg_op1, rn, pass, MO_16);
11621             read_vec_element_i32(s, tcg_op2, rm, pass, MO_16);
11622
11623             switch (fpopcode) {
11624             case 0x0: /* FMAXNM */
11625                 gen_helper_advsimd_maxnumh(tcg_res, tcg_op1, tcg_op2, fpst);
11626                 break;
11627             case 0x1: /* FMLA */
11628                 read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11629                 gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
11630                                            fpst);
11631                 break;
11632             case 0x2: /* FADD */
11633                 gen_helper_advsimd_addh(tcg_res, tcg_op1, tcg_op2, fpst);
11634                 break;
11635             case 0x3: /* FMULX */
11636                 gen_helper_advsimd_mulxh(tcg_res, tcg_op1, tcg_op2, fpst);
11637                 break;
11638             case 0x4: /* FCMEQ */
11639                 gen_helper_advsimd_ceq_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11640                 break;
11641             case 0x6: /* FMAX */
11642                 gen_helper_advsimd_maxh(tcg_res, tcg_op1, tcg_op2, fpst);
11643                 break;
11644             case 0x7: /* FRECPS */
11645                 gen_helper_recpsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11646                 break;
11647             case 0x8: /* FMINNM */
11648                 gen_helper_advsimd_minnumh(tcg_res, tcg_op1, tcg_op2, fpst);
11649                 break;
11650             case 0x9: /* FMLS */
11651                 /* As usual for ARM, separate negation for fused multiply-add */
11652                 tcg_gen_xori_i32(tcg_op1, tcg_op1, 0x8000);
11653                 read_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11654                 gen_helper_advsimd_muladdh(tcg_res, tcg_op1, tcg_op2, tcg_res,
11655                                            fpst);
11656                 break;
11657             case 0xa: /* FSUB */
11658                 gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
11659                 break;
11660             case 0xe: /* FMIN */
11661                 gen_helper_advsimd_minh(tcg_res, tcg_op1, tcg_op2, fpst);
11662                 break;
11663             case 0xf: /* FRSQRTS */
11664                 gen_helper_rsqrtsf_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11665                 break;
11666             case 0x13: /* FMUL */
11667                 gen_helper_advsimd_mulh(tcg_res, tcg_op1, tcg_op2, fpst);
11668                 break;
11669             case 0x14: /* FCMGE */
11670                 gen_helper_advsimd_cge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11671                 break;
11672             case 0x15: /* FACGE */
11673                 gen_helper_advsimd_acge_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11674                 break;
11675             case 0x17: /* FDIV */
11676                 gen_helper_advsimd_divh(tcg_res, tcg_op1, tcg_op2, fpst);
11677                 break;
11678             case 0x1a: /* FABD */
11679                 gen_helper_advsimd_subh(tcg_res, tcg_op1, tcg_op2, fpst);
11680                 tcg_gen_andi_i32(tcg_res, tcg_res, 0x7fff);
11681                 break;
11682             case 0x1c: /* FCMGT */
11683                 gen_helper_advsimd_cgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11684                 break;
11685             case 0x1d: /* FACGT */
11686                 gen_helper_advsimd_acgt_f16(tcg_res, tcg_op1, tcg_op2, fpst);
11687                 break;
11688             default:
11689                 fprintf(stderr, "%s: insn %#04x, fpop %#2x @ %#" PRIx64 "\n",
11690                         __func__, insn, fpopcode, s->pc_curr);
11691                 g_assert_not_reached();
11692             }
11693
11694             write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
11695             tcg_temp_free_i32(tcg_res);
11696             tcg_temp_free_i32(tcg_op1);
11697             tcg_temp_free_i32(tcg_op2);
11698         }
11699     }
11700
11701     tcg_temp_free_ptr(fpst);
11702
11703     clear_vec_high(s, is_q, rd);
11704 }
11705
11706 /* AdvSIMD three same extra
11707  *  31   30  29 28       24 23  22  21 20  16  15 14    11  10 9  5 4  0
11708  * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
11709  * | 0 | Q | U | 0 1 1 1 0 | size | 0 |  Rm  | 1 | opcode | 1 | Rn | Rd |
11710  * +---+---+---+-----------+------+---+------+---+--------+---+----+----+
11711  */
11712 static void disas_simd_three_reg_same_extra(DisasContext *s, uint32_t insn)
11713 {
11714     int rd = extract32(insn, 0, 5);
11715     int rn = extract32(insn, 5, 5);
11716     int opcode = extract32(insn, 11, 4);
11717     int rm = extract32(insn, 16, 5);
11718     int size = extract32(insn, 22, 2);
11719     bool u = extract32(insn, 29, 1);
11720     bool is_q = extract32(insn, 30, 1);
11721     bool feature;
11722     int rot;
11723
11724     switch (u * 16 + opcode) {
11725     case 0x10: /* SQRDMLAH (vector) */
11726     case 0x11: /* SQRDMLSH (vector) */
11727         if (size != 1 && size != 2) {
11728             unallocated_encoding(s);
11729             return;
11730         }
11731         feature = dc_isar_feature(aa64_rdm, s);
11732         break;
11733     case 0x02: /* SDOT (vector) */
11734     case 0x12: /* UDOT (vector) */
11735         if (size != MO_32) {
11736             unallocated_encoding(s);
11737             return;
11738         }
11739         feature = dc_isar_feature(aa64_dp, s);
11740         break;
11741     case 0x18: /* FCMLA, #0 */
11742     case 0x19: /* FCMLA, #90 */
11743     case 0x1a: /* FCMLA, #180 */
11744     case 0x1b: /* FCMLA, #270 */
11745     case 0x1c: /* FCADD, #90 */
11746     case 0x1e: /* FCADD, #270 */
11747         if (size == 0
11748             || (size == 1 && !dc_isar_feature(aa64_fp16, s))
11749             || (size == 3 && !is_q)) {
11750             unallocated_encoding(s);
11751             return;
11752         }
11753         feature = dc_isar_feature(aa64_fcma, s);
11754         break;
11755     default:
11756         unallocated_encoding(s);
11757         return;
11758     }
11759     if (!feature) {
11760         unallocated_encoding(s);
11761         return;
11762     }
11763     if (!fp_access_check(s)) {
11764         return;
11765     }
11766
11767     switch (opcode) {
11768     case 0x0: /* SQRDMLAH (vector) */
11769         switch (size) {
11770         case 1:
11771             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s16);
11772             break;
11773         case 2:
11774             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlah_s32);
11775             break;
11776         default:
11777             g_assert_not_reached();
11778         }
11779         return;
11780
11781     case 0x1: /* SQRDMLSH (vector) */
11782         switch (size) {
11783         case 1:
11784             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s16);
11785             break;
11786         case 2:
11787             gen_gvec_op3_env(s, is_q, rd, rn, rm, gen_helper_gvec_qrdmlsh_s32);
11788             break;
11789         default:
11790             g_assert_not_reached();
11791         }
11792         return;
11793
11794     case 0x2: /* SDOT / UDOT */
11795         gen_gvec_op3_ool(s, is_q, rd, rn, rm, 0,
11796                          u ? gen_helper_gvec_udot_b : gen_helper_gvec_sdot_b);
11797         return;
11798
11799     case 0x8: /* FCMLA, #0 */
11800     case 0x9: /* FCMLA, #90 */
11801     case 0xa: /* FCMLA, #180 */
11802     case 0xb: /* FCMLA, #270 */
11803         rot = extract32(opcode, 0, 2);
11804         switch (size) {
11805         case 1:
11806             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, true, rot,
11807                               gen_helper_gvec_fcmlah);
11808             break;
11809         case 2:
11810             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
11811                               gen_helper_gvec_fcmlas);
11812             break;
11813         case 3:
11814             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, false, rot,
11815                               gen_helper_gvec_fcmlad);
11816             break;
11817         default:
11818             g_assert_not_reached();
11819         }
11820         return;
11821
11822     case 0xc: /* FCADD, #90 */
11823     case 0xe: /* FCADD, #270 */
11824         rot = extract32(opcode, 1, 1);
11825         switch (size) {
11826         case 1:
11827             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11828                               gen_helper_gvec_fcaddh);
11829             break;
11830         case 2:
11831             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11832                               gen_helper_gvec_fcadds);
11833             break;
11834         case 3:
11835             gen_gvec_op3_fpst(s, is_q, rd, rn, rm, size == 1, rot,
11836                               gen_helper_gvec_fcaddd);
11837             break;
11838         default:
11839             g_assert_not_reached();
11840         }
11841         return;
11842
11843     default:
11844         g_assert_not_reached();
11845     }
11846 }
11847
11848 static void handle_2misc_widening(DisasContext *s, int opcode, bool is_q,
11849                                   int size, int rn, int rd)
11850 {
11851     /* Handle 2-reg-misc ops which are widening (so each size element
11852      * in the source becomes a 2*size element in the destination.
11853      * The only instruction like this is FCVTL.
11854      */
11855     int pass;
11856
11857     if (size == 3) {
11858         /* 32 -> 64 bit fp conversion */
11859         TCGv_i64 tcg_res[2];
11860         int srcelt = is_q ? 2 : 0;
11861
11862         for (pass = 0; pass < 2; pass++) {
11863             TCGv_i32 tcg_op = tcg_temp_new_i32();
11864             tcg_res[pass] = tcg_temp_new_i64();
11865
11866             read_vec_element_i32(s, tcg_op, rn, srcelt + pass, MO_32);
11867             gen_helper_vfp_fcvtds(tcg_res[pass], tcg_op, cpu_env);
11868             tcg_temp_free_i32(tcg_op);
11869         }
11870         for (pass = 0; pass < 2; pass++) {
11871             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
11872             tcg_temp_free_i64(tcg_res[pass]);
11873         }
11874     } else {
11875         /* 16 -> 32 bit fp conversion */
11876         int srcelt = is_q ? 4 : 0;
11877         TCGv_i32 tcg_res[4];
11878         TCGv_ptr fpst = get_fpstatus_ptr(false);
11879         TCGv_i32 ahp = get_ahp_flag();
11880
11881         for (pass = 0; pass < 4; pass++) {
11882             tcg_res[pass] = tcg_temp_new_i32();
11883
11884             read_vec_element_i32(s, tcg_res[pass], rn, srcelt + pass, MO_16);
11885             gen_helper_vfp_fcvt_f16_to_f32(tcg_res[pass], tcg_res[pass],
11886                                            fpst, ahp);
11887         }
11888         for (pass = 0; pass < 4; pass++) {
11889             write_vec_element_i32(s, tcg_res[pass], rd, pass, MO_32);
11890             tcg_temp_free_i32(tcg_res[pass]);
11891         }
11892
11893         tcg_temp_free_ptr(fpst);
11894         tcg_temp_free_i32(ahp);
11895     }
11896 }
11897
11898 static void handle_rev(DisasContext *s, int opcode, bool u,
11899                        bool is_q, int size, int rn, int rd)
11900 {
11901     int op = (opcode << 1) | u;
11902     int opsz = op + size;
11903     int grp_size = 3 - opsz;
11904     int dsize = is_q ? 128 : 64;
11905     int i;
11906
11907     if (opsz >= 3) {
11908         unallocated_encoding(s);
11909         return;
11910     }
11911
11912     if (!fp_access_check(s)) {
11913         return;
11914     }
11915
11916     if (size == 0) {
11917         /* Special case bytes, use bswap op on each group of elements */
11918         int groups = dsize / (8 << grp_size);
11919
11920         for (i = 0; i < groups; i++) {
11921             TCGv_i64 tcg_tmp = tcg_temp_new_i64();
11922
11923             read_vec_element(s, tcg_tmp, rn, i, grp_size);
11924             switch (grp_size) {
11925             case MO_16:
11926                 tcg_gen_bswap16_i64(tcg_tmp, tcg_tmp);
11927                 break;
11928             case MO_32:
11929                 tcg_gen_bswap32_i64(tcg_tmp, tcg_tmp);
11930                 break;
11931             case MO_64:
11932                 tcg_gen_bswap64_i64(tcg_tmp, tcg_tmp);
11933                 break;
11934             default:
11935                 g_assert_not_reached();
11936             }
11937             write_vec_element(s, tcg_tmp, rd, i, grp_size);
11938             tcg_temp_free_i64(tcg_tmp);
11939         }
11940         clear_vec_high(s, is_q, rd);
11941     } else {
11942         int revmask = (1 << grp_size) - 1;
11943         int esize = 8 << size;
11944         int elements = dsize / esize;
11945         TCGv_i64 tcg_rn = tcg_temp_new_i64();
11946         TCGv_i64 tcg_rd = tcg_const_i64(0);
11947         TCGv_i64 tcg_rd_hi = tcg_const_i64(0);
11948
11949         for (i = 0; i < elements; i++) {
11950             int e_rev = (i & 0xf) ^ revmask;
11951             int off = e_rev * esize;
11952             read_vec_element(s, tcg_rn, rn, i, size);
11953             if (off >= 64) {
11954                 tcg_gen_deposit_i64(tcg_rd_hi, tcg_rd_hi,
11955                                     tcg_rn, off - 64, esize);
11956             } else {
11957                 tcg_gen_deposit_i64(tcg_rd, tcg_rd, tcg_rn, off, esize);
11958             }
11959         }
11960         write_vec_element(s, tcg_rd, rd, 0, MO_64);
11961         write_vec_element(s, tcg_rd_hi, rd, 1, MO_64);
11962
11963         tcg_temp_free_i64(tcg_rd_hi);
11964         tcg_temp_free_i64(tcg_rd);
11965         tcg_temp_free_i64(tcg_rn);
11966     }
11967 }
11968
11969 static void handle_2misc_pairwise(DisasContext *s, int opcode, bool u,
11970                                   bool is_q, int size, int rn, int rd)
11971 {
11972     /* Implement the pairwise operations from 2-misc:
11973      * SADDLP, UADDLP, SADALP, UADALP.
11974      * These all add pairs of elements in the input to produce a
11975      * double-width result element in the output (possibly accumulating).
11976      */
11977     bool accum = (opcode == 0x6);
11978     int maxpass = is_q ? 2 : 1;
11979     int pass;
11980     TCGv_i64 tcg_res[2];
11981
11982     if (size == 2) {
11983         /* 32 + 32 -> 64 op */
11984         MemOp memop = size + (u ? 0 : MO_SIGN);
11985
11986         for (pass = 0; pass < maxpass; pass++) {
11987             TCGv_i64 tcg_op1 = tcg_temp_new_i64();
11988             TCGv_i64 tcg_op2 = tcg_temp_new_i64();
11989
11990             tcg_res[pass] = tcg_temp_new_i64();
11991
11992             read_vec_element(s, tcg_op1, rn, pass * 2, memop);
11993             read_vec_element(s, tcg_op2, rn, pass * 2 + 1, memop);
11994             tcg_gen_add_i64(tcg_res[pass], tcg_op1, tcg_op2);
11995             if (accum) {
11996                 read_vec_element(s, tcg_op1, rd, pass, MO_64);
11997                 tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
11998             }
11999
12000             tcg_temp_free_i64(tcg_op1);
12001             tcg_temp_free_i64(tcg_op2);
12002         }
12003     } else {
12004         for (pass = 0; pass < maxpass; pass++) {
12005             TCGv_i64 tcg_op = tcg_temp_new_i64();
12006             NeonGenOneOpFn *genfn;
12007             static NeonGenOneOpFn * const fns[2][2] = {
12008                 { gen_helper_neon_addlp_s8,  gen_helper_neon_addlp_u8 },
12009                 { gen_helper_neon_addlp_s16,  gen_helper_neon_addlp_u16 },
12010             };
12011
12012             genfn = fns[size][u];
12013
12014             tcg_res[pass] = tcg_temp_new_i64();
12015
12016             read_vec_element(s, tcg_op, rn, pass, MO_64);
12017             genfn(tcg_res[pass], tcg_op);
12018
12019             if (accum) {
12020                 read_vec_element(s, tcg_op, rd, pass, MO_64);
12021                 if (size == 0) {
12022                     gen_helper_neon_addl_u16(tcg_res[pass],
12023                                              tcg_res[pass], tcg_op);
12024                 } else {
12025                     gen_helper_neon_addl_u32(tcg_res[pass],
12026                                              tcg_res[pass], tcg_op);
12027                 }
12028             }
12029             tcg_temp_free_i64(tcg_op);
12030         }
12031     }
12032     if (!is_q) {
12033         tcg_res[1] = tcg_const_i64(0);
12034     }
12035     for (pass = 0; pass < 2; pass++) {
12036         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
12037         tcg_temp_free_i64(tcg_res[pass]);
12038     }
12039 }
12040
12041 static void handle_shll(DisasContext *s, bool is_q, int size, int rn, int rd)
12042 {
12043     /* Implement SHLL and SHLL2 */
12044     int pass;
12045     int part = is_q ? 2 : 0;
12046     TCGv_i64 tcg_res[2];
12047
12048     for (pass = 0; pass < 2; pass++) {
12049         static NeonGenWidenFn * const widenfns[3] = {
12050             gen_helper_neon_widen_u8,
12051             gen_helper_neon_widen_u16,
12052             tcg_gen_extu_i32_i64,
12053         };
12054         NeonGenWidenFn *widenfn = widenfns[size];
12055         TCGv_i32 tcg_op = tcg_temp_new_i32();
12056
12057         read_vec_element_i32(s, tcg_op, rn, part + pass, MO_32);
12058         tcg_res[pass] = tcg_temp_new_i64();
12059         widenfn(tcg_res[pass], tcg_op);
12060         tcg_gen_shli_i64(tcg_res[pass], tcg_res[pass], 8 << size);
12061
12062         tcg_temp_free_i32(tcg_op);
12063     }
12064
12065     for (pass = 0; pass < 2; pass++) {
12066         write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
12067         tcg_temp_free_i64(tcg_res[pass]);
12068     }
12069 }
12070
12071 /* AdvSIMD two reg misc
12072  *   31  30  29 28       24 23  22 21       17 16    12 11 10 9    5 4    0
12073  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
12074  * | 0 | Q | U | 0 1 1 1 0 | size | 1 0 0 0 0 | opcode | 1 0 |  Rn  |  Rd  |
12075  * +---+---+---+-----------+------+-----------+--------+-----+------+------+
12076  */
12077 static void disas_simd_two_reg_misc(DisasContext *s, uint32_t insn)
12078 {
12079     int size = extract32(insn, 22, 2);
12080     int opcode = extract32(insn, 12, 5);
12081     bool u = extract32(insn, 29, 1);
12082     bool is_q = extract32(insn, 30, 1);
12083     int rn = extract32(insn, 5, 5);
12084     int rd = extract32(insn, 0, 5);
12085     bool need_fpstatus = false;
12086     bool need_rmode = false;
12087     int rmode = -1;
12088     TCGv_i32 tcg_rmode;
12089     TCGv_ptr tcg_fpstatus;
12090
12091     switch (opcode) {
12092     case 0x0: /* REV64, REV32 */
12093     case 0x1: /* REV16 */
12094         handle_rev(s, opcode, u, is_q, size, rn, rd);
12095         return;
12096     case 0x5: /* CNT, NOT, RBIT */
12097         if (u && size == 0) {
12098             /* NOT */
12099             break;
12100         } else if (u && size == 1) {
12101             /* RBIT */
12102             break;
12103         } else if (!u && size == 0) {
12104             /* CNT */
12105             break;
12106         }
12107         unallocated_encoding(s);
12108         return;
12109     case 0x12: /* XTN, XTN2, SQXTUN, SQXTUN2 */
12110     case 0x14: /* SQXTN, SQXTN2, UQXTN, UQXTN2 */
12111         if (size == 3) {
12112             unallocated_encoding(s);
12113             return;
12114         }
12115         if (!fp_access_check(s)) {
12116             return;
12117         }
12118
12119         handle_2misc_narrow(s, false, opcode, u, is_q, size, rn, rd);
12120         return;
12121     case 0x4: /* CLS, CLZ */
12122         if (size == 3) {
12123             unallocated_encoding(s);
12124             return;
12125         }
12126         break;
12127     case 0x2: /* SADDLP, UADDLP */
12128     case 0x6: /* SADALP, UADALP */
12129         if (size == 3) {
12130             unallocated_encoding(s);
12131             return;
12132         }
12133         if (!fp_access_check(s)) {
12134             return;
12135         }
12136         handle_2misc_pairwise(s, opcode, u, is_q, size, rn, rd);
12137         return;
12138     case 0x13: /* SHLL, SHLL2 */
12139         if (u == 0 || size == 3) {
12140             unallocated_encoding(s);
12141             return;
12142         }
12143         if (!fp_access_check(s)) {
12144             return;
12145         }
12146         handle_shll(s, is_q, size, rn, rd);
12147         return;
12148     case 0xa: /* CMLT */
12149         if (u == 1) {
12150             unallocated_encoding(s);
12151             return;
12152         }
12153         /* fall through */
12154     case 0x8: /* CMGT, CMGE */
12155     case 0x9: /* CMEQ, CMLE */
12156     case 0xb: /* ABS, NEG */
12157         if (size == 3 && !is_q) {
12158             unallocated_encoding(s);
12159             return;
12160         }
12161         break;
12162     case 0x3: /* SUQADD, USQADD */
12163         if (size == 3 && !is_q) {
12164             unallocated_encoding(s);
12165             return;
12166         }
12167         if (!fp_access_check(s)) {
12168             return;
12169         }
12170         handle_2misc_satacc(s, false, u, is_q, size, rn, rd);
12171         return;
12172     case 0x7: /* SQABS, SQNEG */
12173         if (size == 3 && !is_q) {
12174             unallocated_encoding(s);
12175             return;
12176         }
12177         break;
12178     case 0xc ... 0xf:
12179     case 0x16 ... 0x1f:
12180     {
12181         /* Floating point: U, size[1] and opcode indicate operation;
12182          * size[0] indicates single or double precision.
12183          */
12184         int is_double = extract32(size, 0, 1);
12185         opcode |= (extract32(size, 1, 1) << 5) | (u << 6);
12186         size = is_double ? 3 : 2;
12187         switch (opcode) {
12188         case 0x2f: /* FABS */
12189         case 0x6f: /* FNEG */
12190             if (size == 3 && !is_q) {
12191                 unallocated_encoding(s);
12192                 return;
12193             }
12194             break;
12195         case 0x1d: /* SCVTF */
12196         case 0x5d: /* UCVTF */
12197         {
12198             bool is_signed = (opcode == 0x1d) ? true : false;
12199             int elements = is_double ? 2 : is_q ? 4 : 2;
12200             if (is_double && !is_q) {
12201                 unallocated_encoding(s);
12202                 return;
12203             }
12204             if (!fp_access_check(s)) {
12205                 return;
12206             }
12207             handle_simd_intfp_conv(s, rd, rn, elements, is_signed, 0, size);
12208             return;
12209         }
12210         case 0x2c: /* FCMGT (zero) */
12211         case 0x2d: /* FCMEQ (zero) */
12212         case 0x2e: /* FCMLT (zero) */
12213         case 0x6c: /* FCMGE (zero) */
12214         case 0x6d: /* FCMLE (zero) */
12215             if (size == 3 && !is_q) {
12216                 unallocated_encoding(s);
12217                 return;
12218             }
12219             handle_2misc_fcmp_zero(s, opcode, false, u, is_q, size, rn, rd);
12220             return;
12221         case 0x7f: /* FSQRT */
12222             if (size == 3 && !is_q) {
12223                 unallocated_encoding(s);
12224                 return;
12225             }
12226             break;
12227         case 0x1a: /* FCVTNS */
12228         case 0x1b: /* FCVTMS */
12229         case 0x3a: /* FCVTPS */
12230         case 0x3b: /* FCVTZS */
12231         case 0x5a: /* FCVTNU */
12232         case 0x5b: /* FCVTMU */
12233         case 0x7a: /* FCVTPU */
12234         case 0x7b: /* FCVTZU */
12235             need_fpstatus = true;
12236             need_rmode = true;
12237             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
12238             if (size == 3 && !is_q) {
12239                 unallocated_encoding(s);
12240                 return;
12241             }
12242             break;
12243         case 0x5c: /* FCVTAU */
12244         case 0x1c: /* FCVTAS */
12245             need_fpstatus = true;
12246             need_rmode = true;
12247             rmode = FPROUNDING_TIEAWAY;
12248             if (size == 3 && !is_q) {
12249                 unallocated_encoding(s);
12250                 return;
12251             }
12252             break;
12253         case 0x3c: /* URECPE */
12254             if (size == 3) {
12255                 unallocated_encoding(s);
12256                 return;
12257             }
12258             /* fall through */
12259         case 0x3d: /* FRECPE */
12260         case 0x7d: /* FRSQRTE */
12261             if (size == 3 && !is_q) {
12262                 unallocated_encoding(s);
12263                 return;
12264             }
12265             if (!fp_access_check(s)) {
12266                 return;
12267             }
12268             handle_2misc_reciprocal(s, opcode, false, u, is_q, size, rn, rd);
12269             return;
12270         case 0x56: /* FCVTXN, FCVTXN2 */
12271             if (size == 2) {
12272                 unallocated_encoding(s);
12273                 return;
12274             }
12275             /* fall through */
12276         case 0x16: /* FCVTN, FCVTN2 */
12277             /* handle_2misc_narrow does a 2*size -> size operation, but these
12278              * instructions encode the source size rather than dest size.
12279              */
12280             if (!fp_access_check(s)) {
12281                 return;
12282             }
12283             handle_2misc_narrow(s, false, opcode, 0, is_q, size - 1, rn, rd);
12284             return;
12285         case 0x17: /* FCVTL, FCVTL2 */
12286             if (!fp_access_check(s)) {
12287                 return;
12288             }
12289             handle_2misc_widening(s, opcode, is_q, size, rn, rd);
12290             return;
12291         case 0x18: /* FRINTN */
12292         case 0x19: /* FRINTM */
12293         case 0x38: /* FRINTP */
12294         case 0x39: /* FRINTZ */
12295             need_rmode = true;
12296             rmode = extract32(opcode, 5, 1) | (extract32(opcode, 0, 1) << 1);
12297             /* fall through */
12298         case 0x59: /* FRINTX */
12299         case 0x79: /* FRINTI */
12300             need_fpstatus = true;
12301             if (size == 3 && !is_q) {
12302                 unallocated_encoding(s);
12303                 return;
12304             }
12305             break;
12306         case 0x58: /* FRINTA */
12307             need_rmode = true;
12308             rmode = FPROUNDING_TIEAWAY;
12309             need_fpstatus = true;
12310             if (size == 3 && !is_q) {
12311                 unallocated_encoding(s);
12312                 return;
12313             }
12314             break;
12315         case 0x7c: /* URSQRTE */
12316             if (size == 3) {
12317                 unallocated_encoding(s);
12318                 return;
12319             }
12320             need_fpstatus = true;
12321             break;
12322         case 0x1e: /* FRINT32Z */
12323         case 0x1f: /* FRINT64Z */
12324             need_rmode = true;
12325             rmode = FPROUNDING_ZERO;
12326             /* fall through */
12327         case 0x5e: /* FRINT32X */
12328         case 0x5f: /* FRINT64X */
12329             need_fpstatus = true;
12330             if ((size == 3 && !is_q) || !dc_isar_feature(aa64_frint, s)) {
12331                 unallocated_encoding(s);
12332                 return;
12333             }
12334             break;
12335         default:
12336             unallocated_encoding(s);
12337             return;
12338         }
12339         break;
12340     }
12341     default:
12342         unallocated_encoding(s);
12343         return;
12344     }
12345
12346     if (!fp_access_check(s)) {
12347         return;
12348     }
12349
12350     if (need_fpstatus || need_rmode) {
12351         tcg_fpstatus = get_fpstatus_ptr(false);
12352     } else {
12353         tcg_fpstatus = NULL;
12354     }
12355     if (need_rmode) {
12356         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
12357         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12358     } else {
12359         tcg_rmode = NULL;
12360     }
12361
12362     switch (opcode) {
12363     case 0x5:
12364         if (u && size == 0) { /* NOT */
12365             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_not, 0);
12366             return;
12367         }
12368         break;
12369     case 0xb:
12370         if (u) { /* ABS, NEG */
12371             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_neg, size);
12372         } else {
12373             gen_gvec_fn2(s, is_q, rd, rn, tcg_gen_gvec_abs, size);
12374         }
12375         return;
12376     }
12377
12378     if (size == 3) {
12379         /* All 64-bit element operations can be shared with scalar 2misc */
12380         int pass;
12381
12382         /* Coverity claims (size == 3 && !is_q) has been eliminated
12383          * from all paths leading to here.
12384          */
12385         tcg_debug_assert(is_q);
12386         for (pass = 0; pass < 2; pass++) {
12387             TCGv_i64 tcg_op = tcg_temp_new_i64();
12388             TCGv_i64 tcg_res = tcg_temp_new_i64();
12389
12390             read_vec_element(s, tcg_op, rn, pass, MO_64);
12391
12392             handle_2misc_64(s, opcode, u, tcg_res, tcg_op,
12393                             tcg_rmode, tcg_fpstatus);
12394
12395             write_vec_element(s, tcg_res, rd, pass, MO_64);
12396
12397             tcg_temp_free_i64(tcg_res);
12398             tcg_temp_free_i64(tcg_op);
12399         }
12400     } else {
12401         int pass;
12402
12403         for (pass = 0; pass < (is_q ? 4 : 2); pass++) {
12404             TCGv_i32 tcg_op = tcg_temp_new_i32();
12405             TCGv_i32 tcg_res = tcg_temp_new_i32();
12406             TCGCond cond;
12407
12408             read_vec_element_i32(s, tcg_op, rn, pass, MO_32);
12409
12410             if (size == 2) {
12411                 /* Special cases for 32 bit elements */
12412                 switch (opcode) {
12413                 case 0xa: /* CMLT */
12414                     /* 32 bit integer comparison against zero, result is
12415                      * test ? (2^32 - 1) : 0. We implement via setcond(test)
12416                      * and inverting.
12417                      */
12418                     cond = TCG_COND_LT;
12419                 do_cmop:
12420                     tcg_gen_setcondi_i32(cond, tcg_res, tcg_op, 0);
12421                     tcg_gen_neg_i32(tcg_res, tcg_res);
12422                     break;
12423                 case 0x8: /* CMGT, CMGE */
12424                     cond = u ? TCG_COND_GE : TCG_COND_GT;
12425                     goto do_cmop;
12426                 case 0x9: /* CMEQ, CMLE */
12427                     cond = u ? TCG_COND_LE : TCG_COND_EQ;
12428                     goto do_cmop;
12429                 case 0x4: /* CLS */
12430                     if (u) {
12431                         tcg_gen_clzi_i32(tcg_res, tcg_op, 32);
12432                     } else {
12433                         tcg_gen_clrsb_i32(tcg_res, tcg_op);
12434                     }
12435                     break;
12436                 case 0x7: /* SQABS, SQNEG */
12437                     if (u) {
12438                         gen_helper_neon_qneg_s32(tcg_res, cpu_env, tcg_op);
12439                     } else {
12440                         gen_helper_neon_qabs_s32(tcg_res, cpu_env, tcg_op);
12441                     }
12442                     break;
12443                 case 0x2f: /* FABS */
12444                     gen_helper_vfp_abss(tcg_res, tcg_op);
12445                     break;
12446                 case 0x6f: /* FNEG */
12447                     gen_helper_vfp_negs(tcg_res, tcg_op);
12448                     break;
12449                 case 0x7f: /* FSQRT */
12450                     gen_helper_vfp_sqrts(tcg_res, tcg_op, cpu_env);
12451                     break;
12452                 case 0x1a: /* FCVTNS */
12453                 case 0x1b: /* FCVTMS */
12454                 case 0x1c: /* FCVTAS */
12455                 case 0x3a: /* FCVTPS */
12456                 case 0x3b: /* FCVTZS */
12457                 {
12458                     TCGv_i32 tcg_shift = tcg_const_i32(0);
12459                     gen_helper_vfp_tosls(tcg_res, tcg_op,
12460                                          tcg_shift, tcg_fpstatus);
12461                     tcg_temp_free_i32(tcg_shift);
12462                     break;
12463                 }
12464                 case 0x5a: /* FCVTNU */
12465                 case 0x5b: /* FCVTMU */
12466                 case 0x5c: /* FCVTAU */
12467                 case 0x7a: /* FCVTPU */
12468                 case 0x7b: /* FCVTZU */
12469                 {
12470                     TCGv_i32 tcg_shift = tcg_const_i32(0);
12471                     gen_helper_vfp_touls(tcg_res, tcg_op,
12472                                          tcg_shift, tcg_fpstatus);
12473                     tcg_temp_free_i32(tcg_shift);
12474                     break;
12475                 }
12476                 case 0x18: /* FRINTN */
12477                 case 0x19: /* FRINTM */
12478                 case 0x38: /* FRINTP */
12479                 case 0x39: /* FRINTZ */
12480                 case 0x58: /* FRINTA */
12481                 case 0x79: /* FRINTI */
12482                     gen_helper_rints(tcg_res, tcg_op, tcg_fpstatus);
12483                     break;
12484                 case 0x59: /* FRINTX */
12485                     gen_helper_rints_exact(tcg_res, tcg_op, tcg_fpstatus);
12486                     break;
12487                 case 0x7c: /* URSQRTE */
12488                     gen_helper_rsqrte_u32(tcg_res, tcg_op, tcg_fpstatus);
12489                     break;
12490                 case 0x1e: /* FRINT32Z */
12491                 case 0x5e: /* FRINT32X */
12492                     gen_helper_frint32_s(tcg_res, tcg_op, tcg_fpstatus);
12493                     break;
12494                 case 0x1f: /* FRINT64Z */
12495                 case 0x5f: /* FRINT64X */
12496                     gen_helper_frint64_s(tcg_res, tcg_op, tcg_fpstatus);
12497                     break;
12498                 default:
12499                     g_assert_not_reached();
12500                 }
12501             } else {
12502                 /* Use helpers for 8 and 16 bit elements */
12503                 switch (opcode) {
12504                 case 0x5: /* CNT, RBIT */
12505                     /* For these two insns size is part of the opcode specifier
12506                      * (handled earlier); they always operate on byte elements.
12507                      */
12508                     if (u) {
12509                         gen_helper_neon_rbit_u8(tcg_res, tcg_op);
12510                     } else {
12511                         gen_helper_neon_cnt_u8(tcg_res, tcg_op);
12512                     }
12513                     break;
12514                 case 0x7: /* SQABS, SQNEG */
12515                 {
12516                     NeonGenOneOpEnvFn *genfn;
12517                     static NeonGenOneOpEnvFn * const fns[2][2] = {
12518                         { gen_helper_neon_qabs_s8, gen_helper_neon_qneg_s8 },
12519                         { gen_helper_neon_qabs_s16, gen_helper_neon_qneg_s16 },
12520                     };
12521                     genfn = fns[size][u];
12522                     genfn(tcg_res, cpu_env, tcg_op);
12523                     break;
12524                 }
12525                 case 0x8: /* CMGT, CMGE */
12526                 case 0x9: /* CMEQ, CMLE */
12527                 case 0xa: /* CMLT */
12528                 {
12529                     static NeonGenTwoOpFn * const fns[3][2] = {
12530                         { gen_helper_neon_cgt_s8, gen_helper_neon_cgt_s16 },
12531                         { gen_helper_neon_cge_s8, gen_helper_neon_cge_s16 },
12532                         { gen_helper_neon_ceq_u8, gen_helper_neon_ceq_u16 },
12533                     };
12534                     NeonGenTwoOpFn *genfn;
12535                     int comp;
12536                     bool reverse;
12537                     TCGv_i32 tcg_zero = tcg_const_i32(0);
12538
12539                     /* comp = index into [CMGT, CMGE, CMEQ, CMLE, CMLT] */
12540                     comp = (opcode - 0x8) * 2 + u;
12541                     /* ...but LE, LT are implemented as reverse GE, GT */
12542                     reverse = (comp > 2);
12543                     if (reverse) {
12544                         comp = 4 - comp;
12545                     }
12546                     genfn = fns[comp][size];
12547                     if (reverse) {
12548                         genfn(tcg_res, tcg_zero, tcg_op);
12549                     } else {
12550                         genfn(tcg_res, tcg_op, tcg_zero);
12551                     }
12552                     tcg_temp_free_i32(tcg_zero);
12553                     break;
12554                 }
12555                 case 0x4: /* CLS, CLZ */
12556                     if (u) {
12557                         if (size == 0) {
12558                             gen_helper_neon_clz_u8(tcg_res, tcg_op);
12559                         } else {
12560                             gen_helper_neon_clz_u16(tcg_res, tcg_op);
12561                         }
12562                     } else {
12563                         if (size == 0) {
12564                             gen_helper_neon_cls_s8(tcg_res, tcg_op);
12565                         } else {
12566                             gen_helper_neon_cls_s16(tcg_res, tcg_op);
12567                         }
12568                     }
12569                     break;
12570                 default:
12571                     g_assert_not_reached();
12572                 }
12573             }
12574
12575             write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
12576
12577             tcg_temp_free_i32(tcg_res);
12578             tcg_temp_free_i32(tcg_op);
12579         }
12580     }
12581     clear_vec_high(s, is_q, rd);
12582
12583     if (need_rmode) {
12584         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12585         tcg_temp_free_i32(tcg_rmode);
12586     }
12587     if (need_fpstatus) {
12588         tcg_temp_free_ptr(tcg_fpstatus);
12589     }
12590 }
12591
12592 /* AdvSIMD [scalar] two register miscellaneous (FP16)
12593  *
12594  *   31  30  29 28  27     24  23 22 21       17 16    12 11 10 9    5 4    0
12595  * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
12596  * | 0 | Q | U | S | 1 1 1 0 | a | 1 1 1 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
12597  * +---+---+---+---+---------+---+-------------+--------+-----+------+------+
12598  *   mask: 1000 1111 0111 1110 0000 1100 0000 0000 0x8f7e 0c00
12599  *   val:  0000 1110 0111 1000 0000 1000 0000 0000 0x0e78 0800
12600  *
12601  * This actually covers two groups where scalar access is governed by
12602  * bit 28. A bunch of the instructions (float to integral) only exist
12603  * in the vector form and are un-allocated for the scalar decode. Also
12604  * in the scalar decode Q is always 1.
12605  */
12606 static void disas_simd_two_reg_misc_fp16(DisasContext *s, uint32_t insn)
12607 {
12608     int fpop, opcode, a, u;
12609     int rn, rd;
12610     bool is_q;
12611     bool is_scalar;
12612     bool only_in_vector = false;
12613
12614     int pass;
12615     TCGv_i32 tcg_rmode = NULL;
12616     TCGv_ptr tcg_fpstatus = NULL;
12617     bool need_rmode = false;
12618     bool need_fpst = true;
12619     int rmode;
12620
12621     if (!dc_isar_feature(aa64_fp16, s)) {
12622         unallocated_encoding(s);
12623         return;
12624     }
12625
12626     rd = extract32(insn, 0, 5);
12627     rn = extract32(insn, 5, 5);
12628
12629     a = extract32(insn, 23, 1);
12630     u = extract32(insn, 29, 1);
12631     is_scalar = extract32(insn, 28, 1);
12632     is_q = extract32(insn, 30, 1);
12633
12634     opcode = extract32(insn, 12, 5);
12635     fpop = deposit32(opcode, 5, 1, a);
12636     fpop = deposit32(fpop, 6, 1, u);
12637
12638     rd = extract32(insn, 0, 5);
12639     rn = extract32(insn, 5, 5);
12640
12641     switch (fpop) {
12642     case 0x1d: /* SCVTF */
12643     case 0x5d: /* UCVTF */
12644     {
12645         int elements;
12646
12647         if (is_scalar) {
12648             elements = 1;
12649         } else {
12650             elements = (is_q ? 8 : 4);
12651         }
12652
12653         if (!fp_access_check(s)) {
12654             return;
12655         }
12656         handle_simd_intfp_conv(s, rd, rn, elements, !u, 0, MO_16);
12657         return;
12658     }
12659     break;
12660     case 0x2c: /* FCMGT (zero) */
12661     case 0x2d: /* FCMEQ (zero) */
12662     case 0x2e: /* FCMLT (zero) */
12663     case 0x6c: /* FCMGE (zero) */
12664     case 0x6d: /* FCMLE (zero) */
12665         handle_2misc_fcmp_zero(s, fpop, is_scalar, 0, is_q, MO_16, rn, rd);
12666         return;
12667     case 0x3d: /* FRECPE */
12668     case 0x3f: /* FRECPX */
12669         break;
12670     case 0x18: /* FRINTN */
12671         need_rmode = true;
12672         only_in_vector = true;
12673         rmode = FPROUNDING_TIEEVEN;
12674         break;
12675     case 0x19: /* FRINTM */
12676         need_rmode = true;
12677         only_in_vector = true;
12678         rmode = FPROUNDING_NEGINF;
12679         break;
12680     case 0x38: /* FRINTP */
12681         need_rmode = true;
12682         only_in_vector = true;
12683         rmode = FPROUNDING_POSINF;
12684         break;
12685     case 0x39: /* FRINTZ */
12686         need_rmode = true;
12687         only_in_vector = true;
12688         rmode = FPROUNDING_ZERO;
12689         break;
12690     case 0x58: /* FRINTA */
12691         need_rmode = true;
12692         only_in_vector = true;
12693         rmode = FPROUNDING_TIEAWAY;
12694         break;
12695     case 0x59: /* FRINTX */
12696     case 0x79: /* FRINTI */
12697         only_in_vector = true;
12698         /* current rounding mode */
12699         break;
12700     case 0x1a: /* FCVTNS */
12701         need_rmode = true;
12702         rmode = FPROUNDING_TIEEVEN;
12703         break;
12704     case 0x1b: /* FCVTMS */
12705         need_rmode = true;
12706         rmode = FPROUNDING_NEGINF;
12707         break;
12708     case 0x1c: /* FCVTAS */
12709         need_rmode = true;
12710         rmode = FPROUNDING_TIEAWAY;
12711         break;
12712     case 0x3a: /* FCVTPS */
12713         need_rmode = true;
12714         rmode = FPROUNDING_POSINF;
12715         break;
12716     case 0x3b: /* FCVTZS */
12717         need_rmode = true;
12718         rmode = FPROUNDING_ZERO;
12719         break;
12720     case 0x5a: /* FCVTNU */
12721         need_rmode = true;
12722         rmode = FPROUNDING_TIEEVEN;
12723         break;
12724     case 0x5b: /* FCVTMU */
12725         need_rmode = true;
12726         rmode = FPROUNDING_NEGINF;
12727         break;
12728     case 0x5c: /* FCVTAU */
12729         need_rmode = true;
12730         rmode = FPROUNDING_TIEAWAY;
12731         break;
12732     case 0x7a: /* FCVTPU */
12733         need_rmode = true;
12734         rmode = FPROUNDING_POSINF;
12735         break;
12736     case 0x7b: /* FCVTZU */
12737         need_rmode = true;
12738         rmode = FPROUNDING_ZERO;
12739         break;
12740     case 0x2f: /* FABS */
12741     case 0x6f: /* FNEG */
12742         need_fpst = false;
12743         break;
12744     case 0x7d: /* FRSQRTE */
12745     case 0x7f: /* FSQRT (vector) */
12746         break;
12747     default:
12748         fprintf(stderr, "%s: insn %#04x fpop %#2x\n", __func__, insn, fpop);
12749         g_assert_not_reached();
12750     }
12751
12752
12753     /* Check additional constraints for the scalar encoding */
12754     if (is_scalar) {
12755         if (!is_q) {
12756             unallocated_encoding(s);
12757             return;
12758         }
12759         /* FRINTxx is only in the vector form */
12760         if (only_in_vector) {
12761             unallocated_encoding(s);
12762             return;
12763         }
12764     }
12765
12766     if (!fp_access_check(s)) {
12767         return;
12768     }
12769
12770     if (need_rmode || need_fpst) {
12771         tcg_fpstatus = get_fpstatus_ptr(true);
12772     }
12773
12774     if (need_rmode) {
12775         tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rmode));
12776         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12777     }
12778
12779     if (is_scalar) {
12780         TCGv_i32 tcg_op = read_fp_hreg(s, rn);
12781         TCGv_i32 tcg_res = tcg_temp_new_i32();
12782
12783         switch (fpop) {
12784         case 0x1a: /* FCVTNS */
12785         case 0x1b: /* FCVTMS */
12786         case 0x1c: /* FCVTAS */
12787         case 0x3a: /* FCVTPS */
12788         case 0x3b: /* FCVTZS */
12789             gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
12790             break;
12791         case 0x3d: /* FRECPE */
12792             gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
12793             break;
12794         case 0x3f: /* FRECPX */
12795             gen_helper_frecpx_f16(tcg_res, tcg_op, tcg_fpstatus);
12796             break;
12797         case 0x5a: /* FCVTNU */
12798         case 0x5b: /* FCVTMU */
12799         case 0x5c: /* FCVTAU */
12800         case 0x7a: /* FCVTPU */
12801         case 0x7b: /* FCVTZU */
12802             gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
12803             break;
12804         case 0x6f: /* FNEG */
12805             tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
12806             break;
12807         case 0x7d: /* FRSQRTE */
12808             gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
12809             break;
12810         default:
12811             g_assert_not_reached();
12812         }
12813
12814         /* limit any sign extension going on */
12815         tcg_gen_andi_i32(tcg_res, tcg_res, 0xffff);
12816         write_fp_sreg(s, rd, tcg_res);
12817
12818         tcg_temp_free_i32(tcg_res);
12819         tcg_temp_free_i32(tcg_op);
12820     } else {
12821         for (pass = 0; pass < (is_q ? 8 : 4); pass++) {
12822             TCGv_i32 tcg_op = tcg_temp_new_i32();
12823             TCGv_i32 tcg_res = tcg_temp_new_i32();
12824
12825             read_vec_element_i32(s, tcg_op, rn, pass, MO_16);
12826
12827             switch (fpop) {
12828             case 0x1a: /* FCVTNS */
12829             case 0x1b: /* FCVTMS */
12830             case 0x1c: /* FCVTAS */
12831             case 0x3a: /* FCVTPS */
12832             case 0x3b: /* FCVTZS */
12833                 gen_helper_advsimd_f16tosinth(tcg_res, tcg_op, tcg_fpstatus);
12834                 break;
12835             case 0x3d: /* FRECPE */
12836                 gen_helper_recpe_f16(tcg_res, tcg_op, tcg_fpstatus);
12837                 break;
12838             case 0x5a: /* FCVTNU */
12839             case 0x5b: /* FCVTMU */
12840             case 0x5c: /* FCVTAU */
12841             case 0x7a: /* FCVTPU */
12842             case 0x7b: /* FCVTZU */
12843                 gen_helper_advsimd_f16touinth(tcg_res, tcg_op, tcg_fpstatus);
12844                 break;
12845             case 0x18: /* FRINTN */
12846             case 0x19: /* FRINTM */
12847             case 0x38: /* FRINTP */
12848             case 0x39: /* FRINTZ */
12849             case 0x58: /* FRINTA */
12850             case 0x79: /* FRINTI */
12851                 gen_helper_advsimd_rinth(tcg_res, tcg_op, tcg_fpstatus);
12852                 break;
12853             case 0x59: /* FRINTX */
12854                 gen_helper_advsimd_rinth_exact(tcg_res, tcg_op, tcg_fpstatus);
12855                 break;
12856             case 0x2f: /* FABS */
12857                 tcg_gen_andi_i32(tcg_res, tcg_op, 0x7fff);
12858                 break;
12859             case 0x6f: /* FNEG */
12860                 tcg_gen_xori_i32(tcg_res, tcg_op, 0x8000);
12861                 break;
12862             case 0x7d: /* FRSQRTE */
12863                 gen_helper_rsqrte_f16(tcg_res, tcg_op, tcg_fpstatus);
12864                 break;
12865             case 0x7f: /* FSQRT */
12866                 gen_helper_sqrt_f16(tcg_res, tcg_op, tcg_fpstatus);
12867                 break;
12868             default:
12869                 g_assert_not_reached();
12870             }
12871
12872             write_vec_element_i32(s, tcg_res, rd, pass, MO_16);
12873
12874             tcg_temp_free_i32(tcg_res);
12875             tcg_temp_free_i32(tcg_op);
12876         }
12877
12878         clear_vec_high(s, is_q, rd);
12879     }
12880
12881     if (tcg_rmode) {
12882         gen_helper_set_rmode(tcg_rmode, tcg_rmode, tcg_fpstatus);
12883         tcg_temp_free_i32(tcg_rmode);
12884     }
12885
12886     if (tcg_fpstatus) {
12887         tcg_temp_free_ptr(tcg_fpstatus);
12888     }
12889 }
12890
12891 /* AdvSIMD scalar x indexed element
12892  *  31 30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
12893  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
12894  * | 0 1 | U | 1 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
12895  * +-----+---+-----------+------+---+---+------+-----+---+---+------+------+
12896  * AdvSIMD vector x indexed element
12897  *   31  30  29 28       24 23  22 21  20  19  16 15 12  11  10 9    5 4    0
12898  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
12899  * | 0 | Q | U | 0 1 1 1 1 | size | L | M |  Rm  | opc | H | 0 |  Rn  |  Rd  |
12900  * +---+---+---+-----------+------+---+---+------+-----+---+---+------+------+
12901  */
12902 static void disas_simd_indexed(DisasContext *s, uint32_t insn)
12903 {
12904     /* This encoding has two kinds of instruction:
12905      *  normal, where we perform elt x idxelt => elt for each
12906      *     element in the vector
12907      *  long, where we perform elt x idxelt and generate a result of
12908      *     double the width of the input element
12909      * The long ops have a 'part' specifier (ie come in INSN, INSN2 pairs).
12910      */
12911     bool is_scalar = extract32(insn, 28, 1);
12912     bool is_q = extract32(insn, 30, 1);
12913     bool u = extract32(insn, 29, 1);
12914     int size = extract32(insn, 22, 2);
12915     int l = extract32(insn, 21, 1);
12916     int m = extract32(insn, 20, 1);
12917     /* Note that the Rm field here is only 4 bits, not 5 as it usually is */
12918     int rm = extract32(insn, 16, 4);
12919     int opcode = extract32(insn, 12, 4);
12920     int h = extract32(insn, 11, 1);
12921     int rn = extract32(insn, 5, 5);
12922     int rd = extract32(insn, 0, 5);
12923     bool is_long = false;
12924     int is_fp = 0;
12925     bool is_fp16 = false;
12926     int index;
12927     TCGv_ptr fpst;
12928
12929     switch (16 * u + opcode) {
12930     case 0x08: /* MUL */
12931     case 0x10: /* MLA */
12932     case 0x14: /* MLS */
12933         if (is_scalar) {
12934             unallocated_encoding(s);
12935             return;
12936         }
12937         break;
12938     case 0x02: /* SMLAL, SMLAL2 */
12939     case 0x12: /* UMLAL, UMLAL2 */
12940     case 0x06: /* SMLSL, SMLSL2 */
12941     case 0x16: /* UMLSL, UMLSL2 */
12942     case 0x0a: /* SMULL, SMULL2 */
12943     case 0x1a: /* UMULL, UMULL2 */
12944         if (is_scalar) {
12945             unallocated_encoding(s);
12946             return;
12947         }
12948         is_long = true;
12949         break;
12950     case 0x03: /* SQDMLAL, SQDMLAL2 */
12951     case 0x07: /* SQDMLSL, SQDMLSL2 */
12952     case 0x0b: /* SQDMULL, SQDMULL2 */
12953         is_long = true;
12954         break;
12955     case 0x0c: /* SQDMULH */
12956     case 0x0d: /* SQRDMULH */
12957         break;
12958     case 0x01: /* FMLA */
12959     case 0x05: /* FMLS */
12960     case 0x09: /* FMUL */
12961     case 0x19: /* FMULX */
12962         is_fp = 1;
12963         break;
12964     case 0x1d: /* SQRDMLAH */
12965     case 0x1f: /* SQRDMLSH */
12966         if (!dc_isar_feature(aa64_rdm, s)) {
12967             unallocated_encoding(s);
12968             return;
12969         }
12970         break;
12971     case 0x0e: /* SDOT */
12972     case 0x1e: /* UDOT */
12973         if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_dp, s)) {
12974             unallocated_encoding(s);
12975             return;
12976         }
12977         break;
12978     case 0x11: /* FCMLA #0 */
12979     case 0x13: /* FCMLA #90 */
12980     case 0x15: /* FCMLA #180 */
12981     case 0x17: /* FCMLA #270 */
12982         if (is_scalar || !dc_isar_feature(aa64_fcma, s)) {
12983             unallocated_encoding(s);
12984             return;
12985         }
12986         is_fp = 2;
12987         break;
12988     case 0x00: /* FMLAL */
12989     case 0x04: /* FMLSL */
12990     case 0x18: /* FMLAL2 */
12991     case 0x1c: /* FMLSL2 */
12992         if (is_scalar || size != MO_32 || !dc_isar_feature(aa64_fhm, s)) {
12993             unallocated_encoding(s);
12994             return;
12995         }
12996         size = MO_16;
12997         /* is_fp, but we pass cpu_env not fp_status.  */
12998         break;
12999     default:
13000         unallocated_encoding(s);
13001         return;
13002     }
13003
13004     switch (is_fp) {
13005     case 1: /* normal fp */
13006         /* convert insn encoded size to MemOp size */
13007         switch (size) {
13008         case 0: /* half-precision */
13009             size = MO_16;
13010             is_fp16 = true;
13011             break;
13012         case MO_32: /* single precision */
13013         case MO_64: /* double precision */
13014             break;
13015         default:
13016             unallocated_encoding(s);
13017             return;
13018         }
13019         break;
13020
13021     case 2: /* complex fp */
13022         /* Each indexable element is a complex pair.  */
13023         size += 1;
13024         switch (size) {
13025         case MO_32:
13026             if (h && !is_q) {
13027                 unallocated_encoding(s);
13028                 return;
13029             }
13030             is_fp16 = true;
13031             break;
13032         case MO_64:
13033             break;
13034         default:
13035             unallocated_encoding(s);
13036             return;
13037         }
13038         break;
13039
13040     default: /* integer */
13041         switch (size) {
13042         case MO_8:
13043         case MO_64:
13044             unallocated_encoding(s);
13045             return;
13046         }
13047         break;
13048     }
13049     if (is_fp16 && !dc_isar_feature(aa64_fp16, s)) {
13050         unallocated_encoding(s);
13051         return;
13052     }
13053
13054     /* Given MemOp size, adjust register and indexing.  */
13055     switch (size) {
13056     case MO_16:
13057         index = h << 2 | l << 1 | m;
13058         break;
13059     case MO_32:
13060         index = h << 1 | l;
13061         rm |= m << 4;
13062         break;
13063     case MO_64:
13064         if (l || !is_q) {
13065             unallocated_encoding(s);
13066             return;
13067         }
13068         index = h;
13069         rm |= m << 4;
13070         break;
13071     default:
13072         g_assert_not_reached();
13073     }
13074
13075     if (!fp_access_check(s)) {
13076         return;
13077     }
13078
13079     if (is_fp) {
13080         fpst = get_fpstatus_ptr(is_fp16);
13081     } else {
13082         fpst = NULL;
13083     }
13084
13085     switch (16 * u + opcode) {
13086     case 0x0e: /* SDOT */
13087     case 0x1e: /* UDOT */
13088         gen_gvec_op3_ool(s, is_q, rd, rn, rm, index,
13089                          u ? gen_helper_gvec_udot_idx_b
13090                          : gen_helper_gvec_sdot_idx_b);
13091         return;
13092     case 0x11: /* FCMLA #0 */
13093     case 0x13: /* FCMLA #90 */
13094     case 0x15: /* FCMLA #180 */
13095     case 0x17: /* FCMLA #270 */
13096         {
13097             int rot = extract32(insn, 13, 2);
13098             int data = (index << 2) | rot;
13099             tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
13100                                vec_full_reg_offset(s, rn),
13101                                vec_full_reg_offset(s, rm), fpst,
13102                                is_q ? 16 : 8, vec_full_reg_size(s), data,
13103                                size == MO_64
13104                                ? gen_helper_gvec_fcmlas_idx
13105                                : gen_helper_gvec_fcmlah_idx);
13106             tcg_temp_free_ptr(fpst);
13107         }
13108         return;
13109
13110     case 0x00: /* FMLAL */
13111     case 0x04: /* FMLSL */
13112     case 0x18: /* FMLAL2 */
13113     case 0x1c: /* FMLSL2 */
13114         {
13115             int is_s = extract32(opcode, 2, 1);
13116             int is_2 = u;
13117             int data = (index << 2) | (is_2 << 1) | is_s;
13118             tcg_gen_gvec_3_ptr(vec_full_reg_offset(s, rd),
13119                                vec_full_reg_offset(s, rn),
13120                                vec_full_reg_offset(s, rm), cpu_env,
13121                                is_q ? 16 : 8, vec_full_reg_size(s),
13122                                data, gen_helper_gvec_fmlal_idx_a64);
13123         }
13124         return;
13125     }
13126
13127     if (size == 3) {
13128         TCGv_i64 tcg_idx = tcg_temp_new_i64();
13129         int pass;
13130
13131         assert(is_fp && is_q && !is_long);
13132
13133         read_vec_element(s, tcg_idx, rm, index, MO_64);
13134
13135         for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13136             TCGv_i64 tcg_op = tcg_temp_new_i64();
13137             TCGv_i64 tcg_res = tcg_temp_new_i64();
13138
13139             read_vec_element(s, tcg_op, rn, pass, MO_64);
13140
13141             switch (16 * u + opcode) {
13142             case 0x05: /* FMLS */
13143                 /* As usual for ARM, separate negation for fused multiply-add */
13144                 gen_helper_vfp_negd(tcg_op, tcg_op);
13145                 /* fall through */
13146             case 0x01: /* FMLA */
13147                 read_vec_element(s, tcg_res, rd, pass, MO_64);
13148                 gen_helper_vfp_muladdd(tcg_res, tcg_op, tcg_idx, tcg_res, fpst);
13149                 break;
13150             case 0x09: /* FMUL */
13151                 gen_helper_vfp_muld(tcg_res, tcg_op, tcg_idx, fpst);
13152                 break;
13153             case 0x19: /* FMULX */
13154                 gen_helper_vfp_mulxd(tcg_res, tcg_op, tcg_idx, fpst);
13155                 break;
13156             default:
13157                 g_assert_not_reached();
13158             }
13159
13160             write_vec_element(s, tcg_res, rd, pass, MO_64);
13161             tcg_temp_free_i64(tcg_op);
13162             tcg_temp_free_i64(tcg_res);
13163         }
13164
13165         tcg_temp_free_i64(tcg_idx);
13166         clear_vec_high(s, !is_scalar, rd);
13167     } else if (!is_long) {
13168         /* 32 bit floating point, or 16 or 32 bit integer.
13169          * For the 16 bit scalar case we use the usual Neon helpers and
13170          * rely on the fact that 0 op 0 == 0 with no side effects.
13171          */
13172         TCGv_i32 tcg_idx = tcg_temp_new_i32();
13173         int pass, maxpasses;
13174
13175         if (is_scalar) {
13176             maxpasses = 1;
13177         } else {
13178             maxpasses = is_q ? 4 : 2;
13179         }
13180
13181         read_vec_element_i32(s, tcg_idx, rm, index, size);
13182
13183         if (size == 1 && !is_scalar) {
13184             /* The simplest way to handle the 16x16 indexed ops is to duplicate
13185              * the index into both halves of the 32 bit tcg_idx and then use
13186              * the usual Neon helpers.
13187              */
13188             tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
13189         }
13190
13191         for (pass = 0; pass < maxpasses; pass++) {
13192             TCGv_i32 tcg_op = tcg_temp_new_i32();
13193             TCGv_i32 tcg_res = tcg_temp_new_i32();
13194
13195             read_vec_element_i32(s, tcg_op, rn, pass, is_scalar ? size : MO_32);
13196
13197             switch (16 * u + opcode) {
13198             case 0x08: /* MUL */
13199             case 0x10: /* MLA */
13200             case 0x14: /* MLS */
13201             {
13202                 static NeonGenTwoOpFn * const fns[2][2] = {
13203                     { gen_helper_neon_add_u16, gen_helper_neon_sub_u16 },
13204                     { tcg_gen_add_i32, tcg_gen_sub_i32 },
13205                 };
13206                 NeonGenTwoOpFn *genfn;
13207                 bool is_sub = opcode == 0x4;
13208
13209                 if (size == 1) {
13210                     gen_helper_neon_mul_u16(tcg_res, tcg_op, tcg_idx);
13211                 } else {
13212                     tcg_gen_mul_i32(tcg_res, tcg_op, tcg_idx);
13213                 }
13214                 if (opcode == 0x8) {
13215                     break;
13216                 }
13217                 read_vec_element_i32(s, tcg_op, rd, pass, MO_32);
13218                 genfn = fns[size - 1][is_sub];
13219                 genfn(tcg_res, tcg_op, tcg_res);
13220                 break;
13221             }
13222             case 0x05: /* FMLS */
13223             case 0x01: /* FMLA */
13224                 read_vec_element_i32(s, tcg_res, rd, pass,
13225                                      is_scalar ? size : MO_32);
13226                 switch (size) {
13227                 case 1:
13228                     if (opcode == 0x5) {
13229                         /* As usual for ARM, separate negation for fused
13230                          * multiply-add */
13231                         tcg_gen_xori_i32(tcg_op, tcg_op, 0x80008000);
13232                     }
13233                     if (is_scalar) {
13234                         gen_helper_advsimd_muladdh(tcg_res, tcg_op, tcg_idx,
13235                                                    tcg_res, fpst);
13236                     } else {
13237                         gen_helper_advsimd_muladd2h(tcg_res, tcg_op, tcg_idx,
13238                                                     tcg_res, fpst);
13239                     }
13240                     break;
13241                 case 2:
13242                     if (opcode == 0x5) {
13243                         /* As usual for ARM, separate negation for
13244                          * fused multiply-add */
13245                         tcg_gen_xori_i32(tcg_op, tcg_op, 0x80000000);
13246                     }
13247                     gen_helper_vfp_muladds(tcg_res, tcg_op, tcg_idx,
13248                                            tcg_res, fpst);
13249                     break;
13250                 default:
13251                     g_assert_not_reached();
13252                 }
13253                 break;
13254             case 0x09: /* FMUL */
13255                 switch (size) {
13256                 case 1:
13257                     if (is_scalar) {
13258                         gen_helper_advsimd_mulh(tcg_res, tcg_op,
13259                                                 tcg_idx, fpst);
13260                     } else {
13261                         gen_helper_advsimd_mul2h(tcg_res, tcg_op,
13262                                                  tcg_idx, fpst);
13263                     }
13264                     break;
13265                 case 2:
13266                     gen_helper_vfp_muls(tcg_res, tcg_op, tcg_idx, fpst);
13267                     break;
13268                 default:
13269                     g_assert_not_reached();
13270                 }
13271                 break;
13272             case 0x19: /* FMULX */
13273                 switch (size) {
13274                 case 1:
13275                     if (is_scalar) {
13276                         gen_helper_advsimd_mulxh(tcg_res, tcg_op,
13277                                                  tcg_idx, fpst);
13278                     } else {
13279                         gen_helper_advsimd_mulx2h(tcg_res, tcg_op,
13280                                                   tcg_idx, fpst);
13281                     }
13282                     break;
13283                 case 2:
13284                     gen_helper_vfp_mulxs(tcg_res, tcg_op, tcg_idx, fpst);
13285                     break;
13286                 default:
13287                     g_assert_not_reached();
13288                 }
13289                 break;
13290             case 0x0c: /* SQDMULH */
13291                 if (size == 1) {
13292                     gen_helper_neon_qdmulh_s16(tcg_res, cpu_env,
13293                                                tcg_op, tcg_idx);
13294                 } else {
13295                     gen_helper_neon_qdmulh_s32(tcg_res, cpu_env,
13296                                                tcg_op, tcg_idx);
13297                 }
13298                 break;
13299             case 0x0d: /* SQRDMULH */
13300                 if (size == 1) {
13301                     gen_helper_neon_qrdmulh_s16(tcg_res, cpu_env,
13302                                                 tcg_op, tcg_idx);
13303                 } else {
13304                     gen_helper_neon_qrdmulh_s32(tcg_res, cpu_env,
13305                                                 tcg_op, tcg_idx);
13306                 }
13307                 break;
13308             case 0x1d: /* SQRDMLAH */
13309                 read_vec_element_i32(s, tcg_res, rd, pass,
13310                                      is_scalar ? size : MO_32);
13311                 if (size == 1) {
13312                     gen_helper_neon_qrdmlah_s16(tcg_res, cpu_env,
13313                                                 tcg_op, tcg_idx, tcg_res);
13314                 } else {
13315                     gen_helper_neon_qrdmlah_s32(tcg_res, cpu_env,
13316                                                 tcg_op, tcg_idx, tcg_res);
13317                 }
13318                 break;
13319             case 0x1f: /* SQRDMLSH */
13320                 read_vec_element_i32(s, tcg_res, rd, pass,
13321                                      is_scalar ? size : MO_32);
13322                 if (size == 1) {
13323                     gen_helper_neon_qrdmlsh_s16(tcg_res, cpu_env,
13324                                                 tcg_op, tcg_idx, tcg_res);
13325                 } else {
13326                     gen_helper_neon_qrdmlsh_s32(tcg_res, cpu_env,
13327                                                 tcg_op, tcg_idx, tcg_res);
13328                 }
13329                 break;
13330             default:
13331                 g_assert_not_reached();
13332             }
13333
13334             if (is_scalar) {
13335                 write_fp_sreg(s, rd, tcg_res);
13336             } else {
13337                 write_vec_element_i32(s, tcg_res, rd, pass, MO_32);
13338             }
13339
13340             tcg_temp_free_i32(tcg_op);
13341             tcg_temp_free_i32(tcg_res);
13342         }
13343
13344         tcg_temp_free_i32(tcg_idx);
13345         clear_vec_high(s, is_q, rd);
13346     } else {
13347         /* long ops: 16x16->32 or 32x32->64 */
13348         TCGv_i64 tcg_res[2];
13349         int pass;
13350         bool satop = extract32(opcode, 0, 1);
13351         MemOp memop = MO_32;
13352
13353         if (satop || !u) {
13354             memop |= MO_SIGN;
13355         }
13356
13357         if (size == 2) {
13358             TCGv_i64 tcg_idx = tcg_temp_new_i64();
13359
13360             read_vec_element(s, tcg_idx, rm, index, memop);
13361
13362             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13363                 TCGv_i64 tcg_op = tcg_temp_new_i64();
13364                 TCGv_i64 tcg_passres;
13365                 int passelt;
13366
13367                 if (is_scalar) {
13368                     passelt = 0;
13369                 } else {
13370                     passelt = pass + (is_q * 2);
13371                 }
13372
13373                 read_vec_element(s, tcg_op, rn, passelt, memop);
13374
13375                 tcg_res[pass] = tcg_temp_new_i64();
13376
13377                 if (opcode == 0xa || opcode == 0xb) {
13378                     /* Non-accumulating ops */
13379                     tcg_passres = tcg_res[pass];
13380                 } else {
13381                     tcg_passres = tcg_temp_new_i64();
13382                 }
13383
13384                 tcg_gen_mul_i64(tcg_passres, tcg_op, tcg_idx);
13385                 tcg_temp_free_i64(tcg_op);
13386
13387                 if (satop) {
13388                     /* saturating, doubling */
13389                     gen_helper_neon_addl_saturate_s64(tcg_passres, cpu_env,
13390                                                       tcg_passres, tcg_passres);
13391                 }
13392
13393                 if (opcode == 0xa || opcode == 0xb) {
13394                     continue;
13395                 }
13396
13397                 /* Accumulating op: handle accumulate step */
13398                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13399
13400                 switch (opcode) {
13401                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
13402                     tcg_gen_add_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
13403                     break;
13404                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
13405                     tcg_gen_sub_i64(tcg_res[pass], tcg_res[pass], tcg_passres);
13406                     break;
13407                 case 0x7: /* SQDMLSL, SQDMLSL2 */
13408                     tcg_gen_neg_i64(tcg_passres, tcg_passres);
13409                     /* fall through */
13410                 case 0x3: /* SQDMLAL, SQDMLAL2 */
13411                     gen_helper_neon_addl_saturate_s64(tcg_res[pass], cpu_env,
13412                                                       tcg_res[pass],
13413                                                       tcg_passres);
13414                     break;
13415                 default:
13416                     g_assert_not_reached();
13417                 }
13418                 tcg_temp_free_i64(tcg_passres);
13419             }
13420             tcg_temp_free_i64(tcg_idx);
13421
13422             clear_vec_high(s, !is_scalar, rd);
13423         } else {
13424             TCGv_i32 tcg_idx = tcg_temp_new_i32();
13425
13426             assert(size == 1);
13427             read_vec_element_i32(s, tcg_idx, rm, index, size);
13428
13429             if (!is_scalar) {
13430                 /* The simplest way to handle the 16x16 indexed ops is to
13431                  * duplicate the index into both halves of the 32 bit tcg_idx
13432                  * and then use the usual Neon helpers.
13433                  */
13434                 tcg_gen_deposit_i32(tcg_idx, tcg_idx, tcg_idx, 16, 16);
13435             }
13436
13437             for (pass = 0; pass < (is_scalar ? 1 : 2); pass++) {
13438                 TCGv_i32 tcg_op = tcg_temp_new_i32();
13439                 TCGv_i64 tcg_passres;
13440
13441                 if (is_scalar) {
13442                     read_vec_element_i32(s, tcg_op, rn, pass, size);
13443                 } else {
13444                     read_vec_element_i32(s, tcg_op, rn,
13445                                          pass + (is_q * 2), MO_32);
13446                 }
13447
13448                 tcg_res[pass] = tcg_temp_new_i64();
13449
13450                 if (opcode == 0xa || opcode == 0xb) {
13451                     /* Non-accumulating ops */
13452                     tcg_passres = tcg_res[pass];
13453                 } else {
13454                     tcg_passres = tcg_temp_new_i64();
13455                 }
13456
13457                 if (memop & MO_SIGN) {
13458                     gen_helper_neon_mull_s16(tcg_passres, tcg_op, tcg_idx);
13459                 } else {
13460                     gen_helper_neon_mull_u16(tcg_passres, tcg_op, tcg_idx);
13461                 }
13462                 if (satop) {
13463                     gen_helper_neon_addl_saturate_s32(tcg_passres, cpu_env,
13464                                                       tcg_passres, tcg_passres);
13465                 }
13466                 tcg_temp_free_i32(tcg_op);
13467
13468                 if (opcode == 0xa || opcode == 0xb) {
13469                     continue;
13470                 }
13471
13472                 /* Accumulating op: handle accumulate step */
13473                 read_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13474
13475                 switch (opcode) {
13476                 case 0x2: /* SMLAL, SMLAL2, UMLAL, UMLAL2 */
13477                     gen_helper_neon_addl_u32(tcg_res[pass], tcg_res[pass],
13478                                              tcg_passres);
13479                     break;
13480                 case 0x6: /* SMLSL, SMLSL2, UMLSL, UMLSL2 */
13481                     gen_helper_neon_subl_u32(tcg_res[pass], tcg_res[pass],
13482                                              tcg_passres);
13483                     break;
13484                 case 0x7: /* SQDMLSL, SQDMLSL2 */
13485                     gen_helper_neon_negl_u32(tcg_passres, tcg_passres);
13486                     /* fall through */
13487                 case 0x3: /* SQDMLAL, SQDMLAL2 */
13488                     gen_helper_neon_addl_saturate_s32(tcg_res[pass], cpu_env,
13489                                                       tcg_res[pass],
13490                                                       tcg_passres);
13491                     break;
13492                 default:
13493                     g_assert_not_reached();
13494                 }
13495                 tcg_temp_free_i64(tcg_passres);
13496             }
13497             tcg_temp_free_i32(tcg_idx);
13498
13499             if (is_scalar) {
13500                 tcg_gen_ext32u_i64(tcg_res[0], tcg_res[0]);
13501             }
13502         }
13503
13504         if (is_scalar) {
13505             tcg_res[1] = tcg_const_i64(0);
13506         }
13507
13508         for (pass = 0; pass < 2; pass++) {
13509             write_vec_element(s, tcg_res[pass], rd, pass, MO_64);
13510             tcg_temp_free_i64(tcg_res[pass]);
13511         }
13512     }
13513
13514     if (fpst) {
13515         tcg_temp_free_ptr(fpst);
13516     }
13517 }
13518
13519 /* Crypto AES
13520  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
13521  * +-----------------+------+-----------+--------+-----+------+------+
13522  * | 0 1 0 0 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
13523  * +-----------------+------+-----------+--------+-----+------+------+
13524  */
13525 static void disas_crypto_aes(DisasContext *s, uint32_t insn)
13526 {
13527     int size = extract32(insn, 22, 2);
13528     int opcode = extract32(insn, 12, 5);
13529     int rn = extract32(insn, 5, 5);
13530     int rd = extract32(insn, 0, 5);
13531     int decrypt;
13532     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13533     TCGv_i32 tcg_decrypt;
13534     CryptoThreeOpIntFn *genfn;
13535
13536     if (!dc_isar_feature(aa64_aes, s) || size != 0) {
13537         unallocated_encoding(s);
13538         return;
13539     }
13540
13541     switch (opcode) {
13542     case 0x4: /* AESE */
13543         decrypt = 0;
13544         genfn = gen_helper_crypto_aese;
13545         break;
13546     case 0x6: /* AESMC */
13547         decrypt = 0;
13548         genfn = gen_helper_crypto_aesmc;
13549         break;
13550     case 0x5: /* AESD */
13551         decrypt = 1;
13552         genfn = gen_helper_crypto_aese;
13553         break;
13554     case 0x7: /* AESIMC */
13555         decrypt = 1;
13556         genfn = gen_helper_crypto_aesmc;
13557         break;
13558     default:
13559         unallocated_encoding(s);
13560         return;
13561     }
13562
13563     if (!fp_access_check(s)) {
13564         return;
13565     }
13566
13567     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13568     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13569     tcg_decrypt = tcg_const_i32(decrypt);
13570
13571     genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_decrypt);
13572
13573     tcg_temp_free_ptr(tcg_rd_ptr);
13574     tcg_temp_free_ptr(tcg_rn_ptr);
13575     tcg_temp_free_i32(tcg_decrypt);
13576 }
13577
13578 /* Crypto three-reg SHA
13579  *  31             24 23  22  21 20  16  15 14    12 11 10 9    5 4    0
13580  * +-----------------+------+---+------+---+--------+-----+------+------+
13581  * | 0 1 0 1 1 1 1 0 | size | 0 |  Rm  | 0 | opcode | 0 0 |  Rn  |  Rd  |
13582  * +-----------------+------+---+------+---+--------+-----+------+------+
13583  */
13584 static void disas_crypto_three_reg_sha(DisasContext *s, uint32_t insn)
13585 {
13586     int size = extract32(insn, 22, 2);
13587     int opcode = extract32(insn, 12, 3);
13588     int rm = extract32(insn, 16, 5);
13589     int rn = extract32(insn, 5, 5);
13590     int rd = extract32(insn, 0, 5);
13591     CryptoThreeOpFn *genfn;
13592     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
13593     bool feature;
13594
13595     if (size != 0) {
13596         unallocated_encoding(s);
13597         return;
13598     }
13599
13600     switch (opcode) {
13601     case 0: /* SHA1C */
13602     case 1: /* SHA1P */
13603     case 2: /* SHA1M */
13604     case 3: /* SHA1SU0 */
13605         genfn = NULL;
13606         feature = dc_isar_feature(aa64_sha1, s);
13607         break;
13608     case 4: /* SHA256H */
13609         genfn = gen_helper_crypto_sha256h;
13610         feature = dc_isar_feature(aa64_sha256, s);
13611         break;
13612     case 5: /* SHA256H2 */
13613         genfn = gen_helper_crypto_sha256h2;
13614         feature = dc_isar_feature(aa64_sha256, s);
13615         break;
13616     case 6: /* SHA256SU1 */
13617         genfn = gen_helper_crypto_sha256su1;
13618         feature = dc_isar_feature(aa64_sha256, s);
13619         break;
13620     default:
13621         unallocated_encoding(s);
13622         return;
13623     }
13624
13625     if (!feature) {
13626         unallocated_encoding(s);
13627         return;
13628     }
13629
13630     if (!fp_access_check(s)) {
13631         return;
13632     }
13633
13634     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13635     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13636     tcg_rm_ptr = vec_full_reg_ptr(s, rm);
13637
13638     if (genfn) {
13639         genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
13640     } else {
13641         TCGv_i32 tcg_opcode = tcg_const_i32(opcode);
13642
13643         gen_helper_crypto_sha1_3reg(tcg_rd_ptr, tcg_rn_ptr,
13644                                     tcg_rm_ptr, tcg_opcode);
13645         tcg_temp_free_i32(tcg_opcode);
13646     }
13647
13648     tcg_temp_free_ptr(tcg_rd_ptr);
13649     tcg_temp_free_ptr(tcg_rn_ptr);
13650     tcg_temp_free_ptr(tcg_rm_ptr);
13651 }
13652
13653 /* Crypto two-reg SHA
13654  *  31             24 23  22 21       17 16    12 11 10 9    5 4    0
13655  * +-----------------+------+-----------+--------+-----+------+------+
13656  * | 0 1 0 1 1 1 1 0 | size | 1 0 1 0 0 | opcode | 1 0 |  Rn  |  Rd  |
13657  * +-----------------+------+-----------+--------+-----+------+------+
13658  */
13659 static void disas_crypto_two_reg_sha(DisasContext *s, uint32_t insn)
13660 {
13661     int size = extract32(insn, 22, 2);
13662     int opcode = extract32(insn, 12, 5);
13663     int rn = extract32(insn, 5, 5);
13664     int rd = extract32(insn, 0, 5);
13665     CryptoTwoOpFn *genfn;
13666     bool feature;
13667     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13668
13669     if (size != 0) {
13670         unallocated_encoding(s);
13671         return;
13672     }
13673
13674     switch (opcode) {
13675     case 0: /* SHA1H */
13676         feature = dc_isar_feature(aa64_sha1, s);
13677         genfn = gen_helper_crypto_sha1h;
13678         break;
13679     case 1: /* SHA1SU1 */
13680         feature = dc_isar_feature(aa64_sha1, s);
13681         genfn = gen_helper_crypto_sha1su1;
13682         break;
13683     case 2: /* SHA256SU0 */
13684         feature = dc_isar_feature(aa64_sha256, s);
13685         genfn = gen_helper_crypto_sha256su0;
13686         break;
13687     default:
13688         unallocated_encoding(s);
13689         return;
13690     }
13691
13692     if (!feature) {
13693         unallocated_encoding(s);
13694         return;
13695     }
13696
13697     if (!fp_access_check(s)) {
13698         return;
13699     }
13700
13701     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13702     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13703
13704     genfn(tcg_rd_ptr, tcg_rn_ptr);
13705
13706     tcg_temp_free_ptr(tcg_rd_ptr);
13707     tcg_temp_free_ptr(tcg_rn_ptr);
13708 }
13709
13710 /* Crypto three-reg SHA512
13711  *  31                   21 20  16 15  14  13 12  11  10  9    5 4    0
13712  * +-----------------------+------+---+---+-----+--------+------+------+
13713  * | 1 1 0 0 1 1 1 0 0 1 1 |  Rm  | 1 | O | 0 0 | opcode |  Rn  |  Rd  |
13714  * +-----------------------+------+---+---+-----+--------+------+------+
13715  */
13716 static void disas_crypto_three_reg_sha512(DisasContext *s, uint32_t insn)
13717 {
13718     int opcode = extract32(insn, 10, 2);
13719     int o =  extract32(insn, 14, 1);
13720     int rm = extract32(insn, 16, 5);
13721     int rn = extract32(insn, 5, 5);
13722     int rd = extract32(insn, 0, 5);
13723     bool feature;
13724     CryptoThreeOpFn *genfn;
13725
13726     if (o == 0) {
13727         switch (opcode) {
13728         case 0: /* SHA512H */
13729             feature = dc_isar_feature(aa64_sha512, s);
13730             genfn = gen_helper_crypto_sha512h;
13731             break;
13732         case 1: /* SHA512H2 */
13733             feature = dc_isar_feature(aa64_sha512, s);
13734             genfn = gen_helper_crypto_sha512h2;
13735             break;
13736         case 2: /* SHA512SU1 */
13737             feature = dc_isar_feature(aa64_sha512, s);
13738             genfn = gen_helper_crypto_sha512su1;
13739             break;
13740         case 3: /* RAX1 */
13741             feature = dc_isar_feature(aa64_sha3, s);
13742             genfn = NULL;
13743             break;
13744         default:
13745             g_assert_not_reached();
13746         }
13747     } else {
13748         switch (opcode) {
13749         case 0: /* SM3PARTW1 */
13750             feature = dc_isar_feature(aa64_sm3, s);
13751             genfn = gen_helper_crypto_sm3partw1;
13752             break;
13753         case 1: /* SM3PARTW2 */
13754             feature = dc_isar_feature(aa64_sm3, s);
13755             genfn = gen_helper_crypto_sm3partw2;
13756             break;
13757         case 2: /* SM4EKEY */
13758             feature = dc_isar_feature(aa64_sm4, s);
13759             genfn = gen_helper_crypto_sm4ekey;
13760             break;
13761         default:
13762             unallocated_encoding(s);
13763             return;
13764         }
13765     }
13766
13767     if (!feature) {
13768         unallocated_encoding(s);
13769         return;
13770     }
13771
13772     if (!fp_access_check(s)) {
13773         return;
13774     }
13775
13776     if (genfn) {
13777         TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
13778
13779         tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13780         tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13781         tcg_rm_ptr = vec_full_reg_ptr(s, rm);
13782
13783         genfn(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr);
13784
13785         tcg_temp_free_ptr(tcg_rd_ptr);
13786         tcg_temp_free_ptr(tcg_rn_ptr);
13787         tcg_temp_free_ptr(tcg_rm_ptr);
13788     } else {
13789         TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
13790         int pass;
13791
13792         tcg_op1 = tcg_temp_new_i64();
13793         tcg_op2 = tcg_temp_new_i64();
13794         tcg_res[0] = tcg_temp_new_i64();
13795         tcg_res[1] = tcg_temp_new_i64();
13796
13797         for (pass = 0; pass < 2; pass++) {
13798             read_vec_element(s, tcg_op1, rn, pass, MO_64);
13799             read_vec_element(s, tcg_op2, rm, pass, MO_64);
13800
13801             tcg_gen_rotli_i64(tcg_res[pass], tcg_op2, 1);
13802             tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
13803         }
13804         write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13805         write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13806
13807         tcg_temp_free_i64(tcg_op1);
13808         tcg_temp_free_i64(tcg_op2);
13809         tcg_temp_free_i64(tcg_res[0]);
13810         tcg_temp_free_i64(tcg_res[1]);
13811     }
13812 }
13813
13814 /* Crypto two-reg SHA512
13815  *  31                                     12  11  10  9    5 4    0
13816  * +-----------------------------------------+--------+------+------+
13817  * | 1 1 0 0 1 1 1 0 1 1 0 0 0 0 0 0 1 0 0 0 | opcode |  Rn  |  Rd  |
13818  * +-----------------------------------------+--------+------+------+
13819  */
13820 static void disas_crypto_two_reg_sha512(DisasContext *s, uint32_t insn)
13821 {
13822     int opcode = extract32(insn, 10, 2);
13823     int rn = extract32(insn, 5, 5);
13824     int rd = extract32(insn, 0, 5);
13825     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr;
13826     bool feature;
13827     CryptoTwoOpFn *genfn;
13828
13829     switch (opcode) {
13830     case 0: /* SHA512SU0 */
13831         feature = dc_isar_feature(aa64_sha512, s);
13832         genfn = gen_helper_crypto_sha512su0;
13833         break;
13834     case 1: /* SM4E */
13835         feature = dc_isar_feature(aa64_sm4, s);
13836         genfn = gen_helper_crypto_sm4e;
13837         break;
13838     default:
13839         unallocated_encoding(s);
13840         return;
13841     }
13842
13843     if (!feature) {
13844         unallocated_encoding(s);
13845         return;
13846     }
13847
13848     if (!fp_access_check(s)) {
13849         return;
13850     }
13851
13852     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
13853     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
13854
13855     genfn(tcg_rd_ptr, tcg_rn_ptr);
13856
13857     tcg_temp_free_ptr(tcg_rd_ptr);
13858     tcg_temp_free_ptr(tcg_rn_ptr);
13859 }
13860
13861 /* Crypto four-register
13862  *  31               23 22 21 20  16 15  14  10 9    5 4    0
13863  * +-------------------+-----+------+---+------+------+------+
13864  * | 1 1 0 0 1 1 1 0 0 | Op0 |  Rm  | 0 |  Ra  |  Rn  |  Rd  |
13865  * +-------------------+-----+------+---+------+------+------+
13866  */
13867 static void disas_crypto_four_reg(DisasContext *s, uint32_t insn)
13868 {
13869     int op0 = extract32(insn, 21, 2);
13870     int rm = extract32(insn, 16, 5);
13871     int ra = extract32(insn, 10, 5);
13872     int rn = extract32(insn, 5, 5);
13873     int rd = extract32(insn, 0, 5);
13874     bool feature;
13875
13876     switch (op0) {
13877     case 0: /* EOR3 */
13878     case 1: /* BCAX */
13879         feature = dc_isar_feature(aa64_sha3, s);
13880         break;
13881     case 2: /* SM3SS1 */
13882         feature = dc_isar_feature(aa64_sm3, s);
13883         break;
13884     default:
13885         unallocated_encoding(s);
13886         return;
13887     }
13888
13889     if (!feature) {
13890         unallocated_encoding(s);
13891         return;
13892     }
13893
13894     if (!fp_access_check(s)) {
13895         return;
13896     }
13897
13898     if (op0 < 2) {
13899         TCGv_i64 tcg_op1, tcg_op2, tcg_op3, tcg_res[2];
13900         int pass;
13901
13902         tcg_op1 = tcg_temp_new_i64();
13903         tcg_op2 = tcg_temp_new_i64();
13904         tcg_op3 = tcg_temp_new_i64();
13905         tcg_res[0] = tcg_temp_new_i64();
13906         tcg_res[1] = tcg_temp_new_i64();
13907
13908         for (pass = 0; pass < 2; pass++) {
13909             read_vec_element(s, tcg_op1, rn, pass, MO_64);
13910             read_vec_element(s, tcg_op2, rm, pass, MO_64);
13911             read_vec_element(s, tcg_op3, ra, pass, MO_64);
13912
13913             if (op0 == 0) {
13914                 /* EOR3 */
13915                 tcg_gen_xor_i64(tcg_res[pass], tcg_op2, tcg_op3);
13916             } else {
13917                 /* BCAX */
13918                 tcg_gen_andc_i64(tcg_res[pass], tcg_op2, tcg_op3);
13919             }
13920             tcg_gen_xor_i64(tcg_res[pass], tcg_res[pass], tcg_op1);
13921         }
13922         write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13923         write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13924
13925         tcg_temp_free_i64(tcg_op1);
13926         tcg_temp_free_i64(tcg_op2);
13927         tcg_temp_free_i64(tcg_op3);
13928         tcg_temp_free_i64(tcg_res[0]);
13929         tcg_temp_free_i64(tcg_res[1]);
13930     } else {
13931         TCGv_i32 tcg_op1, tcg_op2, tcg_op3, tcg_res, tcg_zero;
13932
13933         tcg_op1 = tcg_temp_new_i32();
13934         tcg_op2 = tcg_temp_new_i32();
13935         tcg_op3 = tcg_temp_new_i32();
13936         tcg_res = tcg_temp_new_i32();
13937         tcg_zero = tcg_const_i32(0);
13938
13939         read_vec_element_i32(s, tcg_op1, rn, 3, MO_32);
13940         read_vec_element_i32(s, tcg_op2, rm, 3, MO_32);
13941         read_vec_element_i32(s, tcg_op3, ra, 3, MO_32);
13942
13943         tcg_gen_rotri_i32(tcg_res, tcg_op1, 20);
13944         tcg_gen_add_i32(tcg_res, tcg_res, tcg_op2);
13945         tcg_gen_add_i32(tcg_res, tcg_res, tcg_op3);
13946         tcg_gen_rotri_i32(tcg_res, tcg_res, 25);
13947
13948         write_vec_element_i32(s, tcg_zero, rd, 0, MO_32);
13949         write_vec_element_i32(s, tcg_zero, rd, 1, MO_32);
13950         write_vec_element_i32(s, tcg_zero, rd, 2, MO_32);
13951         write_vec_element_i32(s, tcg_res, rd, 3, MO_32);
13952
13953         tcg_temp_free_i32(tcg_op1);
13954         tcg_temp_free_i32(tcg_op2);
13955         tcg_temp_free_i32(tcg_op3);
13956         tcg_temp_free_i32(tcg_res);
13957         tcg_temp_free_i32(tcg_zero);
13958     }
13959 }
13960
13961 /* Crypto XAR
13962  *  31                   21 20  16 15    10 9    5 4    0
13963  * +-----------------------+------+--------+------+------+
13964  * | 1 1 0 0 1 1 1 0 1 0 0 |  Rm  |  imm6  |  Rn  |  Rd  |
13965  * +-----------------------+------+--------+------+------+
13966  */
13967 static void disas_crypto_xar(DisasContext *s, uint32_t insn)
13968 {
13969     int rm = extract32(insn, 16, 5);
13970     int imm6 = extract32(insn, 10, 6);
13971     int rn = extract32(insn, 5, 5);
13972     int rd = extract32(insn, 0, 5);
13973     TCGv_i64 tcg_op1, tcg_op2, tcg_res[2];
13974     int pass;
13975
13976     if (!dc_isar_feature(aa64_sha3, s)) {
13977         unallocated_encoding(s);
13978         return;
13979     }
13980
13981     if (!fp_access_check(s)) {
13982         return;
13983     }
13984
13985     tcg_op1 = tcg_temp_new_i64();
13986     tcg_op2 = tcg_temp_new_i64();
13987     tcg_res[0] = tcg_temp_new_i64();
13988     tcg_res[1] = tcg_temp_new_i64();
13989
13990     for (pass = 0; pass < 2; pass++) {
13991         read_vec_element(s, tcg_op1, rn, pass, MO_64);
13992         read_vec_element(s, tcg_op2, rm, pass, MO_64);
13993
13994         tcg_gen_xor_i64(tcg_res[pass], tcg_op1, tcg_op2);
13995         tcg_gen_rotri_i64(tcg_res[pass], tcg_res[pass], imm6);
13996     }
13997     write_vec_element(s, tcg_res[0], rd, 0, MO_64);
13998     write_vec_element(s, tcg_res[1], rd, 1, MO_64);
13999
14000     tcg_temp_free_i64(tcg_op1);
14001     tcg_temp_free_i64(tcg_op2);
14002     tcg_temp_free_i64(tcg_res[0]);
14003     tcg_temp_free_i64(tcg_res[1]);
14004 }
14005
14006 /* Crypto three-reg imm2
14007  *  31                   21 20  16 15  14 13 12  11  10  9    5 4    0
14008  * +-----------------------+------+-----+------+--------+------+------+
14009  * | 1 1 0 0 1 1 1 0 0 1 0 |  Rm  | 1 0 | imm2 | opcode |  Rn  |  Rd  |
14010  * +-----------------------+------+-----+------+--------+------+------+
14011  */
14012 static void disas_crypto_three_reg_imm2(DisasContext *s, uint32_t insn)
14013 {
14014     int opcode = extract32(insn, 10, 2);
14015     int imm2 = extract32(insn, 12, 2);
14016     int rm = extract32(insn, 16, 5);
14017     int rn = extract32(insn, 5, 5);
14018     int rd = extract32(insn, 0, 5);
14019     TCGv_ptr tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr;
14020     TCGv_i32 tcg_imm2, tcg_opcode;
14021
14022     if (!dc_isar_feature(aa64_sm3, s)) {
14023         unallocated_encoding(s);
14024         return;
14025     }
14026
14027     if (!fp_access_check(s)) {
14028         return;
14029     }
14030
14031     tcg_rd_ptr = vec_full_reg_ptr(s, rd);
14032     tcg_rn_ptr = vec_full_reg_ptr(s, rn);
14033     tcg_rm_ptr = vec_full_reg_ptr(s, rm);
14034     tcg_imm2   = tcg_const_i32(imm2);
14035     tcg_opcode = tcg_const_i32(opcode);
14036
14037     gen_helper_crypto_sm3tt(tcg_rd_ptr, tcg_rn_ptr, tcg_rm_ptr, tcg_imm2,
14038                             tcg_opcode);
14039
14040     tcg_temp_free_ptr(tcg_rd_ptr);
14041     tcg_temp_free_ptr(tcg_rn_ptr);
14042     tcg_temp_free_ptr(tcg_rm_ptr);
14043     tcg_temp_free_i32(tcg_imm2);
14044     tcg_temp_free_i32(tcg_opcode);
14045 }
14046
14047 /* C3.6 Data processing - SIMD, inc Crypto
14048  *
14049  * As the decode gets a little complex we are using a table based
14050  * approach for this part of the decode.
14051  */
14052 static const AArch64DecodeTable data_proc_simd[] = {
14053     /* pattern  ,  mask     ,  fn                        */
14054     { 0x0e200400, 0x9f200400, disas_simd_three_reg_same },
14055     { 0x0e008400, 0x9f208400, disas_simd_three_reg_same_extra },
14056     { 0x0e200000, 0x9f200c00, disas_simd_three_reg_diff },
14057     { 0x0e200800, 0x9f3e0c00, disas_simd_two_reg_misc },
14058     { 0x0e300800, 0x9f3e0c00, disas_simd_across_lanes },
14059     { 0x0e000400, 0x9fe08400, disas_simd_copy },
14060     { 0x0f000000, 0x9f000400, disas_simd_indexed }, /* vector indexed */
14061     /* simd_mod_imm decode is a subset of simd_shift_imm, so must precede it */
14062     { 0x0f000400, 0x9ff80400, disas_simd_mod_imm },
14063     { 0x0f000400, 0x9f800400, disas_simd_shift_imm },
14064     { 0x0e000000, 0xbf208c00, disas_simd_tb },
14065     { 0x0e000800, 0xbf208c00, disas_simd_zip_trn },
14066     { 0x2e000000, 0xbf208400, disas_simd_ext },
14067     { 0x5e200400, 0xdf200400, disas_simd_scalar_three_reg_same },
14068     { 0x5e008400, 0xdf208400, disas_simd_scalar_three_reg_same_extra },
14069     { 0x5e200000, 0xdf200c00, disas_simd_scalar_three_reg_diff },
14070     { 0x5e200800, 0xdf3e0c00, disas_simd_scalar_two_reg_misc },
14071     { 0x5e300800, 0xdf3e0c00, disas_simd_scalar_pairwise },
14072     { 0x5e000400, 0xdfe08400, disas_simd_scalar_copy },
14073     { 0x5f000000, 0xdf000400, disas_simd_indexed }, /* scalar indexed */
14074     { 0x5f000400, 0xdf800400, disas_simd_scalar_shift_imm },
14075     { 0x4e280800, 0xff3e0c00, disas_crypto_aes },
14076     { 0x5e000000, 0xff208c00, disas_crypto_three_reg_sha },
14077     { 0x5e280800, 0xff3e0c00, disas_crypto_two_reg_sha },
14078     { 0xce608000, 0xffe0b000, disas_crypto_three_reg_sha512 },
14079     { 0xcec08000, 0xfffff000, disas_crypto_two_reg_sha512 },
14080     { 0xce000000, 0xff808000, disas_crypto_four_reg },
14081     { 0xce800000, 0xffe00000, disas_crypto_xar },
14082     { 0xce408000, 0xffe0c000, disas_crypto_three_reg_imm2 },
14083     { 0x0e400400, 0x9f60c400, disas_simd_three_reg_same_fp16 },
14084     { 0x0e780800, 0x8f7e0c00, disas_simd_two_reg_misc_fp16 },
14085     { 0x5e400400, 0xdf60c400, disas_simd_scalar_three_reg_same_fp16 },
14086     { 0x00000000, 0x00000000, NULL }
14087 };
14088
14089 static void disas_data_proc_simd(DisasContext *s, uint32_t insn)
14090 {
14091     /* Note that this is called with all non-FP cases from
14092      * table C3-6 so it must UNDEF for entries not specifically
14093      * allocated to instructions in that table.
14094      */
14095     AArch64DecodeFn *fn = lookup_disas_fn(&data_proc_simd[0], insn);
14096     if (fn) {
14097         fn(s, insn);
14098     } else {
14099         unallocated_encoding(s);
14100     }
14101 }
14102
14103 /* C3.6 Data processing - SIMD and floating point */
14104 static void disas_data_proc_simd_fp(DisasContext *s, uint32_t insn)
14105 {
14106     if (extract32(insn, 28, 1) == 1 && extract32(insn, 30, 1) == 0) {
14107         disas_data_proc_fp(s, insn);
14108     } else {
14109         /* SIMD, including crypto */
14110         disas_data_proc_simd(s, insn);
14111     }
14112 }
14113
14114 /**
14115  * is_guarded_page:
14116  * @env: The cpu environment
14117  * @s: The DisasContext
14118  *
14119  * Return true if the page is guarded.
14120  */
14121 static bool is_guarded_page(CPUARMState *env, DisasContext *s)
14122 {
14123 #ifdef CONFIG_USER_ONLY
14124     return false;  /* FIXME */
14125 #else
14126     uint64_t addr = s->base.pc_first;
14127     int mmu_idx = arm_to_core_mmu_idx(s->mmu_idx);
14128     unsigned int index = tlb_index(env, mmu_idx, addr);
14129     CPUTLBEntry *entry = tlb_entry(env, mmu_idx, addr);
14130
14131     /*
14132      * We test this immediately after reading an insn, which means
14133      * that any normal page must be in the TLB.  The only exception
14134      * would be for executing from flash or device memory, which
14135      * does not retain the TLB entry.
14136      *
14137      * FIXME: Assume false for those, for now.  We could use
14138      * arm_cpu_get_phys_page_attrs_debug to re-read the page
14139      * table entry even for that case.
14140      */
14141     return (tlb_hit(entry->addr_code, addr) &&
14142             env_tlb(env)->d[mmu_idx].iotlb[index].attrs.target_tlb_bit0);
14143 #endif
14144 }
14145
14146 /**
14147  * btype_destination_ok:
14148  * @insn: The instruction at the branch destination
14149  * @bt: SCTLR_ELx.BT
14150  * @btype: PSTATE.BTYPE, and is non-zero
14151  *
14152  * On a guarded page, there are a limited number of insns
14153  * that may be present at the branch target:
14154  *   - branch target identifiers,
14155  *   - paciasp, pacibsp,
14156  *   - BRK insn
14157  *   - HLT insn
14158  * Anything else causes a Branch Target Exception.
14159  *
14160  * Return true if the branch is compatible, false to raise BTITRAP.
14161  */
14162 static bool btype_destination_ok(uint32_t insn, bool bt, int btype)
14163 {
14164     if ((insn & 0xfffff01fu) == 0xd503201fu) {
14165         /* HINT space */
14166         switch (extract32(insn, 5, 7)) {
14167         case 0b011001: /* PACIASP */
14168         case 0b011011: /* PACIBSP */
14169             /*
14170              * If SCTLR_ELx.BT, then PACI*SP are not compatible
14171              * with btype == 3.  Otherwise all btype are ok.
14172              */
14173             return !bt || btype != 3;
14174         case 0b100000: /* BTI */
14175             /* Not compatible with any btype.  */
14176             return false;
14177         case 0b100010: /* BTI c */
14178             /* Not compatible with btype == 3 */
14179             return btype != 3;
14180         case 0b100100: /* BTI j */
14181             /* Not compatible with btype == 2 */
14182             return btype != 2;
14183         case 0b100110: /* BTI jc */
14184             /* Compatible with any btype.  */
14185             return true;
14186         }
14187     } else {
14188         switch (insn & 0xffe0001fu) {
14189         case 0xd4200000u: /* BRK */
14190         case 0xd4400000u: /* HLT */
14191             /* Give priority to the breakpoint exception.  */
14192             return true;
14193         }
14194     }
14195     return false;
14196 }
14197
14198 /* C3.1 A64 instruction index by encoding */
14199 static void disas_a64_insn(CPUARMState *env, DisasContext *s)
14200 {
14201     uint32_t insn;
14202
14203     s->pc_curr = s->base.pc_next;
14204     insn = arm_ldl_code(env, s->base.pc_next, s->sctlr_b);
14205     s->insn = insn;
14206     s->base.pc_next += 4;
14207
14208     s->fp_access_checked = false;
14209
14210     if (dc_isar_feature(aa64_bti, s)) {
14211         if (s->base.num_insns == 1) {
14212             /*
14213              * At the first insn of the TB, compute s->guarded_page.
14214              * We delayed computing this until successfully reading
14215              * the first insn of the TB, above.  This (mostly) ensures
14216              * that the softmmu tlb entry has been populated, and the
14217              * page table GP bit is available.
14218              *
14219              * Note that we need to compute this even if btype == 0,
14220              * because this value is used for BR instructions later
14221              * where ENV is not available.
14222              */
14223             s->guarded_page = is_guarded_page(env, s);
14224
14225             /* First insn can have btype set to non-zero.  */
14226             tcg_debug_assert(s->btype >= 0);
14227
14228             /*
14229              * Note that the Branch Target Exception has fairly high
14230              * priority -- below debugging exceptions but above most
14231              * everything else.  This allows us to handle this now
14232              * instead of waiting until the insn is otherwise decoded.
14233              */
14234             if (s->btype != 0
14235                 && s->guarded_page
14236                 && !btype_destination_ok(insn, s->bt, s->btype)) {
14237                 gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
14238                                    syn_btitrap(s->btype),
14239                                    default_exception_el(s));
14240                 return;
14241             }
14242         } else {
14243             /* Not the first insn: btype must be 0.  */
14244             tcg_debug_assert(s->btype == 0);
14245         }
14246     }
14247
14248     switch (extract32(insn, 25, 4)) {
14249     case 0x0: case 0x1: case 0x3: /* UNALLOCATED */
14250         unallocated_encoding(s);
14251         break;
14252     case 0x2:
14253         if (!dc_isar_feature(aa64_sve, s) || !disas_sve(s, insn)) {
14254             unallocated_encoding(s);
14255         }
14256         break;
14257     case 0x8: case 0x9: /* Data processing - immediate */
14258         disas_data_proc_imm(s, insn);
14259         break;
14260     case 0xa: case 0xb: /* Branch, exception generation and system insns */
14261         disas_b_exc_sys(s, insn);
14262         break;
14263     case 0x4:
14264     case 0x6:
14265     case 0xc:
14266     case 0xe:      /* Loads and stores */
14267         disas_ldst(s, insn);
14268         break;
14269     case 0x5:
14270     case 0xd:      /* Data processing - register */
14271         disas_data_proc_reg(s, insn);
14272         break;
14273     case 0x7:
14274     case 0xf:      /* Data processing - SIMD and floating point */
14275         disas_data_proc_simd_fp(s, insn);
14276         break;
14277     default:
14278         assert(FALSE); /* all 15 cases should be handled above */
14279         break;
14280     }
14281
14282     /* if we allocated any temporaries, free them here */
14283     free_tmp_a64(s);
14284
14285     /*
14286      * After execution of most insns, btype is reset to 0.
14287      * Note that we set btype == -1 when the insn sets btype.
14288      */
14289     if (s->btype > 0 && s->base.is_jmp != DISAS_NORETURN) {
14290         reset_btype(s);
14291     }
14292 }
14293
14294 static void aarch64_tr_init_disas_context(DisasContextBase *dcbase,
14295                                           CPUState *cpu)
14296 {
14297     DisasContext *dc = container_of(dcbase, DisasContext, base);
14298     CPUARMState *env = cpu->env_ptr;
14299     ARMCPU *arm_cpu = env_archcpu(env);
14300     uint32_t tb_flags = dc->base.tb->flags;
14301     int bound, core_mmu_idx;
14302
14303     dc->isar = &arm_cpu->isar;
14304     dc->condjmp = 0;
14305
14306     dc->aarch64 = 1;
14307     /* If we are coming from secure EL0 in a system with a 32-bit EL3, then
14308      * there is no secure EL1, so we route exceptions to EL3.
14309      */
14310     dc->secure_routed_to_el3 = arm_feature(env, ARM_FEATURE_EL3) &&
14311                                !arm_el_is_aa64(env, 3);
14312     dc->thumb = 0;
14313     dc->sctlr_b = 0;
14314     dc->be_data = FIELD_EX32(tb_flags, TBFLAG_ANY, BE_DATA) ? MO_BE : MO_LE;
14315     dc->condexec_mask = 0;
14316     dc->condexec_cond = 0;
14317     core_mmu_idx = FIELD_EX32(tb_flags, TBFLAG_ANY, MMUIDX);
14318     dc->mmu_idx = core_to_aa64_mmu_idx(core_mmu_idx);
14319     dc->tbii = FIELD_EX32(tb_flags, TBFLAG_A64, TBII);
14320     dc->tbid = FIELD_EX32(tb_flags, TBFLAG_A64, TBID);
14321     dc->current_el = arm_mmu_idx_to_el(dc->mmu_idx);
14322 #if !defined(CONFIG_USER_ONLY)
14323     dc->user = (dc->current_el == 0);
14324 #endif
14325     dc->fp_excp_el = FIELD_EX32(tb_flags, TBFLAG_ANY, FPEXC_EL);
14326     dc->sve_excp_el = FIELD_EX32(tb_flags, TBFLAG_A64, SVEEXC_EL);
14327     dc->sve_len = (FIELD_EX32(tb_flags, TBFLAG_A64, ZCR_LEN) + 1) * 16;
14328     dc->pauth_active = FIELD_EX32(tb_flags, TBFLAG_A64, PAUTH_ACTIVE);
14329     dc->bt = FIELD_EX32(tb_flags, TBFLAG_A64, BT);
14330     dc->btype = FIELD_EX32(tb_flags, TBFLAG_A64, BTYPE);
14331     dc->unpriv = FIELD_EX32(tb_flags, TBFLAG_A64, UNPRIV);
14332     dc->vec_len = 0;
14333     dc->vec_stride = 0;
14334     dc->cp_regs = arm_cpu->cp_regs;
14335     dc->features = env->features;
14336
14337     /* Single step state. The code-generation logic here is:
14338      *  SS_ACTIVE == 0:
14339      *   generate code with no special handling for single-stepping (except
14340      *   that anything that can make us go to SS_ACTIVE == 1 must end the TB;
14341      *   this happens anyway because those changes are all system register or
14342      *   PSTATE writes).
14343      *  SS_ACTIVE == 1, PSTATE.SS == 1: (active-not-pending)
14344      *   emit code for one insn
14345      *   emit code to clear PSTATE.SS
14346      *   emit code to generate software step exception for completed step
14347      *   end TB (as usual for having generated an exception)
14348      *  SS_ACTIVE == 1, PSTATE.SS == 0: (active-pending)
14349      *   emit code to generate a software step exception
14350      *   end the TB
14351      */
14352     dc->ss_active = FIELD_EX32(tb_flags, TBFLAG_ANY, SS_ACTIVE);
14353     dc->pstate_ss = FIELD_EX32(tb_flags, TBFLAG_ANY, PSTATE_SS);
14354     dc->is_ldex = false;
14355     dc->debug_target_el = FIELD_EX32(tb_flags, TBFLAG_ANY, DEBUG_TARGET_EL);
14356
14357     /* Bound the number of insns to execute to those left on the page.  */
14358     bound = -(dc->base.pc_first | TARGET_PAGE_MASK) / 4;
14359
14360     /* If architectural single step active, limit to 1.  */
14361     if (dc->ss_active) {
14362         bound = 1;
14363     }
14364     dc->base.max_insns = MIN(dc->base.max_insns, bound);
14365
14366     init_tmp_a64_array(dc);
14367 }
14368
14369 static void aarch64_tr_tb_start(DisasContextBase *db, CPUState *cpu)
14370 {
14371 }
14372
14373 static void aarch64_tr_insn_start(DisasContextBase *dcbase, CPUState *cpu)
14374 {
14375     DisasContext *dc = container_of(dcbase, DisasContext, base);
14376
14377     tcg_gen_insn_start(dc->base.pc_next, 0, 0);
14378     dc->insn_start = tcg_last_op();
14379 }
14380
14381 static bool aarch64_tr_breakpoint_check(DisasContextBase *dcbase, CPUState *cpu,
14382                                         const CPUBreakpoint *bp)
14383 {
14384     DisasContext *dc = container_of(dcbase, DisasContext, base);
14385
14386     if (bp->flags & BP_CPU) {
14387         gen_a64_set_pc_im(dc->base.pc_next);
14388         gen_helper_check_breakpoints(cpu_env);
14389         /* End the TB early; it likely won't be executed */
14390         dc->base.is_jmp = DISAS_TOO_MANY;
14391     } else {
14392         gen_exception_internal_insn(dc, dc->base.pc_next, EXCP_DEBUG);
14393         /* The address covered by the breakpoint must be
14394            included in [tb->pc, tb->pc + tb->size) in order
14395            to for it to be properly cleared -- thus we
14396            increment the PC here so that the logic setting
14397            tb->size below does the right thing.  */
14398         dc->base.pc_next += 4;
14399         dc->base.is_jmp = DISAS_NORETURN;
14400     }
14401
14402     return true;
14403 }
14404
14405 static void aarch64_tr_translate_insn(DisasContextBase *dcbase, CPUState *cpu)
14406 {
14407     DisasContext *dc = container_of(dcbase, DisasContext, base);
14408     CPUARMState *env = cpu->env_ptr;
14409
14410     if (dc->ss_active && !dc->pstate_ss) {
14411         /* Singlestep state is Active-pending.
14412          * If we're in this state at the start of a TB then either
14413          *  a) we just took an exception to an EL which is being debugged
14414          *     and this is the first insn in the exception handler
14415          *  b) debug exceptions were masked and we just unmasked them
14416          *     without changing EL (eg by clearing PSTATE.D)
14417          * In either case we're going to take a swstep exception in the
14418          * "did not step an insn" case, and so the syndrome ISV and EX
14419          * bits should be zero.
14420          */
14421         assert(dc->base.num_insns == 1);
14422         gen_swstep_exception(dc, 0, 0);
14423         dc->base.is_jmp = DISAS_NORETURN;
14424     } else {
14425         disas_a64_insn(env, dc);
14426     }
14427
14428     translator_loop_temp_check(&dc->base);
14429 }
14430
14431 static void aarch64_tr_tb_stop(DisasContextBase *dcbase, CPUState *cpu)
14432 {
14433     DisasContext *dc = container_of(dcbase, DisasContext, base);
14434
14435     if (unlikely(dc->base.singlestep_enabled || dc->ss_active)) {
14436         /* Note that this means single stepping WFI doesn't halt the CPU.
14437          * For conditional branch insns this is harmless unreachable code as
14438          * gen_goto_tb() has already handled emitting the debug exception
14439          * (and thus a tb-jump is not possible when singlestepping).
14440          */
14441         switch (dc->base.is_jmp) {
14442         default:
14443             gen_a64_set_pc_im(dc->base.pc_next);
14444             /* fall through */
14445         case DISAS_EXIT:
14446         case DISAS_JUMP:
14447             if (dc->base.singlestep_enabled) {
14448                 gen_exception_internal(EXCP_DEBUG);
14449             } else {
14450                 gen_step_complete_exception(dc);
14451             }
14452             break;
14453         case DISAS_NORETURN:
14454             break;
14455         }
14456     } else {
14457         switch (dc->base.is_jmp) {
14458         case DISAS_NEXT:
14459         case DISAS_TOO_MANY:
14460             gen_goto_tb(dc, 1, dc->base.pc_next);
14461             break;
14462         default:
14463         case DISAS_UPDATE:
14464             gen_a64_set_pc_im(dc->base.pc_next);
14465             /* fall through */
14466         case DISAS_EXIT:
14467             tcg_gen_exit_tb(NULL, 0);
14468             break;
14469         case DISAS_JUMP:
14470             tcg_gen_lookup_and_goto_ptr();
14471             break;
14472         case DISAS_NORETURN:
14473         case DISAS_SWI:
14474             break;
14475         case DISAS_WFE:
14476             gen_a64_set_pc_im(dc->base.pc_next);
14477             gen_helper_wfe(cpu_env);
14478             break;
14479         case DISAS_YIELD:
14480             gen_a64_set_pc_im(dc->base.pc_next);
14481             gen_helper_yield(cpu_env);
14482             break;
14483         case DISAS_WFI:
14484         {
14485             /* This is a special case because we don't want to just halt the CPU
14486              * if trying to debug across a WFI.
14487              */
14488             TCGv_i32 tmp = tcg_const_i32(4);
14489
14490             gen_a64_set_pc_im(dc->base.pc_next);
14491             gen_helper_wfi(cpu_env, tmp);
14492             tcg_temp_free_i32(tmp);
14493             /* The helper doesn't necessarily throw an exception, but we
14494              * must go back to the main loop to check for interrupts anyway.
14495              */
14496             tcg_gen_exit_tb(NULL, 0);
14497             break;
14498         }
14499         }
14500     }
14501 }
14502
14503 static void aarch64_tr_disas_log(const DisasContextBase *dcbase,
14504                                       CPUState *cpu)
14505 {
14506     DisasContext *dc = container_of(dcbase, DisasContext, base);
14507
14508     qemu_log("IN: %s\n", lookup_symbol(dc->base.pc_first));
14509     log_target_disas(cpu, dc->base.pc_first, dc->base.tb->size);
14510 }
14511
14512 const TranslatorOps aarch64_translator_ops = {
14513     .init_disas_context = aarch64_tr_init_disas_context,
14514     .tb_start           = aarch64_tr_tb_start,
14515     .insn_start         = aarch64_tr_insn_start,
14516     .breakpoint_check   = aarch64_tr_breakpoint_check,
14517     .translate_insn     = aarch64_tr_translate_insn,
14518     .tb_stop            = aarch64_tr_tb_stop,
14519     .disas_log          = aarch64_tr_disas_log,
14520 };
This page took 0.817354 seconds and 4 git commands to generate.