@@ -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//
18171822bool 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