[PULL 26/38] tcg/aarch64: Implement min/max with FEAT_CSSC
Richard Henderson <[email protected]>
| Newsgroups | gmane.comp.emulators.qemu |
|---|---|
| Message-ID | <[email protected]> |
Reviewed-by: Philippe Mathieu-Daudé <[email protected]> Signed-off-by: Richard Henderson <[email protected]> --- 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