[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH 5/7] target/arm: Convert Neon 3-reg-diff long multiplies
From: |
Peter Maydell |
Subject: |
[PATCH 5/7] target/arm: Convert Neon 3-reg-diff long multiplies |
Date: |
Tue, 9 Jun 2020 17:02:07 +0100 |
Convert the Neon 3-reg-diff insns VMULL, VMLAL and VMLSL; these perform
a 32x32->64 multiply with possible accumulate.
Note that for VMLSL we do the accumulate directly with a subtraction
rather than doing a negate-then-add as the old code did.
Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
---
target/arm/neon-dp.decode | 9 +++++
target/arm/translate-neon.inc.c | 71 +++++++++++++++++++++++++++++++++
target/arm/translate.c | 21 +++-------
3 files changed, 86 insertions(+), 15 deletions(-)
diff --git a/target/arm/neon-dp.decode b/target/arm/neon-dp.decode
index 4f0aaaf6bb2..1da492df146 100644
--- a/target/arm/neon-dp.decode
+++ b/target/arm/neon-dp.decode
@@ -450,5 +450,14 @@ Vimm_1r 1111 001 . 1 . 000 ... .... cmode:4 0 .
op:1 1 .... @1reg_imm
VABDL_S_3d 1111 001 0 1 . .. .... .... 0111 . 0 . 0 .... @3diff
VABDL_U_3d 1111 001 1 1 . .. .... .... 0111 . 0 . 0 .... @3diff
+
+ VMLAL_S_3d 1111 001 0 1 . .. .... .... 1000 . 0 . 0 .... @3diff
+ VMLAL_U_3d 1111 001 1 1 . .. .... .... 1000 . 0 . 0 .... @3diff
+
+ VMLSL_S_3d 1111 001 0 1 . .. .... .... 1010 . 0 . 0 .... @3diff
+ VMLSL_U_3d 1111 001 1 1 . .. .... .... 1010 . 0 . 0 .... @3diff
+
+ VMULL_S_3d 1111 001 0 1 . .. .... .... 1100 . 0 . 0 .... @3diff
+ VMULL_U_3d 1111 001 1 1 . .. .... .... 1100 . 0 . 0 .... @3diff
]
}
diff --git a/target/arm/translate-neon.inc.c b/target/arm/translate-neon.inc.c
index fd85ff5ea50..00a779c65a0 100644
--- a/target/arm/translate-neon.inc.c
+++ b/target/arm/translate-neon.inc.c
@@ -2151,3 +2151,74 @@ static bool trans_VABAL_U_3d(DisasContext *s, arg_3diff
*a)
return do_long_3d(s, a, opfn[a->size], addfn[a->size]);
}
+
+static void gen_mull_s32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm)
+{
+ TCGv_i32 lo = tcg_temp_new_i32();
+ TCGv_i32 hi = tcg_temp_new_i32();
+
+ tcg_gen_muls2_i32(lo, hi, rn, rm);
+ tcg_gen_concat_i32_i64(rd, lo, hi);
+
+ tcg_temp_free_i32(lo);
+ tcg_temp_free_i32(hi);
+}
+
+static void gen_mull_u32(TCGv_i64 rd, TCGv_i32 rn, TCGv_i32 rm)
+{
+ TCGv_i32 lo = tcg_temp_new_i32();
+ TCGv_i32 hi = tcg_temp_new_i32();
+
+ tcg_gen_mulu2_i32(lo, hi, rn, rm);
+ tcg_gen_concat_i32_i64(rd, lo, hi);
+
+ tcg_temp_free_i32(lo);
+ tcg_temp_free_i32(hi);
+}
+
+static bool trans_VMULL_S_3d(DisasContext *s, arg_3diff *a)
+{
+ NeonGenTwoOpWidenFn *opfn[] = {
+ gen_helper_neon_mull_s8,
+ gen_helper_neon_mull_s16,
+ gen_mull_s32,
+ NULL,
+ };
+
+ return do_long_3d(s, a, opfn[a->size], NULL);
+}
+
+static bool trans_VMULL_U_3d(DisasContext *s, arg_3diff *a)
+{
+ NeonGenTwoOpWidenFn *opfn[] = {
+ gen_helper_neon_mull_u8,
+ gen_helper_neon_mull_u16,
+ gen_mull_u32,
+ NULL,
+ };
+
+ return do_long_3d(s, a, opfn[a->size], NULL);
+}
+
+#define DO_VMLAL(INSN,MULL,ACC) \
+ static bool trans_##INSN##_3d(DisasContext *s, arg_3diff *a) \
+ { \
+ NeonGenTwoOpWidenFn *opfn[] = { \
+ gen_helper_neon_##MULL##8, \
+ gen_helper_neon_##MULL##16, \
+ gen_##MULL##32, \
+ NULL, \
+ }; \
+ NeonGenTwo64OpFn *accfn[] = { \
+ gen_helper_neon_##ACC##l_u16, \
+ gen_helper_neon_##ACC##l_u32, \
+ tcg_gen_##ACC##_i64, \
+ NULL, \
+ }; \
+ return do_long_3d(s, a, opfn[a->size], accfn[a->size]); \
+ }
+
+DO_VMLAL(VMLAL_S,mull_s,add)
+DO_VMLAL(VMLAL_U,mull_u,add)
+DO_VMLAL(VMLSL_S,mull_s,sub)
+DO_VMLAL(VMLSL_U,mull_u,sub)
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 37fe9d46e0b..a2c47d19f21 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -5246,11 +5246,11 @@ static int disas_neon_data_insn(DisasContext *s,
uint32_t insn)
{0, 0, 0, 7}, /* VABAL */
{0, 0, 0, 7}, /* VSUBHN: handled by decodetree */
{0, 0, 0, 7}, /* VABDL */
- {0, 0, 0, 0}, /* VMLAL */
+ {0, 0, 0, 7}, /* VMLAL */
{0, 0, 0, 9}, /* VQDMLAL */
- {0, 0, 0, 0}, /* VMLSL */
+ {0, 0, 0, 7}, /* VMLSL */
{0, 0, 0, 9}, /* VQDMLSL */
- {0, 0, 0, 0}, /* Integer VMULL */
+ {0, 0, 0, 7}, /* Integer VMULL */
{0, 0, 0, 9}, /* VQDMULL */
{0, 0, 0, 0xa}, /* Polynomial VMULL */
{0, 0, 0, 7}, /* Reserved: always UNDEF */
@@ -5306,8 +5306,8 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t
insn)
tmp2 = neon_load_reg(rm, pass);
}
switch (op) {
- case 8: case 9: case 10: case 11: case 12: case 13:
- /* VMLAL, VQDMLAL, VMLSL, VQDMLSL, VMULL, VQDMULL */
+ case 9: case 11: case 13:
+ /* VQDMLAL, VQDMLSL, VQDMULL */
gen_neon_mull(cpu_V0, tmp, tmp2, size, u);
break;
default: /* 15 is RESERVED: caught earlier */
@@ -5317,16 +5317,10 @@ static int disas_neon_data_insn(DisasContext *s,
uint32_t insn)
/* VQDMULL */
gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
neon_store_reg64(cpu_V0, rd + pass);
- } else if (op == 5 || (op >= 8 && op <= 11)) {
+ } else {
/* Accumulate. */
neon_load_reg64(cpu_V1, rd + pass);
switch (op) {
- case 10: /* VMLSL */
- gen_neon_negl(cpu_V0, size);
- /* Fall through */
- case 8: /* VABAL, VMLAL */
- gen_neon_addl(size);
- break;
case 9: case 11: /* VQDMLAL, VQDMLSL */
gen_neon_addl_saturate(cpu_V0, cpu_V0, size);
if (op == 11) {
@@ -5338,9 +5332,6 @@ static int disas_neon_data_insn(DisasContext *s, uint32_t
insn)
abort();
}
neon_store_reg64(cpu_V0, rd + pass);
- } else {
- /* Write back the result. */
- neon_store_reg64(cpu_V0, rd + pass);
}
}
} else {
--
2.20.1
- [PATCH 0/7] target/arm: Convert Neon 3-reg-diff to decodetree, Peter Maydell, 2020/06/09
- [PATCH 5/7] target/arm: Convert Neon 3-reg-diff long multiplies,
Peter Maydell <=
- [PATCH 4/7] target/arm: Convert Neon 3-reg-diff VABAL, VABDL to decodetree, Peter Maydell, 2020/06/09
- [PATCH 2/7] target/arm: Convert Neon 3-reg-diff prewidening ops to decodetree, Peter Maydell, 2020/06/09
- [PATCH 3/7] target/arm: Convert Neon 3-reg-diff narrowing ops to decodetree, Peter Maydell, 2020/06/09
- [PATCH 1/7] target/arm: Fix missing temp frees in do_vshll_2sh, Peter Maydell, 2020/06/09