Commit 100ec60528 for qemu.org

commit 100ec60528d389a20fa5c4323a2b35a6f5b9fd3c
Author: Richard Henderson <richard.henderson@linaro.org>
Date:   Tue Aug 11 16:40:17 2026 -0700

    tcg/aarch64: Implement min/max with FEAT_CSSC

    Reviewed-by: Philippe Mathieu-Daudé <philmd@oss.qualcomm.com>
    Signed-off-by: Richard Henderson <richard.henderson@linaro.org>

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,