提交 b3ff4b87 编写于 作者: P Peter Maydell

target/arm: Convert the VSEL instructions to decodetree

Convert the VSEL instructions to decodetree.
We leave trans_VSEL() in translate.c for now as this allows
the patch to show just the changes from the old handle_vsel().

In the old code the check for "do D16-D31 exist" was hidden in
the VFP_DREG macro, and assumed that VFPv3 always implied that
D16-D31 exist. In the new code we do the correct ID register test.
This gives identical behaviour for most of our CPUs, and fixes
previously incorrect handling for  Cortex-R5F, Cortex-M4 and
Cortex-M33, which all implement VFPv3 or better with only 16
double-precision registers.
Signed-off-by: NPeter Maydell <peter.maydell@linaro.org>
Reviewed-by: NRichard Henderson <richard.henderson@linaro.org>
上级 973751fd
...@@ -3371,6 +3371,12 @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id) ...@@ -3371,6 +3371,12 @@ static inline bool isar_feature_aa32_fp16_arith(const ARMISARegisters *id)
return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1; return FIELD_EX64(id->id_aa64pfr0, ID_AA64PFR0, FP) == 1;
} }
static inline bool isar_feature_aa32_fp_d32(const ARMISARegisters *id)
{
/* Return true if D16-D31 are implemented */
return FIELD_EX64(id->mvfr0, MVFR0, SIMDREG) >= 2;
}
/* /*
* We always set the FP and SIMD FP16 fields to indicate identical * We always set the FP and SIMD FP16 fields to indicate identical
* levels of support (assuming SIMD is implemented at all), so * levels of support (assuming SIMD is implemented at all), so
......
...@@ -129,3 +129,12 @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled) ...@@ -129,3 +129,12 @@ static bool full_vfp_access_check(DisasContext *s, bool ignore_vfp_enabled)
return true; return true;
} }
/*
* The most usual kind of VFP access check, for everything except
* FMXR/FMRX to the always-available special registers.
*/
static bool vfp_access_check(DisasContext *s)
{
return full_vfp_access_check(s, false);
}
...@@ -3076,10 +3076,27 @@ static void gen_neon_dup_high16(TCGv_i32 var) ...@@ -3076,10 +3076,27 @@ static void gen_neon_dup_high16(TCGv_i32 var)
tcg_temp_free_i32(tmp); tcg_temp_free_i32(tmp);
} }
static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm, static bool trans_VSEL(DisasContext *s, arg_VSEL *a)
uint32_t dp)
{ {
uint32_t cc = extract32(insn, 20, 2); uint32_t rd, rn, rm;
bool dp = a->dp;
if (!dc_isar_feature(aa32_vsel, s)) {
return false;
}
/* UNDEF accesses to D16-D31 if they don't exist */
if (dp && !dc_isar_feature(aa32_fp_d32, s) &&
((a->vm | a->vn | a->vd) & 0x10)) {
return false;
}
rd = a->vd;
rn = a->vn;
rm = a->vm;
if (!vfp_access_check(s)) {
return true;
}
if (dp) { if (dp) {
TCGv_i64 frn, frm, dest; TCGv_i64 frn, frm, dest;
...@@ -3101,7 +3118,7 @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm, ...@@ -3101,7 +3118,7 @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn)); tcg_gen_ld_f64(frn, cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm)); tcg_gen_ld_f64(frm, cpu_env, vfp_reg_offset(dp, rm));
switch (cc) { switch (a->cc) {
case 0: /* eq: Z */ case 0: /* eq: Z */
tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero, tcg_gen_movcond_i64(TCG_COND_EQ, dest, zf, zero,
frn, frm); frn, frm);
...@@ -3148,7 +3165,7 @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm, ...@@ -3148,7 +3165,7 @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
dest = tcg_temp_new_i32(); dest = tcg_temp_new_i32();
tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn)); tcg_gen_ld_f32(frn, cpu_env, vfp_reg_offset(dp, rn));
tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm)); tcg_gen_ld_f32(frm, cpu_env, vfp_reg_offset(dp, rm));
switch (cc) { switch (a->cc) {
case 0: /* eq: Z */ case 0: /* eq: Z */
tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero, tcg_gen_movcond_i32(TCG_COND_EQ, dest, cpu_ZF, zero,
frn, frm); frn, frm);
...@@ -3182,7 +3199,7 @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm, ...@@ -3182,7 +3199,7 @@ static int handle_vsel(uint32_t insn, uint32_t rd, uint32_t rn, uint32_t rm,
tcg_temp_free_i32(zero); tcg_temp_free_i32(zero);
} }
return 0; return true;
} }
static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn, static int handle_vminmaxnm(uint32_t insn, uint32_t rd, uint32_t rn,
...@@ -3354,10 +3371,8 @@ static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn) ...@@ -3354,10 +3371,8 @@ static int disas_vfp_misc_insn(DisasContext *s, uint32_t insn)
rm = VFP_SREG_M(insn); rm = VFP_SREG_M(insn);
} }
if ((insn & 0x0f800e50) == 0x0e000a00 && dc_isar_feature(aa32_vsel, s)) { if ((insn & 0x0fb00e10) == 0x0e800a00 &&
return handle_vsel(insn, rd, rn, rm, dp); dc_isar_feature(aa32_vminmaxnm, s)) {
} else if ((insn & 0x0fb00e10) == 0x0e800a00 &&
dc_isar_feature(aa32_vminmaxnm, s)) {
return handle_vminmaxnm(insn, rd, rn, rm, dp); return handle_vminmaxnm(insn, rd, rn, rm, dp);
} else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 && } else if ((insn & 0x0fbc0ed0) == 0x0eb80a40 &&
dc_isar_feature(aa32_vrint, s)) { dc_isar_feature(aa32_vrint, s)) {
......
...@@ -26,3 +26,22 @@ ...@@ -26,3 +26,22 @@
# 1111 1110 .... .... .... 101. .... .... # 1111 1110 .... .... .... 101. .... ....
# (but those patterns might also cover some Neon instructions, # (but those patterns might also cover some Neon instructions,
# which do not live in this file.) # which do not live in this file.)
# VFP registers have an odd encoding with a four-bit field
# and a one-bit field which are assembled in different orders
# depending on whether the register is double or single precision.
# Each individual instruction function must do the checks for
# "double register selected but CPU does not have double support"
# and "double register number has bit 4 set but CPU does not
# support D16-D31" (which should UNDEF).
%vm_dp 5:1 0:4
%vm_sp 0:4 5:1
%vn_dp 7:1 16:4
%vn_sp 16:4 7:1
%vd_dp 22:1 12:4
%vd_sp 12:4 22:1
VSEL 1111 1110 0. cc:2 .... .... 1010 .0.0 .... \
vm=%vm_sp vn=%vn_sp vd=%vd_sp dp=0
VSEL 1111 1110 0. cc:2 .... .... 1011 .0.0 .... \
vm=%vm_dp vn=%vn_dp vd=%vd_dp dp=1
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册