diff --git a/llvm/include/llvm/MC/MCAsmInfo.h b/llvm/include/llvm/MC/MCAsmInfo.h
--- a/llvm/include/llvm/MC/MCAsmInfo.h
+++ b/llvm/include/llvm/MC/MCAsmInfo.h
@@ -156,6 +156,10 @@
   /// Defaults to false.
   bool AllowAtInName = false;
 
+  /// This is true if the assembler allows $ @ ? characters at the start of
+  /// symbol names. Defaults to false.
+  bool AllowSymbolAtNameStart = false;
+
   /// If this is true, symbol names with invalid characters will be printed in
   /// quotes.
   bool SupportsQuotedNames = true;
@@ -532,6 +536,7 @@
   const char *getCode64Directive() const { return Code64Directive; }
   unsigned getAssemblerDialect() const { return AssemblerDialect; }
   bool doesAllowAtInName() const { return AllowAtInName; }
+  bool doesAllowSymbolAtNameStart() const { return AllowSymbolAtNameStart; }
   bool supportsNameQuoting() const { return SupportsQuotedNames; }
 
   bool doesSupportDataRegionDirectives() const {
diff --git a/llvm/include/llvm/MC/MCParser/AsmLexer.h b/llvm/include/llvm/MC/MCParser/AsmLexer.h
--- a/llvm/include/llvm/MC/MCParser/AsmLexer.h
+++ b/llvm/include/llvm/MC/MCParser/AsmLexer.h
@@ -30,6 +30,7 @@
   bool IsAtStartOfLine = true;
   bool IsAtStartOfStatement = true;
   bool IsPeeking = false;
+  bool EndStatementAtEOF = true;
 
 protected:
   /// LexToken - Read the next token and return its code.
@@ -41,7 +42,8 @@
   AsmLexer &operator=(const AsmLexer &) = delete;
   ~AsmLexer() override;
 
-  void setBuffer(StringRef Buf, const char *ptr = nullptr);
+  void setBuffer(StringRef Buf, const char *ptr = nullptr,
+                 bool EndStatementAtEOF = true);
 
   StringRef LexUntilEndOfStatement() override;
 
diff --git a/llvm/include/llvm/MC/MCParser/MCAsmParser.h b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
--- a/llvm/include/llvm/MC/MCParser/MCAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCAsmParser.h
@@ -250,6 +250,10 @@
   /// characters and return the string contents.
   virtual bool parseEscapedString(std::string &Data) = 0;
 
+  /// Parse an angle-bracket delimited string at the current position if one is
+  /// present, returning the string contents.
+  virtual bool parseAngleBracketString(std::string &Data) = 0;
+
   /// Skip to the end of the current statement, for error recovery.
   virtual void eatToEndOfStatement() = 0;
 
@@ -304,6 +308,9 @@
 MCAsmParser *createMCAsmParser(SourceMgr &, MCContext &, MCStreamer &,
                                const MCAsmInfo &, unsigned CB = 0);
 
+MCAsmParser *createMCMasmParser(SourceMgr &, MCContext &, MCStreamer &,
+                                const MCAsmInfo &, unsigned CB = 0);
+
 } // end namespace llvm
 
 #endif // LLVM_MC_MCPARSER_MCASMPARSER_H
diff --git a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
--- a/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
+++ b/llvm/include/llvm/MC/MCParser/MCTargetAsmParser.h
@@ -376,6 +376,9 @@
   virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
                              SMLoc &EndLoc) = 0;
 
+  virtual OperandMatchResultTy
+  tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) = 0;
+
   /// ParseInstruction - Parse one assembly instruction.
   ///
   /// The parser is positioned following the instruction name. The target
diff --git a/llvm/include/llvm/MC/MCStreamer.h b/llvm/include/llvm/MC/MCStreamer.h
--- a/llvm/include/llvm/MC/MCStreamer.h
+++ b/llvm/include/llvm/MC/MCStreamer.h
@@ -399,7 +399,7 @@
     --I;
     MCSectionSubPair NewSection = I->first;
 
-    if (OldSection != NewSection)
+    if (NewSection.first && OldSection != NewSection)
       ChangeSection(NewSection.first, NewSection.second);
     SectionStack.pop_back();
     return true;
diff --git a/llvm/include/llvm/MC/MCTargetOptions.h b/llvm/include/llvm/MC/MCTargetOptions.h
--- a/llvm/include/llvm/MC/MCTargetOptions.h
+++ b/llvm/include/llvm/MC/MCTargetOptions.h
@@ -56,6 +56,7 @@
   int DwarfVersion = 0;
 
   std::string ABIName;
+  std::string AssemblyLanguage;
   std::string SplitDwarfFile;
 
   /// Additional paths to search for `.include` directives when using the
@@ -68,6 +69,11 @@
   /// textual name of the ABI that we want the backend to use, e.g. o32, or
   /// aapcs-linux.
   StringRef getABIName() const;
+
+  /// getAssemblyLanguage - If this returns a non-empty string this represents
+  /// the textual name of the assembly language that we will use for this
+  /// target, e.g. masm.
+  StringRef getAssemblyLanguage() const;
 };
 
 } // end namespace llvm
diff --git a/llvm/lib/MC/MCParser/AsmLexer.cpp b/llvm/lib/MC/MCParser/AsmLexer.cpp
--- a/llvm/lib/MC/MCParser/AsmLexer.cpp
+++ b/llvm/lib/MC/MCParser/AsmLexer.cpp
@@ -36,7 +36,8 @@
 
 AsmLexer::~AsmLexer() = default;
 
-void AsmLexer::setBuffer(StringRef Buf, const char *ptr) {
+void AsmLexer::setBuffer(StringRef Buf, const char *ptr,
+                         bool EndStatementAtEOF) {
   CurBuf = Buf;
 
   if (ptr)
@@ -45,6 +46,7 @@
     CurPtr = CurBuf.begin();
 
   TokStart = nullptr;
+  this->EndStatementAtEOF = EndStatementAtEOF;
 }
 
 /// ReturnError - Set the error to the specified string at the specified
@@ -584,7 +586,7 @@
 
   // If we're missing a newline at EOF, make sure we still get an
   // EndOfStatement token before the Eof token.
-  if (CurChar == EOF && !IsAtStartOfStatement) {
+  if (CurChar == EOF && !IsAtStartOfStatement && EndStatementAtEOF) {
     IsAtStartOfLine = true;
     IsAtStartOfStatement = true;
     return AsmToken(AsmToken::EndOfStatement, StringRef(TokStart, 1));
@@ -594,15 +596,24 @@
   IsAtStartOfStatement = false;
   switch (CurChar) {
   default:
-    // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
-    if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
-      return LexIdentifier();
+    if (MAI.doesAllowSymbolAtNameStart()) {
+      // Handle Microsoft-style identifier: [a-zA-Z_$.@?][a-zA-Z0-9_$.@?]*
+      if (!isDigit(CurChar) &&
+          IsIdentifierChar(CurChar, MAI.doesAllowAtInName()))
+        return LexIdentifier();
+    } else {
+      // Handle identifier: [a-zA-Z_.][a-zA-Z0-9_$.@]*
+      if (isalpha(CurChar) || CurChar == '_' || CurChar == '.')
+        return LexIdentifier();
+    }
 
     // Unknown character, emit an error.
     return ReturnError(TokStart, "invalid character in input");
   case EOF:
-    IsAtStartOfLine = true;
-    IsAtStartOfStatement = true;
+    if (EndStatementAtEOF) {
+      IsAtStartOfLine = true;
+      IsAtStartOfStatement = true;
+    }
     return AsmToken(AsmToken::Eof, StringRef(TokStart, 0));
   case 0:
   case ' ':
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/AsmParser.cpp
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/AsmParser.cpp
@@ -6,7 +6,7 @@
 //
 //===----------------------------------------------------------------------===//
 //
-// This class implements the parser for assembly files.
+// This class implements a parser for assembly files similar to gas syntax.
 //
 //===----------------------------------------------------------------------===//
 
@@ -74,9 +74,7 @@
 
 MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
 
-static cl::opt<unsigned> AsmMacroMaxNestingDepth(
-     "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
-     cl::desc("The maximum nesting depth allowed for assembly macros."));
+extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
 
 namespace {
 
@@ -645,6 +643,7 @@
   bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
   bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
   bool parseEscapedString(std::string &Data) override;
+  bool parseAngleBracketString(std::string &Data) override;
 
   const MCExpr *applyModifierToExpr(const MCExpr *E,
                                     MCSymbolRefExpr::VariantKind Variant);
@@ -1365,7 +1364,7 @@
 /// implementation. GCC does not fully support this feature and so we will not
 /// support it.
 /// TODO: Adding single quote as a string.
-static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
+static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
   assert((StrLoc.getPointer() != nullptr) &&
          "Argument to the function cannot be a NULL value");
   const char *CharPtr = StrLoc.getPointer();
@@ -1383,7 +1382,7 @@
 }
 
 /// creating a string without the escape characters '!'.
-static std::string altMacroString(StringRef AltMacroStr) {
+static std::string angleBracketString(StringRef AltMacroStr) {
   std::string Res;
   for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
     if (AltMacroStr[Pos] == '!')
@@ -2497,7 +2496,7 @@
             // is considered altMacroString!!!
             else if (AltMacroMode && Token.getString().front() == '<' &&
                      Token.is(AsmToken::String)) {
-              OS << altMacroString(Token.getStringContents());
+              OS << angleBracketString(Token.getStringContents());
             }
             // We expect no quotes around the string's contents when
             // parsing for varargs.
@@ -2690,7 +2689,7 @@
                         StringRef(StrChar, EndChar - StrChar), Value);
       FA.Value.push_back(newToken);
     } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
-               isAltmacroString(StrLoc, EndLoc)) {
+               isAngleBracketString(StrLoc, EndLoc)) {
       const char *StrChar = StrLoc.getPointer();
       const char *EndChar = EndLoc.getPointer();
       jumpToLoc(EndLoc, CurBuffer);
@@ -2969,6 +2968,21 @@
   return false;
 }
 
+bool AsmParser::parseAngleBracketString(std::string &Data) {
+  SMLoc EndLoc, StartLoc = getTok().getLoc();
+  if (isAngleBracketString(StartLoc, EndLoc)) {
+    const char *StartChar = StartLoc.getPointer() + 1;
+    const char *EndChar = EndLoc.getPointer() - 1;
+    jumpToLoc(EndLoc, CurBuffer);
+    /// Eat from '<' to '>'
+    Lex();
+
+    Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
+    return false;
+  }
+  return true;
+}
+
 /// parseDirectiveAscii:
 ///   ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
 bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
diff --git a/llvm/lib/MC/MCParser/CMakeLists.txt b/llvm/lib/MC/MCParser/CMakeLists.txt
--- a/llvm/lib/MC/MCParser/CMakeLists.txt
+++ b/llvm/lib/MC/MCParser/CMakeLists.txt
@@ -2,12 +2,14 @@
   AsmLexer.cpp
   AsmParser.cpp
   COFFAsmParser.cpp
+  COFFMasmParser.cpp
   DarwinAsmParser.cpp
   ELFAsmParser.cpp
   MCAsmLexer.cpp
   MCAsmParser.cpp
   MCAsmParserExtension.cpp
   MCTargetAsmParser.cpp
+  MasmParser.cpp
   WasmAsmParser.cpp
 
   ADDITIONAL_HEADER_DIRS
diff --git a/llvm/lib/MC/MCParser/COFFMasmParser.cpp b/llvm/lib/MC/MCParser/COFFMasmParser.cpp
new file mode 100644
--- /dev/null
+++ b/llvm/lib/MC/MCParser/COFFMasmParser.cpp
@@ -0,0 +1,386 @@
+//===- COFFMasmParser.cpp - COFF MASM Assembly Parser ---------------------===//
+//
+// Part of the LLVM Project, under the Apache License v2.0 with LLVM Exceptions.
+// See https://llvm.org/LICENSE.txt for license information.
+// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception
+//
+//===----------------------------------------------------------------------===//
+
+#include "llvm/ADT/StringRef.h"
+#include "llvm/ADT/StringSwitch.h"
+#include "llvm/ADT/Triple.h"
+#include "llvm/ADT/Twine.h"
+#include "llvm/BinaryFormat/COFF.h"
+#include "llvm/MC/MCContext.h"
+#include "llvm/MC/MCDirectives.h"
+#include "llvm/MC/MCObjectFileInfo.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParserExtension.h"
+#include "llvm/MC/MCParser/MCAsmParserUtils.h"
+#include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/MC/MCRegisterInfo.h"
+#include "llvm/MC/MCSectionCOFF.h"
+#include "llvm/MC/MCStreamer.h"
+#include "llvm/MC/SectionKind.h"
+#include "llvm/Support/SMLoc.h"
+#include <cassert>
+#include <cstdint>
+#include <limits>
+#include <utility>
+
+using namespace llvm;
+
+namespace {
+
+class COFFMasmParser : public MCAsmParserExtension {
+  template <bool (COFFMasmParser::*HandlerMethod)(StringRef, SMLoc)>
+  void addDirectiveHandler(StringRef Directive) {
+    MCAsmParser::ExtensionDirectiveHandler Handler =
+        std::make_pair(this, HandleDirective<COFFMasmParser, HandlerMethod>);
+    getParser().addDirectiveHandler(Directive, Handler);
+  }
+
+  bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+                          SectionKind Kind);
+
+  bool ParseSectionSwitch(StringRef Section, unsigned Characteristics,
+                          SectionKind Kind, StringRef COMDATSymName,
+                          COFF::COMDATType Type);
+
+  bool ParseDirectiveProc(StringRef, SMLoc);
+  bool ParseDirectiveEndProc(StringRef, SMLoc);
+  bool ParseDirectiveSegment(StringRef, SMLoc);
+  bool ParseDirectiveSegmentEnd(StringRef, SMLoc);
+  bool ParseDirectiveIncludelib(StringRef, SMLoc);
+
+  bool IgnoreDirective(StringRef, SMLoc) {
+    while (!getLexer().is(AsmToken::EndOfStatement)) {
+      Lex();
+    }
+    return false;
+  }
+
+  void Initialize(MCAsmParser &Parser) override {
+    // Call the base implementation.
+    MCAsmParserExtension::Initialize(Parser);
+
+    // x64 directives
+    // .allocstack
+    // .endprolog
+    // .pushframe
+    // .pushreg
+    // .savereg
+    // .savexmm128
+    // .setframe
+
+    // Code label directives
+    // label
+    // org
+
+    // Conditional control flow directives
+    // .break
+    // .continue
+    // .else
+    // .elseif
+    // .endif
+    // .endw
+    // .if
+    // .repeat
+    // .until
+    // .untilcxz
+    // .while
+
+    // Data allocation directives
+    // align
+    // byte/sbyte
+    // dword/sdword
+    // even
+    // fword
+    // qword
+    // real4
+    // real8
+    // real10
+    // tbyte
+    // word/sword
+
+    // Listing control directives
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".cref");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".list");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listall");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listif");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacro");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".listmacroall");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nocref");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolist");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistif");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".nolistmacro");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("page");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("subtitle");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".tfcond");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>("title");
+
+    // Macro directives
+    // endm
+    // exitm
+    // goto
+    // local
+    // macro
+    // purge
+
+    // Miscellaneous directives
+    // alias
+    // assume
+    // .fpo
+    addDirectiveHandler<&COFFMasmParser::ParseDirectiveIncludelib>(
+        "includelib");
+    // mmword
+    // option
+    // popcontext
+    // pushcontext
+    // .radix
+    // .safeseh
+    // xmmword
+    // ymmword
+
+    // Procedure directives
+    addDirectiveHandler<&COFFMasmParser::ParseDirectiveEndProc>("endp");
+    // invoke (32-bit only)
+    addDirectiveHandler<&COFFMasmParser::ParseDirectiveProc>("proc");
+    // proto
+
+    // Processor directives
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".386P");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".387");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".486P");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".586P");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".686P");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".k3d");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".mmx");
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".xmm");
+
+    // Repeat blocks directives
+    // for
+    // forc
+    // goto
+    // repeat
+    // while
+
+    // Scope directives
+    // comm
+    // externdef
+
+    // Segment directives
+    // .alpha (32-bit only, order segments alphabetically)
+    // .dosseg (32-bit only, order segments in DOS convention)
+    // .seq (32-bit only, order segments sequentially)
+    addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegmentEnd>("ends");
+    // group (32-bit only)
+    addDirectiveHandler<&COFFMasmParser::ParseDirectiveSegment>("segment");
+
+    // Simplified segment directives
+    addDirectiveHandler<&COFFMasmParser::ParseSectionDirectiveCode>(".code");
+    // .const
+    addDirectiveHandler<
+        &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data");
+    addDirectiveHandler<
+        &COFFMasmParser::ParseSectionDirectiveUninitializedData>(".data?");
+    // .exit
+    // .fardata
+    // .fardata?
+    addDirectiveHandler<&COFFMasmParser::IgnoreDirective>(".model");
+    // .stack
+    // .startup
+
+    // String directives, written <name> <directive> <params>
+    // catstr (equivalent to <name> TEXTEQU <params>)
+    // instr (equivalent to <name> = @InStr(<params>))
+    // sizestr (equivalent to <name> = @SizeStr(<params>))
+    // substr (equivalent to <name> TEXTEQU @SubStr(<params>))
+
+    // Structure and record directives
+    // ends
+    // record
+    // struct
+    // typedef
+    // union
+  }
+
+  bool ParseSectionDirectiveCode(StringRef, SMLoc) {
+    return ParseSectionSwitch(".text",
+                              COFF::IMAGE_SCN_CNT_CODE
+                            | COFF::IMAGE_SCN_MEM_EXECUTE
+                            | COFF::IMAGE_SCN_MEM_READ,
+                              SectionKind::getText());
+  }
+
+  bool ParseSectionDirectiveInitializedData(StringRef, SMLoc) {
+    return ParseSectionSwitch(".data",
+                              COFF::IMAGE_SCN_CNT_INITIALIZED_DATA
+                            | COFF::IMAGE_SCN_MEM_READ
+                            | COFF::IMAGE_SCN_MEM_WRITE,
+                              SectionKind::getData());
+  }
+
+  bool ParseSectionDirectiveUninitializedData(StringRef, SMLoc) {
+    return ParseSectionSwitch(".bss",
+                              COFF::IMAGE_SCN_CNT_UNINITIALIZED_DATA
+                            | COFF::IMAGE_SCN_MEM_READ
+                            | COFF::IMAGE_SCN_MEM_WRITE,
+                              SectionKind::getBSS());
+  }
+
+  StringRef CurrentProcedure;
+
+public:
+  COFFMasmParser() = default;
+};
+
+} // end anonymous namespace.
+
+static SectionKind computeSectionKind(unsigned Flags) {
+  if (Flags & COFF::IMAGE_SCN_MEM_EXECUTE)
+    return SectionKind::getText();
+  if (Flags & COFF::IMAGE_SCN_MEM_READ &&
+      (Flags & COFF::IMAGE_SCN_MEM_WRITE) == 0)
+    return SectionKind::getReadOnly();
+  return SectionKind::getData();
+}
+
+bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
+                                        unsigned Characteristics,
+                                        SectionKind Kind) {
+  return ParseSectionSwitch(Section, Characteristics, Kind, "",
+                            (COFF::COMDATType)0);
+}
+
+bool COFFMasmParser::ParseSectionSwitch(StringRef Section,
+                                        unsigned Characteristics,
+                                        SectionKind Kind,
+                                        StringRef COMDATSymName,
+                                        COFF::COMDATType Type) {
+  if (getLexer().isNot(AsmToken::EndOfStatement))
+    return TokError("unexpected token in section switching directive");
+  Lex();
+
+  getStreamer().SwitchSection(getContext().getCOFFSection(
+      Section, Characteristics, Kind, COMDATSymName, Type));
+
+  return false;
+}
+
+bool COFFMasmParser::ParseDirectiveSegment(StringRef Directive, SMLoc Loc) {
+  StringRef SegmentName;
+  if (!getLexer().is(AsmToken::Identifier))
+    return TokError("expected identifier in directive");
+  SegmentName = getTok().getIdentifier();
+  Lex();
+
+  StringRef SectionName = SegmentName;
+  SmallVector<char, 247> SectionNameVector;
+  unsigned Flags = COFF::IMAGE_SCN_CNT_INITIALIZED_DATA |
+                   COFF::IMAGE_SCN_MEM_READ | COFF::IMAGE_SCN_MEM_WRITE;
+  if (SegmentName == "_TEXT" || SegmentName.startswith("_TEXT$")) {
+    if (SegmentName.size() == 5) {
+      SectionName = ".text";
+    } else {
+      SectionName =
+          (".text$" + SegmentName.substr(6)).toStringRef(SectionNameVector);
+    }
+    Flags = COFF::IMAGE_SCN_CNT_CODE | COFF::IMAGE_SCN_MEM_EXECUTE |
+            COFF::IMAGE_SCN_MEM_READ;
+  }
+  SectionKind Kind = computeSectionKind(Flags);
+  getStreamer().SwitchSection(getContext().getCOFFSection(
+      SectionName, Flags, Kind, "", (COFF::COMDATType)(0)));
+  return false;
+}
+
+/// ParseDirectiveSegmentEnd
+///  ::= identifier "ends"
+bool COFFMasmParser::ParseDirectiveSegmentEnd(StringRef Directive, SMLoc Loc) {
+  StringRef SegmentName;
+  if (!getLexer().is(AsmToken::Identifier))
+    return TokError("expected identifier in directive");
+  SegmentName = getTok().getIdentifier();
+
+  // Ignore; no action necessary.
+  Lex();
+  return false;
+}
+
+/// ParseDirectiveIncludelib
+///  ::= "includelib" identifier
+bool COFFMasmParser::ParseDirectiveIncludelib(StringRef Directive, SMLoc Loc) {
+  StringRef Lib;
+  if (getParser().parseIdentifier(Lib))
+    return TokError("expected identifier in includelib directive");
+
+  unsigned Flags = COFF::IMAGE_SCN_MEM_PRELOAD | COFF::IMAGE_SCN_MEM_16BIT;
+  SectionKind Kind = computeSectionKind(Flags);
+  getStreamer().PushSection();
+  getStreamer().SwitchSection(getContext().getCOFFSection(
+      ".drectve", Flags, Kind, "", (COFF::COMDATType)(0)));
+  getStreamer().EmitBytes("/DEFAULTLIB:");
+  getStreamer().EmitBytes(Lib);
+  getStreamer().EmitBytes(" ");
+  getStreamer().PopSection();
+  return false;
+}
+
+/// ParseDirectiveProc
+/// TODO(epastor): Implement parameters and other attributes.
+///  ::= label "proc" [[distance]]
+///          statements
+///      label "endproc"
+bool COFFMasmParser::ParseDirectiveProc(StringRef Directive, SMLoc Loc) {
+  StringRef Label;
+  if (getParser().parseIdentifier(Label))
+    return Error(Loc, "expected identifier for procedure");
+  if (getLexer().is(AsmToken::Identifier)) {
+    StringRef nextVal = getTok().getString();
+    SMLoc nextLoc = getTok().getLoc();
+    if (nextVal.equals_lower("far")) {
+      // TODO(epastor): Handle far procedure definitions.
+      Lex();
+      return Error(nextLoc, "far procedure definitions not yet supported");
+    } else if (nextVal.equals_lower("near")) {
+      Lex();
+      nextVal = getTok().getString();
+      nextLoc = getTok().getLoc();
+    }
+  }
+  MCSymbol *Sym = getContext().getOrCreateSymbol(Label);
+
+  // Define symbol as simple function
+  getStreamer().BeginCOFFSymbolDef(Sym);
+  getStreamer().EmitCOFFSymbolStorageClass(2);
+  getStreamer().EmitCOFFSymbolType(0x20);
+  getStreamer().EndCOFFSymbolDef();
+
+  getStreamer().EmitLabel(Sym, Loc);
+  CurrentProcedure = Label;
+  return false;
+}
+bool COFFMasmParser::ParseDirectiveEndProc(StringRef Directive, SMLoc Loc) {
+  StringRef Label;
+  SMLoc LabelLoc = getTok().getLoc();
+  if (getParser().parseIdentifier(Label))
+    return Error(LabelLoc, "expected identifier for procedure end");
+
+  if (CurrentProcedure.empty())
+    return Error(Loc, "endp outside of procedure block");
+  else if (CurrentProcedure != Label)
+    return Error(LabelLoc, "endp does not match current procedure '" +
+                               CurrentProcedure + "'");
+  return false;
+}
+
+namespace llvm {
+
+MCAsmParserExtension *createCOFFMasmParser() { return new COFFMasmParser; }
+
+} // end namespace llvm
diff --git a/llvm/lib/MC/MCParser/MCAsmParser.cpp b/llvm/lib/MC/MCParser/MCAsmParser.cpp
--- a/llvm/lib/MC/MCParser/MCAsmParser.cpp
+++ b/llvm/lib/MC/MCParser/MCAsmParser.cpp
@@ -13,6 +13,7 @@
 #include "llvm/MC/MCParser/MCAsmLexer.h"
 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/MC/MCParser/MCTargetAsmParser.h"
+#include "llvm/Support/CommandLine.h"
 #include "llvm/Support/Debug.h"
 #include "llvm/Support/SMLoc.h"
 #include "llvm/Support/raw_ostream.h"
@@ -20,6 +21,10 @@
 
 using namespace llvm;
 
+cl::opt<unsigned> AsmMacroMaxNestingDepth(
+    "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
+    cl::desc("The maximum nesting depth allowed for assembly macros."));
+
 MCAsmParser::MCAsmParser() {}
 
 MCAsmParser::~MCAsmParser() = default;
diff --git a/llvm/lib/MC/MCParser/AsmParser.cpp b/llvm/lib/MC/MCParser/MasmParser.cpp
copy from llvm/lib/MC/MCParser/AsmParser.cpp
copy to llvm/lib/MC/MCParser/MasmParser.cpp
--- a/llvm/lib/MC/MCParser/AsmParser.cpp
+++ b/llvm/lib/MC/MCParser/MasmParser.cpp
@@ -72,11 +72,7 @@
 
 using namespace llvm;
 
