diff --git a/lib/Target/X86/AsmParser/X86AsmParser.cpp b/lib/Target/X86/AsmParser/X86AsmParser.cpp index cdfc26bb335..f1e8958f503 100644 --- a/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -632,8 +632,43 @@ ParseInstruction(const StringRef &Name, SMLoc NameLoc, .Case("cmovnzl", "cmovnel") .Case("cmovzl", "cmovel") .Default(Name); + + // FIXME: Hack to recognize cmp{ss,sd,ps,pd}. + const MCExpr *ExtraImmOp = 0; + if (PatchedName.startswith("cmp") && + (PatchedName.endswith("ss") || PatchedName.endswith("sd") || + PatchedName.endswith("ps") || PatchedName.endswith("pd"))) { + unsigned SSEComparisonCode = StringSwitch( + PatchedName.slice(3, PatchedName.size() - 2)) + .Case("eq", 0) + .Case("lt", 1) + .Case("le", 2) + .Case("unord", 3) + .Case("neq", 4) + .Case("nlt", 5) + .Case("nle", 6) + .Case("ord", 7) + .Default(~0U); + if (SSEComparisonCode != ~0U) { + ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode, + getParser().getContext()); + if (PatchedName.endswith("ss")) { + PatchedName = "cmpss"; + } else if (PatchedName.endswith("sd")) { + PatchedName = "cmpsd"; + } else if (PatchedName.endswith("ps")) { + PatchedName = "cmpps"; + } else { + assert(PatchedName.endswith("pd") && "Unexpected mnemonic!"); + PatchedName = "cmppd"; + } + } + } Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); + if (ExtraImmOp) + Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc)); + if (getLexer().isNot(AsmToken::EndOfStatement)) { // Parse '*' modifier. @@ -648,7 +683,7 @@ ParseInstruction(const StringRef &Name, SMLoc NameLoc, Operands.push_back(Op); else return true; - + while (getLexer().is(AsmToken::Comma)) { Parser.Lex(); // Eat the comma. diff --git a/test/MC/AsmParser/X86/x86_32-new-encoder.s b/test/MC/AsmParser/X86/x86_32-new-encoder.s index f4e6857ba30..19af126027e 100644 --- a/test/MC/AsmParser/X86/x86_32-new-encoder.s +++ b/test/MC/AsmParser/X86/x86_32-new-encoder.s @@ -243,3 +243,37 @@ retl // CHECK: cmpsd $0, (%eax), %xmm1 // CHECK: encoding: [0xf2,0x0f,0xc2,0x08,0x00] cmpsd $0, 0(%eax), %xmm1 + +// Check matching of instructions which embed the SSE comparison code. + +// CHECK: cmpps $0, %xmm0, %xmm1 +// CHECK: encoding: [0x0f,0xc2,0xc8,0x00] + cmpeqps %xmm0, %xmm1 + +// CHECK: cmppd $1, %xmm0, %xmm1 +// CHECK: encoding: [0x66,0x0f,0xc2,0xc8,0x01] + cmpltpd %xmm0, %xmm1 + +// CHECK: cmpss $2, %xmm0, %xmm1 +// CHECK: encoding: [0xf3,0x0f,0xc2,0xc8,0x02] + cmpless %xmm0, %xmm1 + +// CHECK: cmppd $3, %xmm0, %xmm1 +// CHECK: encoding: [0x66,0x0f,0xc2,0xc8,0x03] + cmpunordpd %xmm0, %xmm1 + +// CHECK: cmpps $4, %xmm0, %xmm1 +// CHECK: encoding: [0x0f,0xc2,0xc8,0x04] + cmpneqps %xmm0, %xmm1 + +// CHECK: cmppd $5, %xmm0, %xmm1 +// CHECK: encoding: [0x66,0x0f,0xc2,0xc8,0x05] + cmpnltpd %xmm0, %xmm1 + +// CHECK: cmpss $6, %xmm0, %xmm1 +// CHECK: encoding: [0xf3,0x0f,0xc2,0xc8,0x06] + cmpnless %xmm0, %xmm1 + +// CHECK: cmpsd $7, %xmm0, %xmm1 +// CHECK: encoding: [0xf2,0x0f,0xc2,0xc8,0x07] + cmpordsd %xmm0, %xmm1