xref: /qemu/target/arm/tcg/translate-mve.c (revision 54dc78a901188d208a3dfedb0f98230043509120)
16390eed4SPeter Maydell /*
26390eed4SPeter Maydell  *  ARM translation: M-profile MVE instructions
36390eed4SPeter Maydell  *
46390eed4SPeter Maydell  *  Copyright (c) 2021 Linaro, Ltd.
56390eed4SPeter Maydell  *
66390eed4SPeter Maydell  * This library is free software; you can redistribute it and/or
76390eed4SPeter Maydell  * modify it under the terms of the GNU Lesser General Public
86390eed4SPeter Maydell  * License as published by the Free Software Foundation; either
96390eed4SPeter Maydell  * version 2.1 of the License, or (at your option) any later version.
106390eed4SPeter Maydell  *
116390eed4SPeter Maydell  * This library is distributed in the hope that it will be useful,
126390eed4SPeter Maydell  * but WITHOUT ANY WARRANTY; without even the implied warranty of
136390eed4SPeter Maydell  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
146390eed4SPeter Maydell  * Lesser General Public License for more details.
156390eed4SPeter Maydell  *
166390eed4SPeter Maydell  * You should have received a copy of the GNU Lesser General Public
176390eed4SPeter Maydell  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
186390eed4SPeter Maydell  */
196390eed4SPeter Maydell 
206390eed4SPeter Maydell #include "qemu/osdep.h"
216390eed4SPeter Maydell #include "tcg/tcg-op.h"
226390eed4SPeter Maydell #include "tcg/tcg-op-gvec.h"
236390eed4SPeter Maydell #include "exec/exec-all.h"
246390eed4SPeter Maydell #include "exec/gen-icount.h"
256390eed4SPeter Maydell #include "translate.h"
266390eed4SPeter Maydell #include "translate-a32.h"
276390eed4SPeter Maydell 
28395b92d5SPeter Maydell static inline int vidup_imm(DisasContext *s, int x)
29395b92d5SPeter Maydell {
30395b92d5SPeter Maydell     return 1 << x;
31395b92d5SPeter Maydell }
32395b92d5SPeter Maydell 
336390eed4SPeter Maydell /* Include the generated decoder */
346390eed4SPeter Maydell #include "decode-mve.c.inc"
35507b6a50SPeter Maydell 
36507b6a50SPeter Maydell typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
370f0f2bd5SPeter Maydell typedef void MVEGenOneOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
3868245e44SPeter Maydell typedef void MVEGenTwoOpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_ptr);
39e51896b3SPeter Maydell typedef void MVEGenTwoOpScalarFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
40f9ed6174SPeter Maydell typedef void MVEGenTwoOpShiftFn(TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
411d2386f7SPeter Maydell typedef void MVEGenDualAccOpFn(TCGv_i64, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i64);
426f060a63SPeter Maydell typedef void MVEGenVADDVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32);
43eab84139SPeter Maydell typedef void MVEGenOneOpImmFn(TCGv_ptr, TCGv_ptr, TCGv_i64);
44395b92d5SPeter Maydell typedef void MVEGenVIDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32);
45395b92d5SPeter Maydell typedef void MVEGenVIWDUPFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_i32, TCGv_i32, TCGv_i32);
46eff5d9a9SPeter Maydell typedef void MVEGenCmpFn(TCGv_ptr, TCGv_ptr, TCGv_ptr);
47cce81873SPeter Maydell typedef void MVEGenScalarCmpFn(TCGv_ptr, TCGv_ptr, TCGv_i32);
487f061c0aSPeter Maydell typedef void MVEGenVABAVFn(TCGv_i32, TCGv_ptr, TCGv_ptr, TCGv_ptr, TCGv_i32);
49507b6a50SPeter Maydell 
50507b6a50SPeter Maydell /* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */
51507b6a50SPeter Maydell static inline long mve_qreg_offset(unsigned reg)
52507b6a50SPeter Maydell {
53507b6a50SPeter Maydell     return offsetof(CPUARMState, vfp.zregs[reg].d[0]);
54507b6a50SPeter Maydell }
55507b6a50SPeter Maydell 
56507b6a50SPeter Maydell static TCGv_ptr mve_qreg_ptr(unsigned reg)
57507b6a50SPeter Maydell {
58507b6a50SPeter Maydell     TCGv_ptr ret = tcg_temp_new_ptr();
59507b6a50SPeter Maydell     tcg_gen_addi_ptr(ret, cpu_env, mve_qreg_offset(reg));
60507b6a50SPeter Maydell     return ret;
61507b6a50SPeter Maydell }
62507b6a50SPeter Maydell 
63507b6a50SPeter Maydell static bool mve_check_qreg_bank(DisasContext *s, int qmask)
64507b6a50SPeter Maydell {
65507b6a50SPeter Maydell     /*
66507b6a50SPeter Maydell      * Check whether Qregs are in range. For v8.1M only Q0..Q7
67507b6a50SPeter Maydell      * are supported, see VFPSmallRegisterBank().
68507b6a50SPeter Maydell      */
69507b6a50SPeter Maydell     return qmask < 8;
70507b6a50SPeter Maydell }
71507b6a50SPeter Maydell 
724f57ef95SPeter Maydell bool mve_eci_check(DisasContext *s)
73507b6a50SPeter Maydell {
74507b6a50SPeter Maydell     /*
75507b6a50SPeter Maydell      * This is a beatwise insn: check that ECI is valid (not a
76507b6a50SPeter Maydell      * reserved value) and note that we are handling it.
77507b6a50SPeter Maydell      * Return true if OK, false if we generated an exception.
78507b6a50SPeter Maydell      */
79507b6a50SPeter Maydell     s->eci_handled = true;
80507b6a50SPeter Maydell     switch (s->eci) {
81507b6a50SPeter Maydell     case ECI_NONE:
82507b6a50SPeter Maydell     case ECI_A0:
83507b6a50SPeter Maydell     case ECI_A0A1:
84507b6a50SPeter Maydell     case ECI_A0A1A2:
85507b6a50SPeter Maydell     case ECI_A0A1A2B0:
86507b6a50SPeter Maydell         return true;
87507b6a50SPeter Maydell     default:
88507b6a50SPeter Maydell         /* Reserved value: INVSTATE UsageFault */
89507b6a50SPeter Maydell         gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(),
90507b6a50SPeter Maydell                            default_exception_el(s));
91507b6a50SPeter Maydell         return false;
92507b6a50SPeter Maydell     }
93507b6a50SPeter Maydell }
94507b6a50SPeter Maydell 
95507b6a50SPeter Maydell static void mve_update_eci(DisasContext *s)
96507b6a50SPeter Maydell {
97507b6a50SPeter Maydell     /*
98507b6a50SPeter Maydell      * The helper function will always update the CPUState field,
99507b6a50SPeter Maydell      * so we only need to update the DisasContext field.
100507b6a50SPeter Maydell      */
101507b6a50SPeter Maydell     if (s->eci) {
102507b6a50SPeter Maydell         s->eci = (s->eci == ECI_A0A1A2B0) ? ECI_A0 : ECI_NONE;
103507b6a50SPeter Maydell     }
104507b6a50SPeter Maydell }
105507b6a50SPeter Maydell 
1064f57ef95SPeter Maydell void mve_update_and_store_eci(DisasContext *s)
107387debdbSPeter Maydell {
108387debdbSPeter Maydell     /*
109387debdbSPeter Maydell      * For insns which don't call a helper function that will call
110387debdbSPeter Maydell      * mve_advance_vpt(), this version updates s->eci and also stores
111387debdbSPeter Maydell      * it out to the CPUState field.
112387debdbSPeter Maydell      */
113387debdbSPeter Maydell     if (s->eci) {
114387debdbSPeter Maydell         mve_update_eci(s);
115387debdbSPeter Maydell         store_cpu_field(tcg_constant_i32(s->eci << 4), condexec_bits);
116387debdbSPeter Maydell     }
117387debdbSPeter Maydell }
118387debdbSPeter Maydell 
1191d2386f7SPeter Maydell static bool mve_skip_first_beat(DisasContext *s)
1201d2386f7SPeter Maydell {
1211d2386f7SPeter Maydell     /* Return true if PSR.ECI says we must skip the first beat of this insn */
1221d2386f7SPeter Maydell     switch (s->eci) {
1231d2386f7SPeter Maydell     case ECI_NONE:
1241d2386f7SPeter Maydell         return false;
1251d2386f7SPeter Maydell     case ECI_A0:
1261d2386f7SPeter Maydell     case ECI_A0A1:
1271d2386f7SPeter Maydell     case ECI_A0A1A2:
1281d2386f7SPeter Maydell     case ECI_A0A1A2B0:
1291d2386f7SPeter Maydell         return true;
1301d2386f7SPeter Maydell     default:
1311d2386f7SPeter Maydell         g_assert_not_reached();
1321d2386f7SPeter Maydell     }
1331d2386f7SPeter Maydell }
1341d2386f7SPeter Maydell 
135d59ccc30SPeter Maydell static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn,
136d59ccc30SPeter Maydell                     unsigned msize)
137507b6a50SPeter Maydell {
138507b6a50SPeter Maydell     TCGv_i32 addr;
139507b6a50SPeter Maydell     uint32_t offset;
140507b6a50SPeter Maydell     TCGv_ptr qreg;
141507b6a50SPeter Maydell 
142507b6a50SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
143507b6a50SPeter Maydell         !mve_check_qreg_bank(s, a->qd) ||
144507b6a50SPeter Maydell         !fn) {
145507b6a50SPeter Maydell         return false;
146507b6a50SPeter Maydell     }
147507b6a50SPeter Maydell 
148507b6a50SPeter Maydell     /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */
149507b6a50SPeter Maydell     if (a->rn == 15 || (a->rn == 13 && a->w)) {
150507b6a50SPeter Maydell         return false;
151507b6a50SPeter Maydell     }
152507b6a50SPeter Maydell 
153507b6a50SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
154507b6a50SPeter Maydell         return true;
155507b6a50SPeter Maydell     }
156507b6a50SPeter Maydell 
157d59ccc30SPeter Maydell     offset = a->imm << msize;
158507b6a50SPeter Maydell     if (!a->a) {
159507b6a50SPeter Maydell         offset = -offset;
160507b6a50SPeter Maydell     }
161507b6a50SPeter Maydell     addr = load_reg(s, a->rn);
162507b6a50SPeter Maydell     if (a->p) {
163507b6a50SPeter Maydell         tcg_gen_addi_i32(addr, addr, offset);
164507b6a50SPeter Maydell     }
165507b6a50SPeter Maydell 
166507b6a50SPeter Maydell     qreg = mve_qreg_ptr(a->qd);
167507b6a50SPeter Maydell     fn(cpu_env, qreg, addr);
168507b6a50SPeter Maydell     tcg_temp_free_ptr(qreg);
169507b6a50SPeter Maydell 
170507b6a50SPeter Maydell     /*
171507b6a50SPeter Maydell      * Writeback always happens after the last beat of the insn,
172507b6a50SPeter Maydell      * regardless of predication
173507b6a50SPeter Maydell      */
174507b6a50SPeter Maydell     if (a->w) {
175507b6a50SPeter Maydell         if (!a->p) {
176507b6a50SPeter Maydell             tcg_gen_addi_i32(addr, addr, offset);
177507b6a50SPeter Maydell         }
178507b6a50SPeter Maydell         store_reg(s, a->rn, addr);
179507b6a50SPeter Maydell     } else {
180507b6a50SPeter Maydell         tcg_temp_free_i32(addr);
181507b6a50SPeter Maydell     }
182507b6a50SPeter Maydell     mve_update_eci(s);
183507b6a50SPeter Maydell     return true;
184507b6a50SPeter Maydell }
185507b6a50SPeter Maydell 
186507b6a50SPeter Maydell static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a)
187507b6a50SPeter Maydell {
188507b6a50SPeter Maydell     static MVEGenLdStFn * const ldstfns[4][2] = {
189507b6a50SPeter Maydell         { gen_helper_mve_vstrb, gen_helper_mve_vldrb },
190507b6a50SPeter Maydell         { gen_helper_mve_vstrh, gen_helper_mve_vldrh },
191507b6a50SPeter Maydell         { gen_helper_mve_vstrw, gen_helper_mve_vldrw },
192507b6a50SPeter Maydell         { NULL, NULL }
193507b6a50SPeter Maydell     };
194d59ccc30SPeter Maydell     return do_ldst(s, a, ldstfns[a->size][a->l], a->size);
195507b6a50SPeter Maydell }
1962fc6b751SPeter Maydell 
197d59ccc30SPeter Maydell #define DO_VLDST_WIDE_NARROW(OP, SLD, ULD, ST, MSIZE)           \
1982fc6b751SPeter Maydell     static bool trans_##OP(DisasContext *s, arg_VLDR_VSTR *a)   \
1992fc6b751SPeter Maydell     {                                                           \
2002fc6b751SPeter Maydell         static MVEGenLdStFn * const ldstfns[2][2] = {           \
2012fc6b751SPeter Maydell             { gen_helper_mve_##ST, gen_helper_mve_##SLD },      \
2022fc6b751SPeter Maydell             { NULL, gen_helper_mve_##ULD },                     \
2032fc6b751SPeter Maydell         };                                                      \
204d59ccc30SPeter Maydell         return do_ldst(s, a, ldstfns[a->u][a->l], MSIZE);       \
2052fc6b751SPeter Maydell     }
2062fc6b751SPeter Maydell 
207d59ccc30SPeter Maydell DO_VLDST_WIDE_NARROW(VLDSTB_H, vldrb_sh, vldrb_uh, vstrb_h, MO_8)
208d59ccc30SPeter Maydell DO_VLDST_WIDE_NARROW(VLDSTB_W, vldrb_sw, vldrb_uw, vstrb_w, MO_8)
209d59ccc30SPeter Maydell DO_VLDST_WIDE_NARROW(VLDSTH_W, vldrh_sw, vldrh_uw, vstrh_w, MO_16)
2100f0f2bd5SPeter Maydell 
211ab59362fSPeter Maydell static bool trans_VDUP(DisasContext *s, arg_VDUP *a)
212ab59362fSPeter Maydell {
213ab59362fSPeter Maydell     TCGv_ptr qd;
214ab59362fSPeter Maydell     TCGv_i32 rt;
215ab59362fSPeter Maydell 
216ab59362fSPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
217ab59362fSPeter Maydell         !mve_check_qreg_bank(s, a->qd)) {
218ab59362fSPeter Maydell         return false;
219ab59362fSPeter Maydell     }
220ab59362fSPeter Maydell     if (a->rt == 13 || a->rt == 15) {
221ab59362fSPeter Maydell         /* UNPREDICTABLE; we choose to UNDEF */
222ab59362fSPeter Maydell         return false;
223ab59362fSPeter Maydell     }
224ab59362fSPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
225ab59362fSPeter Maydell         return true;
226ab59362fSPeter Maydell     }
227ab59362fSPeter Maydell 
228ab59362fSPeter Maydell     qd = mve_qreg_ptr(a->qd);
229ab59362fSPeter Maydell     rt = load_reg(s, a->rt);
230ab59362fSPeter Maydell     tcg_gen_dup_i32(a->size, rt, rt);
231ab59362fSPeter Maydell     gen_helper_mve_vdup(cpu_env, qd, rt);
232ab59362fSPeter Maydell     tcg_temp_free_ptr(qd);
233ab59362fSPeter Maydell     tcg_temp_free_i32(rt);
234ab59362fSPeter Maydell     mve_update_eci(s);
235ab59362fSPeter Maydell     return true;
236ab59362fSPeter Maydell }
237ab59362fSPeter Maydell 
2380f0f2bd5SPeter Maydell static bool do_1op(DisasContext *s, arg_1op *a, MVEGenOneOpFn fn)
2390f0f2bd5SPeter Maydell {
2400f0f2bd5SPeter Maydell     TCGv_ptr qd, qm;
2410f0f2bd5SPeter Maydell 
2420f0f2bd5SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
2430f0f2bd5SPeter Maydell         !mve_check_qreg_bank(s, a->qd | a->qm) ||
2440f0f2bd5SPeter Maydell         !fn) {
2450f0f2bd5SPeter Maydell         return false;
2460f0f2bd5SPeter Maydell     }
2470f0f2bd5SPeter Maydell 
2480f0f2bd5SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
2490f0f2bd5SPeter Maydell         return true;
2500f0f2bd5SPeter Maydell     }
2510f0f2bd5SPeter Maydell 
2520f0f2bd5SPeter Maydell     qd = mve_qreg_ptr(a->qd);
2530f0f2bd5SPeter Maydell     qm = mve_qreg_ptr(a->qm);
2540f0f2bd5SPeter Maydell     fn(cpu_env, qd, qm);
2550f0f2bd5SPeter Maydell     tcg_temp_free_ptr(qd);
2560f0f2bd5SPeter Maydell     tcg_temp_free_ptr(qm);
2570f0f2bd5SPeter Maydell     mve_update_eci(s);
2580f0f2bd5SPeter Maydell     return true;
2590f0f2bd5SPeter Maydell }
2600f0f2bd5SPeter Maydell 
2610f0f2bd5SPeter Maydell #define DO_1OP(INSN, FN)                                        \
2620f0f2bd5SPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_1op *a)       \
2630f0f2bd5SPeter Maydell     {                                                           \
2640f0f2bd5SPeter Maydell         static MVEGenOneOpFn * const fns[] = {                  \
2650f0f2bd5SPeter Maydell             gen_helper_mve_##FN##b,                             \
2660f0f2bd5SPeter Maydell             gen_helper_mve_##FN##h,                             \
2670f0f2bd5SPeter Maydell             gen_helper_mve_##FN##w,                             \
2680f0f2bd5SPeter Maydell             NULL,                                               \
2690f0f2bd5SPeter Maydell         };                                                      \
2700f0f2bd5SPeter Maydell         return do_1op(s, a, fns[a->size]);                      \
2710f0f2bd5SPeter Maydell     }
2720f0f2bd5SPeter Maydell 
2730f0f2bd5SPeter Maydell DO_1OP(VCLZ, vclz)
2746437f1f7SPeter Maydell DO_1OP(VCLS, vcls)
27559c91773SPeter Maydell DO_1OP(VABS, vabs)
276399a8c76SPeter Maydell DO_1OP(VNEG, vneg)
277249b5309SPeter Maydell 
278*54dc78a9SPeter Maydell /* Narrowing moves: only size 0 and 1 are valid */
279*54dc78a9SPeter Maydell #define DO_VMOVN(INSN, FN) \
280*54dc78a9SPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_1op *a)       \
281*54dc78a9SPeter Maydell     {                                                           \
282*54dc78a9SPeter Maydell         static MVEGenOneOpFn * const fns[] = {                  \
283*54dc78a9SPeter Maydell             gen_helper_mve_##FN##b,                             \
284*54dc78a9SPeter Maydell             gen_helper_mve_##FN##h,                             \
285*54dc78a9SPeter Maydell             NULL,                                               \
286*54dc78a9SPeter Maydell             NULL,                                               \
287*54dc78a9SPeter Maydell         };                                                      \
288*54dc78a9SPeter Maydell         return do_1op(s, a, fns[a->size]);                      \
289*54dc78a9SPeter Maydell     }
290*54dc78a9SPeter Maydell 
291*54dc78a9SPeter Maydell DO_VMOVN(VMOVNB, vmovnb)
292*54dc78a9SPeter Maydell DO_VMOVN(VMOVNT, vmovnt)
293*54dc78a9SPeter Maydell DO_VMOVN(VQMOVUNB, vqmovunb)
294*54dc78a9SPeter Maydell DO_VMOVN(VQMOVUNT, vqmovunt)
295*54dc78a9SPeter Maydell DO_VMOVN(VQMOVN_BS, vqmovnbs)
296*54dc78a9SPeter Maydell DO_VMOVN(VQMOVN_TS, vqmovnts)
297*54dc78a9SPeter Maydell DO_VMOVN(VQMOVN_BU, vqmovnbu)
298*54dc78a9SPeter Maydell DO_VMOVN(VQMOVN_TU, vqmovntu)
299*54dc78a9SPeter Maydell 
300249b5309SPeter Maydell static bool trans_VREV16(DisasContext *s, arg_1op *a)
301249b5309SPeter Maydell {
302249b5309SPeter Maydell     static MVEGenOneOpFn * const fns[] = {
303249b5309SPeter Maydell         gen_helper_mve_vrev16b,
304249b5309SPeter Maydell         NULL,
305249b5309SPeter Maydell         NULL,
306249b5309SPeter Maydell         NULL,
307249b5309SPeter Maydell     };
308249b5309SPeter Maydell     return do_1op(s, a, fns[a->size]);
309249b5309SPeter Maydell }
310249b5309SPeter Maydell 
311249b5309SPeter Maydell static bool trans_VREV32(DisasContext *s, arg_1op *a)
312249b5309SPeter Maydell {
313249b5309SPeter Maydell     static MVEGenOneOpFn * const fns[] = {
314249b5309SPeter Maydell         gen_helper_mve_vrev32b,
315249b5309SPeter Maydell         gen_helper_mve_vrev32h,
316249b5309SPeter Maydell         NULL,
317249b5309SPeter Maydell         NULL,
318249b5309SPeter Maydell     };
319249b5309SPeter Maydell     return do_1op(s, a, fns[a->size]);
320249b5309SPeter Maydell }
321249b5309SPeter Maydell 
322249b5309SPeter Maydell static bool trans_VREV64(DisasContext *s, arg_1op *a)
323249b5309SPeter Maydell {
324249b5309SPeter Maydell     static MVEGenOneOpFn * const fns[] = {
325249b5309SPeter Maydell         gen_helper_mve_vrev64b,
326249b5309SPeter Maydell         gen_helper_mve_vrev64h,
327249b5309SPeter Maydell         gen_helper_mve_vrev64w,
328249b5309SPeter Maydell         NULL,
329249b5309SPeter Maydell     };
330249b5309SPeter Maydell     return do_1op(s, a, fns[a->size]);
331249b5309SPeter Maydell }
3328abd3c80SPeter Maydell 
3338abd3c80SPeter Maydell static bool trans_VMVN(DisasContext *s, arg_1op *a)
3348abd3c80SPeter Maydell {
3358abd3c80SPeter Maydell     return do_1op(s, a, gen_helper_mve_vmvn);
3368abd3c80SPeter Maydell }
33759c91773SPeter Maydell 
33859c91773SPeter Maydell static bool trans_VABS_fp(DisasContext *s, arg_1op *a)
33959c91773SPeter Maydell {
34059c91773SPeter Maydell     static MVEGenOneOpFn * const fns[] = {
34159c91773SPeter Maydell         NULL,
34259c91773SPeter Maydell         gen_helper_mve_vfabsh,
34359c91773SPeter Maydell         gen_helper_mve_vfabss,
34459c91773SPeter Maydell         NULL,
34559c91773SPeter Maydell     };
34659c91773SPeter Maydell     if (!dc_isar_feature(aa32_mve_fp, s)) {
34759c91773SPeter Maydell         return false;
34859c91773SPeter Maydell     }
34959c91773SPeter Maydell     return do_1op(s, a, fns[a->size]);
35059c91773SPeter Maydell }
351399a8c76SPeter Maydell 
352399a8c76SPeter Maydell static bool trans_VNEG_fp(DisasContext *s, arg_1op *a)
353399a8c76SPeter Maydell {
354399a8c76SPeter Maydell     static MVEGenOneOpFn * const fns[] = {
355399a8c76SPeter Maydell         NULL,
356399a8c76SPeter Maydell         gen_helper_mve_vfnegh,
357399a8c76SPeter Maydell         gen_helper_mve_vfnegs,
358399a8c76SPeter Maydell         NULL,
359399a8c76SPeter Maydell     };
360399a8c76SPeter Maydell     if (!dc_isar_feature(aa32_mve_fp, s)) {
361399a8c76SPeter Maydell         return false;
362399a8c76SPeter Maydell     }
363399a8c76SPeter Maydell     return do_1op(s, a, fns[a->size]);
364399a8c76SPeter Maydell }
36568245e44SPeter Maydell 
36668245e44SPeter Maydell static bool do_2op(DisasContext *s, arg_2op *a, MVEGenTwoOpFn fn)
36768245e44SPeter Maydell {
36868245e44SPeter Maydell     TCGv_ptr qd, qn, qm;
36968245e44SPeter Maydell 
37068245e44SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
37168245e44SPeter Maydell         !mve_check_qreg_bank(s, a->qd | a->qn | a->qm) ||
37268245e44SPeter Maydell         !fn) {
37368245e44SPeter Maydell         return false;
37468245e44SPeter Maydell     }
37568245e44SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
37668245e44SPeter Maydell         return true;
37768245e44SPeter Maydell     }
37868245e44SPeter Maydell 
37968245e44SPeter Maydell     qd = mve_qreg_ptr(a->qd);
38068245e44SPeter Maydell     qn = mve_qreg_ptr(a->qn);
38168245e44SPeter Maydell     qm = mve_qreg_ptr(a->qm);
38268245e44SPeter Maydell     fn(cpu_env, qd, qn, qm);
38368245e44SPeter Maydell     tcg_temp_free_ptr(qd);
38468245e44SPeter Maydell     tcg_temp_free_ptr(qn);
38568245e44SPeter Maydell     tcg_temp_free_ptr(qm);
38668245e44SPeter Maydell     mve_update_eci(s);
38768245e44SPeter Maydell     return true;
38868245e44SPeter Maydell }
38968245e44SPeter Maydell 
39068245e44SPeter Maydell #define DO_LOGIC(INSN, HELPER)                                  \
39168245e44SPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_2op *a)       \
39268245e44SPeter Maydell     {                                                           \
39368245e44SPeter Maydell         return do_2op(s, a, HELPER);                            \
39468245e44SPeter Maydell     }
39568245e44SPeter Maydell 
39668245e44SPeter Maydell DO_LOGIC(VAND, gen_helper_mve_vand)
39768245e44SPeter Maydell DO_LOGIC(VBIC, gen_helper_mve_vbic)
39868245e44SPeter Maydell DO_LOGIC(VORR, gen_helper_mve_vorr)
39968245e44SPeter Maydell DO_LOGIC(VORN, gen_helper_mve_vorn)
40068245e44SPeter Maydell DO_LOGIC(VEOR, gen_helper_mve_veor)
4019333fe4dSPeter Maydell 
402c386443bSPeter Maydell DO_LOGIC(VPSEL, gen_helper_mve_vpsel)
403c386443bSPeter Maydell 
4049333fe4dSPeter Maydell #define DO_2OP(INSN, FN) \
4059333fe4dSPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_2op *a)       \
4069333fe4dSPeter Maydell     {                                                           \
4079333fe4dSPeter Maydell         static MVEGenTwoOpFn * const fns[] = {                  \
4089333fe4dSPeter Maydell             gen_helper_mve_##FN##b,                             \
4099333fe4dSPeter Maydell             gen_helper_mve_##FN##h,                             \
4109333fe4dSPeter Maydell             gen_helper_mve_##FN##w,                             \
4119333fe4dSPeter Maydell             NULL,                                               \
4129333fe4dSPeter Maydell         };                                                      \
4139333fe4dSPeter Maydell         return do_2op(s, a, fns[a->size]);                      \
4149333fe4dSPeter Maydell     }
4159333fe4dSPeter Maydell 
4169333fe4dSPeter Maydell DO_2OP(VADD, vadd)
4179333fe4dSPeter Maydell DO_2OP(VSUB, vsub)
4189333fe4dSPeter Maydell DO_2OP(VMUL, vmul)
419ba62cc56SPeter Maydell DO_2OP(VMULH_S, vmulhs)
420ba62cc56SPeter Maydell DO_2OP(VMULH_U, vmulhu)
421fca87b78SPeter Maydell DO_2OP(VRMULH_S, vrmulhs)
422fca87b78SPeter Maydell DO_2OP(VRMULH_U, vrmulhu)
423cd367ff3SPeter Maydell DO_2OP(VMAX_S, vmaxs)
424cd367ff3SPeter Maydell DO_2OP(VMAX_U, vmaxu)
425cd367ff3SPeter Maydell DO_2OP(VMIN_S, vmins)
426cd367ff3SPeter Maydell DO_2OP(VMIN_U, vminu)
427bc67aa8dSPeter Maydell DO_2OP(VABD_S, vabds)
428bc67aa8dSPeter Maydell DO_2OP(VABD_U, vabdu)
429abc48e31SPeter Maydell DO_2OP(VHADD_S, vhadds)
430abc48e31SPeter Maydell DO_2OP(VHADD_U, vhaddu)
431abc48e31SPeter Maydell DO_2OP(VHSUB_S, vhsubs)
432abc48e31SPeter Maydell DO_2OP(VHSUB_U, vhsubu)
433ac6ad1dcSPeter Maydell DO_2OP(VMULL_BS, vmullbs)
434ac6ad1dcSPeter Maydell DO_2OP(VMULL_BU, vmullbu)
435ac6ad1dcSPeter Maydell DO_2OP(VMULL_TS, vmullts)
436ac6ad1dcSPeter Maydell DO_2OP(VMULL_TU, vmulltu)
437380caf6cSPeter Maydell DO_2OP(VQDMULH, vqdmulh)
438380caf6cSPeter Maydell DO_2OP(VQRDMULH, vqrdmulh)
439f741707bSPeter Maydell DO_2OP(VQADD_S, vqadds)
440f741707bSPeter Maydell DO_2OP(VQADD_U, vqaddu)
441f741707bSPeter Maydell DO_2OP(VQSUB_S, vqsubs)
442f741707bSPeter Maydell DO_2OP(VQSUB_U, vqsubu)
4430372cad8SPeter Maydell DO_2OP(VSHL_S, vshls)
4440372cad8SPeter Maydell DO_2OP(VSHL_U, vshlu)
445bb002345SPeter Maydell DO_2OP(VRSHL_S, vrshls)
446bb002345SPeter Maydell DO_2OP(VRSHL_U, vrshlu)
447483da661SPeter Maydell DO_2OP(VQSHL_S, vqshls)
448483da661SPeter Maydell DO_2OP(VQSHL_U, vqshlu)
4499dc868c4SPeter Maydell DO_2OP(VQRSHL_S, vqrshls)
4509dc868c4SPeter Maydell DO_2OP(VQRSHL_U, vqrshlu)
451fd677f80SPeter Maydell DO_2OP(VQDMLADH, vqdmladh)
452fd677f80SPeter Maydell DO_2OP(VQDMLADHX, vqdmladhx)
453fd677f80SPeter Maydell DO_2OP(VQRDMLADH, vqrdmladh)
454fd677f80SPeter Maydell DO_2OP(VQRDMLADHX, vqrdmladhx)
45592f11732SPeter Maydell DO_2OP(VQDMLSDH, vqdmlsdh)
45692f11732SPeter Maydell DO_2OP(VQDMLSDHX, vqdmlsdhx)
45792f11732SPeter Maydell DO_2OP(VQRDMLSDH, vqrdmlsdh)
45892f11732SPeter Maydell DO_2OP(VQRDMLSDHX, vqrdmlsdhx)
4591eb987a8SPeter Maydell DO_2OP(VRHADD_S, vrhadds)
4601eb987a8SPeter Maydell DO_2OP(VRHADD_U, vrhaddu)
46167ec113bSPeter Maydell /*
46267ec113bSPeter Maydell  * VCADD Qd == Qm at size MO_32 is UNPREDICTABLE; we choose not to diagnose
46367ec113bSPeter Maydell  * so we can reuse the DO_2OP macro. (Our implementation calculates the
4648625693aSPeter Maydell  * "expected" results in this case.) Similarly for VHCADD.
46567ec113bSPeter Maydell  */
46667ec113bSPeter Maydell DO_2OP(VCADD90, vcadd90)
46767ec113bSPeter Maydell DO_2OP(VCADD270, vcadd270)
4688625693aSPeter Maydell DO_2OP(VHCADD90, vhcadd90)
4698625693aSPeter Maydell DO_2OP(VHCADD270, vhcadd270)
4701d2386f7SPeter Maydell 
47143364321SPeter Maydell static bool trans_VQDMULLB(DisasContext *s, arg_2op *a)
47243364321SPeter Maydell {
47343364321SPeter Maydell     static MVEGenTwoOpFn * const fns[] = {
47443364321SPeter Maydell         NULL,
47543364321SPeter Maydell         gen_helper_mve_vqdmullbh,
47643364321SPeter Maydell         gen_helper_mve_vqdmullbw,
47743364321SPeter Maydell         NULL,
47843364321SPeter Maydell     };
47943364321SPeter Maydell     if (a->size == MO_32 && (a->qd == a->qm || a->qd == a->qn)) {
48043364321SPeter Maydell         /* UNPREDICTABLE; we choose to undef */
48143364321SPeter Maydell         return false;
48243364321SPeter Maydell     }
48343364321SPeter Maydell     return do_2op(s, a, fns[a->size]);
48443364321SPeter Maydell }
48543364321SPeter Maydell 
48643364321SPeter Maydell static bool trans_VQDMULLT(DisasContext *s, arg_2op *a)
48743364321SPeter Maydell {
48843364321SPeter Maydell     static MVEGenTwoOpFn * const fns[] = {
48943364321SPeter Maydell         NULL,
49043364321SPeter Maydell         gen_helper_mve_vqdmullth,
49143364321SPeter Maydell         gen_helper_mve_vqdmulltw,
49243364321SPeter Maydell         NULL,
49343364321SPeter Maydell     };
49443364321SPeter Maydell     if (a->size == MO_32 && (a->qd == a->qm || a->qd == a->qn)) {
49543364321SPeter Maydell         /* UNPREDICTABLE; we choose to undef */
49643364321SPeter Maydell         return false;
49743364321SPeter Maydell     }
49843364321SPeter Maydell     return do_2op(s, a, fns[a->size]);
49943364321SPeter Maydell }
50043364321SPeter Maydell 
501c1bd78cbSPeter Maydell static bool trans_VMULLP_B(DisasContext *s, arg_2op *a)
502c1bd78cbSPeter Maydell {
503c1bd78cbSPeter Maydell     /*
504c1bd78cbSPeter Maydell      * Note that a->size indicates the output size, ie VMULL.P8
505c1bd78cbSPeter Maydell      * is the 8x8->16 operation and a->size is MO_16; VMULL.P16
506c1bd78cbSPeter Maydell      * is the 16x16->32 operation and a->size is MO_32.
507c1bd78cbSPeter Maydell      */
508c1bd78cbSPeter Maydell     static MVEGenTwoOpFn * const fns[] = {
509c1bd78cbSPeter Maydell         NULL,
510c1bd78cbSPeter Maydell         gen_helper_mve_vmullpbh,
511c1bd78cbSPeter Maydell         gen_helper_mve_vmullpbw,
512c1bd78cbSPeter Maydell         NULL,
513c1bd78cbSPeter Maydell     };
514c1bd78cbSPeter Maydell     return do_2op(s, a, fns[a->size]);
515c1bd78cbSPeter Maydell }
516c1bd78cbSPeter Maydell 
517c1bd78cbSPeter Maydell static bool trans_VMULLP_T(DisasContext *s, arg_2op *a)
518c1bd78cbSPeter Maydell {
519c1bd78cbSPeter Maydell     /* a->size is as for trans_VMULLP_B */
520c1bd78cbSPeter Maydell     static MVEGenTwoOpFn * const fns[] = {
521c1bd78cbSPeter Maydell         NULL,
522c1bd78cbSPeter Maydell         gen_helper_mve_vmullpth,
523c1bd78cbSPeter Maydell         gen_helper_mve_vmullptw,
524c1bd78cbSPeter Maydell         NULL,
525c1bd78cbSPeter Maydell     };
526c1bd78cbSPeter Maydell     return do_2op(s, a, fns[a->size]);
527c1bd78cbSPeter Maydell }
528c1bd78cbSPeter Maydell 
52989bc4c4fSPeter Maydell /*
53089bc4c4fSPeter Maydell  * VADC and VSBC: these perform an add-with-carry or subtract-with-carry
53189bc4c4fSPeter Maydell  * of the 32-bit elements in each lane of the input vectors, where the
53289bc4c4fSPeter Maydell  * carry-out of each add is the carry-in of the next.  The initial carry
53389bc4c4fSPeter Maydell  * input is either fixed (0 for VADCI, 1 for VSBCI) or is from FPSCR.C
53489bc4c4fSPeter Maydell  * (for VADC and VSBC); the carry out at the end is written back to FPSCR.C.
53589bc4c4fSPeter Maydell  * These insns are subject to beat-wise execution.  Partial execution
53689bc4c4fSPeter Maydell  * of an I=1 (initial carry input fixed) insn which does not
53789bc4c4fSPeter Maydell  * execute the first beat must start with the current FPSCR.NZCV
53889bc4c4fSPeter Maydell  * value, not the fixed constant input.
53989bc4c4fSPeter Maydell  */
54089bc4c4fSPeter Maydell static bool trans_VADC(DisasContext *s, arg_2op *a)
54189bc4c4fSPeter Maydell {
54289bc4c4fSPeter Maydell     return do_2op(s, a, gen_helper_mve_vadc);
54389bc4c4fSPeter Maydell }
54489bc4c4fSPeter Maydell 
54589bc4c4fSPeter Maydell static bool trans_VADCI(DisasContext *s, arg_2op *a)
54689bc4c4fSPeter Maydell {
54789bc4c4fSPeter Maydell     if (mve_skip_first_beat(s)) {
54889bc4c4fSPeter Maydell         return trans_VADC(s, a);
54989bc4c4fSPeter Maydell     }
55089bc4c4fSPeter Maydell     return do_2op(s, a, gen_helper_mve_vadci);
55189bc4c4fSPeter Maydell }
55289bc4c4fSPeter Maydell 
55389bc4c4fSPeter Maydell static bool trans_VSBC(DisasContext *s, arg_2op *a)
55489bc4c4fSPeter Maydell {
55589bc4c4fSPeter Maydell     return do_2op(s, a, gen_helper_mve_vsbc);
55689bc4c4fSPeter Maydell }
55789bc4c4fSPeter Maydell 
55889bc4c4fSPeter Maydell static bool trans_VSBCI(DisasContext *s, arg_2op *a)
55989bc4c4fSPeter Maydell {
56089bc4c4fSPeter Maydell     if (mve_skip_first_beat(s)) {
56189bc4c4fSPeter Maydell         return trans_VSBC(s, a);
56289bc4c4fSPeter Maydell     }
56389bc4c4fSPeter Maydell     return do_2op(s, a, gen_helper_mve_vsbci);
56489bc4c4fSPeter Maydell }
56589bc4c4fSPeter Maydell 
566e51896b3SPeter Maydell static bool do_2op_scalar(DisasContext *s, arg_2scalar *a,
567e51896b3SPeter Maydell                           MVEGenTwoOpScalarFn fn)
568e51896b3SPeter Maydell {
569e51896b3SPeter Maydell     TCGv_ptr qd, qn;
570e51896b3SPeter Maydell     TCGv_i32 rm;
571e51896b3SPeter Maydell 
572e51896b3SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
573e51896b3SPeter Maydell         !mve_check_qreg_bank(s, a->qd | a->qn) ||
574e51896b3SPeter Maydell         !fn) {
575e51896b3SPeter Maydell         return false;
576e51896b3SPeter Maydell     }
577e51896b3SPeter Maydell     if (a->rm == 13 || a->rm == 15) {
578e51896b3SPeter Maydell         /* UNPREDICTABLE */
579e51896b3SPeter Maydell         return false;
580e51896b3SPeter Maydell     }
581e51896b3SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
582e51896b3SPeter Maydell         return true;
583e51896b3SPeter Maydell     }
584e51896b3SPeter Maydell 
585e51896b3SPeter Maydell     qd = mve_qreg_ptr(a->qd);
586e51896b3SPeter Maydell     qn = mve_qreg_ptr(a->qn);
587e51896b3SPeter Maydell     rm = load_reg(s, a->rm);
588e51896b3SPeter Maydell     fn(cpu_env, qd, qn, rm);
589e51896b3SPeter Maydell     tcg_temp_free_i32(rm);
590e51896b3SPeter Maydell     tcg_temp_free_ptr(qd);
591e51896b3SPeter Maydell     tcg_temp_free_ptr(qn);
592e51896b3SPeter Maydell     mve_update_eci(s);
593e51896b3SPeter Maydell     return true;
594e51896b3SPeter Maydell }
595e51896b3SPeter Maydell 
596e51896b3SPeter Maydell #define DO_2OP_SCALAR(INSN, FN) \
597e51896b3SPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_2scalar *a)   \
598e51896b3SPeter Maydell     {                                                           \
599e51896b3SPeter Maydell         static MVEGenTwoOpScalarFn * const fns[] = {            \
600e51896b3SPeter Maydell             gen_helper_mve_##FN##b,                             \
601e51896b3SPeter Maydell             gen_helper_mve_##FN##h,                             \
602e51896b3SPeter Maydell             gen_helper_mve_##FN##w,                             \
603e51896b3SPeter Maydell             NULL,                                               \
604e51896b3SPeter Maydell         };                                                      \
605e51896b3SPeter Maydell         return do_2op_scalar(s, a, fns[a->size]);               \
606e51896b3SPeter Maydell     }
607e51896b3SPeter Maydell 
608e51896b3SPeter Maydell DO_2OP_SCALAR(VADD_scalar, vadd_scalar)
60991a358fdSPeter Maydell DO_2OP_SCALAR(VSUB_scalar, vsub_scalar)
61091a358fdSPeter Maydell DO_2OP_SCALAR(VMUL_scalar, vmul_scalar)
611644f717cSPeter Maydell DO_2OP_SCALAR(VHADD_S_scalar, vhadds_scalar)
612644f717cSPeter Maydell DO_2OP_SCALAR(VHADD_U_scalar, vhaddu_scalar)
613644f717cSPeter Maydell DO_2OP_SCALAR(VHSUB_S_scalar, vhsubs_scalar)
614644f717cSPeter Maydell DO_2OP_SCALAR(VHSUB_U_scalar, vhsubu_scalar)
61539f2ec85SPeter Maydell DO_2OP_SCALAR(VQADD_S_scalar, vqadds_scalar)
61639f2ec85SPeter Maydell DO_2OP_SCALAR(VQADD_U_scalar, vqaddu_scalar)
61739f2ec85SPeter Maydell DO_2OP_SCALAR(VQSUB_S_scalar, vqsubs_scalar)
61839f2ec85SPeter Maydell DO_2OP_SCALAR(VQSUB_U_scalar, vqsubu_scalar)
61966c05767SPeter Maydell DO_2OP_SCALAR(VQDMULH_scalar, vqdmulh_scalar)
62066c05767SPeter Maydell DO_2OP_SCALAR(VQRDMULH_scalar, vqrdmulh_scalar)
621b050543bSPeter Maydell DO_2OP_SCALAR(VBRSR, vbrsr)
6226b895bf8SPeter Maydell DO_2OP_SCALAR(VMLAS, vmlas)
623e51896b3SPeter Maydell 
624a8890353SPeter Maydell static bool trans_VQDMULLB_scalar(DisasContext *s, arg_2scalar *a)
625a8890353SPeter Maydell {
626a8890353SPeter Maydell     static MVEGenTwoOpScalarFn * const fns[] = {
627a8890353SPeter Maydell         NULL,
628a8890353SPeter Maydell         gen_helper_mve_vqdmullb_scalarh,
629a8890353SPeter Maydell         gen_helper_mve_vqdmullb_scalarw,
630a8890353SPeter Maydell         NULL,
631a8890353SPeter Maydell     };
632a8890353SPeter Maydell     if (a->qd == a->qn && a->size == MO_32) {
633a8890353SPeter Maydell         /* UNPREDICTABLE; we choose to undef */
634a8890353SPeter Maydell         return false;
635a8890353SPeter Maydell     }
636a8890353SPeter Maydell     return do_2op_scalar(s, a, fns[a->size]);
637a8890353SPeter Maydell }
638a8890353SPeter Maydell 
639a8890353SPeter Maydell static bool trans_VQDMULLT_scalar(DisasContext *s, arg_2scalar *a)
640a8890353SPeter Maydell {
641a8890353SPeter Maydell     static MVEGenTwoOpScalarFn * const fns[] = {
642a8890353SPeter Maydell         NULL,
643a8890353SPeter Maydell         gen_helper_mve_vqdmullt_scalarh,
644a8890353SPeter Maydell         gen_helper_mve_vqdmullt_scalarw,
645a8890353SPeter Maydell         NULL,
646a8890353SPeter Maydell     };
647a8890353SPeter Maydell     if (a->qd == a->qn && a->size == MO_32) {
648a8890353SPeter Maydell         /* UNPREDICTABLE; we choose to undef */
649a8890353SPeter Maydell         return false;
650a8890353SPeter Maydell     }
651a8890353SPeter Maydell     return do_2op_scalar(s, a, fns[a->size]);
652a8890353SPeter Maydell }
653a8890353SPeter Maydell 
6541d2386f7SPeter Maydell static bool do_long_dual_acc(DisasContext *s, arg_vmlaldav *a,
6551d2386f7SPeter Maydell                              MVEGenDualAccOpFn *fn)
6561d2386f7SPeter Maydell {
6571d2386f7SPeter Maydell     TCGv_ptr qn, qm;
6581d2386f7SPeter Maydell     TCGv_i64 rda;
6591d2386f7SPeter Maydell     TCGv_i32 rdalo, rdahi;
6601d2386f7SPeter Maydell 
6611d2386f7SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
6621d2386f7SPeter Maydell         !mve_check_qreg_bank(s, a->qn | a->qm) ||
6631d2386f7SPeter Maydell         !fn) {
6641d2386f7SPeter Maydell         return false;
6651d2386f7SPeter Maydell     }
6661d2386f7SPeter Maydell     /*
6671d2386f7SPeter Maydell      * rdahi == 13 is UNPREDICTABLE; rdahi == 15 is a related
6681d2386f7SPeter Maydell      * encoding; rdalo always has bit 0 clear so cannot be 13 or 15.
6691d2386f7SPeter Maydell      */
6701d2386f7SPeter Maydell     if (a->rdahi == 13 || a->rdahi == 15) {
6711d2386f7SPeter Maydell         return false;
6721d2386f7SPeter Maydell     }
6731d2386f7SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
6741d2386f7SPeter Maydell         return true;
6751d2386f7SPeter Maydell     }
6761d2386f7SPeter Maydell 
6771d2386f7SPeter Maydell     qn = mve_qreg_ptr(a->qn);
6781d2386f7SPeter Maydell     qm = mve_qreg_ptr(a->qm);
6791d2386f7SPeter Maydell 
6801d2386f7SPeter Maydell     /*
6811d2386f7SPeter Maydell      * This insn is subject to beat-wise execution. Partial execution
6821d2386f7SPeter Maydell      * of an A=0 (no-accumulate) insn which does not execute the first
6831d2386f7SPeter Maydell      * beat must start with the current rda value, not 0.
6841d2386f7SPeter Maydell      */
6851d2386f7SPeter Maydell     if (a->a || mve_skip_first_beat(s)) {
6861d2386f7SPeter Maydell         rda = tcg_temp_new_i64();
6871d2386f7SPeter Maydell         rdalo = load_reg(s, a->rdalo);
6881d2386f7SPeter Maydell         rdahi = load_reg(s, a->rdahi);
6891d2386f7SPeter Maydell         tcg_gen_concat_i32_i64(rda, rdalo, rdahi);
6901d2386f7SPeter Maydell         tcg_temp_free_i32(rdalo);
6911d2386f7SPeter Maydell         tcg_temp_free_i32(rdahi);
6921d2386f7SPeter Maydell     } else {
6931d2386f7SPeter Maydell         rda = tcg_const_i64(0);
6941d2386f7SPeter Maydell     }
6951d2386f7SPeter Maydell 
6961d2386f7SPeter Maydell     fn(rda, cpu_env, qn, qm, rda);
6971d2386f7SPeter Maydell     tcg_temp_free_ptr(qn);
6981d2386f7SPeter Maydell     tcg_temp_free_ptr(qm);
6991d2386f7SPeter Maydell 
7001d2386f7SPeter Maydell     rdalo = tcg_temp_new_i32();
7011d2386f7SPeter Maydell     rdahi = tcg_temp_new_i32();
7021d2386f7SPeter Maydell     tcg_gen_extrl_i64_i32(rdalo, rda);
7031d2386f7SPeter Maydell     tcg_gen_extrh_i64_i32(rdahi, rda);
7041d2386f7SPeter Maydell     store_reg(s, a->rdalo, rdalo);
7051d2386f7SPeter Maydell     store_reg(s, a->rdahi, rdahi);
7061d2386f7SPeter Maydell     tcg_temp_free_i64(rda);
7071d2386f7SPeter Maydell     mve_update_eci(s);
7081d2386f7SPeter Maydell     return true;
7091d2386f7SPeter Maydell }
7101d2386f7SPeter Maydell 
7111d2386f7SPeter Maydell static bool trans_VMLALDAV_S(DisasContext *s, arg_vmlaldav *a)
7121d2386f7SPeter Maydell {
7131d2386f7SPeter Maydell     static MVEGenDualAccOpFn * const fns[4][2] = {
7141d2386f7SPeter Maydell         { NULL, NULL },
7151d2386f7SPeter Maydell         { gen_helper_mve_vmlaldavsh, gen_helper_mve_vmlaldavxsh },
7161d2386f7SPeter Maydell         { gen_helper_mve_vmlaldavsw, gen_helper_mve_vmlaldavxsw },
7171d2386f7SPeter Maydell         { NULL, NULL },
7181d2386f7SPeter Maydell     };
7191d2386f7SPeter Maydell     return do_long_dual_acc(s, a, fns[a->size][a->x]);
7201d2386f7SPeter Maydell }
7211d2386f7SPeter Maydell 
7221d2386f7SPeter Maydell static bool trans_VMLALDAV_U(DisasContext *s, arg_vmlaldav *a)
7231d2386f7SPeter Maydell {
7241d2386f7SPeter Maydell     static MVEGenDualAccOpFn * const fns[4][2] = {
7251d2386f7SPeter Maydell         { NULL, NULL },
7261d2386f7SPeter Maydell         { gen_helper_mve_vmlaldavuh, NULL },
7271d2386f7SPeter Maydell         { gen_helper_mve_vmlaldavuw, NULL },
7281d2386f7SPeter Maydell         { NULL, NULL },
7291d2386f7SPeter Maydell     };
7301d2386f7SPeter Maydell     return do_long_dual_acc(s, a, fns[a->size][a->x]);
7311d2386f7SPeter Maydell }
732181cd971SPeter Maydell 
733181cd971SPeter Maydell static bool trans_VMLSLDAV(DisasContext *s, arg_vmlaldav *a)
734181cd971SPeter Maydell {
735181cd971SPeter Maydell     static MVEGenDualAccOpFn * const fns[4][2] = {
736181cd971SPeter Maydell         { NULL, NULL },
737181cd971SPeter Maydell         { gen_helper_mve_vmlsldavsh, gen_helper_mve_vmlsldavxsh },
738181cd971SPeter Maydell         { gen_helper_mve_vmlsldavsw, gen_helper_mve_vmlsldavxsw },
739181cd971SPeter Maydell         { NULL, NULL },
740181cd971SPeter Maydell     };
741181cd971SPeter Maydell     return do_long_dual_acc(s, a, fns[a->size][a->x]);
742181cd971SPeter Maydell }
74338548747SPeter Maydell 
74438548747SPeter Maydell static bool trans_VRMLALDAVH_S(DisasContext *s, arg_vmlaldav *a)
74538548747SPeter Maydell {
74638548747SPeter Maydell     static MVEGenDualAccOpFn * const fns[] = {
74738548747SPeter Maydell         gen_helper_mve_vrmlaldavhsw, gen_helper_mve_vrmlaldavhxsw,
74838548747SPeter Maydell     };
74938548747SPeter Maydell     return do_long_dual_acc(s, a, fns[a->x]);
75038548747SPeter Maydell }
75138548747SPeter Maydell 
75238548747SPeter Maydell static bool trans_VRMLALDAVH_U(DisasContext *s, arg_vmlaldav *a)
75338548747SPeter Maydell {
75438548747SPeter Maydell     static MVEGenDualAccOpFn * const fns[] = {
75538548747SPeter Maydell         gen_helper_mve_vrmlaldavhuw, NULL,
75638548747SPeter Maydell     };
75738548747SPeter Maydell     return do_long_dual_acc(s, a, fns[a->x]);
75838548747SPeter Maydell }
75938548747SPeter Maydell 
76038548747SPeter Maydell static bool trans_VRMLSLDAVH(DisasContext *s, arg_vmlaldav *a)
76138548747SPeter Maydell {
76238548747SPeter Maydell     static MVEGenDualAccOpFn * const fns[] = {
76338548747SPeter Maydell         gen_helper_mve_vrmlsldavhsw, gen_helper_mve_vrmlsldavhxsw,
76438548747SPeter Maydell     };
76538548747SPeter Maydell     return do_long_dual_acc(s, a, fns[a->x]);
76638548747SPeter Maydell }
767387debdbSPeter Maydell 
76855251786SPeter Maydell static void gen_vpst(DisasContext *s, uint32_t mask)
769387debdbSPeter Maydell {
770387debdbSPeter Maydell     /*
771387debdbSPeter Maydell      * Set the VPR mask fields. We take advantage of MASK01 and MASK23
772387debdbSPeter Maydell      * being adjacent fields in the register.
773387debdbSPeter Maydell      *
77455251786SPeter Maydell      * Updating the masks is not predicated, but it is subject to beat-wise
775387debdbSPeter Maydell      * execution, and the mask is updated on the odd-numbered beats.
776387debdbSPeter Maydell      * So if PSR.ECI says we should skip beat 1, we mustn't update the
777387debdbSPeter Maydell      * 01 mask field.
778387debdbSPeter Maydell      */
77955251786SPeter Maydell     TCGv_i32 vpr = load_cpu_field(v7m.vpr);
780387debdbSPeter Maydell     switch (s->eci) {
781387debdbSPeter Maydell     case ECI_NONE:
782387debdbSPeter Maydell     case ECI_A0:
783387debdbSPeter Maydell         /* Update both 01 and 23 fields */
784387debdbSPeter Maydell         tcg_gen_deposit_i32(vpr, vpr,
78555251786SPeter Maydell                             tcg_constant_i32(mask | (mask << 4)),
786387debdbSPeter Maydell                             R_V7M_VPR_MASK01_SHIFT,
787387debdbSPeter Maydell                             R_V7M_VPR_MASK01_LENGTH + R_V7M_VPR_MASK23_LENGTH);
788387debdbSPeter Maydell         break;
789387debdbSPeter Maydell     case ECI_A0A1:
790387debdbSPeter Maydell     case ECI_A0A1A2:
791387debdbSPeter Maydell     case ECI_A0A1A2B0:
792387debdbSPeter Maydell         /* Update only the 23 mask field */
793387debdbSPeter Maydell         tcg_gen_deposit_i32(vpr, vpr,
79455251786SPeter Maydell                             tcg_constant_i32(mask),
795387debdbSPeter Maydell                             R_V7M_VPR_MASK23_SHIFT, R_V7M_VPR_MASK23_LENGTH);
796387debdbSPeter Maydell         break;
797387debdbSPeter Maydell     default:
798387debdbSPeter Maydell         g_assert_not_reached();
799387debdbSPeter Maydell     }
800387debdbSPeter Maydell     store_cpu_field(vpr, v7m.vpr);
80155251786SPeter Maydell }
80255251786SPeter Maydell 
80355251786SPeter Maydell static bool trans_VPST(DisasContext *s, arg_VPST *a)
80455251786SPeter Maydell {
80555251786SPeter Maydell     /* mask == 0 is a "related encoding" */
80655251786SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) || !a->mask) {
80755251786SPeter Maydell         return false;
80855251786SPeter Maydell     }
80955251786SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
81055251786SPeter Maydell         return true;
81155251786SPeter Maydell     }
81255251786SPeter Maydell     gen_vpst(s, a->mask);
813387debdbSPeter Maydell     mve_update_and_store_eci(s);
814387debdbSPeter Maydell     return true;
815387debdbSPeter Maydell }
8166f060a63SPeter Maydell 
8176f060a63SPeter Maydell static bool trans_VADDV(DisasContext *s, arg_VADDV *a)
8186f060a63SPeter Maydell {
8196f060a63SPeter Maydell     /* VADDV: vector add across vector */
8206f060a63SPeter Maydell     static MVEGenVADDVFn * const fns[4][2] = {
8216f060a63SPeter Maydell         { gen_helper_mve_vaddvsb, gen_helper_mve_vaddvub },
8226f060a63SPeter Maydell         { gen_helper_mve_vaddvsh, gen_helper_mve_vaddvuh },
8236f060a63SPeter Maydell         { gen_helper_mve_vaddvsw, gen_helper_mve_vaddvuw },
8246f060a63SPeter Maydell         { NULL, NULL }
8256f060a63SPeter Maydell     };
8266f060a63SPeter Maydell     TCGv_ptr qm;
8276f060a63SPeter Maydell     TCGv_i32 rda;
8286f060a63SPeter Maydell 
8296f060a63SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
8306f060a63SPeter Maydell         a->size == 3) {
8316f060a63SPeter Maydell         return false;
8326f060a63SPeter Maydell     }
8336f060a63SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
8346f060a63SPeter Maydell         return true;
8356f060a63SPeter Maydell     }
8366f060a63SPeter Maydell 
8376f060a63SPeter Maydell     /*
8386f060a63SPeter Maydell      * This insn is subject to beat-wise execution. Partial execution
8396f060a63SPeter Maydell      * of an A=0 (no-accumulate) insn which does not execute the first
8406f060a63SPeter Maydell      * beat must start with the current value of Rda, not zero.
8416f060a63SPeter Maydell      */
8426f060a63SPeter Maydell     if (a->a || mve_skip_first_beat(s)) {
8436f060a63SPeter Maydell         /* Accumulate input from Rda */
8446f060a63SPeter Maydell         rda = load_reg(s, a->rda);
8456f060a63SPeter Maydell     } else {
8466f060a63SPeter Maydell         /* Accumulate starting at zero */
8476f060a63SPeter Maydell         rda = tcg_const_i32(0);
8486f060a63SPeter Maydell     }
8496f060a63SPeter Maydell 
8506f060a63SPeter Maydell     qm = mve_qreg_ptr(a->qm);
8516f060a63SPeter Maydell     fns[a->size][a->u](rda, cpu_env, qm, rda);
8526f060a63SPeter Maydell     store_reg(s, a->rda, rda);
8536f060a63SPeter Maydell     tcg_temp_free_ptr(qm);
8546f060a63SPeter Maydell 
8556f060a63SPeter Maydell     mve_update_eci(s);
8566f060a63SPeter Maydell     return true;
8576f060a63SPeter Maydell }
858eab84139SPeter Maydell 
859d43ebd9dSPeter Maydell static bool trans_VADDLV(DisasContext *s, arg_VADDLV *a)
860d43ebd9dSPeter Maydell {
861d43ebd9dSPeter Maydell     /*
862d43ebd9dSPeter Maydell      * Vector Add Long Across Vector: accumulate the 32-bit
863d43ebd9dSPeter Maydell      * elements of the vector into a 64-bit result stored in
864d43ebd9dSPeter Maydell      * a pair of general-purpose registers.
865d43ebd9dSPeter Maydell      * No need to check Qm's bank: it is only 3 bits in decode.
866d43ebd9dSPeter Maydell      */
867d43ebd9dSPeter Maydell     TCGv_ptr qm;
868d43ebd9dSPeter Maydell     TCGv_i64 rda;
869d43ebd9dSPeter Maydell     TCGv_i32 rdalo, rdahi;
870d43ebd9dSPeter Maydell 
871d43ebd9dSPeter Maydell     if (!dc_isar_feature(aa32_mve, s)) {
872d43ebd9dSPeter Maydell         return false;
873d43ebd9dSPeter Maydell     }
874d43ebd9dSPeter Maydell     /*
875d43ebd9dSPeter Maydell      * rdahi == 13 is UNPREDICTABLE; rdahi == 15 is a related
876d43ebd9dSPeter Maydell      * encoding; rdalo always has bit 0 clear so cannot be 13 or 15.
877d43ebd9dSPeter Maydell      */
878d43ebd9dSPeter Maydell     if (a->rdahi == 13 || a->rdahi == 15) {
879d43ebd9dSPeter Maydell         return false;
880d43ebd9dSPeter Maydell     }
881d43ebd9dSPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
882d43ebd9dSPeter Maydell         return true;
883d43ebd9dSPeter Maydell     }
884d43ebd9dSPeter Maydell 
885d43ebd9dSPeter Maydell     /*
886d43ebd9dSPeter Maydell      * This insn is subject to beat-wise execution. Partial execution
887d43ebd9dSPeter Maydell      * of an A=0 (no-accumulate) insn which does not execute the first
888d43ebd9dSPeter Maydell      * beat must start with the current value of RdaHi:RdaLo, not zero.
889d43ebd9dSPeter Maydell      */
890d43ebd9dSPeter Maydell     if (a->a || mve_skip_first_beat(s)) {
891d43ebd9dSPeter Maydell         /* Accumulate input from RdaHi:RdaLo */
892d43ebd9dSPeter Maydell         rda = tcg_temp_new_i64();
893d43ebd9dSPeter Maydell         rdalo = load_reg(s, a->rdalo);
894d43ebd9dSPeter Maydell         rdahi = load_reg(s, a->rdahi);
895d43ebd9dSPeter Maydell         tcg_gen_concat_i32_i64(rda, rdalo, rdahi);
896d43ebd9dSPeter Maydell         tcg_temp_free_i32(rdalo);
897d43ebd9dSPeter Maydell         tcg_temp_free_i32(rdahi);
898d43ebd9dSPeter Maydell     } else {
899d43ebd9dSPeter Maydell         /* Accumulate starting at zero */
900d43ebd9dSPeter Maydell         rda = tcg_const_i64(0);
901d43ebd9dSPeter Maydell     }
902d43ebd9dSPeter Maydell 
903d43ebd9dSPeter Maydell     qm = mve_qreg_ptr(a->qm);
904d43ebd9dSPeter Maydell     if (a->u) {
905d43ebd9dSPeter Maydell         gen_helper_mve_vaddlv_u(rda, cpu_env, qm, rda);
906d43ebd9dSPeter Maydell     } else {
907d43ebd9dSPeter Maydell         gen_helper_mve_vaddlv_s(rda, cpu_env, qm, rda);
908d43ebd9dSPeter Maydell     }
909d43ebd9dSPeter Maydell     tcg_temp_free_ptr(qm);
910d43ebd9dSPeter Maydell 
911d43ebd9dSPeter Maydell     rdalo = tcg_temp_new_i32();
912d43ebd9dSPeter Maydell     rdahi = tcg_temp_new_i32();
913d43ebd9dSPeter Maydell     tcg_gen_extrl_i64_i32(rdalo, rda);
914d43ebd9dSPeter Maydell     tcg_gen_extrh_i64_i32(rdahi, rda);
915d43ebd9dSPeter Maydell     store_reg(s, a->rdalo, rdalo);
916d43ebd9dSPeter Maydell     store_reg(s, a->rdahi, rdahi);
917d43ebd9dSPeter Maydell     tcg_temp_free_i64(rda);
918d43ebd9dSPeter Maydell     mve_update_eci(s);
919d43ebd9dSPeter Maydell     return true;
920d43ebd9dSPeter Maydell }
921d43ebd9dSPeter Maydell 
922eab84139SPeter Maydell static bool do_1imm(DisasContext *s, arg_1imm *a, MVEGenOneOpImmFn *fn)
923eab84139SPeter Maydell {
924eab84139SPeter Maydell     TCGv_ptr qd;
925eab84139SPeter Maydell     uint64_t imm;
926eab84139SPeter Maydell 
927eab84139SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
928eab84139SPeter Maydell         !mve_check_qreg_bank(s, a->qd) ||
929eab84139SPeter Maydell         !fn) {
930eab84139SPeter Maydell         return false;
931eab84139SPeter Maydell     }
932eab84139SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
933eab84139SPeter Maydell         return true;
934eab84139SPeter Maydell     }
935eab84139SPeter Maydell 
936eab84139SPeter Maydell     imm = asimd_imm_const(a->imm, a->cmode, a->op);
937eab84139SPeter Maydell 
938eab84139SPeter Maydell     qd = mve_qreg_ptr(a->qd);
939eab84139SPeter Maydell     fn(cpu_env, qd, tcg_constant_i64(imm));
940eab84139SPeter Maydell     tcg_temp_free_ptr(qd);
941eab84139SPeter Maydell     mve_update_eci(s);
942eab84139SPeter Maydell     return true;
943eab84139SPeter Maydell }
944eab84139SPeter Maydell 
945eab84139SPeter Maydell static bool trans_Vimm_1r(DisasContext *s, arg_1imm *a)
946eab84139SPeter Maydell {
947eab84139SPeter Maydell     /* Handle decode of cmode/op here between VORR/VBIC/VMOV */
948eab84139SPeter Maydell     MVEGenOneOpImmFn *fn;
949eab84139SPeter Maydell 
950eab84139SPeter Maydell     if ((a->cmode & 1) && a->cmode < 12) {
951eab84139SPeter Maydell         if (a->op) {
952eab84139SPeter Maydell             /*
953eab84139SPeter Maydell              * For op=1, the immediate will be inverted by asimd_imm_const(),
954eab84139SPeter Maydell              * so the VBIC becomes a logical AND operation.
955eab84139SPeter Maydell              */
956eab84139SPeter Maydell             fn = gen_helper_mve_vandi;
957eab84139SPeter Maydell         } else {
958eab84139SPeter Maydell             fn = gen_helper_mve_vorri;
959eab84139SPeter Maydell         }
960eab84139SPeter Maydell     } else {
961eab84139SPeter Maydell         /* There is one unallocated cmode/op combination in this space */
962eab84139SPeter Maydell         if (a->cmode == 15 && a->op == 1) {
963eab84139SPeter Maydell             return false;
964eab84139SPeter Maydell         }
965eab84139SPeter Maydell         /* asimd_imm_const() sorts out VMVNI vs VMOVI for us */
966eab84139SPeter Maydell         fn = gen_helper_mve_vmovi;
967eab84139SPeter Maydell     }
968eab84139SPeter Maydell     return do_1imm(s, a, fn);
969eab84139SPeter Maydell }
970f9ed6174SPeter Maydell 
971f9ed6174SPeter Maydell static bool do_2shift(DisasContext *s, arg_2shift *a, MVEGenTwoOpShiftFn fn,
972f9ed6174SPeter Maydell                       bool negateshift)
973f9ed6174SPeter Maydell {
974f9ed6174SPeter Maydell     TCGv_ptr qd, qm;
975f9ed6174SPeter Maydell     int shift = a->shift;
976f9ed6174SPeter Maydell 
977f9ed6174SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
978f9ed6174SPeter Maydell         !mve_check_qreg_bank(s, a->qd | a->qm) ||
979f9ed6174SPeter Maydell         !fn) {
980f9ed6174SPeter Maydell         return false;
981f9ed6174SPeter Maydell     }
982f9ed6174SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
983f9ed6174SPeter Maydell         return true;
984f9ed6174SPeter Maydell     }
985f9ed6174SPeter Maydell 
986f9ed6174SPeter Maydell     /*
987f9ed6174SPeter Maydell      * When we handle a right shift insn using a left-shift helper
988f9ed6174SPeter Maydell      * which permits a negative shift count to indicate a right-shift,
989f9ed6174SPeter Maydell      * we must negate the shift count.
990f9ed6174SPeter Maydell      */
991f9ed6174SPeter Maydell     if (negateshift) {
992f9ed6174SPeter Maydell         shift = -shift;
993f9ed6174SPeter Maydell     }
994f9ed6174SPeter Maydell 
995f9ed6174SPeter Maydell     qd = mve_qreg_ptr(a->qd);
996f9ed6174SPeter Maydell     qm = mve_qreg_ptr(a->qm);
997f9ed6174SPeter Maydell     fn(cpu_env, qd, qm, tcg_constant_i32(shift));
998f9ed6174SPeter Maydell     tcg_temp_free_ptr(qd);
999f9ed6174SPeter Maydell     tcg_temp_free_ptr(qm);
1000f9ed6174SPeter Maydell     mve_update_eci(s);
1001f9ed6174SPeter Maydell     return true;
1002f9ed6174SPeter Maydell }
1003f9ed6174SPeter Maydell 
1004f9ed6174SPeter Maydell #define DO_2SHIFT(INSN, FN, NEGATESHIFT)                         \
1005f9ed6174SPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_2shift *a)    \
1006f9ed6174SPeter Maydell     {                                                           \
1007f9ed6174SPeter Maydell         static MVEGenTwoOpShiftFn * const fns[] = {             \
1008f9ed6174SPeter Maydell             gen_helper_mve_##FN##b,                             \
1009f9ed6174SPeter Maydell             gen_helper_mve_##FN##h,                             \
1010f9ed6174SPeter Maydell             gen_helper_mve_##FN##w,                             \
1011f9ed6174SPeter Maydell             NULL,                                               \
1012f9ed6174SPeter Maydell         };                                                      \
1013f9ed6174SPeter Maydell         return do_2shift(s, a, fns[a->size], NEGATESHIFT);      \
1014f9ed6174SPeter Maydell     }
1015f9ed6174SPeter Maydell 
1016f9ed6174SPeter Maydell DO_2SHIFT(VSHLI, vshli_u, false)
1017f9ed6174SPeter Maydell DO_2SHIFT(VQSHLI_S, vqshli_s, false)
1018f9ed6174SPeter Maydell DO_2SHIFT(VQSHLI_U, vqshli_u, false)
1019f9ed6174SPeter Maydell DO_2SHIFT(VQSHLUI, vqshlui_s, false)
10203394116fSPeter Maydell /* These right shifts use a left-shift helper with negated shift count */
10213394116fSPeter Maydell DO_2SHIFT(VSHRI_S, vshli_s, true)
10223394116fSPeter Maydell DO_2SHIFT(VSHRI_U, vshli_u, true)
10233394116fSPeter Maydell DO_2SHIFT(VRSHRI_S, vrshli_s, true)
10243394116fSPeter Maydell DO_2SHIFT(VRSHRI_U, vrshli_u, true)
1025c2262707SPeter Maydell 
1026a78b25faSPeter Maydell DO_2SHIFT(VSRI, vsri, false)
1027a78b25faSPeter Maydell DO_2SHIFT(VSLI, vsli, false)
1028a78b25faSPeter Maydell 
10291b15a97dSPeter Maydell static bool do_2shift_scalar(DisasContext *s, arg_shl_scalar *a,
10301b15a97dSPeter Maydell                              MVEGenTwoOpShiftFn *fn)
10311b15a97dSPeter Maydell {
10321b15a97dSPeter Maydell     TCGv_ptr qda;
10331b15a97dSPeter Maydell     TCGv_i32 rm;
10341b15a97dSPeter Maydell 
10351b15a97dSPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
10361b15a97dSPeter Maydell         !mve_check_qreg_bank(s, a->qda) ||
10371b15a97dSPeter Maydell         a->rm == 13 || a->rm == 15 || !fn) {
10381b15a97dSPeter Maydell         /* Rm cases are UNPREDICTABLE */
10391b15a97dSPeter Maydell         return false;
10401b15a97dSPeter Maydell     }
10411b15a97dSPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
10421b15a97dSPeter Maydell         return true;
10431b15a97dSPeter Maydell     }
10441b15a97dSPeter Maydell 
10451b15a97dSPeter Maydell     qda = mve_qreg_ptr(a->qda);
10461b15a97dSPeter Maydell     rm = load_reg(s, a->rm);
10471b15a97dSPeter Maydell     fn(cpu_env, qda, qda, rm);
10481b15a97dSPeter Maydell     tcg_temp_free_ptr(qda);
10491b15a97dSPeter Maydell     tcg_temp_free_i32(rm);
10501b15a97dSPeter Maydell     mve_update_eci(s);
10511b15a97dSPeter Maydell     return true;
10521b15a97dSPeter Maydell }
10531b15a97dSPeter Maydell 
10541b15a97dSPeter Maydell #define DO_2SHIFT_SCALAR(INSN, FN)                                      \
10551b15a97dSPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_shl_scalar *a)        \
10561b15a97dSPeter Maydell     {                                                                   \
10571b15a97dSPeter Maydell         static MVEGenTwoOpShiftFn * const fns[] = {                     \
10581b15a97dSPeter Maydell             gen_helper_mve_##FN##b,                                     \
10591b15a97dSPeter Maydell             gen_helper_mve_##FN##h,                                     \
10601b15a97dSPeter Maydell             gen_helper_mve_##FN##w,                                     \
10611b15a97dSPeter Maydell             NULL,                                                       \
10621b15a97dSPeter Maydell         };                                                              \
10631b15a97dSPeter Maydell         return do_2shift_scalar(s, a, fns[a->size]);                    \
10641b15a97dSPeter Maydell     }
10651b15a97dSPeter Maydell 
10661b15a97dSPeter Maydell DO_2SHIFT_SCALAR(VSHL_S_scalar, vshli_s)
10671b15a97dSPeter Maydell DO_2SHIFT_SCALAR(VSHL_U_scalar, vshli_u)
10681b15a97dSPeter Maydell DO_2SHIFT_SCALAR(VRSHL_S_scalar, vrshli_s)
10691b15a97dSPeter Maydell DO_2SHIFT_SCALAR(VRSHL_U_scalar, vrshli_u)
10701b15a97dSPeter Maydell DO_2SHIFT_SCALAR(VQSHL_S_scalar, vqshli_s)
10711b15a97dSPeter Maydell DO_2SHIFT_SCALAR(VQSHL_U_scalar, vqshli_u)
10721b15a97dSPeter Maydell DO_2SHIFT_SCALAR(VQRSHL_S_scalar, vqrshli_s)
10731b15a97dSPeter Maydell DO_2SHIFT_SCALAR(VQRSHL_U_scalar, vqrshli_u)
10741b15a97dSPeter Maydell 
1075c2262707SPeter Maydell #define DO_VSHLL(INSN, FN)                                      \
1076c2262707SPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_2shift *a)    \
1077c2262707SPeter Maydell     {                                                           \
1078c2262707SPeter Maydell         static MVEGenTwoOpShiftFn * const fns[] = {             \
1079c2262707SPeter Maydell             gen_helper_mve_##FN##b,                             \
1080c2262707SPeter Maydell             gen_helper_mve_##FN##h,                             \
1081c2262707SPeter Maydell         };                                                      \
1082c2262707SPeter Maydell         return do_2shift(s, a, fns[a->size], false);            \
1083c2262707SPeter Maydell     }
1084c2262707SPeter Maydell 
1085c2262707SPeter Maydell DO_VSHLL(VSHLL_BS, vshllbs)
1086c2262707SPeter Maydell DO_VSHLL(VSHLL_BU, vshllbu)
1087c2262707SPeter Maydell DO_VSHLL(VSHLL_TS, vshllts)
1088c2262707SPeter Maydell DO_VSHLL(VSHLL_TU, vshlltu)
1089162e2655SPeter Maydell 
1090162e2655SPeter Maydell #define DO_2SHIFT_N(INSN, FN)                                   \
1091162e2655SPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_2shift *a)    \
1092162e2655SPeter Maydell     {                                                           \
1093162e2655SPeter Maydell         static MVEGenTwoOpShiftFn * const fns[] = {             \
1094162e2655SPeter Maydell             gen_helper_mve_##FN##b,                             \
1095162e2655SPeter Maydell             gen_helper_mve_##FN##h,                             \
1096162e2655SPeter Maydell         };                                                      \
1097162e2655SPeter Maydell         return do_2shift(s, a, fns[a->size], false);            \
1098162e2655SPeter Maydell     }
1099162e2655SPeter Maydell 
1100162e2655SPeter Maydell DO_2SHIFT_N(VSHRNB, vshrnb)
1101162e2655SPeter Maydell DO_2SHIFT_N(VSHRNT, vshrnt)
1102162e2655SPeter Maydell DO_2SHIFT_N(VRSHRNB, vrshrnb)
1103162e2655SPeter Maydell DO_2SHIFT_N(VRSHRNT, vrshrnt)
1104d6f9e011SPeter Maydell DO_2SHIFT_N(VQSHRNB_S, vqshrnb_s)
1105d6f9e011SPeter Maydell DO_2SHIFT_N(VQSHRNT_S, vqshrnt_s)
1106d6f9e011SPeter Maydell DO_2SHIFT_N(VQSHRNB_U, vqshrnb_u)
1107d6f9e011SPeter Maydell DO_2SHIFT_N(VQSHRNT_U, vqshrnt_u)
1108d6f9e011SPeter Maydell DO_2SHIFT_N(VQSHRUNB, vqshrunb)
1109d6f9e011SPeter Maydell DO_2SHIFT_N(VQSHRUNT, vqshrunt)
1110d6f9e011SPeter Maydell DO_2SHIFT_N(VQRSHRNB_S, vqrshrnb_s)
1111d6f9e011SPeter Maydell DO_2SHIFT_N(VQRSHRNT_S, vqrshrnt_s)
1112d6f9e011SPeter Maydell DO_2SHIFT_N(VQRSHRNB_U, vqrshrnb_u)
1113d6f9e011SPeter Maydell DO_2SHIFT_N(VQRSHRNT_U, vqrshrnt_u)
1114d6f9e011SPeter Maydell DO_2SHIFT_N(VQRSHRUNB, vqrshrunb)
1115d6f9e011SPeter Maydell DO_2SHIFT_N(VQRSHRUNT, vqrshrunt)
11162e6a4ce0SPeter Maydell 
11172e6a4ce0SPeter Maydell static bool trans_VSHLC(DisasContext *s, arg_VSHLC *a)
11182e6a4ce0SPeter Maydell {
11192e6a4ce0SPeter Maydell     /*
11202e6a4ce0SPeter Maydell      * Whole Vector Left Shift with Carry. The carry is taken
11212e6a4ce0SPeter Maydell      * from a general purpose register and written back there.
11222e6a4ce0SPeter Maydell      * An imm of 0 means "shift by 32".
11232e6a4ce0SPeter Maydell      */
11242e6a4ce0SPeter Maydell     TCGv_ptr qd;
11252e6a4ce0SPeter Maydell     TCGv_i32 rdm;
11262e6a4ce0SPeter Maydell 
11272e6a4ce0SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd)) {
11282e6a4ce0SPeter Maydell         return false;
11292e6a4ce0SPeter Maydell     }
11302e6a4ce0SPeter Maydell     if (a->rdm == 13 || a->rdm == 15) {
11312e6a4ce0SPeter Maydell         /* CONSTRAINED UNPREDICTABLE: we UNDEF */
11322e6a4ce0SPeter Maydell         return false;
11332e6a4ce0SPeter Maydell     }
11342e6a4ce0SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
11352e6a4ce0SPeter Maydell         return true;
11362e6a4ce0SPeter Maydell     }
11372e6a4ce0SPeter Maydell 
11382e6a4ce0SPeter Maydell     qd = mve_qreg_ptr(a->qd);
11392e6a4ce0SPeter Maydell     rdm = load_reg(s, a->rdm);
11402e6a4ce0SPeter Maydell     gen_helper_mve_vshlc(rdm, cpu_env, qd, rdm, tcg_constant_i32(a->imm));
11412e6a4ce0SPeter Maydell     store_reg(s, a->rdm, rdm);
11422e6a4ce0SPeter Maydell     tcg_temp_free_ptr(qd);
11432e6a4ce0SPeter Maydell     mve_update_eci(s);
11442e6a4ce0SPeter Maydell     return true;
11452e6a4ce0SPeter Maydell }
1146395b92d5SPeter Maydell 
1147395b92d5SPeter Maydell static bool do_vidup(DisasContext *s, arg_vidup *a, MVEGenVIDUPFn *fn)
1148395b92d5SPeter Maydell {
1149395b92d5SPeter Maydell     TCGv_ptr qd;
1150395b92d5SPeter Maydell     TCGv_i32 rn;
1151395b92d5SPeter Maydell 
1152395b92d5SPeter Maydell     /*
1153395b92d5SPeter Maydell      * Vector increment/decrement with wrap and duplicate (VIDUP, VDDUP).
1154395b92d5SPeter Maydell      * This fills the vector with elements of successively increasing
1155395b92d5SPeter Maydell      * or decreasing values, starting from Rn.
1156395b92d5SPeter Maydell      */
1157395b92d5SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd)) {
1158395b92d5SPeter Maydell         return false;
1159395b92d5SPeter Maydell     }
1160395b92d5SPeter Maydell     if (a->size == MO_64) {
1161395b92d5SPeter Maydell         /* size 0b11 is another encoding */
1162395b92d5SPeter Maydell         return false;
1163395b92d5SPeter Maydell     }
1164395b92d5SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
1165395b92d5SPeter Maydell         return true;
1166395b92d5SPeter Maydell     }
1167395b92d5SPeter Maydell 
1168395b92d5SPeter Maydell     qd = mve_qreg_ptr(a->qd);
1169395b92d5SPeter Maydell     rn = load_reg(s, a->rn);
1170395b92d5SPeter Maydell     fn(rn, cpu_env, qd, rn, tcg_constant_i32(a->imm));
1171395b92d5SPeter Maydell     store_reg(s, a->rn, rn);
1172395b92d5SPeter Maydell     tcg_temp_free_ptr(qd);
1173395b92d5SPeter Maydell     mve_update_eci(s);
1174395b92d5SPeter Maydell     return true;
1175395b92d5SPeter Maydell }
1176395b92d5SPeter Maydell 
1177395b92d5SPeter Maydell static bool do_viwdup(DisasContext *s, arg_viwdup *a, MVEGenVIWDUPFn *fn)
1178395b92d5SPeter Maydell {
1179395b92d5SPeter Maydell     TCGv_ptr qd;
1180395b92d5SPeter Maydell     TCGv_i32 rn, rm;
1181395b92d5SPeter Maydell 
1182395b92d5SPeter Maydell     /*
1183395b92d5SPeter Maydell      * Vector increment/decrement with wrap and duplicate (VIWDUp, VDWDUP)
1184395b92d5SPeter Maydell      * This fills the vector with elements of successively increasing
1185395b92d5SPeter Maydell      * or decreasing values, starting from Rn. Rm specifies a point where
1186395b92d5SPeter Maydell      * the count wraps back around to 0. The updated offset is written back
1187395b92d5SPeter Maydell      * to Rn.
1188395b92d5SPeter Maydell      */
1189395b92d5SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qd)) {
1190395b92d5SPeter Maydell         return false;
1191395b92d5SPeter Maydell     }
1192395b92d5SPeter Maydell     if (!fn || a->rm == 13 || a->rm == 15) {
1193395b92d5SPeter Maydell         /*
1194395b92d5SPeter Maydell          * size 0b11 is another encoding; Rm == 13 is UNPREDICTABLE;
1195395b92d5SPeter Maydell          * Rm == 13 is VIWDUP, VDWDUP.
1196395b92d5SPeter Maydell          */
1197395b92d5SPeter Maydell         return false;
1198395b92d5SPeter Maydell     }
1199395b92d5SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
1200395b92d5SPeter Maydell         return true;
1201395b92d5SPeter Maydell     }
1202395b92d5SPeter Maydell 
1203395b92d5SPeter Maydell     qd = mve_qreg_ptr(a->qd);
1204395b92d5SPeter Maydell     rn = load_reg(s, a->rn);
1205395b92d5SPeter Maydell     rm = load_reg(s, a->rm);
1206395b92d5SPeter Maydell     fn(rn, cpu_env, qd, rn, rm, tcg_constant_i32(a->imm));
1207395b92d5SPeter Maydell     store_reg(s, a->rn, rn);
1208395b92d5SPeter Maydell     tcg_temp_free_ptr(qd);
1209395b92d5SPeter Maydell     tcg_temp_free_i32(rm);
1210395b92d5SPeter Maydell     mve_update_eci(s);
1211395b92d5SPeter Maydell     return true;
1212395b92d5SPeter Maydell }
1213395b92d5SPeter Maydell 
1214395b92d5SPeter Maydell static bool trans_VIDUP(DisasContext *s, arg_vidup *a)
1215395b92d5SPeter Maydell {
1216395b92d5SPeter Maydell     static MVEGenVIDUPFn * const fns[] = {
1217395b92d5SPeter Maydell         gen_helper_mve_vidupb,
1218395b92d5SPeter Maydell         gen_helper_mve_viduph,
1219395b92d5SPeter Maydell         gen_helper_mve_vidupw,
1220395b92d5SPeter Maydell         NULL,
1221395b92d5SPeter Maydell     };
1222395b92d5SPeter Maydell     return do_vidup(s, a, fns[a->size]);
1223395b92d5SPeter Maydell }
1224395b92d5SPeter Maydell 
1225395b92d5SPeter Maydell static bool trans_VDDUP(DisasContext *s, arg_vidup *a)
1226395b92d5SPeter Maydell {
1227395b92d5SPeter Maydell     static MVEGenVIDUPFn * const fns[] = {
1228395b92d5SPeter Maydell         gen_helper_mve_vidupb,
1229395b92d5SPeter Maydell         gen_helper_mve_viduph,
1230395b92d5SPeter Maydell         gen_helper_mve_vidupw,
1231395b92d5SPeter Maydell         NULL,
1232395b92d5SPeter Maydell     };
1233395b92d5SPeter Maydell     /* VDDUP is just like VIDUP but with a negative immediate */
1234395b92d5SPeter Maydell     a->imm = -a->imm;
1235395b92d5SPeter Maydell     return do_vidup(s, a, fns[a->size]);
1236395b92d5SPeter Maydell }
1237395b92d5SPeter Maydell 
1238395b92d5SPeter Maydell static bool trans_VIWDUP(DisasContext *s, arg_viwdup *a)
1239395b92d5SPeter Maydell {
1240395b92d5SPeter Maydell     static MVEGenVIWDUPFn * const fns[] = {
1241395b92d5SPeter Maydell         gen_helper_mve_viwdupb,
1242395b92d5SPeter Maydell         gen_helper_mve_viwduph,
1243395b92d5SPeter Maydell         gen_helper_mve_viwdupw,
1244395b92d5SPeter Maydell         NULL,
1245395b92d5SPeter Maydell     };
1246395b92d5SPeter Maydell     return do_viwdup(s, a, fns[a->size]);
1247395b92d5SPeter Maydell }
1248395b92d5SPeter Maydell 
1249395b92d5SPeter Maydell static bool trans_VDWDUP(DisasContext *s, arg_viwdup *a)
1250395b92d5SPeter Maydell {
1251395b92d5SPeter Maydell     static MVEGenVIWDUPFn * const fns[] = {
1252395b92d5SPeter Maydell         gen_helper_mve_vdwdupb,
1253395b92d5SPeter Maydell         gen_helper_mve_vdwduph,
1254395b92d5SPeter Maydell         gen_helper_mve_vdwdupw,
1255395b92d5SPeter Maydell         NULL,
1256395b92d5SPeter Maydell     };
1257395b92d5SPeter Maydell     return do_viwdup(s, a, fns[a->size]);
1258395b92d5SPeter Maydell }
1259eff5d9a9SPeter Maydell 
1260eff5d9a9SPeter Maydell static bool do_vcmp(DisasContext *s, arg_vcmp *a, MVEGenCmpFn *fn)
1261eff5d9a9SPeter Maydell {
1262eff5d9a9SPeter Maydell     TCGv_ptr qn, qm;
1263eff5d9a9SPeter Maydell 
1264eff5d9a9SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qm) ||
1265eff5d9a9SPeter Maydell         !fn) {
1266eff5d9a9SPeter Maydell         return false;
1267eff5d9a9SPeter Maydell     }
1268eff5d9a9SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
1269eff5d9a9SPeter Maydell         return true;
1270eff5d9a9SPeter Maydell     }
1271eff5d9a9SPeter Maydell 
1272eff5d9a9SPeter Maydell     qn = mve_qreg_ptr(a->qn);
1273eff5d9a9SPeter Maydell     qm = mve_qreg_ptr(a->qm);
1274eff5d9a9SPeter Maydell     fn(cpu_env, qn, qm);
1275eff5d9a9SPeter Maydell     tcg_temp_free_ptr(qn);
1276eff5d9a9SPeter Maydell     tcg_temp_free_ptr(qm);
1277eff5d9a9SPeter Maydell     if (a->mask) {
1278eff5d9a9SPeter Maydell         /* VPT */
1279eff5d9a9SPeter Maydell         gen_vpst(s, a->mask);
1280eff5d9a9SPeter Maydell     }
1281eff5d9a9SPeter Maydell     mve_update_eci(s);
1282eff5d9a9SPeter Maydell     return true;
1283eff5d9a9SPeter Maydell }
1284eff5d9a9SPeter Maydell 
1285cce81873SPeter Maydell static bool do_vcmp_scalar(DisasContext *s, arg_vcmp_scalar *a,
1286cce81873SPeter Maydell                            MVEGenScalarCmpFn *fn)
1287cce81873SPeter Maydell {
1288cce81873SPeter Maydell     TCGv_ptr qn;
1289cce81873SPeter Maydell     TCGv_i32 rm;
1290cce81873SPeter Maydell 
1291cce81873SPeter Maydell     if (!dc_isar_feature(aa32_mve, s) || !fn || a->rm == 13) {
1292cce81873SPeter Maydell         return false;
1293cce81873SPeter Maydell     }
1294cce81873SPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
1295cce81873SPeter Maydell         return true;
1296cce81873SPeter Maydell     }
1297cce81873SPeter Maydell 
1298cce81873SPeter Maydell     qn = mve_qreg_ptr(a->qn);
1299cce81873SPeter Maydell     if (a->rm == 15) {
1300cce81873SPeter Maydell         /* Encoding Rm=0b1111 means "constant zero" */
1301cce81873SPeter Maydell         rm = tcg_constant_i32(0);
1302cce81873SPeter Maydell     } else {
1303cce81873SPeter Maydell         rm = load_reg(s, a->rm);
1304cce81873SPeter Maydell     }
1305cce81873SPeter Maydell     fn(cpu_env, qn, rm);
1306cce81873SPeter Maydell     tcg_temp_free_ptr(qn);
1307cce81873SPeter Maydell     tcg_temp_free_i32(rm);
1308cce81873SPeter Maydell     if (a->mask) {
1309cce81873SPeter Maydell         /* VPT */
1310cce81873SPeter Maydell         gen_vpst(s, a->mask);
1311cce81873SPeter Maydell     }
1312cce81873SPeter Maydell     mve_update_eci(s);
1313cce81873SPeter Maydell     return true;
1314cce81873SPeter Maydell }
1315cce81873SPeter Maydell 
1316eff5d9a9SPeter Maydell #define DO_VCMP(INSN, FN)                                       \
1317eff5d9a9SPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_vcmp *a)      \
1318eff5d9a9SPeter Maydell     {                                                           \
1319eff5d9a9SPeter Maydell         static MVEGenCmpFn * const fns[] = {                    \
1320eff5d9a9SPeter Maydell             gen_helper_mve_##FN##b,                             \
1321eff5d9a9SPeter Maydell             gen_helper_mve_##FN##h,                             \
1322eff5d9a9SPeter Maydell             gen_helper_mve_##FN##w,                             \
1323eff5d9a9SPeter Maydell             NULL,                                               \
1324eff5d9a9SPeter Maydell         };                                                      \
1325eff5d9a9SPeter Maydell         return do_vcmp(s, a, fns[a->size]);                     \
1326cce81873SPeter Maydell     }                                                           \
1327cce81873SPeter Maydell     static bool trans_##INSN##_scalar(DisasContext *s,          \
1328cce81873SPeter Maydell                                       arg_vcmp_scalar *a)       \
1329cce81873SPeter Maydell     {                                                           \
1330cce81873SPeter Maydell         static MVEGenScalarCmpFn * const fns[] = {              \
1331cce81873SPeter Maydell             gen_helper_mve_##FN##_scalarb,                      \
1332cce81873SPeter Maydell             gen_helper_mve_##FN##_scalarh,                      \
1333cce81873SPeter Maydell             gen_helper_mve_##FN##_scalarw,                      \
1334cce81873SPeter Maydell             NULL,                                               \
1335cce81873SPeter Maydell         };                                                      \
1336cce81873SPeter Maydell         return do_vcmp_scalar(s, a, fns[a->size]);              \
1337eff5d9a9SPeter Maydell     }
1338eff5d9a9SPeter Maydell 
1339eff5d9a9SPeter Maydell DO_VCMP(VCMPEQ, vcmpeq)
1340eff5d9a9SPeter Maydell DO_VCMP(VCMPNE, vcmpne)
1341eff5d9a9SPeter Maydell DO_VCMP(VCMPCS, vcmpcs)
1342eff5d9a9SPeter Maydell DO_VCMP(VCMPHI, vcmphi)
1343eff5d9a9SPeter Maydell DO_VCMP(VCMPGE, vcmpge)
1344eff5d9a9SPeter Maydell DO_VCMP(VCMPLT, vcmplt)
1345eff5d9a9SPeter Maydell DO_VCMP(VCMPGT, vcmpgt)
1346eff5d9a9SPeter Maydell DO_VCMP(VCMPLE, vcmple)
1347688ba4cfSPeter Maydell 
1348688ba4cfSPeter Maydell static bool do_vmaxv(DisasContext *s, arg_vmaxv *a, MVEGenVADDVFn fn)
1349688ba4cfSPeter Maydell {
1350688ba4cfSPeter Maydell     /*
1351688ba4cfSPeter Maydell      * MIN/MAX operations across a vector: compute the min or
1352688ba4cfSPeter Maydell      * max of the initial value in a general purpose register
1353688ba4cfSPeter Maydell      * and all the elements in the vector, and store it back
1354688ba4cfSPeter Maydell      * into the general purpose register.
1355688ba4cfSPeter Maydell      */
1356688ba4cfSPeter Maydell     TCGv_ptr qm;
1357688ba4cfSPeter Maydell     TCGv_i32 rda;
1358688ba4cfSPeter Maydell 
1359688ba4cfSPeter Maydell     if (!dc_isar_feature(aa32_mve, s) || !mve_check_qreg_bank(s, a->qm) ||
1360688ba4cfSPeter Maydell         !fn || a->rda == 13 || a->rda == 15) {
1361688ba4cfSPeter Maydell         /* Rda cases are UNPREDICTABLE */
1362688ba4cfSPeter Maydell         return false;
1363688ba4cfSPeter Maydell     }
1364688ba4cfSPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
1365688ba4cfSPeter Maydell         return true;
1366688ba4cfSPeter Maydell     }
1367688ba4cfSPeter Maydell 
1368688ba4cfSPeter Maydell     qm = mve_qreg_ptr(a->qm);
1369688ba4cfSPeter Maydell     rda = load_reg(s, a->rda);
1370688ba4cfSPeter Maydell     fn(rda, cpu_env, qm, rda);
1371688ba4cfSPeter Maydell     store_reg(s, a->rda, rda);
1372688ba4cfSPeter Maydell     tcg_temp_free_ptr(qm);
1373688ba4cfSPeter Maydell     mve_update_eci(s);
1374688ba4cfSPeter Maydell     return true;
1375688ba4cfSPeter Maydell }
1376688ba4cfSPeter Maydell 
1377688ba4cfSPeter Maydell #define DO_VMAXV(INSN, FN)                                      \
1378688ba4cfSPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_vmaxv *a)     \
1379688ba4cfSPeter Maydell     {                                                           \
1380688ba4cfSPeter Maydell         static MVEGenVADDVFn * const fns[] = {                  \
1381688ba4cfSPeter Maydell             gen_helper_mve_##FN##b,                             \
1382688ba4cfSPeter Maydell             gen_helper_mve_##FN##h,                             \
1383688ba4cfSPeter Maydell             gen_helper_mve_##FN##w,                             \
1384688ba4cfSPeter Maydell             NULL,                                               \
1385688ba4cfSPeter Maydell         };                                                      \
1386688ba4cfSPeter Maydell         return do_vmaxv(s, a, fns[a->size]);                    \
1387688ba4cfSPeter Maydell     }
1388688ba4cfSPeter Maydell 
1389688ba4cfSPeter Maydell DO_VMAXV(VMAXV_S, vmaxvs)
1390688ba4cfSPeter Maydell DO_VMAXV(VMAXV_U, vmaxvu)
1391688ba4cfSPeter Maydell DO_VMAXV(VMAXAV, vmaxav)
1392688ba4cfSPeter Maydell DO_VMAXV(VMINV_S, vminvs)
1393688ba4cfSPeter Maydell DO_VMAXV(VMINV_U, vminvu)
1394688ba4cfSPeter Maydell DO_VMAXV(VMINAV, vminav)
13957f061c0aSPeter Maydell 
13967f061c0aSPeter Maydell static bool do_vabav(DisasContext *s, arg_vabav *a, MVEGenVABAVFn *fn)
13977f061c0aSPeter Maydell {
13987f061c0aSPeter Maydell     /* Absolute difference accumulated across vector */
13997f061c0aSPeter Maydell     TCGv_ptr qn, qm;
14007f061c0aSPeter Maydell     TCGv_i32 rda;
14017f061c0aSPeter Maydell 
14027f061c0aSPeter Maydell     if (!dc_isar_feature(aa32_mve, s) ||
14037f061c0aSPeter Maydell         !mve_check_qreg_bank(s, a->qm | a->qn) ||
14047f061c0aSPeter Maydell         !fn || a->rda == 13 || a->rda == 15) {
14057f061c0aSPeter Maydell         /* Rda cases are UNPREDICTABLE */
14067f061c0aSPeter Maydell         return false;
14077f061c0aSPeter Maydell     }
14087f061c0aSPeter Maydell     if (!mve_eci_check(s) || !vfp_access_check(s)) {
14097f061c0aSPeter Maydell         return true;
14107f061c0aSPeter Maydell     }
14117f061c0aSPeter Maydell 
14127f061c0aSPeter Maydell     qm = mve_qreg_ptr(a->qm);
14137f061c0aSPeter Maydell     qn = mve_qreg_ptr(a->qn);
14147f061c0aSPeter Maydell     rda = load_reg(s, a->rda);
14157f061c0aSPeter Maydell     fn(rda, cpu_env, qn, qm, rda);
14167f061c0aSPeter Maydell     store_reg(s, a->rda, rda);
14177f061c0aSPeter Maydell     tcg_temp_free_ptr(qm);
14187f061c0aSPeter Maydell     tcg_temp_free_ptr(qn);
14197f061c0aSPeter Maydell     mve_update_eci(s);
14207f061c0aSPeter Maydell     return true;
14217f061c0aSPeter Maydell }
14227f061c0aSPeter Maydell 
14237f061c0aSPeter Maydell #define DO_VABAV(INSN, FN)                                      \
14247f061c0aSPeter Maydell     static bool trans_##INSN(DisasContext *s, arg_vabav *a)     \
14257f061c0aSPeter Maydell     {                                                           \
14267f061c0aSPeter Maydell         static MVEGenVABAVFn * const fns[] = {                  \
14277f061c0aSPeter Maydell             gen_helper_mve_##FN##b,                             \
14287f061c0aSPeter Maydell             gen_helper_mve_##FN##h,                             \
14297f061c0aSPeter Maydell             gen_helper_mve_##FN##w,                             \
14307f061c0aSPeter Maydell             NULL,                                               \
14317f061c0aSPeter Maydell         };                                                      \
14327f061c0aSPeter Maydell         return do_vabav(s, a, fns[a->size]);                    \
14337f061c0aSPeter Maydell     }
14347f061c0aSPeter Maydell 
14357f061c0aSPeter Maydell DO_VABAV(VABAV_S, vabavs)
14367f061c0aSPeter Maydell DO_VABAV(VABAV_U, vabavu)
1437