mirror of
https://github.com/capstone-engine/llvm-capstone.git
synced 2024-12-23 07:52:06 +00:00
AVX-512: Assembly parsing of broadcast semantic in AVX-512; imlemented by Nis Zinovy (zinovy.y.nis@intel.com)
Fixed truncate i32 to i1; a test will be provided in the next commit. llvm-svn: 201757
This commit is contained in:
parent
830f0c3899
commit
c96570172a
@ -605,6 +605,13 @@ private:
|
||||
return Parser.Error(L, Msg, Ranges);
|
||||
}
|
||||
|
||||
bool ErrorAndEatStatement(SMLoc L, const Twine &Msg,
|
||||
ArrayRef<SMRange> Ranges = None,
|
||||
bool MatchingInlineAsm = false) {
|
||||
Parser.eatToEndOfStatement();
|
||||
return Error(L, Msg, Ranges, MatchingInlineAsm);
|
||||
}
|
||||
|
||||
X86Operand *ErrorOperand(SMLoc Loc, StringRef Msg) {
|
||||
Error(Loc, Msg);
|
||||
return 0;
|
||||
@ -652,6 +659,12 @@ private:
|
||||
/// the parsing mode (Intel vs. AT&T).
|
||||
bool doSrcDstMatch(X86Operand &Op1, X86Operand &Op2);
|
||||
|
||||
/// Parses AVX512 specific operand primitives: masked registers ({%k<NUM>}, {z})
|
||||
/// and memory broadcasting ({1to<NUM>}) primitives, updating Operands vector if required.
|
||||
/// \return \c true if no parsing errors occurred, \c false otherwise.
|
||||
bool HandleAVX512Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
const MCParsedAsmOperand &Op);
|
||||
|
||||
bool is64BitMode() const {
|
||||
// FIXME: Can tablegen auto-generate this?
|
||||
return (STI.getFeatureBits() & X86::Mode64Bit) != 0;
|
||||
@ -2027,6 +2040,72 @@ X86Operand *X86AsmParser::ParseATTOperand() {
|
||||
}
|
||||
}
|
||||
|
||||
bool X86AsmParser::HandleAVX512Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
|
||||
const MCParsedAsmOperand &Op) {
|
||||
if(STI.getFeatureBits() & X86::FeatureAVX512) {
|
||||
if (getLexer().is(AsmToken::LCurly)) {
|
||||
// Eat "{" and mark the current place.
|
||||
const SMLoc consumedToken = consumeToken();
|
||||
// Distinguish {1to<NUM>} from {%k<NUM>}.
|
||||
if(getLexer().is(AsmToken::Integer)) {
|
||||
// Parse memory broadcasting ({1to<NUM>}).
|
||||
if (getLexer().getTok().getIntVal() != 1)
|
||||
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||
"Expected 1to<NUM> at this point");
|
||||
Parser.Lex(); // Eat "1" of 1to8
|
||||
if (!getLexer().is(AsmToken::Identifier) ||
|
||||
!getLexer().getTok().getIdentifier().startswith("to"))
|
||||
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||
"Expected 1to<NUM> at this point");
|
||||
// Recognize only reasonable suffixes.
|
||||
const char *BroadcastPrimitive =
|
||||
StringSwitch<const char*>(getLexer().getTok().getIdentifier())
|
||||
.Case("to8", "{1to8}")
|
||||
.Case("to16", "{1to16}")
|
||||
.Default(0);
|
||||
if (!BroadcastPrimitive)
|
||||
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||
"Invalid memory broadcast primitive.");
|
||||
Parser.Lex(); // Eat "toN" of 1toN
|
||||
if (!getLexer().is(AsmToken::RCurly))
|
||||
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||
"Expected } at this point");
|
||||
Parser.Lex(); // Eat "}"
|
||||
Operands.push_back(X86Operand::CreateToken(BroadcastPrimitive,
|
||||
consumedToken));
|
||||
// No AVX512 specific primitives can pass
|
||||
// after memory broadcasting, so return.
|
||||
return true;
|
||||
} else {
|
||||
// Parse mask register {%k1}
|
||||
Operands.push_back(X86Operand::CreateToken("{", consumedToken));
|
||||
if (X86Operand *Op = ParseOperand()) {
|
||||
Operands.push_back(Op);
|
||||
if (!getLexer().is(AsmToken::RCurly))
|
||||
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||
"Expected } at this point");
|
||||
Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
|
||||
|
||||
// Parse "zeroing non-masked" semantic {z}
|
||||
if (getLexer().is(AsmToken::LCurly)) {
|
||||
Operands.push_back(X86Operand::CreateToken("{z}", consumeToken()));
|
||||
if (!getLexer().is(AsmToken::Identifier) ||
|
||||
getLexer().getTok().getIdentifier() != "z")
|
||||
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||
"Expected z at this point");
|
||||
Parser.Lex(); // Eat the z
|
||||
if (!getLexer().is(AsmToken::RCurly))
|
||||
return !ErrorAndEatStatement(getLexer().getLoc(),
|
||||
"Expected } at this point");
|
||||
Parser.Lex(); // Eat the }
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// ParseMemOperand: segment: disp(basereg, indexreg, scale). The '%ds:' prefix
|
||||
/// has already been parsed if present.
|
||||
X86Operand *X86AsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
|
||||
@ -2285,73 +2364,30 @@ ParseInstruction(ParseInstructionInfo &Info, StringRef Name, SMLoc NameLoc,
|
||||
if (getLexer().is(AsmToken::Star))
|
||||
Operands.push_back(X86Operand::CreateToken("*", consumeToken()));
|
||||
|
||||
// Read the first operand.
|
||||
if (X86Operand *Op = ParseOperand())
|
||||
Operands.push_back(Op);
|
||||
else {
|
||||
Parser.eatToEndOfStatement();
|
||||
return true;
|
||||
}
|
||||
|
||||
while (getLexer().is(AsmToken::Comma)) {
|
||||
Parser.Lex(); // Eat the comma.
|
||||
|
||||
// Parse and remember the operand.
|
||||
if (X86Operand *Op = ParseOperand())
|
||||
Operands.push_back(Op);
|
||||
else {
|
||||
Parser.eatToEndOfStatement();
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
if (STI.getFeatureBits() & X86::FeatureAVX512) {
|
||||
// Parse mask register {%k1}
|
||||
if (getLexer().is(AsmToken::LCurly)) {
|
||||
Operands.push_back(X86Operand::CreateToken("{", consumeToken()));
|
||||
if (X86Operand *Op = ParseOperand()) {
|
||||
Operands.push_back(Op);
|
||||
if (!getLexer().is(AsmToken::RCurly)) {
|
||||
SMLoc Loc = getLexer().getLoc();
|
||||
Parser.eatToEndOfStatement();
|
||||
return Error(Loc, "Expected } at this point");
|
||||
}
|
||||
Operands.push_back(X86Operand::CreateToken("}", consumeToken()));
|
||||
} else {
|
||||
Parser.eatToEndOfStatement();
|
||||
// Read the operands.
|
||||
while(1) {
|
||||
if (X86Operand *Op = ParseOperand()) {
|
||||
Operands.push_back(Op);
|
||||
if (!HandleAVX512Operand(Operands, *Op))
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
Parser.eatToEndOfStatement();
|
||||
return true;
|
||||
}
|
||||
// TODO: add parsing of broadcasts {1to8}, {1to16}
|
||||
// Parse "zeroing non-masked" semantic {z}
|
||||
if (getLexer().is(AsmToken::LCurly)) {
|
||||
Operands.push_back(X86Operand::CreateToken("{z}", consumeToken()));
|
||||
if (!getLexer().is(AsmToken::Identifier) || getLexer().getTok().getIdentifier() != "z") {
|
||||
SMLoc Loc = getLexer().getLoc();
|
||||
Parser.eatToEndOfStatement();
|
||||
return Error(Loc, "Expected z at this point");
|
||||
}
|
||||
Parser.Lex(); // Eat the z
|
||||
if (!getLexer().is(AsmToken::RCurly)) {
|
||||
SMLoc Loc = getLexer().getLoc();
|
||||
Parser.eatToEndOfStatement();
|
||||
return Error(Loc, "Expected } at this point");
|
||||
}
|
||||
Parser.Lex(); // Eat the }
|
||||
}
|
||||
}
|
||||
// check for comma and eat it
|
||||
if (getLexer().is(AsmToken::Comma))
|
||||
Parser.Lex();
|
||||
else
|
||||
break;
|
||||
}
|
||||
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement)) {
|
||||
SMLoc Loc = getLexer().getLoc();
|
||||
Parser.eatToEndOfStatement();
|
||||
return Error(Loc, "unexpected token in argument list");
|
||||
}
|
||||
}
|
||||
if (getLexer().isNot(AsmToken::EndOfStatement))
|
||||
return ErrorAndEatStatement(getLexer().getLoc(), "unexpected token in argument list");
|
||||
}
|
||||
|
||||
if (getLexer().is(AsmToken::EndOfStatement))
|
||||
Parser.Lex(); // Consume the EndOfStatement
|
||||
else if (isPrefix && getLexer().is(AsmToken::Slash))
|
||||
Parser.Lex(); // Consume the prefix separator Slash
|
||||
// Consume the EndOfStatement or the prefix separator Slash
|
||||
if (getLexer().is(AsmToken::EndOfStatement) || isPrefix && getLexer().is(AsmToken::Slash))
|
||||
Parser.Lex();
|
||||
|
||||
if (ExtraImmOp && isParsingIntelSyntax())
|
||||
Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
|
||||
|
@ -956,11 +956,16 @@ let Predicates = [HasAVX512] in {
|
||||
(COPY_TO_REGCLASS (KMOVWkm addr:$src), VK8)>;
|
||||
|
||||
def : Pat<(i1 (trunc (i32 GR32:$src))),
|
||||
(COPY_TO_REGCLASS (KMOVWkr $src), VK1)>;
|
||||
(COPY_TO_REGCLASS (KMOVWkr (AND32ri $src, (i32 1))), VK1)>;
|
||||
|
||||
def : Pat<(i1 (trunc (i8 GR8:$src))),
|
||||
(COPY_TO_REGCLASS
|
||||
(KMOVWkr (SUBREG_TO_REG (i32 0), GR8:$src, sub_8bit)), VK1)>;
|
||||
(COPY_TO_REGCLASS
|
||||
(KMOVWkr (AND32ri (SUBREG_TO_REG (i32 0), GR8:$src, sub_8bit), (i32 1))),
|
||||
VK1)>;
|
||||
def : Pat<(i1 (trunc (i16 GR16:$src))),
|
||||
(COPY_TO_REGCLASS
|
||||
(KMOVWkr (AND32ri (SUBREG_TO_REG (i32 0), $src, sub_16bit), (i32 1))),
|
||||
VK1)>;
|
||||
|
||||
def : Pat<(i32 (zext VK1:$src)), (KMOVWrk (COPY_TO_REGCLASS VK1:$src, VK16))>;
|
||||
def : Pat<(i8 (zext VK1:$src)),
|
||||
|
@ -51,3 +51,11 @@ vmovd %xmm22, -84(%rsp)
|
||||
// CHECK: vextractps
|
||||
// CHECK: encoding: [0x62,0xe3,0x7d,0x08,0x17,0x61,0x1f,0x02]
|
||||
vextractps $2, %xmm20, 124(%rcx)
|
||||
|
||||
// CHECK: vaddpd {{.*}}{1to8}
|
||||
// CHECK: encoding: [0x62,0x61,0xdd,0x50,0x58,0x74,0xf7,0x40]
|
||||
vaddpd 512(%rdi, %rsi, 8) {1to8}, %zmm20, %zmm30
|
||||
|
||||
// CHECK: vaddps {{.*}}{1to16}
|
||||
// CHECK: encoding: [0x62,0x61,0x5c,0x50,0x58,0xb4,0xf7,0x00,0x02,0x00,0x00]
|
||||
vaddps 512(%rdi, %rsi, 8) {1to16}, %zmm20, %zmm30
|
||||
|
Loading…
Reference in New Issue
Block a user