diff --git a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp --- a/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp +++ b/llvm/lib/Target/X86/AsmParser/X86AsmParser.cpp @@ -848,6 +848,8 @@ const SMLoc &StartLoc, SMLoc &EndLoc); + X86::CondCode ParseConditionCode(StringRef CCode); + bool ParseIntelMemoryOperandSize(unsigned &Size); std::unique_ptr CreateMemForInlineAsm(unsigned SegReg, const MCExpr *Disp, unsigned BaseReg, @@ -2005,6 +2007,29 @@ } } +// X86::COND_INVALID if not a recognized condition code or alternate mnemonic, +// otherwise the EFLAGS Condition Code enumerator. +X86::CondCode X86AsmParser::ParseConditionCode(StringRef CC) { + return StringSwitch(CC) + .Case("o", X86::COND_O) // Overflow + .Case("no", X86::COND_NO) // No Overflow + .Cases("b", "nae", X86::COND_B) // Below/Neither Above nor Equal + .Cases("ae", "nb", X86::COND_AE) // Above or Equal/Not Below + .Cases("e", "z", X86::COND_E) // Equal/Zero + .Cases("ne", "nz", X86::COND_NE) // Not Equal/Not Zero + .Cases("be", "na", X86::COND_BE) // Below or Equal/Not Above + .Cases("a", "nbe", X86::COND_A) // Above/Neither Below nor Equal + .Case("s", X86::COND_S) // Sign + .Case("ns", X86::COND_NS) // No Sign + .Cases("p", "pe", X86::COND_P) // Parity/Parity Even + .Cases("np", "po", X86::COND_NP) // No Parity/Parity Odd + .Cases("l", "nge", X86::COND_L) // Less/Neither Greater nor Equal + .Cases("ge", "nl", X86::COND_GE) // Greater or Equal/Not Less + .Cases("le", "ng", X86::COND_LE) // Less or Equal/Not Greater + .Cases("g", "nle", X86::COND_G) // Greater/Neither Less nor Equal + .Default(X86::COND_INVALID); +} + // true on failure, false otherwise // If no {z} mark was found - Parser doesn't advance bool X86AsmParser::ParseZ(std::unique_ptr &Z, @@ -2354,16 +2379,20 @@ StringRef PatchedName = Name; - if ((Name.equals("jmp") || Name.equals("jc") || Name.equals("jz")) && - isParsingIntelSyntax() && isParsingInlineAsm()) { + // Hack to skip "short" following Jcc. + if (isParsingIntelSyntax() && + (PatchedName == "jmp" || + (PatchedName.startswith("j") && + ParseConditionCode(PatchedName.substr(1)) != X86::COND_INVALID))) { StringRef NextTok = Parser.getTok().getString(); if (NextTok == "short") { SMLoc NameEndLoc = NameLoc.getFromPointer(NameLoc.getPointer() + Name.size()); - // Eat the short keyword + // Eat the short keyword. Parser.Lex(); - // MS ignores the short keyword, it determines the jmp type based - // on the distance of the label + // MS and GAS ignore the short keyword; they both determine the jmp type + // based on the distance of the label. (NASM does emit different code with + // and without "short," though.) InstInfo->AsmRewrites->emplace_back(AOK_Skip, NameEndLoc, NextTok.size() + 1); } @@ -2374,7 +2403,7 @@ PatchedName != "setb" && PatchedName != "setnb") PatchedName = PatchedName.substr(0, Name.size()-1); - unsigned ComparisonCode = ~0U; + unsigned ComparisonPredicate = ~0U; // FIXME: Hack to recognize cmp{ss,sd,ps,pd}. if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) && @@ -2442,9 +2471,9 @@ else if (PatchedName.endswith("pd")) PatchedName = IsVCMP ? "vcmppd" : "cmppd"; else - llvm_unreachable("Unexpecte suffix!"); + llvm_unreachable("Unexpected suffix!"); - ComparisonCode = CC; + ComparisonPredicate = CC; } } @@ -2473,7 +2502,7 @@ case 'q': PatchedName = SuffixSize == 2 ? "vpcmpuq" : "vpcmpq"; break; } // Set up the immediate to push into the operands later. - ComparisonCode = CC; + ComparisonPredicate = CC; } } @@ -2502,7 +2531,7 @@ case 'q': PatchedName = SuffixSize == 2 ? "vpcomuq" : "vpcomq"; break; } // Set up the immediate to push into the operands later. - ComparisonCode = CC; + ComparisonPredicate = CC; } } @@ -2578,8 +2607,8 @@ Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc)); // Push the immediate if we extracted one from the mnemonic. - if (ComparisonCode != ~0U && !isParsingIntelSyntax()) { - const MCExpr *ImmOp = MCConstantExpr::create(ComparisonCode, + if (ComparisonPredicate != ~0U && !isParsingIntelSyntax()) { + const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate, getParser().getContext()); Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc)); } @@ -2619,8 +2648,8 @@ } // Push the immediate if we extracted one from the mnemonic. - if (ComparisonCode != ~0U && isParsingIntelSyntax()) { - const MCExpr *ImmOp = MCConstantExpr::create(ComparisonCode, + if (ComparisonPredicate != ~0U && isParsingIntelSyntax()) { + const MCExpr *ImmOp = MCConstantExpr::create(ComparisonPredicate, getParser().getContext()); Operands.push_back(X86Operand::CreateImm(ImmOp, NameLoc, NameLoc)); } diff --git a/llvm/test/MC/X86/intel-syntax.s b/llvm/test/MC/X86/intel-syntax.s --- a/llvm/test/MC/X86/intel-syntax.s +++ b/llvm/test/MC/X86/intel-syntax.s @@ -64,6 +64,10 @@ jmp FWORD ptr [rax] // CHECK: ljmpq *(%rax) ljmp [rax] +// CHECK: jmp _foo + jmp short _foo +// CHECK: jp _foo + jpe short _foo // CHECK: movl $257, -4(%rsp) mov DWORD PTR [RSP - 4], 257