tcg/x86_64/tcg-target-con-set.h | 2 ++ tcg/x86_64/tcg-target.c.inc | 36 ++++++++++++++++++++++++++++++--- 2 files changed, 35 insertions(+), 3 deletions(-)
This vex encoded instruction can be used or either mulu2 or muluh.
This replaces the highly constrained mul insn from the base x86 isa.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/x86_64/tcg-target-con-set.h | 2 ++
tcg/x86_64/tcg-target.c.inc | 36 ++++++++++++++++++++++++++++++---
2 files changed, 35 insertions(+), 3 deletions(-)
diff --git a/tcg/x86_64/tcg-target-con-set.h b/tcg/x86_64/tcg-target-con-set.h
index 458d69c3c07..7df9bf49177 100644
--- a/tcg/x86_64/tcg-target-con-set.h
+++ b/tcg/x86_64/tcg-target-con-set.h
@@ -42,6 +42,7 @@ C_O1_I2(r, 0, reZ)
C_O1_I2(r, 0, ri)
C_O1_I2(r, 0, rI)
C_O1_I2(r, L, L)
+C_O1_I2(r, r, d)
C_O1_I2(r, r, r)
C_O1_I2(r, r, re)
C_O1_I2(r, r, ri)
@@ -56,5 +57,6 @@ C_O1_I4(r, r, reT, r, 0)
C_O1_I4(r, r, r, ri, ri)
C_O2_I1(r, r, L)
C_O2_I2(a, d, a, r)
+C_O2_I2(r, r, r, d)
C_O2_I2(r, r, L, L)
C_O2_I3(a, d, 0, 1, r)
diff --git a/tcg/x86_64/tcg-target.c.inc b/tcg/x86_64/tcg-target.c.inc
index 2c8f1f3e580..8e0d8e08146 100644
--- a/tcg/x86_64/tcg-target.c.inc
+++ b/tcg/x86_64/tcg-target.c.inc
@@ -274,6 +274,7 @@ static bool tcg_target_const_match(int64_t val, int ct,
#define OPC_MOVSLQ (0x63 | P_REXW)
#define OPC_MOVZBL (0xb6 | P_EXT)
#define OPC_MOVZWL (0xb7 | P_EXT)
+#define OPC_MULX (0xf6 | P_SIMDF2 | P_EXT38)
#define OPC_PABSB (0x1c | P_EXT38 | P_DATA16)
#define OPC_PABSW (0x1d | P_EXT38 | P_DATA16)
#define OPC_PABSD (0x1e | P_EXT38 | P_DATA16)
@@ -2732,19 +2733,48 @@ static const TCGOutOpBinary outop_mulsh = {
.base.static_constraint = C_NotImplemented,
};
+static void tgen_muluh(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ /*
+ * Note from the architecture manual:
+ * If the first and second operand are identical,
+ * it will contain the high half of the multiplication result.
+ */
+ int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
+ tcg_out_vex_modrm(s, OPC_MULX + rexw, a0, a0, a1);
+}
+
+static TCGConstraintSetIndex cset_muluh(TCGType type, unsigned flags)
+{
+ return have_bmi2 ? C_O1_I2(r, r, d) : C_NotImplemented;
+}
+
static const TCGOutOpBinary outop_muluh = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_muluh,
+ .out_rrr = tgen_muluh,
};
static void tgen_mulu2(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2, TCGReg a3)
{
int rexw = type == TCG_TYPE_I32 ? 0 : P_REXW;
- tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_MUL, a3);
+ if (have_bmi2) {
+ tcg_out_vex_modrm(s, OPC_MULX + rexw, a0, a1, a2);
+ } else {
+ tcg_out_modrm(s, OPC_GRP3_Ev + rexw, EXT3_MUL, a3);
+ }
+}
+
+static TCGConstraintSetIndex cset_mulu2(TCGType type, unsigned flags)
+{
+ return have_bmi2 ? C_O2_I2(r, r, r, d) : C_O2_I2(a, d, a, r);
}
static const TCGOutOpMul2 outop_mulu2 = {
- .base.static_constraint = C_O2_I2(a, d, a, r),
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_mulu2,
.out_rrrr = tgen_mulu2,
};
--
2.53.0
© 2016 - 2026 Red Hat, Inc.