@samitouri / QOSamiQemu / commits / 100ec60528

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>

Richard Henderson committed Aug 11, 2026 at 16:40 UTC 100ec60528d389a20fa5c4323a2b35a6f5b9fd3c
3 files changed +103 -4
tcg/aarch64/tcg-target-con-set.h
+2
@@ -24,6 +24,8 @@ C_O1_I2(r, r, rAL)
24 C_O1_I2(r, r, rC)
25 C_O1_I2(r, r, ri)
26 C_O1_I2(r, r, rL)
27 +C_O1_I2(r, r, rS)
28 +C_O1_I2(r, r, rU)
29 C_O1_I2(r, rZ, rA)
30 C_O1_I2(r, rz, rMZ)
31 C_O1_I2(r, rz, rz)
tcg/aarch64/tcg-target-con-str.h
+2
@@ -21,4 +21,6 @@ CONST('L', TCG_CT_CONST_LIMM)
21 CONST('M', TCG_CT_CONST_MONE)
22 CONST('O', TCG_CT_CONST_ORRI)
23 CONST('N', TCG_CT_CONST_ANDI)
24 +CONST('S', TCG_CT_CONST_S8)
25 +CONST('U', TCG_CT_CONST_U8)
26 CONST('Z', TCG_CT_CONST_ZERO)
tcg/aarch64/tcg-target.c.inc
+99 -4
@@ -152,6 +152,8 @@ static bool patch_reloc(tcg_insn_unit *code_ptr, int type,
152 #define TCG_CT_CONST_ORRI 0x1000
153 #define TCG_CT_CONST_ANDI 0x2000
154 #define TCG_CT_CONST_CMP 0x4000
155 +#define TCG_CT_CONST_S8 0x8000
156 +#define TCG_CT_CONST_U8 0x10000
157
158 #define ALL_GENERAL_REGS 0xffffffffu
159 #define ALL_VECTOR_REGS 0xffffffff00000000ull
@@ -320,6 +322,12 @@ static bool tcg_target_const_match(int64_t val, int ct,
322 if ((ct & TCG_CT_CONST_LIMM) && is_limm(val)) {
323 return 1;
324 }
325 + if ((ct & TCG_CT_CONST_S8) && val == (int8_t)val) {
326 + return 1;
327 + }
328 + if ((ct & TCG_CT_CONST_U8) && val == (uint8_t)val) {
329 + return 1;
330 + }
331 if ((ct & TCG_CT_CONST_ZERO) && val == 0) {
332 return 1;
333 }
@@ -472,6 +480,12 @@ typedef enum {
480 Iaddsub_imm_SUBI = 0x51000000,
481 Iaddsub_imm_SUBSI = 0x71000000,
482
483 + /* Min/max immediate instructions. */
484 + Iminmax_imm_SMAXI = 0x11c00000,
485 + Iminmax_imm_UMAXI = 0x11c40000,
486 + Iminmax_imm_SMINI = 0x11c80000,
487 + Iminmax_imm_UMINI = 0x11cc0000,
488 +
489 /* Bitfield instructions. */
490 Ibitfield_BFM = 0x33000000,
491 Ibitfield_SBFM = 0x13000000,
@@ -533,6 +547,10 @@ typedef enum {
547 Irrr_UMULH = 0x9bc07c00,
548 Irrr_UDIV = 0x1ac00800,
549 Irrr_SDIV = 0x1ac00c00,
550 + Irrr_SMAX = 0x1ac00600,
551 + Irrr_UMAX = 0x1ac00640,
552 + Irrr_SMIN = 0x1ac00680,
553 + Irrr_UMIN = 0x1ac006c0,
554
555 /* Data-processing (3 source) instructions. */
556 Irrrr_MADD = 0x1b000000,
@@ -737,6 +755,13 @@ static void tcg_out_insn_addsub_imm(TCGContext *s, AArch64Insn insn,
755 tcg_out32(s, insn | ext << 31 | aimm << 10 | rn << 5 | rd);
756 }
757
758 +static void tcg_out_insn_minmax_imm(TCGContext *s, AArch64Insn insn,
759 + TCGType ext, TCGReg rd, TCGReg rn,
760 + uint8_t imm)
761 +{
762 + tcg_out32(s, insn | ext << 31 | imm << 10 | rn << 5 | rd);
763 +}
764 +
765 /* This function can be used for both 3.4.2 (Bitfield) and 3.4.4
766 (Logical immediate). Both insn groups have N, IMMR and IMMS fields
767 that feed the DecodeBitMasks pseudo function. */
@@ -2592,20 +2617,90 @@ static void tcg_out_set_borrow(TCGContext *s)
2617 TCG_REG_XZR, TCG_REG_XZR, TCG_REG_XZR);
2618 }
2619
2620 +static TCGConstraintSetIndex cset_sminmax(TCGType type, unsigned flags)
2621 +{
2622 + return cpuinfo & CPUINFO_CSSC ? C_O1_I2(r, r, rS) : C_NotImplemented;
2623 +}
2624 +
2625 +static void tgen_smax(TCGContext *s, TCGType type,
2626 + TCGReg a0, TCGReg a1, TCGReg a2)
2627 +{
2628 + tcg_out_insn(s, rrr, SMAX, type, a0, a1, a2);
2629 +}
2630 +
2631 +static void tgen_smaxi(TCGContext *s, TCGType type,
2632 + TCGReg a0, TCGReg a1, tcg_target_long a2)
2633 +{
2634 + tcg_out_insn(s, minmax_imm, SMAXI, type, a0, a1, a2);
2635 +}
2636 +
2637 static const TCGOutOpBinary outop_smax = {
2596 - .base.static_constraint = C_NotImplemented,
2638 + .base.static_constraint = C_Dynamic,
2639 + .base.dynamic_constraint = cset_sminmax,
2640 + .out_rrr = tgen_smax,
2641 + .out_rri = tgen_smaxi,
2642 };
2643
2644 +static void tgen_smin(TCGContext *s, TCGType type,
2645 + TCGReg a0, TCGReg a1, TCGReg a2)
2646 +{
2647 + tcg_out_insn(s, rrr, SMIN, type, a0, a1, a2);
2648 +}
2649 +
2650 +static void tgen_smini(TCGContext *s, TCGType type,
2651 + TCGReg a0, TCGReg a1, tcg_target_long a2)
2652 +{
2653 + tcg_out_insn(s, minmax_imm, SMINI, type, a0, a1, a2);
2654 +}
2655 +
2656 static const TCGOutOpBinary outop_smin = {
2600 - .base.static_constraint = C_NotImplemented,
2657 + .base.static_constraint = C_Dynamic,
2658 + .base.dynamic_constraint = cset_sminmax,
2659 + .out_rrr = tgen_smin,
2660 + .out_rri = tgen_smini,
2661 };
2662
2663 +static TCGConstraintSetIndex cset_uminmax(TCGType type, unsigned flags)
2664 +{
2665 + return cpuinfo & CPUINFO_CSSC ? C_O1_I2(r, r, rU) : C_NotImplemented;
2666 +}
2667 +
2668 +static void tgen_umax(TCGContext *s, TCGType type,
2669 + TCGReg a0, TCGReg a1, TCGReg a2)
2670 +{
2671 + tcg_out_insn(s, rrr, UMAX, type, a0, a1, a2);
2672 +}
2673 +
2674 +static void tgen_umaxi(TCGContext *s, TCGType type,
2675 + TCGReg a0, TCGReg a1, tcg_target_long a2)
2676 +{
2677 + tcg_out_insn(s, minmax_imm, UMAXI, type, a0, a1, a2);
2678 +}
2679 +
2680 static const TCGOutOpBinary outop_umax = {
2604 - .base.static_constraint = C_NotImplemented,
2681 + .base.static_constraint = C_Dynamic,
2682 + .base.dynamic_constraint = cset_uminmax,
2683 + .out_rrr = tgen_umax,
2684 + .out_rri = tgen_umaxi,
2685 };
2686
2687 +static void tgen_umin(TCGContext *s, TCGType type,
2688 + TCGReg a0, TCGReg a1, TCGReg a2)
2689 +{
2690 + tcg_out_insn(s, rrr, UMIN, type, a0, a1, a2);
2691 +}
2692 +
2693 +static void tgen_umini(TCGContext *s, TCGType type,
2694 + TCGReg a0, TCGReg a1, tcg_target_long a2)
2695 +{
2696 + tcg_out_insn(s, minmax_imm, UMINI, type, a0, a1, a2);
2697 +}
2698 +
2699 static const TCGOutOpBinary outop_umin = {
2608 - .base.static_constraint = C_NotImplemented,
2700 + .base.static_constraint = C_Dynamic,
2701 + .base.dynamic_constraint = cset_uminmax,
2702 + .out_rrr = tgen_umin,
2703 + .out_rri = tgen_umini,
2704 };
2705
2706 static void tgen_xor(TCGContext *s, TCGType type,