Add an opcode for compound address formation.
Reviewed-by: Matt Turner <[email protected]>
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
---
docs/devel/tcg-ops.rst | 4 ++++
include/tcg/tcg-opc.h | 1 +
tcg/aarch64/tcg-target-has.h | 3 +++
tcg/loongarch64/tcg-target-has.h | 3 +++
tcg/ppc64/tcg-target-has.h | 3 +++
tcg/riscv64/tcg-target-has.h | 3 +++
tcg/s390x/tcg-target-has.h | 3 +++
tcg/sparc64/tcg-target-has.h | 3 +++
tcg/tci/tcg-target-has.h | 3 +++
tcg/x86_64/tcg-target-has.h | 3 +++
tcg/tcg.c | 22 ++++++++++++++++++++++
tcg/aarch64/tcg-target.c.inc | 4 ++++
tcg/loongarch64/tcg-target.c.inc | 4 ++++
tcg/ppc64/tcg-target.c.inc | 3 +++
tcg/riscv64/tcg-target.c.inc | 3 +++
tcg/s390x/tcg-target.c.inc | 3 +++
tcg/sparc64/tcg-target.c.inc | 3 +++
tcg/tci/tcg-target.c.inc | 4 ++++
tcg/x86_64/tcg-target.c.inc | 4 ++++
19 files changed, 79 insertions(+)
diff --git a/docs/devel/tcg-ops.rst b/docs/devel/tcg-ops.rst
index 88d48a1f99a..51fa183e911 100644
--- a/docs/devel/tcg-ops.rst
+++ b/docs/devel/tcg-ops.rst
@@ -524,6 +524,10 @@ Misc
- | Reverse the 64 bits of input *t1* with output in *dest*.
+ * - lea *dest*, *t1*, *t2*, *sh*, *imm*
+
+ - | *dest* = *t1* + (*t2* << *sh*) + *imm*.
+
Conditional moves
-----------------
diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index f3a81d5d7fb..884345afe56 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -64,6 +64,7 @@ DEF(ld16s, 1, 1, 1, TCG_OPF_INT)
DEF(ld32u, 1, 1, 1, TCG_OPF_INT)
DEF(ld32s, 1, 1, 1, TCG_OPF_INT)
DEF(ld, 1, 1, 1, TCG_OPF_INT)
+DEF(lea, 1, 2, 2, TCG_OPF_INT)
DEF(movcond, 1, 4, 1, TCG_OPF_INT)
DEF(mul, 1, 2, 0, TCG_OPF_INT)
DEF(muls2, 2, 2, 0, TCG_OPF_INT)
diff --git a/tcg/aarch64/tcg-target-has.h b/tcg/aarch64/tcg-target-has.h
index 69e83efb69d..86672b2eab4 100644
--- a/tcg/aarch64/tcg-target-has.h
+++ b/tcg/aarch64/tcg-target-has.h
@@ -57,4 +57,7 @@
#define TCG_TARGET_sextract_valid(type, ofs, len) 1
#define TCG_TARGET_deposit_valid(type, ofs, len) 1
+#define TCG_TARGET_lea_sh_valid(type, sh) 0
+#define TCG_TARGET_lea_imm_valid(type, imm) 0
+
#endif
diff --git a/tcg/loongarch64/tcg-target-has.h b/tcg/loongarch64/tcg-target-has.h
index 32abc6f4574..31e6ea9632d 100644
--- a/tcg/loongarch64/tcg-target-has.h
+++ b/tcg/loongarch64/tcg-target-has.h
@@ -54,4 +54,7 @@ tcg_target_sextract_valid(TCGType type, unsigned ofs,
unsigned len)
}
#define TCG_TARGET_sextract_valid tcg_target_sextract_valid
+#define TCG_TARGET_lea_sh_valid(type, sh) 0
+#define TCG_TARGET_lea_imm_valid(type, imm) 0
+
#endif
diff --git a/tcg/ppc64/tcg-target-has.h b/tcg/ppc64/tcg-target-has.h
index a3711feeae2..d11d82f1844 100644
--- a/tcg/ppc64/tcg-target-has.h
+++ b/tcg/ppc64/tcg-target-has.h
@@ -66,4 +66,7 @@ tcg_target_sextract_valid(TCGType type, unsigned ofs,
unsigned len)
}
#define TCG_TARGET_sextract_valid tcg_target_sextract_valid
+#define TCG_TARGET_lea_sh_valid(type, sh) 0
+#define TCG_TARGET_lea_imm_valid(type, imm) 0
+
#endif
diff --git a/tcg/riscv64/tcg-target-has.h b/tcg/riscv64/tcg-target-has.h
index aef10c2d9d6..93f8baad09f 100644
--- a/tcg/riscv64/tcg-target-has.h
+++ b/tcg/riscv64/tcg-target-has.h
@@ -69,4 +69,7 @@ tcg_target_sextract_valid(TCGType type, unsigned ofs,
unsigned len)
#define TCG_TARGET_deposit_valid(type, ofs, len) 0
+#define TCG_TARGET_lea_sh_valid(type, sh) 0
+#define TCG_TARGET_lea_imm_valid(type, imm) 0
+
#endif
diff --git a/tcg/s390x/tcg-target-has.h b/tcg/s390x/tcg-target-has.h
index 0aeb5ba01a9..58e3afe5266 100644
--- a/tcg/s390x/tcg-target-has.h
+++ b/tcg/s390x/tcg-target-has.h
@@ -77,4 +77,7 @@ tcg_target_sextract_valid(TCGType type, unsigned ofs,
unsigned len)
}
#define TCG_TARGET_sextract_valid tcg_target_sextract_valid
+#define TCG_TARGET_lea_sh_valid(type, sh) 0
+#define TCG_TARGET_lea_imm_valid(type, imm) 0
+
#endif
diff --git a/tcg/sparc64/tcg-target-has.h b/tcg/sparc64/tcg-target-has.h
index b29fd177f69..4182a7c1aae 100644
--- a/tcg/sparc64/tcg-target-has.h
+++ b/tcg/sparc64/tcg-target-has.h
@@ -19,4 +19,7 @@
#define TCG_TARGET_deposit_valid(type, ofs, len) 0
+#define TCG_TARGET_lea_sh_valid(type, sh) 0
+#define TCG_TARGET_lea_imm_valid(type, imm) 0
+
#endif
diff --git a/tcg/tci/tcg-target-has.h b/tcg/tci/tcg-target-has.h
index 64742cf0b71..f4f9ddf595f 100644
--- a/tcg/tci/tcg-target-has.h
+++ b/tcg/tci/tcg-target-has.h
@@ -17,4 +17,7 @@
#define TCG_TARGET_sextract_valid(type, ofs, len) 1
#define TCG_TARGET_deposit_valid(type, ofs, len) 1
+#define TCG_TARGET_lea_sh_valid(type, sh) 0
+#define TCG_TARGET_lea_imm_valid(type, imm) 0
+
#endif
diff --git a/tcg/x86_64/tcg-target-has.h b/tcg/x86_64/tcg-target-has.h
index d249c1b3e7f..6ffae51f923 100644
--- a/tcg/x86_64/tcg-target-has.h
+++ b/tcg/x86_64/tcg-target-has.h
@@ -105,4 +105,7 @@ tcg_target_extract_valid(TCGType type, unsigned ofs,
unsigned len)
}
#define TCG_TARGET_extract_valid tcg_target_extract_valid
+#define TCG_TARGET_lea_sh_valid(type, sh) 0
+#define TCG_TARGET_lea_imm_valid(type, imm) 0
+
#endif
diff --git a/tcg/tcg.c b/tcg/tcg.c
index df1590166e7..b88ee847039 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1095,6 +1095,12 @@ typedef struct TCGOutOpSubtract {
TCGReg a0, tcg_target_long a1, TCGReg a2);
} TCGOutOpSubtract;
+typedef struct TCGOutOpLea {
+ TCGOutOp base;
+ void (*out)(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
+ TCGReg a2, unsigned sh, tcg_target_long imm);
+} TCGOutOpLea;
+
#include "tcg-target.c.inc"
#ifndef CONFIG_TCG_INTERPRETER
@@ -1191,6 +1197,7 @@ static const TCGOutOp * const all_outop[NB_OPS] = {
OUTOP(INDEX_op_ld16u, TCGOutOpLoad, outop_ld16u),
OUTOP(INDEX_op_ld32s, TCGOutOpLoad, outop_ld32s),
OUTOP(INDEX_op_ld32u, TCGOutOpLoad, outop_ld32u),
+ OUTOP(INDEX_op_lea, TCGOutOpLea, outop_lea),
OUTOP(INDEX_op_movcond, TCGOutOpMovcond, outop_movcond),
OUTOP(INDEX_op_mul, TCGOutOpBinary, outop_mul),
OUTOP(INDEX_op_muls2, TCGOutOpMul2, outop_muls2),
@@ -5990,6 +5997,21 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp
*op)
}
break;
+ case INDEX_op_lea:
+ {
+ const TCGOutOpLea *out = &outop_lea;
+ int sh = new_args[3];
+ tcg_target_long imm = new_args[4];
+
+ tcg_debug_assert(!const_args[1]);
+ tcg_debug_assert(!const_args[2]);
+ tcg_debug_assert(TCG_TARGET_lea_sh_valid(type, sh));
+ tcg_debug_assert(TCG_TARGET_lea_imm_valid(type, imm));
+
+ out->out(s, type, new_args[0], new_args[1], new_args[2], sh, imm);
+ }
+ break;
+
case INDEX_op_goto_ptr:
tcg_debug_assert(!const_args[0]);
tcg_out_goto_ptr(s, new_args[0]);
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 4ebdef7e077..76adb2256f9 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -3081,6 +3081,10 @@ static const TCGOutOpStore outop_st = {
.out_r = tcg_out_st,
};
+static const TCGOutOpLea outop_lea = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
unsigned vecl, unsigned vece,
const TCGArg args[TCG_MAX_OP_ARGS],
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 69e76807d6e..17784d8bbe2 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -2098,6 +2098,10 @@ static const TCGOutOpStore outop_st = {
.out_r = tcg_out_st,
};
+static const TCGOutOpLea outop_lea = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
TCGReg rd, TCGReg rs)
{
diff --git a/tcg/ppc64/tcg-target.c.inc b/tcg/ppc64/tcg-target.c.inc
index cd1c2343672..99f4469f4b9 100644
--- a/tcg/ppc64/tcg-target.c.inc
+++ b/tcg/ppc64/tcg-target.c.inc
@@ -3633,6 +3633,9 @@ static const TCGOutOpStore outop_st = {
.out_r = tcg_out_st,
};
+static const TCGOutOpLea outop_lea = {
+ .base.static_constraint = C_NotImplemented,
+};
int tcg_can_emit_vec_op(TCGOpcode opc, TCGType type, unsigned vece)
{
diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc
index 2ce9d47a633..df4c4a9789b 100644
--- a/tcg/riscv64/tcg-target.c.inc
+++ b/tcg/riscv64/tcg-target.c.inc
@@ -2725,6 +2725,9 @@ static const TCGOutOpStore outop_st = {
.out_r = tcg_out_st,
};
+static const TCGOutOpLea outop_lea = {
+ .base.static_constraint = C_NotImplemented,
+};
static void tcg_out_vec_op(TCGContext *s, TCGOpcode opc,
unsigned vecl, unsigned vece,
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index 4d1a779c47c..2fd7012d047 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -3187,6 +3187,9 @@ static const TCGOutOpStore outop_st = {
.out_r = tcg_out_st,
};
+static const TCGOutOpLea outop_lea = {
+ .base.static_constraint = C_NotImplemented,
+};
static bool tcg_out_dup_vec(TCGContext *s, TCGType type, unsigned vece,
TCGReg dst, TCGReg src)
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index 35cd14a5b65..cb457453ff9 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -2120,6 +2120,9 @@ static const TCGOutOpStore outop_st = {
.out_r = tcg_out_st,
};
+static const TCGOutOpLea outop_lea = {
+ .base.static_constraint = C_NotImplemented,
+};
static TCGConstraintSetIndex
tcg_target_op_def(TCGOpcode op, TCGType type, unsigned flags)
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
index 4cd1c1431ce..6942fdbb4e0 100644
--- a/tcg/tci/tcg-target.c.inc
+++ b/tcg/tci/tcg-target.c.inc
@@ -1220,6 +1220,10 @@ static inline bool tcg_out_sti(TCGContext *s, TCGType
type, TCGArg val,
return false;
}
+static const TCGOutOpLea outop_lea = {
+ .base.static_constraint = C_NotImplemented,
+};
+
/* Test if a constant matches the constraint. */
static bool tcg_target_const_match(int64_t val, int ct,
TCGType type, TCGCond cond, int vece)
diff --git a/tcg/x86_64/tcg-target.c.inc b/tcg/x86_64/tcg-target.c.inc
index 2c8f1f3e580..660350b963d 100644
--- a/tcg/x86_64/tcg-target.c.inc
+++ b/tcg/x86_64/tcg-target.c.inc
@@ -3327,6 +3327,10 @@ static const TCGOutOpStore outop_st = {
.out_i = tgen_st_i,
};
+static const TCGOutOpLea outop_lea = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static int const umin_insn[4] = {
OPC_PMINUB, OPC_PMINUW, OPC_PMINUD, OPC_VPMINUQ
};
--
2.53.0