target/arm: Implement VFP fp16 VCMP
[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_sp(DisasContext *s, arg_VLDR_VSTR_sp *a)
890 {
891     uint32_t offset;
892     TCGv_i32 addr, tmp;
893
894     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
895         return false;
896     }
897
898     if (!vfp_access_check(s)) {
899         return true;
900     }
901
902     offset = a->imm << 2;
903     if (!a->u) {
904         offset = -offset;
905     }
906
907     /* For thumb, use of PC is UNPREDICTABLE.  */
908     addr = add_reg_for_lit(s, a->rn, offset);
909     tmp = tcg_temp_new_i32();
910     if (a->l) {
911         gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
912         neon_store_reg32(tmp, a->vd);
913     } else {
914         neon_load_reg32(tmp, a->vd);
915         gen_aa32_st32(s, tmp, addr, get_mem_index(s));
916     }
917     tcg_temp_free_i32(tmp);
918     tcg_temp_free_i32(addr);
919
920     return true;
921 }
922
923 static bool trans_VLDR_VSTR_dp(DisasContext *s, arg_VLDR_VSTR_dp *a)
924 {
925     uint32_t offset;
926     TCGv_i32 addr;
927     TCGv_i64 tmp;
928
929     /* Note that this does not require support for double arithmetic.  */
930     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
931         return false;
932     }
933
934     /* UNDEF accesses to D16-D31 if they don't exist */
935     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
936         return false;
937     }
938
939     if (!vfp_access_check(s)) {
940         return true;
941     }
942
943     offset = a->imm << 2;
944     if (!a->u) {
945         offset = -offset;
946     }
947
948     /* For thumb, use of PC is UNPREDICTABLE.  */
949     addr = add_reg_for_lit(s, a->rn, offset);
950     tmp = tcg_temp_new_i64();
951     if (a->l) {
952         gen_aa32_ld64(s, tmp, addr, get_mem_index(s));
953         neon_store_reg64(tmp, a->vd);
954     } else {
955         neon_load_reg64(tmp, a->vd);
956         gen_aa32_st64(s, tmp, addr, get_mem_index(s));
957     }
958     tcg_temp_free_i64(tmp);
959     tcg_temp_free_i32(addr);
960
961     return true;
962 }
963
964 static bool trans_VLDM_VSTM_sp(DisasContext *s, arg_VLDM_VSTM_sp *a)
965 {
966     uint32_t offset;
967     TCGv_i32 addr, tmp;
968     int i, n;
969
970     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
971         return false;
972     }
973
974     n = a->imm;
975
976     if (n == 0 || (a->vd + n) > 32) {
977         /*
978          * UNPREDICTABLE cases for bad immediates: we choose to
979          * UNDEF to avoid generating huge numbers of TCG ops
980          */
981         return false;
982     }
983     if (a->rn == 15 && a->w) {
984         /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
985         return false;
986     }
987
988     if (!vfp_access_check(s)) {
989         return true;
990     }
991
992     /* For thumb, use of PC is UNPREDICTABLE.  */
993     addr = add_reg_for_lit(s, a->rn, 0);
994     if (a->p) {
995         /* pre-decrement */
996         tcg_gen_addi_i32(addr, addr, -(a->imm << 2));
997     }
998
999     if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1000         /*
1001          * Here 'addr' is the lowest address we will store to,
1002          * and is either the old SP (if post-increment) or
1003          * the new SP (if pre-decrement). For post-increment
1004          * where the old value is below the limit and the new
1005          * value is above, it is UNKNOWN whether the limit check
1006          * triggers; we choose to trigger.
1007          */
1008         gen_helper_v8m_stackcheck(cpu_env, addr);
1009     }
1010
1011     offset = 4;
1012     tmp = tcg_temp_new_i32();
1013     for (i = 0; i < n; i++) {
1014         if (a->l) {
1015             /* load */
1016             gen_aa32_ld32u(s, tmp, addr, get_mem_index(s));
1017             neon_store_reg32(tmp, a->vd + i);
1018         } else {
1019             /* store */
1020             neon_load_reg32(tmp, a->vd + i);
1021             gen_aa32_st32(s, tmp, addr, get_mem_index(s));
1022         }
1023         tcg_gen_addi_i32(addr, addr, offset);
1024     }
1025     tcg_temp_free_i32(tmp);
1026     if (a->w) {
1027         /* writeback */
1028         if (a->p) {
1029             offset = -offset * n;
1030             tcg_gen_addi_i32(addr, addr, offset);
1031         }
1032         store_reg(s, a->rn, addr);
1033     } else {
1034         tcg_temp_free_i32(addr);
1035     }
1036
1037     return true;
1038 }
1039
1040 static bool trans_VLDM_VSTM_dp(DisasContext *s, arg_VLDM_VSTM_dp *a)
1041 {
1042     uint32_t offset;
1043     TCGv_i32 addr;
1044     TCGv_i64 tmp;
1045     int i, n;
1046
1047     /* Note that this does not require support for double arithmetic.  */
1048     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1049         return false;
1050     }
1051
1052     n = a->imm >> 1;
1053
1054     if (n == 0 || (a->vd + n) > 32 || n > 16) {
1055         /*
1056          * UNPREDICTABLE cases for bad immediates: we choose to
1057          * UNDEF to avoid generating huge numbers of TCG ops
1058          */
1059         return false;
1060     }
1061     if (a->rn == 15 && a->w) {
1062         /* writeback to PC is UNPREDICTABLE, we choose to UNDEF */
1063         return false;
1064     }
1065
1066     /* UNDEF accesses to D16-D31 if they don't exist */
1067     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd + n) > 16) {
1068         return false;
1069     }
1070
1071     if (!vfp_access_check(s)) {
1072         return true;
1073     }
1074
1075     /* For thumb, use of PC is UNPREDICTABLE.  */
1076     addr = add_reg_for_lit(s, a->rn, 0);
1077     if (a->p) {
1078         /* pre-decrement */
1079         tcg_gen_addi_i32(addr, addr, -(a->imm << 2));
1080     }
1081
1082     if (s->v8m_stackcheck && a->rn == 13 && a->w) {
1083         /*
1084          * Here 'addr' is the lowest address we will store to,
1085          * and is either the old SP (if post-increment) or
1086          * the new SP (if pre-decrement). For post-increment
1087          * where the old value is below the limit and the new
1088          * value is above, it is UNKNOWN whether the limit check
1089          * triggers; we choose to trigger.
1090          */
1091         gen_helper_v8m_stackcheck(cpu_env, addr);
1092     }
1093
1094     offset = 8;
1095     tmp = tcg_temp_new_i64();
1096     for (i = 0; i < n; i++) {
1097         if (a->l) {
1098             /* load */
1099             gen_aa32_ld64(s, tmp, addr, get_mem_index(s));
1100             neon_store_reg64(tmp, a->vd + i);
1101         } else {
1102             /* store */
1103             neon_load_reg64(tmp, a->vd + i);
1104             gen_aa32_st64(s, tmp, addr, get_mem_index(s));
1105         }
1106         tcg_gen_addi_i32(addr, addr, offset);
1107     }
1108     tcg_temp_free_i64(tmp);
1109     if (a->w) {
1110         /* writeback */
1111         if (a->p) {
1112             offset = -offset * n;
1113         } else if (a->imm & 1) {
1114             offset = 4;
1115         } else {
1116             offset = 0;
1117         }
1118
1119         if (offset != 0) {
1120             tcg_gen_addi_i32(addr, addr, offset);
1121         }
1122         store_reg(s, a->rn, addr);
1123     } else {
1124         tcg_temp_free_i32(addr);
1125     }
1126
1127     return true;
1128 }
1129
1130 /*
1131  * Types for callbacks for do_vfp_3op_sp() and do_vfp_3op_dp().
1132  * The callback should emit code to write a value to vd. If
1133  * do_vfp_3op_{sp,dp}() was passed reads_vd then the TCGv vd
1134  * will contain the old value of the relevant VFP register;
1135  * otherwise it must be written to only.
1136  */
1137 typedef void VFPGen3OpSPFn(TCGv_i32 vd,
1138                            TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst);
1139 typedef void VFPGen3OpDPFn(TCGv_i64 vd,
1140                            TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst);
1141
1142 /*
1143  * Types for callbacks for do_vfp_2op_sp() and do_vfp_2op_dp().
1144  * The callback should emit code to write a value to vd (which
1145  * should be written to only).
1146  */
1147 typedef void VFPGen2OpSPFn(TCGv_i32 vd, TCGv_i32 vm);
1148 typedef void VFPGen2OpDPFn(TCGv_i64 vd, TCGv_i64 vm);
1149
1150 /*
1151  * Return true if the specified S reg is in a scalar bank
1152  * (ie if it is s0..s7)
1153  */
1154 static inline bool vfp_sreg_is_scalar(int reg)
1155 {
1156     return (reg & 0x18) == 0;
1157 }
1158
1159 /*
1160  * Return true if the specified D reg is in a scalar bank
1161  * (ie if it is d0..d3 or d16..d19)
1162  */
1163 static inline bool vfp_dreg_is_scalar(int reg)
1164 {
1165     return (reg & 0xc) == 0;
1166 }
1167
1168 /*
1169  * Advance the S reg number forwards by delta within its bank
1170  * (ie increment the low 3 bits but leave the rest the same)
1171  */
1172 static inline int vfp_advance_sreg(int reg, int delta)
1173 {
1174     return ((reg + delta) & 0x7) | (reg & ~0x7);
1175 }
1176
1177 /*
1178  * Advance the D reg number forwards by delta within its bank
1179  * (ie increment the low 2 bits but leave the rest the same)
1180  */
1181 static inline int vfp_advance_dreg(int reg, int delta)
1182 {
1183     return ((reg + delta) & 0x3) | (reg & ~0x3);
1184 }
1185
1186 /*
1187  * Perform a 3-operand VFP data processing instruction. fn is the
1188  * callback to do the actual operation; this function deals with the
1189  * code to handle looping around for VFP vector processing.
1190  */
1191 static bool do_vfp_3op_sp(DisasContext *s, VFPGen3OpSPFn *fn,
1192                           int vd, int vn, int vm, bool reads_vd)
1193 {
1194     uint32_t delta_m = 0;
1195     uint32_t delta_d = 0;
1196     int veclen = s->vec_len;
1197     TCGv_i32 f0, f1, fd;
1198     TCGv_ptr fpst;
1199
1200     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1201         return false;
1202     }
1203
1204     if (!dc_isar_feature(aa32_fpshvec, s) &&
1205         (veclen != 0 || s->vec_stride != 0)) {
1206         return false;
1207     }
1208
1209     if (!vfp_access_check(s)) {
1210         return true;
1211     }
1212
1213     if (veclen > 0) {
1214         /* Figure out what type of vector operation this is.  */
1215         if (vfp_sreg_is_scalar(vd)) {
1216             /* scalar */
1217             veclen = 0;
1218         } else {
1219             delta_d = s->vec_stride + 1;
1220
1221             if (vfp_sreg_is_scalar(vm)) {
1222                 /* mixed scalar/vector */
1223                 delta_m = 0;
1224             } else {
1225                 /* vector */
1226                 delta_m = delta_d;
1227             }
1228         }
1229     }
1230
1231     f0 = tcg_temp_new_i32();
1232     f1 = tcg_temp_new_i32();
1233     fd = tcg_temp_new_i32();
1234     fpst = fpstatus_ptr(FPST_FPCR);
1235
1236     neon_load_reg32(f0, vn);
1237     neon_load_reg32(f1, vm);
1238
1239     for (;;) {
1240         if (reads_vd) {
1241             neon_load_reg32(fd, vd);
1242         }
1243         fn(fd, f0, f1, fpst);
1244         neon_store_reg32(fd, vd);
1245
1246         if (veclen == 0) {
1247             break;
1248         }
1249
1250         /* Set up the operands for the next iteration */
1251         veclen--;
1252         vd = vfp_advance_sreg(vd, delta_d);
1253         vn = vfp_advance_sreg(vn, delta_d);
1254         neon_load_reg32(f0, vn);
1255         if (delta_m) {
1256             vm = vfp_advance_sreg(vm, delta_m);
1257             neon_load_reg32(f1, vm);
1258         }
1259     }
1260
1261     tcg_temp_free_i32(f0);
1262     tcg_temp_free_i32(f1);
1263     tcg_temp_free_i32(fd);
1264     tcg_temp_free_ptr(fpst);
1265
1266     return true;
1267 }
1268
1269 static bool do_vfp_3op_hp(DisasContext *s, VFPGen3OpSPFn *fn,
1270                           int vd, int vn, int vm, bool reads_vd)
1271 {
1272     /*
1273      * Do a half-precision operation. Functionally this is
1274      * the same as do_vfp_3op_sp(), except:
1275      *  - it uses the FPST_FPCR_F16
1276      *  - it doesn't need the VFP vector handling (fp16 is a
1277      *    v8 feature, and in v8 VFP vectors don't exist)
1278      *  - it does the aa32_fp16_arith feature test
1279      */
1280     TCGv_i32 f0, f1, fd;
1281     TCGv_ptr fpst;
1282
1283     if (!dc_isar_feature(aa32_fp16_arith, s)) {
1284         return false;
1285     }
1286
1287     if (s->vec_len != 0 || s->vec_stride != 0) {
1288         return false;
1289     }
1290
1291     if (!vfp_access_check(s)) {
1292         return true;
1293     }
1294
1295     f0 = tcg_temp_new_i32();
1296     f1 = tcg_temp_new_i32();
1297     fd = tcg_temp_new_i32();
1298     fpst = fpstatus_ptr(FPST_FPCR_F16);
1299
1300     neon_load_reg32(f0, vn);
1301     neon_load_reg32(f1, vm);
1302
1303     if (reads_vd) {
1304         neon_load_reg32(fd, vd);
1305     }
1306     fn(fd, f0, f1, fpst);
1307     neon_store_reg32(fd, vd);
1308
1309     tcg_temp_free_i32(f0);
1310     tcg_temp_free_i32(f1);
1311     tcg_temp_free_i32(fd);
1312     tcg_temp_free_ptr(fpst);
1313
1314     return true;
1315 }
1316
1317 static bool do_vfp_3op_dp(DisasContext *s, VFPGen3OpDPFn *fn,
1318                           int vd, int vn, int vm, bool reads_vd)
1319 {
1320     uint32_t delta_m = 0;
1321     uint32_t delta_d = 0;
1322     int veclen = s->vec_len;
1323     TCGv_i64 f0, f1, fd;
1324     TCGv_ptr fpst;
1325
1326     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
1327         return false;
1328     }
1329
1330     /* UNDEF accesses to D16-D31 if they don't exist */
1331     if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vn | vm) & 0x10)) {
1332         return false;
1333     }
1334
1335     if (!dc_isar_feature(aa32_fpshvec, s) &&
1336         (veclen != 0 || s->vec_stride != 0)) {
1337         return false;
1338     }
1339
1340     if (!vfp_access_check(s)) {
1341         return true;
1342     }
1343
1344     if (veclen > 0) {
1345         /* Figure out what type of vector operation this is.  */
1346         if (vfp_dreg_is_scalar(vd)) {
1347             /* scalar */
1348             veclen = 0;
1349         } else {
1350             delta_d = (s->vec_stride >> 1) + 1;
1351
1352             if (vfp_dreg_is_scalar(vm)) {
1353                 /* mixed scalar/vector */
1354                 delta_m = 0;
1355             } else {
1356                 /* vector */
1357                 delta_m = delta_d;
1358             }
1359         }
1360     }
1361
1362     f0 = tcg_temp_new_i64();
1363     f1 = tcg_temp_new_i64();
1364     fd = tcg_temp_new_i64();
1365     fpst = fpstatus_ptr(FPST_FPCR);
1366
1367     neon_load_reg64(f0, vn);
1368     neon_load_reg64(f1, vm);
1369
1370     for (;;) {
1371         if (reads_vd) {
1372             neon_load_reg64(fd, vd);
1373         }
1374         fn(fd, f0, f1, fpst);
1375         neon_store_reg64(fd, vd);
1376
1377         if (veclen == 0) {
1378             break;
1379         }
1380         /* Set up the operands for the next iteration */
1381         veclen--;
1382         vd = vfp_advance_dreg(vd, delta_d);
1383         vn = vfp_advance_dreg(vn, delta_d);
1384         neon_load_reg64(f0, vn);
1385         if (delta_m) {
1386             vm = vfp_advance_dreg(vm, delta_m);
1387             neon_load_reg64(f1, vm);
1388         }
1389     }
1390
1391     tcg_temp_free_i64(f0);
1392     tcg_temp_free_i64(f1);
1393     tcg_temp_free_i64(fd);
1394     tcg_temp_free_ptr(fpst);
1395
1396     return true;
1397 }
1398
1399 static bool do_vfp_2op_sp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
1400 {
1401     uint32_t delta_m = 0;
1402     uint32_t delta_d = 0;
1403     int veclen = s->vec_len;
1404     TCGv_i32 f0, fd;
1405
1406     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
1407         return false;
1408     }
1409
1410     if (!dc_isar_feature(aa32_fpshvec, s) &&
1411         (veclen != 0 || s->vec_stride != 0)) {
1412         return false;
1413     }
1414
1415     if (!vfp_access_check(s)) {
1416         return true;
1417     }
1418
1419     if (veclen > 0) {
1420         /* Figure out what type of vector operation this is.  */
1421         if (vfp_sreg_is_scalar(vd)) {
1422             /* scalar */
1423             veclen = 0;
1424         } else {
1425             delta_d = s->vec_stride + 1;
1426
1427             if (vfp_sreg_is_scalar(vm)) {
1428                 /* mixed scalar/vector */
1429                 delta_m = 0;
1430             } else {
1431                 /* vector */
1432                 delta_m = delta_d;
1433             }
1434         }
1435     }
1436
1437     f0 = tcg_temp_new_i32();
1438     fd = tcg_temp_new_i32();
1439
1440     neon_load_reg32(f0, vm);
1441
1442     for (;;) {
1443         fn(fd, f0);
1444         neon_store_reg32(fd, vd);
1445
1446         if (veclen == 0) {
1447             break;
1448         }
1449
1450         if (delta_m == 0) {
1451             /* single source one-many */
1452             while (veclen--) {
1453                 vd = vfp_advance_sreg(vd, delta_d);
1454                 neon_store_reg32(fd, vd);
1455             }
1456             break;
1457         }
1458
1459         /* Set up the operands for the next iteration */
1460         veclen--;
1461         vd = vfp_advance_sreg(vd, delta_d);
1462         vm = vfp_advance_sreg(vm, delta_m);
1463         neon_load_reg32(f0, vm);
1464     }
1465
1466     tcg_temp_free_i32(f0);
1467     tcg_temp_free_i32(fd);
1468
1469     return true;
1470 }
1471
1472 static bool do_vfp_2op_hp(DisasContext *s, VFPGen2OpSPFn *fn, int vd, int vm)
1473 {
1474     /*
1475      * Do a half-precision operation. Functionally this is
1476      * the same as do_vfp_2op_sp(), except:
1477      *  - it doesn't need the VFP vector handling (fp16 is a
1478      *    v8 feature, and in v8 VFP vectors don't exist)
1479      *  - it does the aa32_fp16_arith feature test
1480      */
1481     TCGv_i32 f0;
1482
1483     if (!dc_isar_feature(aa32_fp16_arith, s)) {
1484         return false;
1485     }
1486
1487     if (s->vec_len != 0 || s->vec_stride != 0) {
1488         return false;
1489     }
1490
1491     if (!vfp_access_check(s)) {
1492         return true;
1493     }
1494
1495     f0 = tcg_temp_new_i32();
1496     neon_load_reg32(f0, vm);
1497     fn(f0, f0);
1498     neon_store_reg32(f0, vd);
1499     tcg_temp_free_i32(f0);
1500
1501     return true;
1502 }
1503
1504 static bool do_vfp_2op_dp(DisasContext *s, VFPGen2OpDPFn *fn, int vd, int vm)
1505 {
1506     uint32_t delta_m = 0;
1507     uint32_t delta_d = 0;
1508     int veclen = s->vec_len;
1509     TCGv_i64 f0, fd;
1510
1511     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
1512         return false;
1513     }
1514
1515     /* UNDEF accesses to D16-D31 if they don't exist */
1516     if (!dc_isar_feature(aa32_simd_r32, s) && ((vd | vm) & 0x10)) {
1517         return false;
1518     }
1519
1520     if (!dc_isar_feature(aa32_fpshvec, s) &&
1521         (veclen != 0 || s->vec_stride != 0)) {
1522         return false;
1523     }
1524
1525     if (!vfp_access_check(s)) {
1526         return true;
1527     }
1528
1529     if (veclen > 0) {
1530         /* Figure out what type of vector operation this is.  */
1531         if (vfp_dreg_is_scalar(vd)) {
1532             /* scalar */
1533             veclen = 0;
1534         } else {
1535             delta_d = (s->vec_stride >> 1) + 1;
1536
1537             if (vfp_dreg_is_scalar(vm)) {
1538                 /* mixed scalar/vector */
1539                 delta_m = 0;
1540             } else {
1541                 /* vector */
1542                 delta_m = delta_d;
1543             }
1544         }
1545     }
1546
1547     f0 = tcg_temp_new_i64();
1548     fd = tcg_temp_new_i64();
1549
1550     neon_load_reg64(f0, vm);
1551
1552     for (;;) {
1553         fn(fd, f0);
1554         neon_store_reg64(fd, vd);
1555
1556         if (veclen == 0) {
1557             break;
1558         }
1559
1560         if (delta_m == 0) {
1561             /* single source one-many */
1562             while (veclen--) {
1563                 vd = vfp_advance_dreg(vd, delta_d);
1564                 neon_store_reg64(fd, vd);
1565             }
1566             break;
1567         }
1568
1569         /* Set up the operands for the next iteration */
1570         veclen--;
1571         vd = vfp_advance_dreg(vd, delta_d);
1572         vd = vfp_advance_dreg(vm, delta_m);
1573         neon_load_reg64(f0, vm);
1574     }
1575
1576     tcg_temp_free_i64(f0);
1577     tcg_temp_free_i64(fd);
1578
1579     return true;
1580 }
1581
1582 static void gen_VMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1583 {
1584     /* Note that order of inputs to the add matters for NaNs */
1585     TCGv_i32 tmp = tcg_temp_new_i32();
1586
1587     gen_helper_vfp_mulh(tmp, vn, vm, fpst);
1588     gen_helper_vfp_addh(vd, vd, tmp, fpst);
1589     tcg_temp_free_i32(tmp);
1590 }
1591
1592 static bool trans_VMLA_hp(DisasContext *s, arg_VMLA_sp *a)
1593 {
1594     return do_vfp_3op_hp(s, gen_VMLA_hp, a->vd, a->vn, a->vm, true);
1595 }
1596
1597 static void gen_VMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1598 {
1599     /* Note that order of inputs to the add matters for NaNs */
1600     TCGv_i32 tmp = tcg_temp_new_i32();
1601
1602     gen_helper_vfp_muls(tmp, vn, vm, fpst);
1603     gen_helper_vfp_adds(vd, vd, tmp, fpst);
1604     tcg_temp_free_i32(tmp);
1605 }
1606
1607 static bool trans_VMLA_sp(DisasContext *s, arg_VMLA_sp *a)
1608 {
1609     return do_vfp_3op_sp(s, gen_VMLA_sp, a->vd, a->vn, a->vm, true);
1610 }
1611
1612 static void gen_VMLA_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1613 {
1614     /* Note that order of inputs to the add matters for NaNs */
1615     TCGv_i64 tmp = tcg_temp_new_i64();
1616
1617     gen_helper_vfp_muld(tmp, vn, vm, fpst);
1618     gen_helper_vfp_addd(vd, vd, tmp, fpst);
1619     tcg_temp_free_i64(tmp);
1620 }
1621
1622 static bool trans_VMLA_dp(DisasContext *s, arg_VMLA_dp *a)
1623 {
1624     return do_vfp_3op_dp(s, gen_VMLA_dp, a->vd, a->vn, a->vm, true);
1625 }
1626
1627 static void gen_VMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1628 {
1629     /*
1630      * VMLS: vd = vd + -(vn * vm)
1631      * Note that order of inputs to the add matters for NaNs.
1632      */
1633     TCGv_i32 tmp = tcg_temp_new_i32();
1634
1635     gen_helper_vfp_mulh(tmp, vn, vm, fpst);
1636     gen_helper_vfp_negh(tmp, tmp);
1637     gen_helper_vfp_addh(vd, vd, tmp, fpst);
1638     tcg_temp_free_i32(tmp);
1639 }
1640
1641 static bool trans_VMLS_hp(DisasContext *s, arg_VMLS_sp *a)
1642 {
1643     return do_vfp_3op_hp(s, gen_VMLS_hp, a->vd, a->vn, a->vm, true);
1644 }
1645
1646 static void gen_VMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1647 {
1648     /*
1649      * VMLS: vd = vd + -(vn * vm)
1650      * Note that order of inputs to the add matters for NaNs.
1651      */
1652     TCGv_i32 tmp = tcg_temp_new_i32();
1653
1654     gen_helper_vfp_muls(tmp, vn, vm, fpst);
1655     gen_helper_vfp_negs(tmp, tmp);
1656     gen_helper_vfp_adds(vd, vd, tmp, fpst);
1657     tcg_temp_free_i32(tmp);
1658 }
1659
1660 static bool trans_VMLS_sp(DisasContext *s, arg_VMLS_sp *a)
1661 {
1662     return do_vfp_3op_sp(s, gen_VMLS_sp, a->vd, a->vn, a->vm, true);
1663 }
1664
1665 static void gen_VMLS_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1666 {
1667     /*
1668      * VMLS: vd = vd + -(vn * vm)
1669      * Note that order of inputs to the add matters for NaNs.
1670      */
1671     TCGv_i64 tmp = tcg_temp_new_i64();
1672
1673     gen_helper_vfp_muld(tmp, vn, vm, fpst);
1674     gen_helper_vfp_negd(tmp, tmp);
1675     gen_helper_vfp_addd(vd, vd, tmp, fpst);
1676     tcg_temp_free_i64(tmp);
1677 }
1678
1679 static bool trans_VMLS_dp(DisasContext *s, arg_VMLS_dp *a)
1680 {
1681     return do_vfp_3op_dp(s, gen_VMLS_dp, a->vd, a->vn, a->vm, true);
1682 }
1683
1684 static void gen_VNMLS_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1685 {
1686     /*
1687      * VNMLS: -fd + (fn * fm)
1688      * Note that it isn't valid to replace (-A + B) with (B - A) or similar
1689      * plausible looking simplifications because this will give wrong results
1690      * for NaNs.
1691      */
1692     TCGv_i32 tmp = tcg_temp_new_i32();
1693
1694     gen_helper_vfp_mulh(tmp, vn, vm, fpst);
1695     gen_helper_vfp_negh(vd, vd);
1696     gen_helper_vfp_addh(vd, vd, tmp, fpst);
1697     tcg_temp_free_i32(tmp);
1698 }
1699
1700 static bool trans_VNMLS_hp(DisasContext *s, arg_VNMLS_sp *a)
1701 {
1702     return do_vfp_3op_hp(s, gen_VNMLS_hp, a->vd, a->vn, a->vm, true);
1703 }
1704
1705 static void gen_VNMLS_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1706 {
1707     /*
1708      * VNMLS: -fd + (fn * fm)
1709      * Note that it isn't valid to replace (-A + B) with (B - A) or similar
1710      * plausible looking simplifications because this will give wrong results
1711      * for NaNs.
1712      */
1713     TCGv_i32 tmp = tcg_temp_new_i32();
1714
1715     gen_helper_vfp_muls(tmp, vn, vm, fpst);
1716     gen_helper_vfp_negs(vd, vd);
1717     gen_helper_vfp_adds(vd, vd, tmp, fpst);
1718     tcg_temp_free_i32(tmp);
1719 }
1720
1721 static bool trans_VNMLS_sp(DisasContext *s, arg_VNMLS_sp *a)
1722 {
1723     return do_vfp_3op_sp(s, gen_VNMLS_sp, a->vd, a->vn, a->vm, true);
1724 }
1725
1726 static void gen_VNMLS_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1727 {
1728     /*
1729      * VNMLS: -fd + (fn * fm)
1730      * Note that it isn't valid to replace (-A + B) with (B - A) or similar
1731      * plausible looking simplifications because this will give wrong results
1732      * for NaNs.
1733      */
1734     TCGv_i64 tmp = tcg_temp_new_i64();
1735
1736     gen_helper_vfp_muld(tmp, vn, vm, fpst);
1737     gen_helper_vfp_negd(vd, vd);
1738     gen_helper_vfp_addd(vd, vd, tmp, fpst);
1739     tcg_temp_free_i64(tmp);
1740 }
1741
1742 static bool trans_VNMLS_dp(DisasContext *s, arg_VNMLS_dp *a)
1743 {
1744     return do_vfp_3op_dp(s, gen_VNMLS_dp, a->vd, a->vn, a->vm, true);
1745 }
1746
1747 static void gen_VNMLA_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1748 {
1749     /* VNMLA: -fd + -(fn * fm) */
1750     TCGv_i32 tmp = tcg_temp_new_i32();
1751
1752     gen_helper_vfp_mulh(tmp, vn, vm, fpst);
1753     gen_helper_vfp_negh(tmp, tmp);
1754     gen_helper_vfp_negh(vd, vd);
1755     gen_helper_vfp_addh(vd, vd, tmp, fpst);
1756     tcg_temp_free_i32(tmp);
1757 }
1758
1759 static bool trans_VNMLA_hp(DisasContext *s, arg_VNMLA_sp *a)
1760 {
1761     return do_vfp_3op_hp(s, gen_VNMLA_hp, a->vd, a->vn, a->vm, true);
1762 }
1763
1764 static void gen_VNMLA_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1765 {
1766     /* VNMLA: -fd + -(fn * fm) */
1767     TCGv_i32 tmp = tcg_temp_new_i32();
1768
1769     gen_helper_vfp_muls(tmp, vn, vm, fpst);
1770     gen_helper_vfp_negs(tmp, tmp);
1771     gen_helper_vfp_negs(vd, vd);
1772     gen_helper_vfp_adds(vd, vd, tmp, fpst);
1773     tcg_temp_free_i32(tmp);
1774 }
1775
1776 static bool trans_VNMLA_sp(DisasContext *s, arg_VNMLA_sp *a)
1777 {
1778     return do_vfp_3op_sp(s, gen_VNMLA_sp, a->vd, a->vn, a->vm, true);
1779 }
1780
1781 static void gen_VNMLA_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1782 {
1783     /* VNMLA: -fd + (fn * fm) */
1784     TCGv_i64 tmp = tcg_temp_new_i64();
1785
1786     gen_helper_vfp_muld(tmp, vn, vm, fpst);
1787     gen_helper_vfp_negd(tmp, tmp);
1788     gen_helper_vfp_negd(vd, vd);
1789     gen_helper_vfp_addd(vd, vd, tmp, fpst);
1790     tcg_temp_free_i64(tmp);
1791 }
1792
1793 static bool trans_VNMLA_dp(DisasContext *s, arg_VNMLA_dp *a)
1794 {
1795     return do_vfp_3op_dp(s, gen_VNMLA_dp, a->vd, a->vn, a->vm, true);
1796 }
1797
1798 static bool trans_VMUL_hp(DisasContext *s, arg_VMUL_sp *a)
1799 {
1800     return do_vfp_3op_hp(s, gen_helper_vfp_mulh, a->vd, a->vn, a->vm, false);
1801 }
1802
1803 static bool trans_VMUL_sp(DisasContext *s, arg_VMUL_sp *a)
1804 {
1805     return do_vfp_3op_sp(s, gen_helper_vfp_muls, a->vd, a->vn, a->vm, false);
1806 }
1807
1808 static bool trans_VMUL_dp(DisasContext *s, arg_VMUL_dp *a)
1809 {
1810     return do_vfp_3op_dp(s, gen_helper_vfp_muld, a->vd, a->vn, a->vm, false);
1811 }
1812
1813 static void gen_VNMUL_hp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1814 {
1815     /* VNMUL: -(fn * fm) */
1816     gen_helper_vfp_mulh(vd, vn, vm, fpst);
1817     gen_helper_vfp_negh(vd, vd);
1818 }
1819
1820 static bool trans_VNMUL_hp(DisasContext *s, arg_VNMUL_sp *a)
1821 {
1822     return do_vfp_3op_hp(s, gen_VNMUL_hp, a->vd, a->vn, a->vm, false);
1823 }
1824
1825 static void gen_VNMUL_sp(TCGv_i32 vd, TCGv_i32 vn, TCGv_i32 vm, TCGv_ptr fpst)
1826 {
1827     /* VNMUL: -(fn * fm) */
1828     gen_helper_vfp_muls(vd, vn, vm, fpst);
1829     gen_helper_vfp_negs(vd, vd);
1830 }
1831
1832 static bool trans_VNMUL_sp(DisasContext *s, arg_VNMUL_sp *a)
1833 {
1834     return do_vfp_3op_sp(s, gen_VNMUL_sp, a->vd, a->vn, a->vm, false);
1835 }
1836
1837 static void gen_VNMUL_dp(TCGv_i64 vd, TCGv_i64 vn, TCGv_i64 vm, TCGv_ptr fpst)
1838 {
1839     /* VNMUL: -(fn * fm) */
1840     gen_helper_vfp_muld(vd, vn, vm, fpst);
1841     gen_helper_vfp_negd(vd, vd);
1842 }
1843
1844 static bool trans_VNMUL_dp(DisasContext *s, arg_VNMUL_dp *a)
1845 {
1846     return do_vfp_3op_dp(s, gen_VNMUL_dp, a->vd, a->vn, a->vm, false);
1847 }
1848
1849 static bool trans_VADD_hp(DisasContext *s, arg_VADD_sp *a)
1850 {
1851     return do_vfp_3op_hp(s, gen_helper_vfp_addh, a->vd, a->vn, a->vm, false);
1852 }
1853
1854 static bool trans_VADD_sp(DisasContext *s, arg_VADD_sp *a)
1855 {
1856     return do_vfp_3op_sp(s, gen_helper_vfp_adds, a->vd, a->vn, a->vm, false);
1857 }
1858
1859 static bool trans_VADD_dp(DisasContext *s, arg_VADD_dp *a)
1860 {
1861     return do_vfp_3op_dp(s, gen_helper_vfp_addd, a->vd, a->vn, a->vm, false);
1862 }
1863
1864 static bool trans_VSUB_hp(DisasContext *s, arg_VSUB_sp *a)
1865 {
1866     return do_vfp_3op_hp(s, gen_helper_vfp_subh, a->vd, a->vn, a->vm, false);
1867 }
1868
1869 static bool trans_VSUB_sp(DisasContext *s, arg_VSUB_sp *a)
1870 {
1871     return do_vfp_3op_sp(s, gen_helper_vfp_subs, a->vd, a->vn, a->vm, false);
1872 }
1873
1874 static bool trans_VSUB_dp(DisasContext *s, arg_VSUB_dp *a)
1875 {
1876     return do_vfp_3op_dp(s, gen_helper_vfp_subd, a->vd, a->vn, a->vm, false);
1877 }
1878
1879 static bool trans_VDIV_hp(DisasContext *s, arg_VDIV_sp *a)
1880 {
1881     return do_vfp_3op_hp(s, gen_helper_vfp_divh, a->vd, a->vn, a->vm, false);
1882 }
1883
1884 static bool trans_VDIV_sp(DisasContext *s, arg_VDIV_sp *a)
1885 {
1886     return do_vfp_3op_sp(s, gen_helper_vfp_divs, a->vd, a->vn, a->vm, false);
1887 }
1888
1889 static bool trans_VDIV_dp(DisasContext *s, arg_VDIV_dp *a)
1890 {
1891     return do_vfp_3op_dp(s, gen_helper_vfp_divd, a->vd, a->vn, a->vm, false);
1892 }
1893
1894 static bool trans_VMINNM_hp(DisasContext *s, arg_VMINNM_sp *a)
1895 {
1896     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1897         return false;
1898     }
1899     return do_vfp_3op_hp(s, gen_helper_vfp_minnumh,
1900                          a->vd, a->vn, a->vm, false);
1901 }
1902
1903 static bool trans_VMAXNM_hp(DisasContext *s, arg_VMAXNM_sp *a)
1904 {
1905     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1906         return false;
1907     }
1908     return do_vfp_3op_hp(s, gen_helper_vfp_maxnumh,
1909                          a->vd, a->vn, a->vm, false);
1910 }
1911
1912 static bool trans_VMINNM_sp(DisasContext *s, arg_VMINNM_sp *a)
1913 {
1914     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1915         return false;
1916     }
1917     return do_vfp_3op_sp(s, gen_helper_vfp_minnums,
1918                          a->vd, a->vn, a->vm, false);
1919 }
1920
1921 static bool trans_VMAXNM_sp(DisasContext *s, arg_VMAXNM_sp *a)
1922 {
1923     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1924         return false;
1925     }
1926     return do_vfp_3op_sp(s, gen_helper_vfp_maxnums,
1927                          a->vd, a->vn, a->vm, false);
1928 }
1929
1930 static bool trans_VMINNM_dp(DisasContext *s, arg_VMINNM_dp *a)
1931 {
1932     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1933         return false;
1934     }
1935     return do_vfp_3op_dp(s, gen_helper_vfp_minnumd,
1936                          a->vd, a->vn, a->vm, false);
1937 }
1938
1939 static bool trans_VMAXNM_dp(DisasContext *s, arg_VMAXNM_dp *a)
1940 {
1941     if (!dc_isar_feature(aa32_vminmaxnm, s)) {
1942         return false;
1943     }
1944     return do_vfp_3op_dp(s, gen_helper_vfp_maxnumd,
1945                          a->vd, a->vn, a->vm, false);
1946 }
1947
1948 static bool do_vfm_hp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
1949 {
1950     /*
1951      * VFNMA : fd = muladd(-fd,  fn, fm)
1952      * VFNMS : fd = muladd(-fd, -fn, fm)
1953      * VFMA  : fd = muladd( fd,  fn, fm)
1954      * VFMS  : fd = muladd( fd, -fn, fm)
1955      *
1956      * These are fused multiply-add, and must be done as one floating
1957      * point operation with no rounding between the multiplication and
1958      * addition steps.  NB that doing the negations here as separate
1959      * steps is correct : an input NaN should come out with its sign
1960      * bit flipped if it is a negated-input.
1961      */
1962     TCGv_ptr fpst;
1963     TCGv_i32 vn, vm, vd;
1964
1965     /*
1966      * Present in VFPv4 only, and only with the FP16 extension.
1967      * Note that we can't rely on the SIMDFMAC check alone, because
1968      * in a Neon-no-VFP core that ID register field will be non-zero.
1969      */
1970     if (!dc_isar_feature(aa32_fp16_arith, s) ||
1971         !dc_isar_feature(aa32_simdfmac, s) ||
1972         !dc_isar_feature(aa32_fpsp_v2, s)) {
1973         return false;
1974     }
1975
1976     if (s->vec_len != 0 || s->vec_stride != 0) {
1977         return false;
1978     }
1979
1980     if (!vfp_access_check(s)) {
1981         return true;
1982     }
1983
1984     vn = tcg_temp_new_i32();
1985     vm = tcg_temp_new_i32();
1986     vd = tcg_temp_new_i32();
1987
1988     neon_load_reg32(vn, a->vn);
1989     neon_load_reg32(vm, a->vm);
1990     if (neg_n) {
1991         /* VFNMS, VFMS */
1992         gen_helper_vfp_negh(vn, vn);
1993     }
1994     neon_load_reg32(vd, a->vd);
1995     if (neg_d) {
1996         /* VFNMA, VFNMS */
1997         gen_helper_vfp_negh(vd, vd);
1998     }
1999     fpst = fpstatus_ptr(FPST_FPCR_F16);
2000     gen_helper_vfp_muladdh(vd, vn, vm, vd, fpst);
2001     neon_store_reg32(vd, a->vd);
2002
2003     tcg_temp_free_ptr(fpst);
2004     tcg_temp_free_i32(vn);
2005     tcg_temp_free_i32(vm);
2006     tcg_temp_free_i32(vd);
2007
2008     return true;
2009 }
2010
2011 static bool do_vfm_sp(DisasContext *s, arg_VFMA_sp *a, bool neg_n, bool neg_d)
2012 {
2013     /*
2014      * VFNMA : fd = muladd(-fd,  fn, fm)
2015      * VFNMS : fd = muladd(-fd, -fn, fm)
2016      * VFMA  : fd = muladd( fd,  fn, fm)
2017      * VFMS  : fd = muladd( fd, -fn, fm)
2018      *
2019      * These are fused multiply-add, and must be done as one floating
2020      * point operation with no rounding between the multiplication and
2021      * addition steps.  NB that doing the negations here as separate
2022      * steps is correct : an input NaN should come out with its sign
2023      * bit flipped if it is a negated-input.
2024      */
2025     TCGv_ptr fpst;
2026     TCGv_i32 vn, vm, vd;
2027
2028     /*
2029      * Present in VFPv4 only.
2030      * Note that we can't rely on the SIMDFMAC check alone, because
2031      * in a Neon-no-VFP core that ID register field will be non-zero.
2032      */
2033     if (!dc_isar_feature(aa32_simdfmac, s) ||
2034         !dc_isar_feature(aa32_fpsp_v2, s)) {
2035         return false;
2036     }
2037     /*
2038      * In v7A, UNPREDICTABLE with non-zero vector length/stride; from
2039      * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
2040      */
2041     if (s->vec_len != 0 || s->vec_stride != 0) {
2042         return false;
2043     }
2044
2045     if (!vfp_access_check(s)) {
2046         return true;
2047     }
2048
2049     vn = tcg_temp_new_i32();
2050     vm = tcg_temp_new_i32();
2051     vd = tcg_temp_new_i32();
2052
2053     neon_load_reg32(vn, a->vn);
2054     neon_load_reg32(vm, a->vm);
2055     if (neg_n) {
2056         /* VFNMS, VFMS */
2057         gen_helper_vfp_negs(vn, vn);
2058     }
2059     neon_load_reg32(vd, a->vd);
2060     if (neg_d) {
2061         /* VFNMA, VFNMS */
2062         gen_helper_vfp_negs(vd, vd);
2063     }
2064     fpst = fpstatus_ptr(FPST_FPCR);
2065     gen_helper_vfp_muladds(vd, vn, vm, vd, fpst);
2066     neon_store_reg32(vd, a->vd);
2067
2068     tcg_temp_free_ptr(fpst);
2069     tcg_temp_free_i32(vn);
2070     tcg_temp_free_i32(vm);
2071     tcg_temp_free_i32(vd);
2072
2073     return true;
2074 }
2075
2076 static bool do_vfm_dp(DisasContext *s, arg_VFMA_dp *a, bool neg_n, bool neg_d)
2077 {
2078     /*
2079      * VFNMA : fd = muladd(-fd,  fn, fm)
2080      * VFNMS : fd = muladd(-fd, -fn, fm)
2081      * VFMA  : fd = muladd( fd,  fn, fm)
2082      * VFMS  : fd = muladd( fd, -fn, fm)
2083      *
2084      * These are fused multiply-add, and must be done as one floating
2085      * point operation with no rounding between the multiplication and
2086      * addition steps.  NB that doing the negations here as separate
2087      * steps is correct : an input NaN should come out with its sign
2088      * bit flipped if it is a negated-input.
2089      */
2090     TCGv_ptr fpst;
2091     TCGv_i64 vn, vm, vd;
2092
2093     /*
2094      * Present in VFPv4 only.
2095      * Note that we can't rely on the SIMDFMAC check alone, because
2096      * in a Neon-no-VFP core that ID register field will be non-zero.
2097      */
2098     if (!dc_isar_feature(aa32_simdfmac, s) ||
2099         !dc_isar_feature(aa32_fpdp_v2, s)) {
2100         return false;
2101     }
2102     /*
2103      * In v7A, UNPREDICTABLE with non-zero vector length/stride; from
2104      * v8A, must UNDEF. We choose to UNDEF for both v7A and v8A.
2105      */
2106     if (s->vec_len != 0 || s->vec_stride != 0) {
2107         return false;
2108     }
2109
2110     /* UNDEF accesses to D16-D31 if they don't exist. */
2111     if (!dc_isar_feature(aa32_simd_r32, s) &&
2112         ((a->vd | a->vn | a->vm) & 0x10)) {
2113         return false;
2114     }
2115
2116     if (!vfp_access_check(s)) {
2117         return true;
2118     }
2119
2120     vn = tcg_temp_new_i64();
2121     vm = tcg_temp_new_i64();
2122     vd = tcg_temp_new_i64();
2123
2124     neon_load_reg64(vn, a->vn);
2125     neon_load_reg64(vm, a->vm);
2126     if (neg_n) {
2127         /* VFNMS, VFMS */
2128         gen_helper_vfp_negd(vn, vn);
2129     }
2130     neon_load_reg64(vd, a->vd);
2131     if (neg_d) {
2132         /* VFNMA, VFNMS */
2133         gen_helper_vfp_negd(vd, vd);
2134     }
2135     fpst = fpstatus_ptr(FPST_FPCR);
2136     gen_helper_vfp_muladdd(vd, vn, vm, vd, fpst);
2137     neon_store_reg64(vd, a->vd);
2138
2139     tcg_temp_free_ptr(fpst);
2140     tcg_temp_free_i64(vn);
2141     tcg_temp_free_i64(vm);
2142     tcg_temp_free_i64(vd);
2143
2144     return true;
2145 }
2146
2147 #define MAKE_ONE_VFM_TRANS_FN(INSN, PREC, NEGN, NEGD)                   \
2148     static bool trans_##INSN##_##PREC(DisasContext *s,                  \
2149                                       arg_##INSN##_##PREC *a)           \
2150     {                                                                   \
2151         return do_vfm_##PREC(s, a, NEGN, NEGD);                         \
2152     }
2153
2154 #define MAKE_VFM_TRANS_FNS(PREC) \
2155     MAKE_ONE_VFM_TRANS_FN(VFMA, PREC, false, false) \
2156     MAKE_ONE_VFM_TRANS_FN(VFMS, PREC, true, false) \
2157     MAKE_ONE_VFM_TRANS_FN(VFNMA, PREC, false, true) \
2158     MAKE_ONE_VFM_TRANS_FN(VFNMS, PREC, true, true)
2159
2160 MAKE_VFM_TRANS_FNS(hp)
2161 MAKE_VFM_TRANS_FNS(sp)
2162 MAKE_VFM_TRANS_FNS(dp)
2163
2164 static bool trans_VMOV_imm_hp(DisasContext *s, arg_VMOV_imm_sp *a)
2165 {
2166     TCGv_i32 fd;
2167
2168     if (!dc_isar_feature(aa32_fp16_arith, s)) {
2169         return false;
2170     }
2171
2172     if (s->vec_len != 0 || s->vec_stride != 0) {
2173         return false;
2174     }
2175
2176     if (!vfp_access_check(s)) {
2177         return true;
2178     }
2179
2180     fd = tcg_const_i32(vfp_expand_imm(MO_16, a->imm));
2181     neon_store_reg32(fd, a->vd);
2182     tcg_temp_free_i32(fd);
2183     return true;
2184 }
2185
2186 static bool trans_VMOV_imm_sp(DisasContext *s, arg_VMOV_imm_sp *a)
2187 {
2188     uint32_t delta_d = 0;
2189     int veclen = s->vec_len;
2190     TCGv_i32 fd;
2191     uint32_t vd;
2192
2193     vd = a->vd;
2194
2195     if (!dc_isar_feature(aa32_fpsp_v3, s)) {
2196         return false;
2197     }
2198
2199     if (!dc_isar_feature(aa32_fpshvec, s) &&
2200         (veclen != 0 || s->vec_stride != 0)) {
2201         return false;
2202     }
2203
2204     if (!vfp_access_check(s)) {
2205         return true;
2206     }
2207
2208     if (veclen > 0) {
2209         /* Figure out what type of vector operation this is.  */
2210         if (vfp_sreg_is_scalar(vd)) {
2211             /* scalar */
2212             veclen = 0;
2213         } else {
2214             delta_d = s->vec_stride + 1;
2215         }
2216     }
2217
2218     fd = tcg_const_i32(vfp_expand_imm(MO_32, a->imm));
2219
2220     for (;;) {
2221         neon_store_reg32(fd, vd);
2222
2223         if (veclen == 0) {
2224             break;
2225         }
2226
2227         /* Set up the operands for the next iteration */
2228         veclen--;
2229         vd = vfp_advance_sreg(vd, delta_d);
2230     }
2231
2232     tcg_temp_free_i32(fd);
2233     return true;
2234 }
2235
2236 static bool trans_VMOV_imm_dp(DisasContext *s, arg_VMOV_imm_dp *a)
2237 {
2238     uint32_t delta_d = 0;
2239     int veclen = s->vec_len;
2240     TCGv_i64 fd;
2241     uint32_t vd;
2242
2243     vd = a->vd;
2244
2245     if (!dc_isar_feature(aa32_fpdp_v3, s)) {
2246         return false;
2247     }
2248
2249     /* UNDEF accesses to D16-D31 if they don't exist. */
2250     if (!dc_isar_feature(aa32_simd_r32, s) && (vd & 0x10)) {
2251         return false;
2252     }
2253
2254     if (!dc_isar_feature(aa32_fpshvec, s) &&
2255         (veclen != 0 || s->vec_stride != 0)) {
2256         return false;
2257     }
2258
2259     if (!vfp_access_check(s)) {
2260         return true;
2261     }
2262
2263     if (veclen > 0) {
2264         /* Figure out what type of vector operation this is.  */
2265         if (vfp_dreg_is_scalar(vd)) {
2266             /* scalar */
2267             veclen = 0;
2268         } else {
2269             delta_d = (s->vec_stride >> 1) + 1;
2270         }
2271     }
2272
2273     fd = tcg_const_i64(vfp_expand_imm(MO_64, a->imm));
2274
2275     for (;;) {
2276         neon_store_reg64(fd, vd);
2277
2278         if (veclen == 0) {
2279             break;
2280         }
2281
2282         /* Set up the operands for the next iteration */
2283         veclen--;
2284         vd = vfp_advance_dreg(vd, delta_d);
2285     }
2286
2287     tcg_temp_free_i64(fd);
2288     return true;
2289 }
2290
2291 #define DO_VFP_2OP(INSN, PREC, FN)                              \
2292     static bool trans_##INSN##_##PREC(DisasContext *s,          \
2293                                       arg_##INSN##_##PREC *a)   \
2294     {                                                           \
2295         return do_vfp_2op_##PREC(s, FN, a->vd, a->vm);          \
2296     }
2297
2298 DO_VFP_2OP(VMOV_reg, sp, tcg_gen_mov_i32)
2299 DO_VFP_2OP(VMOV_reg, dp, tcg_gen_mov_i64)
2300
2301 DO_VFP_2OP(VABS, hp, gen_helper_vfp_absh)
2302 DO_VFP_2OP(VABS, sp, gen_helper_vfp_abss)
2303 DO_VFP_2OP(VABS, dp, gen_helper_vfp_absd)
2304
2305 DO_VFP_2OP(VNEG, hp, gen_helper_vfp_negh)
2306 DO_VFP_2OP(VNEG, sp, gen_helper_vfp_negs)
2307 DO_VFP_2OP(VNEG, dp, gen_helper_vfp_negd)
2308
2309 static void gen_VSQRT_hp(TCGv_i32 vd, TCGv_i32 vm)
2310 {
2311     gen_helper_vfp_sqrth(vd, vm, cpu_env);
2312 }
2313
2314 static void gen_VSQRT_sp(TCGv_i32 vd, TCGv_i32 vm)
2315 {
2316     gen_helper_vfp_sqrts(vd, vm, cpu_env);
2317 }
2318
2319 static void gen_VSQRT_dp(TCGv_i64 vd, TCGv_i64 vm)
2320 {
2321     gen_helper_vfp_sqrtd(vd, vm, cpu_env);
2322 }
2323
2324 DO_VFP_2OP(VSQRT, hp, gen_VSQRT_hp)
2325 DO_VFP_2OP(VSQRT, sp, gen_VSQRT_sp)
2326 DO_VFP_2OP(VSQRT, dp, gen_VSQRT_dp)
2327
2328 static bool trans_VCMP_hp(DisasContext *s, arg_VCMP_sp *a)
2329 {
2330     TCGv_i32 vd, vm;
2331
2332     if (!dc_isar_feature(aa32_fp16_arith, s)) {
2333         return false;
2334     }
2335
2336     /* Vm/M bits must be zero for the Z variant */
2337     if (a->z && a->vm != 0) {
2338         return false;
2339     }
2340
2341     if (!vfp_access_check(s)) {
2342         return true;
2343     }
2344
2345     vd = tcg_temp_new_i32();
2346     vm = tcg_temp_new_i32();
2347
2348     neon_load_reg32(vd, a->vd);
2349     if (a->z) {
2350         tcg_gen_movi_i32(vm, 0);
2351     } else {
2352         neon_load_reg32(vm, a->vm);
2353     }
2354
2355     if (a->e) {
2356         gen_helper_vfp_cmpeh(vd, vm, cpu_env);
2357     } else {
2358         gen_helper_vfp_cmph(vd, vm, cpu_env);
2359     }
2360
2361     tcg_temp_free_i32(vd);
2362     tcg_temp_free_i32(vm);
2363
2364     return true;
2365 }
2366
2367 static bool trans_VCMP_sp(DisasContext *s, arg_VCMP_sp *a)
2368 {
2369     TCGv_i32 vd, vm;
2370
2371     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
2372         return false;
2373     }
2374
2375     /* Vm/M bits must be zero for the Z variant */
2376     if (a->z && a->vm != 0) {
2377         return false;
2378     }
2379
2380     if (!vfp_access_check(s)) {
2381         return true;
2382     }
2383
2384     vd = tcg_temp_new_i32();
2385     vm = tcg_temp_new_i32();
2386
2387     neon_load_reg32(vd, a->vd);
2388     if (a->z) {
2389         tcg_gen_movi_i32(vm, 0);
2390     } else {
2391         neon_load_reg32(vm, a->vm);
2392     }
2393
2394     if (a->e) {
2395         gen_helper_vfp_cmpes(vd, vm, cpu_env);
2396     } else {
2397         gen_helper_vfp_cmps(vd, vm, cpu_env);
2398     }
2399
2400     tcg_temp_free_i32(vd);
2401     tcg_temp_free_i32(vm);
2402
2403     return true;
2404 }
2405
2406 static bool trans_VCMP_dp(DisasContext *s, arg_VCMP_dp *a)
2407 {
2408     TCGv_i64 vd, vm;
2409
2410     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2411         return false;
2412     }
2413
2414     /* Vm/M bits must be zero for the Z variant */
2415     if (a->z && a->vm != 0) {
2416         return false;
2417     }
2418
2419     /* UNDEF accesses to D16-D31 if they don't exist. */
2420     if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2421         return false;
2422     }
2423
2424     if (!vfp_access_check(s)) {
2425         return true;
2426     }
2427
2428     vd = tcg_temp_new_i64();
2429     vm = tcg_temp_new_i64();
2430
2431     neon_load_reg64(vd, a->vd);
2432     if (a->z) {
2433         tcg_gen_movi_i64(vm, 0);
2434     } else {
2435         neon_load_reg64(vm, a->vm);
2436     }
2437
2438     if (a->e) {
2439         gen_helper_vfp_cmped(vd, vm, cpu_env);
2440     } else {
2441         gen_helper_vfp_cmpd(vd, vm, cpu_env);
2442     }
2443
2444     tcg_temp_free_i64(vd);
2445     tcg_temp_free_i64(vm);
2446
2447     return true;
2448 }
2449
2450 static bool trans_VCVT_f32_f16(DisasContext *s, arg_VCVT_f32_f16 *a)
2451 {
2452     TCGv_ptr fpst;
2453     TCGv_i32 ahp_mode;
2454     TCGv_i32 tmp;
2455
2456     if (!dc_isar_feature(aa32_fp16_spconv, s)) {
2457         return false;
2458     }
2459
2460     if (!vfp_access_check(s)) {
2461         return true;
2462     }
2463
2464     fpst = fpstatus_ptr(FPST_FPCR);
2465     ahp_mode = get_ahp_flag();
2466     tmp = tcg_temp_new_i32();
2467     /* The T bit tells us if we want the low or high 16 bits of Vm */
2468     tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t));
2469     gen_helper_vfp_fcvt_f16_to_f32(tmp, tmp, fpst, ahp_mode);
2470     neon_store_reg32(tmp, a->vd);
2471     tcg_temp_free_i32(ahp_mode);
2472     tcg_temp_free_ptr(fpst);
2473     tcg_temp_free_i32(tmp);
2474     return true;
2475 }
2476
2477 static bool trans_VCVT_f64_f16(DisasContext *s, arg_VCVT_f64_f16 *a)
2478 {
2479     TCGv_ptr fpst;
2480     TCGv_i32 ahp_mode;
2481     TCGv_i32 tmp;
2482     TCGv_i64 vd;
2483
2484     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2485         return false;
2486     }
2487
2488     if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
2489         return false;
2490     }
2491
2492     /* UNDEF accesses to D16-D31 if they don't exist. */
2493     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd  & 0x10)) {
2494         return false;
2495     }
2496
2497     if (!vfp_access_check(s)) {
2498         return true;
2499     }
2500
2501     fpst = fpstatus_ptr(FPST_FPCR);
2502     ahp_mode = get_ahp_flag();
2503     tmp = tcg_temp_new_i32();
2504     /* The T bit tells us if we want the low or high 16 bits of Vm */
2505     tcg_gen_ld16u_i32(tmp, cpu_env, vfp_f16_offset(a->vm, a->t));
2506     vd = tcg_temp_new_i64();
2507     gen_helper_vfp_fcvt_f16_to_f64(vd, tmp, fpst, ahp_mode);
2508     neon_store_reg64(vd, a->vd);
2509     tcg_temp_free_i32(ahp_mode);
2510     tcg_temp_free_ptr(fpst);
2511     tcg_temp_free_i32(tmp);
2512     tcg_temp_free_i64(vd);
2513     return true;
2514 }
2515
2516 static bool trans_VCVT_f16_f32(DisasContext *s, arg_VCVT_f16_f32 *a)
2517 {
2518     TCGv_ptr fpst;
2519     TCGv_i32 ahp_mode;
2520     TCGv_i32 tmp;
2521
2522     if (!dc_isar_feature(aa32_fp16_spconv, s)) {
2523         return false;
2524     }
2525
2526     if (!vfp_access_check(s)) {
2527         return true;
2528     }
2529
2530     fpst = fpstatus_ptr(FPST_FPCR);
2531     ahp_mode = get_ahp_flag();
2532     tmp = tcg_temp_new_i32();
2533
2534     neon_load_reg32(tmp, a->vm);
2535     gen_helper_vfp_fcvt_f32_to_f16(tmp, tmp, fpst, ahp_mode);
2536     tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t));
2537     tcg_temp_free_i32(ahp_mode);
2538     tcg_temp_free_ptr(fpst);
2539     tcg_temp_free_i32(tmp);
2540     return true;
2541 }
2542
2543 static bool trans_VCVT_f16_f64(DisasContext *s, arg_VCVT_f16_f64 *a)
2544 {
2545     TCGv_ptr fpst;
2546     TCGv_i32 ahp_mode;
2547     TCGv_i32 tmp;
2548     TCGv_i64 vm;
2549
2550     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2551         return false;
2552     }
2553
2554     if (!dc_isar_feature(aa32_fp16_dpconv, s)) {
2555         return false;
2556     }
2557
2558     /* UNDEF accesses to D16-D31 if they don't exist. */
2559     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm  & 0x10)) {
2560         return false;
2561     }
2562
2563     if (!vfp_access_check(s)) {
2564         return true;
2565     }
2566
2567     fpst = fpstatus_ptr(FPST_FPCR);
2568     ahp_mode = get_ahp_flag();
2569     tmp = tcg_temp_new_i32();
2570     vm = tcg_temp_new_i64();
2571
2572     neon_load_reg64(vm, a->vm);
2573     gen_helper_vfp_fcvt_f64_to_f16(tmp, vm, fpst, ahp_mode);
2574     tcg_temp_free_i64(vm);
2575     tcg_gen_st16_i32(tmp, cpu_env, vfp_f16_offset(a->vd, a->t));
2576     tcg_temp_free_i32(ahp_mode);
2577     tcg_temp_free_ptr(fpst);
2578     tcg_temp_free_i32(tmp);
2579     return true;
2580 }
2581
2582 static bool trans_VRINTR_sp(DisasContext *s, arg_VRINTR_sp *a)
2583 {
2584     TCGv_ptr fpst;
2585     TCGv_i32 tmp;
2586
2587     if (!dc_isar_feature(aa32_vrint, s)) {
2588         return false;
2589     }
2590
2591     if (!vfp_access_check(s)) {
2592         return true;
2593     }
2594
2595     tmp = tcg_temp_new_i32();
2596     neon_load_reg32(tmp, a->vm);
2597     fpst = fpstatus_ptr(FPST_FPCR);
2598     gen_helper_rints(tmp, tmp, fpst);
2599     neon_store_reg32(tmp, a->vd);
2600     tcg_temp_free_ptr(fpst);
2601     tcg_temp_free_i32(tmp);
2602     return true;
2603 }
2604
2605 static bool trans_VRINTR_dp(DisasContext *s, arg_VRINTR_dp *a)
2606 {
2607     TCGv_ptr fpst;
2608     TCGv_i64 tmp;
2609
2610     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2611         return false;
2612     }
2613
2614     if (!dc_isar_feature(aa32_vrint, s)) {
2615         return false;
2616     }
2617
2618     /* UNDEF accesses to D16-D31 if they don't exist. */
2619     if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2620         return false;
2621     }
2622
2623     if (!vfp_access_check(s)) {
2624         return true;
2625     }
2626
2627     tmp = tcg_temp_new_i64();
2628     neon_load_reg64(tmp, a->vm);
2629     fpst = fpstatus_ptr(FPST_FPCR);
2630     gen_helper_rintd(tmp, tmp, fpst);
2631     neon_store_reg64(tmp, a->vd);
2632     tcg_temp_free_ptr(fpst);
2633     tcg_temp_free_i64(tmp);
2634     return true;
2635 }
2636
2637 static bool trans_VRINTZ_sp(DisasContext *s, arg_VRINTZ_sp *a)
2638 {
2639     TCGv_ptr fpst;
2640     TCGv_i32 tmp;
2641     TCGv_i32 tcg_rmode;
2642
2643     if (!dc_isar_feature(aa32_vrint, s)) {
2644         return false;
2645     }
2646
2647     if (!vfp_access_check(s)) {
2648         return true;
2649     }
2650
2651     tmp = tcg_temp_new_i32();
2652     neon_load_reg32(tmp, a->vm);
2653     fpst = fpstatus_ptr(FPST_FPCR);
2654     tcg_rmode = tcg_const_i32(float_round_to_zero);
2655     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
2656     gen_helper_rints(tmp, tmp, fpst);
2657     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
2658     neon_store_reg32(tmp, a->vd);
2659     tcg_temp_free_ptr(fpst);
2660     tcg_temp_free_i32(tcg_rmode);
2661     tcg_temp_free_i32(tmp);
2662     return true;
2663 }
2664
2665 static bool trans_VRINTZ_dp(DisasContext *s, arg_VRINTZ_dp *a)
2666 {
2667     TCGv_ptr fpst;
2668     TCGv_i64 tmp;
2669     TCGv_i32 tcg_rmode;
2670
2671     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2672         return false;
2673     }
2674
2675     if (!dc_isar_feature(aa32_vrint, s)) {
2676         return false;
2677     }
2678
2679     /* UNDEF accesses to D16-D31 if they don't exist. */
2680     if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2681         return false;
2682     }
2683
2684     if (!vfp_access_check(s)) {
2685         return true;
2686     }
2687
2688     tmp = tcg_temp_new_i64();
2689     neon_load_reg64(tmp, a->vm);
2690     fpst = fpstatus_ptr(FPST_FPCR);
2691     tcg_rmode = tcg_const_i32(float_round_to_zero);
2692     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
2693     gen_helper_rintd(tmp, tmp, fpst);
2694     gen_helper_set_rmode(tcg_rmode, tcg_rmode, fpst);
2695     neon_store_reg64(tmp, a->vd);
2696     tcg_temp_free_ptr(fpst);
2697     tcg_temp_free_i64(tmp);
2698     tcg_temp_free_i32(tcg_rmode);
2699     return true;
2700 }
2701
2702 static bool trans_VRINTX_sp(DisasContext *s, arg_VRINTX_sp *a)
2703 {
2704     TCGv_ptr fpst;
2705     TCGv_i32 tmp;
2706
2707     if (!dc_isar_feature(aa32_vrint, s)) {
2708         return false;
2709     }
2710
2711     if (!vfp_access_check(s)) {
2712         return true;
2713     }
2714
2715     tmp = tcg_temp_new_i32();
2716     neon_load_reg32(tmp, a->vm);
2717     fpst = fpstatus_ptr(FPST_FPCR);
2718     gen_helper_rints_exact(tmp, tmp, fpst);
2719     neon_store_reg32(tmp, a->vd);
2720     tcg_temp_free_ptr(fpst);
2721     tcg_temp_free_i32(tmp);
2722     return true;
2723 }
2724
2725 static bool trans_VRINTX_dp(DisasContext *s, arg_VRINTX_dp *a)
2726 {
2727     TCGv_ptr fpst;
2728     TCGv_i64 tmp;
2729
2730     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2731         return false;
2732     }
2733
2734     if (!dc_isar_feature(aa32_vrint, s)) {
2735         return false;
2736     }
2737
2738     /* UNDEF accesses to D16-D31 if they don't exist. */
2739     if (!dc_isar_feature(aa32_simd_r32, s) && ((a->vd | a->vm) & 0x10)) {
2740         return false;
2741     }
2742
2743     if (!vfp_access_check(s)) {
2744         return true;
2745     }
2746
2747     tmp = tcg_temp_new_i64();
2748     neon_load_reg64(tmp, a->vm);
2749     fpst = fpstatus_ptr(FPST_FPCR);
2750     gen_helper_rintd_exact(tmp, tmp, fpst);
2751     neon_store_reg64(tmp, a->vd);
2752     tcg_temp_free_ptr(fpst);
2753     tcg_temp_free_i64(tmp);
2754     return true;
2755 }
2756
2757 static bool trans_VCVT_sp(DisasContext *s, arg_VCVT_sp *a)
2758 {
2759     TCGv_i64 vd;
2760     TCGv_i32 vm;
2761
2762     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2763         return false;
2764     }
2765
2766     /* UNDEF accesses to D16-D31 if they don't exist. */
2767     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
2768         return false;
2769     }
2770
2771     if (!vfp_access_check(s)) {
2772         return true;
2773     }
2774
2775     vm = tcg_temp_new_i32();
2776     vd = tcg_temp_new_i64();
2777     neon_load_reg32(vm, a->vm);
2778     gen_helper_vfp_fcvtds(vd, vm, cpu_env);
2779     neon_store_reg64(vd, a->vd);
2780     tcg_temp_free_i32(vm);
2781     tcg_temp_free_i64(vd);
2782     return true;
2783 }
2784
2785 static bool trans_VCVT_dp(DisasContext *s, arg_VCVT_dp *a)
2786 {
2787     TCGv_i64 vm;
2788     TCGv_i32 vd;
2789
2790     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2791         return false;
2792     }
2793
2794     /* UNDEF accesses to D16-D31 if they don't exist. */
2795     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
2796         return false;
2797     }
2798
2799     if (!vfp_access_check(s)) {
2800         return true;
2801     }
2802
2803     vd = tcg_temp_new_i32();
2804     vm = tcg_temp_new_i64();
2805     neon_load_reg64(vm, a->vm);
2806     gen_helper_vfp_fcvtsd(vd, vm, cpu_env);
2807     neon_store_reg32(vd, a->vd);
2808     tcg_temp_free_i32(vd);
2809     tcg_temp_free_i64(vm);
2810     return true;
2811 }
2812
2813 static bool trans_VCVT_int_sp(DisasContext *s, arg_VCVT_int_sp *a)
2814 {
2815     TCGv_i32 vm;
2816     TCGv_ptr fpst;
2817
2818     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
2819         return false;
2820     }
2821
2822     if (!vfp_access_check(s)) {
2823         return true;
2824     }
2825
2826     vm = tcg_temp_new_i32();
2827     neon_load_reg32(vm, a->vm);
2828     fpst = fpstatus_ptr(FPST_FPCR);
2829     if (a->s) {
2830         /* i32 -> f32 */
2831         gen_helper_vfp_sitos(vm, vm, fpst);
2832     } else {
2833         /* u32 -> f32 */
2834         gen_helper_vfp_uitos(vm, vm, fpst);
2835     }
2836     neon_store_reg32(vm, a->vd);
2837     tcg_temp_free_i32(vm);
2838     tcg_temp_free_ptr(fpst);
2839     return true;
2840 }
2841
2842 static bool trans_VCVT_int_dp(DisasContext *s, arg_VCVT_int_dp *a)
2843 {
2844     TCGv_i32 vm;
2845     TCGv_i64 vd;
2846     TCGv_ptr fpst;
2847
2848     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2849         return false;
2850     }
2851
2852     /* UNDEF accesses to D16-D31 if they don't exist. */
2853     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
2854         return false;
2855     }
2856
2857     if (!vfp_access_check(s)) {
2858         return true;
2859     }
2860
2861     vm = tcg_temp_new_i32();
2862     vd = tcg_temp_new_i64();
2863     neon_load_reg32(vm, a->vm);
2864     fpst = fpstatus_ptr(FPST_FPCR);
2865     if (a->s) {
2866         /* i32 -> f64 */
2867         gen_helper_vfp_sitod(vd, vm, fpst);
2868     } else {
2869         /* u32 -> f64 */
2870         gen_helper_vfp_uitod(vd, vm, fpst);
2871     }
2872     neon_store_reg64(vd, a->vd);
2873     tcg_temp_free_i32(vm);
2874     tcg_temp_free_i64(vd);
2875     tcg_temp_free_ptr(fpst);
2876     return true;
2877 }
2878
2879 static bool trans_VJCVT(DisasContext *s, arg_VJCVT *a)
2880 {
2881     TCGv_i32 vd;
2882     TCGv_i64 vm;
2883
2884     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
2885         return false;
2886     }
2887
2888     if (!dc_isar_feature(aa32_jscvt, s)) {
2889         return false;
2890     }
2891
2892     /* UNDEF accesses to D16-D31 if they don't exist. */
2893     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
2894         return false;
2895     }
2896
2897     if (!vfp_access_check(s)) {
2898         return true;
2899     }
2900
2901     vm = tcg_temp_new_i64();
2902     vd = tcg_temp_new_i32();
2903     neon_load_reg64(vm, a->vm);
2904     gen_helper_vjcvt(vd, vm, cpu_env);
2905     neon_store_reg32(vd, a->vd);
2906     tcg_temp_free_i64(vm);
2907     tcg_temp_free_i32(vd);
2908     return true;
2909 }
2910
2911 static bool trans_VCVT_fix_sp(DisasContext *s, arg_VCVT_fix_sp *a)
2912 {
2913     TCGv_i32 vd, shift;
2914     TCGv_ptr fpst;
2915     int frac_bits;
2916
2917     if (!dc_isar_feature(aa32_fpsp_v3, s)) {
2918         return false;
2919     }
2920
2921     if (!vfp_access_check(s)) {
2922         return true;
2923     }
2924
2925     frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
2926
2927     vd = tcg_temp_new_i32();
2928     neon_load_reg32(vd, a->vd);
2929
2930     fpst = fpstatus_ptr(FPST_FPCR);
2931     shift = tcg_const_i32(frac_bits);
2932
2933     /* Switch on op:U:sx bits */
2934     switch (a->opc) {
2935     case 0:
2936         gen_helper_vfp_shtos(vd, vd, shift, fpst);
2937         break;
2938     case 1:
2939         gen_helper_vfp_sltos(vd, vd, shift, fpst);
2940         break;
2941     case 2:
2942         gen_helper_vfp_uhtos(vd, vd, shift, fpst);
2943         break;
2944     case 3:
2945         gen_helper_vfp_ultos(vd, vd, shift, fpst);
2946         break;
2947     case 4:
2948         gen_helper_vfp_toshs_round_to_zero(vd, vd, shift, fpst);
2949         break;
2950     case 5:
2951         gen_helper_vfp_tosls_round_to_zero(vd, vd, shift, fpst);
2952         break;
2953     case 6:
2954         gen_helper_vfp_touhs_round_to_zero(vd, vd, shift, fpst);
2955         break;
2956     case 7:
2957         gen_helper_vfp_touls_round_to_zero(vd, vd, shift, fpst);
2958         break;
2959     default:
2960         g_assert_not_reached();
2961     }
2962
2963     neon_store_reg32(vd, a->vd);
2964     tcg_temp_free_i32(vd);
2965     tcg_temp_free_i32(shift);
2966     tcg_temp_free_ptr(fpst);
2967     return true;
2968 }
2969
2970 static bool trans_VCVT_fix_dp(DisasContext *s, arg_VCVT_fix_dp *a)
2971 {
2972     TCGv_i64 vd;
2973     TCGv_i32 shift;
2974     TCGv_ptr fpst;
2975     int frac_bits;
2976
2977     if (!dc_isar_feature(aa32_fpdp_v3, s)) {
2978         return false;
2979     }
2980
2981     /* UNDEF accesses to D16-D31 if they don't exist. */
2982     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vd & 0x10)) {
2983         return false;
2984     }
2985
2986     if (!vfp_access_check(s)) {
2987         return true;
2988     }
2989
2990     frac_bits = (a->opc & 1) ? (32 - a->imm) : (16 - a->imm);
2991
2992     vd = tcg_temp_new_i64();
2993     neon_load_reg64(vd, a->vd);
2994
2995     fpst = fpstatus_ptr(FPST_FPCR);
2996     shift = tcg_const_i32(frac_bits);
2997
2998     /* Switch on op:U:sx bits */
2999     switch (a->opc) {
3000     case 0:
3001         gen_helper_vfp_shtod(vd, vd, shift, fpst);
3002         break;
3003     case 1:
3004         gen_helper_vfp_sltod(vd, vd, shift, fpst);
3005         break;
3006     case 2:
3007         gen_helper_vfp_uhtod(vd, vd, shift, fpst);
3008         break;
3009     case 3:
3010         gen_helper_vfp_ultod(vd, vd, shift, fpst);
3011         break;
3012     case 4:
3013         gen_helper_vfp_toshd_round_to_zero(vd, vd, shift, fpst);
3014         break;
3015     case 5:
3016         gen_helper_vfp_tosld_round_to_zero(vd, vd, shift, fpst);
3017         break;
3018     case 6:
3019         gen_helper_vfp_touhd_round_to_zero(vd, vd, shift, fpst);
3020         break;
3021     case 7:
3022         gen_helper_vfp_tould_round_to_zero(vd, vd, shift, fpst);
3023         break;
3024     default:
3025         g_assert_not_reached();
3026     }
3027
3028     neon_store_reg64(vd, a->vd);
3029     tcg_temp_free_i64(vd);
3030     tcg_temp_free_i32(shift);
3031     tcg_temp_free_ptr(fpst);
3032     return true;
3033 }
3034
3035 static bool trans_VCVT_sp_int(DisasContext *s, arg_VCVT_sp_int *a)
3036 {
3037     TCGv_i32 vm;
3038     TCGv_ptr fpst;
3039
3040     if (!dc_isar_feature(aa32_fpsp_v2, s)) {
3041         return false;
3042     }
3043
3044     if (!vfp_access_check(s)) {
3045         return true;
3046     }
3047
3048     fpst = fpstatus_ptr(FPST_FPCR);
3049     vm = tcg_temp_new_i32();
3050     neon_load_reg32(vm, a->vm);
3051
3052     if (a->s) {
3053         if (a->rz) {
3054             gen_helper_vfp_tosizs(vm, vm, fpst);
3055         } else {
3056             gen_helper_vfp_tosis(vm, vm, fpst);
3057         }
3058     } else {
3059         if (a->rz) {
3060             gen_helper_vfp_touizs(vm, vm, fpst);
3061         } else {
3062             gen_helper_vfp_touis(vm, vm, fpst);
3063         }
3064     }
3065     neon_store_reg32(vm, a->vd);
3066     tcg_temp_free_i32(vm);
3067     tcg_temp_free_ptr(fpst);
3068     return true;
3069 }
3070
3071 static bool trans_VCVT_dp_int(DisasContext *s, arg_VCVT_dp_int *a)
3072 {
3073     TCGv_i32 vd;
3074     TCGv_i64 vm;
3075     TCGv_ptr fpst;
3076
3077     if (!dc_isar_feature(aa32_fpdp_v2, s)) {
3078         return false;
3079     }
3080
3081     /* UNDEF accesses to D16-D31 if they don't exist. */
3082     if (!dc_isar_feature(aa32_simd_r32, s) && (a->vm & 0x10)) {
3083         return false;
3084     }
3085
3086     if (!vfp_access_check(s)) {
3087         return true;
3088     }
3089
3090     fpst = fpstatus_ptr(FPST_FPCR);
3091     vm = tcg_temp_new_i64();
3092     vd = tcg_temp_new_i32();
3093     neon_load_reg64(vm, a->vm);
3094
3095     if (a->s) {
3096         if (a->rz) {
3097             gen_helper_vfp_tosizd(vd, vm, fpst);
3098         } else {
3099             gen_helper_vfp_tosid(vd, vm, fpst);
3100         }
3101     } else {
3102         if (a->rz) {
3103             gen_helper_vfp_touizd(vd, vm, fpst);
3104         } else {
3105             gen_helper_vfp_touid(vd, vm, fpst);
3106         }
3107     }
3108     neon_store_reg32(vd, a->vd);
3109     tcg_temp_free_i32(vd);
3110     tcg_temp_free_i64(vm);
3111     tcg_temp_free_ptr(fpst);
3112     return true;
3113 }
3114
3115 /*
3116  * Decode VLLDM and VLSTM are nonstandard because:
3117  *  * if there is no FPU then these insns must NOP in
3118  *    Secure state and UNDEF in Nonsecure state
3119  *  * if there is an FPU then these insns do not have
3120  *    the usual behaviour that vfp_access_check() provides of
3121  *    being controlled by CPACR/NSACR enable bits or the
3122  *    lazy-stacking logic.
3123  */
3124 static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a)
3125 {
3126     TCGv_i32 fptr;
3127
3128     if (!arm_dc_feature(s, ARM_FEATURE_M) ||
3129         !arm_dc_feature(s, ARM_FEATURE_V8)) {
3130         return false;
3131     }
3132     /*
3133      * If not secure, UNDEF. We must emit code for this
3134      * rather than returning false so that this takes
3135      * precedence over the m-nocp.decode NOCP fallback.
3136      */
3137     if (!s->v8m_secure) {
3138         unallocated_encoding(s);
3139         return true;
3140     }
3141     /* If no fpu, NOP. */
3142     if (!dc_isar_feature(aa32_vfp, s)) {
3143         return true;
3144     }
3145
3146     fptr = load_reg(s, a->rn);
3147     if (a->l) {
3148         gen_helper_v7m_vlldm(cpu_env, fptr);
3149     } else {
3150         gen_helper_v7m_vlstm(cpu_env, fptr);
3151     }
3152     tcg_temp_free_i32(fptr);
3153
3154     /* End the TB, because we have updated FP control bits */
3155     s->base.is_jmp = DISAS_UPDATE_EXIT;
3156     return true;
3157 }
3158
3159 static bool trans_NOCP(DisasContext *s, arg_NOCP *a)
3160 {
3161     /*
3162      * Handle M-profile early check for disabled coprocessor:
3163      * all we need to do here is emit the NOCP exception if
3164      * the coprocessor is disabled. Otherwise we return false
3165      * and the real VFP/etc decode will handle the insn.
3166      */
3167     assert(arm_dc_feature(s, ARM_FEATURE_M));
3168
3169     if (a->cp == 11) {
3170         a->cp = 10;
3171     }
3172     /* TODO: in v8.1M cp 8, 9, 14, 15 also are governed by the cp10 enable */
3173
3174     if (a->cp != 10) {
3175         gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
3176                            syn_uncategorized(), default_exception_el(s));
3177         return true;
3178     }
3179
3180     if (s->fp_excp_el != 0) {
3181         gen_exception_insn(s, s->pc_curr, EXCP_NOCP,
3182                            syn_uncategorized(), s->fp_excp_el);
3183         return true;
3184     }
3185
3186     return false;
3187 }