* [PATCH 0/7] tcg: Add min/max opcodes
@ 2026-08-12 0:31 Richard Henderson
2026-08-12 0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
` (6 more replies)
0 siblings, 7 replies; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 0:31 UTC (permalink / raw)
To: qemu-devel
Since two hosts now have (optional) support for min/max,
I thought it might be worth implementing natively.
While I was there, use some more of the FEAT_CSSC extension.
r~
Richard Henderson (7):
tcg: Add integer min/max opcodes
tcg/optimize: Handle min/max opcodes
util/cpuinfo-aarch64: Detect FEAT_CSSC
tcg/aarch64: Implement min/max with FEAT_CSSC
target/riscv64: Implement min/max with Zbb
tcg/aarch64: Implement ctpop with FEAT_CSSC
tcg/aarch64: Use CTZ from FEAT_CSSC
host/include/aarch64/host/cpuinfo.h | 1 +
include/tcg/tcg-opc.h | 4 +
tcg/aarch64/tcg-target-con-set.h | 2 +
tcg/aarch64/tcg-target-con-str.h | 2 +
tcg/optimize.c | 52 +++++++++
tcg/tcg-op.c | 48 ++++++--
tcg/tcg.c | 4 +
util/cpuinfo-aarch64.c | 13 ++-
docs/devel/tcg-ops.rst | 14 ++-
tcg/aarch64/tcg-target.c.inc | 169 ++++++++++++++++++++++++++--
tcg/loongarch64/tcg-target.c.inc | 16 +++
tcg/ppc64/tcg-target.c.inc | 16 +++
tcg/riscv64/tcg-target.c.inc | 52 +++++++++
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 +++
17 files changed, 435 insertions(+), 22 deletions(-)
--
2.43.0
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH 1/7] tcg: Add integer min/max opcodes
2026-08-12 0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
@ 2026-08-12 0:31 ` Richard Henderson
2026-08-12 8:42 ` Alex Bennée
2026-08-12 0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
` (5 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 0:31 UTC (permalink / raw)
To: qemu-devel
We already have these for vectors; replicate for integers.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
include/tcg/tcg-opc.h | 4 +++
tcg/tcg-op.c | 48 ++++++++++++++++++++++++++------
tcg/tcg.c | 4 +++
docs/devel/tcg-ops.rst | 14 +++++++++-
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, 189 insertions(+), 9 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 4c2207c6af..54f7906cb7 100644
--- a/tcg/tcg.c
+++ b/tcg/tcg.c
@@ -5512,6 +5512,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..d30db9ea65 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
-------
@@ -512,7 +524,7 @@ Misc
- | Reverse the 64 bits of input *t1* with output in *dest*.
-Conditional moves
+Conditional motes
-----------------
.. list-table::
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
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 2/7] tcg/optimize: Handle min/max opcodes
2026-08-12 0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
2026-08-12 0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
@ 2026-08-12 0:31 ` Richard Henderson
2026-08-12 7:17 ` Philippe Mathieu-Daudé
2026-08-12 8:46 ` Alex Bennée
2026-08-12 0:31 ` [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC Richard Henderson
` (4 subsequent siblings)
6 siblings, 2 replies; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 0:31 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/optimize.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
1 file changed, 52 insertions(+)
diff --git a/tcg/optimize.c b/tcg/optimize.c
index facf4c1e0f..d291c844ca 100644
--- a/tcg/optimize.c
+++ b/tcg/optimize.c
@@ -597,6 +597,30 @@ static uint64_t do_constant_folding_2(TCGOpcode op, TCGType type,
}
return (uint64_t)x % ((uint64_t)y ? : 1);
+ case INDEX_op_smax:
+ if (type == TCG_TYPE_I32) {
+ return MAX((int32_t)x, (int32_t)y);
+ }
+ return MAX((int64_t)x, (int64_t)y);
+
+ case INDEX_op_smin:
+ if (type == TCG_TYPE_I32) {
+ return MIN((int32_t)x, (int32_t)y);
+ }
+ return MIN((int64_t)x, (int64_t)y);
+
+ case INDEX_op_umax:
+ if (type == TCG_TYPE_I32) {
+ return MAX((uint32_t)x, (uint32_t)y);
+ }
+ return MAX((uint64_t)x, (uint64_t)y);
+
+ case INDEX_op_umin:
+ if (type == TCG_TYPE_I32) {
+ return MIN((uint32_t)x, (uint32_t)y);
+ }
+ return MIN((uint64_t)x, (uint64_t)y);
+
default:
g_assert_not_reached();
}
@@ -2101,6 +2125,16 @@ static bool fold_mb(OptContext *ctx, TCGOp *op)
return true;
}
+static bool fold_minmax(OptContext *ctx, TCGOp *op, uint64_t bound)
+{
+ if (fold_const2_commutative(ctx, op) ||
+ fold_xi_to_i(ctx, op, bound) ||
+ fold_xx_to_x(ctx, op)) {
+ return true;
+ }
+ return finish_folding(ctx, op);
+}
+
static bool fold_mov(OptContext *ctx, TCGOp *op)
{
return tcg_opt_gen_mov(ctx, op, op->args[0], op->args[1]);
@@ -3258,6 +3292,14 @@ void tcg_optimize(TCGContext *s)
case INDEX_op_sextract:
done = fold_sextract(&ctx, op);
break;
+ case INDEX_op_smax:
+ done = fold_minmax(&ctx, op, (ctx.type == TCG_TYPE_I32
+ ? INT32_MAX : INT64_MAX));
+ break;
+ case INDEX_op_smin:
+ done = fold_minmax(&ctx, op, (ctx.type == TCG_TYPE_I32
+ ? INT32_MIN : INT64_MIN));
+ break;
case INDEX_op_sub:
done = fold_sub(&ctx, op);
break;
@@ -3273,6 +3315,16 @@ void tcg_optimize(TCGContext *s)
case INDEX_op_sub_vec:
done = fold_sub_vec(&ctx, op);
break;
+ case INDEX_op_umax:
+ /*
+ * Note that 32-bit constants are stored sign extended,
+ * so (int32_t)UINT32_MAX == -1.
+ */
+ done = fold_minmax(&ctx, op, -1);
+ break;
+ case INDEX_op_umin:
+ done = fold_minmax(&ctx, op, 0);
+ break;
case INDEX_op_xor:
case INDEX_op_xor_vec:
done = fold_xor(&ctx, op);
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC
2026-08-12 0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
2026-08-12 0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
2026-08-12 0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
@ 2026-08-12 0:31 ` Richard Henderson
2026-08-12 3:35 ` Brad Smith
2026-08-12 0:31 ` [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC Richard Henderson
` (3 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 0:31 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
host/include/aarch64/host/cpuinfo.h | 1 +
util/cpuinfo-aarch64.c | 13 ++++++++++++-
2 files changed, 13 insertions(+), 1 deletion(-)
diff --git a/host/include/aarch64/host/cpuinfo.h b/host/include/aarch64/host/cpuinfo.h
index fe671534e4..c32c04dade 100644
--- a/host/include/aarch64/host/cpuinfo.h
+++ b/host/include/aarch64/host/cpuinfo.h
@@ -12,6 +12,7 @@
#define CPUINFO_AES (1u << 3)
#define CPUINFO_PMULL (1u << 4)
#define CPUINFO_BTI (1u << 5)
+#define CPUINFO_CSSC (1u << 6)
/* Initialized with a constructor. */
extern unsigned cpuinfo;
diff --git a/util/cpuinfo-aarch64.c b/util/cpuinfo-aarch64.c
index 288074c08f..0b4f8a747d 100644
--- a/util/cpuinfo-aarch64.c
+++ b/util/cpuinfo-aarch64.c
@@ -72,6 +72,7 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2);
info |= (hwcap2 & HWCAP2_BTI ? CPUINFO_BTI : 0);
+ info |= (hwcap2 & HWCAP2_CSSC ? CPUINFO_CSSC : 0);
#endif
#ifdef CONFIG_DARWIN
info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
@@ -79,10 +80,11 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
info |= sysctl_for_bool("hw.optional.arm.FEAT_AES") * CPUINFO_AES;
info |= sysctl_for_bool("hw.optional.arm.FEAT_PMULL") * CPUINFO_PMULL;
info |= sysctl_for_bool("hw.optional.arm.FEAT_BTI") * CPUINFO_BTI;
+ info |= sysctl_for_bool("hw.optional.arm.FEAT_CSSC") * CPUINFO_CSSC;
#endif
#if defined(__OpenBSD__) && !defined(CONFIG_ELF_AUX_INFO)
int mib[2];
- uint64_t isar0;
+ uint64_t isar0, isar2;
uint64_t pfr1;
size_t len;
@@ -101,6 +103,15 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
}
}
+ mib[0] = CTL_MACHDEP;
+ mib[1] = CPU_ID_AA64ISAR2;
+ len = sizeof(isar2);
+ if (sysctl(mib, 2, &isar2, &len, NULL, 0) != -1) {
+ if (ID_AA64ISAR2_CSSC(isar2) >= ID_AA64ISAR2_CSSC_IMPL) {
+ info |= CPUINFO_CSSC;
+ }
+ }
+
mib[0] = CTL_MACHDEP;
mib[1] = CPU_ID_AA64PFR1;
len = sizeof(pfr1);
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC
2026-08-12 0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
` (2 preceding siblings ...)
2026-08-12 0:31 ` [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC Richard Henderson
@ 2026-08-12 0:31 ` Richard Henderson
2026-08-12 7:15 ` Philippe Mathieu-Daudé
2026-08-12 0:31 ` [PATCH 5/7] target/riscv64: Implement min/max with Zbb Richard Henderson
` (2 subsequent siblings)
6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 0:31 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/aarch64/tcg-target-con-set.h | 2 +
tcg/aarch64/tcg-target-con-str.h | 2 +
tcg/aarch64/tcg-target.c.inc | 103 +++++++++++++++++++++++++++++--
3 files changed, 103 insertions(+), 4 deletions(-)
diff --git a/tcg/aarch64/tcg-target-con-set.h b/tcg/aarch64/tcg-target-con-set.h
index d0622e65fb..dd84a9af58 100644
--- a/tcg/aarch64/tcg-target-con-set.h
+++ b/tcg/aarch64/tcg-target-con-set.h
@@ -24,6 +24,8 @@ C_O1_I2(r, r, rAL)
C_O1_I2(r, r, rC)
C_O1_I2(r, r, ri)
C_O1_I2(r, r, rL)
+C_O1_I2(r, r, rS)
+C_O1_I2(r, r, rU)
C_O1_I2(r, rZ, rA)
C_O1_I2(r, rz, rMZ)
C_O1_I2(r, rz, rz)
diff --git a/tcg/aarch64/tcg-target-con-str.h b/tcg/aarch64/tcg-target-con-str.h
index 48e1722c68..fef75e8a76 100644
--- a/tcg/aarch64/tcg-target-con-str.h
+++ b/tcg/aarch64/tcg-target-con-str.h
@@ -21,4 +21,6 @@ CONST('L', TCG_CT_CONST_LIMM)
CONST('M', TCG_CT_CONST_MONE)
CONST('O', TCG_CT_CONST_ORRI)
CONST('N', TCG_CT_CONST_ANDI)
+CONST('S', TCG_CT_CONST_S8)
+CONST('U', TCG_CT_CONST_U8)
CONST('Z', TCG_CT_CONST_ZERO)
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index f5c185bbf4..55b3be0b96 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -152,6 +152,8 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
#define TCG_CT_CONST_ORRI 0x1000
#define TCG_CT_CONST_ANDI 0x2000
#define TCG_CT_CONST_CMP 0x4000
+#define TCG_CT_CONST_S8 0x8000
+#define TCG_CT_CONST_U8 0x10000
#define ALL_GENERAL_REGS 0xffffffffu
#define ALL_VECTOR_REGS 0xffffffff00000000ull
@@ -320,6 +322,12 @@ static bool tcg_target_const_match(int64_t val, int ct,
if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) {
return 1;
}
+ if ((ct & TCG_CT_CONST_S8) && val == (int8_t)val) {
+ return 1;
+ }
+ if ((ct & TCG_CT_CONST_U8) && val == (uint8_t)val) {
+ return 1;
+ }
if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
return 1;
}
@@ -472,6 +480,12 @@ typedef enum {
Iaddsub_imm_SUBI = 0x51000000,
Iaddsub_imm_SUBSI = 0x71000000,
+ /* Min/max immediate instructions. */
+ Iminmax_imm_SMAXI = 0x11c00000,
+ Iminmax_imm_UMAXI = 0x11c40000,
+ Iminmax_imm_SMINI = 0x11c80000,
+ Iminmax_imm_UMINI = 0x11cc0000,
+
/* Bitfield instructions. */
Ibitfield_BFM = 0x33000000,
Ibitfield_SBFM = 0x13000000,
@@ -533,6 +547,10 @@ typedef enum {
Irrr_UMULH = 0x9bc07c00,
Irrr_UDIV = 0x1ac00800,
Irrr_SDIV = 0x1ac00c00,
+ Irrr_SMAX = 0x1ac00600,
+ Irrr_UMAX = 0x1ac00640,
+ Irrr_SMIN = 0x1ac00680,
+ Irrr_UMIN = 0x1ac006c0,
/* Data-processing (3 source) instructions. */
Irrrr_MADD = 0x1b000000,
@@ -737,6 +755,13 @@ static void tcg_out_insn_addsub_imm(TCGContext *s, AArch64Insn insn,
tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd);
}
+static void tcg_out_insn_minmax_imm(TCGContext *s, AArch64Insn insn,
+ TCGType ext, TCGReg rd, TCGReg rn,
+ uint8_t imm)
+{
+ tcg_out32(s, insn | ext << 31 | imm << 10 | rn << 5 | rd);
+}
+
/* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
(Logical immediate). Both insn groups have N, IMMR and IMMS fields
that feed the DecodeBitMasks pseudo function. */
@@ -2592,20 +2617,90 @@ static void tcg_out_set_borrow(TCGContext *s)
TCG_REG_XZR, TCG_REG_XZR, TCG_REG_XZR);
}
+static TCGConstraintSetIndex cset_sminmax(TCGType type, unsigned flags)
+{
+ return cpuinfo & CPUINFO_CSSC ? C_O1_I2(r, r, rS) : C_NotImplemented;
+}
+
+static void tgen_smax(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_insn(s, rrr, SMAX, type, a0, a1, a2);
+}
+
+static void tgen_smaxi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_insn(s, minmax_imm, SMAXI, type, a0, a1, a2);
+}
+
static const TCGOutOpBinary outop_smax = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_sminmax,
+ .out_rrr = tgen_smax,
+ .out_rri = tgen_smaxi,
};
+static void tgen_smin(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_insn(s, rrr, SMIN, type, a0, a1, a2);
+}
+
+static void tgen_smini(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_insn(s, minmax_imm, SMINI, type, a0, a1, a2);
+}
+
static const TCGOutOpBinary outop_smin = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_sminmax,
+ .out_rrr = tgen_smin,
+ .out_rri = tgen_smini,
};
+static TCGConstraintSetIndex cset_uminmax(TCGType type, unsigned flags)
+{
+ return cpuinfo & CPUINFO_CSSC ? C_O1_I2(r, r, rU) : C_NotImplemented;
+}
+
+static void tgen_umax(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_insn(s, rrr, UMAX, type, a0, a1, a2);
+}
+
+static void tgen_umaxi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_insn(s, minmax_imm, UMAXI, type, a0, a1, a2);
+}
+
static const TCGOutOpBinary outop_umax = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_uminmax,
+ .out_rrr = tgen_umax,
+ .out_rri = tgen_umaxi,
};
+static void tgen_umin(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_insn(s, rrr, UMIN, type, a0, a1, a2);
+}
+
+static void tgen_umini(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tcg_out_insn(s, minmax_imm, UMINI, type, a0, a1, a2);
+}
+
static const TCGOutOpBinary outop_umin = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_uminmax,
+ .out_rrr = tgen_umin,
+ .out_rri = tgen_umini,
};
static void tgen_xor(TCGContext *s, TCGType type,
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 5/7] target/riscv64: Implement min/max with Zbb
2026-08-12 0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
` (3 preceding siblings ...)
2026-08-12 0:31 ` [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC Richard Henderson
@ 2026-08-12 0:31 ` Richard Henderson
2026-08-12 0:31 ` [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC Richard Henderson
2026-08-12 0:31 ` [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC Richard Henderson
6 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 0:31 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/riscv64/tcg-target.c.inc | 44 ++++++++++++++++++++++++++++++++----
1 file changed, 40 insertions(+), 4 deletions(-)
diff --git a/tcg/riscv64/tcg-target.c.inc b/tcg/riscv64/tcg-target.c.inc
index 723c21b3da..2ce9d47a63 100644
--- a/tcg/riscv64/tcg-target.c.inc
+++ b/tcg/riscv64/tcg-target.c.inc
@@ -233,6 +233,10 @@ typedef enum {
OPC_CPOPW = 0x6020101b,
OPC_CTZ = 0x60101013,
OPC_CTZW = 0x6010101b,
+ OPC_MAX = 0x0a006033,
+ OPC_MAXU = 0x0a007033,
+ OPC_MIN = 0x0a004033,
+ OPC_MINU = 0x0a005033,
OPC_ORN = 0x40006033,
OPC_REV8 = 0x6b805013,
OPC_ROL = 0x60001033,
@@ -2404,20 +2408,52 @@ static void tcg_out_set_borrow(TCGContext *s)
g_assert_not_reached();
}
+static void tgen_smax(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_opc_reg(s, OPC_MAX, a0, a1, a2);
+}
+
static const TCGOutOpBinary outop_smax = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_zbb_rrr,
+ .out_rrr = tgen_smax,
};
+static void tgen_smin(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_opc_reg(s, OPC_MIN, a0, a1, a2);
+}
+
static const TCGOutOpBinary outop_smin = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_zbb_rrr,
+ .out_rrr = tgen_smin,
};
+static void tgen_umax(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_opc_reg(s, OPC_MAXU, a0, a1, a2);
+}
+
static const TCGOutOpBinary outop_umax = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_zbb_rrr,
+ .out_rrr = tgen_umax,
};
+static void tgen_umin(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tcg_out_opc_reg(s, OPC_MINU, a0, a1, a2);
+}
+
static const TCGOutOpBinary outop_umin = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_zbb_rrr,
+ .out_rrr = tgen_umin,
};
static void tgen_xor(TCGContext *s, TCGType type,
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC
2026-08-12 0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
` (4 preceding siblings ...)
2026-08-12 0:31 ` [PATCH 5/7] target/riscv64: Implement min/max with Zbb Richard Henderson
@ 2026-08-12 0:31 ` Richard Henderson
2026-08-12 6:59 ` Philippe Mathieu-Daudé
2026-08-12 0:31 ` [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC Richard Henderson
6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 0:31 UTC (permalink / raw)
To: qemu-devel
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/aarch64/tcg-target.c.inc | 15 ++++++++++++++-
1 file changed, 14 insertions(+), 1 deletion(-)
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 55b3be0b96..1f784e8d46 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -535,6 +535,7 @@ typedef enum {
/* Data-processing (1 source) instructions. */
Irr_sf_CLZ = 0x5ac01000,
+ Irr_sf_CNT = 0x5ac01c00,
Irr_sf_RBIT = 0x5ac00000,
Irr_sf_REV = 0x5ac00000, /* + size << 10 */
@@ -2251,8 +2252,20 @@ static const TCGOutOpBinary outop_clz = {
.out_rri = tgen_clzi,
};
+static TCGConstraintSetIndex cset_ctpop(TCGType type, unsigned flags)
+{
+ return cpuinfo & CPUINFO_CSSC ? C_O1_I1(r, r) : C_NotImplemented;
+}
+
+static void tgen_ctpop(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1)
+{
+ tcg_out_insn(s, rr_sf, CNT, type, a0, a1);
+}
+
static const TCGOutOpUnary outop_ctpop = {
- .base.static_constraint = C_NotImplemented,
+ .base.static_constraint = C_Dynamic,
+ .base.dynamic_constraint = cset_ctpop,
+ .out_rr = tgen_ctpop,
};
static void tgen_ctz(TCGContext *s, TCGType type,
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC
2026-08-12 0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
` (5 preceding siblings ...)
2026-08-12 0:31 ` [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC Richard Henderson
@ 2026-08-12 0:31 ` Richard Henderson
2026-08-12 7:06 ` Philippe Mathieu-Daudé
6 siblings, 1 reply; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 0:31 UTC (permalink / raw)
To: qemu-devel
We already have an expansion of CTZ using RBIT+CLZ,
but use the new insn with FEAT_CSSC is present.
Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
---
tcg/aarch64/tcg-target.c.inc | 43 +++++++++++++++++++++++++++---------
1 file changed, 32 insertions(+), 11 deletions(-)
diff --git a/tcg/aarch64/tcg-target.c.inc b/tcg/aarch64/tcg-target.c.inc
index 1f784e8d46..ce5c039557 100644
--- a/tcg/aarch64/tcg-target.c.inc
+++ b/tcg/aarch64/tcg-target.c.inc
@@ -535,6 +535,7 @@ typedef enum {
/* Data-processing (1 source) instructions. */
Irr_sf_CLZ = 0x5ac01000,
+ Irr_sf_CTZ = 0x5ac01800,
Irr_sf_CNT = 0x5ac01c00,
Irr_sf_RBIT = 0x5ac00000,
Irr_sf_REV = 0x5ac00000, /* + size << 10 */
@@ -2213,24 +2214,30 @@ static const TCGOutOpBinary outop_andc = {
.out_rrr = tgen_andc,
};
-static void tgen_clz(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, TCGReg a2)
+static void tgen_clzctz(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
+ TCGReg a2, AArch64Insn insn)
{
tcg_out_cmp(s, type, TCG_COND_NE, a1, 0, true);
- tcg_out_insn(s, rr_sf, CLZ, type, TCG_REG_TMP0, a1);
+ tcg_out_insn_rr_sf(s, insn, type, TCG_REG_TMP0, a1);
tcg_out_insn(s, csel, CSEL, type, a0, TCG_REG_TMP0, a2, TCG_COND_NE);
}
-static void tgen_clzi(TCGContext *s, TCGType type,
- TCGReg a0, TCGReg a1, tcg_target_long a2)
+static void tgen_clz(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, TCGReg a2)
+{
+ tgen_clzctz(s, type, a0, a1, a2, Irr_sf_CLZ);
+}
+
+static void tgen_clzctzi(TCGContext *s, TCGType type, TCGReg a0, TCGReg a1,
+ tcg_target_long a2, AArch64Insn insn)
{
if (a2 == (type == TCG_TYPE_I32 ? 32 : 64)) {
- tcg_out_insn(s, rr_sf, CLZ, type, a0, a1);
+ tcg_out_insn_rr_sf(s, insn, type, a0, a1);
return;
}
tcg_out_cmp(s, type, TCG_COND_NE, a1, 0, true);
- tcg_out_insn(s, rr_sf, CLZ, type, a0, a1);
+ tcg_out_insn_rr_sf(s, insn, type, a0, a1);
switch (a2) {
case -1:
@@ -2246,6 +2253,12 @@ static void tgen_clzi(TCGContext *s, TCGType type,
}
}
+static void tgen_clzi(TCGContext *s, TCGType type,
+ TCGReg a0, TCGReg a1, tcg_target_long a2)
+{
+ tgen_clzctzi(s, type, a0, a1, a2, Irr_sf_CLZ);
+}
+
static const TCGOutOpBinary outop_clz = {
.base.static_constraint = C_O1_I2(r, r, rAL),
.out_rrr = tgen_clz,
@@ -2271,15 +2284,23 @@ static const TCGOutOpUnary outop_ctpop = {
static void tgen_ctz(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, TCGReg a2)
{
- tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
- tgen_clz(s, type, a0, TCG_REG_TMP0, a2);
+ if (cpuinfo & CPUINFO_CSSC) {
+ tgen_clzctz(s, type, a0, a1, a2, Irr_sf_CTZ);
+ } else {
+ tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
+ tgen_clzctz(s, type, a0, TCG_REG_TMP0, a2, Irr_sf_CLZ);
+ }
}
static void tgen_ctzi(TCGContext *s, TCGType type,
TCGReg a0, TCGReg a1, tcg_target_long a2)
{
- tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
- tgen_clzi(s, type, a0, TCG_REG_TMP0, a2);
+ if (cpuinfo & CPUINFO_CSSC) {
+ tgen_clzctzi(s, type, a0, a1, a2, Irr_sf_CTZ);
+ } else {
+ tcg_out_insn(s, rr_sf, RBIT, type, TCG_REG_TMP0, a1);
+ tgen_clzctzi(s, type, a0, a1, a2, Irr_sf_CLZ);
+ }
}
static const TCGOutOpBinary outop_ctz = {
--
2.43.0
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC
2026-08-12 0:31 ` [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC Richard Henderson
@ 2026-08-12 3:35 ` Brad Smith
2026-08-12 13:56 ` Richard Henderson
0 siblings, 1 reply; 16+ messages in thread
From: Brad Smith @ 2026-08-12 3:35 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 2026-08-11 8:31 p.m., Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> host/include/aarch64/host/cpuinfo.h | 1 +
> util/cpuinfo-aarch64.c | 13 ++++++++++++-
> 2 files changed, 13 insertions(+), 1 deletion(-)
>
> diff --git a/host/include/aarch64/host/cpuinfo.h b/host/include/aarch64/host/cpuinfo.h
> index fe671534e4..c32c04dade 100644
> --- a/host/include/aarch64/host/cpuinfo.h
> +++ b/host/include/aarch64/host/cpuinfo.h
> @@ -12,6 +12,7 @@
> #define CPUINFO_AES (1u << 3)
> #define CPUINFO_PMULL (1u << 4)
> #define CPUINFO_BTI (1u << 5)
> +#define CPUINFO_CSSC (1u << 6)
>
> /* Initialized with a constructor. */
> extern unsigned cpuinfo;
> diff --git a/util/cpuinfo-aarch64.c b/util/cpuinfo-aarch64.c
> index 288074c08f..0b4f8a747d 100644
> --- a/util/cpuinfo-aarch64.c
> +++ b/util/cpuinfo-aarch64.c
> @@ -72,6 +72,7 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
>
> unsigned long hwcap2 = qemu_getauxval(AT_HWCAP2);
> info |= (hwcap2 & HWCAP2_BTI ? CPUINFO_BTI : 0);
> + info |= (hwcap2 & HWCAP2_CSSC ? CPUINFO_CSSC : 0);
> #endif
> #ifdef CONFIG_DARWIN
> info |= sysctl_for_bool("hw.optional.arm.FEAT_LSE") * CPUINFO_LSE;
> @@ -79,10 +80,11 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
> info |= sysctl_for_bool("hw.optional.arm.FEAT_AES") * CPUINFO_AES;
> info |= sysctl_for_bool("hw.optional.arm.FEAT_PMULL") * CPUINFO_PMULL;
> info |= sysctl_for_bool("hw.optional.arm.FEAT_BTI") * CPUINFO_BTI;
> + info |= sysctl_for_bool("hw.optional.arm.FEAT_CSSC") * CPUINFO_CSSC;
> #endif
> #if defined(__OpenBSD__) && !defined(CONFIG_ELF_AUX_INFO)
> int mib[2];
> - uint64_t isar0;
> + uint64_t isar0, isar2;
> uint64_t pfr1;
> size_t len;
>
> @@ -101,6 +103,15 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
> }
> }
>
> + mib[0] = CTL_MACHDEP;
> + mib[1] = CPU_ID_AA64ISAR2;
> + len = sizeof(isar2);
> + if (sysctl(mib, 2, &isar2, &len, NULL, 0) != -1) {
> + if (ID_AA64ISAR2_CSSC(isar2) >= ID_AA64ISAR2_CSSC_IMPL) {
> + info |= CPUINFO_CSSC;
> + }
> + }
> +
> mib[0] = CTL_MACHDEP;
> mib[1] = CPU_ID_AA64PFR1;
> len = sizeof(pfr1);
You can remove the bottom chunk. Any OpenBSD release that has the
ID_AA64ISAR2_CSSC
and ID_AA64ISAR2_CSSC_IMPL constants is also covered by elf_aux_info()
which is the
first chunk.
ID_AA64ISAR2_CSSC_IMPL
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC
2026-08-12 0:31 ` [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC Richard Henderson
@ 2026-08-12 6:59 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 16+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-12 6:59 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 12/8/26 02:31, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> tcg/aarch64/tcg-target.c.inc | 15 ++++++++++++++-
> 1 file changed, 14 insertions(+), 1 deletion(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC
2026-08-12 0:31 ` [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC Richard Henderson
@ 2026-08-12 7:06 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 16+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-12 7:06 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 12/8/26 02:31, Richard Henderson wrote:
> We already have an expansion of CTZ using RBIT+CLZ,
> but use the new insn with FEAT_CSSC is present.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> tcg/aarch64/tcg-target.c.inc | 43 +++++++++++++++++++++++++++---------
> 1 file changed, 32 insertions(+), 11 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC
2026-08-12 0:31 ` [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC Richard Henderson
@ 2026-08-12 7:15 ` Philippe Mathieu-Daudé
0 siblings, 0 replies; 16+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-12 7:15 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 12/8/26 02:31, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> tcg/aarch64/tcg-target-con-set.h | 2 +
> tcg/aarch64/tcg-target-con-str.h | 2 +
> tcg/aarch64/tcg-target.c.inc | 103 +++++++++++++++++++++++++++++--
> 3 files changed, 103 insertions(+), 4 deletions(-)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/7] tcg/optimize: Handle min/max opcodes
2026-08-12 0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
@ 2026-08-12 7:17 ` Philippe Mathieu-Daudé
2026-08-12 8:46 ` Alex Bennée
1 sibling, 0 replies; 16+ messages in thread
From: Philippe Mathieu-Daudé @ 2026-08-12 7:17 UTC (permalink / raw)
To: Richard Henderson, qemu-devel
On 12/8/26 02:31, Richard Henderson wrote:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> tcg/optimize.c | 52 ++++++++++++++++++++++++++++++++++++++++++++++++++
> 1 file changed, 52 insertions(+)
Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 1/7] tcg: Add integer min/max opcodes
2026-08-12 0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
@ 2026-08-12 8:42 ` Alex Bennée
0 siblings, 0 replies; 16+ messages in thread
From: Alex Bennée @ 2026-08-12 8:42 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> We already have these for vectors; replicate for integers.
>
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
> ---
> include/tcg/tcg-opc.h | 4 +++
> tcg/tcg-op.c | 48 ++++++++++++++++++++++++++------
> tcg/tcg.c | 4 +++
> docs/devel/tcg-ops.rst | 14 +++++++++-
> 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, 189 insertions(+), 9 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 4c2207c6af..54f7906cb7 100644
> --- a/tcg/tcg.c
> +++ b/tcg/tcg.c
> @@ -5512,6 +5512,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..d30db9ea65 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
> -------
>
> @@ -512,7 +524,7 @@ Misc
>
> - | Reverse the 64 bits of input *t1* with output in *dest*.
>
> -Conditional moves
> +Conditional motes
> -----------------
A typo snuck in....
Otherwise:
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 2/7] tcg/optimize: Handle min/max opcodes
2026-08-12 0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
2026-08-12 7:17 ` Philippe Mathieu-Daudé
@ 2026-08-12 8:46 ` Alex Bennée
1 sibling, 0 replies; 16+ messages in thread
From: Alex Bennée @ 2026-08-12 8:46 UTC (permalink / raw)
To: Richard Henderson; +Cc: qemu-devel
Richard Henderson <richard.henderson@linaro.org> writes:
> Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Alex Bennée <alex.bennee@linaro.org>
--
Alex Bennée
Virtualisation Tech Lead @ Linaro
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC
2026-08-12 3:35 ` Brad Smith
@ 2026-08-12 13:56 ` Richard Henderson
0 siblings, 0 replies; 16+ messages in thread
From: Richard Henderson @ 2026-08-12 13:56 UTC (permalink / raw)
To: Brad Smith, qemu-devel
On 8/11/26 20:35, Brad Smith wrote:
>> @@ -101,6 +103,15 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
>> }
>> }
>> + mib[0] = CTL_MACHDEP;
>> + mib[1] = CPU_ID_AA64ISAR2;
>> + len = sizeof(isar2);
>> + if (sysctl(mib, 2, &isar2, &len, NULL, 0) != -1) {
>> + if (ID_AA64ISAR2_CSSC(isar2) >= ID_AA64ISAR2_CSSC_IMPL) {
>> + info |= CPUINFO_CSSC;
>> + }
>> + }
>> +
>> mib[0] = CTL_MACHDEP;
>> mib[1] = CPU_ID_AA64PFR1;
>> len = sizeof(pfr1);
>
> You can remove the bottom chunk. Any OpenBSD release that has the ID_AA64ISAR2_CSSC
> and ID_AA64ISAR2_CSSC_IMPL constants is also covered by elf_aux_info() which is the
> first chunk.
Right-o. Thanks!
r~
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2026-08-12 13:56 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-08-12 0:31 [PATCH 0/7] tcg: Add min/max opcodes Richard Henderson
2026-08-12 0:31 ` [PATCH 1/7] tcg: Add integer " Richard Henderson
2026-08-12 8:42 ` Alex Bennée
2026-08-12 0:31 ` [PATCH 2/7] tcg/optimize: Handle " Richard Henderson
2026-08-12 7:17 ` Philippe Mathieu-Daudé
2026-08-12 8:46 ` Alex Bennée
2026-08-12 0:31 ` [PATCH 3/7] util/cpuinfo-aarch64: Detect FEAT_CSSC Richard Henderson
2026-08-12 3:35 ` Brad Smith
2026-08-12 13:56 ` Richard Henderson
2026-08-12 0:31 ` [PATCH 4/7] tcg/aarch64: Implement min/max with FEAT_CSSC Richard Henderson
2026-08-12 7:15 ` Philippe Mathieu-Daudé
2026-08-12 0:31 ` [PATCH 5/7] target/riscv64: Implement min/max with Zbb Richard Henderson
2026-08-12 0:31 ` [PATCH 6/7] tcg/aarch64: Implement ctpop with FEAT_CSSC Richard Henderson
2026-08-12 6:59 ` Philippe Mathieu-Daudé
2026-08-12 0:31 ` [PATCH 7/7] tcg/aarch64: Use CTZ from FEAT_CSSC Richard Henderson
2026-08-12 7:06 ` Philippe Mathieu-Daudé
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.