[PULL 23/38] tcg: Add integer min/max opcodes
Richard Henderson <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
We already have these for vectors; replicate for integers. Reviewed-by: Alex Bennée <[email protected]> Signed-off-by: Richard Henderson <[email protected]> --- include/tcg/tcg-opc.h | 4 +++ tcg/tcg-op.c | 48 ++++++++++++++++++++++++++------ tcg/tcg.c | 8 ++++++ docs/devel/tcg-ops.rst | 12 ++++++++ tcg/aarch64/tcg-target.c.inc | 16 +++++++++++ tcg/loongarch64/tcg-target.c.inc | 16 +++++++++++ tcg/ppc64/tcg-target.c.inc | 16 +++++++++++ tcg/riscv64/tcg-target.c.inc | 16 +++++++++++ tcg/s390x/tcg-target.c.inc | 16 +++++++++++ tcg/sparc64/tcg-target.c.inc | 16 +++++++++++ tcg/tci/tcg-target.c.inc | 16 +++++++++++ tcg/x86_64/tcg-target.c.inc | 16 +++++++++++ 12 files changed, 192 insertions(+), 8 deletions(-) diff --git a/include/tcg/tcg-opc.h b/include/tcg/tcg-opc.h index 13c7f17f76..f3a81d5d7f 100644 --- a/include/tcg/tcg-opc.h +++ b/include/tcg/tcg-opc.h @@ -89,11 +89,15 @@ DEF(setcond, 1, 2, 1, TCG_OPF_INT) DEF(sextract, 1, 1, 2, TCG_OPF_INT) DEF(shl, 1, 2, 0, TCG_OPF_INT) DEF(shr, 1, 2, 0, TCG_OPF_INT) +DEF(smax, 1, 2, 0, TCG_OPF_INT) +DEF(smin, 1, 2, 0, TCG_OPF_INT) DEF(st8, 0, 2, 1, TCG_OPF_INT) DEF(st16, 0, 2, 1, TCG_OPF_INT) DEF(st32, 0, 2, 1, TCG_OPF_INT) DEF(st, 0, 2, 1, TCG_OPF_INT) DEF(sub, 1, 2, 0, TCG_OPF_INT) +DEF(umax, 1, 2, 0, TCG_OPF_INT) +DEF(umin, 1, 2, 0, TCG_OPF_INT) DEF(xor, 1, 2, 0, TCG_OPF_INT) DEF(addco, 1, 2, 0, TCG_OPF_INT | TCG_OPF_CARRY_OUT) diff --git a/tcg/tcg-op.c b/tcg/tcg-op.c index c302a484cd..e28944cf72 100644 --- a/tcg/tcg-op.c +++ b/tcg/tcg-op.c @@ -1294,22 +1294,38 @@ void tcg_gen_revbit32_i32(TCGv_i32 ret, TCGv_i32 arg) void tcg_gen_smin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) { - tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b); + if (tcg_op_supported(INDEX_op_smin, TCG_TYPE_I32, 0)) { + tcg_gen_op3_i32(INDEX_op_smin, ret, a, b); + } else { + tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, a, b); + } } void tcg_gen_umin_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) { - tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b); + if (tcg_op_supported(INDEX_op_umin, TCG_TYPE_I32, 0)) { + tcg_gen_op3_i32(INDEX_op_umin, ret, a, b); + } else { + tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, a, b); + } } void tcg_gen_smax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) { - tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a); + if (tcg_op_supported(INDEX_op_smax, TCG_TYPE_I32, 0)) { + tcg_gen_op3_i32(INDEX_op_smax, ret, a, b); + } else { + tcg_gen_movcond_i32(TCG_COND_LT, ret, a, b, b, a); + } } void tcg_gen_umax_i32(TCGv_i32 ret, TCGv_i32 a, TCGv_i32 b) { - tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a); + if (tcg_op_supported(INDEX_op_umax, TCG_TYPE_I32, 0)) { + tcg_gen_op3_i32(INDEX_op_umax, ret, a, b); + } else { + tcg_gen_movcond_i32(TCG_COND_LTU, ret, a, b, b, a); + } } void tcg_gen_abs_i32(TCGv_i32 ret, TCGv_i32 a) @@ -2473,22 +2489,38 @@ void tcg_gen_mulsu2_i64(TCGv_i64 rl, TCGv_i64 rh, TCGv_i64 arg1, TCGv_i64 arg2) void tcg_gen_smin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) { - tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b); + if (tcg_op_supported(INDEX_op_smin, TCG_TYPE_I64, 0)) { + tcg_gen_op3_i64(INDEX_op_smin, ret, a, b); + } else { + tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, a, b); + } } void tcg_gen_umin_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) { - tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b); + if (tcg_op_supported(INDEX_op_umin, TCG_TYPE_I64, 0)) { + tcg_gen_op3_i64(INDEX_op_umin, ret, a, b); + } else { + tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, a, b); + } } void tcg_gen_smax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) { - tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a); + if (tcg_op_supported(INDEX_op_smax, TCG_TYPE_I64, 0)) { + tcg_gen_op3_i64(INDEX_op_smax, ret, a, b); + } else { + tcg_gen_movcond_i64(TCG_COND_LT, ret, a, b, b, a); + } } void tcg_gen_umax_i64(TCGv_i64 ret, TCGv_i64 a, TCGv_i64 b) { - tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a); + if (tcg_op_supported(INDEX_op_umax, TCG_TYPE_I64, 0)) { + tcg_gen_op3_i64(INDEX_op_umax, ret, a, b); + } else { + tcg_gen_movcond_i64(TCG_COND_LTU, ret, a, b, b, a); + } } void tcg_gen_abs_i64(TCGv_i64 ret, TCGv_i64 a) diff --git a/tcg/tcg.c b/tcg/tcg.c index 8a324ce885..489df0e738 100644 --- a/tcg/tcg.c +++ b/tcg/tcg.c @@ -1211,6 +1211,8 @@ static const TCGOutOp * const all_outop[NB_OPS] = { OUTOP(INDEX_op_sextract, TCGOutOpExtract, outop_sextract), OUTOP(INDEX_op_shl, TCGOutOpBinary, outop_shl), OUTOP(INDEX_op_shr, TCGOutOpBinary, outop_shr), + OUTOP(INDEX_op_smax, TCGOutOpBinary, outop_smax), + OUTOP(INDEX_op_smin, TCGOutOpBinary, outop_smin), OUTOP(INDEX_op_st, TCGOutOpStore, outop_st), OUTOP(INDEX_op_st8, TCGOutOpStore, outop_st8), OUTOP(INDEX_op_st16, TCGOutOpStore, outop_st16), @@ -1220,6 +1222,8 @@ static const TCGOutOp * const all_outop[NB_OPS] = { OUTOP(INDEX_op_subbo, TCGOutOpAddSubCarry, outop_subbo), /* subb1o is implemented with set_borrow + subbio */ OUTOP(INDEX_op_subb1o, TCGOutOpAddSubCarry, outop_subbio), + OUTOP(INDEX_op_umax, TCGOutOpBinary, outop_umax), + OUTOP(INDEX_op_umin, TCGOutOpBinary, outop_umin), OUTOP(INDEX_op_xor, TCGOutOpBinary, outop_xor), [INDEX_op_goto_ptr] = &outop_goto_ptr, @@ -5518,6 +5522,10 @@ static void tcg_reg_alloc_op(TCGContext *s, const TCGOp *op) case INDEX_op_sar: case INDEX_op_shl: case INDEX_op_shr: + case INDEX_op_smax: + case INDEX_op_smin: + case INDEX_op_umax: + case INDEX_op_umin: case INDEX_op_xor: { const TCGOutOpBinary *out = diff --git a/docs/devel/tcg-ops.rst b/docs/devel/tcg-ops.rst index f2e9255dd9..88d48a1f99 100644 --- a/docs/devel/tcg-ops.rst +++ b/docs/devel/tcg-ops.rst @@ -317,6 +317,18 @@ Arithmetic pass 0 to *nh* to make a simple zero-extension of *nl*, so overflow should never occur. + * - smax *t0*, *t1*, *t2* + + umax *t0*, *t1*, *t2* + + - | *t0* = MAX(*t1*, *t2*), for signed and unsigned integers. + + * - smin *t0*, *t1*, *t2* + + umin *t0*, *t1*, *t2* + + - | *t0* = MIN(*t1*, *t2*), for signed and unsigned integers. + Logical ------- diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc index 80995403e4..f5c185bbf4 100644 --- a/tcg/aarch64/tcg-target.c.inc +++ b/tcg/aarch64/tcg-target.c.inc @@ -2592,6 +2592,22 @@ static void tcg_out_set_borrow(TCGContext *s) TCG_REG_XZR, TCG_REG_XZR, TCG_REG_XZR); } +static const TCGOutOpBinary outop_smax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_smin = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umin = { + .base.static_constraint = C_NotImplemented, +}; + static void tgen_xor(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, TCGReg a2) { diff --git a/tcg/loongarch64/tcg-target.c.inc b/tcg/loongarch64/tcg-target.c.inc index 7d89e80886..f65496a040 100644 --- a/tcg/loongarch64/tcg-target.c.inc +++ b/tcg/loongarch64/tcg-target.c.inc @@ -1804,6 +1804,22 @@ static void tcg_out_set_borrow(TCGContext *s) g_assert_not_reached(); } +static const TCGOutOpBinary outop_smax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_smin = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umin = { + .base.static_constraint = C_NotImplemented, +}; + static void tgen_xor(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, TCGReg a2) { diff --git a/tcg/ppc64/tcg-target.c.inc b/tcg/ppc64/tcg-target.c.inc index 07dff67e84..cd1c234367 100644 --- a/tcg/ppc64/tcg-target.c.inc +++ b/tcg/ppc64/tcg-target.c.inc @@ -3281,6 +3281,22 @@ static void tcg_out_set_borrow(TCGContext *s) tcg_out32(s, ADDIC | TAI(TCG_REG_R0, TCG_REG_R0, 0)); } +static const TCGOutOpBinary outop_smax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_smin = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umin = { + .base.static_constraint = C_NotImplemented, +}; + static void tgen_xor(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, TCGReg a2) { diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc index 8fd32644fe..723c21b3da 100644 --- a/tcg/riscv64/tcg-target.c.inc +++ b/tcg/riscv64/tcg-target.c.inc @@ -2404,6 +2404,22 @@ static void tcg_out_set_borrow(TCGContext *s) g_assert_not_reached(); } +static const TCGOutOpBinary outop_smax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_smin = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umin = { + .base.static_constraint = C_NotImplemented, +}; + static void tgen_xor(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, TCGReg a2) { diff --git a/tcg/s390x/tcg-target.c.inc b/tcg/s390x/tcg-target.c.inc index c481745c3f..4d1a779c47 100644 --- a/tcg/s390x/tcg-target.c.inc +++ b/tcg/s390x/tcg-target.c.inc @@ -2950,6 +2950,22 @@ static void tcg_out_set_borrow(TCGContext *s) tcg_out_insn(s, RR, CLR, TCG_REG_R0, TCG_REG_R0); /* cc = 0 */ } +static const TCGOutOpBinary outop_smax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_smin = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umin = { + .base.static_constraint = C_NotImplemented, +}; + static void tgen_xor(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, TCGReg a2) { diff --git a/tcg/sparc64/tcg-target.c.inc b/tcg/sparc64/tcg-target.c.inc index d6ed9d3362..35cd14a5b6 100644 --- a/tcg/sparc64/tcg-target.c.inc +++ b/tcg/sparc64/tcg-target.c.inc @@ -1917,6 +1917,22 @@ static void tcg_out_set_borrow(TCGContext *s) tcg_out_set_carry(s); /* borrow == carry */ } +static const TCGOutOpBinary outop_smax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_smin = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umin = { + .base.static_constraint = C_NotImplemented, +}; + static void tgen_xor(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, TCGReg a2) { diff --git a/tcg/tci/tcg-target.c.inc b/tcg/tci/tcg-target.c.inc index 1b61668517..4cd1c1431c 100644 --- a/tcg/tci/tcg-target.c.inc +++ b/tcg/tci/tcg-target.c.inc @@ -894,6 +894,22 @@ static void tcg_out_set_borrow(TCGContext *s) tcg_out_op_v(s, INDEX_op_tci_setcarry); /* borrow == carry */ } +static const TCGOutOpBinary outop_smax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_smin = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umin = { + .base.static_constraint = C_NotImplemented, +}; + static void tgen_xor(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, TCGReg a2) { diff --git a/tcg/x86_64/tcg-target.c.inc b/tcg/x86_64/tcg-target.c.inc index 37acba9045..2c8f1f3e58 100644 --- a/tcg/x86_64/tcg-target.c.inc +++ b/tcg/x86_64/tcg-target.c.inc @@ -2977,6 +2977,22 @@ static void tcg_out_set_borrow(TCGContext *s) tcg_out8(s, OPC_STC); } +static const TCGOutOpBinary outop_smax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_smin = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umax = { + .base.static_constraint = C_NotImplemented, +}; + +static const TCGOutOpBinary outop_umin = { + .base.static_constraint = C_NotImplemented, +}; + static void tgen_xor(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1, TCGReg a2) { -- 2.43.0