diff options
Diffstat (limited to 'target/arm/translate-vfp.c.inc')
-rw-r--r-- | target/arm/translate-vfp.c.inc | 84 |
1 files changed, 84 insertions, 0 deletions
diff --git a/target/arm/translate-vfp.c.inc b/target/arm/translate-vfp.c.inc index 96948f5a2d..2a67ed0f6e 100644 --- a/target/arm/translate-vfp.c.inc +++ b/target/arm/translate-vfp.c.inc @@ -3406,6 +3406,90 @@ static bool trans_VLLDM_VLSTM(DisasContext *s, arg_VLLDM_VLSTM *a) return true; } +static bool trans_VSCCLRM(DisasContext *s, arg_VSCCLRM *a) +{ + int btmreg, topreg; + TCGv_i64 zero; + TCGv_i32 aspen, sfpa; + + if (!dc_isar_feature(aa32_m_sec_state, s)) { + /* Before v8.1M, fall through in decode to NOCP check */ + return false; + } + + /* Explicitly UNDEF because this takes precedence over NOCP */ + if (!arm_dc_feature(s, ARM_FEATURE_M_MAIN) || !s->v8m_secure) { + unallocated_encoding(s); + return true; + } + + if (!dc_isar_feature(aa32_vfp_simd, s)) { + /* NOP if we have neither FP nor MVE */ + return true; + } + + /* + * If FPCCR.ASPEN != 0 && CONTROL_S.SFPA == 0 then there is no + * active floating point context so we must NOP (without doing + * any lazy state preservation or the NOCP check). + */ + aspen = load_cpu_field(v7m.fpccr[M_REG_S]); + sfpa = load_cpu_field(v7m.control[M_REG_S]); + tcg_gen_andi_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK); + tcg_gen_xori_i32(aspen, aspen, R_V7M_FPCCR_ASPEN_MASK); + tcg_gen_andi_i32(sfpa, sfpa, R_V7M_CONTROL_SFPA_MASK); + tcg_gen_or_i32(sfpa, sfpa, aspen); + arm_gen_condlabel(s); + tcg_gen_brcondi_i32(TCG_COND_EQ, sfpa, 0, s->condlabel); + + if (s->fp_excp_el != 0) { + gen_exception_insn(s, s->pc_curr, EXCP_NOCP, + syn_uncategorized(), s->fp_excp_el); + return true; + } + + topreg = a->vd + a->imm - 1; + btmreg = a->vd; + + /* Convert to Sreg numbers if the insn specified in Dregs */ + if (a->size == 3) { + topreg = topreg * 2 + 1; + btmreg *= 2; + } + + if (topreg > 63 || (topreg > 31 && !(topreg & 1))) { + /* UNPREDICTABLE: we choose to undef */ + unallocated_encoding(s); + return true; + } + + /* Silently ignore requests to clear D16-D31 if they don't exist */ + if (topreg > 31 && !dc_isar_feature(aa32_simd_r32, s)) { + topreg = 31; + } + + if (!vfp_access_check(s)) { + return true; + } + + /* Zero the Sregs from btmreg to topreg inclusive. */ + zero = tcg_const_i64(0); + if (btmreg & 1) { + write_neon_element64(zero, btmreg >> 1, 1, MO_32); + btmreg++; + } + for (; btmreg + 1 <= topreg; btmreg += 2) { + write_neon_element64(zero, btmreg >> 1, 0, MO_64); + } + if (btmreg == topreg) { + write_neon_element64(zero, btmreg >> 1, 0, MO_32); + btmreg++; + } + assert(btmreg == topreg + 1); + /* TODO: when MVE is implemented, zero VPR here */ + return true; +} + static bool trans_NOCP(DisasContext *s, arg_nocp *a) { /* |