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