Skip to content

Commit f0e17f0

Browse files
committed
[X86][MC] Support encoding/decoding for APX variant ADD/SUB/ADC/SBB/OR/XOR instructions
Four variants: promoted legacy, ND (new data destination), NF (no flags update) and NF_ND (NF + ND).
1 parent 9f4b6e1 commit f0e17f0

37 files changed

+7107
-87
lines changed

llvm/include/llvm/Support/X86DisassemblerDecoderCommon.h

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,8 @@ enum attributeBits {
7070
ATTR_EVEXKZ = 0x1 << 11,
7171
ATTR_EVEXB = 0x1 << 12,
7272
ATTR_REX2 = 0x1 << 13,
73-
ATTR_max = 0x1 << 14,
73+
ATTR_EVEXNF = 0x1 << 14,
74+
ATTR_max = 0x1 << 15,
7475
};
7576

7677
// Combinations of the above attributes that are relevant to instruction
@@ -137,12 +138,15 @@ enum attributeBits {
137138
ENUM_ENTRY(IC_VEX_L_W_XD, 5, "requires VEX, L, W and XD prefix") \
138139
ENUM_ENTRY(IC_VEX_L_W_OPSIZE, 5, "requires VEX, L, W and OpSize") \
139140
ENUM_ENTRY(IC_EVEX, 1, "requires an EVEX prefix") \
141+
ENUM_ENTRY(IC_EVEX_NF, 2, "requires EVEX and NF prefix") \
140142
ENUM_ENTRY(IC_EVEX_XS, 2, "requires EVEX and the XS prefix") \
141143
ENUM_ENTRY(IC_EVEX_XD, 2, "requires EVEX and the XD prefix") \
142144
ENUM_ENTRY(IC_EVEX_OPSIZE, 2, "requires EVEX and the OpSize prefix") \
145+
ENUM_ENTRY(IC_EVEX_OPSIZE_NF, 3, "requires EVEX, NF and the OpSize prefix") \
143146
ENUM_ENTRY(IC_EVEX_OPSIZE_ADSIZE, 3, \
144147
"requires EVEX, OPSIZE and the ADSIZE prefix") \
145148
ENUM_ENTRY(IC_EVEX_W, 3, "requires EVEX and the W prefix") \
149+
ENUM_ENTRY(IC_EVEX_W_NF, 4, "requires EVEX, W and NF prefix") \
146150
ENUM_ENTRY(IC_EVEX_W_XS, 4, "requires EVEX, W, and XS prefix") \
147151
ENUM_ENTRY(IC_EVEX_W_XD, 4, "requires EVEX, W, and XD prefix") \
148152
ENUM_ENTRY(IC_EVEX_W_OPSIZE, 4, "requires EVEX, W, and OpSize") \
@@ -187,10 +191,13 @@ enum attributeBits {
187191
ENUM_ENTRY(IC_EVEX_L2_W_XD_K, 4, "requires EVEX_K, L2, W and XD prefix") \
188192
ENUM_ENTRY(IC_EVEX_L2_W_OPSIZE_K, 4, "requires EVEX_K, L2, W and OpSize") \
189193
ENUM_ENTRY(IC_EVEX_B, 1, "requires an EVEX_B prefix") \
194+
ENUM_ENTRY(IC_EVEX_B_NF, 2, "requires EVEX_NF and EVEX_B prefix") \
190195
ENUM_ENTRY(IC_EVEX_XS_B, 2, "requires EVEX_B and the XS prefix") \
191196
ENUM_ENTRY(IC_EVEX_XD_B, 2, "requires EVEX_B and the XD prefix") \
192197
ENUM_ENTRY(IC_EVEX_OPSIZE_B, 2, "requires EVEX_B and the OpSize prefix") \
198+
ENUM_ENTRY(IC_EVEX_OPSIZE_B_NF, 3, "requires EVEX_B, NF and Opsize prefix") \
193199
ENUM_ENTRY(IC_EVEX_W_B, 3, "requires EVEX_B and the W prefix") \
200+
ENUM_ENTRY(IC_EVEX_W_B_NF, 4, "requires EVEX_NF, EVEX_B and the W prefix") \
194201
ENUM_ENTRY(IC_EVEX_W_XS_B, 4, "requires EVEX_B, W, and XS prefix") \
195202
ENUM_ENTRY(IC_EVEX_W_XD_B, 4, "requires EVEX_B, W, and XD prefix") \
196203
ENUM_ENTRY(IC_EVEX_W_OPSIZE_B, 4, "requires EVEX_B, W, and OpSize") \

llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -108,6 +108,8 @@ class X86AsmParser : public MCTargetAsmParser {
108108

109109
// Does this instruction use apx extended register?
110110
bool UseApxExtendedReg = false;
111+
// Is this instruction explicitly required not to update flags?
112+
bool ForcedNoFlag = false;
111113

112114
private:
113115
SMLoc consumeToken() {
@@ -3125,6 +3127,7 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
31253127
ForcedVEXEncoding = VEXEncoding_Default;
31263128
ForcedDispEncoding = DispEncoding_Default;
31273129
UseApxExtendedReg = false;
3130+
ForcedNoFlag = false;
31283131

31293132
// Parse pseudo prefixes.
31303133
while (true) {
@@ -3149,6 +3152,8 @@ bool X86AsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
31493152
ForcedDispEncoding = DispEncoding_Disp8;
31503153
else if (Prefix == "disp32")
31513154
ForcedDispEncoding = DispEncoding_Disp32;
3155+
else if (Prefix == "nf")
3156+
ForcedNoFlag = true;
31523157
else
31533158
return Error(NameLoc, "unknown prefix");
31543159

@@ -3996,6 +4001,8 @@ unsigned X86AsmParser::checkTargetMatchPredicate(MCInst &Inst) {
39964001

39974002
if (UseApxExtendedReg && !X86II::canUseApxExtendedReg(MCID))
39984003
return Match_Unsupported;
4004+
if (ForcedNoFlag != static_cast<bool>(MCID.TSFlags & X86II::EVEX_NF))
4005+
return Match_Unsupported;
39994006

40004007
if (ForcedVEXEncoding == VEXEncoding_EVEX &&
40014008
(MCID.TSFlags & X86II::EncodingMask) != X86II::EVEX)

llvm/lib/Target/X86/Disassembler/X86Disassembler.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1169,7 +1169,11 @@ static int getInstructionID(struct InternalInstruction *insn,
11691169
attrMask |= ATTR_EVEXKZ;
11701170
if (bFromEVEX4of4(insn->vectorExtensionPrefix[3]))
11711171
attrMask |= ATTR_EVEXB;
1172-
if (aaaFromEVEX4of4(insn->vectorExtensionPrefix[3]))
1172+
// nf bit is the MSB of aaa
1173+
if (nfFromEVEX4of4(insn->vectorExtensionPrefix[3]) &&
1174+
insn->opcodeType == MAP4)
1175+
attrMask |= ATTR_EVEXNF;
1176+
else if (aaaFromEVEX4of4(insn->vectorExtensionPrefix[3]))
11731177
attrMask |= ATTR_EVEXK;
11741178
if (lFromEVEX4of4(insn->vectorExtensionPrefix[3]))
11751179
attrMask |= ATTR_VEXL;

llvm/lib/Target/X86/Disassembler/X86DisassemblerDecoder.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -103,6 +103,7 @@ namespace X86Disassembler {
103103
#define bFromEVEX4of4(evex) bitFromOffset4(evex)
104104
#define v2FromEVEX4of4(evex) invertedBitFromOffset3(evex)
105105
#define aaaFromEVEX4of4(evex) threeBitsFromOffset0(evex)
106+
#define nfFromEVEX4of4(evex) bitFromOffset2(evex)
106107

107108
// These enums represent Intel registers for use by the decoder.
108109
#define REGS_8BIT \

llvm/lib/Target/X86/MCTargetDesc/X86BaseInfo.h

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -870,7 +870,10 @@ enum : uint64_t {
870870
ExplicitVEXPrefix = 2ULL << ExplicitOpPrefixShift,
871871
/// For instructions that are promoted to EVEX space for EGPR.
872872
ExplicitEVEXPrefix = 3ULL << ExplicitOpPrefixShift,
873-
ExplicitOpPrefixMask = 3ULL << ExplicitOpPrefixShift
873+
ExplicitOpPrefixMask = 3ULL << ExplicitOpPrefixShift,
874+
/// EVEX_NF - Set if this instruction has EVEX.NF field set.
875+
EVEX_NFShift = ExplicitOpPrefixShift + 2,
876+
EVEX_NF = 1ULL << EVEX_NFShift
874877
};
875878

876879
/// \returns true if the instruction with given opcode is a prefix.
@@ -992,6 +995,12 @@ inline unsigned getOperandBias(const MCInstrDesc &Desc) {
992995
}
993996
}
994997

998+
/// \returns true if the instruction has a NDD (new data destination).
999+
inline bool isND(uint64_t TSFlags) {
1000+
return (TSFlags & X86II::OpMapMask) == X86II::T_MAP4 &&
1001+
(TSFlags & X86II::EVEX_B) && (TSFlags & X86II::VEX_4V);
1002+
}
1003+
9951004
/// \returns operand # for the first field of the memory operand or -1 if no
9961005
/// memory operands.
9971006
/// NOTE: This ignores tied operands. If there is a tied register which is
@@ -1018,7 +1027,7 @@ inline int getMemoryOperandNo(uint64_t TSFlags) {
10181027
return -1;
10191028
case X86II::MRMDestMem:
10201029
case X86II::MRMDestMemFSIB:
1021-
return 0;
1030+
return isND(TSFlags);
10221031
case X86II::MRMSrcMem:
10231032
case X86II::MRMSrcMemFSIB:
10241033
// Start from 1, skip any registers encoded in VEX_VVVV or I8IMM, or a

llvm/lib/Target/X86/MCTargetDesc/X86InstPrinterCommon.cpp

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -369,6 +369,9 @@ void X86InstPrinterCommon::printInstFlags(const MCInst *MI, raw_ostream &O,
369369
else if (Flags & X86::IP_HAS_REPEAT)
370370
O << "\trep\t";
371371

372+
if (TSFlags & X86II::EVEX_NF)
373+
O << "\t{nf}";
374+
372375
// These all require a pseudo prefix
373376
if ((Flags & X86::IP_USE_VEX) ||
374377
(TSFlags & X86II::ExplicitOpPrefixMask) == X86II::ExplicitVEXPrefix)

llvm/lib/Target/X86/MCTargetDesc/X86MCCodeEmitter.cpp

Lines changed: 39 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,7 @@ class X86OpcodePrefixHelper {
251251
void setAAA(const MCInst &MI, unsigned OpNum) {
252252
EVEX_aaa = getRegEncoding(MI, OpNum);
253253
}
254+
void setNF(bool V) { EVEX_aaa |= V << 2; }
254255

255256
X86OpcodePrefixHelper(const MCRegisterInfo &MRI)
256257
: W(0), R(0), X(0), B(0), M(0), R2(0), X2(0), B2(0), VEX_4V(0), VEX_L(0),
@@ -987,6 +988,7 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
987988
}
988989

989990
Prefix.setW(TSFlags & X86II::REX_W);
991+
Prefix.setNF(TSFlags & X86II::EVEX_NF);
990992

991993
bool HasEVEX_K = TSFlags & X86II::EVEX_K;
992994
bool HasVEX_4V = TSFlags & X86II::VEX_4V;
@@ -1049,6 +1051,8 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
10491051

10501052
bool EncodeRC = false;
10511053
uint8_t EVEX_rc = 0;
1054+
bool IsND = X86II::isND(TSFlags);
1055+
10521056
unsigned CurOp = X86II::getOperandBias(Desc);
10531057

10541058
switch (TSFlags & X86II::FormMask) {
@@ -1073,16 +1077,21 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
10731077
// MemAddr, src1(VEX_4V), src2(ModR/M)
10741078
// MemAddr, src1(ModR/M), imm8
10751079
//
1080+
// NDD:
1081+
// dst(VEX_4V), MemAddr, src1(ModR/M)
10761082
Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
10771083
Prefix.setXX2(MI, MemOperand + X86::AddrIndexReg);
10781084
Prefix.setV2(MI, MemOperand + X86::AddrIndexReg, HasVEX_4V);
10791085

1086+
if (IsND)
1087+
Prefix.set4VV2(MI, CurOp++);
1088+
10801089
CurOp += X86::AddrNumOperands;
10811090

10821091
if (HasEVEX_K)
10831092
Prefix.setAAA(MI, CurOp++);
10841093

1085-
if (HasVEX_4V)
1094+
if (!IsND && HasVEX_4V)
10861095
Prefix.set4VV2(MI, CurOp++);
10871096

10881097
Prefix.setRR2(MI, CurOp++);
@@ -1098,12 +1107,18 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
10981107
//
10991108
// FMA4:
11001109
// dst(ModR/M.reg), src1(VEX_4V), src2(ModR/M), src3(Imm[7:4])
1110+
//
1111+
// NDD:
1112+
// dst(VEX_4V), src1(ModR/M), MemAddr
1113+
if (IsND)
1114+
Prefix.set4VV2(MI, CurOp++);
1115+
11011116
Prefix.setRR2(MI, CurOp++);
11021117

11031118
if (HasEVEX_K)
11041119
Prefix.setAAA(MI, CurOp++);
11051120

1106-
if (HasVEX_4V)
1121+
if (!IsND && HasVEX_4V)
11071122
Prefix.set4VV2(MI, CurOp++);
11081123

11091124
Prefix.setBB2(MI, MemOperand + X86::AddrBaseReg);
@@ -1160,12 +1175,17 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
11601175
//
11611176
// FMA4:
11621177
// dst(ModR/M.reg), src1(VEX_4V), src2(Imm[7:4]), src3(ModR/M),
1178+
//
1179+
// NDD:
1180+
// dst(VEX_4V), src1(ModR/M.reg), src2(ModR/M)
1181+
if (IsND)
1182+
Prefix.set4VV2(MI, CurOp++);
11631183
Prefix.setRR2(MI, CurOp++);
11641184

11651185
if (HasEVEX_K)
11661186
Prefix.setAAA(MI, CurOp++);
11671187

1168-
if (HasVEX_4V)
1188+
if (!IsND && HasVEX_4V)
11691189
Prefix.set4VV2(MI, CurOp++);
11701190

11711191
Prefix.setBB2(MI, CurOp);
@@ -1209,14 +1229,19 @@ X86MCCodeEmitter::emitVEXOpcodePrefix(int MemOperand, const MCInst &MI,
12091229
// dst(ModR/M), src(ModR/M)
12101230
// dst(ModR/M), src(ModR/M), imm8
12111231
// dst(ModR/M), src1(VEX_4V), src2(ModR/M)
1232+
//
1233+
// NDD:
1234+
// dst(VEX_4V), src1(ModR/M), src2(ModR/M)
1235+
if (IsND)
1236+
Prefix.set4VV2(MI, CurOp++);
12121237
Prefix.setBB2(MI, CurOp);
12131238
Prefix.setX(MI, CurOp, 4);
12141239
++CurOp;
12151240

12161241
if (HasEVEX_K)
12171242
Prefix.setAAA(MI, CurOp++);
12181243

1219-
if (HasVEX_4V)
1244+
if (!IsND && HasVEX_4V)
12201245
Prefix.set4VV2(MI, CurOp++);
12211246

12221247
Prefix.setRR2(MI, CurOp++);
@@ -1508,6 +1533,8 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI,
15081533

15091534
unsigned OpcodeOffset = 0;
15101535

1536+
bool IsND = X86II::isND(TSFlags);
1537+
15111538
uint64_t Form = TSFlags & X86II::FormMask;
15121539
switch (Form) {
15131540
default:
@@ -1576,6 +1603,8 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI,
15761603

15771604
if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
15781605
++SrcRegNum;
1606+
if (IsND) // Skip the NDD operand encoded in EVEX_VVVV
1607+
++CurOp;
15791608

15801609
emitRegModRMByte(MI.getOperand(CurOp),
15811610
getX86RegNum(MI.getOperand(SrcRegNum)), CB);
@@ -1602,6 +1631,9 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI,
16021631
if (HasVEX_4V) // Skip 1st src (which is encoded in VEX_VVVV)
16031632
++SrcRegNum;
16041633

1634+
if (IsND) // Skip new data destination
1635+
++CurOp;
1636+
16051637
bool ForceSIB = (Form == X86II::MRMDestMemFSIB);
16061638
emitMemModRMByte(MI, CurOp, getX86RegNum(MI.getOperand(SrcRegNum)), TSFlags,
16071639
Kind, StartByte, CB, Fixups, STI, ForceSIB);
@@ -1669,6 +1701,9 @@ void X86MCCodeEmitter::encodeInstruction(const MCInst &MI,
16691701
case X86II::MRMSrcMem: {
16701702
unsigned FirstMemOp = CurOp + 1;
16711703

1704+
if (IsND) // Skip new data destination
1705+
CurOp++;
1706+
16721707
if (HasEVEX_K) // Skip writemask
16731708
++FirstMemOp;
16741709

0 commit comments

Comments
 (0)