target/arm: Implement VFP fp16 VLDR and VSTR
[qemu.git] / target / arm / translate-vfp.c.inc
1 /*
2  *  ARM translation: AArch32 VFP instructions
3  *
4  *  Copyright (c) 2003 Fabrice Bellard
5  *  Copyright (c) 2005-2007 CodeSourcery
6  *  Copyright (c) 2007 OpenedHand, Ltd.
7  *  Copyright (c) 2019 Linaro, Ltd.
8  *
9  * This library is free software; you can redistribute it and/or
10  * modify it under the terms of the GNU Lesser General Public
11  * License as published by the Free Software Foundation; either
12  * version 2 of the License, or (at your option) any later version.
13  *
14  * This library is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17  * Lesser General Public License for more details.
18  *
19  * You should have received a copy of the GNU Lesser General Public
20  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
21  */
22
23 /*
24  * This file is intended to be included from translate.c; it uses
25  * some macros and definitions provided by that file.
26  * It might be possible to convert it to a standalone .c file eventually.
27  */
28
29 /* Include the generated VFP decoder */
30 #include "decode-vfp.c.inc"
31 #include "decode-vfp-uncond.c.inc"
32
33 /*
34  * The imm8 encodes the sign bit, enough bits to represent an exponent in
35  * the range 01....1xx to 10....0xx, and the most significant 4 bits of
36  * the mantissa; see VFPExpandImm() in the v8 ARM ARM.
37  */
38 uint64_t vfp_expand_imm(int size, uint8_t imm8)
39 {
40     uint64_t imm;
41
42     switch (size) {
43     case MO_64:
44         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
45             (extract32(imm8, 6, 1) ? 0x3fc0 : 0x4000) |
46             extract32(imm8, 0, 6);
47         imm <<= 48;
48         break;
49     case MO_32:
50         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
51             (extract32(imm8, 6, 1) ? 0x3e00 : 0x4000) |
52             (extract32(imm8, 0, 6) << 3);
53         imm <<= 16;
54         break;
55     case MO_16:
56         imm = (extract32(imm8, 7, 1) ? 0x8000 : 0) |
57             (extract32(imm8, 6, 1) ? 0x3000 : 0x4000) |
58             (extract32(imm8, 0, 6) << 6);
59         break;
60     default:
61         g_assert_not_reached();
62     }
63     return imm;
64 }
65
66 /*
67  * Return the offset of a 16-bit half of the specified VFP single-precision
68  * register. If top is true, returns the top 16 bits; otherwise the bottom
69  * 16 bits.
70  */
71 static inline long vfp_f16_offset(unsigned reg, bool top)
72 {
73     long offs = vfp_reg_offset(false, reg);
74 #ifdef HOST_WORDS_BIGENDIAN
75     if (!top) {
76         offs += 2;
77     }
78 #else
79     if (top) {
80         offs += 2;
81     }
82 #endif
83     return offs;
84 }
85
86 /*
87  * Check that VFP access is enabled. If it is, do the necessary
88  * M-profile lazy-FP handling and then return true.
89  * If not, emit code to generate an appropriate exception and
90  * return false.
91  * The ignore_vfp_enabled argument specifies that we should ignore
92  * whether VFP is enabled via FPEXC[EN]: this should be true for FMXR/FMRX
93  * accesses to FPSID, FPEXC, MVFR0, MVFR1, MVFR2, and false for all other insns.
94  */
95 static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
96 {
97     if (s->fp_excp_el) {
98         /* M-profile handled this earlier, in disas_m_nocp() */
99         assert (!arm_dc_feature(s, ARM_FEATURE_M));
100         gen_exception_insn(s, s->pc_curr, EXCP_UDEF,
101                            syn_fp_access_trap(1, 0xe, false),
102                            s->fp_excp_el);
103         return false;
104     }
105
106     if (!s->vfp_enabled && !ignore_vfp_enabled) {
107         assert(!arm_dc_feature(s, ARM_FEATURE_M));
108         unallocated_encoding(s);
109         return false;
110     }
111
112     if (arm_dc_feature(s, ARM_FEATURE_M)) {
113         /* Handle M-profile lazy FP state mechanics */
114
115         /* Trigger lazy-state preservation if necessary */
116         if (s->v7m_lspact) {
117             /*
118              * Lazy state saving affects external memory and also the NVIC,
119              * so we must mark it as an IO operation for icount (and cause
120              * this to be the last insn in the TB).
121              */
122             if (tb_cflags(s->base.tb) & CF_USE_ICOUNT) {
123                 s->base.is_jmp = DISAS_UPDATE_EXIT;
124                 gen_io_start();
125             }
126             gen_helper_v7m_preserve_fp_state(cpu_env);
127             /*
128              * If the preserve_fp_state helper doesn't throw an exception
129              * then it will clear LSPACT; we don't need to repeat this for
130              * any further FP insns in this TB.
131              */
132             s->v7m_lspact = false;
133         }
134
135         /* Update ownership of FP context: set FPCCR.S to match current state */
136         if (s->v8m_fpccr_s_wrong) {
137             TCGv_i32 tmp;
138
139             tmp = load_cpu_field(v7m.fpccr[M_REG_S]);
140             if (s->v8m_secure) {
141                 tcg_gen_ori_i32(tmp, tmp, R_V7M_FPCCR_S_MASK);
142             } else {
143                 tcg_gen_andi_i32(tmp, tmp, ~R_V7M_FPCCR_S_MASK);
144             }
145             store_cpu_field(tmp, v7m.fpccr[M_REG_S]);
146             /* Don't need to do this for any further FP insns in this TB */
147             s->v8m_fpccr_s_wrong = false;
148         }
149
150         if (s->v7m_new_fp_ctxt_needed) {
151             /*
152              * Create new FP context by updating CONTROL.FPCA, CONTROL.SFPA
153              * and the FPSCR.
154              */
155             TCGv_i32 control, fpscr;
156             uint32_t bits = R_V7M_CONTROL_FPCA_MASK;
157
158             fpscr = load_cpu_field(v7m.fpdscr[s->v8m_secure]);
159             gen_helper_vfp_set_fpscr(cpu_env, fpscr);
160             tcg_temp_free_i32(fpscr);
161             /*
162              * We don't need to arrange to end the TB, because the only
163              * parts of FPSCR which we cache in the TB flags are the VECLEN
164              * and VECSTRIDE, and those don't exist for M-profile.
165              */
166
167             if (s->v8m_secure) {
168                 bits |= R_V7M_CONTROL_SFPA_MASK;
169             }
170             control = load_cpu_field(v7m.control[M_REG_S]);
171             tcg_gen_ori_i32(control, control, bits);
172             store_cpu_field(control, v7m.control[M_REG_S]);
173             /* Don't need to do this for any further FP insns in this TB */
174             s->v7m_new_fp_ctxt_needed = false;
175         }
176     }
177
178     return true;
179 }
180
181 /*
182  * The most usual kind of VFP access check, for everything except
183  * FMXR/FMRX to the always-available special registers.
184  */
185 static bool vfp_access_check(DisasContext *s)
186 {
187     return full_vfp_access_check(s, false);
188 }
189
190 static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
191 {
192     uint32_t rd, rn, rm;
193     bool dp = a->dp;
194
195     if (!dc_isar_feature(aa32_vsel, s)) {
196         return false;
197     }
198
199     if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
200         return false;
201     }
202
203     /* UNDEF accesses to D16-D31 if they don't exist */
204     if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
205         ((a->vm | a->vn | a->vd) & 0x10)) {
206         return false;
207     }
208
209     rd = a->vd;
210     rn = a->vn;
211     rm = a->vm;
212
213     if (!vfp_access_check(s)) {
214         return true;
215     }
216
217     if (dp) {
218         TCGv_i64 frn, frm, dest;
219         TCGv_i64 tmp, zero, zf, nf, vf;
220
221         zero = tcg_const_i64(0);
222
223         frn = tcg_temp_new_i64();
224         frm = tcg_temp_new_i64();
225         dest = tcg_temp_new_i64();
226
227         zf = tcg_temp_new_i64();
228         nf = tcg_temp_new_i64();
229         vf = tcg_temp_new_i64();
230
231         tcg_gen_extu_i32_i64(zf, cpu_ZF);
232         tcg_gen_ext_i32_i64(nf, cpu_NF);
233         tcg_gen_ext_i32_i64(vf, cpu_VF);
234
235         neon_load_reg64(frn, rn);
236         neon_load_reg64(frm, rm);
237         switch (a->cc) {
238         case 0: /* eq: Z */
239             tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
240                                 frn, frm);
241             break;
242         case 1: /* vs: V */
243             tcg_gen_movcond_i64(TCG_COND_LT, dest, vf, zero,
244                                 frn, frm);
245             break;
246         case 2: /* ge: N == V -> N ^ V == 0 */
247             tmp = tcg_temp_new_i64();
248             tcg_gen_xor_i64(tmp, vf, nf);
249             tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
250                                 frn, frm);
251             tcg_temp_free_i64(tmp);
252             break;
253         case 3: /* gt: !Z && N == V */
254             tcg_gen_movcond_i64(TCG_COND_NE, dest, zf, zero,
255                                 frn, frm);
256             tmp = tcg_temp_new_i64();
257             tcg_gen_xor_i64(tmp, vf, nf);
258             tcg_gen_movcond_i64(TCG_COND_GE, dest, tmp, zero,
259                                 dest, frm);
260             tcg_temp_free_i64(tmp);
261             break;
262         }
263         neon_store_reg64(dest, rd);
264         tcg_temp_free_i64(frn);
265         tcg_temp_free_i64(frm);
266         tcg_temp_free_i64(dest);
267
268         tcg_temp_free_i64(zf);
269         tcg_temp_free_i64(nf);
270         tcg_temp_free_i64(vf);
271
272         tcg_temp_free_i64(zero);
273     } else {
274         TCGv_i32 frn, frm, dest;
275         TCGv_i32 tmp, zero;
276
277         zero = tcg_const_i32(0);
278
279         frn = tcg_temp_new_i32();
280         frm = tcg_temp_new_i32();
281         dest = tcg_temp_new_i32();
282         neon_load_reg32(frn, rn);
283         neon_load_reg32(frm, rm);
284         switch (a->cc) {
285         case 0: /* eq: Z */
286             tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
287                                 frn, frm);
288             break;
289         case 1: /* vs: V */
290             tcg_gen_movcond_i32(TCG_COND_LT, dest, cpu_VF, zero,
291                                 frn, frm);
292             break;
293         case 2: /* ge: N == V -> N ^ V == 0 */
294             tmp = tcg_temp_new_i32();
295             tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
296             tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
297                                 frn, frm);
298             tcg_temp_free_i32(tmp);
299             break;
300         case 3: /* gt: !Z && N == V */
301             tcg_gen_movcond_i32(TCG_COND_NE, dest, cpu_ZF, zero,
302                                 frn, frm);
303             tmp = tcg_temp_new_i32();
304             tcg_gen_xor_i32(tmp, cpu_VF, cpu_NF);
305             tcg_gen_movcond_i32(TCG_COND_GE, dest, tmp, zero,
306                                 dest, frm);
307             tcg_temp_free_i32(tmp);
308             break;
309         }
310         neon_store_reg32(dest, rd);
311         tcg_temp_free_i32(frn);
312         tcg_temp_free_i32(frm);
313         tcg_temp_free_i32(dest);
314
315         tcg_temp_free_i32(zero);
316     }
317
318     return true;
319 }
320
321 /*
322  * Table for converting the most common AArch32 encoding of
323  * rounding mode to arm_fprounding order (which matches the
324  * common AArch64 order); see ARM ARM pseudocode FPDecodeRM().
325  */
326 static const uint8_t fp_decode_rm[] = {
327     FPROUNDING_TIEAWAY,
328     FPROUNDING_TIEEVEN,
329     FPROUNDING_POSINF,
330     FPROUNDING_NEGINF,
331 };
332
333 static bool trans_VRINT(DisasContext *s, arg_VRINT *a)
334 {
335     uint32_t rd, rm;
336     bool dp = a->dp;
337     TCGv_ptr fpst;
338     TCGv_i32 tcg_rmode;
339     int rounding = fp_decode_rm[a->rm];
340
341     if (!dc_isar_feature(aa32_vrint, s)) {
342         return false;
343     }
344
345     if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
346         return false;
347     }
348
349     /* UNDEF accesses to D16-D31 if they don't exist */
350     if (dp && !dc_isar_feature(aa32_simd_r32, s) &&
351         ((a->vm | a->vd) & 0x10)) {
352         return false;
353     }
354
355     rd = a->vd;
356     rm = a->vm;
357
358     if (!vfp_access_check(s)) {
359         return true;
360     }
361
362     fpst = fpstatus_ptr(FPST_FPCR);
363
364     tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
365     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
366
367     if (dp) {
368         TCGv_i64 tcg_op;
369         TCGv_i64 tcg_res;
370         tcg_op = tcg_temp_new_i64();
371         tcg_res = tcg_temp_new_i64();
372         neon_load_reg64(tcg_op, rm);
373         gen_helper_rintd(tcg_res, tcg_op, fpst);
374         neon_store_reg64(tcg_res, rd);
375         tcg_temp_free_i64(tcg_op);
376         tcg_temp_free_i64(tcg_res);
377     } else {
378         TCGv_i32 tcg_op;
379         TCGv_i32 tcg_res;
380         tcg_op = tcg_temp_new_i32();
381         tcg_res = tcg_temp_new_i32();
382         neon_load_reg32(tcg_op, rm);
383         gen_helper_rints(tcg_res, tcg_op, fpst);
384         neon_store_reg32(tcg_res, rd);
385         tcg_temp_free_i32(tcg_op);
386         tcg_temp_free_i32(tcg_res);
387     }
388
389     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
390     tcg_temp_free_i32(tcg_rmode);
391
392     tcg_temp_free_ptr(fpst);
393     return true;
394 }
395
396 static bool trans_VCVT(DisasContext *s, arg_VCVT *a)
397 {
398     uint32_t rd, rm;
399     bool dp = a->dp;
400     TCGv_ptr fpst;
401     TCGv_i32 tcg_rmode, tcg_shift;
402     int rounding = fp_decode_rm[a->rm];
403     bool is_signed = a->op;
404
405     if (!dc_isar_feature(aa32_vcvt_dr, s)) {
406         return false;
407     }
408
409     if (dp && !dc_isar_feature(aa32_fpdp_v2, s)) {
410         return false;
411     }
412
413     /* UNDEF accesses to D16-D31 if they don't exist */
414     if (dp && !dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
415         return false;
416     }
417
418     rd = a->vd;
419     rm = a->vm;
420
421     if (!vfp_access_check(s)) {
422         return true;
423     }
424
425     fpst = fpstatus_ptr(FPST_FPCR);
426
427     tcg_shift = tcg_const_i32(0);
428
429     tcg_rmode = tcg_const_i32(arm_rmode_to_sf(rounding));
430     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
431
432     if (dp) {
433         TCGv_i64 tcg_double, tcg_res;
434         TCGv_i32 tcg_tmp;
435         tcg_double = tcg_temp_new_i64();
436         tcg_res = tcg_temp_new_i64();
437         tcg_tmp = tcg_temp_new_i32();
438         neon_load_reg64(tcg_double, rm);
439         if (is_signed) {
440             gen_helper_vfp_tosld(tcg_res, tcg_double, tcg_shift, fpst);
441         } else {
442             gen_helper_vfp_tould(tcg_res, tcg_double, tcg_shift, fpst);
443         }
444         tcg_gen_extrl_i64_i32(tcg_tmp, tcg_res);
445         neon_store_reg32(tcg_tmp, rd);
446         tcg_temp_free_i32(tcg_tmp);
447         tcg_temp_free_i64(tcg_res);
448         tcg_temp_free_i64(tcg_double);
449     } else {
450         TCGv_i32 tcg_single, tcg_res;
451         tcg_single = tcg_temp_new_i32();
452         tcg_res = tcg_temp_new_i32();
453         neon_load_reg32(tcg_single, rm);
454         if (is_signed) {
455             gen_helper_vfp_tosls(tcg_res, tcg_single, tcg_shift, fpst);
456         } else {
457             gen_helper_vfp_touls(tcg_res, tcg_single, tcg_shift, fpst);
458         }
459         neon_store_reg32(tcg_res, rd);
460         tcg_temp_free_i32(tcg_res);
461         tcg_temp_free_i32(tcg_single);
462     }
463
464     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
465     tcg_temp_free_i32(tcg_rmode);
466
467     tcg_temp_free_i32(tcg_shift);
468
469     tcg_temp_free_ptr(fpst);
470
471     return true;
472 }
473
474 static bool trans_VMOV_to_gp(DisasContext *s, arg_VMOV_to_gp *a)
475 {
476     /* VMOV scalar to general purpose register */
477     TCGv_i32 tmp;
478     int pass;
479     uint32_t offset;
480
481     /* SIZE == 2 is a VFP instruction; otherwise NEON.  */
482     if (a->size == 2
483         ? !dc_isar_feature(aa32_fpsp_v2, s)
484         : !arm_dc_feature(s, ARM_FEATURE_NEON)) {
485         return false;
486     }
487
488     /* UNDEF accesses to D16-D31 if they don't exist */
489     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
490         return false;
491     }
492
493     offset = a->index << a->size;
494     pass = extract32(offset, 2, 1);
495     offset = extract32(offset, 0, 2) * 8;
496
497     if (!vfp_access_check(s)) {
498         return true;
499     }
500
501     tmp = neon_load_reg(a->vn, pass);
502     switch (a->size) {
503     case 0:
504         if (offset) {
505             tcg_gen_shri_i32(tmp, tmp, offset);
506         }
507         if (a->u) {
508             gen_uxtb(tmp);
509         } else {
510             gen_sxtb(tmp);
511         }
512         break;
513     case 1:
514         if (a->u) {
515             if (offset) {
516                 tcg_gen_shri_i32(tmp, tmp, 16);
517             } else {
518                 gen_uxth(tmp);
519             }
520         } else {
521             if (offset) {
522                 tcg_gen_sari_i32(tmp, tmp, 16);
523             } else {
524                 gen_sxth(tmp);
525             }
526         }
527         break;
528     case 2:
529         break;
530     }
531     store_reg(s, a->rt, tmp);
532
533     return true;
534 }
535
536 static bool trans_VMOV_from_gp(DisasContext *s, arg_VMOV_from_gp *a)
537 {
538     /* VMOV general purpose register to scalar */
539     TCGv_i32 tmp, tmp2;
540     int pass;
541     uint32_t offset;
542
543     /* SIZE == 2 is a VFP instruction; otherwise NEON.  */
544     if (a->size == 2
545         ? !dc_isar_feature(aa32_fpsp_v2, s)
546         : !arm_dc_feature(s, ARM_FEATURE_NEON)) {
547         return false;
548     }
549
550     /* UNDEF accesses to D16-D31 if they don't exist */
551     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
552         return false;
553     }
554
555     offset = a->index << a->size;
556     pass = extract32(offset, 2, 1);
557     offset = extract32(offset, 0, 2) * 8;
558
559     if (!vfp_access_check(s)) {
560         return true;
561     }
562
563     tmp = load_reg(s, a->rt);
564     switch (a->size) {
565     case 0:
566         tmp2 = neon_load_reg(a->vn, pass);
567         tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 8);
568         tcg_temp_free_i32(tmp2);
569         break;
570     case 1:
571         tmp2 = neon_load_reg(a->vn, pass);
572         tcg_gen_deposit_i32(tmp, tmp2, tmp, offset, 16);
573         tcg_temp_free_i32(tmp2);
574         break;
575     case 2:
576         break;
577     }
578     neon_store_reg(a->vn, pass, tmp);
579
580     return true;
581 }
582
583 static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
584 {
585     /* VDUP (general purpose register) */
586     TCGv_i32 tmp;
587     int size, vec_size;
588
589     if (!arm_dc_feature(s, ARM_FEATURE_NEON)) {
590         return false;
591     }
592
593     /* UNDEF accesses to D16-D31 if they don't exist */
594     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vn & 0x10)) {
595         return false;
596     }
597
598     if (a->b && a->e) {
599         return false;
600     }
601
602     if (a->q && (a->vn & 1)) {
603         return false;
604     }
605
606     vec_size = a->q ? 16 : 8;
607     if (a->b) {
608         size = 0;
609     } else if (a->e) {
610         size = 1;
611     } else {
612         size = 2;
613     }
614
615     if (!vfp_access_check(s)) {
616         return true;
617     }
618
619     tmp = load_reg(s, a->rt);
620     tcg_gen_gvec_dup_i32(size, neon_reg_offset(a->vn, 0),
621                          vec_size, vec_size, tmp);
622     tcg_temp_free_i32(tmp);
623
624     return true;
625 }
626
627 static bool trans_VMSR_VMRS(DisasContext *s, arg_VMSR_VMRS *a)
628 {
629     TCGv_i32 tmp;
630     bool ignore_vfp_enabled = false;
631
632     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
633         return false;
634     }
635
636     if (arm_dc_feature(s, ARM_FEATURE_M)) {
637         /*
638          * The only M-profile VFP vmrs/vmsr sysreg is FPSCR.
639          * Accesses to R15 are UNPREDICTABLE; we choose to undef.
640          * (FPSCR -> r15 is a special case which writes to the PSR flags.)
641          */
642         if (a->rt == 15 && (!a->l || a->reg != ARM_VFP_FPSCR)) {
643             return false;
644         }
645     }
646
647     switch (a->reg) {
648     case ARM_VFP_FPSID:
649         /*
650          * VFPv2 allows access to FPSID from userspace; VFPv3 restricts
651          * all ID registers to privileged access only.
652          */
653         if (IS_USER(s) && dc_isar_feature(aa32_fpsp_v3, s)) {
654             return false;
655         }
656         ignore_vfp_enabled = true;
657         break;
658     case ARM_VFP_MVFR0:
659     case ARM_VFP_MVFR1:
660         if (IS_USER(s) || !arm_dc_feature(s, ARM_FEATURE_MVFR)) {
661             return false;
662         }
663         ignore_vfp_enabled = true;
664         break;
665     case ARM_VFP_MVFR2:
666         if (IS_USER(s) || !arm_dc_feature(s, ARM_FEATURE_V8)) {
667             return false;
668         }
669         ignore_vfp_enabled = true;
670         break;
671     case ARM_VFP_FPSCR:
672         break;
673     case ARM_VFP_FPEXC:
674         if (IS_USER(s)) {
675             return false;
676         }
677         ignore_vfp_enabled = true;
678         break;
679     case ARM_VFP_FPINST:
680     case ARM_VFP_FPINST2:
681         /* Not present in VFPv3 */
682         if (IS_USER(s) || dc_isar_feature(aa32_fpsp_v3, s)) {
683             return false;
684         }
685         break;
686     default:
687         return false;
688     }
689
690     if (!full_vfp_access_check(s, ignore_vfp_enabled)) {
691         return true;
692     }
693
694     if (a->l) {
695         /* VMRS, move VFP special register to gp register */
696         switch (a->reg) {
697         case ARM_VFP_MVFR0:
698         case ARM_VFP_MVFR1:
699         case ARM_VFP_MVFR2:
700         case ARM_VFP_FPSID:
701             if (s->current_el == 1) {
702                 TCGv_i32 tcg_reg, tcg_rt;
703
704                 gen_set_condexec(s);
705                 gen_set_pc_im(s, s->pc_curr);
706                 tcg_reg = tcg_const_i32(a->reg);
707                 tcg_rt = tcg_const_i32(a->rt);
708                 gen_helper_check_hcr_el2_trap(cpu_env, tcg_rt, tcg_reg);
709                 tcg_temp_free_i32(tcg_reg);
710                 tcg_temp_free_i32(tcg_rt);
711             }
712             /* fall through */
713         case ARM_VFP_FPEXC:
714         case ARM_VFP_FPINST:
715         case ARM_VFP_FPINST2:
716             tmp = load_cpu_field(vfp.xregs[a->reg]);
717             break;
718         case ARM_VFP_FPSCR:
719             if (a->rt == 15) {
720                 tmp = load_cpu_field(vfp.xregs[ARM_VFP_FPSCR]);
721                 tcg_gen_andi_i32(tmp, tmp, 0xf0000000);
722             } else {
723                 tmp = tcg_temp_new_i32();
724                 gen_helper_vfp_get_fpscr(tmp, cpu_env);
725             }
726             break;
727         default:
728             g_assert_not_reached();
729         }
730
731         if (a->rt == 15) {
732             /* Set the 4 flag bits in the CPSR.  */
733             gen_set_nzcv(tmp);
734             tcg_temp_free_i32(tmp);
735         } else {
736             store_reg(s, a->rt, tmp);
737         }
738     } else {
739         /* VMSR, move gp register to VFP special register */
740         switch (a->reg) {
741         case ARM_VFP_FPSID:
742         case ARM_VFP_MVFR0:
743         case ARM_VFP_MVFR1:
744         case ARM_VFP_MVFR2:
745             /* Writes are ignored.  */
746             break;
747         case ARM_VFP_FPSCR:
748             tmp = load_reg(s, a->rt);
749             gen_helper_vfp_set_fpscr(cpu_env, tmp);
750             tcg_temp_free_i32(tmp);
751             gen_lookup_tb(s);
752             break;
753         case ARM_VFP_FPEXC:
754             /*
755              * TODO: VFP subarchitecture support.
756              * For now, keep the EN bit only
757              */
758             tmp = load_reg(s, a->rt);
759             tcg_gen_andi_i32(tmp, tmp, 1 << 30);
760             store_cpu_field(tmp, vfp.xregs[a->reg]);
761             gen_lookup_tb(s);
762             break;
763         case ARM_VFP_FPINST:
764         case ARM_VFP_FPINST2:
765             tmp = load_reg(s, a->rt);
766             store_cpu_field(tmp, vfp.xregs[a->reg]);
767             break;
768         default:
769             g_assert_not_reached();
770         }
771     }
772
773     return true;
774 }
775
776 static bool trans_VMOV_single(DisasContext *s, arg_VMOV_single *a)
777 {
778     TCGv_i32 tmp;
779
780     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
781         return false;
782     }
783
784     if (!vfp_access_check(s)) {
785         return true;
786     }
787
788     if (a->l) {
789         /* VFP to general purpose register */
790         tmp = tcg_temp_new_i32();
791         neon_load_reg32(tmp, a->vn);
792         if (a->rt == 15) {
793             /* Set the 4 flag bits in the CPSR.  */
794             gen_set_nzcv(tmp);
795             tcg_temp_free_i32(tmp);
796         } else {
797             store_reg(s, a->rt, tmp);
798         }
799     } else {
800         /* general purpose register to VFP */
801         tmp = load_reg(s, a->rt);
802         neon_store_reg32(tmp, a->vn);
803         tcg_temp_free_i32(tmp);
804     }
805
806     return true;
807 }
808
809 static bool trans_VMOV_64_sp(DisasContext *s, arg_VMOV_64_sp *a)
810 {
811     TCGv_i32 tmp;
812
813     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
814         return false;
815     }
816
817     /*
818      * VMOV between two general-purpose registers and two single precision
819      * floating point registers
820      */
821     if (!vfp_access_check(s)) {
822         return true;
823     }
824
825     if (a->op) {
826         /* fpreg to gpreg */
827         tmp = tcg_temp_new_i32();
828         neon_load_reg32(tmp, a->vm);
829         store_reg(s, a->rt, tmp);
830         tmp = tcg_temp_new_i32();
831         neon_load_reg32(tmp, a->vm + 1);
832         store_reg(s, a->rt2, tmp);
833     } else {
834         /* gpreg to fpreg */
835         tmp = load_reg(s, a->rt);
836         neon_store_reg32(tmp, a->vm);
837         tcg_temp_free_i32(tmp);
838         tmp = load_reg(s, a->rt2);
839         neon_store_reg32(tmp, a->vm + 1);
840         tcg_temp_free_i32(tmp);
841     }
842
843     return true;
844 }
845
846 static bool trans_VMOV_64_dp(DisasContext *s, arg_VMOV_64_dp *a)
847 {
848     TCGv_i32 tmp;
849
850     /*
851      * VMOV between two general-purpose registers and one double precision
852      * floating point register.  Note that this does not require support
853      * for double precision arithmetic.
854      */
855     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
856         return false;
857     }
858
859     /* UNDEF accesses to D16-D31 if they don't exist */
860     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
861         return false;
862     }
863
864     if (!vfp_access_check(s)) {
865         return true;
866     }
867
868     if (a->op) {
869         /* fpreg to gpreg */
870         tmp = tcg_temp_new_i32();
871         neon_load_reg32(tmp, a->vm * 2);
872         store_reg(s, a->rt, tmp);
873         tmp = tcg_temp_new_i32();
874         neon_load_reg32(tmp, a->vm * 2 + 1);
875         store_reg(s, a->rt2, tmp);
876     } else {
877         /* gpreg to fpreg */
878         tmp = load_reg(s, a->rt);
879         neon_store_reg32(tmp, a->vm * 2);
880         tcg_temp_free_i32(tmp);
881         tmp = load_reg(s, a->rt2);
882         neon_store_reg32(tmp, a->vm * 2 + 1);
883         tcg_temp_free_i32(tmp);
884     }
885
886     return true;
887 }
888
889 static bool trans_VLDR_VSTR_hp(DisasContext *s, arg_VLDR_VSTR_sp *a)
890 {
891     uint32_t offset;
892     TCGv_i32 addr, tmp;
893
894     if (!dc_isar_feature(aa32_fp16_arith, s)) {
895         return false;
896     }
897
898     if (!vfp_access_check(s)) {
899         return true;
900     }
901
902     /* imm8 field is offset/2 for fp16, unlike fp32 and fp64 */
903     offset = a->imm << 1;
904     if (!a->u) {
905         offset = -offset;
906     }
907
908     /* For thumb, use of PC is UNPREDICTABLE.  */
909     addr = add_reg_for_lit(s, a->rn, offset);
910     tmp = tcg_temp_new_i32();
911     if (a->l) {
912         gen_aa32_ld16u(s, tmp, addr, get_mem_index(s));
913         neon_store_reg32(tmp, a->vd);
914     } else {
915         neon_load_reg32(tmp, a->vd);
916         gen_aa32_st16(s, tmp, addr, get_mem_index(s));
917     }
918     tcg_temp_free_i32(tmp);
919     tcg_temp_free_i32(addr);
920
921     return true;
922 }
923
924 static bool trans_VLDR_VSTR_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
925 {
926     uint32_t offset;
927     TCGv_i32 addr, tmp;
928
929     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
930         return false;
931     }
932
933     if (!vfp_access_check(s)) {
934         return true;
935     }
936
937     offset = a->imm << 2;
938     if (!a->u) {
939         offset = -offset;
940     }
941
942     /* For thumb, use of PC is UNPREDICTABLE.  */
943     addr = add_reg_for_lit(s, a->rn, offset);
944     tmp = tcg_temp_new_i32();
945     if (a->l) {
946         gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
947         neon_store_reg32(tmp, a->vd);
948     } else {
949         neon_load_reg32(tmp, a->vd);
950         gen_aa32_st32(s, tmp, addr, get_mem_index(s));
951     }
952     tcg_temp_free_i32(tmp);
953     tcg_temp_free_i32(addr);
954
955     return true;
956 }
957
958 static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
959 {
960     uint32_t offset;
961     TCGv_i32 addr;
962     TCGv_i64 tmp;
963
964     /* Note that this does not require support for double arithmetic.  */
965     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
966         return false;
967     }
968
969     /* UNDEF accesses to D16-D31 if they don't exist */
970     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
971         return false;
972     }
973
974     if (!vfp_access_check(s)) {
975         return true;
976     }
977
978     offset = a->imm << 2;
979     if (!a->u) {
980         offset = -offset;
981     }
982
983     /* For thumb, use of PC is UNPREDICTABLE.  */
984     addr = add_reg_for_lit(s, a->rn, offset);
985     tmp = tcg_temp_new_i64();
986     if (a->l) {
987         gen_aa32_ld64(s, tmp, addr, get_mem_index(s));
988         neon_store_reg64(tmp, a->vd);
989     } else {
990         neon_load_reg64(tmp, a->vd);
991         gen_aa32_st64(s, tmp, addr, get_mem_index(s));
992     }
993     tcg_temp_free_i64(tmp);
994     tcg_temp_free_i32(addr);
995
996     return true;
997 }
998
999 static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a)
1000 {
1001     uint32_t offset;
1002     TCGv_i32 addr, tmp;
1003     int i, n;
1004
1005     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1006         return false;
1007     }
1008
1009     n = a->imm;
1010
1011     if (n == 0 || (a->vd + n) > 32) {
1012         /*
1013          * UNPREDICTABLE cases for bad immediates: we choose to
1014          * UNDEF to avoid generating huge numbers of TCG ops
1015          */
1016         return false;
1017     }
1018     if (a->rn == 15 && a->w) {
1019         /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
1020         return false;
1021     }
1022
1023     if (!vfp_access_check(s)) {
1024         return true;
1025     }
1026
1027     /* For thumb, use of PC is UNPREDICTABLE.  */
1028     addr = add_reg_for_lit(s, a->rn, 0);
1029     if (a->p) {
1030         /* pre-decrement */
1031         tcg_gen_addi_i32(addr, addr, -(a->imm << 2));
1032     }
1033
1034     if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1035         /*
1036          * Here 'addr' is the lowest address we will store to,
1037          * and is either the old SP (if post-increment) or
1038          * the new SP (if pre-decrement). For post-increment
1039          * where the old value is below the limit and the new
1040          * value is above, it is UNKNOWN whether the limit check
1041          * triggers; we choose to trigger.
1042          */
1043         gen_helper_v8m_stackcheck(cpu_env, addr);
1044     }
1045
1046     offset = 4;
1047     tmp = tcg_temp_new_i32();
1048     for (i = 0; i < n; i++) {
1049         if (a->l) {
1050             /* load */
1051             gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1052             neon_store_reg32(tmp, a->vd + i);
1053         } else {
1054             /* store */
1055             neon_load_reg32(tmp, a->vd + i);
1056             gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1057         }
1058         tcg_gen_addi_i32(addr, addr, offset);
1059     }
1060     tcg_temp_free_i32(tmp);
1061     if (a->w) {
1062         /* writeback */
1063         if (a->p) {
1064             offset = -offset * n;
1065             tcg_gen_addi_i32(addr, addr, offset);
1066         }
1067         store_reg(s, a->rn, addr);
1068     } else {
1069         tcg_temp_free_i32(addr);
1070     }
1071
1072     return true;
1073 }
1074
1075 static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
1076 {
1077     uint32_t offset;
1078     TCGv_i32 addr;
1079     TCGv_i64 tmp;
1080     int i, n;
1081
1082     /* Note that this does not require support for double arithmetic.  */
1083     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1084         return false;
1085     }
1086
1087     n = a->imm >> 1;
1088
1089     if (n == 0 || (a->vd + n) > 32 || n > 16) {
1090         /*
1091          * UNPREDICTABLE cases for bad immediates: we choose to
1092          * UNDEF to avoid generating huge numbers of TCG ops
1093          */
1094         return false;
1095     }
1096     if (a->rn == 15 && a->w) {
1097         /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
1098         return false;
1099     }
1100
1101     /* UNDEF accesses to D16-D31 if they don't exist */
1102     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd + n) > 16) {
1103         return false;
1104     }
1105
1106     if (!vfp_access_check(s)) {
1107         return true;
1108     }
1109
1110     /* For thumb, use of PC is UNPREDICTABLE.  */
1111     addr = add_reg_for_lit(s, a->rn, 0);
1112     if (a->p) {
1113         /* pre-decrement */
1114         tcg_gen_addi_i32(addr, addr, -(a->imm << 2));
1115     }
1116
1117     if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1118         /*
1119          * Here 'addr' is the lowest address we will store to,
1120          * and is either the old SP (if post-increment) or
1121          * the new SP (if pre-decrement). For post-increment
1122          * where the old value is below the limit and the new
1123          * value is above, it is UNKNOWN whether the limit check
1124          * triggers; we choose to trigger.
1125          */
1126         gen_helper_v8m_stackcheck(cpu_env, addr);
1127     }
1128
1129     offset = 8;
1130     tmp = tcg_temp_new_i64();
1131     for (i = 0; i < n; i++) {
1132         if (a->l) {
1133             /* load */
1134             gen_aa32_ld64(s, tmp, addr, get_mem_index(s));
1135             neon_store_reg64(tmp, a->vd + i);
1136         } else {
1137             /* store */
1138             neon_load_reg64(tmp, a->vd + i);
1139             gen_aa32_st64(s, tmp, addr, get_mem_index(s));
1140         }
1141         tcg_gen_addi_i32(addr, addr, offset);
1142     }
1143     tcg_temp_free_i64(tmp);
1144     if (a->w) {
1145         /* writeback */
1146         if (a->p) {
1147             offset = -offset * n;
1148         } else if (a->imm & 1) {
1149             offset = 4;
1150         } else {
1151             offset = 0;
1152         }
1153
1154         if (offset != 0) {
1155             tcg_gen_addi_i32(addr, addr, offset);
1156         }
1157         store_reg(s, a->rn, addr);
1158     } else {
1159         tcg_temp_free_i32(addr);
1160     }
1161
1162     return true;
1163 }
1164
1165 /*
1166  * Types for callbacks for do_vfp_3op_sp() and do_vfp_3op_dp().
1167  * The callback should emit code to write a value to vd. If
1168  * do_vfp_3op_{sp,dp}() was passed reads_vd then the TCGv vd
1169  * will contain the old value of the relevant VFP register;
1170  * otherwise it must be written to only.
1171  */
1172 typedef void VFPGen3OpSPFn(TCGv_i32 vd,
1173                            TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst);
1174 typedef void VFPGen3OpDPFn(TCGv_i64 vd,
1175                            TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst);
1176
1177 /*
1178  * Types for callbacks for do_vfp_2op_sp() and do_vfp_2op_dp().
1179  * The callback should emit code to write a value to vd (which
1180  * should be written to only).
1181  */
1182 typedef void VFPGen2OpSPFn(TCGv_i32 vd, TCGv_i32 vm);
1183 typedef void VFPGen2OpDPFn(TCGv_i64 vd, TCGv_i64 vm);
1184
1185 /*
1186  * Return true if the specified S reg is in a scalar bank
1187  * (ie if it is s0..s7)
1188  */
1189 static inline bool vfp_sreg_is_scalar(int reg)
1190 {
1191     return (reg & 0x18) == 0;
1192 }
1193
1194 /*
1195  * Return true if the specified D reg is in a scalar bank
1196  * (ie if it is d0..d3 or d16..d19)
1197  */
1198 static inline bool vfp_dreg_is_scalar(int reg)
1199 {
1200     return (reg & 0xc) == 0;
1201 }
1202
1203 /*
1204  * Advance the S reg number forwards by delta within its bank
1205  * (ie increment the low 3 bits but leave the rest the same)
1206  */
1207 static inline int vfp_advance_sreg(int reg, int delta)
1208 {
1209     return ((reg + delta) & 0x7) | (reg & ~0x7);
1210 }
1211
1212 /*
1213  * Advance the D reg number forwards by delta within its bank
1214  * (ie increment the low 2 bits but leave the rest the same)
1215  */
1216 static inline int vfp_advance_dreg(int reg, int delta)
1217 {
1218     return ((reg + delta) & 0x3) | (reg & ~0x3);
1219 }
1220
1221 /*
1222  * Perform a 3-operand VFP data processing instruction. fn is the
1223  * callback to do the actual operation; this function deals with the
1224  * code to handle looping around for VFP vector processing.
1225  */
1226 static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
1227                           int vd, int vn, int vm, bool reads_vd)
1228 {
1229     uint32_t delta_m = 0;
1230     uint32_t delta_d = 0;
1231     int veclen = s->vec_len;
1232     TCGv_i32 f0, f1, fd;
1233     TCGv_ptr fpst;
1234
1235     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1236         return false;
1237     }
1238
1239     if (!dc_isar_feature(aa32_fpshvec, s) &&
1240         (veclen != 0 || s->vec_stride != 0)) {
1241         return false;
1242     }
1243
1244     if (!vfp_access_check(s)) {
1245         return true;
1246     }
1247
1248     if (veclen > 0) {
1249         /* Figure out what type of vector operation this is.  */
1250         if (vfp_sreg_is_scalar(vd)) {
1251             /* scalar */
1252             veclen = 0;
1253         } else {
1254             delta_d = s->vec_stride + 1;
1255
1256             if (vfp_sreg_is_scalar(vm)) {
1257                 /* mixed scalar/vector */
1258                 delta_m = 0;
1259             } else {
1260                 /* vector */
1261                 delta_m = delta_d;
1262             }
1263         }
1264     }
1265
1266     f0 = tcg_temp_new_i32();
1267     f1 = tcg_temp_new_i32();
1268     fd = tcg_temp_new_i32();
1269     fpst = fpstatus_ptr(FPST_FPCR);
1270
1271     neon_load_reg32(f0, vn);
1272     neon_load_reg32(f1, vm);
1273
1274     for (;;) {
1275         if (reads_vd) {
1276             neon_load_reg32(fd, vd);
1277         }
1278         fn(fd, f0, f1, fpst);
1279         neon_store_reg32(fd, vd);
1280
1281         if (veclen == 0) {
1282             break;
1283         }
1284
1285         /* Set up the operands for the next iteration */
1286         veclen--;
1287         vd = vfp_advance_sreg(vd, delta_d);
1288         vn = vfp_advance_sreg(vn, delta_d);
1289         neon_load_reg32(f0, vn);
1290         if (delta_m) {
1291             vm = vfp_advance_sreg(vm, delta_m);
1292             neon_load_reg32(f1, vm);
1293         }
1294     }
1295
1296     tcg_temp_free_i32(f0);
1297     tcg_temp_free_i32(f1);
1298     tcg_temp_free_i32(fd);
1299     tcg_temp_free_ptr(fpst);
1300
1301     return true;
1302 }
1303
1304 static bool do_vfp_3op_hp(DisasContext *s, VFPGen3OpSPFn *fn,
1305                           int vd, int vn, int vm, bool reads_vd)
1306 {
1307     /*
1308      * Do a half-precision operation. Functionally this is
1309      * the same as do_vfp_3op_sp(), except:
1310      *  - it uses the FPST_FPCR_F16
1311      *  - it doesn't need the VFP vector handling (fp16 is a
1312      *    v8 feature, and in v8 VFP vectors don't exist)
1313      *  - it does the aa32_fp16_arith feature test
1314      */
1315     TCGv_i32 f0, f1, fd;
1316     TCGv_ptr fpst;
1317
1318     if (!dc_isar_feature(aa32_fp16_arith, s)) {
1319         return false;
1320     }
1321
1322     if (s->vec_len != 0 || s->vec_stride != 0) {
1323         return false;
1324     }
1325
1326     if (!vfp_access_check(s)) {
1327         return true;
1328     }
1329
1330     f0 = tcg_temp_new_i32();
1331     f1 = tcg_temp_new_i32();
1332     fd = tcg_temp_new_i32();
1333     fpst = fpstatus_ptr(FPST_FPCR_F16);
1334
1335     neon_load_reg32(f0, vn);
1336     neon_load_reg32(f1, vm);
1337
1338     if (reads_vd) {
1339         neon_load_reg32(fd, vd);
1340     }
1341     fn(fd, f0, f1, fpst);
1342     neon_store_reg32(fd, vd);
1343
1344     tcg_temp_free_i32(f0);
1345     tcg_temp_free_i32(f1);
1346     tcg_temp_free_i32(fd);
1347     tcg_temp_free_ptr(fpst);
1348
1349     return true;
1350 }
1351
1352 static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
1353                           int vd, int vn, int vm, bool reads_vd)
1354 {
1355     uint32_t delta_m = 0;
1356     uint32_t delta_d = 0;
1357     int veclen = s->vec_len;
1358     TCGv_i64 f0, f1, fd;
1359     TCGv_ptr fpst;
1360
1361     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
1362         return false;
1363     }
1364
1365     /* UNDEF accesses to D16-D31 if they don't exist */
1366     if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
1367         return false;
1368     }
1369
1370     if (!dc_isar_feature(aa32_fpshvec, s) &&
1371         (veclen != 0 || s->vec_stride != 0)) {
1372         return false;
1373     }
1374
1375     if (!vfp_access_check(s)) {
1376         return true;
1377     }
1378
1379     if (veclen > 0) {
1380         /* Figure out what type of vector operation this is.  */
1381         if (vfp_dreg_is_scalar(vd)) {
1382             /* scalar */
1383             veclen = 0;
1384         } else {
1385             delta_d = (s->vec_stride >> 1) + 1;
1386
1387             if (vfp_dreg_is_scalar(vm)) {
1388                 /* mixed scalar/vector */
1389                 delta_m = 0;
1390             } else {
1391                 /* vector */
1392                 delta_m = delta_d;
1393             }
1394         }
1395     }
1396
1397     f0 = tcg_temp_new_i64();
1398     f1 = tcg_temp_new_i64();
1399     fd = tcg_temp_new_i64();
1400     fpst = fpstatus_ptr(FPST_FPCR);
1401
1402     neon_load_reg64(f0, vn);
1403     neon_load_reg64(f1, vm);
1404
1405     for (;;) {
1406         if (reads_vd) {
1407             neon_load_reg64(fd, vd);
1408         }
1409         fn(fd, f0, f1, fpst);
1410         neon_store_reg64(fd, vd);
1411
1412         if (veclen == 0) {
1413             break;
1414         }
1415         /* Set up the operands for the next iteration */
1416         veclen--;
1417         vd = vfp_advance_dreg(vd, delta_d);
1418         vn = vfp_advance_dreg(vn, delta_d);
1419         neon_load_reg64(f0, vn);
1420         if (delta_m) {
1421             vm = vfp_advance_dreg(vm, delta_m);
1422             neon_load_reg64(f1, vm);
1423         }
1424     }
1425
1426     tcg_temp_free_i64(f0);
1427     tcg_temp_free_i64(f1);
1428     tcg_temp_free_i64(fd);
1429     tcg_temp_free_ptr(fpst);
1430
1431     return true;
1432 }
1433
1434 static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
1435 {
1436     uint32_t delta_m = 0;
1437     uint32_t delta_d = 0;
1438     int veclen = s->vec_len;
1439     TCGv_i32 f0, fd;
1440
1441     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1442         return false;
1443     }
1444
1445     if (!dc_isar_feature(aa32_fpshvec, s) &&
1446         (veclen != 0 || s->vec_stride != 0)) {
1447         return false;
1448     }
1449
1450     if (!vfp_access_check(s)) {
1451         return true;
1452     }
1453
1454     if (veclen > 0) {
1455         /* Figure out what type of vector operation this is.  */
1456         if (vfp_sreg_is_scalar(vd)) {
1457             /* scalar */
1458             veclen = 0;
1459         } else {
1460             delta_d = s->vec_stride + 1;
1461
1462             if (vfp_sreg_is_scalar(vm)) {
1463                 /* mixed scalar/vector */
1464                 delta_m = 0;
1465             } else {
1466                 /* vector */
1467                 delta_m = delta_d;
1468             }
1469         }
1470     }
1471
1472     f0 = tcg_temp_new_i32();
1473     fd = tcg_temp_new_i32();
1474
1475     neon_load_reg32(f0, vm);
1476
1477     for (;;) {
1478         fn(fd, f0);
1479         neon_store_reg32(fd, vd);
1480
1481         if (veclen == 0) {
1482             break;
1483         }
1484
1485         if (delta_m == 0) {
1486             /* single source one-many */
1487             while (veclen--) {
1488                 vd = vfp_advance_sreg(vd, delta_d);
1489                 neon_store_reg32(fd, vd);
1490             }
1491             break;
1492         }
1493
1494         /* Set up the operands for the next iteration */
1495         veclen--;
1496         vd = vfp_advance_sreg(vd, delta_d);
1497         vm = vfp_advance_sreg(vm, delta_m);
1498         neon_load_reg32(f0, vm);
1499     }
1500
1501     tcg_temp_free_i32(f0);
1502     tcg_temp_free_i32(fd);
1503
1504     return true;
1505 }
1506
1507 static bool do_vfp_2op_hp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
1508 {
1509     /*
1510      * Do a half-precision operation. Functionally this is
1511      * the same as do_vfp_2op_sp(), except:
1512      *  - it doesn't need the VFP vector handling (fp16 is a
1513      *    v8 feature, and in v8 VFP vectors don't exist)
1514      *  - it does the aa32_fp16_arith feature test
1515      */
1516     TCGv_i32 f0;
1517
1518     if (!dc_isar_feature(aa32_fp16_arith, s)) {
1519         return false;
1520     }
1521
1522     if (s->vec_len != 0 || s->vec_stride != 0) {
1523         return false;
1524     }
1525
1526     if (!vfp_access_check(s)) {
1527         return true;
1528     }
1529
1530     f0 = tcg_temp_new_i32();
1531     neon_load_reg32(f0, vm);
1532     fn(f0, f0);
1533     neon_store_reg32(f0, vd);
1534     tcg_temp_free_i32(f0);
1535
1536     return true;
1537 }
1538
1539 static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
1540 {
1541     uint32_t delta_m = 0;
1542     uint32_t delta_d = 0;
1543     int veclen = s->vec_len;
1544     TCGv_i64 f0, fd;
1545
1546     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
1547         return false;
1548     }
1549
1550     /* UNDEF accesses to D16-D31 if they don't exist */
1551     if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
1552         return false;
1553     }
1554
1555     if (!dc_isar_feature(aa32_fpshvec, s) &&
1556         (veclen != 0 || s->vec_stride != 0)) {
1557         return false;
1558     }
1559
1560     if (!vfp_access_check(s)) {
1561         return true;
1562     }
1563
1564     if (veclen > 0) {
1565         /* Figure out what type of vector operation this is.  */
1566         if (vfp_dreg_is_scalar(vd)) {
1567             /* scalar */
1568             veclen = 0;
1569         } else {
1570             delta_d = (s->vec_stride >> 1) + 1;
1571
1572             if (vfp_dreg_is_scalar(vm)) {
1573                 /* mixed scalar/vector */
1574                 delta_m = 0;
1575             } else {
1576                 /* vector */
1577                 delta_m = delta_d;
1578             }
1579         }
1580     }
1581
1582     f0 = tcg_temp_new_i64();
1583     fd = tcg_temp_new_i64();
1584
1585     neon_load_reg64(f0, vm);
1586
1587     for (;;) {
1588         fn(fd, f0);
1589         neon_store_reg64(fd, vd);
1590
1591         if (veclen == 0) {
1592             break;
1593         }
1594
1595         if (delta_m == 0) {
1596             /* single source one-many */
1597             while (veclen--) {
1598                 vd = vfp_advance_dreg(vd, delta_d);
1599                 neon_store_reg64(fd, vd);
1600             }
1601             break;
1602         }
1603
1604         /* Set up the operands for the next iteration */
1605         veclen--;
1606         vd = vfp_advance_dreg(vd, delta_d);
1607         vd = vfp_advance_dreg(vm, delta_m);
1608         neon_load_reg64(f0, vm);
1609     }
1610
1611     tcg_temp_free_i64(f0);
1612     tcg_temp_free_i64(fd);
1613
1614     return true;
1615 }
1616
1617 static void gen_VMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1618 {
1619     /* Note that order of inputs to the add matters for NaNs */
1620     TCGv_i32 tmp = tcg_temp_new_i32();
1621
1622     gen_helper_vfp_mulh(tmp, vn, vm, fpst);
1623     gen_helper_vfp_addh(vd, vd, tmp, fpst);
1624     tcg_temp_free_i32(tmp);
1625 }
1626
1627 static bool trans_VMLA_hp(DisasContext *s, arg_VMLA_sp *a)
1628 {
1629     return do_vfp_3op_hp(s, gen_VMLA_hp, a->vd, a->vn, a->vm, true);
1630 }
1631
1632 static void gen_VMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1633 {
1634     /* Note that order of inputs to the add matters for NaNs */
1635     TCGv_i32 tmp = tcg_temp_new_i32();
1636
1637     gen_helper_vfp_muls(tmp, vn, vm, fpst);
1638     gen_helper_vfp_adds(vd, vd, tmp, fpst);
1639     tcg_temp_free_i32(tmp);
1640 }
1641
1642 static bool trans_VMLA_sp(DisasContext *s, arg_VMLA_sp *a)
1643 {
1644     return do_vfp_3op_sp(s, gen_VMLA_sp, a->vd, a->vn, a->vm, true);
1645 }
1646
1647 static void gen_VMLA_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1648 {
1649     /* Note that order of inputs to the add matters for NaNs */
1650     TCGv_i64 tmp = tcg_temp_new_i64();
1651
1652     gen_helper_vfp_muld(tmp, vn, vm, fpst);
1653     gen_helper_vfp_addd(vd, vd, tmp, fpst);
1654     tcg_temp_free_i64(tmp);
1655 }
1656
1657 static bool trans_VMLA_dp(DisasContext *s, arg_VMLA_dp *a)
1658 {
1659     return do_vfp_3op_dp(s, gen_VMLA_dp, a->vd, a->vn, a->vm, true);
1660 }
1661
1662 static void gen_VMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1663 {
1664     /*
1665      * VMLS: vd = vd + -(vn * vm)
1666      * Note that order of inputs to the add matters for NaNs.
1667      */
1668     TCGv_i32 tmp = tcg_temp_new_i32();
1669
1670     gen_helper_vfp_mulh(tmp, vn, vm, fpst);
1671     gen_helper_vfp_negh(tmp, tmp);
1672     gen_helper_vfp_addh(vd, vd, tmp, fpst);
1673     tcg_temp_free_i32(tmp);
1674 }
1675
1676 static bool trans_VMLS_hp(DisasContext *s, arg_VMLS_sp *a)
1677 {
1678     return do_vfp_3op_hp(s, gen_VMLS_hp, a->vd, a->vn, a->vm, true);
1679 }
1680
1681 static void gen_VMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1682 {
1683     /*
1684      * VMLS: vd = vd + -(vn * vm)
1685      * Note that order of inputs to the add matters for NaNs.
1686      */
1687     TCGv_i32 tmp = tcg_temp_new_i32();
1688
1689     gen_helper_vfp_muls(tmp, vn, vm, fpst);
1690     gen_helper_vfp_negs(tmp, tmp);
1691     gen_helper_vfp_adds(vd, vd, tmp, fpst);
1692     tcg_temp_free_i32(tmp);
1693 }
1694
1695 static bool trans_VMLS_sp(DisasContext *s, arg_VMLS_sp *a)
1696 {
1697     return do_vfp_3op_sp(s, gen_VMLS_sp, a->vd, a->vn, a->vm, true);
1698 }
1699
1700 static void gen_VMLS_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1701 {
1702     /*
1703      * VMLS: vd = vd + -(vn * vm)
1704      * Note that order of inputs to the add matters for NaNs.
1705      */
1706     TCGv_i64 tmp = tcg_temp_new_i64();
1707
1708     gen_helper_vfp_muld(tmp, vn, vm, fpst);
1709     gen_helper_vfp_negd(tmp, tmp);
1710     gen_helper_vfp_addd(vd, vd, tmp, fpst);
1711     tcg_temp_free_i64(tmp);
1712 }
1713
1714 static bool trans_VMLS_dp(DisasContext *s, arg_VMLS_dp *a)
1715 {
1716     return do_vfp_3op_dp(s, gen_VMLS_dp, a->vd, a->vn, a->vm, true);
1717 }
1718
1719 static void gen_VNMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1720 {
1721     /*
1722      * VNMLS: -fd + (fn * fm)
1723      * Note that it isn't valid to replace (-A + B) with (B - A) or similar
1724      * plausible looking simplifications because this will give wrong results
1725      * for NaNs.
1726      */
1727     TCGv_i32 tmp = tcg_temp_new_i32();
1728
1729     gen_helper_vfp_mulh(tmp, vn, vm, fpst);
1730     gen_helper_vfp_negh(vd, vd);
1731     gen_helper_vfp_addh(vd, vd, tmp, fpst);
1732     tcg_temp_free_i32(tmp);
1733 }
1734
1735 static bool trans_VNMLS_hp(DisasContext *s, arg_VNMLS_sp *a)
1736 {
1737     return do_vfp_3op_hp(s, gen_VNMLS_hp, a->vd, a->vn, a->vm, true);
1738 }
1739
1740 static void gen_VNMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1741 {
1742     /*
1743      * VNMLS: -fd + (fn * fm)
1744      * Note that it isn't valid to replace (-A + B) with (B - A) or similar
1745      * plausible looking simplifications because this will give wrong results
1746      * for NaNs.
1747      */
1748     TCGv_i32 tmp = tcg_temp_new_i32();
1749
1750     gen_helper_vfp_muls(tmp, vn, vm, fpst);
1751     gen_helper_vfp_negs(vd, vd);
1752     gen_helper_vfp_adds(vd, vd, tmp, fpst);
1753     tcg_temp_free_i32(tmp);
1754 }
1755
1756 static bool trans_VNMLS_sp(DisasContext *s, arg_VNMLS_sp *a)
1757 {
1758     return do_vfp_3op_sp(s, gen_VNMLS_sp, a->vd, a->vn, a->vm, true);
1759 }
1760
1761 static void gen_VNMLS_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1762 {
1763     /*
1764      * VNMLS: -fd + (fn * fm)
1765      * Note that it isn't valid to replace (-A + B) with (B - A) or similar
1766      * plausible looking simplifications because this will give wrong results
1767      * for NaNs.
1768      */
1769     TCGv_i64 tmp = tcg_temp_new_i64();
1770
1771     gen_helper_vfp_muld(tmp, vn, vm, fpst);
1772     gen_helper_vfp_negd(vd, vd);
1773     gen_helper_vfp_addd(vd, vd, tmp, fpst);
1774     tcg_temp_free_i64(tmp);
1775 }
1776
1777 static bool trans_VNMLS_dp(DisasContext *s, arg_VNMLS_dp *a)
1778 {
1779     return do_vfp_3op_dp(s, gen_VNMLS_dp, a->vd, a->vn, a->vm, true);
1780 }
1781
1782 static void gen_VNMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1783 {
1784     /* VNMLA: -fd + -(fn * fm) */
1785     TCGv_i32 tmp = tcg_temp_new_i32();
1786
1787     gen_helper_vfp_mulh(tmp, vn, vm, fpst);
1788     gen_helper_vfp_negh(tmp, tmp);
1789     gen_helper_vfp_negh(vd, vd);
1790     gen_helper_vfp_addh(vd, vd, tmp, fpst);
1791     tcg_temp_free_i32(tmp);
1792 }
1793
1794 static bool trans_VNMLA_hp(DisasContext *s, arg_VNMLA_sp *a)
1795 {
1796     return do_vfp_3op_hp(s, gen_VNMLA_hp, a->vd, a->vn, a->vm, true);
1797 }
1798
1799 static void gen_VNMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1800 {
1801     /* VNMLA: -fd + -(fn * fm) */
1802     TCGv_i32 tmp = tcg_temp_new_i32();
1803
1804     gen_helper_vfp_muls(tmp, vn, vm, fpst);
1805     gen_helper_vfp_negs(tmp, tmp);
1806     gen_helper_vfp_negs(vd, vd);
1807     gen_helper_vfp_adds(vd, vd, tmp, fpst);
1808     tcg_temp_free_i32(tmp);
1809 }
1810
1811 static bool trans_VNMLA_sp(DisasContext *s, arg_VNMLA_sp *a)
1812 {
1813     return do_vfp_3op_sp(s, gen_VNMLA_sp, a->vd, a->vn, a->vm, true);
1814 }
1815
1816 static void gen_VNMLA_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1817 {
1818     /* VNMLA: -fd + (fn * fm) */
1819     TCGv_i64 tmp = tcg_temp_new_i64();
1820
1821     gen_helper_vfp_muld(tmp, vn, vm, fpst);
1822     gen_helper_vfp_negd(tmp, tmp);
1823     gen_helper_vfp_negd(vd, vd);
1824     gen_helper_vfp_addd(vd, vd, tmp, fpst);
1825     tcg_temp_free_i64(tmp);
1826 }
1827
1828 static bool trans_VNMLA_dp(DisasContext *s, arg_VNMLA_dp *a)
1829 {
1830     return do_vfp_3op_dp(s, gen_VNMLA_dp, a->vd, a->vn, a->vm, true);
1831 }
1832
1833 static bool trans_VMUL_hp(DisasContext *s, arg_VMUL_sp *a)
1834 {
1835     return do_vfp_3op_hp(s, gen_helper_vfp_mulh, a->vd, a->vn, a->vm, false);
1836 }
1837
1838 static bool trans_VMUL_sp(DisasContext *s, arg_VMUL_sp *a)
1839 {
1840     return do_vfp_3op_sp(s, gen_helper_vfp_muls, a->vd, a->vn, a->vm, false);
1841 }
1842
1843 static bool trans_VMUL_dp(DisasContext *s, arg_VMUL_dp *a)
1844 {
1845     return do_vfp_3op_dp(s, gen_helper_vfp_muld, a->vd, a->vn, a->vm, false);
1846 }
1847
1848 static void gen_VNMUL_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1849 {
1850     /* VNMUL: -(fn * fm) */
1851     gen_helper_vfp_mulh(vd, vn, vm, fpst);
1852     gen_helper_vfp_negh(vd, vd);
1853 }
1854
1855 static bool trans_VNMUL_hp(DisasContext *s, arg_VNMUL_sp *a)
1856 {
1857     return do_vfp_3op_hp(s, gen_VNMUL_hp, a->vd, a->vn, a->vm, false);
1858 }
1859
1860 static void gen_VNMUL_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1861 {
1862     /* VNMUL: -(fn * fm) */
1863     gen_helper_vfp_muls(vd, vn, vm, fpst);
1864     gen_helper_vfp_negs(vd, vd);
1865 }
1866
1867 static bool trans_VNMUL_sp(DisasContext *s, arg_VNMUL_sp *a)
1868 {
1869     return do_vfp_3op_sp(s, gen_VNMUL_sp, a->vd, a->vn, a->vm, false);
1870 }
1871
1872 static void gen_VNMUL_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1873 {
1874     /* VNMUL: -(fn * fm) */
1875     gen_helper_vfp_muld(vd, vn, vm, fpst);
1876     gen_helper_vfp_negd(vd, vd);
1877 }
1878
1879 static bool trans_VNMUL_dp(DisasContext *s, arg_VNMUL_dp *a)
1880 {
1881     return do_vfp_3op_dp(s, gen_VNMUL_dp, a->vd, a->vn, a->vm, false);
1882 }
1883
1884 static bool trans_VADD_hp(DisasContext *s, arg_VADD_sp *a)
1885 {
1886     return do_vfp_3op_hp(s, gen_helper_vfp_addh, a->vd, a->vn, a->vm, false);
1887 }
1888
1889 static bool trans_VADD_sp(DisasContext *s, arg_VADD_sp *a)
1890 {
1891     return do_vfp_3op_sp(s, gen_helper_vfp_adds, a->vd, a->vn, a->vm, false);
1892 }
1893
1894 static bool trans_VADD_dp(DisasContext *s, arg_VADD_dp *a)
1895 {
1896     return do_vfp_3op_dp(s, gen_helper_vfp_addd, a->vd, a->vn, a->vm, false);
1897 }
1898
1899 static bool trans_VSUB_hp(DisasContext *s, arg_VSUB_sp *a)
1900 {
1901     return do_vfp_3op_hp(s, gen_helper_vfp_subh, a->vd, a->vn, a->vm, false);
1902 }
1903
1904 static bool trans_VSUB_sp(DisasContext *s, arg_VSUB_sp *a)
1905 {
1906     return do_vfp_3op_sp(s, gen_helper_vfp_subs, a->vd, a->vn, a->vm, false);
1907 }
1908
1909 static bool trans_VSUB_dp(DisasContext *s, arg_VSUB_dp *a)
1910 {
1911     return do_vfp_3op_dp(s, gen_helper_vfp_subd, a->vd, a->vn, a->vm, false);
1912 }
1913
1914 static bool trans_VDIV_hp(DisasContext *s, arg_VDIV_sp *a)
1915 {
1916     return do_vfp_3op_hp(s, gen_helper_vfp_divh, a->vd, a->vn, a->vm, false);
1917 }
1918
1919 static bool trans_VDIV_sp(DisasContext *s, arg_VDIV_sp *a)
1920 {
1921     return do_vfp_3op_sp(s, gen_helper_vfp_divs, a->vd, a->vn, a->vm, false);
1922 }
1923
1924 static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
1925 {
1926     return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
1927 }
1928
1929 static bool trans_VMINNM_hp(DisasContext *s, arg_VMINNM_sp *a)
1930 {
1931     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1932         return false;
1933     }
1934     return do_vfp_3op_hp(s, gen_helper_vfp_minnumh,
1935                          a->vd, a->vn, a->vm, false);
1936 }
1937
1938 static bool trans_VMAXNM_hp(DisasContext *s, arg_VMAXNM_sp *a)
1939 {
1940     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1941         return false;
1942     }
1943     return do_vfp_3op_hp(s, gen_helper_vfp_maxnumh,
1944                          a->vd, a->vn, a->vm, false);
1945 }
1946
1947 static bool trans_VMINNM_sp(DisasContext *s, arg_VMINNM_sp *a)
1948 {
1949     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1950         return false;
1951     }
1952     return do_vfp_3op_sp(s, gen_helper_vfp_minnums,
1953                          a->vd, a->vn, a->vm, false);
1954 }
1955
1956 static bool trans_VMAXNM_sp(DisasContext *s, arg_VMAXNM_sp *a)
1957 {
1958     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1959         return false;
1960     }
1961     return do_vfp_3op_sp(s, gen_helper_vfp_maxnums,
1962                          a->vd, a->vn, a->vm, false);
1963 }
1964
1965 static bool trans_VMINNM_dp(DisasContext *s, arg_VMINNM_dp *a)
1966 {
1967     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1968         return false;
1969     }
1970     return do_vfp_3op_dp(s, gen_helper_vfp_minnumd,
1971                          a->vd, a->vn, a->vm, false);
1972 }
1973
1974 static bool trans_VMAXNM_dp(DisasContext *s, arg_VMAXNM_dp *a)
1975 {
1976     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1977         return false;
1978     }
1979     return do_vfp_3op_dp(s, gen_helper_vfp_maxnumd,
1980                          a->vd, a->vn, a->vm, false);
1981 }
1982
1983 static bool do_vfm_hp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
1984 {
1985     /*
1986      * VFNMA : fd = muladd(-fd,  fn, fm)
1987      * VFNMS : fd = muladd(-fd, -fn, fm)
1988      * VFMA  : fd = muladd( fd,  fn, fm)
1989      * VFMS  : fd = muladd( fd, -fn, fm)
1990      *
1991      * These are fused multiply-add, and must be done as one floating
1992      * point operation with no rounding between the multiplication and
1993      * addition steps.  NB that doing the negations here as separate
1994      * steps is correct : an input NaN should come out with its sign
1995      * bit flipped if it is a negated-input.
1996      */
1997     TCGv_ptr fpst;
1998     TCGv_i32 vn, vm, vd;
1999
2000     /*
2001      * Present in VFPv4 only, and only with the FP16 extension.
2002      * Note that we can't rely on the SIMDFMAC check alone, because
2003      * in a Neon-no-VFP core that ID register field will be non-zero.
2004      */
2005     if (!dc_isar_feature(aa32_fp16_arith, s) ||
2006         !dc_isar_feature(aa32_simdfmac, s) ||
2007         !dc_isar_feature(aa32_fpsp_v2, s)) {
2008         return false;
2009     }
2010
2011     if (s->vec_len != 0 || s->vec_stride != 0) {
2012         return false;
2013     }
2014
2015     if (!vfp_access_check(s)) {
2016         return true;
2017     }
2018
2019     vn = tcg_temp_new_i32();
2020     vm = tcg_temp_new_i32();
2021     vd = tcg_temp_new_i32();
2022
2023     neon_load_reg32(vn, a->vn);
2024     neon_load_reg32(vm, a->vm);
2025     if (neg_n) {
2026         /* VFNMS, VFMS */
2027         gen_helper_vfp_negh(vn, vn);
2028     }
2029     neon_load_reg32(vd, a->vd);
2030     if (neg_d) {
2031         /* VFNMA, VFNMS */
2032         gen_helper_vfp_negh(vd, vd);
2033     }
2034     fpst = fpstatus_ptr(FPST_FPCR_F16);
2035     gen_helper_vfp_muladdh(vd, vn, vm, vd, fpst);
2036     neon_store_reg32(vd, a->vd);
2037
2038     tcg_temp_free_ptr(fpst);
2039     tcg_temp_free_i32(vn);
2040     tcg_temp_free_i32(vm);
2041     tcg_temp_free_i32(vd);
2042
2043     return true;
2044 }
2045
2046 static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
2047 {
2048     /*
2049      * VFNMA : fd = muladd(-fd,  fn, fm)
2050      * VFNMS : fd = muladd(-fd, -fn, fm)
2051      * VFMA  : fd = muladd( fd,  fn, fm)
2052      * VFMS  : fd = muladd( fd, -fn, fm)
2053      *
2054      * These are fused multiply-add, and must be done as one floating
2055      * point operation with no rounding between the multiplication and
2056      * addition steps.  NB that doing the negations here as separate
2057      * steps is correct : an input NaN should come out with its sign
2058      * bit flipped if it is a negated-input.
2059      */
2060     TCGv_ptr fpst;
2061     TCGv_i32 vn, vm, vd;
2062
2063     /*
2064      * Present in VFPv4 only.
2065      * Note that we can't rely on the SIMDFMAC check alone, because
2066      * in a Neon-no-VFP core that ID register field will be non-zero.
2067      */
2068     if (!dc_isar_feature(aa32_simdfmac, s) ||
2069         !dc_isar_feature(aa32_fpsp_v2, s)) {
2070         return false;
2071     }
2072     /*
2073      * In v7A, UNPREDICTABLE with non-zero vector length/stride; from
2074      * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
2075      */
2076     if (s->vec_len != 0 || s->vec_stride != 0) {
2077         return false;
2078     }
2079
2080     if (!vfp_access_check(s)) {
2081         return true;
2082     }
2083
2084     vn = tcg_temp_new_i32();
2085     vm = tcg_temp_new_i32();
2086     vd = tcg_temp_new_i32();
2087
2088     neon_load_reg32(vn, a->vn);
2089     neon_load_reg32(vm, a->vm);
2090     if (neg_n) {
2091         /* VFNMS, VFMS */
2092         gen_helper_vfp_negs(vn, vn);
2093     }
2094     neon_load_reg32(vd, a->vd);
2095     if (neg_d) {
2096         /* VFNMA, VFNMS */
2097         gen_helper_vfp_negs(vd, vd);
2098     }
2099     fpst = fpstatus_ptr(FPST_FPCR);
2100     gen_helper_vfp_muladds(vd, vn, vm, vd, fpst);
2101     neon_store_reg32(vd, a->vd);
2102
2103     tcg_temp_free_ptr(fpst);
2104     tcg_temp_free_i32(vn);
2105     tcg_temp_free_i32(vm);
2106     tcg_temp_free_i32(vd);
2107
2108     return true;
2109 }
2110
2111 static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
2112 {
2113     /*
2114      * VFNMA : fd = muladd(-fd,  fn, fm)
2115      * VFNMS : fd = muladd(-fd, -fn, fm)
2116      * VFMA  : fd = muladd( fd,  fn, fm)
2117      * VFMS  : fd = muladd( fd, -fn, fm)
2118      *
2119      * These are fused multiply-add, and must be done as one floating
2120      * point operation with no rounding between the multiplication and
2121      * addition steps.  NB that doing the negations here as separate
2122      * steps is correct : an input NaN should come out with its sign
2123      * bit flipped if it is a negated-input.
2124      */
2125     TCGv_ptr fpst;
2126     TCGv_i64 vn, vm, vd;
2127
2128     /*
2129      * Present in VFPv4 only.
2130      * Note that we can't rely on the SIMDFMAC check alone, because
2131      * in a Neon-no-VFP core that ID register field will be non-zero.
2132      */
2133     if (!dc_isar_feature(aa32_simdfmac, s) ||
2134         !dc_isar_feature(aa32_fpdp_v2, s)) {
2135         return false;
2136     }
2137     /*
2138      * In v7A, UNPREDICTABLE with non-zero vector length/stride; from
2139      * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
2140      */
2141     if (s->vec_len != 0 || s->vec_stride != 0) {
2142         return false;
2143     }
2144
2145     /* UNDEF accesses to D16-D31 if they don't exist. */
2146     if (!dc_isar_feature(aa32_simd_r32, s) &&
2147         ((a->vd | a->vn | a->vm) & 0x10)) {
2148         return false;
2149     }
2150
2151     if (!vfp_access_check(s)) {
2152         return true;
2153     }
2154
2155     vn = tcg_temp_new_i64();
2156     vm = tcg_temp_new_i64();
2157     vd = tcg_temp_new_i64();
2158
2159     neon_load_reg64(vn, a->vn);
2160     neon_load_reg64(vm, a->vm);
2161     if (neg_n) {
2162         /* VFNMS, VFMS */
2163         gen_helper_vfp_negd(vn, vn);
2164     }
2165     neon_load_reg64(vd, a->vd);
2166     if (neg_d) {
2167         /* VFNMA, VFNMS */
2168         gen_helper_vfp_negd(vd, vd);
2169     }
2170     fpst = fpstatus_ptr(FPST_FPCR);
2171     gen_helper_vfp_muladdd(vd, vn, vm, vd, fpst);
2172     neon_store_reg64(vd, a->vd);
2173
2174     tcg_temp_free_ptr(fpst);
2175     tcg_temp_free_i64(vn);
2176     tcg_temp_free_i64(vm);
2177     tcg_temp_free_i64(vd);
2178
2179     return true;
2180 }
2181
2182 #define MAKE_ONE_VFM_TRANS_FN(INSN, PREC, NEGN, NEGD)                   \
2183     static bool trans_##INSN##_##PREC(DisasContext *s,                  \
2184                                       arg_##INSN##_##PREC *a)           \
2185     {                                                                   \
2186         return do_vfm_##PREC(s, a, NEGN, NEGD);                         \
2187     }
2188
2189 #define MAKE_VFM_TRANS_FNS(PREC) \
2190     MAKE_ONE_VFM_TRANS_FN(VFMA, PREC, false, false) \
2191     MAKE_ONE_VFM_TRANS_FN(VFMS, PREC, true, false) \
2192     MAKE_ONE_VFM_TRANS_FN(VFNMA, PREC, false, true) \
2193     MAKE_ONE_VFM_TRANS_FN(VFNMS, PREC, true, true)
2194
2195 MAKE_VFM_TRANS_FNS(hp)
2196 MAKE_VFM_TRANS_FNS(sp)
2197 MAKE_VFM_TRANS_FNS(dp)
2198
2199 static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a)
2200 {
2201     TCGv_i32 fd;
2202
2203     if (!dc_isar_feature(aa32_fp16_arith, s)) {
2204         return false;
2205     }
2206
2207     if (s->vec_len != 0 || s->vec_stride != 0) {
2208         return false;
2209     }
2210
2211     if (!vfp_access_check(s)) {
2212         return true;
2213     }
2214
2215     fd = tcg_const_i32(vfp_expand_imm(MO_16, a->imm));
2216     neon_store_reg32(fd, a->vd);
2217     tcg_temp_free_i32(fd);
2218     return true;
2219 }
2220
2221 static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
2222 {
2223     uint32_t delta_d = 0;
2224     int veclen = s->vec_len;
2225     TCGv_i32 fd;
2226     uint32_t vd;
2227
2228     vd = a->vd;
2229
2230     if (!dc_isar_feature(aa32_fpsp_v3, s)) {
2231         return false;
2232     }
2233
2234     if (!dc_isar_feature(aa32_fpshvec, s) &&
2235         (veclen != 0 || s->vec_stride != 0)) {
2236         return false;
2237     }
2238
2239     if (!vfp_access_check(s)) {
2240         return true;
2241     }
2242
2243     if (veclen > 0) {
2244         /* Figure out what type of vector operation this is.  */
2245         if (vfp_sreg_is_scalar(vd)) {
2246             /* scalar */
2247             veclen = 0;
2248         } else {
2249             delta_d = s->vec_stride + 1;
2250         }
2251     }
2252
2253     fd = tcg_const_i32(vfp_expand_imm(MO_32, a->imm));
2254
2255     for (;;) {
2256         neon_store_reg32(fd, vd);
2257
2258         if (veclen == 0) {
2259             break;
2260         }
2261
2262         /* Set up the operands for the next iteration */
2263         veclen--;
2264         vd = vfp_advance_sreg(vd, delta_d);
2265     }
2266
2267     tcg_temp_free_i32(fd);
2268     return true;
2269 }
2270
2271 static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
2272 {
2273     uint32_t delta_d = 0;
2274     int veclen = s->vec_len;
2275     TCGv_i64 fd;
2276     uint32_t vd;
2277
2278     vd = a->vd;
2279
2280     if (!dc_isar_feature(aa32_fpdp_v3, s)) {
2281         return false;
2282     }
2283
2284     /* UNDEF accesses to D16-D31 if they don't exist. */
2285     if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
2286         return false;
2287     }
2288
2289     if (!dc_isar_feature(aa32_fpshvec, s) &&
2290         (veclen != 0 || s->vec_stride != 0)) {
2291         return false;
2292     }
2293
2294     if (!vfp_access_check(s)) {
2295         return true;
2296     }
2297
2298     if (veclen > 0) {
2299         /* Figure out what type of vector operation this is.  */
2300         if (vfp_dreg_is_scalar(vd)) {
2301             /* scalar */
2302             veclen = 0;
2303         } else {
2304             delta_d = (s->vec_stride >> 1) + 1;
2305         }
2306     }
2307
2308     fd = tcg_const_i64(vfp_expand_imm(MO_64, a->imm));
2309
2310     for (;;) {
2311         neon_store_reg64(fd, vd);
2312
2313         if (veclen == 0) {
2314             break;
2315         }
2316
2317         /* Set up the operands for the next iteration */
2318         veclen--;
2319         vd = vfp_advance_dreg(vd, delta_d);
2320     }
2321
2322     tcg_temp_free_i64(fd);
2323     return true;
2324 }
2325
2326 #define DO_VFP_2OP(INSN, PREC, FN)                              \
2327     static bool trans_##INSN##_##PREC(DisasContext *s,          \
2328                                       arg_##INSN##_##PREC *a)   \
2329     {                                                           \
2330         return do_vfp_2op_##PREC(s, FN, a->vd, a->vm);          \
2331     }
2332
2333 DO_VFP_2OP(VMOV_reg, sp, tcg_gen_mov_i32)
2334 DO_VFP_2OP(VMOV_reg, dp, tcg_gen_mov_i64)
2335
2336 DO_VFP_2OP(VABS, hp, gen_helper_vfp_absh)
2337 DO_VFP_2OP(VABS, sp, gen_helper_vfp_abss)
2338 DO_VFP_2OP(VABS, dp, gen_helper_vfp_absd)
2339
2340 DO_VFP_2OP(VNEG, hp, gen_helper_vfp_negh)
2341 DO_VFP_2OP(VNEG, sp, gen_helper_vfp_negs)
2342 DO_VFP_2OP(VNEG, dp, gen_helper_vfp_negd)
2343
2344 static void gen_VSQRT_hp(TCGv_i32 vd, TCGv_i32 vm)
2345 {
2346     gen_helper_vfp_sqrth(vd, vm, cpu_env);
2347 }
2348
2349 static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm)
2350 {
2351     gen_helper_vfp_sqrts(vd, vm, cpu_env);
2352 }
2353
2354 static void gen_VSQRT_dp(TCGv_i64 vd, TCGv_i64 vm)
2355 {
2356     gen_helper_vfp_sqrtd(vd, vm, cpu_env);
2357 }
2358
2359 DO_VFP_2OP(VSQRT, hp, gen_VSQRT_hp)
2360 DO_VFP_2OP(VSQRT, sp, gen_VSQRT_sp)
2361 DO_VFP_2OP(VSQRT, dp, gen_VSQRT_dp)
2362
2363 static bool trans_VCMP_hp(DisasContext *s, arg_VCMP_sp *a)
2364 {
2365     TCGv_i32 vd, vm;
2366
2367     if (!dc_isar_feature(aa32_fp16_arith, s)) {
2368         return false;
2369     }
2370
2371     /* Vm/M bits must be zero for the Z variant */
2372     if (a->z && a->vm != 0) {
2373         return false;
2374     }
2375
2376     if (!vfp_access_check(s)) {
2377         return true;
2378     }
2379
2380     vd = tcg_temp_new_i32();
2381     vm = tcg_temp_new_i32();
2382
2383     neon_load_reg32(vd, a->vd);
2384     if (a->z) {
2385         tcg_gen_movi_i32(vm, 0);
2386     } else {
2387         neon_load_reg32(vm, a->vm);
2388     }
2389
2390     if (a->e) {
2391         gen_helper_vfp_cmpeh(vd, vm, cpu_env);
2392     } else {
2393         gen_helper_vfp_cmph(vd, vm, cpu_env);
2394     }
2395
2396     tcg_temp_free_i32(vd);
2397     tcg_temp_free_i32(vm);
2398
2399     return true;
2400 }
2401
2402 static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
2403 {
2404     TCGv_i32 vd, vm;
2405
2406     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
2407         return false;
2408     }
2409
2410     /* Vm/M bits must be zero for the Z variant */
2411     if (a->z && a->vm != 0) {
2412         return false;
2413     }
2414
2415     if (!vfp_access_check(s)) {
2416         return true;
2417     }
2418
2419     vd = tcg_temp_new_i32();
2420     vm = tcg_temp_new_i32();
2421
2422     neon_load_reg32(vd, a->vd);
2423     if (a->z) {
2424         tcg_gen_movi_i32(vm, 0);
2425     } else {
2426         neon_load_reg32(vm, a->vm);
2427     }
2428
2429     if (a->e) {
2430         gen_helper_vfp_cmpes(vd, vm, cpu_env);
2431     } else {
2432         gen_helper_vfp_cmps(vd, vm, cpu_env);
2433     }
2434
2435     tcg_temp_free_i32(vd);
2436     tcg_temp_free_i32(vm);
2437
2438     return true;
2439 }
2440
2441 static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
2442 {
2443     TCGv_i64 vd, vm;
2444
2445     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2446         return false;
2447     }
2448
2449     /* Vm/M bits must be zero for the Z variant */
2450     if (a->z && a->vm != 0) {
2451         return false;
2452     }
2453
2454     /* UNDEF accesses to D16-D31 if they don't exist. */
2455     if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2456         return false;
2457     }
2458
2459     if (!vfp_access_check(s)) {
2460         return true;
2461     }
2462
2463     vd = tcg_temp_new_i64();
2464     vm = tcg_temp_new_i64();
2465
2466     neon_load_reg64(vd, a->vd);
2467     if (a->z) {
2468         tcg_gen_movi_i64(vm, 0);
2469     } else {
2470         neon_load_reg64(vm, a->vm);
2471     }
2472
2473     if (a->e) {
2474         gen_helper_vfp_cmped(vd, vm, cpu_env);
2475     } else {
2476         gen_helper_vfp_cmpd(vd, vm, cpu_env);
2477     }
2478
2479     tcg_temp_free_i64(vd);
2480     tcg_temp_free_i64(vm);
2481
2482     return true;
2483 }
2484
2485 static bool trans_VCVT_f32_f16(DisasContext *s, arg_VCVT_f32_f16 *a)
2486 {
2487     TCGv_ptr fpst;
2488     TCGv_i32 ahp_mode;
2489     TCGv_i32 tmp;
2490
2491     if (!dc_isar_feature(aa32_fp16_spconv, s)) {
2492         return false;
2493     }
2494
2495     if (!vfp_access_check(s)) {
2496         return true;
2497     }
2498
2499     fpst = fpstatus_ptr(FPST_FPCR);
2500     ahp_mode = get_ahp_flag();
2501     tmp = tcg_temp_new_i32();
2502     /* The T bit tells us if we want the low or high 16 bits of Vm */
2503     tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t));
2504     gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp_mode);
2505     neon_store_reg32(tmp, a->vd);
2506     tcg_temp_free_i32(ahp_mode);
2507     tcg_temp_free_ptr(fpst);
2508     tcg_temp_free_i32(tmp);
2509     return true;
2510 }
2511
2512 static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
2513 {
2514     TCGv_ptr fpst;
2515     TCGv_i32 ahp_mode;
2516     TCGv_i32 tmp;
2517     TCGv_i64 vd;
2518
2519     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2520         return false;
2521     }
2522
2523     if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
2524         return false;
2525     }
2526
2527     /* UNDEF accesses to D16-D31 if they don't exist. */
2528     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd  & 0x10)) {
2529         return false;
2530     }
2531
2532     if (!vfp_access_check(s)) {
2533         return true;
2534     }
2535
2536     fpst = fpstatus_ptr(FPST_FPCR);
2537     ahp_mode = get_ahp_flag();
2538     tmp = tcg_temp_new_i32();
2539     /* The T bit tells us if we want the low or high 16 bits of Vm */
2540     tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t));
2541     vd = tcg_temp_new_i64();
2542     gen_helper_vfp_fcvt_f16_to_f64(vd, tmp, fpst, ahp_mode);
2543     neon_store_reg64(vd, a->vd);
2544     tcg_temp_free_i32(ahp_mode);
2545     tcg_temp_free_ptr(fpst);
2546     tcg_temp_free_i32(tmp);
2547     tcg_temp_free_i64(vd);
2548     return true;
2549 }
2550
2551 static bool trans_VCVT_f16_f32(DisasContext *s, arg_VCVT_f16_f32 *a)
2552 {
2553     TCGv_ptr fpst;
2554     TCGv_i32 ahp_mode;
2555     TCGv_i32 tmp;
2556
2557     if (!dc_isar_feature(aa32_fp16_spconv, s)) {
2558         return false;
2559     }
2560
2561     if (!vfp_access_check(s)) {
2562         return true;
2563     }
2564
2565     fpst = fpstatus_ptr(FPST_FPCR);
2566     ahp_mode = get_ahp_flag();
2567     tmp = tcg_temp_new_i32();
2568
2569     neon_load_reg32(tmp, a->vm);
2570     gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp_mode);
2571     tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t));
2572     tcg_temp_free_i32(ahp_mode);
2573     tcg_temp_free_ptr(fpst);
2574     tcg_temp_free_i32(tmp);
2575     return true;
2576 }
2577
2578 static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
2579 {
2580     TCGv_ptr fpst;
2581     TCGv_i32 ahp_mode;
2582     TCGv_i32 tmp;
2583     TCGv_i64 vm;
2584
2585     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2586         return false;
2587     }
2588
2589     if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
2590         return false;
2591     }
2592
2593     /* UNDEF accesses to D16-D31 if they don't exist. */
2594     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm  & 0x10)) {
2595         return false;
2596     }
2597
2598     if (!vfp_access_check(s)) {
2599         return true;
2600     }
2601
2602     fpst = fpstatus_ptr(FPST_FPCR);
2603     ahp_mode = get_ahp_flag();
2604     tmp = tcg_temp_new_i32();
2605     vm = tcg_temp_new_i64();
2606
2607     neon_load_reg64(vm, a->vm);
2608     gen_helper_vfp_fcvt_f64_to_f16(tmp, vm, fpst, ahp_mode);
2609     tcg_temp_free_i64(vm);
2610     tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t));
2611     tcg_temp_free_i32(ahp_mode);
2612     tcg_temp_free_ptr(fpst);
2613     tcg_temp_free_i32(tmp);
2614     return true;
2615 }
2616
2617 static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a)
2618 {
2619     TCGv_ptr fpst;
2620     TCGv_i32 tmp;
2621
2622     if (!dc_isar_feature(aa32_vrint, s)) {
2623         return false;
2624     }
2625
2626     if (!vfp_access_check(s)) {
2627         return true;
2628     }
2629
2630     tmp = tcg_temp_new_i32();
2631     neon_load_reg32(tmp, a->vm);
2632     fpst = fpstatus_ptr(FPST_FPCR);
2633     gen_helper_rints(tmp, tmp, fpst);
2634     neon_store_reg32(tmp, a->vd);
2635     tcg_temp_free_ptr(fpst);
2636     tcg_temp_free_i32(tmp);
2637     return true;
2638 }
2639
2640 static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
2641 {
2642     TCGv_ptr fpst;
2643     TCGv_i64 tmp;
2644
2645     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2646         return false;
2647     }
2648
2649     if (!dc_isar_feature(aa32_vrint, s)) {
2650         return false;
2651     }
2652
2653     /* UNDEF accesses to D16-D31 if they don't exist. */
2654     if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2655         return false;
2656     }
2657
2658     if (!vfp_access_check(s)) {
2659         return true;
2660     }
2661
2662     tmp = tcg_temp_new_i64();
2663     neon_load_reg64(tmp, a->vm);
2664     fpst = fpstatus_ptr(FPST_FPCR);
2665     gen_helper_rintd(tmp, tmp, fpst);
2666     neon_store_reg64(tmp, a->vd);
2667     tcg_temp_free_ptr(fpst);
2668     tcg_temp_free_i64(tmp);
2669     return true;
2670 }
2671
2672 static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a)
2673 {
2674     TCGv_ptr fpst;
2675     TCGv_i32 tmp;
2676     TCGv_i32 tcg_rmode;
2677
2678     if (!dc_isar_feature(aa32_vrint, s)) {
2679         return false;
2680     }
2681
2682     if (!vfp_access_check(s)) {
2683         return true;
2684     }
2685
2686     tmp = tcg_temp_new_i32();
2687     neon_load_reg32(tmp, a->vm);
2688     fpst = fpstatus_ptr(FPST_FPCR);
2689     tcg_rmode = tcg_const_i32(float_round_to_zero);
2690     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
2691     gen_helper_rints(tmp, tmp, fpst);
2692     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
2693     neon_store_reg32(tmp, a->vd);
2694     tcg_temp_free_ptr(fpst);
2695     tcg_temp_free_i32(tcg_rmode);
2696     tcg_temp_free_i32(tmp);
2697     return true;
2698 }
2699
2700 static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
2701 {
2702     TCGv_ptr fpst;
2703     TCGv_i64 tmp;
2704     TCGv_i32 tcg_rmode;
2705
2706     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2707         return false;
2708     }
2709
2710     if (!dc_isar_feature(aa32_vrint, s)) {
2711         return false;
2712     }
2713
2714     /* UNDEF accesses to D16-D31 if they don't exist. */
2715     if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2716         return false;
2717     }
2718
2719     if (!vfp_access_check(s)) {
2720         return true;
2721     }
2722
2723     tmp = tcg_temp_new_i64();
2724     neon_load_reg64(tmp, a->vm);
2725     fpst = fpstatus_ptr(FPST_FPCR);
2726     tcg_rmode = tcg_const_i32(float_round_to_zero);
2727     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
2728     gen_helper_rintd(tmp, tmp, fpst);
2729     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
2730     neon_store_reg64(tmp, a->vd);
2731     tcg_temp_free_ptr(fpst);
2732     tcg_temp_free_i64(tmp);
2733     tcg_temp_free_i32(tcg_rmode);
2734     return true;
2735 }
2736
2737 static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a)
2738 {
2739     TCGv_ptr fpst;
2740     TCGv_i32 tmp;
2741
2742     if (!dc_isar_feature(aa32_vrint, s)) {
2743         return false;
2744     }
2745
2746     if (!vfp_access_check(s)) {
2747         return true;
2748     }
2749
2750     tmp = tcg_temp_new_i32();
2751     neon_load_reg32(tmp, a->vm);
2752     fpst = fpstatus_ptr(FPST_FPCR);
2753     gen_helper_rints_exact(tmp, tmp, fpst);
2754     neon_store_reg32(tmp, a->vd);
2755     tcg_temp_free_ptr(fpst);
2756     tcg_temp_free_i32(tmp);
2757     return true;
2758 }
2759
2760 static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
2761 {
2762     TCGv_ptr fpst;
2763     TCGv_i64 tmp;
2764
2765     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2766         return false;
2767     }
2768
2769     if (!dc_isar_feature(aa32_vrint, s)) {
2770         return false;
2771     }
2772
2773     /* UNDEF accesses to D16-D31 if they don't exist. */
2774     if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2775         return false;
2776     }
2777
2778     if (!vfp_access_check(s)) {
2779         return true;
2780     }
2781
2782     tmp = tcg_temp_new_i64();
2783     neon_load_reg64(tmp, a->vm);
2784     fpst = fpstatus_ptr(FPST_FPCR);
2785     gen_helper_rintd_exact(tmp, tmp, fpst);
2786     neon_store_reg64(tmp, a->vd);
2787     tcg_temp_free_ptr(fpst);
2788     tcg_temp_free_i64(tmp);
2789     return true;
2790 }
2791
2792 static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
2793 {
2794     TCGv_i64 vd;
2795     TCGv_i32 vm;
2796
2797     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2798         return false;
2799     }
2800
2801     /* UNDEF accesses to D16-D31 if they don't exist. */
2802     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
2803         return false;
2804     }
2805
2806     if (!vfp_access_check(s)) {
2807         return true;
2808     }
2809
2810     vm = tcg_temp_new_i32();
2811     vd = tcg_temp_new_i64();
2812     neon_load_reg32(vm, a->vm);
2813     gen_helper_vfp_fcvtds(vd, vm, cpu_env);
2814     neon_store_reg64(vd, a->vd);
2815     tcg_temp_free_i32(vm);
2816     tcg_temp_free_i64(vd);
2817     return true;
2818 }
2819
2820 static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
2821 {
2822     TCGv_i64 vm;
2823     TCGv_i32 vd;
2824
2825     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2826         return false;
2827     }
2828
2829     /* UNDEF accesses to D16-D31 if they don't exist. */
2830     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
2831         return false;
2832     }
2833
2834     if (!vfp_access_check(s)) {
2835         return true;
2836     }
2837
2838     vd = tcg_temp_new_i32();
2839     vm = tcg_temp_new_i64();
2840     neon_load_reg64(vm, a->vm);
2841     gen_helper_vfp_fcvtsd(vd, vm, cpu_env);
2842     neon_store_reg32(vd, a->vd);
2843     tcg_temp_free_i32(vd);
2844     tcg_temp_free_i64(vm);
2845     return true;
2846 }
2847
2848 static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a)
2849 {
2850     TCGv_i32 vm;
2851     TCGv_ptr fpst;
2852
2853     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
2854         return false;
2855     }
2856
2857     if (!vfp_access_check(s)) {
2858         return true;
2859     }
2860
2861     vm = tcg_temp_new_i32();
2862     neon_load_reg32(vm, a->vm);
2863     fpst = fpstatus_ptr(FPST_FPCR);
2864     if (a->s) {
2865         /* i32 -> f32 */
2866         gen_helper_vfp_sitos(vm, vm, fpst);
2867     } else {
2868         /* u32 -> f32 */
2869         gen_helper_vfp_uitos(vm, vm, fpst);
2870     }
2871     neon_store_reg32(vm, a->vd);
2872     tcg_temp_free_i32(vm);
2873     tcg_temp_free_ptr(fpst);
2874     return true;
2875 }
2876
2877 static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
2878 {
2879     TCGv_i32 vm;
2880     TCGv_i64 vd;
2881     TCGv_ptr fpst;
2882
2883     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2884         return false;
2885     }
2886
2887     /* UNDEF accesses to D16-D31 if they don't exist. */
2888     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
2889         return false;
2890     }
2891
2892     if (!vfp_access_check(s)) {
2893         return true;
2894     }
2895
2896     vm = tcg_temp_new_i32();
2897     vd = tcg_temp_new_i64();
2898     neon_load_reg32(vm, a->vm);
2899     fpst = fpstatus_ptr(FPST_FPCR);
2900     if (a->s) {
2901         /* i32 -> f64 */
2902         gen_helper_vfp_sitod(vd, vm, fpst);
2903     } else {
2904         /* u32 -> f64 */
2905         gen_helper_vfp_uitod(vd, vm, fpst);
2906     }
2907     neon_store_reg64(vd, a->vd);
2908     tcg_temp_free_i32(vm);
2909     tcg_temp_free_i64(vd);
2910     tcg_temp_free_ptr(fpst);
2911     return true;
2912 }
2913
2914 static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
2915 {
2916     TCGv_i32 vd;
2917     TCGv_i64 vm;
2918
2919     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2920         return false;
2921     }
2922
2923     if (!dc_isar_feature(aa32_jscvt, s)) {
2924         return false;
2925     }
2926
2927     /* UNDEF accesses to D16-D31 if they don't exist. */
2928     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
2929         return false;
2930     }
2931
2932     if (!vfp_access_check(s)) {
2933         return true;
2934     }
2935
2936     vm = tcg_temp_new_i64();
2937     vd = tcg_temp_new_i32();
2938     neon_load_reg64(vm, a->vm);
2939     gen_helper_vjcvt(vd, vm, cpu_env);
2940     neon_store_reg32(vd, a->vd);
2941     tcg_temp_free_i64(vm);
2942     tcg_temp_free_i32(vd);
2943     return true;
2944 }
2945
2946 static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
2947 {
2948     TCGv_i32 vd, shift;
2949     TCGv_ptr fpst;
2950     int frac_bits;
2951
2952     if (!dc_isar_feature(aa32_fpsp_v3, s)) {
2953         return false;
2954     }
2955
2956     if (!vfp_access_check(s)) {
2957         return true;
2958     }
2959
2960     frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
2961
2962     vd = tcg_temp_new_i32();
2963     neon_load_reg32(vd, a->vd);
2964
2965     fpst = fpstatus_ptr(FPST_FPCR);
2966     shift = tcg_const_i32(frac_bits);
2967
2968     /* Switch on op:U:sx bits */
2969     switch (a->opc) {
2970     case 0:
2971         gen_helper_vfp_shtos(vd, vd, shift, fpst);
2972         break;
2973     case 1:
2974         gen_helper_vfp_sltos(vd, vd, shift, fpst);
2975         break;
2976     case 2:
2977         gen_helper_vfp_uhtos(vd, vd, shift, fpst);
2978         break;
2979     case 3:
2980         gen_helper_vfp_ultos(vd, vd, shift, fpst);
2981         break;
2982     case 4:
2983         gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
2984         break;
2985     case 5:
2986         gen_helper_vfp_tosls_round_to_zero(vd, vd, shift, fpst);
2987         break;
2988     case 6:
2989         gen_helper_vfp_touhs_round_to_zero(vd, vd, shift, fpst);
2990         break;
2991     case 7:
2992         gen_helper_vfp_touls_round_to_zero(vd, vd, shift, fpst);
2993         break;
2994     default:
2995         g_assert_not_reached();
2996     }
2997
2998     neon_store_reg32(vd, a->vd);
2999     tcg_temp_free_i32(vd);
3000     tcg_temp_free_i32(shift);
3001     tcg_temp_free_ptr(fpst);
3002     return true;
3003 }
3004
3005 static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
3006 {
3007     TCGv_i64 vd;
3008     TCGv_i32 shift;
3009     TCGv_ptr fpst;
3010     int frac_bits;
3011
3012     if (!dc_isar_feature(aa32_fpdp_v3, s)) {
3013         return false;
3014     }
3015
3016     /* UNDEF accesses to D16-D31 if they don't exist. */
3017     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
3018         return false;
3019     }
3020
3021     if (!vfp_access_check(s)) {
3022         return true;
3023     }
3024
3025     frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
3026
3027     vd = tcg_temp_new_i64();
3028     neon_load_reg64(vd, a->vd);
3029
3030     fpst = fpstatus_ptr(FPST_FPCR);
3031     shift = tcg_const_i32(frac_bits);
3032
3033     /* Switch on op:U:sx bits */
3034     switch (a->opc) {
3035     case 0:
3036         gen_helper_vfp_shtod(vd, vd, shift, fpst);
3037         break;
3038     case 1:
3039         gen_helper_vfp_sltod(vd, vd, shift, fpst);
3040         break;
3041     case 2:
3042         gen_helper_vfp_uhtod(vd, vd, shift, fpst);
3043         break;
3044     case 3:
3045         gen_helper_vfp_ultod(vd, vd, shift, fpst);
3046         break;
3047     case 4:
3048         gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
3049         break;
3050     case 5:
3051         gen_helper_vfp_tosld_round_to_zero(vd, vd, shift, fpst);
3052         break;
3053     case 6:
3054         gen_helper_vfp_touhd_round_to_zero(vd, vd, shift, fpst);
3055         break;
3056     case 7:
3057         gen_helper_vfp_tould_round_to_zero(vd, vd, shift, fpst);
3058         break;
3059     default:
3060         g_assert_not_reached();
3061     }
3062
3063     neon_store_reg64(vd, a->vd);
3064     tcg_temp_free_i64(vd);
3065     tcg_temp_free_i32(shift);
3066     tcg_temp_free_ptr(fpst);
3067     return true;
3068 }
3069
3070 static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a)
3071 {
3072     TCGv_i32 vm;
3073     TCGv_ptr fpst;
3074
3075     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
3076         return false;
3077     }
3078
3079     if (!vfp_access_check(s)) {
3080         return true;
3081     }
3082
3083     fpst = fpstatus_ptr(FPST_FPCR);
3084     vm = tcg_temp_new_i32();
3085     neon_load_reg32(vm, a->vm);
3086
3087     if (a->s) {
3088         if (a->rz) {
3089             gen_helper_vfp_tosizs(vm, vm, fpst);
3090         } else {
3091             gen_helper_vfp_tosis(vm, vm, fpst);
3092         }
3093     } else {
3094         if (a->rz) {
3095             gen_helper_vfp_touizs(vm, vm, fpst);
3096         } else {
3097             gen_helper_vfp_touis(vm, vm, fpst);
3098         }
3099     }
3100     neon_store_reg32(vm, a->vd);
3101     tcg_temp_free_i32(vm);
3102     tcg_temp_free_ptr(fpst);
3103     return true;
3104 }
3105
3106 static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
3107 {
3108     TCGv_i32 vd;
3109     TCGv_i64 vm;
3110     TCGv_ptr fpst;
3111
3112     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
3113         return false;
3114     }
3115
3116     /* UNDEF accesses to D16-D31 if they don't exist. */
3117     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
3118         return false;
3119     }
3120
3121     if (!vfp_access_check(s)) {
3122         return true;
3123     }
3124
3125     fpst = fpstatus_ptr(FPST_FPCR);
3126     vm = tcg_temp_new_i64();
3127     vd = tcg_temp_new_i32();
3128     neon_load_reg64(vm, a->vm);
3129
3130     if (a->s) {
3131         if (a->rz) {
3132             gen_helper_vfp_tosizd(vd, vm, fpst);
3133         } else {
3134             gen_helper_vfp_tosid(vd, vm, fpst);
3135         }
3136     } else {
3137         if (a->rz) {
3138             gen_helper_vfp_touizd(vd, vm, fpst);
3139         } else {
3140             gen_helper_vfp_touid(vd, vm, fpst);
3141         }
3142     }
3143     neon_store_reg32(vd, a->vd);
3144     tcg_temp_free_i32(vd);
3145     tcg_temp_free_i64(vm);
3146     tcg_temp_free_ptr(fpst);
3147     return true;
3148 }
3149
3150 /*
3151  * Decode VLLDM and VLSTM are nonstandard because:
3152  *  * if there is no FPU then these insns must NOP in
3153  *    Secure state and UNDEF in Nonsecure state
3154  *  * if there is an FPU then these insns do not have
3155  *    the usual behaviour that vfp_access_check() provides of
3156  *    being controlled by CPACR/NSACR enable bits or the
3157  *    lazy-stacking logic.
3158  */
3159 static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
3160 {
3161     TCGv_i32 fptr;
3162
3163     if (!arm_dc_feature(s, ARM_FEATURE_M) ||
3164         !arm_dc_feature(s, ARM_FEATURE_V8)) {
3165         return false;
3166     }
3167     /*
3168      * If not secure, UNDEF. We must emit code for this
3169      * rather than returning false so that this takes
3170      * precedence over the m-nocp.decode NOCP fallback.
3171      */
3172     if (!s->v8m_secure) {
3173         unallocated_encoding(s);
3174         return true;
3175     }
3176     /* If no fpu, NOP. */
3177     if (!dc_isar_feature(aa32_vfp, s)) {
3178         return true;
3179     }
3180
3181     fptr = load_reg(s, a->rn);
3182     if (a->l) {
3183         gen_helper_v7m_vlldm(cpu_env, fptr);
3184     } else {
3185         gen_helper_v7m_vlstm(cpu_env, fptr);
3186     }
3187     tcg_temp_free_i32(fptr);
3188
3189     /* End the TB, because we have updated FP control bits */
3190     s->base.is_jmp = DISAS_UPDATE_EXIT;
3191     return true;
3192 }
3193
3194 static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
3195 {
3196     /*
3197      * Handle M-profile early check for disabled coprocessor:
3198      * all we need to do here is emit the NOCP exception if
3199      * the coprocessor is disabled. Otherwise we return false
3200      * and the real VFP/etc decode will handle the insn.
3201      */
3202     assert(arm_dc_feature(s, ARM_FEATURE_M));
3203
3204     if (a->cp == 11) {
3205         a->cp = 10;
3206     }
3207     /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
3208
3209     if (a->cp != 10) {
3210         gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
3211                            syn_uncategorized(), default_exception_el(s));
3212         return true;
3213     }
3214
3215     if (s->fp_excp_el != 0) {
3216         gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
3217                            syn_uncategorized(), s->fp_excp_el);
3218         return true;
3219     }
3220
3221     return false;
3222 }