Skip to content

Commit 809f921

Browse files
committed
Add EPGRs for Extended EVEX.
1 parent c341c3b commit 809f921

File tree

1 file changed

+68
-16
lines changed

1 file changed

+68
-16
lines changed

src/coreclr/jit/emitxarch.cpp

Lines changed: 68 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1720,6 +1720,11 @@ bool emitter::TakesEvexPrefix(const instrDesc* id) const
17201720
return true;
17211721
}
17221722

1723+
if (HasExtendedGPReg(id))
1724+
{
1725+
return true;
1726+
}
1727+
17231728
if (id->idIsEvexNfContextSet() && IsBMIInstruction(ins))
17241729
{
17251730
// Only a few BMI instructions shall be promoted to APX-EVEX due to NF feature.
@@ -1816,9 +1821,7 @@ bool emitter::TakesRex2Prefix(const instrDesc* id) const
18161821
//
18171822
bool emitter::TakesApxExtendedEvexPrefix(const instrDesc* id) const
18181823
{
1819-
// TODO-XArch-APX:
1820-
// Isolating legacy-promoted-EVEX case out from VEX/EVEX-promoted-EVEX,
1821-
// as the latter ones are relatively simple, providing EGPRs functionality,
1824+
#ifdef TARGET_AMD64
18221825
instruction ins = id->idIns();
18231826
if (!IsApxExtendedEvexInstruction(ins))
18241827
{
@@ -1858,6 +1861,9 @@ bool emitter::TakesApxExtendedEvexPrefix(const instrDesc* id) const
18581861
}
18591862

18601863
return false;
1864+
#else // !TARGET_AMD64
1865+
return false;
1866+
#endif
18611867
}
18621868

18631869
// Intel AVX-512 encoding is defined in "Intel 64 and ia-32 architectures software developer's manual volume 2", Section
@@ -4231,8 +4237,19 @@ inline unsigned emitter::insEncodeReg012(const instrDesc* id, regNumber reg, emi
42314237
if (IsExtendedGPReg(reg))
42324238
{
42334239
// Seperate the encoding for REX2.B3/B4, REX2.B3 will be handled in `AddRexBPrefix`.
4234-
assert(TakesRex2Prefix(id));
4235-
*code |= 0x001000000000ULL; // REX2.B4
4240+
assert(TakesRex2Prefix(id) || TakesApxExtendedEvexPrefix(id) || TakesEvexPrefix(id));
4241+
if (hasRex2Prefix(*code))
4242+
{
4243+
*code |= 0x001000000000ULL; // REX2.B4
4244+
}
4245+
else if (hasEvexPrefix(*code))
4246+
{
4247+
*code |= 0x8000000000000ULL; // EVEX.B4
4248+
}
4249+
else
4250+
{
4251+
// There are cases when this method is called before prefix is attached.
4252+
}
42364253
}
42374254
}
42384255
else if ((EA_SIZE(size) == EA_1BYTE) && (reg > REG_RBX) && (code != nullptr))
@@ -4280,8 +4297,19 @@ inline unsigned emitter::insEncodeReg345(const instrDesc* id, regNumber reg, emi
42804297
if (IsExtendedGPReg(reg))
42814298
{
42824299
// Seperate the encoding for REX2.R3/R4, REX2.R3 will be handled in `AddRexRPrefix`.
4283-
assert(TakesRex2Prefix(id));
4284-
*code |= 0x004000000000ULL; // REX2.R4
4300+
assert(TakesRex2Prefix(id) || TakesApxExtendedEvexPrefix(id) || TakesEvexPrefix(id));
4301+
if (hasRex2Prefix(*code))
4302+
{
4303+
*code |= 0x004000000000ULL; // REX2.R4
4304+
}
4305+
else if (hasEvexPrefix(*code))
4306+
{
4307+
*code = AddEvexRPrimePrefix(*code); // EVEX.R4
4308+
}
4309+
else
4310+
{
4311+
// There are cases when this method is called before prefix is attached.
4312+
}
42854313
}
42864314
}
42874315
else if ((EA_SIZE(size) == EA_1BYTE) && (reg > REG_RBX) && (code != nullptr))
@@ -4339,6 +4367,12 @@ inline emitter::code_t emitter::insEncodeReg3456(const instrDesc* id, regNumber
43394367
// Have to set the EVEX V' bit
43404368
code = AddEvexVPrimePrefix(code);
43414369
}
4370+
4371+
if (isHighGPReg(reg) && IsBMIInstruction(ins))
4372+
{
4373+
// APX: BMI instructions use RVM operand encoding
4374+
code = AddEvexVPrimePrefix(code);
4375+
}
43424376
#endif
43434377

43444378
// Shift count = 5-bytes of opcode + 0-2 bits for EVEX
@@ -4364,7 +4398,7 @@ inline emitter::code_t emitter::insEncodeReg3456(const instrDesc* id, regNumber
43644398
// Rather see these paths cleaned up.
43654399
regBits = HighAwareRegEncoding(reg);
43664400

4367-
if (false /*reg >= REG_R16 && reg <= REG_R31*/)
4401+
if (isHighGPReg(reg))
43684402
{
43694403
// Have to set the EVEX V' bit
43704404
code = AddEvexVPrimePrefix(code);
@@ -4410,8 +4444,20 @@ inline unsigned emitter::insEncodeRegSIB(const instrDesc* id, regNumber reg, cod
44104444
if (IsExtendedGPReg(reg))
44114445
{
44124446
// Separate the encoding for REX2.X3/X4, REX2.X3 will be handled in `AddRexXPrefix`.
4413-
assert(TakesRex2Prefix(id));
4414-
*code |= 0x002000000000ULL; // REX2.X4
4447+
assert(TakesRex2Prefix(id) || TakesApxExtendedEvexPrefix(id) || TakesEvexPrefix(id));
4448+
if (hasRex2Prefix(*code))
4449+
{
4450+
*code |= 0x002000000000ULL; // REX2.X4
4451+
}
4452+
else if (hasEvexPrefix(*code))
4453+
{
4454+
// Note that APX-EVEX use EVEX.X4 as the MSB of the INDEX register to address GPRs, and the original EVEX.V4 is used for VSIB addressing.
4455+
*code &= 0xFFFFFBFFFFFFFFFFULL; // EVEX.X4
4456+
}
4457+
else
4458+
{
4459+
// There are cases when this method is called before prefix is attached.
4460+
}
44154461
}
44164462
}
44174463
unsigned regBits = RegEncoding(reg);
@@ -15348,6 +15394,12 @@ BYTE* emitter::emitOutputSV(BYTE* dst, instrDesc* id, code_t code, CnsVal* addc)
1534815394
{
1534915395
dst += emitOutputByte(dst, 0x66);
1535015396
}
15397+
#ifdef TARGET_AMD64
15398+
else
15399+
{
15400+
code |= EXTENDED_EVEX_PP_BITS;
15401+
}
15402+
#endif // TARGET_AMD64
1535115403
}
1535215404
FALLTHROUGH;
1535315405

@@ -16974,15 +17026,15 @@ BYTE* emitter::emitOutputRI(BYTE* dst, instrDesc* id)
1697417026
code = insCodeACC(ins);
1697517027
assert(code < 0x100);
1697617028

16977-
code |= 0x08; // Set the 'w' bit
16978-
unsigned regcode = insEncodeReg012(id, reg, size, &code);
16979-
code |= regcode;
16980-
17029+
1698117030
// This is INS_mov and will not take VEX prefix
1698217031
assert(!TakesVexPrefix(ins));
16983-
17032+
1698417033
code = AddX86PrefixIfNeededAndNotPresent(id, code, size);
16985-
17034+
code |= 0x08; // Set the 'w' bit
17035+
unsigned regcode = insEncodeReg012(id, reg, size, &code);
17036+
code |= regcode;
17037+
1698617038
if (TakesRexWPrefix(id))
1698717039
{
1698817040
code = AddRexWPrefix(id, code);

0 commit comments

Comments
 (0)