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 286390eed4SPeter Maydell /* Include the generated decoder */ 296390eed4SPeter Maydell #include "decode-mve.c.inc" 30*507b6a50SPeter Maydell 31*507b6a50SPeter Maydell typedef void MVEGenLdStFn(TCGv_ptr, TCGv_ptr, TCGv_i32); 32*507b6a50SPeter Maydell 33*507b6a50SPeter Maydell /* Return the offset of a Qn register (same semantics as aa32_vfp_qreg()) */ 34*507b6a50SPeter Maydell static inline long mve_qreg_offset(unsigned reg) 35*507b6a50SPeter Maydell { 36*507b6a50SPeter Maydell return offsetof(CPUARMState, vfp.zregs[reg].d[0]); 37*507b6a50SPeter Maydell } 38*507b6a50SPeter Maydell 39*507b6a50SPeter Maydell static TCGv_ptr mve_qreg_ptr(unsigned reg) 40*507b6a50SPeter Maydell { 41*507b6a50SPeter Maydell TCGv_ptr ret = tcg_temp_new_ptr(); 42*507b6a50SPeter Maydell tcg_gen_addi_ptr(ret, cpu_env, mve_qreg_offset(reg)); 43*507b6a50SPeter Maydell return ret; 44*507b6a50SPeter Maydell } 45*507b6a50SPeter Maydell 46*507b6a50SPeter Maydell static bool mve_check_qreg_bank(DisasContext *s, int qmask) 47*507b6a50SPeter Maydell { 48*507b6a50SPeter Maydell /* 49*507b6a50SPeter Maydell * Check whether Qregs are in range. For v8.1M only Q0..Q7 50*507b6a50SPeter Maydell * are supported, see VFPSmallRegisterBank(). 51*507b6a50SPeter Maydell */ 52*507b6a50SPeter Maydell return qmask < 8; 53*507b6a50SPeter Maydell } 54*507b6a50SPeter Maydell 55*507b6a50SPeter Maydell static bool mve_eci_check(DisasContext *s) 56*507b6a50SPeter Maydell { 57*507b6a50SPeter Maydell /* 58*507b6a50SPeter Maydell * This is a beatwise insn: check that ECI is valid (not a 59*507b6a50SPeter Maydell * reserved value) and note that we are handling it. 60*507b6a50SPeter Maydell * Return true if OK, false if we generated an exception. 61*507b6a50SPeter Maydell */ 62*507b6a50SPeter Maydell s->eci_handled = true; 63*507b6a50SPeter Maydell switch (s->eci) { 64*507b6a50SPeter Maydell case ECI_NONE: 65*507b6a50SPeter Maydell case ECI_A0: 66*507b6a50SPeter Maydell case ECI_A0A1: 67*507b6a50SPeter Maydell case ECI_A0A1A2: 68*507b6a50SPeter Maydell case ECI_A0A1A2B0: 69*507b6a50SPeter Maydell return true; 70*507b6a50SPeter Maydell default: 71*507b6a50SPeter Maydell /* Reserved value: INVSTATE UsageFault */ 72*507b6a50SPeter Maydell gen_exception_insn(s, s->pc_curr, EXCP_INVSTATE, syn_uncategorized(), 73*507b6a50SPeter Maydell default_exception_el(s)); 74*507b6a50SPeter Maydell return false; 75*507b6a50SPeter Maydell } 76*507b6a50SPeter Maydell } 77*507b6a50SPeter Maydell 78*507b6a50SPeter Maydell static void mve_update_eci(DisasContext *s) 79*507b6a50SPeter Maydell { 80*507b6a50SPeter Maydell /* 81*507b6a50SPeter Maydell * The helper function will always update the CPUState field, 82*507b6a50SPeter Maydell * so we only need to update the DisasContext field. 83*507b6a50SPeter Maydell */ 84*507b6a50SPeter Maydell if (s->eci) { 85*507b6a50SPeter Maydell s->eci = (s->eci == ECI_A0A1A2B0) ? ECI_A0 : ECI_NONE; 86*507b6a50SPeter Maydell } 87*507b6a50SPeter Maydell } 88*507b6a50SPeter Maydell 89*507b6a50SPeter Maydell static bool do_ldst(DisasContext *s, arg_VLDR_VSTR *a, MVEGenLdStFn *fn) 90*507b6a50SPeter Maydell { 91*507b6a50SPeter Maydell TCGv_i32 addr; 92*507b6a50SPeter Maydell uint32_t offset; 93*507b6a50SPeter Maydell TCGv_ptr qreg; 94*507b6a50SPeter Maydell 95*507b6a50SPeter Maydell if (!dc_isar_feature(aa32_mve, s) || 96*507b6a50SPeter Maydell !mve_check_qreg_bank(s, a->qd) || 97*507b6a50SPeter Maydell !fn) { 98*507b6a50SPeter Maydell return false; 99*507b6a50SPeter Maydell } 100*507b6a50SPeter Maydell 101*507b6a50SPeter Maydell /* CONSTRAINED UNPREDICTABLE: we choose to UNDEF */ 102*507b6a50SPeter Maydell if (a->rn == 15 || (a->rn == 13 && a->w)) { 103*507b6a50SPeter Maydell return false; 104*507b6a50SPeter Maydell } 105*507b6a50SPeter Maydell 106*507b6a50SPeter Maydell if (!mve_eci_check(s) || !vfp_access_check(s)) { 107*507b6a50SPeter Maydell return true; 108*507b6a50SPeter Maydell } 109*507b6a50SPeter Maydell 110*507b6a50SPeter Maydell offset = a->imm << a->size; 111*507b6a50SPeter Maydell if (!a->a) { 112*507b6a50SPeter Maydell offset = -offset; 113*507b6a50SPeter Maydell } 114*507b6a50SPeter Maydell addr = load_reg(s, a->rn); 115*507b6a50SPeter Maydell if (a->p) { 116*507b6a50SPeter Maydell tcg_gen_addi_i32(addr, addr, offset); 117*507b6a50SPeter Maydell } 118*507b6a50SPeter Maydell 119*507b6a50SPeter Maydell qreg = mve_qreg_ptr(a->qd); 120*507b6a50SPeter Maydell fn(cpu_env, qreg, addr); 121*507b6a50SPeter Maydell tcg_temp_free_ptr(qreg); 122*507b6a50SPeter Maydell 123*507b6a50SPeter Maydell /* 124*507b6a50SPeter Maydell * Writeback always happens after the last beat of the insn, 125*507b6a50SPeter Maydell * regardless of predication 126*507b6a50SPeter Maydell */ 127*507b6a50SPeter Maydell if (a->w) { 128*507b6a50SPeter Maydell if (!a->p) { 129*507b6a50SPeter Maydell tcg_gen_addi_i32(addr, addr, offset); 130*507b6a50SPeter Maydell } 131*507b6a50SPeter Maydell store_reg(s, a->rn, addr); 132*507b6a50SPeter Maydell } else { 133*507b6a50SPeter Maydell tcg_temp_free_i32(addr); 134*507b6a50SPeter Maydell } 135*507b6a50SPeter Maydell mve_update_eci(s); 136*507b6a50SPeter Maydell return true; 137*507b6a50SPeter Maydell } 138*507b6a50SPeter Maydell 139*507b6a50SPeter Maydell static bool trans_VLDR_VSTR(DisasContext *s, arg_VLDR_VSTR *a) 140*507b6a50SPeter Maydell { 141*507b6a50SPeter Maydell static MVEGenLdStFn * const ldstfns[4][2] = { 142*507b6a50SPeter Maydell { gen_helper_mve_vstrb, gen_helper_mve_vldrb }, 143*507b6a50SPeter Maydell { gen_helper_mve_vstrh, gen_helper_mve_vldrh }, 144*507b6a50SPeter Maydell { gen_helper_mve_vstrw, gen_helper_mve_vldrw }, 145*507b6a50SPeter Maydell { NULL, NULL } 146*507b6a50SPeter Maydell }; 147*507b6a50SPeter Maydell return do_ldst(s, a, ldstfns[a->size][a->l]); 148*507b6a50SPeter Maydell } 149