diff options
author | Peter Maydell <peter.maydell@linaro.org> | 2020-06-16 10:32:28 +0100 |
---|---|---|
committer | Peter Maydell <peter.maydell@linaro.org> | 2020-06-16 10:32:28 +0100 |
commit | 54e96c744b70a5d19f14b212a579dd3be8fcaad9 (patch) | |
tree | 313dd9ae69f63e097656e9908cd368bad8e5dad4 /target/arm/translate-neon.inc.c | |
parent | 0aad761fb0aed40c99039eacac470cbd03d07019 (diff) |
target/arm: Convert Neon VTBL, VTBX to decodetree
Convert the Neon VTBL, VTBX instructions to decodetree. The actual
implementation of the insn is copied across to the new trans function
unchanged except for renaming 'tmp5' to 'tmp4'.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Diffstat (limited to 'target/arm/translate-neon.inc.c')
-rw-r--r-- | target/arm/translate-neon.inc.c | 56 |
1 files changed, 56 insertions, 0 deletions
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c index 84bc2b239c..da0e5dbc6f 100644 --- a/target/arm/translate-neon.inc.c +++ b/target/arm/translate-neon.inc.c @@ -2888,3 +2888,59 @@ static bool trans_VEXT(DisasContext *s, arg_VEXT *a) } return true; } + +static bool trans_VTBL(DisasContext *s, arg_VTBL *a) +{ + int n; + TCGv_i32 tmp, tmp2, tmp3, tmp4; + TCGv_ptr ptr1; + + if (!arm_dc_feature(s, ARM_FEATURE_NEON)) { + return false; + } + + /* UNDEF accesses to D16-D31 if they don't exist. */ + if (!dc_isar_feature(aa32_simd_r32, s) && + ((a->vd | a->vn | a->vm) & 0x10)) { + return false; + } + + if (!vfp_access_check(s)) { + return true; + } + + n = a->len + 1; + if ((a->vn + n) > 32) { + /* + * This is UNPREDICTABLE; we choose to UNDEF to avoid the + * helper function running off the end of the register file. + */ + return false; + } + n <<= 3; + if (a->op) { + tmp = neon_load_reg(a->vd, 0); + } else { + tmp = tcg_temp_new_i32(); + tcg_gen_movi_i32(tmp, 0); + } + tmp2 = neon_load_reg(a->vm, 0); + ptr1 = vfp_reg_ptr(true, a->vn); + tmp4 = tcg_const_i32(n); + gen_helper_neon_tbl(tmp2, tmp2, tmp, ptr1, tmp4); + tcg_temp_free_i32(tmp); + if (a->op) { + tmp = neon_load_reg(a->vd, 1); + } else { + tmp = tcg_temp_new_i32(); + tcg_gen_movi_i32(tmp, 0); + } + tmp3 = neon_load_reg(a->vm, 1); + gen_helper_neon_tbl(tmp3, tmp3, tmp, ptr1, tmp4); + tcg_temp_free_i32(tmp4); + tcg_temp_free_ptr(ptr1); + neon_store_reg(a->vd, 0, tmp2); + neon_store_reg(a->vd, 1, tmp3); + tcg_temp_free_i32(tmp); + return true; +} |