diff --git a/src/coreclr/jit/emitarm64.cpp b/src/coreclr/jit/emitarm64.cpp index 38d8f1c9c42eb1..8c474c3b9d8166 100644 --- a/src/coreclr/jit/emitarm64.cpp +++ b/src/coreclr/jit/emitarm64.cpp @@ -1312,6 +1312,18 @@ static const char * const wRegNames[] = #include "register.h" }; + +static const char * const zRegNames[] = +{ + "z0", "z1", "z2", "z3", "z4", + "z5", "z6", "z7", "z8", "z9", + "z10", "z11", "z12", "z13", "z14", + "z15", "z16", "z17", "z18", "z19", + "z20", "z21", "z22", "z23", "z24", + "z25", "z26", "z27", "z28", "z29", + "z30", "z31" +}; + static const char * const vRegNames[] = { "v0", "v1", "v2", "v3", "v4", @@ -1354,6 +1366,14 @@ static const char * const bRegNames[] = "b25", "b26", "b27", "b28", "b29", "b30", "b31" }; + +static const char * const pRegNames[] = +{ + "p0", "p1", "p2", "p3", "p4", + "p5", "p6", "p7", "p8", "p9", + "p10", "p11", "p12", "p13", "p14", + "p15" +}; // clang-format on //------------------------------------------------------------------------ @@ -1395,6 +1415,10 @@ const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName) con { rn = bRegNames[reg - REG_V0]; } + else if (size == EA_SCALABLE) + { + rn = zRegNames[reg - REG_V0]; + } } assert(rn != nullptr); @@ -1402,6 +1426,24 @@ const char* emitter::emitRegName(regNumber reg, emitAttr size, bool varName) con return rn; } +//------------------------------------------------------------------------ +// emitSveRegName: Returns a scalable vector register name. +// +// Arguments: +// reg - A SIMD and floating-point register. +// +// Return value: +// A string that represents a scalable vector register name. +// +const char* emitter::emitSveRegName(regNumber reg) +{ + assert((reg >= REG_V0) && (reg <= REG_V31)); + + int index = (int)reg - (int)REG_V0; + + return zRegNames[index]; +} + //------------------------------------------------------------------------ // emitVectorRegName: Returns a SIMD vector register name. // @@ -1420,6 +1462,24 @@ const char* emitter::emitVectorRegName(regNumber reg) return vRegNames[index]; } +//------------------------------------------------------------------------ +// emitPredicateRegName: Returns a predicate register name. +// +// Arguments: +// reg - A predicate register. +// +// Return value: +// A string that represents a predicate register name. +// +const char* emitter::emitPredicateRegName(regNumber reg) +{ + assert((reg >= REG_P0) && (reg <= REG_P15)); + + int index = (int)reg - (int)REG_P0; + + return vRegNames[index]; +} + /***************************************************************************** * * Returns the base encoding of the given CPU instruction. @@ -10571,6 +10631,45 @@ void emitter::emitIns_Call(EmitCallType callType, return ureg << 10; } +/***************************************************************************** + * + * Returns an encoding for the specified register used in the 'Pd' position + */ + +/*static*/ emitter::code_t emitter::insEncodeReg_Pd(regNumber reg) +{ + assert(emitter::isPredicateRegister(reg)); + emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_P0; + assert((ureg >= 0) && (ureg <= 15)); + return ureg; +} + +/***************************************************************************** + * + * Returns an encoding for the specified register used in the 'Pn' position + */ + +/*static*/ emitter::code_t emitter::insEncodeReg_Pn(regNumber reg) +{ + assert(emitter::isPredicateRegister(reg)); + emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_P0; + assert((ureg >= 0) && (ureg <= 15)); + return ureg << 5; +} + +/***************************************************************************** + * + * Returns an encoding for the specified register used in the 'Pm' position + */ + +/*static*/ emitter::code_t emitter::insEncodeReg_Pm(regNumber reg) +{ + assert(emitter::isPredicateRegister(reg)); + emitter::code_t ureg = (emitter::code_t)reg - (emitter::code_t)REG_P0; + assert((ureg >= 0) && (ureg <= 15)); + return ureg << 16; +} + /***************************************************************************** * * Returns an encoding for the specified condition code. @@ -13768,7 +13867,21 @@ void emitter::emitDispReg(regNumber reg, emitAttr attr, bool addComma) } //------------------------------------------------------------------------ -// emitDispVectorReg: Display a SIMD vector register name with with an arrangement suffix +// emitDispSveReg: Display a scalable vector register name with an arrangement suffix +// +void emitter::emitDispSveReg(regNumber reg, insOpts opt, bool addComma) +{ + assert(insOptsScalable(opt)); + assert(isVectorRegister(reg)); + printf(emitSveRegName(reg)); + emitDispArrangement(opt); + + if (addComma) + emitDispComma(); +} + +//------------------------------------------------------------------------ +// emitDispVectorReg: Display a SIMD vector register name with an arrangement suffix // void emitter::emitDispVectorReg(regNumber reg, insOpts opt, bool addComma) { @@ -13849,6 +13962,19 @@ void emitter::emitDispVectorElemList( } } +//------------------------------------------------------------------------ +// emitDispPredicateReg: Display a predicate register name with with an arrangement suffix +// +void emitter::emitDispPredicateReg(regNumber reg, insOpts opt, bool addComma) +{ + assert(isPredicateRegister(reg)); + printf(emitPredicateRegName(reg)); + emitDispArrangement(opt); + + if (addComma) + emitDispComma(); +} + //------------------------------------------------------------------------ // emitDispArrangement: Display a SIMD vector arrangement suffix // @@ -13864,24 +13990,36 @@ void emitter::emitDispArrangement(insOpts opt) case INS_OPTS_16B: str = "16b"; break; + case INS_OPTS_SCALABLE_B: + str = "b"; + break; case INS_OPTS_4H: str = "4h"; break; case INS_OPTS_8H: str = "8h"; break; + case INS_OPTS_SCALABLE_H: + str = "h"; + break; case INS_OPTS_2S: str = "2s"; break; case INS_OPTS_4S: str = "4s"; break; + case INS_OPTS_SCALABLE_S: + str = "s"; + break; case INS_OPTS_1D: str = "1d"; break; case INS_OPTS_2D: str = "2d"; break; + case INS_OPTS_SCALABLE_D: + str = "d"; + break; default: assert(!"Invalid insOpt for vector register"); diff --git a/src/coreclr/jit/emitarm64.h b/src/coreclr/jit/emitarm64.h index 7a1d8d33e4e3cc..24f2d1199a4c88 100644 --- a/src/coreclr/jit/emitarm64.h +++ b/src/coreclr/jit/emitarm64.h @@ -19,7 +19,9 @@ static bool strictArmAsm; /* Debug-only routines to display instructions */ /************************************************************************/ +const char* emitSveRegName(regNumber reg); const char* emitVectorRegName(regNumber reg); +const char* emitPredicateRegName(regNumber reg); void emitDispInsHelp( instrDesc* id, bool isNew, bool doffs, bool asmfm, unsigned offset, BYTE* pCode, size_t sz, insGroup* ig); @@ -38,10 +40,12 @@ void emitDispShiftOpts(insOpts opt); void emitDispExtendOpts(insOpts opt); void emitDispLSExtendOpts(insOpts opt); void emitDispReg(regNumber reg, emitAttr attr, bool addComma); +void emitDispSveReg(regNumber reg, insOpts opt, bool addComma); void emitDispVectorReg(regNumber reg, insOpts opt, bool addComma); void emitDispVectorRegIndex(regNumber reg, emitAttr elemsize, ssize_t index, bool addComma); void emitDispVectorRegList(regNumber firstReg, unsigned listSize, insOpts opt, bool addComma); void emitDispVectorElemList(regNumber firstReg, unsigned listSize, emitAttr elemsize, unsigned index, bool addComma); +void emitDispPredicateReg(regNumber reg, insOpts opt, bool addComma); void emitDispArrangement(insOpts opt); void emitDispElemsize(emitAttr elemsize); void emitDispShiftedReg(regNumber reg, insOpts opt, ssize_t imm, emitAttr attr); @@ -312,6 +316,15 @@ static code_t insEncodeReg_Vm(regNumber reg); // Returns an encoding for the specified register used in the 'Va' position static code_t insEncodeReg_Va(regNumber reg); +// Returns an encoding for the specified register used in the 'Pd' position +static code_t insEncodeReg_Pd(regNumber reg); + +// Returns an encoding for the specified register used in the 'Pn' position +static code_t insEncodeReg_Pn(regNumber reg); + +// Returns an encoding for the specified register used in the 'Pm' position +static code_t insEncodeReg_Pm(regNumber reg); + // Returns an encoding for the imm which represents the condition code. static code_t insEncodeCond(insCond cond); @@ -604,6 +617,11 @@ inline static bool isValidScalarDatasize(emitAttr size) return (size == EA_8BYTE) || (size == EA_4BYTE); } +inline static bool isValidScalableDatasize(emitAttr size) +{ + return ((size & EA_SCALABLE) == EA_SCALABLE); +} + inline static bool isValidVectorDatasize(emitAttr size) { return (size == EA_16BYTE) || (size == EA_8BYTE); @@ -664,6 +682,11 @@ inline static bool isFloatReg(regNumber reg) return isVectorRegister(reg); } +inline static bool isPredicateRegister(regNumber reg) +{ + return (reg >= REG_PREDICATE_FIRST && reg <= REG_PREDICATE_LAST); +} + inline static bool insOptsNone(insOpts opt) { return (opt == INS_OPTS_NONE); @@ -760,6 +783,12 @@ inline static bool insOptsConvertIntToFloat(insOpts opt) return ((opt >= INS_OPTS_4BYTE_TO_S) && (opt <= INS_OPTS_8BYTE_TO_D)); } +inline static bool insOptsScalable(insOpts opt) +{ + return ((opt == INS_OPTS_SCALABLE_B || opt == INS_OPTS_SCALABLE_H || opt == INS_OPTS_SCALABLE_S || + opt == INS_OPTS_SCALABLE_D)); +} + static bool isValidImmCond(ssize_t imm); static bool isValidImmCondFlags(ssize_t imm); static bool isValidImmCondFlagsImm5(ssize_t imm); diff --git a/src/coreclr/jit/instr.h b/src/coreclr/jit/instr.h index 4ee2a249a489e7..a3a70ab92107bb 100644 --- a/src/coreclr/jit/instr.h +++ b/src/coreclr/jit/instr.h @@ -268,6 +268,11 @@ enum insOpts : unsigned INS_OPTS_1D, INS_OPTS_2D, + INS_OPTS_SCALABLE_B, + INS_OPTS_SCALABLE_H, + INS_OPTS_SCALABLE_S, + INS_OPTS_SCALABLE_D, + INS_OPTS_MSL, // Vector Immediate (shifting ones variant) INS_OPTS_S_TO_4BYTE, // Single to INT32 @@ -418,8 +423,10 @@ enum emitAttr : unsigned EA_4BYTE = 0x004, EA_8BYTE = 0x008, EA_16BYTE = 0x010, - -#if defined(TARGET_XARCH) +#if defined(TARGET_ARM64) + EA_SCALABLE = 0x020, + EA_SIZE_MASK = 0x03F, +#elif defined(TARGET_XARCH) EA_32BYTE = 0x020, EA_64BYTE = 0x040, EA_SIZE_MASK = 0x07F, diff --git a/src/coreclr/jit/registerarm64.h b/src/coreclr/jit/registerarm64.h index 7ce66ada1beb0e..e8c126fac148cb 100644 --- a/src/coreclr/jit/registerarm64.h +++ b/src/coreclr/jit/registerarm64.h @@ -94,6 +94,26 @@ REGDEF(V29, 29+VBASE, VMASK(29), "d29", "s29") REGDEF(V30, 30+VBASE, VMASK(30), "d30", "s30") REGDEF(V31, 31+VBASE, VMASK(31), "d31", "s31") +// TODO-SVE: Fix once we add predicate registers +REGALIAS(P0, V0) +REGALIAS(P1, V1) +REGALIAS(P2, V2) +REGALIAS(P3, V3) +REGALIAS(P4, V4) +REGALIAS(P5, V5) +REGALIAS(P6, V6) +REGALIAS(P7, V7) +REGALIAS(P8, V8) +REGALIAS(P9, V9) +REGALIAS(P10, V10) +REGALIAS(P11, V11) +REGALIAS(P12, V12) +REGALIAS(P13, V13) +REGALIAS(P14, V14) +REGALIAS(P15, V15) + + + // The registers with values 64 (NBASE) and above are not real register numbers #define NBASE 64 diff --git a/src/coreclr/jit/targetarm64.h b/src/coreclr/jit/targetarm64.h index a454b47608bb37..61b3f3245ee22a 100644 --- a/src/coreclr/jit/targetarm64.h +++ b/src/coreclr/jit/targetarm64.h @@ -50,6 +50,8 @@ #define REG_FP_LAST REG_V31 #define FIRST_FP_ARGREG REG_V0 #define LAST_FP_ARGREG REG_V15 + #define REG_PREDICATE_FIRST REG_P0 + #define REG_PREDICATE_LAST REG_P15 #define REGNUM_BITS 6 // number of bits in a REG_* #define REGSIZE_BYTES 8 // number of bytes in one general purpose register