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