Add the plumbing, but not yet implemented for any host.
Reviewed-by: Philippe Mathieu-Daudé <[email protected]>
Signed-off-by: Richard Henderson <[email protected]>
---
include/tcg/tcg-opc.h | 3 ++
tcg/tcg-op.c | 66 +++++++++++++++++++++++++-------
tcg/tcg.c | 7 ++++
docs/devel/tcg-ops.rst | 16 ++++++++
tcg/aarch64/tcg-target.c.inc | 12 ++++++
tcg/loongarch64/tcg-target.c.inc | 12 ++++++
tcg/ppc64/tcg-target.c.inc | 12 ++++++
tcg/riscv64/tcg-target.c.inc | 12 ++++++
tcg/s390x/tcg-target.c.inc | 12 ++++++
tcg/sparc64/tcg-target.c.inc | 12 ++++++
tcg/tci/tcg-target.c.inc | 12 ++++++
tcg/x86_64/tcg-target.c.inc | 12 ++++++
12 files changed, 174 insertions(+), 14 deletions(-)
diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h
index 61f1c28858..13c7f17f76 100644
--- a/include/tcg/tcg-opc.h
+++ b/include/tcg/tcg-opc.h
@@ -79,6 +79,9 @@ DEF(or, 1, 2, 0, TCG_OPF_INT)
DEF(orc, 1, 2, 0, TCG_OPF_INT)
DEF(rems, 1, 2, 0, TCG_OPF_INT)
DEF(remu, 1, 2, 0, TCG_OPF_INT)
+DEF(revbit8, 1, 1, 0, TCG_OPF_INT)
+DEF(revbit32, 1, 1, 1, TCG_OPF_INT)
+DEF(revbit64, 1, 1, 0, TCG_OPF_INT)
DEF(rotl, 1, 2, 0, TCG_OPF_INT)
DEF(rotr, 1, 2, 0, TCG_OPF_INT)
DEF(sar, 1, 2, 0, TCG_OPF_INT)
diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c
index c24a7962fc..c302a484cd 100644
--- a/tcg/tcg-op.c
+++ b/tcg/tcg-op.c
@@ -1270,15 +1270,26 @@ void tcg_gen_hswap_i32(TCGv_i32 ret, TCGv_i32 arg)
void tcg_gen_revbit8_i32(TCGv_i32 ret, TCGv_i32 arg)
{
- gen_bitswap_i32(ret, arg, 0x55555555u);
- gen_bitswap_i32(ret, ret, 0x33333333u);
- gen_bitswap_i32(ret, ret, 0x0f0f0f0fu);
+ if (tcg_op_supported(INDEX_op_revbit8, TCG_TYPE_I32, 0)) {
+ tcg_gen_op2_i32(INDEX_op_revbit8, ret, arg);
+ } else if (tcg_op_supported(INDEX_op_revbit32, TCG_TYPE_I32, 0)) {
+ tcg_gen_op2_i32(INDEX_op_revbit32, ret, arg);
+ tcg_gen_bswap32_i32(ret, ret);
+ } else {
+ gen_bitswap_i32(ret, arg, 0x55555555u);
+ gen_bitswap_i32(ret, ret, 0x33333333u);
+ gen_bitswap_i32(ret, ret, 0x0f0f0f0fu);
+ }
}
void tcg_gen_revbit32_i32(TCGv_i32 ret, TCGv_i32 arg)
{
- tcg_gen_revbit8_i32(ret, arg);
- tcg_gen_bswap32_i32(ret, ret);
+ if (tcg_op_supported(INDEX_op_revbit32, TCG_TYPE_I32, 0)) {
+ tcg_gen_op3i_i32(INDEX_op_revbit32, ret, arg, 0);
+ } else {
+ tcg_gen_revbit8_i32(ret, arg);
+ tcg_gen_bswap32_i32(ret, ret);
+ }
}
void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b)
@@ -1870,23 +1881,50 @@ void tcg_gen_revbit32_i64(TCGv_i64 ret, TCGv_i64 arg,
int flags)
/* Only one extension flag may be present. */
tcg_debug_assert(!(flags & TCG_BSWAP_OS) || !(flags & TCG_BSWAP_OZ));
- gen_bitswap_i64(ret, arg, 0x55555555ull);
- gen_bitswap_i64(ret, ret, 0x33333333ull);
- gen_bitswap_i64(ret, ret, 0x0f0f0f0full);
- tcg_gen_bswap32_i64(ret, ret, flags | TCG_BSWAP_IZ);
+ if (tcg_op_supported(INDEX_op_revbit32, TCG_TYPE_I64, 0)) {
+ tcg_gen_op3i_i64(INDEX_op_revbit32, ret, arg, flags);
+ } else if (tcg_op_supported(INDEX_op_revbit64, TCG_TYPE_I64, 0)) {
+ tcg_gen_op2_i64(INDEX_op_revbit64, ret, arg);
+ if (flags & TCG_BSWAP_OS) {
+ tcg_gen_sari_i64(ret, ret, 32);
+ } else {
+ tcg_gen_shri_i64(ret, ret, 32);
+ }
+ } else {
+ if (tcg_op_supported(INDEX_op_revbit8, TCG_TYPE_I64, 0)) {
+ tcg_gen_op2_i64(INDEX_op_revbit8, ret, arg);
+ } else {
+ gen_bitswap_i64(ret, arg, 0x55555555ull);
+ gen_bitswap_i64(ret, ret, 0x33333333ull);
+ gen_bitswap_i64(ret, ret, 0x0f0f0f0full);
+ flags |= TCG_BSWAP_IZ;
+ }
+ tcg_gen_bswap32_i64(ret, ret, flags);
+ }
}
void tcg_gen_revbit8_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- gen_bitswap_i64(ret, arg, 0x5555555555555555ull);
- gen_bitswap_i64(ret, ret, 0x3333333333333333ull);
- gen_bitswap_i64(ret, ret, 0x0f0f0f0f0f0f0f0full);
+ if (tcg_op_supported(INDEX_op_revbit8, TCG_TYPE_I64, 0)) {
+ tcg_gen_op2_i64(INDEX_op_revbit8, ret, arg);
+ } else if (tcg_op_supported(INDEX_op_revbit64, TCG_TYPE_I64, 0)) {
+ tcg_gen_op2_i64(INDEX_op_revbit64, ret, arg);
+ tcg_gen_bswap64_i64(ret, ret);
+ } else {
+ gen_bitswap_i64(ret, arg, 0x5555555555555555ull);
+ gen_bitswap_i64(ret, ret, 0x3333333333333333ull);
+ gen_bitswap_i64(ret, ret, 0x0f0f0f0f0f0f0f0full);
+ }
}
void tcg_gen_revbit64_i64(TCGv_i64 ret, TCGv_i64 arg)
{
- tcg_gen_revbit8_i64(ret, arg);
- tcg_gen_bswap64_i64(ret, ret);
+ if (tcg_op_supported(INDEX_op_revbit64, TCG_TYPE_I64, 0)) {
+ tcg_gen_op2_i64(INDEX_op_revbit64, ret, arg);
+ } else {
+ tcg_gen_revbit8_i64(ret, arg);
+ tcg_gen_bswap64_i64(ret, ret);
+ }
}
void tcg_gen_not_i64(TCGv_i64 ret, TCGv_i64 arg)
diff --git a/tcg/tcg.c b/tcg/tcg.c
index 937d0c8fd7..8a324ce885 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -1203,6 +1203,7 @@ static const TCGOutOp * const all_outop[NB_OPS] = {
OUTOP(INDEX_op_qemu_st2, TCGOutOpQemuLdSt2, outop_qemu_st2),
OUTOP(INDEX_op_rems, TCGOutOpBinary, outop_rems),
OUTOP(INDEX_op_remu, TCGOutOpBinary, outop_remu),
+ OUTOP(INDEX_op_revbit32, TCGOutOpBswap, outop_revbit32),
OUTOP(INDEX_op_rotl, TCGOutOpBinary, outop_rotl),
OUTOP(INDEX_op_rotr, TCGOutOpBinary, outop_rotr),
OUTOP(INDEX_op_sar, TCGOutOpBinary, outop_sar),
@@ -1230,6 +1231,8 @@ static const TCGOutOp * const all_outop[NB_OPS] = {
OUTOP(INDEX_op_extrh_i64_i32, TCGOutOpUnary, outop_extrh_i64_i32),
OUTOP(INDEX_op_ld32u, TCGOutOpLoad, outop_ld32u),
OUTOP(INDEX_op_ld32s, TCGOutOpLoad, outop_ld32s),
+ OUTOP(INDEX_op_revbit8, TCGOutOpUnary, outop_revbit8),
+ OUTOP(INDEX_op_revbit64, TCGOutOpUnary, outop_revbit64),
OUTOP(INDEX_op_st32, TCGOutOpStore, outop_st),
};
@@ -2950,6 +2953,7 @@ void tcg_dump_ops(TCGContext *s, FILE *f, bool have_prefs)
case INDEX_op_bswap16:
case INDEX_op_bswap32:
case INDEX_op_bswap64:
+ case INDEX_op_revbit32:
{
TCGArg flags = op->args[k];
const char *name = NULL;
@@ -5581,6 +5585,8 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp
*op)
case INDEX_op_ctpop:
case INDEX_op_neg:
case INDEX_op_not:
+ case INDEX_op_revbit8:
+ case INDEX_op_revbit64:
{
const TCGOutOpUnary *out =
container_of(all_outop[op->opc], TCGOutOpUnary, base);
@@ -5593,6 +5599,7 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp
*op)
case INDEX_op_bswap16:
case INDEX_op_bswap32:
+ case INDEX_op_revbit32:
{
const TCGOutOpBswap *out =
container_of(all_outop[op->opc], TCGOutOpBswap, base);
diff --git a/docs/devel/tcg-ops.rst b/docs/devel/tcg-ops.rst
index 92ef127c80..f2e9255dd9 100644
--- a/docs/devel/tcg-ops.rst
+++ b/docs/devel/tcg-ops.rst
@@ -495,6 +495,22 @@ Misc
into 32-bit output *t0*. Depending on the host, this may be a simple
shift,
or may require additional canonicalization.
+ * - revbit8 *dest*, *t1*
+
+ - | Reverse the 8 bits within each byte of input *t1* with
+ | output in *dest*; the byte order is unchanged.
+
+ * - revbit32 *dest*, *t1*, *flags*
+
+ - | Reverse the 32 bits of the lower 32 bits of input *t1*
+ | with output in *dest*. On TCG_TYPE_I64, *flags* control
+ | any required sign or zero extension of the result in
+ | the same way as for bswap32.
+ | On TCG_TYPE_I32, *flags* should be zero.
+
+ * - revbit64 *dest*, *t1*
+
+ - | Reverse the 64 bits of input *t1* with output in *dest*.
Conditional moves
-----------------
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index cc9c2a5158..0afa988087 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -2652,6 +2652,18 @@ static const TCGOutOpUnary outop_bswap64 = {
.out_rr = tgen_bswap64,
};
+static const TCGOutOpUnary outop_revbit8 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBswap outop_revbit32 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpUnary outop_revbit64 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
{
tgen_sub(s, type, a0, TCG_REG_XZR, a1);
diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc
index 182dcfd5eb..97ed51d99c 100644
--- a/tcg/loongarch64/tcg-target.c.inc
+++ b/tcg/loongarch64/tcg-target.c.inc
@@ -1866,6 +1866,18 @@ static const TCGOutOpUnary outop_bswap64 = {
.out_rr = tgen_bswap64,
};
+static const TCGOutOpUnary outop_revbit8 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBswap outop_revbit32 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpUnary outop_revbit64 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
{
tgen_sub(s, type, a0, TCG_REG_ZERO, a1);
diff --git a/tcg/ppc64/tcg-target.c.inc b/tcg/ppc64/tcg-target.c.inc
index b54afa0b6d..07dff67e84 100644
--- a/tcg/ppc64/tcg-target.c.inc
+++ b/tcg/ppc64/tcg-target.c.inc
@@ -3421,6 +3421,18 @@ static const TCGOutOpUnary outop_bswap64 = {
.out_rr = tgen_bswap64,
};
+static const TCGOutOpUnary outop_revbit8 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBswap outop_revbit32 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpUnary outop_revbit64 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
{
tcg_out32(s, NEG | RT(a0) | RA(a1));
diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc
index 76dd4fca97..687146e0b0 100644
--- a/tcg/riscv64/tcg-target.c.inc
+++ b/tcg/riscv64/tcg-target.c.inc
@@ -2469,6 +2469,18 @@ static const TCGOutOpUnary outop_bswap64 = {
.out_rr = tgen_bswap64,
};
+static const TCGOutOpUnary outop_revbit8 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBswap outop_revbit32 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpUnary outop_revbit64 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
{
tgen_sub(s, type, a0, TCG_REG_ZERO, a1);
diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc
index 84a9e73a46..c481745c3f 100644
--- a/tcg/s390x/tcg-target.c.inc
+++ b/tcg/s390x/tcg-target.c.inc
@@ -3020,6 +3020,18 @@ static const TCGOutOpUnary outop_bswap64 = {
.out_rr = tgen_bswap64,
};
+static const TCGOutOpUnary outop_revbit8 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBswap outop_revbit32 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpUnary outop_revbit64 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
{
if (type == TCG_TYPE_I32) {
diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc
index 5e5c3f1cda..d6ed9d3362 100644
--- a/tcg/sparc64/tcg-target.c.inc
+++ b/tcg/sparc64/tcg-target.c.inc
@@ -1947,6 +1947,18 @@ static const TCGOutOpUnary outop_bswap64 = {
.base.static_constraint = C_NotImplemented,
};
+static const TCGOutOpUnary outop_revbit8 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBswap outop_revbit32 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpUnary outop_revbit64 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
{
tgen_sub(s, type, a0, TCG_REG_G0, a1);
diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc
index 1b22c70616..1b61668517 100644
--- a/tcg/tci/tcg-target.c.inc
+++ b/tcg/tci/tcg-target.c.inc
@@ -959,6 +959,18 @@ static const TCGOutOpUnary outop_bswap64 = {
.out_rr = tgen_bswap64,
};
+static const TCGOutOpUnary outop_revbit8 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBswap outop_revbit32 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpUnary outop_revbit64 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static void tgen_neg(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
{
tcg_out_op_rr(s, INDEX_op_neg, a0, a1);
diff --git a/tcg/x86_64/tcg-target.c.inc b/tcg/x86_64/tcg-target.c.inc
index 1fc45e4ec6..37acba9045 100644
--- a/tcg/x86_64/tcg-target.c.inc
+++ b/tcg/x86_64/tcg-target.c.inc
@@ -1290,6 +1290,18 @@ static inline void tcg_out_bswap64(TCGContext *s, int
reg)
tcg_out_opc(s, OPC_BSWAP + P_REXW + LOWREGMASK(reg), 0, reg, 0);
}
+static const TCGOutOpUnary outop_revbit8 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpBswap outop_revbit32 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
+static const TCGOutOpUnary outop_revbit64 = {
+ .base.static_constraint = C_NotImplemented,
+};
+
static void tgen_arithi(TCGContext *s, int c, int r0,
tcg_target_long val, int cf)
{
--
2.43.0