-MCAsmParserSemaCallback::~MCAsmParserSemaCallback() = default;
-
-static cl::opt<unsigned> AsmMacroMaxNestingDepth(
-     "asm-macro-max-nesting-depth", cl::init(20), cl::Hidden,
-     cl::desc("The maximum nesting depth allowed for assembly macros."));
+extern cl::opt<unsigned> AsmMacroMaxNestingDepth;
 
 namespace {
 
@@ -114,11 +110,13 @@
 
   ParseStatementInfo() = delete;
   ParseStatementInfo(SmallVectorImpl<AsmRewrite> *rewrites)
-    : AsmRewrites(rewrites) {}
+      : AsmRewrites(rewrites) {}
 };
 
 /// The concrete assembly parser instance.
-class AsmParser : public MCAsmParser {
+// Note that this is a full MCAsmParser, not an MCAsmParserExtension!
+// It's a peer of AsmParser, not of COFFAsmParser, WasmAsmParser, etc.
+class MasmParser : public MCAsmParser {
 private:
   AsmLexer Lexer;
   MCContext &Ctx;
@@ -141,6 +139,16 @@
   /// addDirectiveHandler.
   StringMap<ExtensionDirectiveHandler> ExtensionDirectiveMap;
 
+  /// maps assembly-time variable names to variables
+  struct Variable {
+    StringRef Name;
+    bool Redefinable = true;
+    bool IsText = false;
+    int64_t NumericValue = 0;
+    std::string TextValue;
+  };
+  StringMap<Variable> Variables;
+
   /// Stack of active macro instantiations.
   std::vector<MacroInstantiation*> ActiveMacros;
 
@@ -170,7 +178,8 @@
   SmallVector<std::tuple<SMLoc, CppHashInfoTy, MCSymbol *>, 4> DirLabels;
 
   /// AssemblerDialect. ~OU means unset value and use value provided by MAI.
-  unsigned AssemblerDialect = ~0U;
+  /// Defaults to 1U, meaning Intel.
+  unsigned AssemblerDialect = 1U;
 
   /// is Darwin compatibility enabled?
   bool IsDarwin = false;
@@ -185,17 +194,20 @@
   bool AltMacroMode = false;
 
 public:
-  AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
-            const MCAsmInfo &MAI, unsigned CB);
-  AsmParser(const AsmParser &) = delete;
-  AsmParser &operator=(const AsmParser &) = delete;
-  ~AsmParser() override;
+  MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
+             const MCAsmInfo &MAI, unsigned CB);
+  MasmParser(const MasmParser &) = delete;
+  MasmParser &operator=(const MasmParser &) = delete;
+  ~MasmParser() override;
 
   bool Run(bool NoInitialTextSection, bool NoFinalize = false) override;
 
   void addDirectiveHandler(StringRef Directive,
                            ExtensionDirectiveHandler Handler) override {
     ExtensionDirectiveMap[Directive] = Handler;
+    if (DirectiveKindMap.find(Directive) == DirectiveKindMap.end()) {
+      DirectiveKindMap[Directive] = DK_HANDLER_DIRECTIVE;
+    }
   }
 
   void addAliasForDirective(StringRef Directive, StringRef Alias) override {
@@ -340,8 +352,7 @@
   /// return the contents from the current token up to the end or comma.
   StringRef parseStringToComma();
 
-  bool parseAssignment(StringRef Name, bool allow_redef,
-                       bool NoDeadStrip = false);
+  bool parseTextItem(std::string &Data);
 
   unsigned getBinOpPrecedence(AsmToken::TokenKind K,
                               MCBinaryExpr::Opcode &Kind);
@@ -358,108 +369,57 @@
   // Generic (target and platform independent) directive parsing.
   enum DirectiveKind {
     DK_NO_DIRECTIVE, // Placeholder
-    DK_SET,
+    DK_HANDLER_DIRECTIVE,
+    DK_ASSIGN,
     DK_EQU,
-    DK_EQUIV,
+    DK_TEXTEQU,
     DK_ASCII,
     DK_ASCIZ,
     DK_STRING,
     DK_BYTE,
-    DK_SHORT,
-    DK_RELOC,
-    DK_VALUE,
-    DK_2BYTE,
-    DK_LONG,
-    DK_INT,
-    DK_4BYTE,
-    DK_QUAD,
-    DK_8BYTE,
-    DK_OCTA,
-    DK_DC,
-    DK_DC_A,
-    DK_DC_B,
-    DK_DC_D,
-    DK_DC_L,
-    DK_DC_S,
-    DK_DC_W,
-    DK_DC_X,
-    DK_DCB,
-    DK_DCB_B,
-    DK_DCB_D,
-    DK_DCB_L,
-    DK_DCB_S,
-    DK_DCB_W,
-    DK_DCB_X,
-    DK_DS,
-    DK_DS_B,
-    DK_DS_D,
-    DK_DS_L,
-    DK_DS_P,
-    DK_DS_S,
-    DK_DS_W,
-    DK_DS_X,
-    DK_SINGLE,
-    DK_FLOAT,
-    DK_DOUBLE,
+    DK_WORD,
+    DK_DWORD,
+    DK_FWORD,
+    DK_QWORD,
+    DK_DB,
+    DK_DD,
+    DK_DQ,
+    DK_DW,
+    DK_REAL4,
+    DK_REAL8,
     DK_ALIGN,
-    DK_ALIGN32,
-    DK_BALIGN,
-    DK_BALIGNW,
-    DK_BALIGNL,
-    DK_P2ALIGN,
-    DK_P2ALIGNW,
-    DK_P2ALIGNL,
     DK_ORG,
-    DK_FILL,
     DK_ENDR,
-    DK_BUNDLE_ALIGN_MODE,
-    DK_BUNDLE_LOCK,
-    DK_BUNDLE_UNLOCK,
-    DK_ZERO,
     DK_EXTERN,
-    DK_GLOBL,
-    DK_GLOBAL,
-    DK_LAZY_REFERENCE,
-    DK_NO_DEAD_STRIP,
-    DK_SYMBOL_RESOLVER,
-    DK_PRIVATE_EXTERN,
-    DK_REFERENCE,
-    DK_WEAK_DEFINITION,
-    DK_WEAK_REFERENCE,
-    DK_WEAK_DEF_CAN_BE_HIDDEN,
-    DK_COLD,
+    DK_PUBLIC,
     DK_COMM,
-    DK_COMMON,
-    DK_LCOMM,
-    DK_ABORT,
+    DK_COMMENT,
     DK_INCLUDE,
-    DK_INCBIN,
-    DK_CODE16,
-    DK_CODE16GCC,
     DK_REPT,
     DK_IRP,
     DK_IRPC,
     DK_IF,
-    DK_IFEQ,
-    DK_IFGE,
-    DK_IFGT,
-    DK_IFLE,
-    DK_IFLT,
-    DK_IFNE,
+    DK_IFE,
     DK_IFB,
     DK_IFNB,
-    DK_IFC,
-    DK_IFEQS,
-    DK_IFNC,
-    DK_IFNES,
     DK_IFDEF,
     DK_IFNDEF,
-    DK_IFNOTDEF,
+    DK_IFDIF,
+    DK_IFDIFI,
+    DK_IFIDN,
+    DK_IFIDNI,
     DK_ELSEIF,
+    DK_ELSEIFE,
+    DK_ELSEIFB,
+    DK_ELSEIFNB,
+    DK_ELSEIFDEF,
+    DK_ELSEIFNDEF,
+    DK_ELSEIFDIF,
+    DK_ELSEIFDIFI,
+    DK_ELSEIFIDN,
+    DK_ELSEIFIDNI,
     DK_ELSE,
     DK_ENDIF,
-    DK_SPACE,
-    DK_SKIP,
     DK_FILE,
     DK_LINE,
     DK_LOC,
@@ -498,23 +458,24 @@
     DK_CFI_REGISTER,
     DK_CFI_WINDOW_SAVE,
     DK_CFI_B_KEY_FRAME,
-    DK_MACROS_ON,
-    DK_MACROS_OFF,
     DK_ALTMACRO,
     DK_NOALTMACRO,
     DK_MACRO,
     DK_EXITM,
     DK_ENDM,
-    DK_ENDMACRO,
     DK_PURGEM,
-    DK_SLEB128,
-    DK_ULEB128,
     DK_ERR,
-    DK_ERROR,
-    DK_WARNING,
-    DK_PRINT,
-    DK_ADDRSIG,
-    DK_ADDRSIG_SYM,
+    DK_ERRB,
+    DK_ERRNB,
+    DK_ERRDEF,
+    DK_ERRNDEF,
+    DK_ERRDIF,
+    DK_ERRDIFI,
+    DK_ERRIDN,
+    DK_ERRIDNI,
+    DK_ERRE,
+    DK_ERRNZ,
+    DK_ECHO,
     DK_END
   };
 
@@ -537,19 +498,17 @@
 
   // ".ascii", ".asciz", ".string"
   bool parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated);
-  bool parseDirectiveReloc(SMLoc DirectiveLoc); // ".reloc"
   bool parseDirectiveValue(StringRef IDVal,
-                           unsigned Size);       // ".byte", ".long", ...
-  bool parseDirectiveOctaValue(StringRef IDVal); // ".octa", ...
+                           unsigned Size);       // "byte", "word", ...
   bool parseDirectiveRealValue(StringRef IDVal,
-                               const fltSemantics &); // ".single", ...
-  bool parseDirectiveFill(); // ".fill"
-  bool parseDirectiveZero(); // ".zero"
-  // ".set", ".equ", ".equiv"
-  bool parseDirectiveSet(StringRef IDVal, bool allow_redef);
+                               const fltSemantics &);  // "real4", ...
+
+  // "=", "equ", "textequ"
+  bool parseDirectiveEquate(StringRef IDVal, StringRef Name,
+                            DirectiveKind DirKind);
+
   bool parseDirectiveOrg(); // ".org"
-  // ".align{,32}", ".p2align{,w,l}"
-  bool parseDirectiveAlign(bool IsPow2, unsigned ValueSize);
+  bool parseDirectiveAlign();  // "align"
 
   // ".file", ".line", ".loc", ".stabs"
   bool parseDirectiveFile(SMLoc DirectiveLoc);
@@ -602,24 +561,6 @@
   bool parseDirectiveMacrosOnOff(StringRef Directive);
   // alternate macro mode directives
   bool parseDirectiveAltmacro(StringRef Directive);
-  // ".bundle_align_mode"
-  bool parseDirectiveBundleAlignMode();
-  // ".bundle_lock"
-  bool parseDirectiveBundleLock();
-  // ".bundle_unlock"
-  bool parseDirectiveBundleUnlock();
-
-  // ".space", ".skip"
-  bool parseDirectiveSpace(StringRef IDVal);
-
-  // ".dcb"
-  bool parseDirectiveDCB(StringRef IDVal, unsigned Size);
-  bool parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &);
-  // ".ds"
-  bool parseDirectiveDS(StringRef IDVal, unsigned Size);
-
-  // .sleb128 (Signed=true) and .uleb128 (Signed=false)
-  bool parseDirectiveLEB128(bool Signed);
 
   /// Parse a directive like ".globl" which
   /// accepts a single symbol (which should be a label or an external).
@@ -627,24 +568,34 @@
 
   bool parseDirectiveComm(bool IsLocal); // ".comm" and ".lcomm"
 
-  bool parseDirectiveAbort(); // ".abort"
-  bool parseDirectiveInclude(); // ".include"
-  bool parseDirectiveIncbin(); // ".incbin"
+  bool parseDirectiveComment(SMLoc DirectiveLoc); // "comment"
 
-  // ".if", ".ifeq", ".ifge", ".ifgt" , ".ifle", ".iflt" or ".ifne"
+  bool parseDirectiveInclude(); // "include"
+
+  // "if" or "ife"
   bool parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
-  // ".ifb" or ".ifnb", depending on ExpectBlank.
+  // "ifb" or "ifnb", depending on ExpectBlank.
   bool parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank);
-  // ".ifc" or ".ifnc", depending on ExpectEqual.
-  bool parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual);
-  // ".ifeqs" or ".ifnes", depending on ExpectEqual.
-  bool parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual);
-  // ".ifdef" or ".ifndef", depending on expect_defined
+  // "ifidn", "ifdif", "ifidni", or "ifdifi", depending on ExpectEqual and
+  // CaseInsensitive.
+  bool parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+                           bool CaseInsensitive);
+  // "ifdef" or "ifndef", depending on expect_defined
   bool parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined);
-  bool parseDirectiveElseIf(SMLoc DirectiveLoc); // ".elseif"
-  bool parseDirectiveElse(SMLoc DirectiveLoc); // ".else"
-  bool parseDirectiveEndIf(SMLoc DirectiveLoc); // .endif
+  // "elseif" or "elseife"
+  bool parseDirectiveElseIf(SMLoc DirectiveLoc, DirectiveKind DirKind);
+  // "elseifb" or "elseifnb", depending on ExpectBlank.
+  bool parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+  // ".elseifdef" or ".elseifndef", depending on expect_defined
+  bool parseDirectiveElseIfdef(SMLoc DirectiveLoc, bool expect_defined);
+  // "elseifidn", "elseifdif", "elseifidni", or "elseifdifi", depending on
+  // ExpectEqual and CaseInsensitive.
+  bool parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+                               bool CaseInsensitive);
+  bool parseDirectiveElse(SMLoc DirectiveLoc);   // "else"
+  bool parseDirectiveEndIf(SMLoc DirectiveLoc);  // "endif"
   bool parseEscapedString(std::string &Data) override;
+  bool parseAngleBracketString(std::string &Data) override;
 
   const MCExpr *applyModifierToExpr(const MCExpr *E,
                                     MCSymbolRefExpr::VariantKind Variant);
@@ -668,18 +619,21 @@
   // "end"
   bool parseDirectiveEnd(SMLoc DirectiveLoc);
 
-  // ".err" or ".error"
-  bool parseDirectiveError(SMLoc DirectiveLoc, bool WithMessage);
-
-  // ".warning"
-  bool parseDirectiveWarning(SMLoc DirectiveLoc);
-
-  // .print <double-quotes-string>
-  bool parseDirectivePrint(SMLoc DirectiveLoc);
-
-  // Directives to support address-significance tables.
-  bool parseDirectiveAddrsig();
-  bool parseDirectiveAddrsigSym();
+  // ".err"
+  bool parseDirectiveError(SMLoc DirectiveLoc);
+  // ".errb" or ".errnb", depending on ExpectBlank.
+  bool parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank);
+  // ".errdef" or ".errndef", depending on ExpectBlank.
+  bool parseDirectiveErrorIfdef(SMLoc DirectiveLoc, bool ExpectDefined);
+  // ".erridn", ".errdif", ".erridni", or ".errdifi", depending on ExpectEqual
+  // and CaseInsensitive.
+  bool parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+                                bool CaseInsensitive);
+  // ".erre" or ".errnz", depending on ExpectZero.
+  bool parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero);
+
+  // "echo"
+  bool parseDirectiveEcho();
 
   void initializeDirectiveKindMap();
   void initializeCVDefRangeTypeMap();
@@ -689,17 +643,14 @@
 
 namespace llvm {
 
-extern MCAsmParserExtension *createDarwinAsmParser();
-extern MCAsmParserExtension *createELFAsmParser();
-extern MCAsmParserExtension *createCOFFAsmParser();
-extern MCAsmParserExtension *createWasmAsmParser();
+extern MCAsmParserExtension *createCOFFMasmParser();
 
 } // end namespace llvm
 
 enum { DEFAULT_ADDRSPACE = 0 };
 
-AsmParser::AsmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
-                     const MCAsmInfo &MAI, unsigned CB = 0)
+MasmParser::MasmParser(SourceMgr &SM, MCContext &Ctx, MCStreamer &Out,
+                       const MCAsmInfo &MAI, unsigned CB = 0)
     : Lexer(MAI), Ctx(Ctx), Out(Out), MAI(MAI), SrcMgr(SM),
       CurBuffer(CB ? CB : SM.getMainFileID()), MacrosEnabledFlag(true) {
   HadError = false;
@@ -713,32 +664,35 @@
   // Initialize the platform / file format parser.
   switch (Ctx.getObjectFileInfo()->getObjectFileType()) {
   case MCObjectFileInfo::IsCOFF:
-    PlatformParser.reset(createCOFFAsmParser());
+    PlatformParser.reset(createCOFFMasmParser());
     break;
   case MCObjectFileInfo::IsMachO:
-    PlatformParser.reset(createDarwinAsmParser());
+    report_fatal_error(
+        "Need to implement createDarwinMasmParser for Mach-O format.");
     IsDarwin = true;
     break;
   case MCObjectFileInfo::IsELF:
-    PlatformParser.reset(createELFAsmParser());
+    report_fatal_error(
+        "Need to implement createELFMasmParser for ELF format.");
     break;
   case MCObjectFileInfo::IsWasm:
-    PlatformParser.reset(createWasmAsmParser());
+    report_fatal_error(
+        "Need to implement createWasmMasmParser for WASM format.");
     break;
   case MCObjectFileInfo::IsXCOFF:
     report_fatal_error(
-        "Need to implement createXCOFFAsmParser for XCOFF format.");
+        "Need to implement createXCOFFMasmParser for XCOFF format.");
     break;
   }
 
-  PlatformParser->Initialize(*this);
   initializeDirectiveKindMap();
+  PlatformParser->Initialize(*this);
   initializeCVDefRangeTypeMap();
 
   NumOfMacroInstantiations = 0;
 }
 
