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,