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