-AsmParser::~AsmParser() {
+MasmParser::~MasmParser() {
   assert((HadError || ActiveMacros.empty()) &&
          "Unexpected active macro instantiation!");
 
@@ -747,7 +701,7 @@
   SrcMgr.setDiagHandler(SavedDiagHandler, SavedDiagContext);
 }
 
-void AsmParser::printMacroInstantiations() {
+void MasmParser::printMacroInstantiations() {
   // Print the active macro instantiation stack.
   for (std::vector<MacroInstantiation *>::const_reverse_iterator
            it = ActiveMacros.rbegin(),
@@ -757,14 +711,14 @@
                  "while in macro instantiation");
 }
 
-void AsmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
+void MasmParser::Note(SMLoc L, const Twine &Msg, SMRange Range) {
   printPendingErrors();
   printMessage(L, SourceMgr::DK_Note, Msg, Range);
   printMacroInstantiations();
 }
 
-bool AsmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
-  if(getTargetParser().getTargetOptions().MCNoWarn)
+bool MasmParser::Warning(SMLoc L, const Twine &Msg, SMRange Range) {
+  if (getTargetParser().getTargetOptions().MCNoWarn)
     return false;
   if (getTargetParser().getTargetOptions().MCFatalWarnings)
     return Error(L, Msg, Range);
@@ -773,14 +727,14 @@
   return false;
 }
 
-bool AsmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
+bool MasmParser::printError(SMLoc L, const Twine &Msg, SMRange Range) {
   HadError = true;
   printMessage(L, SourceMgr::DK_Error, Msg, Range);
   printMacroInstantiations();
   return true;
 }
 
-bool AsmParser::enterIncludeFile(const std::string &Filename) {
+bool MasmParser::enterIncludeFile(const std::string &Filename) {
   std::string IncludedFile;
   unsigned NewBuf =
       SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
@@ -795,8 +749,8 @@
 /// Process the specified .incbin file by searching for it in the include paths
 /// then just emitting the byte contents of the file to the streamer. This
 /// returns true on failure.
-bool AsmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
-                                  const MCExpr *Count, SMLoc Loc) {
+bool MasmParser::processIncbinFile(const std::string &Filename, int64_t Skip,
+                                   const MCExpr *Count, SMLoc Loc) {
   std::string IncludedFile;
   unsigned NewBuf =
       SrcMgr.AddIncludeFile(Filename, Lexer.getLoc(), IncludedFile);
@@ -818,13 +772,13 @@
   return false;
 }
 
-void AsmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
+void MasmParser::jumpToLoc(SMLoc Loc, unsigned InBuffer) {
   CurBuffer = InBuffer ? InBuffer : SrcMgr.FindBufferContainingLoc(Loc);
   Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(),
                   Loc.getPointer());
 }
 
-const AsmToken &AsmParser::Lex() {
+const AsmToken &MasmParser::Lex() {
   if (Lexer.getTok().is(AsmToken::Error))
     Error(Lexer.getErrLoc(), Lexer.getErr());
 
@@ -838,6 +792,24 @@
 
   const AsmToken *tok = &Lexer.Lex();
 
+  while (tok->is(AsmToken::Identifier)) {
+    auto it = Variables.find(tok->getIdentifier());
+    if (it != Variables.end() && it->second.IsText) {
+      std::unique_ptr<MemoryBuffer> Instantiation =
+          MemoryBuffer::getMemBufferCopy(it->second.TextValue,
+                                         "<instantiation>");
+
+      // Jump to the macro instantiation and prime the lexer.
+      CurBuffer = SrcMgr.AddNewSourceBuffer(std::move(Instantiation),
+                                            getTok().getEndLoc());
+      Lexer.setBuffer(SrcMgr.getMemoryBuffer(CurBuffer)->getBuffer(), nullptr,
+                      /*EndStatementAtEOF=*/false);
+      tok = &Lexer.Lex();
+    } else {
+      break;
+    }
+  }
+
   // Parse comments here to be deferred until end of next statement.
   while (tok->is(AsmToken::Comment)) {
     if (MAI.preserveAsmComments())
@@ -858,7 +830,7 @@
   return *tok;
 }
 
-bool AsmParser::enabledGenDwarfForAssembly() {
+bool MasmParser::enabledGenDwarfForAssembly() {
   // Check whether the user specified -g.
   if (!getContext().getGenDwarfForAssembly())
     return false;
@@ -882,7 +854,7 @@
   return true;
 }
 
-bool AsmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
+bool MasmParser::Run(bool NoInitialTextSection, bool NoFinalize) {
   // Create the initial section, if requested.
   if (!NoInitialTextSection)
     Out.InitSections(false);
@@ -994,7 +966,7 @@
   return HadError || getContext().hadError();
 }
 
-bool AsmParser::checkForValidSection() {
+bool MasmParser::checkForValidSection() {
   if (!ParsingInlineAsm && !getStreamer().getCurrentSectionOnly()) {
     Out.InitSections(false);
     return Error(getTok().getLoc(),
@@ -1004,7 +976,7 @@
 }
 
 /// Throw away the rest of the line for testing purposes.
-void AsmParser::eatToEndOfStatement() {
+void MasmParser::eatToEndOfStatement() {
   while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
     Lexer.Lex();
 
@@ -1013,7 +985,7 @@
     Lexer.Lex();
 }
 
-StringRef AsmParser::parseStringToEndOfStatement() {
+StringRef MasmParser::parseStringToEndOfStatement() {
   const char *Start = getTok().getLoc().getPointer();
 
   while (Lexer.isNot(AsmToken::EndOfStatement) && Lexer.isNot(AsmToken::Eof))
@@ -1023,7 +995,7 @@
   return StringRef(Start, End - Start);
 }
 
-StringRef AsmParser::parseStringToComma() {
+StringRef MasmParser::parseStringToComma() {
   const char *Start = getTok().getLoc().getPointer();
 
   while (Lexer.isNot(AsmToken::EndOfStatement) &&
@@ -1039,7 +1011,7 @@
 ///
 /// parenexpr ::= expr)
 ///
-bool AsmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+bool MasmParser::parseParenExpr(const MCExpr *&Res, SMLoc &EndLoc) {
   if (parseExpression(Res))
     return true;
   if (Lexer.isNot(AsmToken::RParen))
@@ -1054,7 +1026,7 @@
 ///
 /// bracketexpr ::= expr]
 ///
-bool AsmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+bool MasmParser::parseBracketExpr(const MCExpr *&Res, SMLoc &EndLoc) {
   if (parseExpression(Res))
     return true;
   EndLoc = getTok().getEndLoc();
@@ -1069,7 +1041,7 @@
 ///  primaryexpr ::= number
 ///  primaryexpr ::= '.'
 ///  primaryexpr ::= ~,+,- primaryexpr
-bool AsmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
+bool MasmParser::parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) {
   SMLoc FirstTokenLoc = getLexer().getLoc();
   AsmToken::TokenKind FirstTokenKind = Lexer.getKind();
   switch (FirstTokenKind) {
@@ -1295,14 +1267,14 @@
   }
 }
 
-bool AsmParser::parseExpression(const MCExpr *&Res) {
+bool MasmParser::parseExpression(const MCExpr *&Res) {
   SMLoc EndLoc;
   return parseExpression(Res, EndLoc);
 }
 
 const MCExpr *
-AsmParser::applyModifierToExpr(const MCExpr *E,
-                               MCSymbolRefExpr::VariantKind Variant) {
+MasmParser::applyModifierToExpr(const MCExpr *E,
+                                MCSymbolRefExpr::VariantKind Variant) {
   // Ask the target implementation about this expression first.
   const MCExpr *NewE = getTargetParser().applyModifierToExpr(E, Variant, Ctx);
   if (NewE)
@@ -1365,7 +1337,7 @@
 /// implementation. GCC does not fully support this feature and so we will not
 /// support it.
 /// TODO: Adding single quote as a string.
-static bool isAltmacroString(SMLoc &StrLoc, SMLoc &EndLoc) {
+static bool isAngleBracketString(SMLoc &StrLoc, SMLoc &EndLoc) {
   assert((StrLoc.getPointer() != nullptr) &&
          "Argument to the function cannot be a NULL value");
   const char *CharPtr = StrLoc.getPointer();
@@ -1383,7 +1355,7 @@
 }
 
 /// creating a string without the escape characters '!'.
-static std::string altMacroString(StringRef AltMacroStr) {
+static std::string angleBracketString(StringRef AltMacroStr) {
   std::string Res;
   for (size_t Pos = 0; Pos < AltMacroStr.size(); Pos++) {
     if (AltMacroStr[Pos] == '!')
@@ -1403,7 +1375,7 @@
 ///  expr ::= expr *,/,% expr               -> highest.
 ///  expr ::= primaryexpr
 ///
-bool AsmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+bool MasmParser::parseExpression(const MCExpr *&Res, SMLoc &EndLoc) {
   // Parse the expression.
   Res = nullptr;
   if (getTargetParser().parsePrimaryExpr(Res, EndLoc) ||
@@ -1443,13 +1415,13 @@
   return false;
 }
 
-bool AsmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
+bool MasmParser::parseParenExpression(const MCExpr *&Res, SMLoc &EndLoc) {
   Res = nullptr;
   return parseParenExpr(Res, EndLoc) || parseBinOpRHS(1, Res, EndLoc);
 }
 
-bool AsmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
-                                      SMLoc &EndLoc) {
+bool MasmParser::parseParenExprOfDepth(unsigned ParenDepth, const MCExpr *&Res,
+                                       SMLoc &EndLoc) {
   if (parseParenExpr(Res, EndLoc))
     return true;
 
@@ -1469,7 +1441,7 @@
   return false;
 }
 
-bool AsmParser::parseAbsoluteExpression(int64_t &Res) {
+bool MasmParser::parseAbsoluteExpression(int64_t &Res) {
   const MCExpr *Expr;
 
   SMLoc StartLoc = Lexer.getLoc();
@@ -1636,8 +1608,8 @@
   }
 }
 
-unsigned AsmParser::getBinOpPrecedence(AsmToken::TokenKind K,
-                                       MCBinaryExpr::Opcode &Kind) {
+unsigned MasmParser::getBinOpPrecedence(AsmToken::TokenKind K,
+                                        MCBinaryExpr::Opcode &Kind) {
   bool ShouldUseLogicalShr = MAI.shouldUseLogicalShr();
   return IsDarwin ? getDarwinBinOpPrecedence(K, Kind, ShouldUseLogicalShr)
                   : getGNUBinOpPrecedence(K, Kind, ShouldUseLogicalShr);
@@ -1645,8 +1617,8 @@
 
 /// Parse all binary operators with precedence >= 'Precedence'.
 /// Res contains the LHS of the expression on input.
-bool AsmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
-                              SMLoc &EndLoc) {
+bool MasmParser::parseBinOpRHS(unsigned Precedence, const MCExpr *&Res,
+                               SMLoc &EndLoc) {
   SMLoc StartLoc = Lexer.getLoc();
   while (true) {
     MCBinaryExpr::Opcode Kind = MCBinaryExpr::Add;
@@ -1680,8 +1652,8 @@
 ///   ::= EndOfStatement
 ///   ::= Label* Directive ...Operands... EndOfStatement
 ///   ::= Label* Identifier OperandList* EndOfStatement
-bool AsmParser::parseStatement(ParseStatementInfo &Info,
-                               MCAsmParserSemaCallback *SI) {
+bool MasmParser::parseStatement(ParseStatementInfo &Info,
+                                MCAsmParserSemaCallback *SI) {
   assert(!hasPendingError() && "parseStatement started with pending error");
   // Eat initial spaces and comments
   while (Lexer.is(AsmToken::Space))
@@ -1694,7 +1666,8 @@
     Lex();
     return false;
   }
-  // Statements always start with an identifier.
+  // Statements always start with an identifier, unless we're dealing with a
+  // processor directive (.386, .686, etc.) that lexes as a real.
   AsmToken ID = getTok();
   SMLoc IDLoc = ID.getLoc();
   StringRef IDVal;
@@ -1738,6 +1711,12 @@
     // Accept '*' as a valid start of statement.
     Lex();
     IDVal = "*";
+  } else if (Lexer.is(AsmToken::Real)) {
+    // Treat ".<number>" as a valid identifier in this context.
+    IDVal = getTok().getString();
+    Lex(); // always eat a token
+    if (!IDVal.startswith("."))
+      return Error(IDLoc, "unexpected token at start of statement");
   } else if (parseIdentifier(IDVal)) {
     if (!TheCondState.Ignore) {
       Lex(); // always eat a token
@@ -1759,32 +1738,51 @@
   default:
     break;
   case DK_IF:
-  case DK_IFEQ:
-  case DK_IFGE:
-  case DK_IFGT:
-  case DK_IFLE:
-  case DK_IFLT:
-  case DK_IFNE:
+  case DK_IFE:
     return parseDirectiveIf(IDLoc, DirKind);
   case DK_IFB:
     return parseDirectiveIfb(IDLoc, true);
   case DK_IFNB:
     return parseDirectiveIfb(IDLoc, false);
-  case DK_IFC:
-    return parseDirectiveIfc(IDLoc, true);
-  case DK_IFEQS:
-    return parseDirectiveIfeqs(IDLoc, true);
-  case DK_IFNC:
-    return parseDirectiveIfc(IDLoc, false);
-  case DK_IFNES:
-    return parseDirectiveIfeqs(IDLoc, false);
   case DK_IFDEF:
     return parseDirectiveIfdef(IDLoc, true);
   case DK_IFNDEF:
-  case DK_IFNOTDEF:
     return parseDirectiveIfdef(IDLoc, false);
+  case DK_IFDIF:
+    return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
+                               /*CaseInsensitive=*/false);
+  case DK_IFDIFI:
+    return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/false,
+                               /*CaseInsensitive=*/true);
+  case DK_IFIDN:
+    return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
+                               /*CaseInsensitive=*/false);
+  case DK_IFIDNI:
+    return parseDirectiveIfidn(IDLoc, /*ExpectEqual=*/true,
+                               /*CaseInsensitive=*/true);
   case DK_ELSEIF:
-    return parseDirectiveElseIf(IDLoc);
+  case DK_ELSEIFE:
+    return parseDirectiveElseIf(IDLoc, DirKind);
+  case DK_ELSEIFB:
+    return parseDirectiveElseIfb(IDLoc, true);
+  case DK_ELSEIFNB:
+    return parseDirectiveElseIfb(IDLoc, false);
+  case DK_ELSEIFDEF:
+    return parseDirectiveElseIfdef(IDLoc, true);
+  case DK_ELSEIFNDEF:
+    return parseDirectiveElseIfdef(IDLoc, false);
+  case DK_ELSEIFDIF:
+    return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
+                                   /*CaseInsensitive=*/false);
+  case DK_ELSEIFDIFI:
+    return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/false,
+                                   /*CaseInsensitive=*/true);
+  case DK_ELSEIFIDN:
+    return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
+                                   /*CaseInsensitive=*/false);
+  case DK_ELSEIFIDNI:
+    return parseDirectiveElseIfidn(IDLoc, /*ExpectEqual=*/true,
+                                   /*CaseInsensitive=*/true);
   case DK_ELSE:
     return parseDirectiveElse(IDLoc);
   case DK_ENDIF:
@@ -1867,14 +1865,6 @@
     return false;
   }
 
-  case AsmToken::Equal:
-    if (!getTargetParser().equalIsAsmAssignment())
-      break;
-    // identifier '=' ... -> assignment statement
-    Lex();
-
-    return parseAssignment(IDVal, true);
-
   default: // Normal instruction or directive.
     break;
   }
@@ -1887,8 +1877,7 @@
 
   // Otherwise, we have a normal instruction or directive.
 
-  // Directives start with "."
-  if (IDVal.startswith(".") && IDVal != ".") {
+  if (DirKind != DK_NO_DIRECTIVE) {
     // There are several entities interested in parsing directives:
     //
     // 1. The target-specific assembly parser. Some directives are target
@@ -1903,7 +1892,8 @@
     getTargetParser().flushPendingInstructions(getStreamer());
 
     SMLoc StartTokLoc = getTok().getLoc();
-    bool TPDirectiveReturn = getTargetParser().ParseDirective(ID);
+    bool TPDirectiveReturn =
+        ID.is(AsmToken::Identifier) && getTargetParser().ParseDirective(ID);
 
     if (hasPendingError())
       return true;
@@ -1930,110 +1920,44 @@
     switch (DirKind) {
     default:
       break;
-    case DK_SET:
-    case DK_EQU:
-      return parseDirectiveSet(IDVal, true);
-    case DK_EQUIV:
-      return parseDirectiveSet(IDVal, false);
     case DK_ASCII:
       return parseDirectiveAscii(IDVal, false);
     case DK_ASCIZ:
     case DK_STRING:
       return parseDirectiveAscii(IDVal, true);
     case DK_BYTE:
-    case DK_DC_B:
+    case DK_DB:
       return parseDirectiveValue(IDVal, 1);
-    case DK_DC:
-    case DK_DC_W:
-    case DK_SHORT:
-    case DK_VALUE:
-    case DK_2BYTE:
+    case DK_WORD:
+    case DK_DW:
       return parseDirectiveValue(IDVal, 2);
-    case DK_LONG:
-    case DK_INT:
-    case DK_4BYTE:
-    case DK_DC_L:
+    case DK_DWORD:
+    case DK_DD:
       return parseDirectiveValue(IDVal, 4);
-    case DK_QUAD:
-    case DK_8BYTE:
+    case DK_FWORD:
+      return parseDirectiveValue(IDVal, 6);
+    case DK_QWORD:
+    case DK_DQ:
       return parseDirectiveValue(IDVal, 8);
-    case DK_DC_A:
-      return parseDirectiveValue(
-          IDVal, getContext().getAsmInfo()->getCodePointerSize());
-    case DK_OCTA:
-      return parseDirectiveOctaValue(IDVal);
-    case DK_SINGLE:
-    case DK_FLOAT:
-    case DK_DC_S:
+    case DK_REAL4:
       return parseDirectiveRealValue(IDVal, APFloat::IEEEsingle());
-    case DK_DOUBLE:
-    case DK_DC_D:
+    case DK_REAL8:
       return parseDirectiveRealValue(IDVal, APFloat::IEEEdouble());
-    case DK_ALIGN: {
-      bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
-      return parseDirectiveAlign(IsPow2, /*ExprSize=*/1);
-    }
-    case DK_ALIGN32: {
-      bool IsPow2 = !getContext().getAsmInfo()->getAlignmentIsInBytes();
-      return parseDirectiveAlign(IsPow2, /*ExprSize=*/4);
-    }
-    case DK_BALIGN:
-      return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/1);
-    case DK_BALIGNW:
-      return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/2);
-    case DK_BALIGNL:
-      return parseDirectiveAlign(/*IsPow2=*/false, /*ExprSize=*/4);
-    case DK_P2ALIGN:
-      return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/1);
-    case DK_P2ALIGNW:
-      return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/2);
-    case DK_P2ALIGNL:
-      return parseDirectiveAlign(/*IsPow2=*/true, /*ExprSize=*/4);
+    case DK_ALIGN:
+      return parseDirectiveAlign();
     case DK_ORG:
       return parseDirectiveOrg();
-    case DK_FILL:
-      return parseDirectiveFill();
-    case DK_ZERO:
-      return parseDirectiveZero();
     case DK_EXTERN:
       eatToEndOfStatement(); // .extern is the default, ignore it.
       return false;
-    case DK_GLOBL:
-    case DK_GLOBAL:
+    case DK_PUBLIC:
       return parseDirectiveSymbolAttribute(MCSA_Global);
-    case DK_LAZY_REFERENCE:
-      return parseDirectiveSymbolAttribute(MCSA_LazyReference);
-    case DK_NO_DEAD_STRIP:
-      return parseDirectiveSymbolAttribute(MCSA_NoDeadStrip);
-    case DK_SYMBOL_RESOLVER:
-      return parseDirectiveSymbolAttribute(MCSA_SymbolResolver);
-    case DK_PRIVATE_EXTERN:
-      return parseDirectiveSymbolAttribute(MCSA_PrivateExtern);
-    case DK_REFERENCE:
-      return parseDirectiveSymbolAttribute(MCSA_Reference);
-    case DK_WEAK_DEFINITION:
-      return parseDirectiveSymbolAttribute(MCSA_WeakDefinition);
-    case DK_WEAK_REFERENCE:
-      return parseDirectiveSymbolAttribute(MCSA_WeakReference);
-    case DK_WEAK_DEF_CAN_BE_HIDDEN:
-      return parseDirectiveSymbolAttribute(MCSA_WeakDefAutoPrivate);
-    case DK_COLD:
-      return parseDirectiveSymbolAttribute(MCSA_Cold);
     case DK_COMM:
-    case DK_COMMON:
       return parseDirectiveComm(/*IsLocal=*/false);
-    case DK_LCOMM:
-      return parseDirectiveComm(/*IsLocal=*/true);
-    case DK_ABORT:
-      return parseDirectiveAbort();
+    case DK_COMMENT:
+      return parseDirectiveComment(IDLoc);
     case DK_INCLUDE:
       return parseDirectiveInclude();
-    case DK_INCBIN:
-      return parseDirectiveIncbin();
-    case DK_CODE16:
-    case DK_CODE16GCC:
-      return TokError(Twine(IDVal) +
-                      " not currently supported for this target");
     case DK_REPT:
       return parseDirectiveRept(IDLoc, IDVal);
     case DK_IRP:
@@ -2042,19 +1966,6 @@
       return parseDirectiveIrpc(IDLoc);
     case DK_ENDR:
       return parseDirectiveEndr(IDLoc);
-    case DK_BUNDLE_ALIGN_MODE:
-      return parseDirectiveBundleAlignMode();
-    case DK_BUNDLE_LOCK:
-      return parseDirectiveBundleLock();
-    case DK_BUNDLE_UNLOCK:
-      return parseDirectiveBundleUnlock();
-    case DK_SLEB128:
-      return parseDirectiveLEB128(true);
-    case DK_ULEB128:
-      return parseDirectiveLEB128(false);
-    case DK_SPACE:
-    case DK_SKIP:
-      return parseDirectiveSpace(IDVal);
     case DK_FILE:
       return parseDirectiveFile(IDLoc);
     case DK_LINE:
@@ -2129,9 +2040,6 @@
       return parseDirectiveCFIRegister(IDLoc);
     case DK_CFI_WINDOW_SAVE:
       return parseDirectiveCFIWindowSave();
-    case DK_MACROS_ON:
-    case DK_MACROS_OFF:
-      return parseDirectiveMacrosOnOff(IDVal);
     case DK_MACRO:
       return parseDirectiveMacro(IDLoc);
     case DK_ALTMACRO:
@@ -2140,59 +2048,86 @@
     case DK_EXITM:
       return parseDirectiveExitMacro(IDVal);
     case DK_ENDM:
-    case DK_ENDMACRO:
       return parseDirectiveEndMacro(IDVal);
     case DK_PURGEM:
       return parseDirectivePurgeMacro(IDLoc);
     case DK_END:
       return parseDirectiveEnd(IDLoc);
     case DK_ERR:
-      return parseDirectiveError(IDLoc, false);
-    case DK_ERROR:
-      return parseDirectiveError(IDLoc, true);
-    case DK_WARNING:
-      return parseDirectiveWarning(IDLoc);
-    case DK_RELOC:
-      return parseDirectiveReloc(IDLoc);
-    case DK_DCB:
-    case DK_DCB_W:
-      return parseDirectiveDCB(IDVal, 2);
-    case DK_DCB_B:
-      return parseDirectiveDCB(IDVal, 1);
-    case DK_DCB_D:
-      return parseDirectiveRealDCB(IDVal, APFloat::IEEEdouble());
-    case DK_DCB_L:
-      return parseDirectiveDCB(IDVal, 4);
-    case DK_DCB_S:
-      return parseDirectiveRealDCB(IDVal, APFloat::IEEEsingle());
-    case DK_DC_X:
-    case DK_DCB_X:
-      return TokError(Twine(IDVal) +
-                      " not currently supported for this target");
-    case DK_DS:
-    case DK_DS_W:
-      return parseDirectiveDS(IDVal, 2);
-    case DK_DS_B:
-      return parseDirectiveDS(IDVal, 1);
-    case DK_DS_D:
-      return parseDirectiveDS(IDVal, 8);
-    case DK_DS_L:
-    case DK_DS_S:
-      return parseDirectiveDS(IDVal, 4);
-    case DK_DS_P:
-    case DK_DS_X:
-      return parseDirectiveDS(IDVal, 12);
-    case DK_PRINT:
-      return parseDirectivePrint(IDLoc);
-    case DK_ADDRSIG:
-      return parseDirectiveAddrsig();
-    case DK_ADDRSIG_SYM:
-      return parseDirectiveAddrsigSym();
+      return parseDirectiveError(IDLoc);
+    case DK_ERRB:
+      return parseDirectiveErrorIfb(IDLoc, true);
+    case DK_ERRNB:
+      return parseDirectiveErrorIfb(IDLoc, false);
+    case DK_ERRDEF:
+      return parseDirectiveErrorIfdef(IDLoc, true);
+    case DK_ERRNDEF:
+      return parseDirectiveErrorIfdef(IDLoc, false);
+    case DK_ERRDIF:
+      return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
+                                      /*CaseInsensitive=*/false);
+    case DK_ERRDIFI:
+      return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/false,
+                                      /*CaseInsensitive=*/true);
+    case DK_ERRIDN:
+      return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
+                                      /*CaseInsensitive=*/false);
+    case DK_ERRIDNI:
+      return parseDirectiveErrorIfidn(IDLoc, /*ExpectEqual=*/true,
+                                      /*CaseInsensitive=*/true);
+    case DK_ERRE:
+      return parseDirectiveErrorIfe(IDLoc, true);
+    case DK_ERRNZ:
+      return parseDirectiveErrorIfe(IDLoc, false);
+    case DK_ECHO:
+      return parseDirectiveEcho();
     }
 
     return Error(IDLoc, "unknown directive");
   }
 
+  // Non-conditional Microsoft directives sometimes follow their first argument.
+  const AsmToken nextTok = getTok();
+  const StringRef nextVal = nextTok.getString();
+  const SMLoc nextLoc = nextTok.getLoc();
+
+  // There are several entities interested in parsing infix directives:
+  //
+  // 1. Asm parser extensions. For example, platform-specific parsers
+  //    (like the ELF parser) register themselves as extensions.
+  // 2. The generic directive parser implemented by this class. These are
+  //    all the directives that behave in a target and platform independent
+  //    manner, or at least have a default behavior that's shared between
+  //    all targets and platforms.
+
+  getTargetParser().flushPendingInstructions(getStreamer());
+
+  // First, check the extension directive map to see if any extension has
+  // registered itself to parse this directive.
+  std::pair<MCAsmParserExtension *, DirectiveHandler> Handler =
+      ExtensionDirectiveMap.lookup(nextVal);
+  if (Handler.first) {
+    Lex();
+    Lexer.UnLex(ID);
+    return (*Handler.second)(Handler.first, nextVal, nextLoc);
+  }
+
+  // Finally, if no one else is interested in this directive, it must be
+  // generic and familiar to this class.
+  DirKindIt = DirectiveKindMap.find(nextVal);
+  DirKind = (DirKindIt == DirectiveKindMap.end())
+                ? DK_NO_DIRECTIVE
+                : DirKindIt->getValue();
+  switch (DirKind) {
+  default:
+    break;
+  case DK_ASSIGN:
+  case DK_EQU:
+  case DK_TEXTEQU:
+    Lex();
+    return parseDirectiveEquate(nextVal, IDVal, DirKind);
+  }
+
   // __asm _emit or __asm __emit
   if (ParsingInlineAsm && (IDVal == "_emit" || IDVal == "__emit" ||
                            IDVal == "_EMIT" || IDVal == "__EMIT"))
@@ -2276,8 +2211,8 @@
 }
 
 // Parse and erase curly braces marking block start/end
-bool
-AsmParser::parseCurlyBlockScope(SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
+bool MasmParser::parseCurlyBlockScope(
+    SmallVectorImpl<AsmRewrite> &AsmStrRewrites) {
   // Identify curly brace marking block start/end
   if (Lexer.isNot(AsmToken::LCurly) && Lexer.isNot(AsmToken::RCurly))
     return false;
@@ -2295,7 +2230,7 @@
 
 /// parseCppHashLineFilenameComment as this:
 ///   ::= # number "filename"
-bool AsmParser::parseCppHashLineFilenameComment(SMLoc L) {
+bool MasmParser::parseCppHashLineFilenameComment(SMLoc L) {
   Lex(); // Eat the hash token.
   // Lexer only ever emits HashDirective if it fully formed if it's
   // done the checking already so this is an internal error.
@@ -2324,8 +2259,8 @@
 
 /// will use the last parsed cpp hash line filename comment
 /// for the Filename and LineNo if any in the diagnostic.
-void AsmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
-  const AsmParser *Parser = static_cast<const AsmParser *>(Context);
+void MasmParser::DiagHandler(const SMDiagnostic &Diag, void *Context) {
+  const MasmParser *Parser = static_cast<const MasmParser *>(Context);
   raw_ostream &OS = errs();
 
   const SourceMgr &DiagSrcMgr = *Diag.getSourceMgr();
@@ -2385,10 +2320,10 @@
          c == '.';
 }
 
-bool AsmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
-                            ArrayRef<MCAsmMacroParameter> Parameters,
-                            ArrayRef<MCAsmMacroArgument> A,
-                            bool EnableAtPseudoVariable, SMLoc L) {
+bool MasmParser::expandMacro(raw_svector_ostream &OS, StringRef Body,
+                             ArrayRef<MCAsmMacroParameter> Parameters,
+                             ArrayRef<MCAsmMacroArgument> A,
+                             bool EnableAtPseudoVariable, SMLoc L) {
   unsigned NParameters = Parameters.size();
   bool HasVararg = NParameters ? Parameters.back().Vararg : false;
   if ((!IsDarwin || NParameters != 0) && NParameters != A.size())
@@ -2497,7 +2432,7 @@
             // is considered altMacroString!!!
             else if (AltMacroMode && Token.getString().front() == '<' &&
                      Token.is(AsmToken::String)) {
-              OS << altMacroString(Token.getStringContents());
+              OS << angleBracketString(Token.getStringContents());
             }
             // We expect no quotes around the string's contents when
             // parsing for varargs.
@@ -2565,7 +2500,7 @@
 
 } // end anonymous namespace
 
-bool AsmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
+bool MasmParser::parseMacroArgument(MCAsmMacroArgument &MA, bool Vararg) {
 
   if (Vararg) {
     if (Lexer.isNot(AsmToken::EndOfStatement)) {
@@ -2638,8 +2573,8 @@
 }
 
 // Parse the macro instantiation arguments.
-bool AsmParser::parseMacroArguments(const MCAsmMacro *M,
-                                    MCAsmMacroArguments &A) {
+bool MasmParser::parseMacroArguments(const MCAsmMacro *M,
+                                     MCAsmMacroArguments &A) {
   const unsigned NParameters = M ? M->Parameters.size() : 0;
   bool NamedParametersFound = false;
   SmallVector<SMLoc, 4> FALocs;
@@ -2690,7 +2625,7 @@
                         StringRef(StrChar, EndChar - StrChar), Value);
       FA.Value.push_back(newToken);
     } else if (AltMacroMode && Lexer.is(AsmToken::Less) &&
-               isAltmacroString(StrLoc, EndLoc)) {
+               isAngleBracketString(StrLoc, EndLoc)) {
       const char *StrChar = StrLoc.getPointer();
       const char *EndChar = EndLoc.getPointer();
       jumpToLoc(EndLoc, CurBuffer);
@@ -2756,7 +2691,7 @@
   return TokError("too many positional arguments");
 }
 
-bool AsmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
+bool MasmParser::handleMacroEntry(const MCAsmMacro *M, SMLoc NameLoc) {
   // Arbitrarily limit macro nesting depth (default matches 'as'). We can
   // eliminate this, although we should protect against infinite loops.
   unsigned MaxNestingDepth = AsmMacroMaxNestingDepth;
@@ -2805,7 +2740,7 @@
   return false;
 }
 
-void AsmParser::handleMacroExit() {
+void MasmParser::handleMacroExit() {
   // Jump to the EndOfStatement we should return to, and consume it.
   jumpToLoc(ActiveMacros.back()->ExitLoc, ActiveMacros.back()->ExitBuffer);
   Lex();
@@ -2815,38 +2750,15 @@
   ActiveMacros.pop_back();
 }
 
-bool AsmParser::parseAssignment(StringRef Name, bool allow_redef,
-                                bool NoDeadStrip) {
-  MCSymbol *Sym;
-  const MCExpr *Value;
-  if (MCParserUtils::parseAssignmentExpression(Name, allow_redef, *this, Sym,
-                                               Value))
-    return true;
-
-  if (!Sym) {
-    // In the case where we parse an expression starting with a '.', we will
-    // not generate an error, nor will we create a symbol.  In this case we
-    // should just return out.
-    return false;
-  }
-
-  // Do the assignment.
-  Out.EmitAssignment(Sym, Value);
-  if (NoDeadStrip)
-    Out.EmitSymbolAttribute(Sym, MCSA_NoDeadStrip);
-
-  return false;
-}
-
 /// parseIdentifier:
 ///   ::= identifier
 ///   ::= string
-bool AsmParser::parseIdentifier(StringRef &Res) {
+bool MasmParser::parseIdentifier(StringRef &Res) {
   // The assembler has relaxed rules for accepting identifiers, in particular we
-  // allow things like '.globl $foo' and '.def @feat.00', which would normally be
-  // separate tokens. At this level, we have already lexed so we cannot (currently)
-  // handle this as a context dependent token, instead we detect adjacent tokens
-  // and return the combined identifier.
+  // allow things like '.globl $foo' and '.def @feat.00', which would normally
+  // be separate tokens. At this level, we have already lexed so we cannot
+  // (currently) handle this as a context dependent token, instead we detect
+  // adjacent tokens and return the combined identifier.
   if (Lexer.is(AsmToken::Dollar) || Lexer.is(AsmToken::At)) {
     SMLoc PrefixLoc = getLexer().getLoc();
 
@@ -2881,19 +2793,61 @@
   return false;
 }
 
-/// parseDirectiveSet:
-///   ::= .equ identifier ',' expression
-///   ::= .equiv identifier ',' expression
-///   ::= .set identifier ',' expression
-bool AsmParser::parseDirectiveSet(StringRef IDVal, bool allow_redef) {
-  StringRef Name;
-  if (check(parseIdentifier(Name), "expected identifier") ||
-      parseToken(AsmToken::Comma) || parseAssignment(Name, allow_redef, true))
+/// parseDirectiveEquate:
+///  ::= name "=" expression
+///    | name "equ" expression    (not redefinable)
+///    | name "equ" text-list
+///    | name "textequ" text-list
+bool MasmParser::parseDirectiveEquate(StringRef IDVal, StringRef Name,
+                                      DirectiveKind DirKind) {
+  Variable &Var = Variables[Name];
+  if (Var.Name.empty()) {
+    Var.Name = Name;
+  } else if (!Var.Redefinable) {
+    return TokError("invalid variable redefinition");
+  }
+  Var.Redefinable = (DirKind != DK_EQU);
+
+  if (DirKind == DK_EQU || DirKind == DK_TEXTEQU) {
+    // "equ" and "textequ" both allow text expressions.
+    std::string Value;
+    if (!parseTextItem(Value)) {
+      Var.IsText = true;
+      Var.TextValue = Value;
+
+      // Accept a text-list, not just one text-item
+      auto parseItem = [&]() -> bool {
+        if (parseTextItem(Value))
+          return true;
+        Var.TextValue += Value;
+        return false;
+      };
+      if (parseOptionalToken(AsmToken::Comma) && parseMany(parseItem))
+        return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+
+      return false;
+    }
+  }
+  if (DirKind == DK_TEXTEQU)
+    return TokError("expected <text> in '" + Twine(IDVal) + "' directive");
+
+  // Parse as expression assignment
+  const MCExpr *Expr;
+  SMLoc EndLoc, StartLoc = Lexer.getLoc();
+  if (parseExpression(Expr, EndLoc))
     return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
+  if (Expr->evaluateAsAbsolute(Var.NumericValue,
+                               getStreamer().getAssemblerPtr()))
+    return false;
+
+  // Not an absolute expression; define as a text replacement.
+  Var.IsText = true;
+  Var.TextValue = StringRef(StartLoc.getPointer(),
+                            EndLoc.getPointer() - StartLoc.getPointer());
   return false;
 }
 
-bool AsmParser::parseEscapedString(std::string &Data) {
+bool MasmParser::parseEscapedString(std::string &Data) {
   if (check(getTok().isNot(AsmToken::String), "expected string"))
     return true;
 
@@ -2969,9 +2923,30 @@
   return false;
 }
 
+bool MasmParser::parseAngleBracketString(std::string &Data) {
+  SMLoc EndLoc, StartLoc = getTok().getLoc();
+  if (isAngleBracketString(StartLoc, EndLoc)) {
+    const char *StartChar = StartLoc.getPointer() + 1;
+    const char *EndChar = EndLoc.getPointer() - 1;
+    jumpToLoc(EndLoc, CurBuffer);
+    /// Eat from '<' to '>'
+    Lex();
+
+    Data = angleBracketString(StringRef(StartChar, EndChar - StartChar));
+    return false;
+  }
+  return true;
+}
+
+/// textItem ::= textLiteral | textMacroID | % constExpr
+bool MasmParser::parseTextItem(std::string &Data) {
+  // TODO(epastor): Support textMacroID and % expansion of expressions.
+  return parseAngleBracketString(Data);
+}
+
 /// parseDirectiveAscii:
 ///   ::= ( .ascii | .asciz | .string ) [ "string" ( , "string" )* ]
-bool AsmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
+bool MasmParser::parseDirectiveAscii(StringRef IDVal, bool ZeroTerminated) {
   auto parseOp = [&]() -> bool {
     std::string Data;
     if (checkForValidSection() || parseEscapedString(Data))
@@ -2987,57 +2962,9 @@
   return false;
 }
 
-/// parseDirectiveReloc
-///  ::= .reloc expression , identifier [ , expression ]
-bool AsmParser::parseDirectiveReloc(SMLoc DirectiveLoc) {
-  const MCExpr *Offset;
-  const MCExpr *Expr = nullptr;
-  int64_t OffsetValue;
-  SMLoc OffsetLoc = Lexer.getTok().getLoc();
-
-  if (parseExpression(Offset))
-    return true;
-
-  if ((Offset->evaluateAsAbsolute(OffsetValue,
-                                  getStreamer().getAssemblerPtr()) &&
-       check(OffsetValue < 0, OffsetLoc, "expression is negative")) ||
-      (check(Offset->getKind() != llvm::MCExpr::Constant &&
-             Offset->getKind() != llvm::MCExpr::SymbolRef,
-             OffsetLoc, "expected non-negative number or a label")) ||
-      (parseToken(AsmToken::Comma, "expected comma") ||
-       check(getTok().isNot(AsmToken::Identifier), "expected relocation name")))
-    return true;
-
-  SMLoc NameLoc = Lexer.getTok().getLoc();
-  StringRef Name = Lexer.getTok().getIdentifier();
-  Lex();
-
-  if (Lexer.is(AsmToken::Comma)) {
-    Lex();
-    SMLoc ExprLoc = Lexer.getLoc();
-    if (parseExpression(Expr))
-      return true;
-
-    MCValue Value;
-    if (!Expr->evaluateAsRelocatable(Value, nullptr, nullptr))
-      return Error(ExprLoc, "expression must be relocatable");
-  }
-
-  if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in .reloc directive"))
-      return true;
-
-  const MCTargetAsmParser &MCT = getTargetParser();
-  const MCSubtargetInfo &STI = MCT.getSTI();
-  if (getStreamer().EmitRelocDirective(*Offset, Name, Expr, DirectiveLoc, STI))
-    return Error(NameLoc, "unknown relocation name");
-
-  return false;
-}
-
 /// parseDirectiveValue
-///  ::= (.byte | .short | ... ) [ expression (, expression)* ]
-bool AsmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
+///  ::= (byte | word | ... ) [ expression (, expression)* ]
+bool MasmParser::parseDirectiveValue(StringRef IDVal, unsigned Size) {
   auto parseOp = [&]() -> bool {
     const MCExpr *Value;
     SMLoc ExprLoc = getLexer().getLoc();
@@ -3060,7 +2987,7 @@
   return false;
 }
 
-static bool parseHexOcta(AsmParser &Asm, uint64_t &hi, uint64_t &lo) {
+static bool parseHexOcta(MasmParser &Asm, uint64_t &hi, uint64_t &lo) {
   if (Asm.getTok().isNot(AsmToken::Integer) &&
       Asm.getTok().isNot(AsmToken::BigNum))
     return Asm.TokError("unknown token in expression");
@@ -3079,32 +3006,7 @@
   return false;
 }
 
-/// ParseDirectiveOctaValue
-///  ::= .octa [ hexconstant (, hexconstant)* ]
-
-bool AsmParser::parseDirectiveOctaValue(StringRef IDVal) {
-  auto parseOp = [&]() -> bool {
-    if (checkForValidSection())
-      return true;
-    uint64_t hi, lo;
-    if (parseHexOcta(*this, hi, lo))
-      return true;
-    if (MAI.isLittleEndian()) {
-      getStreamer().EmitIntValue(lo, 8);
-      getStreamer().EmitIntValue(hi, 8);
-    } else {
-      getStreamer().EmitIntValue(hi, 8);
-      getStreamer().EmitIntValue(lo, 8);
-    }
-    return false;
-  };
-
-  if (parseMany(parseOp))
-    return addErrorSuffix(" in '" + Twine(IDVal) + "' directive");
-  return false;
-}
-
-bool AsmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
+bool MasmParser::parseRealValue(const fltSemantics &Semantics, APInt &Res) {
   // We don't truly support arithmetic on floating point expressions, so we
   // have to manually parse unary prefixes.
   bool IsNeg = false;
@@ -3147,8 +3049,8 @@
 
 /// parseDirectiveRealValue
 ///  ::= (.single | .double) [ expression (, expression)* ]
-bool AsmParser::parseDirectiveRealValue(StringRef IDVal,
-                                        const fltSemantics &Semantics) {
+bool MasmParser::parseDirectiveRealValue(StringRef IDVal,
+                                         const fltSemantics &Semantics) {
   auto parseOp = [&]() -> bool {
     APInt AsInt;
     if (checkForValidSection() || parseRealValue(Semantics, AsInt))
@@ -3163,76 +3065,9 @@
   return false;
 }
 
-/// parseDirectiveZero
-///  ::= .zero expression
-bool AsmParser::parseDirectiveZero() {
-  SMLoc NumBytesLoc = Lexer.getLoc();
-  const MCExpr *NumBytes;
-  if (checkForValidSection() || parseExpression(NumBytes))
-    return true;
-
-  int64_t Val = 0;
-  if (getLexer().is(AsmToken::Comma)) {
-    Lex();
-    if (parseAbsoluteExpression(Val))
-      return true;
-  }
-
-  if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '.zero' directive"))
-    return true;
-  getStreamer().emitFill(*NumBytes, Val, NumBytesLoc);
-
-  return false;
-}
-
-/// parseDirectiveFill
-///  ::= .fill expression [ , expression [ , expression ] ]
-bool AsmParser::parseDirectiveFill() {
-  SMLoc NumValuesLoc = Lexer.getLoc();
-  const MCExpr *NumValues;
-  if (checkForValidSection() || parseExpression(NumValues))
-    return true;
-
-  int64_t FillSize = 1;
-  int64_t FillExpr = 0;
-
-  SMLoc SizeLoc, ExprLoc;
-
-  if (parseOptionalToken(AsmToken::Comma)) {
-    SizeLoc = getTok().getLoc();
-    if (parseAbsoluteExpression(FillSize))
-      return true;
-    if (parseOptionalToken(AsmToken::Comma)) {
-      ExprLoc = getTok().getLoc();
-      if (parseAbsoluteExpression(FillExpr))
-        return true;
-    }
-  }
-  if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '.fill' directive"))
-    return true;
-
-  if (FillSize < 0) {
-    Warning(SizeLoc, "'.fill' directive with negative size has no effect");
-    return false;
-  }
-  if (FillSize > 8) {
-    Warning(SizeLoc, "'.fill' directive with size greater than 8 has been truncated to 8");
-    FillSize = 8;
-  }
-
-  if (!isUInt<32>(FillExpr) && FillSize > 4)
-    Warning(ExprLoc, "'.fill' directive pattern has been truncated to 32-bits");
-
-  getStreamer().emitFill(*NumValues, FillSize, FillExpr, NumValuesLoc);
-
-  return false;
-}
-
 /// parseDirectiveOrg
 ///  ::= .org expression [ , expression ]
-bool AsmParser::parseDirectiveOrg() {
+bool MasmParser::parseDirectiveOrg() {
   const MCExpr *Offset;
   SMLoc OffsetLoc = Lexer.getLoc();
   if (checkForValidSection() || parseExpression(Offset))
@@ -3251,95 +3086,43 @@
 }
 
 /// parseDirectiveAlign
-///  ::= {.align, ...} expression [ , expression [ , expression ]]
-bool AsmParser::parseDirectiveAlign(bool IsPow2, unsigned ValueSize) {
+///  ::= align expression
+bool MasmParser::parseDirectiveAlign() {
   SMLoc AlignmentLoc = getLexer().getLoc();
   int64_t Alignment;
-  SMLoc MaxBytesLoc;
-  bool HasFillExpr = false;
-  int64_t FillExpr = 0;
-  int64_t MaxBytesToFill = 0;
-
-  auto parseAlign = [&]() -> bool {
-    if (parseAbsoluteExpression(Alignment))
-      return true;
-    if (parseOptionalToken(AsmToken::Comma)) {
-      // The fill expression can be omitted while specifying a maximum number of
-      // alignment bytes, e.g:
-      //  .align 3,,4
-      if (getTok().isNot(AsmToken::Comma)) {
-        HasFillExpr = true;
-        if (parseAbsoluteExpression(FillExpr))
-          return true;
-      }
-      if (parseOptionalToken(AsmToken::Comma))
-        if (parseTokenLoc(MaxBytesLoc) ||
-            parseAbsoluteExpression(MaxBytesToFill))
-          return true;
-    }
-    return parseToken(AsmToken::EndOfStatement);
-  };
 
   if (checkForValidSection())
-    return addErrorSuffix(" in directive");
-  // Ignore empty '.p2align' directives for GNU-as compatibility
-  if (IsPow2 && (ValueSize == 1) && getTok().is(AsmToken::EndOfStatement)) {
-    Warning(AlignmentLoc, "p2align directive with no operand(s) is ignored");
+    return addErrorSuffix(" in align directive");
+  // Ignore empty 'align' directives
+  if (getTok().is(AsmToken::EndOfStatement)) {
+    Warning(AlignmentLoc, "align directive with no operand is ignored");
     return parseToken(AsmToken::EndOfStatement);
   }
-  if (parseAlign())
-    return addErrorSuffix(" in directive");
+  if (parseAbsoluteExpression(Alignment) ||
+      parseToken(AsmToken::EndOfStatement))
+    return addErrorSuffix(" in align directive");
 
   // Always emit an alignment here even if we thrown an error.
   bool ReturnVal = false;
 
-  // Compute alignment in bytes.
-  if (IsPow2) {
-    // FIXME: Diagnose overflow.
-    if (Alignment >= 32) {
-      ReturnVal |= Error(AlignmentLoc, "invalid alignment value");
-      Alignment = 31;
-    }
-
-    Alignment = 1ULL << Alignment;
-  } else {
-    // Reject alignments that aren't either a power of two or zero,
-    // for gas compatibility. Alignment of zero is silently rounded
-    // up to one.
-    if (Alignment == 0)
-      Alignment = 1;
-    if (!isPowerOf2_64(Alignment))
-      ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
-  }
-
-  // Diagnose non-sensical max bytes to align.
-  if (MaxBytesLoc.isValid()) {
-    if (MaxBytesToFill < 1) {
-      ReturnVal |= Error(MaxBytesLoc,
-                         "alignment directive can never be satisfied in this "
-                         "many bytes, ignoring maximum bytes expression");
-      MaxBytesToFill = 0;
-    }
+  // Reject alignments that aren't either a power of two or zero,
+  // for gas compatibility. Alignment of zero is silently rounded
+  // up to one.
+  if (Alignment == 0)
+    Alignment = 1;
+  if (!isPowerOf2_64(Alignment))
+    ReturnVal |= Error(AlignmentLoc, "alignment must be a power of 2");
 
-    if (MaxBytesToFill >= Alignment) {
-      Warning(MaxBytesLoc, "maximum bytes expression exceeds alignment and "
-                           "has no effect");
-      MaxBytesToFill = 0;
-    }
-  }
-
-  // Check whether we should use optimal code alignment for this .align
+  // Check whether we should use optimal code alignment for this align
   // directive.
   const MCSection *Section = getStreamer().getCurrentSectionOnly();
   assert(Section && "must have section to emit alignment");
-  bool UseCodeAlign = Section->UseCodeAlign();
-  if ((!HasFillExpr || Lexer.getMAI().getTextAlignFillValue() == FillExpr) &&
-      ValueSize == 1 && UseCodeAlign) {
-    getStreamer().EmitCodeAlignment(Alignment, MaxBytesToFill);
+  if (Section->UseCodeAlign()) {
+    getStreamer().EmitCodeAlignment(Alignment, /*MaxBytesToEmit=*/0);
   } else {
     // FIXME: Target specific behavior about how the "extra" bytes are filled.
-    getStreamer().EmitValueToAlignment(Alignment, FillExpr, ValueSize,
-                                       MaxBytesToFill);
+    getStreamer().EmitValueToAlignment(Alignment, /*Value=*/0, /*ValueSize=*/1,
+                                       /*MaxBytesToEmit=*/0);
   }
 
   return ReturnVal;
@@ -3348,7 +3131,7 @@
 /// parseDirectiveFile
 /// ::= .file filename
 /// ::= .file number [directory] filename [md5 checksum] [source source-text]
-bool AsmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveFile(SMLoc DirectiveLoc) {
   // FIXME: I'm not sure what this is.
   int64_t FileNumber = -1;
   if (getLexer().is(AsmToken::Integer)) {
@@ -3466,7 +3249,7 @@
 
 /// parseDirectiveLine
 /// ::= .line [number]
-bool AsmParser::parseDirectiveLine() {
+bool MasmParser::parseDirectiveLine() {
   int64_t LineNumber;
   if (getLexer().is(AsmToken::Integer)) {
     if (parseIntToken(LineNumber, "unexpected token in '.line' directive"))
@@ -3488,7 +3271,7 @@
 /// a .file directive, the second number is the line number and optionally the
 /// third number is a column position (zero if not specified).  The remaining
 /// optional items are .loc sub-directives.
-bool AsmParser::parseDirectiveLoc() {
+bool MasmParser::parseDirectiveLoc() {
   int64_t FileNumber = 0, LineNumber = 0;
   SMLoc Loc = getTok().getLoc();
   if (parseIntToken(FileNumber, "unexpected token in '.loc' directive") ||
@@ -3581,13 +3364,13 @@
 
 /// parseDirectiveStabs
 /// ::= .stabs string, number, number, number
-bool AsmParser::parseDirectiveStabs() {
+bool MasmParser::parseDirectiveStabs() {
   return TokError("unsupported directive '.stabs'");
 }
 
 /// parseDirectiveCVFile
 /// ::= .cv_file number filename [checksum] [checksumkind]
-bool AsmParser::parseDirectiveCVFile() {
+bool MasmParser::parseDirectiveCVFile() {
   SMLoc FileNumberLoc = getTok().getLoc();
   int64_t FileNumber;
   std::string Filename;
@@ -3625,8 +3408,8 @@
   return false;
 }
 
-bool AsmParser::parseCVFunctionId(int64_t &FunctionId,
-                                  StringRef DirectiveName) {
+bool MasmParser::parseCVFunctionId(int64_t &FunctionId,
+                                   StringRef DirectiveName) {
   SMLoc Loc;
   return parseTokenLoc(Loc) ||
          parseIntToken(FunctionId, "expected function id in '" + DirectiveName +
@@ -3635,7 +3418,7 @@
                "expected function id within range [0, UINT_MAX)");
 }
 
-bool AsmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
+bool MasmParser::parseCVFileId(int64_t &FileNumber, StringRef DirectiveName) {
   SMLoc Loc;
   return parseTokenLoc(Loc) ||
          parseIntToken(FileNumber, "expected integer in '" + DirectiveName +
@@ -3650,7 +3433,7 @@
 /// ::= .cv_func_id FunctionId
 ///
 /// Introduces a function ID that can be used with .cv_loc.
-bool AsmParser::parseDirectiveCVFuncId() {
+bool MasmParser::parseDirectiveCVFuncId() {
   SMLoc FunctionIdLoc = getTok().getLoc();
   int64_t FunctionId;
 
@@ -3673,7 +3456,7 @@
 /// Introduces a function ID that can be used with .cv_loc. Includes "inlined
 /// at" source location information for use in the line table of the caller,
 /// whether the caller is a real function or another inlined call site.
-bool AsmParser::parseDirectiveCVInlineSiteId() {
+bool MasmParser::parseDirectiveCVInlineSiteId() {
   SMLoc FunctionIdLoc = getTok().getLoc();
   int64_t FunctionId;
   int64_t IAFunc;
@@ -3733,7 +3516,7 @@
 /// a .file directive, the second number is the line number and optionally the
 /// third number is a column position (zero if not specified).  The remaining
 /// optional items are .loc sub-directives.
-bool AsmParser::parseDirectiveCVLoc() {
+bool MasmParser::parseDirectiveCVLoc() {
   SMLoc DirectiveLoc = getTok().getLoc();
   int64_t FunctionId, FileNumber;
   if (parseCVFunctionId(FunctionId, ".cv_loc") ||
@@ -3795,7 +3578,7 @@
 
 /// parseDirectiveCVLinetable
 /// ::= .cv_linetable FunctionId, FnStart, FnEnd
-bool AsmParser::parseDirectiveCVLinetable() {
+bool MasmParser::parseDirectiveCVLinetable() {
   int64_t FunctionId;
   StringRef FnStartName, FnEndName;
   SMLoc Loc = getTok().getLoc();
@@ -3819,7 +3602,7 @@
 
 /// parseDirectiveCVInlineLinetable
 /// ::= .cv_inline_linetable PrimaryFunctionId FileId LineNum FnStart FnEnd
-bool AsmParser::parseDirectiveCVInlineLinetable() {
+bool MasmParser::parseDirectiveCVInlineLinetable() {
   int64_t PrimaryFunctionId, SourceFileId, SourceLineNum;
   StringRef FnStartName, FnEndName;
   SMLoc Loc = getTok().getLoc();
@@ -3853,7 +3636,7 @@
   return false;
 }
 
-void AsmParser::initializeCVDefRangeTypeMap() {
+void MasmParser::initializeCVDefRangeTypeMap() {
   CVDefRangeTypeMap["reg"] = CVDR_DEFRANGE_REGISTER;
   CVDefRangeTypeMap["frame_ptr_rel"] = CVDR_DEFRANGE_FRAMEPOINTER_REL;
   CVDefRangeTypeMap["subfield_reg"] = CVDR_DEFRANGE_SUBFIELD_REGISTER;
@@ -3862,7 +3645,7 @@
 
 /// parseDirectiveCVDefRange
 /// ::= .cv_def_range RangeStart RangeEnd (GapStart GapEnd)*, bytes*
-bool AsmParser::parseDirectiveCVDefRange() {
+bool MasmParser::parseDirectiveCVDefRange() {
   SMLoc Loc;
   std::vector<std::pair<const MCSymbol *, const MCSymbol *>> Ranges;
   while (getLexer().is(AsmToken::Identifier)) {
@@ -3971,7 +3754,7 @@
 
 /// parseDirectiveCVString
 /// ::= .cv_stringtable "string"
-bool AsmParser::parseDirectiveCVString() {
+bool MasmParser::parseDirectiveCVString() {
   std::string Data;
   if (checkForValidSection() || parseEscapedString(Data))
     return addErrorSuffix(" in '.cv_string' directive");
@@ -3985,21 +3768,21 @@
 
 /// parseDirectiveCVStringTable
 /// ::= .cv_stringtable
-bool AsmParser::parseDirectiveCVStringTable() {
+bool MasmParser::parseDirectiveCVStringTable() {
   getStreamer().EmitCVStringTableDirective();
   return false;
 }
 
 /// parseDirectiveCVFileChecksums
 /// ::= .cv_filechecksums
-bool AsmParser::parseDirectiveCVFileChecksums() {
+bool MasmParser::parseDirectiveCVFileChecksums() {
   getStreamer().EmitCVFileChecksumsDirective();
   return false;
 }
 
 /// parseDirectiveCVFileChecksumOffset
 /// ::= .cv_filechecksumoffset fileno
-bool AsmParser::parseDirectiveCVFileChecksumOffset() {
+bool MasmParser::parseDirectiveCVFileChecksumOffset() {
   int64_t FileNo;
   if (parseIntToken(FileNo, "expected identifier in directive"))
     return true;
@@ -4011,7 +3794,7 @@
 
 /// parseDirectiveCVFPOData
 /// ::= .cv_fpo_data procsym
-bool AsmParser::parseDirectiveCVFPOData() {
+bool MasmParser::parseDirectiveCVFPOData() {
   SMLoc DirLoc = getLexer().getLoc();
   StringRef ProcName;
   if (parseIdentifier(ProcName))
@@ -4025,7 +3808,7 @@
 
 /// parseDirectiveCFISections
 /// ::= .cfi_sections section [, section]
-bool AsmParser::parseDirectiveCFISections() {
+bool MasmParser::parseDirectiveCFISections() {
   StringRef Name;
   bool EH = false;
   bool Debug = false;
@@ -4056,7 +3839,7 @@
 
 /// parseDirectiveCFIStartProc
 /// ::= .cfi_startproc [simple]
-bool AsmParser::parseDirectiveCFIStartProc() {
+bool MasmParser::parseDirectiveCFIStartProc() {
   StringRef Simple;
   if (!parseOptionalToken(AsmToken::EndOfStatement)) {
     if (check(parseIdentifier(Simple) || Simple != "simple",
@@ -4076,14 +3859,14 @@
 
 /// parseDirectiveCFIEndProc
 /// ::= .cfi_endproc
-bool AsmParser::parseDirectiveCFIEndProc() {
+bool MasmParser::parseDirectiveCFIEndProc() {
   getStreamer().EmitCFIEndProc();
   return false;
 }
 
 /// parse register name or number.
-bool AsmParser::parseRegisterOrRegisterNumber(int64_t &Register,
-                                              SMLoc DirectiveLoc) {
+bool MasmParser::parseRegisterOrRegisterNumber(int64_t &Register,
+                                               SMLoc DirectiveLoc) {
   unsigned RegNo;
 
   if (getLexer().isNot(AsmToken::Integer)) {
@@ -4098,7 +3881,7 @@
 
 /// parseDirectiveCFIDefCfa
 /// ::= .cfi_def_cfa register,  offset
-bool AsmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveCFIDefCfa(SMLoc DirectiveLoc) {
   int64_t Register = 0, Offset = 0;
   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
       parseToken(AsmToken::Comma, "unexpected token in directive") ||
@@ -4111,7 +3894,7 @@
 
 /// parseDirectiveCFIDefCfaOffset
 /// ::= .cfi_def_cfa_offset offset
-bool AsmParser::parseDirectiveCFIDefCfaOffset() {
+bool MasmParser::parseDirectiveCFIDefCfaOffset() {
   int64_t Offset = 0;
   if (parseAbsoluteExpression(Offset))
     return true;
@@ -4122,7 +3905,7 @@
 
 /// parseDirectiveCFIRegister
 /// ::= .cfi_register register, register
-bool AsmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveCFIRegister(SMLoc DirectiveLoc) {
   int64_t Register1 = 0, Register2 = 0;
   if (parseRegisterOrRegisterNumber(Register1, DirectiveLoc) ||
       parseToken(AsmToken::Comma, "unexpected token in directive") ||
@@ -4135,14 +3918,14 @@
 
 /// parseDirectiveCFIWindowSave
 /// ::= .cfi_window_save
-bool AsmParser::parseDirectiveCFIWindowSave() {
+bool MasmParser::parseDirectiveCFIWindowSave() {
   getStreamer().EmitCFIWindowSave();
   return false;
 }
 
 /// parseDirectiveCFIAdjustCfaOffset
 /// ::= .cfi_adjust_cfa_offset adjustment
-bool AsmParser::parseDirectiveCFIAdjustCfaOffset() {
+bool MasmParser::parseDirectiveCFIAdjustCfaOffset() {
   int64_t Adjustment = 0;
   if (parseAbsoluteExpression(Adjustment))
     return true;
@@ -4153,7 +3936,7 @@
 
 /// parseDirectiveCFIDefCfaRegister
 /// ::= .cfi_def_cfa_register register
-bool AsmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveCFIDefCfaRegister(SMLoc DirectiveLoc) {
   int64_t Register = 0;
   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
     return true;
@@ -4164,7 +3947,7 @@
 
 /// parseDirectiveCFIOffset
 /// ::= .cfi_offset register, offset
-bool AsmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveCFIOffset(SMLoc DirectiveLoc) {
   int64_t Register = 0;
   int64_t Offset = 0;
 
@@ -4179,7 +3962,7 @@
 
 /// parseDirectiveCFIRelOffset
 /// ::= .cfi_rel_offset register, offset
-bool AsmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveCFIRelOffset(SMLoc DirectiveLoc) {
   int64_t Register = 0, Offset = 0;
 
   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc) ||
@@ -4217,7 +4000,7 @@
 /// IsPersonality true for cfi_personality, false for cfi_lsda
 /// ::= .cfi_personality encoding, [symbol_name]
 /// ::= .cfi_lsda encoding, [symbol_name]
-bool AsmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
+bool MasmParser::parseDirectiveCFIPersonalityOrLsda(bool IsPersonality) {
   int64_t Encoding = 0;
   if (parseAbsoluteExpression(Encoding))
     return true;
@@ -4241,21 +4024,21 @@
 
 /// parseDirectiveCFIRememberState
 /// ::= .cfi_remember_state
-bool AsmParser::parseDirectiveCFIRememberState() {
+bool MasmParser::parseDirectiveCFIRememberState() {
   getStreamer().EmitCFIRememberState();
   return false;
 }
 
 /// parseDirectiveCFIRestoreState
 /// ::= .cfi_remember_state
-bool AsmParser::parseDirectiveCFIRestoreState() {
+bool MasmParser::parseDirectiveCFIRestoreState() {
   getStreamer().EmitCFIRestoreState();
   return false;
 }
 
 /// parseDirectiveCFISameValue
 /// ::= .cfi_same_value register
-bool AsmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveCFISameValue(SMLoc DirectiveLoc) {
   int64_t Register = 0;
 
   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
@@ -4267,7 +4050,7 @@
 
 /// parseDirectiveCFIRestore
 /// ::= .cfi_restore register
-bool AsmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveCFIRestore(SMLoc DirectiveLoc) {
   int64_t Register = 0;
   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
     return true;
@@ -4278,7 +4061,7 @@
 
 /// parseDirectiveCFIEscape
 /// ::= .cfi_escape expression[,...]
-bool AsmParser::parseDirectiveCFIEscape() {
+bool MasmParser::parseDirectiveCFIEscape() {
   std::string Values;
   int64_t CurrValue;
   if (parseAbsoluteExpression(CurrValue))
@@ -4301,7 +4084,7 @@
 
 /// parseDirectiveCFIReturnColumn
 /// ::= .cfi_return_column register
-bool AsmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveCFIReturnColumn(SMLoc DirectiveLoc) {
   int64_t Register = 0;
   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
     return true;
@@ -4311,7 +4094,7 @@
 
 /// parseDirectiveCFISignalFrame
 /// ::= .cfi_signal_frame
-bool AsmParser::parseDirectiveCFISignalFrame() {
+bool MasmParser::parseDirectiveCFISignalFrame() {
   if (parseToken(AsmToken::EndOfStatement,
                  "unexpected token in '.cfi_signal_frame'"))
     return true;
@@ -4322,7 +4105,7 @@
 
 /// parseDirectiveCFIUndefined
 /// ::= .cfi_undefined register
-bool AsmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveCFIUndefined(SMLoc DirectiveLoc) {
   int64_t Register = 0;
 
   if (parseRegisterOrRegisterNumber(Register, DirectiveLoc))
@@ -4335,7 +4118,7 @@
 /// parseDirectiveAltmacro
 /// ::= .altmacro
 /// ::= .noaltmacro
-bool AsmParser::parseDirectiveAltmacro(StringRef Directive) {
+bool MasmParser::parseDirectiveAltmacro(StringRef Directive) {
   if (getLexer().isNot(AsmToken::EndOfStatement))
     return TokError("unexpected token in '" + Directive + "' directive");
   AltMacroMode = (Directive == ".altmacro");
@@ -4345,7 +4128,7 @@
 /// parseDirectiveMacrosOnOff
 /// ::= .macros_on
 /// ::= .macros_off
-bool AsmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
+bool MasmParser::parseDirectiveMacrosOnOff(StringRef Directive) {
   if (parseToken(AsmToken::EndOfStatement,
                  "unexpected token in '" + Directive + "' directive"))
     return true;
@@ -4356,7 +4139,7 @@
 
 /// parseDirectiveMacro
 /// ::= .macro name[,] [parameters]
-bool AsmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveMacro(SMLoc DirectiveLoc) {
   StringRef Name;
   if (parseIdentifier(Name))
     return TokError("expected identifier in '.macro' directive");
@@ -4494,9 +4277,9 @@
 /// intended or change the macro to use the named parameters.  It is possible
 /// this warning will trigger when the none of the named parameters are used
 /// and the strings like $1 are infact to simply to be passed trough unchanged.
-void AsmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
-                                 StringRef Body,
-                                 ArrayRef<MCAsmMacroParameter> Parameters) {
+void MasmParser::checkForBadMacro(SMLoc DirectiveLoc, StringRef Name,
+                                  StringRef Body,
+                                  ArrayRef<MCAsmMacroParameter> Parameters) {
   // If this macro is not defined with named parameters the warning we are
   // checking for here doesn't apply.
   unsigned NParameters = Parameters.size();
@@ -4584,7 +4367,7 @@
 
 /// parseDirectiveExitMacro
 /// ::= .exitm
-bool AsmParser::parseDirectiveExitMacro(StringRef Directive) {
+bool MasmParser::parseDirectiveExitMacro(StringRef Directive) {
   if (parseToken(AsmToken::EndOfStatement,
                  "unexpected token in '" + Directive + "' directive"))
     return true;
@@ -4606,7 +4389,7 @@
 /// parseDirectiveEndMacro
 /// ::= .endm
 /// ::= .endmacro
-bool AsmParser::parseDirectiveEndMacro(StringRef Directive) {
+bool MasmParser::parseDirectiveEndMacro(StringRef Directive) {
   if (getLexer().isNot(AsmToken::EndOfStatement))
     return TokError("unexpected token in '" + Directive + "' directive");
 
@@ -4625,7 +4408,7 @@
 
 /// parseDirectivePurgeMacro
 /// ::= .purgem
-bool AsmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectivePurgeMacro(SMLoc DirectiveLoc) {
   StringRef Name;
   SMLoc Loc;
   if (parseTokenLoc(Loc) ||
@@ -4644,275 +4427,76 @@
   return false;
 }
 
-/// parseDirectiveBundleAlignMode
-/// ::= {.bundle_align_mode} expression
-bool AsmParser::parseDirectiveBundleAlignMode() {
-  // Expect a single argument: an expression that evaluates to a constant
-  // in the inclusive range 0-30.
-  SMLoc ExprLoc = getLexer().getLoc();
-  int64_t AlignSizePow2;
-  if (checkForValidSection() || parseAbsoluteExpression(AlignSizePow2) ||
-      parseToken(AsmToken::EndOfStatement, "unexpected token after expression "
-                                           "in '.bundle_align_mode' "
-                                           "directive") ||
-      check(AlignSizePow2 < 0 || AlignSizePow2 > 30, ExprLoc,
-            "invalid bundle alignment size (expected between 0 and 30)"))
-    return true;
-
-  // Because of AlignSizePow2's verified range we can safely truncate it to
-  // unsigned.
-  getStreamer().EmitBundleAlignMode(static_cast<unsigned>(AlignSizePow2));
-  return false;
-}
-
-/// parseDirectiveBundleLock
-/// ::= {.bundle_lock} [align_to_end]
-bool AsmParser::parseDirectiveBundleLock() {
-  if (checkForValidSection())
-    return true;
-  bool AlignToEnd = false;
-
-  StringRef Option;
-  SMLoc Loc = getTok().getLoc();
-  const char *kInvalidOptionError =
-      "invalid option for '.bundle_lock' directive";
-
-  if (!parseOptionalToken(AsmToken::EndOfStatement)) {
-    if (check(parseIdentifier(Option), Loc, kInvalidOptionError) ||
-        check(Option != "align_to_end", Loc, kInvalidOptionError) ||
-        parseToken(AsmToken::EndOfStatement,
-                   "unexpected token after '.bundle_lock' directive option"))
-      return true;
-    AlignToEnd = true;
-  }
+/// parseDirectiveSymbolAttribute
+///  ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
+bool MasmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
+  auto parseOp = [&]() -> bool {
+    StringRef Name;
+    SMLoc Loc = getTok().getLoc();
+    if (parseIdentifier(Name))
+      return Error(Loc, "expected identifier");
+    MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
 
-  getStreamer().EmitBundleLock(AlignToEnd);
-  return false;
-}
+    // Assembler local symbols don't make any sense here. Complain loudly.
+    if (Sym->isTemporary())
+      return Error(Loc, "non-local symbol required");
 
-/// parseDirectiveBundleLock
-/// ::= {.bundle_lock}
-bool AsmParser::parseDirectiveBundleUnlock() {
-  if (checkForValidSection() ||
-      parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '.bundle_unlock' directive"))
-    return true;
+    if (!getStreamer().EmitSymbolAttribute(Sym, Attr))
+      return Error(Loc, "unable to emit symbol attribute");
+    return false;
+  };
 
-  getStreamer().EmitBundleUnlock();
+  if (parseMany(parseOp))
+    return addErrorSuffix(" in directive");
   return false;
 }
 
-/// parseDirectiveSpace
-/// ::= (.skip | .space) expression [ , expression ]
-bool AsmParser::parseDirectiveSpace(StringRef IDVal) {
-  SMLoc NumBytesLoc = Lexer.getLoc();
-  const MCExpr *NumBytes;
-  if (checkForValidSection() || parseExpression(NumBytes))
+/// parseDirectiveComm
+///  ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
+bool MasmParser::parseDirectiveComm(bool IsLocal) {
+  if (checkForValidSection())
     return true;
 
-  int64_t FillExpr = 0;
-  if (parseOptionalToken(AsmToken::Comma))
-    if (parseAbsoluteExpression(FillExpr))
-      return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
-  if (parseToken(AsmToken::EndOfStatement))
-    return addErrorSuffix("in '" + Twine(IDVal) + "' directive");
+  SMLoc IDLoc = getLexer().getLoc();
+  StringRef Name;
+  if (parseIdentifier(Name))
+    return TokError("expected identifier in directive");
 
-  // FIXME: Sometimes the fill expr is 'nop' if it isn't supplied, instead of 0.
-  getStreamer().emitFill(*NumBytes, FillExpr, NumBytesLoc);
+  // Handle the identifier as the key symbol.
+  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
 
-  return false;
-}
+  if (getLexer().isNot(AsmToken::Comma))
+    return TokError("unexpected token in directive");
+  Lex();
 
-/// parseDirectiveDCB
-/// ::= .dcb.{b, l, w} expression, expression
-bool AsmParser::parseDirectiveDCB(StringRef IDVal, unsigned Size) {
-  SMLoc NumValuesLoc = Lexer.getLoc();
-  int64_t NumValues;
-  if (checkForValidSection() || parseAbsoluteExpression(NumValues))
+  int64_t Size;
+  SMLoc SizeLoc = getLexer().getLoc();
+  if (parseAbsoluteExpression(Size))
     return true;
 
-  if (NumValues < 0) {
-    Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
-    return false;
-  }
-
-  if (parseToken(AsmToken::Comma,
-                 "unexpected token in '" + Twine(IDVal) + "' directive"))
-    return true;
+  int64_t Pow2Alignment = 0;
+  SMLoc Pow2AlignmentLoc;
+  if (getLexer().is(AsmToken::Comma)) {
+    Lex();
+    Pow2AlignmentLoc = getLexer().getLoc();
+    if (parseAbsoluteExpression(Pow2Alignment))
+      return true;
 
-  const MCExpr *Value;
-  SMLoc ExprLoc = getLexer().getLoc();
-  if (parseExpression(Value))
-    return true;
+    LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
+    if (IsLocal && LCOMM == LCOMM::NoAlignment)
+      return Error(Pow2AlignmentLoc, "alignment not supported on this target");
 
-  // Special case constant expressions to match code generator.
-  if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Value)) {
-    assert(Size <= 8 && "Invalid size");
-    uint64_t IntValue = MCE->getValue();
-    if (!isUIntN(8 * Size, IntValue) && !isIntN(8 * Size, IntValue))
-      return Error(ExprLoc, "literal value out of range for directive");
-    for (uint64_t i = 0, e = NumValues; i != e; ++i)
-      getStreamer().EmitIntValue(IntValue, Size);
-  } else {
-    for (uint64_t i = 0, e = NumValues; i != e; ++i)
-      getStreamer().EmitValue(Value, Size, ExprLoc);
+    // If this target takes alignments in bytes (not log) validate and convert.
+    if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
+        (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
+      if (!isPowerOf2_64(Pow2Alignment))
+        return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
+      Pow2Alignment = Log2_64(Pow2Alignment);
+    }
   }
 
   if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '" + Twine(IDVal) + "' directive"))
-    return true;
-
-  return false;
-}
-
-/// parseDirectiveRealDCB
-/// ::= .dcb.{d, s} expression, expression
-bool AsmParser::parseDirectiveRealDCB(StringRef IDVal, const fltSemantics &Semantics) {
-  SMLoc NumValuesLoc = Lexer.getLoc();
-  int64_t NumValues;
-  if (checkForValidSection() || parseAbsoluteExpression(NumValues))
-    return true;
-
-  if (NumValues < 0) {
-    Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
-    return false;
-  }
-
-  if (parseToken(AsmToken::Comma,
-                 "unexpected token in '" + Twine(IDVal) + "' directive"))
-    return true;
-
-  APInt AsInt;
-  if (parseRealValue(Semantics, AsInt))
-    return true;
-
-  if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '" + Twine(IDVal) + "' directive"))
-    return true;
-
-  for (uint64_t i = 0, e = NumValues; i != e; ++i)
-    getStreamer().EmitIntValue(AsInt.getLimitedValue(),
-                               AsInt.getBitWidth() / 8);
-
-  return false;
-}
-
-/// parseDirectiveDS
-/// ::= .ds.{b, d, l, p, s, w, x} expression
-bool AsmParser::parseDirectiveDS(StringRef IDVal, unsigned Size) {
-  SMLoc NumValuesLoc = Lexer.getLoc();
-  int64_t NumValues;
-  if (checkForValidSection() || parseAbsoluteExpression(NumValues))
-    return true;
-
-  if (NumValues < 0) {
-    Warning(NumValuesLoc, "'" + Twine(IDVal) + "' directive with negative repeat count has no effect");
-    return false;
-  }
-
-  if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '" + Twine(IDVal) + "' directive"))
-    return true;
-
-  for (uint64_t i = 0, e = NumValues; i != e; ++i)
-    getStreamer().emitFill(Size, 0);
-
-  return false;
-}
-
-/// parseDirectiveLEB128
-/// ::= (.sleb128 | .uleb128) [ expression (, expression)* ]
-bool AsmParser::parseDirectiveLEB128(bool Signed) {
-  if (checkForValidSection())
-    return true;
-
-  auto parseOp = [&]() -> bool {
-    const MCExpr *Value;
-    if (parseExpression(Value))
-      return true;
-    if (Signed)
-      getStreamer().EmitSLEB128Value(Value);
-    else
-      getStreamer().EmitULEB128Value(Value);
-    return false;
-  };
-
-  if (parseMany(parseOp))
-    return addErrorSuffix(" in directive");
-
-  return false;
-}
-
-/// parseDirectiveSymbolAttribute
-///  ::= { ".globl", ".weak", ... } [ identifier ( , identifier )* ]
-bool AsmParser::parseDirectiveSymbolAttribute(MCSymbolAttr Attr) {
-  auto parseOp = [&]() -> bool {
-    StringRef Name;
-    SMLoc Loc = getTok().getLoc();
-    if (parseIdentifier(Name))
-      return Error(Loc, "expected identifier");
-    MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
-    // Assembler local symbols don't make any sense here. Complain loudly.
-    if (Sym->isTemporary())
-      return Error(Loc, "non-local symbol required");
-
-    if (!getStreamer().EmitSymbolAttribute(Sym, Attr))
-      return Error(Loc, "unable to emit symbol attribute");
-    return false;
-  };
-
-  if (parseMany(parseOp))
-    return addErrorSuffix(" in directive");
-  return false;
-}
-
-/// parseDirectiveComm
-///  ::= ( .comm | .lcomm ) identifier , size_expression [ , align_expression ]
-bool AsmParser::parseDirectiveComm(bool IsLocal) {
-  if (checkForValidSection())
-    return true;
-
-  SMLoc IDLoc = getLexer().getLoc();
-  StringRef Name;
-  if (parseIdentifier(Name))
-    return TokError("expected identifier in directive");
-
-  // Handle the identifier as the key symbol.
-  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-
-  if (getLexer().isNot(AsmToken::Comma))
-    return TokError("unexpected token in directive");
-  Lex();
-
-  int64_t Size;
-  SMLoc SizeLoc = getLexer().getLoc();
-  if (parseAbsoluteExpression(Size))
-    return true;
-
-  int64_t Pow2Alignment = 0;
-  SMLoc Pow2AlignmentLoc;
-  if (getLexer().is(AsmToken::Comma)) {
-    Lex();
-    Pow2AlignmentLoc = getLexer().getLoc();
-    if (parseAbsoluteExpression(Pow2Alignment))
-      return true;
-
-    LCOMM::LCOMMType LCOMM = Lexer.getMAI().getLCOMMDirectiveAlignmentType();
-    if (IsLocal && LCOMM == LCOMM::NoAlignment)
-      return Error(Pow2AlignmentLoc, "alignment not supported on this target");
-
-    // If this target takes alignments in bytes (not log) validate and convert.
-    if ((!IsLocal && Lexer.getMAI().getCOMMDirectiveAlignmentIsInBytes()) ||
-        (IsLocal && LCOMM == LCOMM::ByteAlignment)) {
-      if (!isPowerOf2_64(Pow2Alignment))
-        return Error(Pow2AlignmentLoc, "alignment must be a power of 2");
-      Pow2Alignment = Log2_64(Pow2Alignment);
-    }
-  }
-
-  if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '.comm' or '.lcomm' directive"))
+                 "unexpected token in '.comm' or '.lcomm' directive"))
     return true;
 
   // NOTE: a size of zero for a .comm should create a undefined symbol
@@ -4942,38 +4526,38 @@
   return false;
 }
 
-/// parseDirectiveAbort
-///  ::= .abort [... message ...]
-bool AsmParser::parseDirectiveAbort() {
-  // FIXME: Use loc from directive.
-  SMLoc Loc = getLexer().getLoc();
-
-  StringRef Str = parseStringToEndOfStatement();
-  if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '.abort' directive"))
-    return true;
-
-  if (Str.empty())
-    return Error(Loc, ".abort detected. Assembly stopping.");
-  else
-    return Error(Loc, ".abort '" + Str + "' detected. Assembly stopping.");
-  // FIXME: Actually abort assembly here.
-
-  return false;
+/// parseDirectiveComment
+///  ::= comment delimiter [[text]]
+///              [[text]]
+///              [[text]] delimiter [[text]]
+bool MasmParser::parseDirectiveComment(SMLoc DirectiveLoc) {
+  StringRef FirstLine = parseStringToEndOfStatement();
+  size_t DelimiterEnd = FirstLine.find_first_of("\b\t\v\f\r\x1A ");
+  StringRef Delimiter = FirstLine.take_front(DelimiterEnd);
+  if (Delimiter.empty())
+    return Error(DirectiveLoc, "no delimiter in 'comment' directive");
+  do {
+    if (getTok().is(AsmToken::Eof))
+      return Error(DirectiveLoc, "unmatched delimiter in 'comment' directive");
+    Lex();  // eat end of statement
+  } while (!parseStringToEndOfStatement().contains(Delimiter));
+  return parseToken(AsmToken::EndOfStatement,
+                    "unexpected token in 'comment' directive");
 }
 
 /// parseDirectiveInclude
-///  ::= .include "filename"
-bool AsmParser::parseDirectiveInclude() {
+///  ::= include <filename>
+///    | include filename
+bool MasmParser::parseDirectiveInclude() {
   // Allow the strings to have escaped octal character sequence.
   std::string Filename;
   SMLoc IncludeLoc = getTok().getLoc();
 
-  if (check(getTok().isNot(AsmToken::String),
-            "expected string in '.include' directive") ||
-      parseEscapedString(Filename) ||
+  if (!parseAngleBracketString(Filename))
+    Filename = parseStringToEndOfStatement();
+  if (check(!Filename.empty(), "missing filename in 'include' directive") ||
       check(getTok().isNot(AsmToken::EndOfStatement),
-            "unexpected token in '.include' directive") ||
+            "unexpected token in 'include' directive") ||
       // Attempt to switch the lexer to the included file before consuming the
       // end of statement to avoid losing it when we switch.
       check(enterIncludeFile(Filename), IncludeLoc,
@@ -4983,50 +4567,9 @@
   return false;
 }
 
-/// parseDirectiveIncbin
-///  ::= .incbin "filename" [ , skip [ , count ] ]
-bool AsmParser::parseDirectiveIncbin() {
-  // Allow the strings to have escaped octal character sequence.
-  std::string Filename;
-  SMLoc IncbinLoc = getTok().getLoc();
-  if (check(getTok().isNot(AsmToken::String),
-            "expected string in '.incbin' directive") ||
-      parseEscapedString(Filename))
-    return true;
-
-  int64_t Skip = 0;
-  const MCExpr *Count = nullptr;
-  SMLoc SkipLoc, CountLoc;
-  if (parseOptionalToken(AsmToken::Comma)) {
-    // The skip expression can be omitted while specifying the count, e.g:
-    //  .incbin "filename",,4
-    if (getTok().isNot(AsmToken::Comma)) {
-      if (parseTokenLoc(SkipLoc) || parseAbsoluteExpression(Skip))
-        return true;
-    }
-    if (parseOptionalToken(AsmToken::Comma)) {
-      CountLoc = getTok().getLoc();
-      if (parseExpression(Count))
-        return true;
-    }
-  }
-
-  if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '.incbin' directive"))
-    return true;
-
-  if (check(Skip < 0, SkipLoc, "skip is negative"))
-    return true;
-
-  // Attempt to process the included file.
-  if (processIncbinFile(Filename, Skip, Count, CountLoc))
-    return Error(IncbinLoc, "Could not find incbin file '" + Filename + "'");
-  return false;
-}
-
 /// parseDirectiveIf
 /// ::= .if{,eq,ge,gt,le,lt,ne} expression
-bool AsmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
+bool MasmParser::parseDirectiveIf(SMLoc DirectiveLoc, DirectiveKind DirKind) {
   TheCondStack.push_back(TheCondState);
   TheCondState.TheCond = AsmCond::IfCond;
   if (TheCondState.Ignore) {
@@ -5042,23 +4585,10 @@
     default:
       llvm_unreachable("unsupported directive");
     case DK_IF:
-    case DK_IFNE:
       break;
-    case DK_IFEQ:
+    case DK_IFE:
       ExprValue = ExprValue == 0;
       break;
-    case DK_IFGE:
-      ExprValue = ExprValue >= 0;
-      break;
-    case DK_IFGT:
-      ExprValue = ExprValue > 0;
-      break;
-    case DK_IFLE:
-      ExprValue = ExprValue <= 0;
-      break;
-    case DK_IFLT:
-      ExprValue = ExprValue < 0;
-      break;
     }
 
     TheCondState.CondMet = ExprValue;
@@ -5070,17 +4600,19 @@
 
 /// parseDirectiveIfb
 /// ::= .ifb string
-bool AsmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+bool MasmParser::parseDirectiveIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
   TheCondStack.push_back(TheCondState);
   TheCondState.TheCond = AsmCond::IfCond;
 
   if (TheCondState.Ignore) {
     eatToEndOfStatement();
   } else {
-    StringRef Str = parseStringToEndOfStatement();
+    std::string Str;
+    if (parseTextItem(Str))
+      return TokError("expected string parameter for 'ifb' directive");
 
     if (parseToken(AsmToken::EndOfStatement,
-                   "unexpected token in '.ifb' directive"))
+                   "unexpected token in 'ifb' directive"))
       return true;
 
     TheCondState.CondMet = ExpectBlank == Str.empty();
@@ -5090,92 +4622,73 @@
   return false;
 }
 
-/// parseDirectiveIfc
-/// ::= .ifc string1, string2
-/// ::= .ifnc string1, string2
-bool AsmParser::parseDirectiveIfc(SMLoc DirectiveLoc, bool ExpectEqual) {
-  TheCondStack.push_back(TheCondState);
-  TheCondState.TheCond = AsmCond::IfCond;
-
-  if (TheCondState.Ignore) {
-    eatToEndOfStatement();
-  } else {
-    StringRef Str1 = parseStringToComma();
-
-    if (parseToken(AsmToken::Comma, "unexpected token in '.ifc' directive"))
-      return true;
-
-    StringRef Str2 = parseStringToEndOfStatement();
-
-    if (parseToken(AsmToken::EndOfStatement,
-                   "unexpected token in '.ifc' directive"))
-      return true;
-
-    TheCondState.CondMet = ExpectEqual == (Str1.trim() == Str2.trim());
-    TheCondState.Ignore = !TheCondState.CondMet;
-  }
-
-  return false;
-}
+/// parseDirectiveIfidn
+///   ::= ifidn string1, string2
+bool MasmParser::parseDirectiveIfidn(SMLoc DirectiveLoc, bool ExpectEqual, bool CaseInsensitive) {
+  std::string String1, String2;
 
-/// parseDirectiveIfeqs
-///   ::= .ifeqs string1, string2
-bool AsmParser::parseDirectiveIfeqs(SMLoc DirectiveLoc, bool ExpectEqual) {
-  if (Lexer.isNot(AsmToken::String)) {
+  if (parseTextItem(String1)) {
     if (ExpectEqual)
-      return TokError("expected string parameter for '.ifeqs' directive");
-    return TokError("expected string parameter for '.ifnes' directive");
+      return TokError("expected string parameter for 'ifidn' directive");
+    return TokError("expected string parameter for 'ifdif' directive");
   }
 
-  StringRef String1 = getTok().getStringContents();
-  Lex();
-
   if (Lexer.isNot(AsmToken::Comma)) {
     if (ExpectEqual)
       return TokError(
-          "expected comma after first string for '.ifeqs' directive");
-    return TokError("expected comma after first string for '.ifnes' directive");
+          "expected comma after first string for 'ifidn' directive");
+    return TokError("expected comma after first string for 'ifdif' directive");
   }
-
   Lex();
 
-  if (Lexer.isNot(AsmToken::String)) {
+  if (parseTextItem(String2)) {
     if (ExpectEqual)
-      return TokError("expected string parameter for '.ifeqs' directive");
-    return TokError("expected string parameter for '.ifnes' directive");
+      return TokError("expected string parameter for 'ifidn' directive");
+    return TokError("expected string parameter for 'ifdif' directive");
   }
 
-  StringRef String2 = getTok().getStringContents();
-  Lex();
-
   TheCondStack.push_back(TheCondState);
   TheCondState.TheCond = AsmCond::IfCond;
-  TheCondState.CondMet = ExpectEqual == (String1 == String2);
+  if (CaseInsensitive)
+    TheCondState.CondMet =
+        ExpectEqual == (StringRef(String1).equals_lower(String2));
+  else
+    TheCondState.CondMet = ExpectEqual == (String1 == String2);
   TheCondState.Ignore = !TheCondState.CondMet;
 
   return false;
 }
 
 /// parseDirectiveIfdef
-/// ::= .ifdef symbol
-bool AsmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
-  StringRef Name;
+/// ::= ifdef symbol
+///   | ifdef variable
+bool MasmParser::parseDirectiveIfdef(SMLoc DirectiveLoc, bool expect_defined) {
   TheCondStack.push_back(TheCondState);
   TheCondState.TheCond = AsmCond::IfCond;
 
   if (TheCondState.Ignore) {
     eatToEndOfStatement();
   } else {
-    if (check(parseIdentifier(Name), "expected identifier after '.ifdef'") ||
-        parseToken(AsmToken::EndOfStatement, "unexpected token in '.ifdef'"))
-      return true;
+    bool is_defined = false;
+    unsigned RegNo;
+    SMLoc StartLoc, EndLoc;
+    is_defined = (getTargetParser().tryParseRegister(
+                      RegNo, StartLoc, EndLoc) == MatchOperand_Success);
+    if (!is_defined) {
+      StringRef Name;
+      if (check(parseIdentifier(Name), "expected identifier after 'ifdef'") ||
+          parseToken(AsmToken::EndOfStatement, "unexpected token in 'ifdef'"))
+        return true;
 
-    MCSymbol *Sym = getContext().lookupSymbol(Name);
+      if (Variables.find(Name) != Variables.end()) {
+        is_defined = true;
+      } else {
+        MCSymbol *Sym = getContext().lookupSymbol(Name);
+        is_defined = (Sym && !Sym->isUndefined(false));
+      }
+    }
 
-    if (expect_defined)
-      TheCondState.CondMet = (Sym && !Sym->isUndefined(false));
-    else
-      TheCondState.CondMet = (!Sym || Sym->isUndefined(false));
+    TheCondState.CondMet = (is_defined == expect_defined);
     TheCondState.Ignore = !TheCondState.CondMet;
   }
 
@@ -5183,8 +4696,9 @@
 }
 
 /// parseDirectiveElseIf
-/// ::= .elseif expression
-bool AsmParser::parseDirectiveElseIf(SMLoc DirectiveLoc) {
+/// ::= elseif expression
+bool MasmParser::parseDirectiveElseIf(SMLoc DirectiveLoc,
+                                      DirectiveKind DirKind) {
   if (TheCondState.TheCond != AsmCond::IfCond &&
       TheCondState.TheCond != AsmCond::ElseIfCond)
     return Error(DirectiveLoc, "Encountered a .elseif that doesn't follow an"
@@ -5206,6 +4720,16 @@
                    "unexpected token in '.elseif' directive"))
       return true;
 
+    switch (DirKind) {
+    default:
+      llvm_unreachable("unsupported directive");
+    case DK_ELSEIF:
+      break;
+    case DK_ELSEIFE:
+      ExprValue = ExprValue == 0;
+      break;
+    }
+
     TheCondState.CondMet = ExprValue;
     TheCondState.Ignore = !TheCondState.CondMet;
   }
@@ -5213,17 +4737,145 @@
   return false;
 }
 
+/// parseDirectiveElseIfb
+/// ::= elseifb expression
+bool MasmParser::parseDirectiveElseIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+  if (TheCondState.TheCond != AsmCond::IfCond &&
+      TheCondState.TheCond != AsmCond::ElseIfCond)
+    return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
+                               " if or an elseif");
+  TheCondState.TheCond = AsmCond::ElseIfCond;
+
+  bool LastIgnoreState = false;
+  if (!TheCondStack.empty())
+    LastIgnoreState = TheCondStack.back().Ignore;
+  if (LastIgnoreState || TheCondState.CondMet) {
+    TheCondState.Ignore = true;
+    eatToEndOfStatement();
+  } else {
+    std::string Str;
+    if (parseTextItem(Str))
+      return TokError("expected string parameter for 'elseifb' directive");
+
+    if (parseToken(AsmToken::EndOfStatement,
+                   "unexpected token in 'elseifb' directive"))
+      return true;
+
+    TheCondState.CondMet = ExpectBlank == Str.empty();
+    TheCondState.Ignore = !TheCondState.CondMet;
+  }
+
+  return false;
+}
+
+/// parseDirectiveElseIfdef
+/// ::= elseifdef symbol
+///   | elseifdef variable
+bool MasmParser::parseDirectiveElseIfdef(SMLoc DirectiveLoc,
+                                         bool expect_defined) {
+  if (TheCondState.TheCond != AsmCond::IfCond &&
+      TheCondState.TheCond != AsmCond::ElseIfCond)
+    return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
+                               " if or an elseif");
+  TheCondState.TheCond = AsmCond::ElseIfCond;
+
+  bool LastIgnoreState = false;
+  if (!TheCondStack.empty())
+    LastIgnoreState = TheCondStack.back().Ignore;
+  if (LastIgnoreState || TheCondState.CondMet) {
+    TheCondState.Ignore = true;
+    eatToEndOfStatement();
+  } else {
+    bool is_defined = false;
+    unsigned RegNo;
+    SMLoc StartLoc, EndLoc;
+    is_defined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
+                  MatchOperand_Success);
+    if (!is_defined) {
+      StringRef Name;
+      if (check(parseIdentifier(Name),
+                "expected identifier after 'elseifdef'") ||
+          parseToken(AsmToken::EndOfStatement,
+                     "unexpected token in 'elseifdef'"))
+        return true;
+
+      if (Variables.find(Name) != Variables.end()) {
+        is_defined = true;
+      } else {
+        MCSymbol *Sym = getContext().lookupSymbol(Name);
+        is_defined = (Sym && !Sym->isUndefined(false));
+      }
+    }
+
+    TheCondState.CondMet = (is_defined == expect_defined);
+    TheCondState.Ignore = !TheCondState.CondMet;
+  }
+
+  return false;
+}
+
+/// parseDirectiveElseIfidn
+/// ::= elseifidn string1, string2
+bool MasmParser::parseDirectiveElseIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+                                         bool CaseInsensitive) {
+  if (TheCondState.TheCond != AsmCond::IfCond &&
+      TheCondState.TheCond != AsmCond::ElseIfCond)
+    return Error(DirectiveLoc, "Encountered an elseif that doesn't follow an"
+                               " if or an elseif");
+  TheCondState.TheCond = AsmCond::ElseIfCond;
+
+  bool LastIgnoreState = false;
+  if (!TheCondStack.empty())
+    LastIgnoreState = TheCondStack.back().Ignore;
+  if (LastIgnoreState || TheCondState.CondMet) {
+    TheCondState.Ignore = true;
+    eatToEndOfStatement();
+  } else {
+    std::string String1, String2;
+
+    if (parseTextItem(String1)) {
+      if (ExpectEqual)
+        return TokError("expected string parameter for 'elseifidn' directive");
+      return TokError("expected string parameter for 'elseifdif' directive");
+    }
+
+    if (Lexer.isNot(AsmToken::Comma)) {
+      if (ExpectEqual)
+        return TokError(
+            "expected comma after first string for 'elseifidn' directive");
+      return TokError(
+          "expected comma after first string for 'elseifdif' directive");
+    }
+    Lex();
+
+    if (parseTextItem(String2)) {
+      if (ExpectEqual)
+        return TokError("expected string parameter for 'elseifidn' directive");
+      return TokError("expected string parameter for 'elseifdif' directive");
+    }
+
+    if (CaseInsensitive)
+      TheCondState.CondMet =
+          ExpectEqual == (StringRef(String1).equals_lower(String2));
+    else
+      TheCondState.CondMet = ExpectEqual == (String1 == String2);
+    TheCondState.Ignore = !TheCondState.CondMet;
+  }
+
+  return false;
+}
+
 /// parseDirectiveElse
-/// ::= .else
-bool AsmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
+/// ::= else
+bool MasmParser::parseDirectiveElse(SMLoc DirectiveLoc) {
   if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '.else' directive"))
+                 "unexpected token in 'else' directive"))
     return true;
 
   if (TheCondState.TheCond != AsmCond::IfCond &&
       TheCondState.TheCond != AsmCond::ElseIfCond)
-    return Error(DirectiveLoc, "Encountered a .else that doesn't follow "
-                               " an .if or an .elseif");
+    return Error(DirectiveLoc, "Encountered an else that doesn't follow an if"
+                               " or an elseif");
   TheCondState.TheCond = AsmCond::ElseCond;
   bool LastIgnoreState = false;
   if (!TheCondStack.empty())
@@ -5237,10 +4889,10 @@
 }
 
 /// parseDirectiveEnd
-/// ::= .end
-bool AsmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
+/// ::= end
+bool MasmParser::parseDirectiveEnd(SMLoc DirectiveLoc) {
   if (parseToken(AsmToken::EndOfStatement,
-                 "unexpected token in '.end' directive"))
+                 "unexpected token in 'end' directive"))
     return true;
 
   while (Lexer.isNot(AsmToken::Eof))
@@ -5250,9 +4902,8 @@
 }
 
 /// parseDirectiveError
-///   ::= .err
-///   ::= .error [string]
-bool AsmParser::parseDirectiveError(SMLoc L, bool WithMessage) {
+///   ::= .err [message]
+bool MasmParser::parseDirectiveError(SMLoc DirectiveLoc) {
   if (!TheCondStack.empty()) {
     if (TheCondStack.back().Ignore) {
       eatToEndOfStatement();
@@ -5260,24 +4911,87 @@
     }
   }
 
-  if (!WithMessage)
-    return Error(L, ".err encountered");
+  std::string Message = ".err directive invoked in source file";
+  if (Lexer.isNot(AsmToken::EndOfStatement))
+    Message = parseStringToEndOfStatement();
+  Lex();
+
+  return Error(DirectiveLoc, Message);
+}
 
-  StringRef Message = ".error directive invoked in source file";
+/// parseDirectiveErrorIfb
+///   ::= .errb textitem[, message]
+bool MasmParser::parseDirectiveErrorIfb(SMLoc DirectiveLoc, bool ExpectBlank) {
+  if (!TheCondStack.empty()) {
+    if (TheCondStack.back().Ignore) {
+      eatToEndOfStatement();
+      return false;
+    }
+  }
+
+  std::string Text;
+  if (parseTextItem(Text))
+    return Error(getTok().getLoc(), "missing text item in '.errb' directive");
+
+  std::string Message = ".errb directive invoked in source file";
   if (Lexer.isNot(AsmToken::EndOfStatement)) {
-    if (Lexer.isNot(AsmToken::String))
-      return TokError(".error argument must be a string");
+    if (parseToken(AsmToken::Comma))
+      return addErrorSuffix(" in '.errb' directive");
+    Message = parseStringToEndOfStatement();
+  }
+  Lex();
 
-    Message = getTok().getStringContents();
-    Lex();
+  if (Text.empty() == ExpectBlank)
+    return Error(DirectiveLoc, Message);
+  return false;
+}
+
+/// parseDirectiveErrorIfdef
+///   ::= .errdef name[, message]
+bool MasmParser::parseDirectiveErrorIfdef(SMLoc DirectiveLoc,
+                                          bool ExpectDefined) {
+  if (!TheCondStack.empty()) {
+    if (TheCondStack.back().Ignore) {
+      eatToEndOfStatement();
+      return false;
+    }
+  }
+
+  bool IsDefined = false;
+  unsigned RegNo;
+  SMLoc StartLoc, EndLoc;
+  IsDefined = (getTargetParser().tryParseRegister(RegNo, StartLoc, EndLoc) ==
+               MatchOperand_Success);
+  if (!IsDefined) {
+    StringRef Name;
+    if (check(parseIdentifier(Name), "expected identifier after '.errdef'"))
+      return true;
+
+    if (Variables.find(Name) != Variables.end()) {
+      IsDefined = true;
+    } else {
+      MCSymbol *Sym = getContext().lookupSymbol(Name);
+      IsDefined = (Sym && !Sym->isUndefined(false));
+    }
+  }
+
+  std::string Message = ".errdef directive invoked in source file";
+  if (Lexer.isNot(AsmToken::EndOfStatement)) {
+    if (parseToken(AsmToken::Comma))
+      return addErrorSuffix(" in '.errdef' directive");
+    Message = parseStringToEndOfStatement();
   }
+  Lex();
 
-  return Error(L, Message);
+  if (IsDefined == ExpectDefined)
+    return Error(DirectiveLoc, Message);
+  return false;
 }
 
-/// parseDirectiveWarning
-///   ::= .warning [string]
-bool AsmParser::parseDirectiveWarning(SMLoc L) {
+/// parseDirectiveErrorIfidn
+///   ::= .erridn textitem1, textitem2[, message]
+bool MasmParser::parseDirectiveErrorIfidn(SMLoc DirectiveLoc, bool ExpectEqual,
+                                          bool CaseInsensitive) {
   if (!TheCondStack.empty()) {
     if (TheCondStack.back().Ignore) {
       eatToEndOfStatement();
@@ -5285,25 +4999,85 @@
     }
   }
 
-  StringRef Message = ".warning directive invoked in source file";
+  std::string String1, String2;
 
-  if (!parseOptionalToken(AsmToken::EndOfStatement)) {
-    if (Lexer.isNot(AsmToken::String))
-      return TokError(".warning argument must be a string");
+  if (parseTextItem(String1)) {
+    if (ExpectEqual)
+      return TokError("expected string parameter for '.erridn' directive");
+    return TokError("expected string parameter for '.errdif' directive");
+  }
 
-    Message = getTok().getStringContents();
-    Lex();
-    if (parseToken(AsmToken::EndOfStatement,
-                   "expected end of statement in '.warning' directive"))
-      return true;
+  if (Lexer.isNot(AsmToken::Comma)) {
+    if (ExpectEqual)
+      return TokError(
+          "expected comma after first string for '.erridn' directive");
+    return TokError(
+        "expected comma after first string for '.errdif' directive");
   }
+  Lex();
+
+  if (parseTextItem(String2)) {
+    if (ExpectEqual)
+      return TokError("expected string parameter for '.erridn' directive");
+    return TokError("expected string parameter for '.errdif' directive");
+  }
+
+  std::string Message;
+  if (ExpectEqual)
+    Message = ".erridn directive invoked in source file";
+  else
+    Message = ".errdif directive invoked in source file";
+  if (Lexer.isNot(AsmToken::EndOfStatement)) {
+    if (parseToken(AsmToken::Comma))
+      return addErrorSuffix(" in '.erridn' directive");
+    Message = parseStringToEndOfStatement();
+  }
+  Lex();
+
+  if (CaseInsensitive)
+    TheCondState.CondMet =
+        ExpectEqual == (StringRef(String1).equals_lower(String2));
+  else
+    TheCondState.CondMet = ExpectEqual == (String1 == String2);
+  TheCondState.Ignore = !TheCondState.CondMet;
 
-  return Warning(L, Message);
+  if ((CaseInsensitive &&
+       ExpectEqual == StringRef(String1).equals_lower(String2)) ||
+      (ExpectEqual == (String1 == String2)))
+    return Error(DirectiveLoc, Message);
+  return false;
+}
+
+/// parseDirectiveErrorIfe
+///   ::= .erre expression[, message]
+bool MasmParser::parseDirectiveErrorIfe(SMLoc DirectiveLoc, bool ExpectZero) {
+  if (!TheCondStack.empty()) {
+    if (TheCondStack.back().Ignore) {
+      eatToEndOfStatement();
+      return false;
+    }
+  }
+
+  int64_t ExprValue;
+  if (parseAbsoluteExpression(ExprValue))
+    return addErrorSuffix(" in '.erre' directive");
+
+  std::string Message = ".erre directive invoked in source file";
+  if (Lexer.isNot(AsmToken::EndOfStatement)) {
+    if (parseToken(AsmToken::Comma))
+      return addErrorSuffix(" in '.erre' directive");
+    Message = parseStringToEndOfStatement();
+  }
+  Lex();
+
+  if ((ExprValue == 0) == ExpectZero)
+    return Error(DirectiveLoc, Message);
+  return false;
 }
 
 /// parseDirectiveEndIf
 /// ::= .endif
-bool AsmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveEndIf(SMLoc DirectiveLoc) {
   if (parseToken(AsmToken::EndOfStatement,
                  "unexpected token in '.endif' directive"))
     return true;
@@ -5319,169 +5093,113 @@
   return false;
 }
 
-void AsmParser::initializeDirectiveKindMap() {
-  DirectiveKindMap[".set"] = DK_SET;
-  DirectiveKindMap[".equ"] = DK_EQU;
-  DirectiveKindMap[".equiv"] = DK_EQUIV;
-  DirectiveKindMap[".ascii"] = DK_ASCII;
-  DirectiveKindMap[".asciz"] = DK_ASCIZ;
-  DirectiveKindMap[".string"] = DK_STRING;
-  DirectiveKindMap[".byte"] = DK_BYTE;
-  DirectiveKindMap[".short"] = DK_SHORT;
-  DirectiveKindMap[".value"] = DK_VALUE;
-  DirectiveKindMap[".2byte"] = DK_2BYTE;
-  DirectiveKindMap[".long"] = DK_LONG;
-  DirectiveKindMap[".int"] = DK_INT;
-  DirectiveKindMap[".4byte"] = DK_4BYTE;
-  DirectiveKindMap[".quad"] = DK_QUAD;
-  DirectiveKindMap[".8byte"] = DK_8BYTE;
-  DirectiveKindMap[".octa"] = DK_OCTA;
-  DirectiveKindMap[".single"] = DK_SINGLE;
-  DirectiveKindMap[".float"] = DK_FLOAT;
-  DirectiveKindMap[".double"] = DK_DOUBLE;
-  DirectiveKindMap[".align"] = DK_ALIGN;
-  DirectiveKindMap[".align32"] = DK_ALIGN32;
-  DirectiveKindMap[".balign"] = DK_BALIGN;
-  DirectiveKindMap[".balignw"] = DK_BALIGNW;
-  DirectiveKindMap[".balignl"] = DK_BALIGNL;
-  DirectiveKindMap[".p2align"] = DK_P2ALIGN;
-  DirectiveKindMap[".p2alignw"] = DK_P2ALIGNW;
-  DirectiveKindMap[".p2alignl"] = DK_P2ALIGNL;
-  DirectiveKindMap[".org"] = DK_ORG;
-  DirectiveKindMap[".fill"] = DK_FILL;
-  DirectiveKindMap[".zero"] = DK_ZERO;
-  DirectiveKindMap[".extern"] = DK_EXTERN;
-  DirectiveKindMap[".globl"] = DK_GLOBL;
-  DirectiveKindMap[".global"] = DK_GLOBAL;
-  DirectiveKindMap[".lazy_reference"] = DK_LAZY_REFERENCE;
-  DirectiveKindMap[".no_dead_strip"] = DK_NO_DEAD_STRIP;
-  DirectiveKindMap[".symbol_resolver"] = DK_SYMBOL_RESOLVER;
-  DirectiveKindMap[".private_extern"] = DK_PRIVATE_EXTERN;
-  DirectiveKindMap[".reference"] = DK_REFERENCE;
-  DirectiveKindMap[".weak_definition"] = DK_WEAK_DEFINITION;
-  DirectiveKindMap[".weak_reference"] = DK_WEAK_REFERENCE;
-  DirectiveKindMap[".weak_def_can_be_hidden"] = DK_WEAK_DEF_CAN_BE_HIDDEN;
-  DirectiveKindMap[".cold"] = DK_COLD;
-  DirectiveKindMap[".comm"] = DK_COMM;
-  DirectiveKindMap[".common"] = DK_COMMON;
-  DirectiveKindMap[".lcomm"] = DK_LCOMM;
-  DirectiveKindMap[".abort"] = DK_ABORT;
-  DirectiveKindMap[".include"] = DK_INCLUDE;
-  DirectiveKindMap[".incbin"] = DK_INCBIN;
-  DirectiveKindMap[".code16"] = DK_CODE16;
-  DirectiveKindMap[".code16gcc"] = DK_CODE16GCC;
-  DirectiveKindMap[".rept"] = DK_REPT;
-  DirectiveKindMap[".rep"] = DK_REPT;
-  DirectiveKindMap[".irp"] = DK_IRP;
-  DirectiveKindMap[".irpc"] = DK_IRPC;
-  DirectiveKindMap[".endr"] = DK_ENDR;
-  DirectiveKindMap[".bundle_align_mode"] = DK_BUNDLE_ALIGN_MODE;
-  DirectiveKindMap[".bundle_lock"] = DK_BUNDLE_LOCK;
-  DirectiveKindMap[".bundle_unlock"] = DK_BUNDLE_UNLOCK;
-  DirectiveKindMap[".if"] = DK_IF;
-  DirectiveKindMap[".ifeq"] = DK_IFEQ;
-  DirectiveKindMap[".ifge"] = DK_IFGE;
-  DirectiveKindMap[".ifgt"] = DK_IFGT;
-  DirectiveKindMap[".ifle"] = DK_IFLE;
-  DirectiveKindMap[".iflt"] = DK_IFLT;
-  DirectiveKindMap[".ifne"] = DK_IFNE;
-  DirectiveKindMap[".ifb"] = DK_IFB;
-  DirectiveKindMap[".ifnb"] = DK_IFNB;
-  DirectiveKindMap[".ifc"] = DK_IFC;
-  DirectiveKindMap[".ifeqs"] = DK_IFEQS;
-  DirectiveKindMap[".ifnc"] = DK_IFNC;
-  DirectiveKindMap[".ifnes"] = DK_IFNES;
-  DirectiveKindMap[".ifdef"] = DK_IFDEF;
-  DirectiveKindMap[".ifndef"] = DK_IFNDEF;
-  DirectiveKindMap[".ifnotdef"] = DK_IFNOTDEF;
-  DirectiveKindMap[".elseif"] = DK_ELSEIF;
-  DirectiveKindMap[".else"] = DK_ELSE;
-  DirectiveKindMap[".end"] = DK_END;
-  DirectiveKindMap[".endif"] = DK_ENDIF;
-  DirectiveKindMap[".skip"] = DK_SKIP;
-  DirectiveKindMap[".space"] = DK_SPACE;
-  DirectiveKindMap[".file"] = DK_FILE;
-  DirectiveKindMap[".line"] = DK_LINE;
-  DirectiveKindMap[".loc"] = DK_LOC;
-  DirectiveKindMap[".stabs"] = DK_STABS;
-  DirectiveKindMap[".cv_file"] = DK_CV_FILE;
-  DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
-  DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
-  DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
-  DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
-  DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
-  DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
-  DirectiveKindMap[".cv_string"] = DK_CV_STRING;
-  DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
-  DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
-  DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
-  DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
-  DirectiveKindMap[".sleb128"] = DK_SLEB128;
-  DirectiveKindMap[".uleb128"] = DK_ULEB128;
-  DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
-  DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
-  DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
-  DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
-  DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
-  DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
-  DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
-  DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
-  DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
-  DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
-  DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
-  DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
-  DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
-  DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
-  DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
-  DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
-  DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
-  DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
-  DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
-  DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
-  DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
-  DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
-  DirectiveKindMap[".macros_on"] = DK_MACROS_ON;
-  DirectiveKindMap[".macros_off"] = DK_MACROS_OFF;
-  DirectiveKindMap[".macro"] = DK_MACRO;
-  DirectiveKindMap[".exitm"] = DK_EXITM;
-  DirectiveKindMap[".endm"] = DK_ENDM;
-  DirectiveKindMap[".endmacro"] = DK_ENDMACRO;
-  DirectiveKindMap[".purgem"] = DK_PURGEM;
+void MasmParser::initializeDirectiveKindMap() {
+  DirectiveKindMap["="] = DK_ASSIGN;
+  DirectiveKindMap["equ"] = DK_EQU;
+  DirectiveKindMap["textequ"] = DK_TEXTEQU;
+  // DirectiveKindMap[".ascii"] = DK_ASCII;
+  // DirectiveKindMap[".asciz"] = DK_ASCIZ;
+  // DirectiveKindMap[".string"] = DK_STRING;
+  DirectiveKindMap["byte"] = DK_BYTE;
+  DirectiveKindMap["word"] = DK_WORD;
+  DirectiveKindMap["dword"] = DK_DWORD;
+  DirectiveKindMap["fword"] = DK_FWORD;
+  DirectiveKindMap["qword"] = DK_QWORD;
+  DirectiveKindMap["real4"] = DK_REAL4;
+  DirectiveKindMap["real8"] = DK_REAL8;
+  DirectiveKindMap["align"] = DK_ALIGN;
+  // DirectiveKindMap[".org"] = DK_ORG;
+  DirectiveKindMap["extern"] = DK_EXTERN;
+  DirectiveKindMap["public"] = DK_PUBLIC;
+  // DirectiveKindMap[".comm"] = DK_COMM;
+  DirectiveKindMap["comment"] = DK_COMMENT;
+  DirectiveKindMap["include"] = DK_INCLUDE;
+  // DirectiveKindMap[".rept"] = DK_REPT;
+  // DirectiveKindMap[".rep"] = DK_REPT;
+  // DirectiveKindMap[".irp"] = DK_IRP;
+  // DirectiveKindMap[".irpc"] = DK_IRPC;
+  // DirectiveKindMap[".endr"] = DK_ENDR;
+  DirectiveKindMap["if"] = DK_IF;
+  DirectiveKindMap["ife"] = DK_IFE;
+  DirectiveKindMap["ifb"] = DK_IFB;
+  DirectiveKindMap["ifnb"] = DK_IFNB;
+  DirectiveKindMap["ifdef"] = DK_IFDEF;
+  DirectiveKindMap["ifndef"] = DK_IFNDEF;
+  DirectiveKindMap["ifdif"] = DK_IFDIF;
+  DirectiveKindMap["ifdifi"] = DK_IFDIFI;
+  DirectiveKindMap["ifidn"] = DK_IFIDN;
+  DirectiveKindMap["ifidni"] = DK_IFIDNI;
+  DirectiveKindMap["elseif"] = DK_ELSEIF;
+  DirectiveKindMap["elseifdef"] = DK_ELSEIFDEF;
+  DirectiveKindMap["elseifndef"] = DK_ELSEIFNDEF;
+  DirectiveKindMap["elseifdif"] = DK_ELSEIFDIF;
+  DirectiveKindMap["elseifidn"] = DK_ELSEIFIDN;
+  DirectiveKindMap["else"] = DK_ELSE;
+  DirectiveKindMap["end"] = DK_END;
+  DirectiveKindMap["endif"] = DK_ENDIF;
+  // DirectiveKindMap[".file"] = DK_FILE;
+  // DirectiveKindMap[".line"] = DK_LINE;
+  // DirectiveKindMap[".loc"] = DK_LOC;
+  // DirectiveKindMap[".stabs"] = DK_STABS;
+  // DirectiveKindMap[".cv_file"] = DK_CV_FILE;
+  // DirectiveKindMap[".cv_func_id"] = DK_CV_FUNC_ID;
+  // DirectiveKindMap[".cv_loc"] = DK_CV_LOC;
+  // DirectiveKindMap[".cv_linetable"] = DK_CV_LINETABLE;
+  // DirectiveKindMap[".cv_inline_linetable"] = DK_CV_INLINE_LINETABLE;
+  // DirectiveKindMap[".cv_inline_site_id"] = DK_CV_INLINE_SITE_ID;
+  // DirectiveKindMap[".cv_def_range"] = DK_CV_DEF_RANGE;
+  // DirectiveKindMap[".cv_string"] = DK_CV_STRING;
+  // DirectiveKindMap[".cv_stringtable"] = DK_CV_STRINGTABLE;
+  // DirectiveKindMap[".cv_filechecksums"] = DK_CV_FILECHECKSUMS;
+  // DirectiveKindMap[".cv_filechecksumoffset"] = DK_CV_FILECHECKSUM_OFFSET;
+  // DirectiveKindMap[".cv_fpo_data"] = DK_CV_FPO_DATA;
+  // DirectiveKindMap[".cfi_sections"] = DK_CFI_SECTIONS;
+  // DirectiveKindMap[".cfi_startproc"] = DK_CFI_STARTPROC;
+  // DirectiveKindMap[".cfi_endproc"] = DK_CFI_ENDPROC;
+  // DirectiveKindMap[".cfi_def_cfa"] = DK_CFI_DEF_CFA;
+  // DirectiveKindMap[".cfi_def_cfa_offset"] = DK_CFI_DEF_CFA_OFFSET;
+  // DirectiveKindMap[".cfi_adjust_cfa_offset"] = DK_CFI_ADJUST_CFA_OFFSET;
+  // DirectiveKindMap[".cfi_def_cfa_register"] = DK_CFI_DEF_CFA_REGISTER;
+  // DirectiveKindMap[".cfi_offset"] = DK_CFI_OFFSET;
+  // DirectiveKindMap[".cfi_rel_offset"] = DK_CFI_REL_OFFSET;
+  // DirectiveKindMap[".cfi_personality"] = DK_CFI_PERSONALITY;
+  // DirectiveKindMap[".cfi_lsda"] = DK_CFI_LSDA;
+  // DirectiveKindMap[".cfi_remember_state"] = DK_CFI_REMEMBER_STATE;
+  // DirectiveKindMap[".cfi_restore_state"] = DK_CFI_RESTORE_STATE;
+  // DirectiveKindMap[".cfi_same_value"] = DK_CFI_SAME_VALUE;
+  // DirectiveKindMap[".cfi_restore"] = DK_CFI_RESTORE;
+  // DirectiveKindMap[".cfi_escape"] = DK_CFI_ESCAPE;
+  // DirectiveKindMap[".cfi_return_column"] = DK_CFI_RETURN_COLUMN;
+  // DirectiveKindMap[".cfi_signal_frame"] = DK_CFI_SIGNAL_FRAME;
+  // DirectiveKindMap[".cfi_undefined"] = DK_CFI_UNDEFINED;
+  // DirectiveKindMap[".cfi_register"] = DK_CFI_REGISTER;
+  // DirectiveKindMap[".cfi_window_save"] = DK_CFI_WINDOW_SAVE;
+  // DirectiveKindMap[".cfi_b_key_frame"] = DK_CFI_B_KEY_FRAME;
+  // DirectiveKindMap[".macro"] = DK_MACRO;
+  // DirectiveKindMap[".exitm"] = DK_EXITM;
+  // DirectiveKindMap[".endm"] = DK_ENDM;
+  // DirectiveKindMap[".purgem"] = DK_PURGEM;
   DirectiveKindMap[".err"] = DK_ERR;
-  DirectiveKindMap[".error"] = DK_ERROR;
-  DirectiveKindMap[".warning"] = DK_WARNING;
-  DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
-  DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
-  DirectiveKindMap[".reloc"] = DK_RELOC;
-  DirectiveKindMap[".dc"] = DK_DC;
-  DirectiveKindMap[".dc.a"] = DK_DC_A;
-  DirectiveKindMap[".dc.b"] = DK_DC_B;
-  DirectiveKindMap[".dc.d"] = DK_DC_D;
-  DirectiveKindMap[".dc.l"] = DK_DC_L;
-  DirectiveKindMap[".dc.s"] = DK_DC_S;
-  DirectiveKindMap[".dc.w"] = DK_DC_W;
-  DirectiveKindMap[".dc.x"] = DK_DC_X;
-  DirectiveKindMap[".dcb"] = DK_DCB;
-  DirectiveKindMap[".dcb.b"] = DK_DCB_B;
-  DirectiveKindMap[".dcb.d"] = DK_DCB_D;
-  DirectiveKindMap[".dcb.l"] = DK_DCB_L;
-  DirectiveKindMap[".dcb.s"] = DK_DCB_S;
-  DirectiveKindMap[".dcb.w"] = DK_DCB_W;
-  DirectiveKindMap[".dcb.x"] = DK_DCB_X;
-  DirectiveKindMap[".ds"] = DK_DS;
-  DirectiveKindMap[".ds.b"] = DK_DS_B;
-  DirectiveKindMap[".ds.d"] = DK_DS_D;
-  DirectiveKindMap[".ds.l"] = DK_DS_L;
-  DirectiveKindMap[".ds.p"] = DK_DS_P;
-  DirectiveKindMap[".ds.s"] = DK_DS_S;
-  DirectiveKindMap[".ds.w"] = DK_DS_W;
-  DirectiveKindMap[".ds.x"] = DK_DS_X;
-  DirectiveKindMap[".print"] = DK_PRINT;
-  DirectiveKindMap[".addrsig"] = DK_ADDRSIG;
-  DirectiveKindMap[".addrsig_sym"] = DK_ADDRSIG_SYM;
-}
-
-MCAsmMacro *AsmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
+  DirectiveKindMap[".errb"] = DK_ERRB;
+  DirectiveKindMap[".errnb"] = DK_ERRNB;
+  DirectiveKindMap[".errdef"] = DK_ERRDEF;
+  DirectiveKindMap[".errndef"] = DK_ERRNDEF;
+  DirectiveKindMap[".errdif"] = DK_ERRDIF;
+  DirectiveKindMap[".errdifi"] = DK_ERRDIFI;
+  DirectiveKindMap[".erridn"] = DK_ERRIDN;
+  DirectiveKindMap[".erridni"] = DK_ERRIDNI;
+  DirectiveKindMap[".erre"] = DK_ERRE;
+  DirectiveKindMap[".errnz"] = DK_ERRNZ;
+  // DirectiveKindMap[".altmacro"] = DK_ALTMACRO;
+  // DirectiveKindMap[".noaltmacro"] = DK_NOALTMACRO;
+  DirectiveKindMap["db"] = DK_DB;
+  DirectiveKindMap["dd"] = DK_DD;
+  DirectiveKindMap["dq"] = DK_DQ;
+  DirectiveKindMap["dw"] = DK_DW;
+  DirectiveKindMap["echo"] = DK_ECHO;
+}
+
+MCAsmMacro *MasmParser::parseMacroLikeBody(SMLoc DirectiveLoc) {
   AsmToken EndToken, StartToken = getTok();
 
   unsigned NestLevel = 0;
@@ -5528,8 +5246,8 @@
   return &MacroLikeBodies.back();
 }
 
-void AsmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
-                                         raw_svector_ostream &OS) {
+void MasmParser::instantiateMacroLikeBody(MCAsmMacro *M, SMLoc DirectiveLoc,
+                                          raw_svector_ostream &OS) {
   OS << ".endr\n";
 
   std::unique_ptr<MemoryBuffer> Instantiation =
@@ -5549,7 +5267,7 @@
 
 /// parseDirectiveRept
 ///   ::= .rep | .rept count
-bool AsmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
+bool MasmParser::parseDirectiveRept(SMLoc DirectiveLoc, StringRef Dir) {
   const MCExpr *CountExpr;
   SMLoc CountLoc = getTok().getLoc();
   if (parseExpression(CountExpr))
@@ -5586,7 +5304,7 @@
 
 /// parseDirectiveIrp
 /// ::= .irp symbol,values
-bool AsmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveIrp(SMLoc DirectiveLoc) {
   MCAsmMacroParameter Parameter;
   MCAsmMacroArguments A;
   if (check(parseIdentifier(Parameter.Name),
@@ -5620,7 +5338,7 @@
 
 /// parseDirectiveIrpc
 /// ::= .irpc symbol,values
-bool AsmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveIrpc(SMLoc DirectiveLoc) {
   MCAsmMacroParameter Parameter;
   MCAsmMacroArguments A;
 
@@ -5663,7 +5381,7 @@
   return false;
 }
 
-bool AsmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
+bool MasmParser::parseDirectiveEndr(SMLoc DirectiveLoc) {
   if (ActiveMacros.empty())
     return TokError("unmatched '.endr' directive");
 
@@ -5675,8 +5393,8 @@
   return false;
 }
 
-bool AsmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
-                                     size_t Len) {
+bool MasmParser::parseDirectiveMSEmit(SMLoc IDLoc, ParseStatementInfo &Info,
+                                      size_t Len) {
   const MCExpr *Value;
   SMLoc ExprLoc = getLexer().getLoc();
   if (parseExpression(Value))
@@ -5692,7 +5410,7 @@
   return false;
 }
 
-bool AsmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
+bool MasmParser::parseDirectiveMSAlign(SMLoc IDLoc, ParseStatementInfo &Info) {
   const MCExpr *Value;
   SMLoc ExprLoc = getLexer().getLoc();
   if (parseExpression(Value))
@@ -5708,29 +5426,10 @@
   return false;
 }
 
-bool AsmParser::parseDirectivePrint(SMLoc DirectiveLoc) {
-  const AsmToken StrTok = getTok();
-  Lex();
-  if (StrTok.isNot(AsmToken::String) || StrTok.getString().front() != '"')
-    return Error(DirectiveLoc, "expected double quoted string after .print");
-  if (parseToken(AsmToken::EndOfStatement, "expected end of statement"))
-    return true;
-  llvm::outs() << StrTok.getStringContents() << '\n';
-  return false;
-}
-
-bool AsmParser::parseDirectiveAddrsig() {
-  getStreamer().EmitAddrsig();
-  return false;
-}
-
-bool AsmParser::parseDirectiveAddrsigSym() {
-  StringRef Name;
-  if (check(parseIdentifier(Name),
-            "expected identifier in '.addrsig_sym' directive"))
-    return true;
-  MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
-  getStreamer().EmitAddrsigSym(Sym);
+bool MasmParser::parseDirectiveEcho() {
+  StringRef Message = parseStringToEndOfStatement();
+  Lex();  // eat end of statement
+  llvm::outs() << Message << '\n';
   return false;
 }
 
@@ -5757,7 +5456,7 @@
   llvm_unreachable("Unstable rewrite sort.");
 }
 
-bool AsmParser::parseMSInlineAsm(
+bool MasmParser::parseMSInlineAsm(
     void *AsmLoc, std::string &AsmString, unsigned &NumOutputs,
     unsigned &NumInputs, SmallVectorImpl<std::pair<void *, bool>> &OpDecls,
     SmallVectorImpl<std::string> &Constraints,
@@ -6021,92 +5720,9 @@
   return false;
 }
 
-namespace llvm {
-namespace MCParserUtils {
-
-/// Returns whether the given symbol is used anywhere in the given expression,
-/// or subexpressions.
-static bool isSymbolUsedInExpression(const MCSymbol *Sym, const MCExpr *Value) {
-  switch (Value->getKind()) {
-  case MCExpr::Binary: {
-    const MCBinaryExpr *BE = static_cast<const MCBinaryExpr *>(Value);
-    return isSymbolUsedInExpression(Sym, BE->getLHS()) ||
-           isSymbolUsedInExpression(Sym, BE->getRHS());
-  }
-  case MCExpr::Target:
-  case MCExpr::Constant:
-    return false;
-  case MCExpr::SymbolRef: {
-    const MCSymbol &S =
-        static_cast<const MCSymbolRefExpr *>(Value)->getSymbol();
-    if (S.isVariable())
-      return isSymbolUsedInExpression(Sym, S.getVariableValue());
-    return &S == Sym;
-  }
-  case MCExpr::Unary:
-    return isSymbolUsedInExpression(
-        Sym, static_cast<const MCUnaryExpr *>(Value)->getSubExpr());
-  }
-
-  llvm_unreachable("Unknown expr kind!");
-}
-
-bool parseAssignmentExpression(StringRef Name, bool allow_redef,
-                               MCAsmParser &Parser, MCSymbol *&Sym,
-                               const MCExpr *&Value) {
-
-  // FIXME: Use better location, we should use proper tokens.
-  SMLoc EqualLoc = Parser.getTok().getLoc();
-  if (Parser.parseExpression(Value))
-    return Parser.TokError("missing expression");
-
-  // Note: we don't count b as used in "a = b". This is to allow
-  // a = b
-  // b = c
-
-  if (Parser.parseToken(AsmToken::EndOfStatement))
-    return true;
-
-  // Validate that the LHS is allowed to be a variable (either it has not been
-  // used as a symbol, or it is an absolute symbol).
-  Sym = Parser.getContext().lookupSymbol(Name);
-  if (Sym) {
-    // Diagnose assignment to a label.
-    //
-    // FIXME: Diagnostics. Note the location of the definition as a label.
-    // FIXME: Diagnose assignment to protected identifier (e.g., register name).
-    if (isSymbolUsedInExpression(Sym, Value))
-      return Parser.Error(EqualLoc, "Recursive use of '" + Name + "'");
-    else if (Sym->isUndefined(/*SetUsed*/ false) && !Sym->isUsed() &&
-             !Sym->isVariable())
-      ; // Allow redefinitions of undefined symbols only used in directives.
-    else if (Sym->isVariable() && !Sym->isUsed() && allow_redef)
-      ; // Allow redefinitions of variables that haven't yet been used.
-    else if (!Sym->isUndefined() && (!Sym->isVariable() || !allow_redef))
-      return Parser.Error(EqualLoc, "redefinition of '" + Name + "'");
-    else if (!Sym->isVariable())
-      return Parser.Error(EqualLoc, "invalid assignment to '" + Name + "'");
-    else if (!isa<MCConstantExpr>(Sym->getVariableValue()))
-      return Parser.Error(EqualLoc,
-                          "invalid reassignment of non-absolute variable '" +
-                              Name + "'");
-  } else if (Name == ".") {
-    Parser.getStreamer().emitValueToOffset(Value, 0, EqualLoc);
-    return false;
-  } else
-    Sym = Parser.getContext().getOrCreateSymbol(Name);
-
-  Sym->setRedefinable(allow_redef);
-
-  return false;
-}
-
-} // end namespace MCParserUtils
-} // end namespace llvm
-
 /// Create an MCAsmParser instance.
-MCAsmParser *llvm::createMCAsmParser(SourceMgr &SM, MCContext &C,
-                                     MCStreamer &Out, const MCAsmInfo &MAI,
-                                     unsigned CB) {
-  return new AsmParser(SM, C, Out, MAI, CB);
+MCAsmParser *llvm::createMCMasmParser(SourceMgr &SM, MCContext &C,
+                                      MCStreamer &Out, const MCAsmInfo &MAI,
+                                      unsigned CB) {
+  return new MasmParser(SM, C, Out, MAI, CB);
 }
diff --git a/llvm/lib/MC/MCTargetOptions.cpp b/llvm/lib/MC/MCTargetOptions.cpp
--- a/llvm/lib/MC/MCTargetOptions.cpp
+++ b/llvm/lib/MC/MCTargetOptions.cpp
@@ -21,3 +21,7 @@
 StringRef MCTargetOptions::getABIName() const {
   return ABIName;
 }
+
+StringRef MCTargetOptions::getAssemblyLanguage() const {
+  return AssemblyLanguage;
+}
diff --git a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
--- a/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
+++ b/llvm/lib/Target/AArch64/AsmParser/AArch64AsmParser.cpp
@@ -260,6 +260,8 @@
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
   bool ParseDirective(AsmToken DirectiveID) override;
   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
                                       unsigned Kind) override;
@@ -2243,10 +2245,16 @@
 
 bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
                                      SMLoc &EndLoc) {
+  return tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success;
+}
+
+OperandMatchResultTy AArch64AsmParser::tryParseRegister(unsigned &RegNo,
+                                                        SMLoc &StartLoc,
+                                                        SMLoc &EndLoc) {
   StartLoc = getLoc();
   auto Res = tryParseScalarRegister(RegNo);
   EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
-  return Res != MatchOperand_Success;
+  return Res;
 }
 
 // Matches a register name or register alias previously defined by '.req'
diff --git a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
--- a/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
+++ b/llvm/lib/Target/AMDGPU/AsmParser/AMDGPUAsmParser.cpp
@@ -1227,7 +1227,10 @@
   ArrayRef<unsigned> getMatchedVariants() const;
 
   std::unique_ptr<AMDGPUOperand> parseRegister();
+  std::unique_ptr<AMDGPUOperand> tryParseRegister();
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
   unsigned checkTargetMatchPredicate(MCInst &Inst) override;
   unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
                                       unsigned Kind) override;
@@ -1990,6 +1993,13 @@
   return false;
 }
 
+OperandMatchResultTy AMDGPUAsmParser::tryParseRegister(unsigned &RegNo,
+                                                       SMLoc &StartLoc,
+                                                       SMLoc &EndLoc) {
+  return ParseRegister(RegNo, StartLoc, EndLoc) ? MatchOperand_NoMatch
+                                                : MatchOperand_Success;
+}
+
 bool AMDGPUAsmParser::AddNextRegisterToList(unsigned &Reg, unsigned &RegWidth,
                                             RegisterKind RegKind, unsigned Reg1) {
   switch (RegKind) {
@@ -2334,6 +2344,24 @@
   return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc);
 }
 
+std::unique_ptr<AMDGPUOperand> AMDGPUAsmParser::tryParseRegister() {
+  const auto &Tok = Parser.getTok();
+  SMLoc StartLoc = Tok.getLoc();
+  SMLoc EndLoc = Tok.getEndLoc();
+  RegisterKind RegKind;
+  unsigned Reg, RegNum, RegWidth;
+
+  if (!ParseAMDGPURegister(RegKind, Reg, RegNum, RegWidth)) {
+    return nullptr;
+  }
+  if (AMDGPU::IsaInfo::hasCodeObjectV3(&getSTI())) {
+    if (!updateGprCountSymbols(RegKind, RegNum, RegWidth))
+      return nullptr;
+  } else
+    KernelScope.usesRegister(RegKind, RegNum, RegWidth);
+  return AMDGPUOperand::CreateReg(this, Reg, StartLoc, EndLoc);
+}
+
 OperandMatchResultTy
 AMDGPUAsmParser::parseImm(OperandVector &Operands, bool HasSP3AbsModifier) {
   // TODO: add syntactic sugar for 1/(2*PI)
diff --git a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
--- a/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
+++ b/llvm/lib/Target/ARM/AsmParser/ARMAsmParser.cpp
@@ -628,6 +628,8 @@
 
   // Implementation of the MCTargetAsmParser interface:
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
   bool ParseDirective(AsmToken DirectiveID) override;
@@ -3885,6 +3887,14 @@
   return (RegNo == (unsigned)-1);
 }
 
+OperandMatchResultTy ARMAsmParser::tryParseRegister(unsigned &RegNo,
+                                                    SMLoc &StartLoc,
+                                                    SMLoc &EndLoc) {
+  if (ParseRegister(RegNo, StartLoc, EndLoc))
+    return MatchOperand_NoMatch;
+  return MatchOperand_Success;
+}
+
 /// Try to parse a register name.  The token must be an Identifier when called,
 /// and if it is a register name the token is eaten and the register number is
 /// returned.  Otherwise return -1.
diff --git a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
--- a/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
+++ b/llvm/lib/Target/AVR/AsmParser/AVRAsmParser.cpp
@@ -53,6 +53,8 @@
                                bool MatchingInlineAsm) override;
 
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
 
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
@@ -379,6 +381,31 @@
   return RegNum;
 }
 
+int AVRAsmParser::tryParseRegister() {
+  int RegNum = AVR::NoRegister;
+
+  if (Parser.getTok().is(AsmToken::Identifier)) {
+    // Check for register pair syntax
+    if (Parser.getLexer().peekTok().is(AsmToken::Colon)) {
+      AsmToken HighTok = Parser.getTok();
+      Parser.Lex();
+      AsmToken ColonTok = Parser.getTok();
+      Parser.Lex(); // Eat high (odd) register and colon
+
+      if (Parser.getTok().is(AsmToken::Identifier)) {
+        // Convert lower (even) register to DREG
+        RegNum = toDREG(parseRegisterName());
+      } else {
+        getLexer().UnLex(HighTok);
+        getLexer().UnLex(ColonTok);
+      }
+    } else {
+      RegNum = parseRegisterName();
+    }
+  }
+  return RegNum;
+}
+
 bool AVRAsmParser::tryParseRegisterOperand(OperandVector &Operands) {
   int RegNo = parseRegister();
 
@@ -586,6 +613,18 @@
   return (RegNo == AVR::NoRegister);
 }
 
+OperandMatchResultTy AVRAsmParser::tryParseRegister(unsigned &RegNo,
+                                                    SMLoc &StartLoc,
+                                                    SMLoc &EndLoc) {
+  StartLoc = Parser.getTok().getLoc();
+  RegNo = tryParseRegister();
+  EndLoc = Parser.getTok().getLoc();
+
+  if (RegNo == AVR::NoRegister)
+    return MatchOperand_NoMatch;
+  return MatchOperand_Success;
+}
+
 void AVRAsmParser::eatComma() {
   if (getLexer().is(AsmToken::Comma)) {
     Parser.Lex();
diff --git a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
--- a/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
+++ b/llvm/lib/Target/BPF/AsmParser/BPFAsmParser.cpp
@@ -39,6 +39,8 @@
                                bool MatchingInlineAsm) override;
 
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
 
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
@@ -322,6 +324,14 @@
 
 bool BPFAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
                                  SMLoc &EndLoc) {
+  if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
+    return Error(StartLoc, "invalid register name");
+  return false;
+}
+
+OperandMatchResultTy BPFAsmParser::tryParseRegister(unsigned &RegNo,
+                                                    SMLoc &StartLoc,
+                                                    SMLoc &EndLoc) {
   const AsmToken &Tok = getParser().getTok();
   StartLoc = Tok.getLoc();
   EndLoc = Tok.getEndLoc();
@@ -330,10 +340,10 @@
 
   if (!MatchRegisterName(Name)) {
     getParser().Lex(); // Eat identifier token.
-    return false;
+    return MatchOperand_Success;
   }
 
-  return Error(StartLoc, "invalid register name");
+  return MatchOperand_NoMatch;
 }
 
 OperandMatchResultTy
diff --git a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
--- a/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
+++ b/llvm/lib/Target/Hexagon/AsmParser/HexagonAsmParser.cpp
@@ -116,6 +116,8 @@
   bool ParseDirectiveFalign(unsigned Size, SMLoc L);
 
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
   bool ParseDirectiveSubsection(SMLoc L);
   bool ParseDirectiveComm(bool IsLocal, SMLoc L);
   bool RegisterMatchesArch(unsigned MatchNum) const;
@@ -1026,6 +1028,15 @@
   return true;
 }
 
+OperandMatchResultTy HexagonAsmParser::tryParseRegister(unsigned &RegNo,
+                                                        SMLoc &StartLoc,
+                                                        SMLoc &EndLoc) {
+  if (ParseRegister(RegNo, StartLoc, EndLoc)) {
+    return MatchOperand_NoMatch;
+  }
+  return MatchOperand_Success;
+}
+
 bool HexagonAsmParser::implicitExpressionLocation(OperandVector &Operands) {
   if (previousEqual(Operands, 0, "call"))
     return true;
diff --git a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
--- a/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
+++ b/llvm/lib/Target/Lanai/AsmParser/LanaiAsmParser.cpp
@@ -48,6 +48,7 @@
 class LanaiAsmParser : public MCTargetAsmParser {
   // Parse operands
   std::unique_ptr<LanaiOperand> parseRegister();
+  std::unique_ptr<LanaiOperand> tryParseRegister();
 
   std::unique_ptr<LanaiOperand> parseImmediate();
 
@@ -67,6 +68,8 @@
                         SMLoc NameLoc, OperandVector &Operands) override;
 
   bool ParseRegister(unsigned &RegNum, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
 
   bool MatchAndEmitInstruction(SMLoc IdLoc, unsigned &Opcode,
                                OperandVector &Operands, MCStreamer &Out,
@@ -705,6 +708,35 @@
   return nullptr;
 }
 
+// Both '%rN' and 'rN' are parsed as valid registers. This was done to remain
+// backwards compatible with GCC and the different ways inline assembly is
+// handled.
+// TODO: see if there isn't a better way to do this.
+std::unique_ptr<LanaiOperand> LanaiAsmParser::tryParseRegister() {
+  SMLoc Start = Parser.getTok().getLoc();
+  SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
+  SmallVector<AsmToken, 1> Tokens;
+
+  unsigned RegNum;
+  // Eat the '%'.
+  if (Lexer.getKind() == AsmToken::Percent) {
+    Tokens.push_back(Parser.getTok());
+    Parser.Lex();
+  }
+  if (Lexer.getKind() == AsmToken::Identifier) {
+    RegNum = MatchRegisterName(Lexer.getTok().getIdentifier());
+    if (RegNum == 0) {
+      for (const AsmToken &Tok : Tokens) {
+        Lexer.UnLex(Tok);
+      }
+      return nullptr;
+    }
+    Parser.Lex(); // Eat identifier token
+    return LanaiOperand::createReg(RegNum, Start, End);
+  }
+  return nullptr;
+}
+
 bool LanaiAsmParser::ParseRegister(unsigned &RegNum, SMLoc &StartLoc,
                                    SMLoc &EndLoc) {
   const AsmToken &Tok = getParser().getTok();
@@ -716,6 +748,19 @@
   return (Op == nullptr);
 }
 
+OperandMatchResultTy LanaiAsmParser::tryParseRegister(unsigned &RegNum,
+                                                      SMLoc &StartLoc,
+                                                      SMLoc &EndLoc) {
+  const AsmToken &Tok = getParser().getTok();
+  StartLoc = Tok.getLoc();
+  EndLoc = Tok.getEndLoc();
+  std::unique_ptr<LanaiOperand> Op = tryParseRegister();
+  if (Op == nullptr)
+    return MatchOperand_NoMatch;
+  RegNum = Op->getReg();
+  return MatchOperand_Success;
+}
+
 std::unique_ptr<LanaiOperand> LanaiAsmParser::parseIdentifier() {
   SMLoc Start = Parser.getTok().getLoc();
   SMLoc End = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
diff --git a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
--- a/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
+++ b/llvm/lib/Target/MSP430/AsmParser/MSP430AsmParser.cpp
@@ -46,6 +46,8 @@
                                bool MatchingInlineAsm) override;
 
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
 
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
@@ -308,6 +310,29 @@
   return Error(StartLoc, "invalid register name");
 }
 
+OperandMatchResultTy MSP430AsmParser::tryParseRegister(unsigned &RegNo,
+                                                       SMLoc &StartLoc,
+                                                       SMLoc &EndLoc) {
+  if (getLexer().getKind() == AsmToken::Identifier) {
+    auto Name = getLexer().getTok().getIdentifier().lower();
+    RegNo = MatchRegisterName(Name);
+    if (RegNo == MSP430::NoRegister) {
+      RegNo = MatchRegisterAltName(Name);
+      if (RegNo == MSP430::NoRegister)
+        return MatchOperand_NoMatch;
+    }
+
+    AsmToken const &T = getParser().getTok();
+    StartLoc = T.getLoc();
+    EndLoc = T.getEndLoc();
+    getLexer().Lex(); // eat register token
+
+    return MatchOperand_Success;
+  }
+
+  return MatchOperand_NoMatch;
+}
+
 bool MSP430AsmParser::parseJccInstruction(ParseInstructionInfo &Info,
                                           StringRef Name, SMLoc NameLoc,
                                           OperandVector &Operands) {
diff --git a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
--- a/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
+++ b/llvm/lib/Target/Mips/AsmParser/MipsAsmParser.cpp
@@ -179,6 +179,8 @@
 
   /// Parse a register as used in CFI directives
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
 
   bool parseParenSuffix(StringRef Name, OperandVector &Operands);
 
@@ -6226,6 +6228,13 @@
   return (RegNo == (unsigned)-1);
 }
 
+OperandMatchResultTy MipsAsmParser::tryParseRegister(unsigned &RegNo,
+                                                     SMLoc &StartLoc,
+                                                     SMLoc &EndLoc) {
+  return ParseRegister(RegNo, StartLoc, EndLoc) ? MatchOperand_NoMatch
+                                                : MatchOperand_Success;
+}
+
 bool MipsAsmParser::parseMemOffset(const MCExpr *&Res, bool isParenExpr) {
   SMLoc S;
 
diff --git a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
--- a/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
+++ b/llvm/lib/Target/PowerPC/AsmParser/PPCAsmParser.cpp
@@ -109,6 +109,8 @@
   bool MatchRegisterName(unsigned &RegNo, int64_t &IntVal);
 
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
 
   const MCExpr *ExtractModifierFromExpr(const MCExpr *E,
                                         PPCMCExpr::VariantKind &Variant);
@@ -1210,14 +1212,21 @@
 
 bool PPCAsmParser::
 ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
+  if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success)
+    return TokError("invalid register name");
+  return false;
+}
+
+OperandMatchResultTy PPCAsmParser::
+tryParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) {
   const AsmToken &Tok = getParser().getTok();
   StartLoc = Tok.getLoc();
   EndLoc = Tok.getEndLoc();
   RegNo = 0;
   int64_t IntVal;
   if (MatchRegisterName(RegNo, IntVal))
-    return TokError("invalid register name");
-  return false;
+    return MatchOperand_NoMatch;
+  return MatchOperand_Success;
 }
 
 /// Extract \code @l/@ha \endcode modifier from expression.  Recursively scan
diff --git a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
--- a/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
+++ b/llvm/lib/Target/RISCV/AsmParser/RISCVAsmParser.cpp
@@ -74,6 +74,8 @@
                                bool MatchingInlineAsm) override;
 
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
 
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
@@ -997,17 +999,26 @@
 
 bool RISCVAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
                                    SMLoc &EndLoc) {
+  if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) {
+    return Error(StartLoc, "invalid register name");
+  }
+  return false;
+}
+
+OperandMatchResultTy RISCVAsmParser::tryParseRegister(unsigned &RegNo,
+                                                      SMLoc &StartLoc,
+                                                      SMLoc &EndLoc) {
   const AsmToken &Tok = getParser().getTok();
   StartLoc = Tok.getLoc();
   EndLoc = Tok.getEndLoc();
   RegNo = 0;
   StringRef Name = getLexer().getTok().getIdentifier();
 
-  if (matchRegisterNameHelper(isRV32E(), (Register&)RegNo, Name))
-    return Error(StartLoc, "invalid register name");
+  if (matchRegisterNameHelper(isRV32E(), (Register &)RegNo, Name))
+    return MatchOperand_NoMatch;
 
   getParser().Lex(); // Eat identifier token.
-  return false;
+  return MatchOperand_Success;
 }
 
 OperandMatchResultTy RISCVAsmParser::parseRegister(OperandVector &Operands,
diff --git a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
--- a/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
+++ b/llvm/lib/Target/Sparc/AsmParser/SparcAsmParser.cpp
@@ -68,6 +68,8 @@
                                uint64_t &ErrorInfo,
                                bool MatchingInlineAsm) override;
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
   bool ParseDirective(AsmToken DirectiveID) override;
@@ -630,20 +632,31 @@
 
 bool SparcAsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
                                    SMLoc &EndLoc) {
+  if (tryParseRegister(RegNo, StartLoc, EndLoc) != MatchOperand_Success) {
+    return Error(StartLoc, "invalid register name");
+  }
+
+  return false;
+}
+
+OperandMatchResultTy SparcAsmParser::tryParseRegister(unsigned &RegNo,
+                                                      SMLoc &StartLoc,
+                                                      SMLoc &EndLoc) {
   const AsmToken &Tok = Parser.getTok();
   StartLoc = Tok.getLoc();
   EndLoc = Tok.getEndLoc();
   RegNo = 0;
   if (getLexer().getKind() != AsmToken::Percent)
-    return false;
+    return MatchOperand_Success;
   Parser.Lex();
   unsigned regKind = SparcOperand::rk_None;
   if (matchRegisterName(Tok, RegNo, regKind)) {
     Parser.Lex();
-    return false;
+    return MatchOperand_Success;
   }
 
-  return Error(StartLoc, "invalid register name");
+  getLexer().UnLex(Tok);
+  return MatchOperand_NoMatch;
 }
 
 static void applyMnemonicAliases(StringRef &Mnemonic,
diff --git a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
--- a/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
+++ b/llvm/lib/Target/SystemZ/AsmParser/SystemZAsmParser.cpp
@@ -406,6 +406,7 @@
   };
 
   bool parseRegister(Register &Reg);
+  bool tryParseRegister(Register &Reg);
 
   bool parseRegister(Register &Reg, RegisterGroup Group, const unsigned *Regs,
                      bool IsAddress = false);
@@ -449,6 +450,8 @@
   // Override MCTargetAsmParser.
   bool ParseDirective(AsmToken DirectiveID) override;
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
   bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
                         SMLoc NameLoc, OperandVector &Operands) override;
   bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
@@ -732,6 +735,57 @@
   return false;
 }
 
+// Parse one register of the form %<prefix><number>.
+bool SystemZAsmParser::tryParseRegister(Register &Reg) {
+  Reg.StartLoc = Parser.getTok().getLoc();
+
+  // Eat the % prefix.
+  if (Parser.getTok().isNot(AsmToken::Percent))
+    return true;
+  const AsmToken &PercentTok = Parser.getTok();
+  Parser.Lex();
+
+  // Expect a register name.
+  if (Parser.getTok().isNot(AsmToken::Identifier)) {
+    getLexer().UnLex(PercentTok);
+    return true;
+  }
+
+  // Check that there's a prefix.
+  StringRef Name = Parser.getTok().getString();
+  if (Name.size() < 2) {
+    getLexer().UnLex(PercentTok);
+    return true;
+  }
+  char Prefix = Name[0];
+
+  // Treat the rest of the register name as a register number.
+  if (Name.substr(1).getAsInteger(10, Reg.Num)) {
+    getLexer().UnLex(PercentTok);
+    return true;
+  }
+
+  // Look for valid combinations of prefix and number.
+  if (Prefix == 'r' && Reg.Num < 16) {
+    Reg.Group = RegGR;
+  } else if (Prefix == 'f' && Reg.Num < 16) {
+    Reg.Group = RegFP;
+  } else if (Prefix == 'v' && Reg.Num < 32) {
+    Reg.Group = RegV;
+  } else if (Prefix == 'a' && Reg.Num < 16) {
+    Reg.Group = RegAR;
+  } else if (Prefix == 'c' && Reg.Num < 16) {
+    Reg.Group = RegCR;
+  } else {
+    getLexer().UnLex(PercentTok);
+    return true;
+  }
+
+  Reg.EndLoc = Parser.getTok().getLoc();
+  Parser.Lex();
+  return false;
+}
+
 // Parse a register of group Group.  If Regs is nonnull, use it to map
 // the raw register number to LLVM numbering, with zero entries
 // indicating an invalid register.  IsAddress says whether the
@@ -1143,6 +1197,27 @@
   return false;
 }
 
+OperandMatchResultTy SystemZAsmParser::tryParseRegister(unsigned &RegNo,
+                                                        SMLoc &StartLoc,
+                                                        SMLoc &EndLoc) {
+  Register Reg;
+  if (tryParseRegister(Reg))
+    return MatchOperand_NoMatch;
+  if (Reg.Group == RegGR)
+    RegNo = SystemZMC::GR64Regs[Reg.Num];
+  else if (Reg.Group == RegFP)
+    RegNo = SystemZMC::FP64Regs[Reg.Num];
+  else if (Reg.Group == RegV)
+    RegNo = SystemZMC::VR128Regs[Reg.Num];
+  else if (Reg.Group == RegAR)
+    RegNo = SystemZMC::AR32Regs[Reg.Num];
+  else if (Reg.Group == RegCR)
+    RegNo = SystemZMC::CR64Regs[Reg.Num];
+  StartLoc = Reg.StartLoc;
+  EndLoc = Reg.EndLoc;
+  return MatchOperand_Success;
+}
+
 bool SystemZAsmParser::ParseInstruction(ParseInstructionInfo &Info,
                                         StringRef Name, SMLoc NameLoc,
                                         OperandVector &Operands) {
diff --git a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
--- a/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
+++ b/llvm/lib/Target/WebAssembly/AsmParser/WebAssemblyAsmParser.cpp
@@ -214,6 +214,11 @@
                      SMLoc & /*EndLoc*/) override {
     llvm_unreachable("ParseRegister is not implemented.");
   }
+  OperandMatchResultTy tryParseRegister(unsigned & /*RegNo*/,
+                                        SMLoc & /*StartLoc*/,
+                                        SMLoc & /*EndLoc*/) override {
+    llvm_unreachable("tryParseRegister is not implemented.");
+  }
 
   bool error(const Twine &Msg, const AsmToken &Tok) {
     return Parser.Error(Tok.getLoc(), Msg + Tok.getString());
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
@@ -1023,6 +1023,8 @@
   }
 
   bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
+  OperandMatchResultTy tryParseRegister(unsigned &RegNo, SMLoc &StartLoc,
+                                        SMLoc &EndLoc) override;
 
   bool parsePrimaryExpr(const MCExpr *&Res, SMLoc &EndLoc) override;
 
@@ -1259,6 +1261,166 @@
   return false;
 }
 
+OperandMatchResultTy X86AsmParser::tryParseRegister(unsigned &RegNo,
+                                                    SMLoc &StartLoc,
+                                                    SMLoc &EndLoc) {
+  MCAsmParser &Parser = getParser();
+  RegNo = 0;
+  SmallVector<AsmToken, 5> Tokens;
+
+  const AsmToken &PercentTok = Parser.getTok();
+  StartLoc = PercentTok.getLoc();
+
+  // If we encounter a %, ignore it. This code handles registers with and
+  // without the prefix, unprefixed registers can occur in cfi directives.
+  if (!isParsingIntelSyntax() && PercentTok.is(AsmToken::Percent)) {
+    // Eat percent token.
+    Tokens.push_back(PercentTok);
+    Parser.Lex();
+  }
+
+  const AsmToken &Tok = Parser.getTok();
+  EndLoc = Tok.getEndLoc();
+
+  if (Tok.isNot(AsmToken::Identifier)) {
+    for (const AsmToken &ReplaceTok : Tokens) {
+      getLexer().UnLex(ReplaceTok);
+    }
+    if (isParsingIntelSyntax()) return MatchOperand_NoMatch;
+    return MatchOperand_NoMatch;
+  }
+
+  RegNo = MatchRegisterName(Tok.getString());
+
+  // If the match failed, try the register name as lowercase.
+  if (RegNo == 0)
+    RegNo = MatchRegisterName(Tok.getString().lower());
+
+  // The "flags" and "mxcsr" registers cannot be referenced directly.
+  // Treat it as an identifier instead.
+  if (isParsingInlineAsm() && isParsingIntelSyntax() &&
+      (RegNo == X86::EFLAGS || RegNo == X86::MXCSR))
+    RegNo = 0;
+
+  if (!is64BitMode()) {
+    // FIXME: This should be done using Requires<Not64BitMode> and
+    // Requires<In64BitMode> so "eiz" usage in 64-bit instructions can be also
+    // checked.
+    // FIXME: Check AH, CH, DH, BH cannot be used in an instruction requiring a
+    // REX prefix.
+    if (RegNo == X86::RIZ || RegNo == X86::RIP ||
+        X86MCRegisterClasses[X86::GR64RegClassID].contains(RegNo) ||
+        X86II::isX86_64NonExtLowByteReg(RegNo) ||
+        X86II::isX86_64ExtendedReg(RegNo)) {
+      for (const AsmToken &ReplaceTok : Tokens) {
+        getLexer().UnLex(ReplaceTok);
+      }
+      return MatchOperand_NoMatch;
+    }
+  }
+
+  // Parse "%st" as "%st(0)" and "%st(1)", which is multiple tokens.
+  if (RegNo == X86::ST0) {
+     // Eat 'st'
+    Tokens.push_back(Parser.getTok());
+    Parser.Lex();
+
+    // Check to see if we have '(4)' after %st.
+    if (getLexer().isNot(AsmToken::LParen))
+      return MatchOperand_Success;
+    // Lex the paren.
+    Tokens.push_back(Parser.getTok());
+    Parser.Lex();
+
+    const AsmToken &IntTok = Parser.getTok();
+    if (IntTok.isNot(AsmToken::Integer)) {
+      for (const AsmToken &ReplaceTok : Tokens) {
+        getLexer().UnLex(ReplaceTok);
+      }
+      return MatchOperand_NoMatch;
+    }
+    switch (IntTok.getIntVal()) {
+    case 0: RegNo = X86::ST0; break;
+    case 1: RegNo = X86::ST1; break;
+    case 2: RegNo = X86::ST2; break;
+    case 3: RegNo = X86::ST3; break;
+    case 4: RegNo = X86::ST4; break;
+    case 5: RegNo = X86::ST5; break;
+    case 6: RegNo = X86::ST6; break;
+    case 7: RegNo = X86::ST7; break;
+    default:
+      for (const AsmToken &ReplaceTok : Tokens) {
+        getLexer().UnLex(ReplaceTok);
+      }
+      return MatchOperand_ParseFail;
+    }
+
+    Tokens.push_back(IntTok);
+    if (Parser.Lex().isNot(AsmToken::RParen)) {
+      for (const AsmToken &ReplaceTok : Tokens) {
+        getLexer().UnLex(ReplaceTok);
+      }
+      return MatchOperand_NoMatch;
+    }
+
+    EndLoc = Parser.getTok().getEndLoc();
+    // Eat ')'
+    Tokens.push_back(Parser.getTok());
+    Parser.Lex();
+    return MatchOperand_Success;
+  }
+
+  EndLoc = Parser.getTok().getEndLoc();
+
+  // If this is "db[0-15]", match it as an alias
+  // for dr[0-15].
+  if (RegNo == 0 && Tok.getString().startswith("db")) {
+    if (Tok.getString().size() == 3) {
+      switch (Tok.getString()[2]) {
+      case '0': RegNo = X86::DR0; break;
+      case '1': RegNo = X86::DR1; break;
+      case '2': RegNo = X86::DR2; break;
+      case '3': RegNo = X86::DR3; break;
+      case '4': RegNo = X86::DR4; break;
+      case '5': RegNo = X86::DR5; break;
+      case '6': RegNo = X86::DR6; break;
+      case '7': RegNo = X86::DR7; break;
+      case '8': RegNo = X86::DR8; break;
+      case '9': RegNo = X86::DR9; break;
+      }
+    } else if (Tok.getString().size() == 4 && Tok.getString()[2] == '1') {
+      switch (Tok.getString()[3]) {
+      case '0': RegNo = X86::DR10; break;
+      case '1': RegNo = X86::DR11; break;
+      case '2': RegNo = X86::DR12; break;
+      case '3': RegNo = X86::DR13; break;
+      case '4': RegNo = X86::DR14; break;
+      case '5': RegNo = X86::DR15; break;
+      }
+    }
+
+    if (RegNo != 0) {
+      EndLoc = Parser.getTok().getEndLoc();
+      // Eat it.
+      Tokens.push_back(Parser.getTok());
+      Parser.Lex();
+      return MatchOperand_Success;
+    }
+  }
+
+  if (RegNo == 0) {
+    for (const AsmToken &ReplaceTok : Tokens) {
+      getLexer().UnLex(ReplaceTok);
+    }
+    return MatchOperand_NoMatch;
+  }
+
+  // Eat identifier token.
+  Tokens.push_back(Parser.getTok());
+  Parser.Lex();
+  return MatchOperand_Success;
+}
+
 std::unique_ptr<X86Operand> X86AsmParser::DefaultMemSIOperand(SMLoc Loc) {
   bool Parse32 = is32BitMode() || Code16GCC;
   unsigned Basereg = is64BitMode() ? X86::RSI : (Parse32 ? X86::ESI : X86::SI);
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.h
@@ -49,6 +49,13 @@
   explicit X86MCAsmInfoMicrosoft(const Triple &Triple);
 };
 
+class X86MCAsmInfoMicrosoftMASM : public X86MCAsmInfoMicrosoft {
+  void anchor() override;
+
+public:
+  explicit X86MCAsmInfoMicrosoftMASM(const Triple &Triple);
+};
+
 class X86MCAsmInfoGNUCOFF : public MCAsmInfoGNUCOFF {
   void anchor() override;
 
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCAsmInfo.cpp
@@ -145,6 +145,16 @@
   UseIntegratedAssembler = true;
 }
 
+void X86MCAsmInfoMicrosoftMASM::anchor() { }
+
+X86MCAsmInfoMicrosoftMASM::X86MCAsmInfoMicrosoftMASM(const Triple &Triple)
+    : X86MCAsmInfoMicrosoft(Triple) {
+  DollarIsPC = true;
+  SeparatorString = "\n";
+  CommentString = ";";
+  AllowSymbolAtNameStart = true;
+}
+
 void X86MCAsmInfoGNUCOFF::anchor() { }
 
 X86MCAsmInfoGNUCOFF::X86MCAsmInfoGNUCOFF(const Triple &Triple) {
diff --git a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
--- a/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
+++ b/llvm/lib/Target/X86/MCTargetDesc/X86MCTargetDesc.cpp
@@ -335,7 +335,10 @@
     MAI = new X86ELFMCAsmInfo(TheTriple);
   } else if (TheTriple.isWindowsMSVCEnvironment() ||
              TheTriple.isWindowsCoreCLREnvironment()) {
-    MAI = new X86MCAsmInfoMicrosoft(TheTriple);
+    if (Options.getAssemblyLanguage().equals_lower("masm"))
+      MAI = new X86MCAsmInfoMicrosoftMASM(TheTriple);
+    else
+      MAI = new X86MCAsmInfoMicrosoft(TheTriple);
   } else if (TheTriple.isOSCygMing() ||
              TheTriple.isWindowsItaniumEnvironment()) {
     MAI = new X86MCAsmInfoGNUCOFF(TheTriple);
diff --git a/llvm/tools/llvm-ml/llvm-ml.cpp b/llvm/tools/llvm-ml/llvm-ml.cpp
--- a/llvm/tools/llvm-ml/llvm-ml.cpp
+++ b/llvm/tools/llvm-ml/llvm-ml.cpp
@@ -205,7 +205,8 @@
                          SourceMgr &SrcMgr, MCContext &Ctx, MCStreamer &Str,
                          MCAsmInfo &MAI, MCSubtargetInfo &STI,
                          MCInstrInfo &MCII, MCTargetOptions &MCOptions) {
-  std::unique_ptr<MCAsmParser> Parser(createMCAsmParser(SrcMgr, Ctx, Str, MAI));
+  std::unique_ptr<MCAsmParser> Parser(
+      createMCMasmParser(SrcMgr, Ctx, Str, MAI));
 
   // XXX hm
   std::unique_ptr<MCTargetAsmParser> TAP(
@@ -240,6 +241,7 @@
 
   cl::ParseCommandLineOptions(argc, argv, "llvm machine code playground\n");
   MCTargetOptions MCOptions = InitMCTargetOptionsFromFlags();
+  MCOptions.AssemblyLanguage = "masm";
 
   const char *ProgName = argv[0];
   const Target *TheTarget = GetTarget(ProgName);
diff --git a/llvm/utils/gn/secondary/llvm/lib/MC/MCParser/BUILD.gn b/llvm/utils/gn/secondary/llvm/lib/MC/MCParser/BUILD.gn
--- a/llvm/utils/gn/secondary/llvm/lib/MC/MCParser/BUILD.gn
+++ b/llvm/utils/gn/secondary/llvm/lib/MC/MCParser/BUILD.gn
@@ -14,6 +14,7 @@
     "MCAsmLexer.cpp",
     "MCAsmParser.cpp",
     "MCAsmParserExtension.cpp",
+    "MasmParser.cpp",
     "MCTargetAsmParser.cpp",
     "WasmAsmParser.cpp",
   ]