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