[PULL 14/38] tcg: Add revbit{8,32,64} opcodes
Richard Henderson <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
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