add a missed cmov alias, part of rdar://8416805
[oota-llvm.git] / lib / Target / X86 / AsmParser / X86AsmParser.cpp
index d102b371d4aebfd82b18480727d11de31c663101..6a664ad4ce1c718b96b99d630ebeaf13333cab27 100644 (file)
@@ -7,14 +7,21 @@
 //
 //===----------------------------------------------------------------------===//
 
+#include "llvm/Target/TargetAsmParser.h"
 #include "X86.h"
+#include "X86Subtarget.h"
+#include "llvm/ADT/SmallString.h"
 #include "llvm/ADT/SmallVector.h"
+#include "llvm/ADT/StringSwitch.h"
 #include "llvm/ADT/Twine.h"
-#include "llvm/MC/MCAsmLexer.h"
-#include "llvm/MC/MCAsmParser.h"
+#include "llvm/MC/MCStreamer.h"
 #include "llvm/MC/MCExpr.h"
 #include "llvm/MC/MCInst.h"
+#include "llvm/MC/MCParser/MCAsmLexer.h"
+#include "llvm/MC/MCParser/MCAsmParser.h"
+#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
 #include "llvm/Support/SourceMgr.h"
+#include "llvm/Support/raw_ostream.h"
 #include "llvm/Target/TargetRegistry.h"
 #include "llvm/Target/TargetAsmParser.h"
 using namespace llvm;
@@ -24,56 +31,91 @@ struct X86Operand;
 
 class X86ATTAsmParser : public TargetAsmParser {
   MCAsmParser &Parser;
+  TargetMachine &TM;
+
+protected:
+  unsigned Is64Bit : 1;
 
 private:
   MCAsmParser &getParser() const { return Parser; }
 
   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
 
-  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
-
   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
 
-  bool ParseRegister(X86Operand &Op);
+  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
 
-  bool ParseOperand(X86Operand &Op);
+  X86Operand *ParseOperand();
+  X86Operand *ParseMemOperand(unsigned SegReg, SMLoc StartLoc);
 
-  bool ParseMemOperand(X86Operand &Op);
-  
-  /// @name Auto-generated Match Functions
-  /// {  
+  bool ParseDirectiveWord(unsigned Size, SMLoc L);
 
-  bool MatchInstruction(SmallVectorImpl<X86Operand> &Operands,
+  bool MatchInstruction(SMLoc IDLoc,
+                        const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
                         MCInst &Inst);
 
-  /// MatchRegisterName - Match the given string to a register name, or 0 if
-  /// there is no match.
-  unsigned MatchRegisterName(const StringRef &Name);
-
+  /// @name Auto-generated Matcher Functions
+  /// {
+  
+#define GET_ASSEMBLER_HEADER
+#include "X86GenAsmMatcher.inc"
+  
   /// }
 
 public:
-  X86ATTAsmParser(const Target &T, MCAsmParser &_Parser)
-    : TargetAsmParser(T), Parser(_Parser) {}
+  X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
+    : TargetAsmParser(T), Parser(_Parser), TM(TM) {
+
+    // Initialize the set of available features.
+    setAvailableFeatures(ComputeAvailableFeatures(
+                           &TM.getSubtarget<X86Subtarget>()));
+  }
 
-  virtual bool ParseInstruction(const StringRef &Name, MCInst &Inst);
+  virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
+                                SmallVectorImpl<MCParsedAsmOperand*> &Operands);
+
+  virtual bool ParseDirective(AsmToken DirectiveID);
 };
-  
+
+class X86_32ATTAsmParser : public X86ATTAsmParser {
+public:
+  X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
+    : X86ATTAsmParser(T, _Parser, TM) {
+    Is64Bit = false;
+  }
+};
+
+class X86_64ATTAsmParser : public X86ATTAsmParser {
+public:
+  X86_64ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
+    : X86ATTAsmParser(T, _Parser, TM) {
+    Is64Bit = true;
+  }
+};
+
 } // end anonymous namespace
 
+/// @name Auto-generated Match Functions
+/// {
+
+static unsigned MatchRegisterName(StringRef Name);
+
+/// }
 
 namespace {
 
 /// X86Operand - Instances of this class represent a parsed X86 machine
 /// instruction.
-struct X86Operand {
-  enum {
+struct X86Operand : public MCParsedAsmOperand {
+  enum KindTy {
     Token,
     Register,
     Immediate,
     Memory
   } Kind;
 
+  SMLoc StartLoc, EndLoc;
+
   union {
     struct {
       const char *Data;
@@ -97,10 +139,25 @@ struct X86Operand {
     } Mem;
   };
 
+  X86Operand(KindTy K, SMLoc Start, SMLoc End)
+    : Kind(K), StartLoc(Start), EndLoc(End) {}
+
+  /// getStartLoc - Get the location of the first token of this operand.
+  SMLoc getStartLoc() const { return StartLoc; }
+  /// getEndLoc - Get the location of the last token of this operand.
+  SMLoc getEndLoc() const { return EndLoc; }
+
+  virtual void dump(raw_ostream &OS) const {}
+
   StringRef getToken() const {
     assert(Kind == Token && "Invalid access!");
     return StringRef(Tok.Data, Tok.Length);
   }
+  void setTokenValue(StringRef Value) {
+    assert(Kind == Token && "Invalid access!");
+    Tok.Data = Value.data();
+    Tok.Length = Value.size();
+  }
 
   unsigned getReg() const {
     assert(Kind == Register && "Invalid access!");
@@ -136,25 +193,91 @@ struct X86Operand {
   bool isToken() const {return Kind == Token; }
 
   bool isImm() const { return Kind == Immediate; }
-  
-  bool isImmSExt8() const { 
-    // Accept immediates which fit in 8 bits when sign extended, and
-    // non-absolute immediates.
+
+  bool isImmSExti16i8() const {
     if (!isImm())
       return false;
 
-    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) {
-      int64_t Value = CE->getValue();
-      return Value == (int64_t) (int8_t) Value;
-    }
+    // If this isn't a constant expr, just assume it fits and let relaxation
+    // handle it.
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE)
+      return true;
 
-    return true;
+    // Otherwise, check the value is in a range that makes sense for this
+    // extension.
+    uint64_t Value = CE->getValue();
+    return ((                                  Value <= 0x000000000000007FULL)||
+            (0x000000000000FF80ULL <= Value && Value <= 0x000000000000FFFFULL)||
+            (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
   }
-  
+  bool isImmSExti32i8() const {
+    if (!isImm())
+      return false;
+
+    // If this isn't a constant expr, just assume it fits and let relaxation
+    // handle it.
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE)
+      return true;
+
+    // Otherwise, check the value is in a range that makes sense for this
+    // extension.
+    uint64_t Value = CE->getValue();
+    return ((                                  Value <= 0x000000000000007FULL)||
+            (0x00000000FFFFFF80ULL <= Value && Value <= 0x00000000FFFFFFFFULL)||
+            (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
+  }
+  bool isImmSExti64i8() const {
+    if (!isImm())
+      return false;
+
+    // If this isn't a constant expr, just assume it fits and let relaxation
+    // handle it.
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE)
+      return true;
+
+    // Otherwise, check the value is in a range that makes sense for this
+    // extension.
+    uint64_t Value = CE->getValue();
+    return ((                                  Value <= 0x000000000000007FULL)||
+            (0xFFFFFFFFFFFFFF80ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
+  }
+  bool isImmSExti64i32() const {
+    if (!isImm())
+      return false;
+
+    // If this isn't a constant expr, just assume it fits and let relaxation
+    // handle it.
+    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
+    if (!CE)
+      return true;
+
+    // Otherwise, check the value is in a range that makes sense for this
+    // extension.
+    uint64_t Value = CE->getValue();
+    return ((                                  Value <= 0x000000007FFFFFFFULL)||
+            (0xFFFFFFFF80000000ULL <= Value && Value <= 0xFFFFFFFFFFFFFFFFULL));
+  }
+
   bool isMem() const { return Kind == Memory; }
 
+  bool isAbsMem() const {
+    return Kind == Memory && !getMemSegReg() && !getMemBaseReg() &&
+      !getMemIndexReg() && getMemScale() == 1;
+  }
+
   bool isReg() const { return Kind == Register; }
 
+  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
+    // Add as immediates when possible.
+    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
+      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
+    else
+      Inst.addOperand(MCOperand::CreateExpr(Expr));
+  }
+
   void addRegOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
     Inst.addOperand(MCOperand::CreateReg(getReg()));
@@ -162,66 +285,71 @@ struct X86Operand {
 
   void addImmOperands(MCInst &Inst, unsigned N) const {
     assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateExpr(getImm()));
-  }
-
-  void addImmSExt8Operands(MCInst &Inst, unsigned N) const {
-    // FIXME: Support user customization of the render method.
-    assert(N == 1 && "Invalid number of operands!");
-    Inst.addOperand(MCOperand::CreateExpr(getImm()));
+    addExpr(Inst, getImm());
   }
 
   void addMemOperands(MCInst &Inst, unsigned N) const {
-    assert((N == 4 || N == 5) && "Invalid number of operands!");
-
+    assert((N == 5) && "Invalid number of operands!");
     Inst.addOperand(MCOperand::CreateReg(getMemBaseReg()));
     Inst.addOperand(MCOperand::CreateImm(getMemScale()));
     Inst.addOperand(MCOperand::CreateReg(getMemIndexReg()));
+    addExpr(Inst, getMemDisp());
+    Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
+  }
+
+  void addAbsMemOperands(MCInst &Inst, unsigned N) const {
+    assert((N == 1) && "Invalid number of operands!");
     Inst.addOperand(MCOperand::CreateExpr(getMemDisp()));
+  }
 
-    // FIXME: What a hack.
-    if (N == 5)
-      Inst.addOperand(MCOperand::CreateReg(getMemSegReg()));
+  static X86Operand *CreateToken(StringRef Str, SMLoc Loc) {
+    X86Operand *Res = new X86Operand(Token, Loc, Loc);
+    Res->Tok.Data = Str.data();
+    Res->Tok.Length = Str.size();
+    return Res;
   }
 
-  static X86Operand CreateToken(StringRef Str) {
-    X86Operand Res;
-    Res.Kind = Token;
-    Res.Tok.Data = Str.data();
-    Res.Tok.Length = Str.size();
+  static X86Operand *CreateReg(unsigned RegNo, SMLoc StartLoc, SMLoc EndLoc) {
+    X86Operand *Res = new X86Operand(Register, StartLoc, EndLoc);
+    Res->Reg.RegNo = RegNo;
     return Res;
   }
 
-  static X86Operand CreateReg(unsigned RegNo) {
-    X86Operand Res;
-    Res.Kind = Register;
-    Res.Reg.RegNo = RegNo;
+  static X86Operand *CreateImm(const MCExpr *Val, SMLoc StartLoc, SMLoc EndLoc){
+    X86Operand *Res = new X86Operand(Immediate, StartLoc, EndLoc);
+    Res->Imm.Val = Val;
     return Res;
   }
 
-  static X86Operand CreateImm(const MCExpr *Val) {
-    X86Operand Res;
-    Res.Kind = Immediate;
-    Res.Imm.Val = Val;
+  /// Create an absolute memory operand.
+  static X86Operand *CreateMem(const MCExpr *Disp, SMLoc StartLoc,
+                               SMLoc EndLoc) {
+    X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
+    Res->Mem.SegReg   = 0;
+    Res->Mem.Disp     = Disp;
+    Res->Mem.BaseReg  = 0;
+    Res->Mem.IndexReg = 0;
+    Res->Mem.Scale    = 1;
     return Res;
   }
 
-  static X86Operand CreateMem(unsigned SegReg, const MCExpr *Disp,
-                              unsigned BaseReg, unsigned IndexReg,
-                              unsigned Scale) {
-    // We should never just have a displacement, that would be an immediate.
+  /// Create a generalized memory operand.
+  static X86Operand *CreateMem(unsigned SegReg, const MCExpr *Disp,
+                               unsigned BaseReg, unsigned IndexReg,
+                               unsigned Scale, SMLoc StartLoc, SMLoc EndLoc) {
+    // We should never just have a displacement, that should be parsed as an
+    // absolute memory operand.
     assert((SegReg || BaseReg || IndexReg) && "Invalid memory operand!");
 
     // The scale should always be one of {1,2,4,8}.
     assert(((Scale == 1 || Scale == 2 || Scale == 4 || Scale == 8)) &&
            "Invalid scale!");
-    X86Operand Res;
-    Res.Kind = Memory;
-    Res.Mem.SegReg   = SegReg;
-    Res.Mem.Disp     = Disp;
-    Res.Mem.BaseReg  = BaseReg;
-    Res.Mem.IndexReg = IndexReg;
-    Res.Mem.Scale    = Scale;
+    X86Operand *Res = new X86Operand(Memory, StartLoc, EndLoc);
+    Res->Mem.SegReg   = SegReg;
+    Res->Mem.Disp     = Disp;
+    Res->Mem.BaseReg  = BaseReg;
+    Res->Mem.IndexReg = IndexReg;
+    Res->Mem.Scale    = Scale;
     return Res;
   }
 };
@@ -229,212 +357,741 @@ struct X86Operand {
 } // end anonymous namespace.
 
 
-bool X86ATTAsmParser::ParseRegister(X86Operand &Op) {
-  const AsmToken &TokPercent = getLexer().getTok();
+bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
+                                    SMLoc &StartLoc, SMLoc &EndLoc) {
+  RegNo = 0;
+  const AsmToken &TokPercent = Parser.getTok();
   assert(TokPercent.is(AsmToken::Percent) && "Invalid token kind!");
-  getLexer().Lex(); // Eat percent token.
+  StartLoc = TokPercent.getLoc();
+  Parser.Lex(); // Eat percent token.
 
-  const AsmToken &Tok = getLexer().getTok();
-  assert(TokPercent.is(AsmToken::Identifier) && "Invalid token kind!");
+  const AsmToken &Tok = Parser.getTok();
+  if (Tok.isNot(AsmToken::Identifier))
+    return Error(Tok.getLoc(), "invalid register name");
 
   // FIXME: Validate register for the current architecture; we have to do
   // validation later, so maybe there is no need for this here.
-  unsigned RegNo;
-
   RegNo = MatchRegisterName(Tok.getString());
+
+  // FIXME: This should be done using Requires<In32BitMode> and
+  // Requires<In64BitMode> so "eiz" usage in 64-bit instructions
+  // can be also checked.
+  if (RegNo == X86::RIZ && !Is64Bit)
+    return Error(Tok.getLoc(), "riz register in 64-bit mode only");
+
+  // Parse %st(1) and "%st" as "%st(0)"
+  if (RegNo == 0 && Tok.getString() == "st") {
+    RegNo = X86::ST0;
+    EndLoc = Tok.getLoc();
+    Parser.Lex(); // Eat 'st'
+
+    // Check to see if we have '(4)' after %st.
+    if (getLexer().isNot(AsmToken::LParen))
+      return false;
+    // Lex the paren.
+    getParser().Lex();
+
+    const AsmToken &IntTok = Parser.getTok();
+    if (IntTok.isNot(AsmToken::Integer))
+      return Error(IntTok.getLoc(), "expected stack index");
+    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: return Error(IntTok.getLoc(), "invalid stack index");
+    }
+
+    if (getParser().Lex().isNot(AsmToken::RParen))
+      return Error(Parser.getTok().getLoc(), "expected ')'");
+
+    EndLoc = Tok.getLoc();
+    Parser.Lex(); // Eat ')'
+    return false;
+  }
+
+  // If this is "db[0-7]", match it as an alias
+  // for dr[0-7].
+  if (RegNo == 0 && Tok.getString().size() == 3 &&
+      Tok.getString().startswith("db")) {
+    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;
+    }
+
+    if (RegNo != 0) {
+      EndLoc = Tok.getLoc();
+      Parser.Lex(); // Eat it.
+      return false;
+    }
+  }
+
   if (RegNo == 0)
     return Error(Tok.getLoc(), "invalid register name");
 
-  Op = X86Operand::CreateReg(RegNo);
-  getLexer().Lex(); // Eat identifier token.
-
+  EndLoc = Tok.getLoc();
+  Parser.Lex(); // Eat identifier token.
   return false;
 }
 
-bool X86ATTAsmParser::ParseOperand(X86Operand &Op) {
+X86Operand *X86ATTAsmParser::ParseOperand() {
   switch (getLexer().getKind()) {
   default:
-    return ParseMemOperand(Op);
-  case AsmToken::Percent:
-    // FIXME: if a segment register, this could either be just the seg reg, or
-    // the start of a memory operand.
-    return ParseRegister(Op);
+    // Parse a memory operand with no segment register.
+    return ParseMemOperand(0, Parser.getTok().getLoc());
+  case AsmToken::Percent: {
+    // Read the register.
+    unsigned RegNo;
+    SMLoc Start, End;
+    if (ParseRegister(RegNo, Start, End)) return 0;
+    if (RegNo == X86::EIZ || RegNo == X86::RIZ) {
+      Error(Start, "eiz and riz can only be used as index registers");
+      return 0;
+    }
+
+    // If this is a segment register followed by a ':', then this is the start
+    // of a memory reference, otherwise this is a normal register reference.
+    if (getLexer().isNot(AsmToken::Colon))
+      return X86Operand::CreateReg(RegNo, Start, End);
+
+
+    getParser().Lex(); // Eat the colon.
+    return ParseMemOperand(RegNo, Start);
+  }
   case AsmToken::Dollar: {
     // $42 -> immediate.
-    getLexer().Lex();
+    SMLoc Start = Parser.getTok().getLoc(), End;
+    Parser.Lex();
     const MCExpr *Val;
-    if (getParser().ParseExpression(Val))
-      return true;
-    Op = X86Operand::CreateImm(Val);
-    return false;
+    if (getParser().ParseExpression(Val, End))
+      return 0;
+    return X86Operand::CreateImm(Val, Start, End);
   }
   }
 }
 
-/// ParseMemOperand: segment: disp(basereg, indexreg, scale)
-bool X86ATTAsmParser::ParseMemOperand(X86Operand &Op) {
-  // FIXME: If SegReg ':'  (e.g. %gs:), eat and remember.
-  unsigned SegReg = 0;
-  
+/// ParseMemOperand: segment: disp(basereg, indexreg, scale).  The '%ds:' prefix
+/// has already been parsed if present.
+X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
+
   // We have to disambiguate a parenthesized expression "(4+5)" from the start
   // of a memory operand with a missing displacement "(%ebx)" or "(,%eax)".  The
-  // only way to do this without lookahead is to eat the ( and see what is after
-  // it.
+  // only way to do this without lookahead is to eat the '(' and see what is
+  // after it.
   const MCExpr *Disp = MCConstantExpr::Create(0, getParser().getContext());
   if (getLexer().isNot(AsmToken::LParen)) {
-    if (getParser().ParseExpression(Disp)) return true;
-    
+    SMLoc ExprEnd;
+    if (getParser().ParseExpression(Disp, ExprEnd)) return 0;
+
     // After parsing the base expression we could either have a parenthesized
     // memory address or not.  If not, return now.  If so, eat the (.
     if (getLexer().isNot(AsmToken::LParen)) {
       // Unless we have a segment register, treat this as an immediate.
-      if (SegReg)
-        Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1);
-      else
-        Op = X86Operand::CreateImm(Disp);
-      return false;
+      if (SegReg == 0)
+        return X86Operand::CreateMem(Disp, MemStart, ExprEnd);
+      return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
     }
-    
+
     // Eat the '('.
-    getLexer().Lex();
+    Parser.Lex();
   } else {
     // Okay, we have a '('.  We don't know if this is an expression or not, but
     // so we have to eat the ( to see beyond it.
-    getLexer().Lex(); // Eat the '('.
-    
+    SMLoc LParenLoc = Parser.getTok().getLoc();
+    Parser.Lex(); // Eat the '('.
+
     if (getLexer().is(AsmToken::Percent) || getLexer().is(AsmToken::Comma)) {
       // Nothing to do here, fall into the code below with the '(' part of the
       // memory operand consumed.
     } else {
+      SMLoc ExprEnd;
+
       // It must be an parenthesized expression, parse it now.
-      if (getParser().ParseParenExpression(Disp))
-        return true;
-      
+      if (getParser().ParseParenExpression(Disp, ExprEnd))
+        return 0;
+
       // After parsing the base expression we could either have a parenthesized
       // memory address or not.  If not, return now.  If so, eat the (.
       if (getLexer().isNot(AsmToken::LParen)) {
         // Unless we have a segment register, treat this as an immediate.
-        if (SegReg)
-          Op = X86Operand::CreateMem(SegReg, Disp, 0, 0, 1);
-        else
-          Op = X86Operand::CreateImm(Disp);
-        return false;
+        if (SegReg == 0)
+          return X86Operand::CreateMem(Disp, LParenLoc, ExprEnd);
+        return X86Operand::CreateMem(SegReg, Disp, 0, 0, 1, MemStart, ExprEnd);
       }
-      
+
       // Eat the '('.
-      getLexer().Lex();
+      Parser.Lex();
     }
   }
-  
+
   // If we reached here, then we just ate the ( of the memory operand.  Process
   // the rest of the memory operand.
   unsigned BaseReg = 0, IndexReg = 0, Scale = 1;
-  
+
   if (getLexer().is(AsmToken::Percent)) {
-    if (ParseRegister(Op))
-      return true;
-    BaseReg = Op.getReg();
+    SMLoc L;
+    if (ParseRegister(BaseReg, L, L)) return 0;
+    if (BaseReg == X86::EIZ || BaseReg == X86::RIZ) {
+      Error(L, "eiz and riz can only be used as index registers");
+      return 0;
+    }
   }
-  
+
   if (getLexer().is(AsmToken::Comma)) {
-    getLexer().Lex(); // Eat the comma.
+    Parser.Lex(); // Eat the comma.
 
     // Following the comma we should have either an index register, or a scale
     // value. We don't support the later form, but we want to parse it
     // correctly.
     //
     // Not that even though it would be completely consistent to support syntax
-    // like "1(%eax,,1)", the assembler doesn't.
+    // like "1(%eax,,1)", the assembler doesn't. Use "eiz" or "riz" for this.
     if (getLexer().is(AsmToken::Percent)) {
-      if (ParseRegister(Op))
-        return true;
-      IndexReg = Op.getReg();
-    
+      SMLoc L;
+      if (ParseRegister(IndexReg, L, L)) return 0;
+
       if (getLexer().isNot(AsmToken::RParen)) {
         // Parse the scale amount:
         //  ::= ',' [scale-expression]
-        if (getLexer().isNot(AsmToken::Comma))
-          return true;
-        getLexer().Lex(); // Eat the comma.
+        if (getLexer().isNot(AsmToken::Comma)) {
+          Error(Parser.getTok().getLoc(),
+                "expected comma in scale expression");
+          return 0;
+        }
+        Parser.Lex(); // Eat the comma.
 
         if (getLexer().isNot(AsmToken::RParen)) {
-          SMLoc Loc = getLexer().getTok().getLoc();
+          SMLoc Loc = Parser.getTok().getLoc();
 
           int64_t ScaleVal;
           if (getParser().ParseAbsoluteExpression(ScaleVal))
-            return true;
-          
+            return 0;
+
           // Validate the scale amount.
-          if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8)
-            return Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
+          if (ScaleVal != 1 && ScaleVal != 2 && ScaleVal != 4 && ScaleVal != 8){
+            Error(Loc, "scale factor in address must be 1, 2, 4 or 8");
+            return 0;
+          }
           Scale = (unsigned)ScaleVal;
         }
       }
     } else if (getLexer().isNot(AsmToken::RParen)) {
-      // Otherwise we have the unsupported form of a scale amount without an
+      // A scale amount without an index is ignored.
       // index.
-      SMLoc Loc = getLexer().getTok().getLoc();
+      SMLoc Loc = Parser.getTok().getLoc();
 
       int64_t Value;
       if (getParser().ParseAbsoluteExpression(Value))
-        return true;
-      
-      return Error(Loc, "cannot have scale factor without index register");
+        return 0;
+
+      if (Value != 1)
+        Warning(Loc, "scale factor without index register is ignored");
+      Scale = 1;
     }
   }
-  
+
   // Ok, we've eaten the memory operand, verify we have a ')' and eat it too.
-  if (getLexer().isNot(AsmToken::RParen))
-    return Error(getLexer().getTok().getLoc(),
-                    "unexpected token in memory operand");
-  getLexer().Lex(); // Eat the ')'.
-  
-  Op = X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale);
-  return false;
+  if (getLexer().isNot(AsmToken::RParen)) {
+    Error(Parser.getTok().getLoc(), "unexpected token in memory operand");
+    return 0;
+  }
+  SMLoc MemEnd = Parser.getTok().getLoc();
+  Parser.Lex(); // Eat the ')'.
+
+  return X86Operand::CreateMem(SegReg, Disp, BaseReg, IndexReg, Scale,
+                               MemStart, MemEnd);
 }
 
-bool X86ATTAsmParser::ParseInstruction(const StringRef &Name, MCInst &Inst) {
-  SmallVector<X86Operand, 8> Operands;
+bool X86ATTAsmParser::
+ParseInstruction(StringRef Name, SMLoc NameLoc,
+                 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
+  // FIXME: Hack to recognize "sal..." and "rep..." for now. We need a way to
+  // represent alternative syntaxes in the .td file, without requiring
+  // instruction duplication.
+  StringRef PatchedName = StringSwitch<StringRef>(Name)
+    .Case("sal", "shl")
+    .Case("salb", "shlb")
+    .Case("sall", "shll")
+    .Case("salq", "shlq")
+    .Case("salw", "shlw")
+    .Case("repe", "rep")
+    .Case("repz", "rep")
+    .Case("repnz", "repne")
+    .Case("iret", "iretl")
+    .Case("sysret", "sysretl")
+    .Case("push", Is64Bit ? "pushq" : "pushl")
+    .Case("pop", Is64Bit ? "popq" : "popl")
+    .Case("pushf", Is64Bit ? "pushfq" : "pushfl")
+    .Case("popf",  Is64Bit ? "popfq"  : "popfl")
+    .Case("pushfd", "pushfl")
+    .Case("popfd",  "popfl")
+    .Case("retl", Is64Bit ? "retl" : "ret")
+    .Case("retq", Is64Bit ? "ret" : "retq")
+    .Case("setz", "sete")  .Case("setnz", "setne")
+    .Case("setc", "setb")  .Case("setna", "setbe")
+    .Case("setnae", "setb").Case("setnb", "setae")
+    .Case("setnbe", "seta").Case("setnc", "setae")
+    .Case("setng", "setle").Case("setnge", "setl")
+    .Case("setnl", "setge").Case("setnle", "setg")
+    .Case("setpe", "setp") .Case("setpo", "setnp")
+    .Case("jz", "je")  .Case("jnz", "jne")
+    .Case("jc", "jb")  .Case("jna", "jbe")
+    .Case("jnae", "jb").Case("jnb", "jae")
+    .Case("jnbe", "ja").Case("jnc", "jae")
+    .Case("jng", "jle").Case("jnge", "jl")
+    .Case("jnl", "jge").Case("jnle", "jg")
+    .Case("jpe", "jp") .Case("jpo", "jnp")
+    // Condition code aliases for 16-bit, 32-bit, 64-bit and unspec operands.
+    .Case("cmovcw",  "cmovbw") .Case("cmovcl",  "cmovbl")
+    .Case("cmovcq",  "cmovbq") .Case("cmovc",   "cmovb")
+    .Case("cmovnaew","cmovbw") .Case("cmovnael","cmovbl")
+    .Case("cmovnaeq","cmovbq") .Case("cmovnae", "cmovb")
+    .Case("cmovnaw", "cmovbew").Case("cmovnal", "cmovbel")
+    .Case("cmovnaq", "cmovbeq").Case("cmovna",  "cmovbe")
+    .Case("cmovnbw", "cmovaew").Case("cmovnbl", "cmovael")
+    .Case("cmovnbq", "cmovaeq").Case("cmovnb",  "cmovae")
+    .Case("cmovnbew","cmovaw") .Case("cmovnbel","cmoval")
+    .Case("cmovnbeq","cmovaq") .Case("cmovnbe", "cmova")
+    .Case("cmovncw", "cmovaew").Case("cmovncl", "cmovael")
+    .Case("cmovncq", "cmovaeq").Case("cmovnc",  "cmovae")
+    .Case("cmovngw", "cmovlew").Case("cmovngl", "cmovlel")
+    .Case("cmovngq", "cmovleq").Case("cmovng",  "cmovle")
+    .Case("cmovnw",  "cmovgew").Case("cmovnl",  "cmovgel")
+    .Case("cmovnq",  "cmovgeq").Case("cmovn",   "cmovge")
+    .Case("cmovngw", "cmovlew").Case("cmovngl", "cmovlel")
+    .Case("cmovngq", "cmovleq").Case("cmovng",  "cmovle")
+    .Case("cmovngew","cmovlw") .Case("cmovngel","cmovll")
+    .Case("cmovngeq","cmovlq") .Case("cmovnge", "cmovl")
+    .Case("cmovnlw", "cmovgew").Case("cmovnll", "cmovgel")
+    .Case("cmovnlq", "cmovgeq").Case("cmovnl",  "cmovge")
+    .Case("cmovnlew","cmovgw") .Case("cmovnlel","cmovgl")
+    .Case("cmovnleq","cmovgq") .Case("cmovnle", "cmovg")
+    .Case("cmovnzw", "cmovnew").Case("cmovnzl", "cmovnel")
+    .Case("cmovnzq", "cmovneq").Case("cmovnz",  "cmovne")
+    .Case("cmovzw",  "cmovew") .Case("cmovzl",  "cmovel")
+    .Case("cmovzq",  "cmoveq") .Case("cmovz",   "cmove")
+    .Case("fwait", "wait")
+    .Case("movzx", "movzb")
+    .Default(Name);
+
+  // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
+  const MCExpr *ExtraImmOp = 0;
+  if ((PatchedName.startswith("cmp") || PatchedName.startswith("vcmp")) &&
+      (PatchedName.endswith("ss") || PatchedName.endswith("sd") ||
+       PatchedName.endswith("ps") || PatchedName.endswith("pd"))) {
+    bool IsVCMP = PatchedName.startswith("vcmp");
+    unsigned SSECCIdx = IsVCMP ? 4 : 3;
+    unsigned SSEComparisonCode = StringSwitch<unsigned>(
+      PatchedName.slice(SSECCIdx, PatchedName.size() - 2))
+      .Case("eq",          0)
+      .Case("lt",          1)
+      .Case("le",          2)
+      .Case("unord",       3)
+      .Case("neq",         4)
+      .Case("nlt",         5)
+      .Case("nle",         6)
+      .Case("ord",         7)
+      .Case("eq_uq",       8)
+      .Case("nge",         9)
+      .Case("ngt",      0x0A)
+      .Case("false",    0x0B)
+      .Case("neq_oq",   0x0C)
+      .Case("ge",       0x0D)
+      .Case("gt",       0x0E)
+      .Case("true",     0x0F)
+      .Case("eq_os",    0x10)
+      .Case("lt_oq",    0x11)
+      .Case("le_oq",    0x12)
+      .Case("unord_s",  0x13)
+      .Case("neq_us",   0x14)
+      .Case("nlt_uq",   0x15)
+      .Case("nle_uq",   0x16)
+      .Case("ord_s",    0x17)
+      .Case("eq_us",    0x18)
+      .Case("nge_uq",   0x19)
+      .Case("ngt_uq",   0x1A)
+      .Case("false_os", 0x1B)
+      .Case("neq_os",   0x1C)
+      .Case("ge_oq",    0x1D)
+      .Case("gt_oq",    0x1E)
+      .Case("true_us",  0x1F)
+      .Default(~0U);
+    if (SSEComparisonCode != ~0U) {
+      ExtraImmOp = MCConstantExpr::Create(SSEComparisonCode,
+                                          getParser().getContext());
+      if (PatchedName.endswith("ss")) {
+        PatchedName = IsVCMP ? "vcmpss" : "cmpss";
+      } else if (PatchedName.endswith("sd")) {
+        PatchedName = IsVCMP ? "vcmpsd" : "cmpsd";
+      } else if (PatchedName.endswith("ps")) {
+        PatchedName = IsVCMP ? "vcmpps" : "cmpps";
+      } else {
+        assert(PatchedName.endswith("pd") && "Unexpected mnemonic!");
+        PatchedName = IsVCMP ? "vcmppd" : "cmppd";
+      }
+    }
+  }
 
-  Operands.push_back(X86Operand::CreateToken(Name));
+  // FIXME: Hack to recognize vpclmul<src1_quadword, src2_quadword>dq
+  if (PatchedName.startswith("vpclmul")) {
+    unsigned CLMULQuadWordSelect = StringSwitch<unsigned>(
+      PatchedName.slice(7, PatchedName.size() - 2))
+      .Case("lqlq", 0x00) // src1[63:0],   src2[63:0]
+      .Case("hqlq", 0x01) // src1[127:64], src2[63:0]
+      .Case("lqhq", 0x10) // src1[63:0],   src2[127:64]
+      .Case("hqhq", 0x11) // src1[127:64], src2[127:64]
+      .Default(~0U);
+    if (CLMULQuadWordSelect != ~0U) {
+      ExtraImmOp = MCConstantExpr::Create(CLMULQuadWordSelect,
+                                          getParser().getContext());
+      assert(PatchedName.endswith("dq") && "Unexpected mnemonic!");
+      PatchedName = "vpclmulqdq";
+    }
+  }
+  
+  Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
 
-  SMLoc Loc = getLexer().getTok().getLoc();
-  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+  if (ExtraImmOp)
+    Operands.push_back(X86Operand::CreateImm(ExtraImmOp, NameLoc, NameLoc));
+  
+  
+  // Determine whether this is an instruction prefix.
+  bool isPrefix =
+    PatchedName == "lock" || PatchedName == "rep" || 
+    PatchedName == "repne";
+  
+  
+  // This does the actual operand parsing.  Don't parse any more if we have a
+  // prefix juxtaposed with an operation like "lock incl 4(%rax)", because we
+  // just want to parse the "lock" as the first instruction and the "incl" as
+  // the next one.
+  if (getLexer().isNot(AsmToken::EndOfStatement) && !isPrefix) {
 
     // Parse '*' modifier.
     if (getLexer().is(AsmToken::Star)) {
-      getLexer().Lex(); // Eat the star.
-      Operands.push_back(X86Operand::CreateToken("*"));
+      SMLoc Loc = Parser.getTok().getLoc();
+      Operands.push_back(X86Operand::CreateToken("*", Loc));
+      Parser.Lex(); // Eat the star.
     }
 
     // Read the first operand.
-    Operands.push_back(X86Operand());
-    if (ParseOperand(Operands.back()))
+    if (X86Operand *Op = ParseOperand())
+      Operands.push_back(Op);
+    else {
+      Parser.EatToEndOfStatement();
       return true;
+    }
 
     while (getLexer().is(AsmToken::Comma)) {
-      getLexer().Lex();  // Eat the comma.
+      Parser.Lex();  // Eat the comma.
 
       // Parse and remember the operand.
-      Operands.push_back(X86Operand());
-      if (ParseOperand(Operands.back()))
+      if (X86Operand *Op = ParseOperand())
+        Operands.push_back(Op);
+      else {
+        Parser.EatToEndOfStatement();
         return true;
+      }
+    }
+    
+    if (getLexer().isNot(AsmToken::EndOfStatement)) {
+      Parser.EatToEndOfStatement();
+      return TokError("unexpected token in argument list");
+    }
+  }
+  
+  if (getLexer().is(AsmToken::EndOfStatement))
+    Parser.Lex(); // Consume the EndOfStatement
+
+  // FIXME: Hack to handle recognize s{hr,ar,hl} <op>, $1.  Canonicalize to
+  // "shift <op>".
+  if ((Name.startswith("shr") || Name.startswith("sar") ||
+       Name.startswith("shl")) &&
+      Operands.size() == 3) {
+    X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]);
+    if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) &&
+        cast<MCConstantExpr>(Op1->getImm())->getValue() == 1) {
+      delete Operands[1];
+      Operands.erase(Operands.begin() + 1);
     }
   }
 
-  if (!MatchInstruction(Operands, Inst))
+  // FIXME: Hack to handle recognize "in[bwl] <op>".  Canonicalize it to
+  // "inb <op>, %al".
+  if ((Name == "inb" || Name == "inw" || Name == "inl") &&
+      Operands.size() == 2) {
+    unsigned Reg;
+    if (Name[2] == 'b')
+      Reg = MatchRegisterName("al");
+    else if (Name[2] == 'w')
+      Reg = MatchRegisterName("ax");
+    else
+      Reg = MatchRegisterName("eax");
+    SMLoc Loc = Operands.back()->getEndLoc();
+    Operands.push_back(X86Operand::CreateReg(Reg, Loc, Loc));
+  }
+  
+  // FIXME: Hack to handle recognize "out[bwl] <op>".  Canonicalize it to
+  // "outb %al, <op>".
+  if ((Name == "outb" || Name == "outw" || Name == "outl") &&
+      Operands.size() == 2) {
+    unsigned Reg;
+    if (Name[3] == 'b')
+      Reg = MatchRegisterName("al");
+    else if (Name[3] == 'w')
+      Reg = MatchRegisterName("ax");
+    else
+      Reg = MatchRegisterName("eax");
+    SMLoc Loc = Operands.back()->getEndLoc();
+    Operands.push_back(X86Operand::CreateReg(Reg, Loc, Loc));
+    std::swap(Operands[1], Operands[2]);
+  }
+  
+  // FIXME: Hack to handle "f{mul*,add*,sub*,div*} $op, st(0)" the same as
+  // "f{mul*,add*,sub*,div*} $op"
+  if ((Name.startswith("fmul") || Name.startswith("fadd") ||
+       Name.startswith("fsub") || Name.startswith("fdiv")) &&
+      Operands.size() == 3 &&
+      static_cast<X86Operand*>(Operands[2])->isReg() &&
+      static_cast<X86Operand*>(Operands[2])->getReg() == X86::ST0) {
+    delete Operands[2];
+    Operands.erase(Operands.begin() + 2);
+  }
+
+  // FIXME: Hack to handle "imul <imm>, B" which is an alias for "imul <imm>, B,
+  // B".
+  if (Name.startswith("imul") && Operands.size() == 3 &&
+      static_cast<X86Operand*>(Operands[1])->isImm() &&
+      static_cast<X86Operand*>(Operands.back())->isReg()) {
+    X86Operand *Op = static_cast<X86Operand*>(Operands.back());
+    Operands.push_back(X86Operand::CreateReg(Op->getReg(), Op->getStartLoc(),
+                                             Op->getEndLoc()));
+  }
+  
+  // 'sldt <mem>' can be encoded with either sldtw or sldtq with the same
+  // effect (both store to a 16-bit mem).  Force to sldtw to avoid ambiguity
+  // errors, since its encoding is the most compact.
+  if (Name == "sldt" && Operands.size() == 2 &&
+      static_cast<X86Operand*>(Operands[1])->isMem()) {
+    delete Operands[0];
+    Operands[0] = X86Operand::CreateToken("sldtw", NameLoc);
+  }
+  
+  // The assembler accepts "xchgX <reg>, <mem>" and "xchgX <mem>, <reg>" as
+  // synonyms.  Our tables only have the "<reg>, <mem>" form, so if we see the
+  // other operand order, swap them.
+  if (Name == "xchgb" || Name == "xchgw" || Name == "xchgl" || Name == "xchgq"||
+      Name == "xchg")
+    if (Operands.size() == 3 &&
+        static_cast<X86Operand*>(Operands[1])->isMem() &&
+        static_cast<X86Operand*>(Operands[2])->isReg()) {
+      std::swap(Operands[1], Operands[2]);
+    }
+
+  // The assembler accepts "testX <reg>, <mem>" and "testX <mem>, <reg>" as
+  // synonyms.  Our tables only have the "<mem>, <reg>" form, so if we see the
+  // other operand order, swap them.
+  if (Name == "testb" || Name == "testw" || Name == "testl" || Name == "testq"||
+      Name == "test")
+    if (Operands.size() == 3 &&
+        static_cast<X86Operand*>(Operands[1])->isReg() &&
+        static_cast<X86Operand*>(Operands[2])->isMem()) {
+      std::swap(Operands[1], Operands[2]);
+    }
+  
+  return false;
+}
+
+bool X86ATTAsmParser::ParseDirective(AsmToken DirectiveID) {
+  StringRef IDVal = DirectiveID.getIdentifier();
+  if (IDVal == ".word")
+    return ParseDirectiveWord(2, DirectiveID.getLoc());
+  return true;
+}
+
+/// ParseDirectiveWord
+///  ::= .word [ expression (, expression)* ]
+bool X86ATTAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
+  if (getLexer().isNot(AsmToken::EndOfStatement)) {
+    for (;;) {
+      const MCExpr *Value;
+      if (getParser().ParseExpression(Value))
+        return true;
+
+      getParser().getStreamer().EmitValue(Value, Size, 0 /*addrspace*/);
+
+      if (getLexer().is(AsmToken::EndOfStatement))
+        break;
+
+      // FIXME: Improve diagnostic.
+      if (getLexer().isNot(AsmToken::Comma))
+        return Error(L, "unexpected token in directive");
+      Parser.Lex();
+    }
+  }
+
+  Parser.Lex();
+  return false;
+}
+
+
+bool
+X86ATTAsmParser::MatchInstruction(SMLoc IDLoc,
+                                  const SmallVectorImpl<MCParsedAsmOperand*>
+                                    &Operands,
+                                  MCInst &Inst) {
+  assert(!Operands.empty() && "Unexpect empty operand list!");
+
+  bool WasOriginallyInvalidOperand = false;
+  unsigned OrigErrorInfo;
+  
+  // First, try a direct match.
+  switch (MatchInstructionImpl(Operands, Inst, OrigErrorInfo)) {
+  case Match_Success:
     return false;
+  case Match_MissingFeature:
+    Error(IDLoc, "instruction requires a CPU feature not currently enabled");
+    return true;
+  case Match_InvalidOperand:
+    WasOriginallyInvalidOperand = true;
+    break;
+  case Match_MnemonicFail:
+    break;
+  }
 
-  // FIXME: We should give nicer diagnostics about the exact failure.
+  // FIXME: Ideally, we would only attempt suffix matches for things which are
+  // valid prefixes, and we could just infer the right unambiguous
+  // type. However, that requires substantially more matcher support than the
+  // following hack.
 
-  Error(Loc, "unrecognized instruction");
+  X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
+  assert(Op->isToken() && "Leading operand should always be a mnemonic!");
+  
+  // Change the operand to point to a temporary token.
+  StringRef Base = Op->getToken();
+  SmallString<16> Tmp;
+  Tmp += Base;
+  Tmp += ' ';
+  Op->setTokenValue(Tmp.str());
+
+  // Check for the various suffix matches.
+  Tmp[Base.size()] = 'b';
+  unsigned BErrorInfo, WErrorInfo, LErrorInfo, QErrorInfo;
+  MatchResultTy MatchB = MatchInstructionImpl(Operands, Inst, BErrorInfo);
+  Tmp[Base.size()] = 'w';
+  MatchResultTy MatchW = MatchInstructionImpl(Operands, Inst, WErrorInfo);
+  Tmp[Base.size()] = 'l';
+  MatchResultTy MatchL = MatchInstructionImpl(Operands, Inst, LErrorInfo);
+  Tmp[Base.size()] = 'q';
+  MatchResultTy MatchQ = MatchInstructionImpl(Operands, Inst, QErrorInfo);
+
+  // Restore the old token.
+  Op->setTokenValue(Base);
+
+  // If exactly one matched, then we treat that as a successful match (and the
+  // instruction will already have been filled in correctly, since the failing
+  // matches won't have modified it).
+  unsigned NumSuccessfulMatches =
+    (MatchB == Match_Success) + (MatchW == Match_Success) +
+    (MatchL == Match_Success) + (MatchQ == Match_Success);
+  if (NumSuccessfulMatches == 1)
+    return false;
+
+  // Otherwise, the match failed, try to produce a decent error message.
+
+  // If we had multiple suffix matches, then identify this as an ambiguous
+  // match.
+  if (NumSuccessfulMatches > 1) {
+    char MatchChars[4];
+    unsigned NumMatches = 0;
+    if (MatchB == Match_Success)
+      MatchChars[NumMatches++] = 'b';
+    if (MatchW == Match_Success)
+      MatchChars[NumMatches++] = 'w';
+    if (MatchL == Match_Success)
+      MatchChars[NumMatches++] = 'l';
+    if (MatchQ == Match_Success)
+      MatchChars[NumMatches++] = 'q';
+
+    SmallString<126> Msg;
+    raw_svector_ostream OS(Msg);
+    OS << "ambiguous instructions require an explicit suffix (could be ";
+    for (unsigned i = 0; i != NumMatches; ++i) {
+      if (i != 0)
+        OS << ", ";
+      if (i + 1 == NumMatches)
+        OS << "or ";
+      OS << "'" << Base << MatchChars[i] << "'";
+    }
+    OS << ")";
+    Error(IDLoc, OS.str());
+    return true;
+  }
+  
+  // Okay, we know that none of the variants matched successfully.
+  
+  // If all of the instructions reported an invalid mnemonic, then the original
+  // mnemonic was invalid.
+  if ((MatchB == Match_MnemonicFail) && (MatchW == Match_MnemonicFail) &&
+      (MatchL == Match_MnemonicFail) && (MatchQ == Match_MnemonicFail)) {
+    if (!WasOriginallyInvalidOperand) {
+      Error(IDLoc, "invalid instruction mnemonic '" + Base + "'"); 
+      return true;
+    }
+
+    // Recover location info for the operand if we know which was the problem.
+    SMLoc ErrorLoc = IDLoc;
+    if (OrigErrorInfo != ~0U) {
+      ErrorLoc = ((X86Operand*)Operands[OrigErrorInfo])->getStartLoc();
+      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
+    }
+
+    Error(ErrorLoc, "invalid operand for instruction");
+    return true;
+  }
+  
+  // If one instruction matched with a missing feature, report this as a
+  // missing feature.
+  if ((MatchB == Match_MissingFeature) + (MatchW == Match_MissingFeature) +
+      (MatchL == Match_MissingFeature) + (MatchQ == Match_MissingFeature) == 1){
+    Error(IDLoc, "instruction requires a CPU feature not currently enabled");
+    return true;
+  }
+  
+  // If one instruction matched with an invalid operand, report this as an
+  // operand failure.
+  if ((MatchB == Match_InvalidOperand) + (MatchW == Match_InvalidOperand) +
+      (MatchL == Match_InvalidOperand) + (MatchQ == Match_InvalidOperand) == 1){
+    Error(IDLoc, "invalid operand for instruction");
+    return true;
+  }
+  
+  // If all of these were an outright failure, report it in a useless way.
+  // FIXME: We should give nicer diagnostics about the exact failure.
+  Error(IDLoc, "unknown use of instruction mnemonic without a size suffix");
   return true;
 }
 
+
+extern "C" void LLVMInitializeX86AsmLexer();
+
 // Force static initialization.
 extern "C" void LLVMInitializeX86AsmParser() {
-  RegisterAsmParser<X86ATTAsmParser> X(TheX86_32Target);
-  RegisterAsmParser<X86ATTAsmParser> Y(TheX86_64Target);
+  RegisterAsmParser<X86_32ATTAsmParser> X(TheX86_32Target);
+  RegisterAsmParser<X86_64ATTAsmParser> Y(TheX86_64Target);
+  LLVMInitializeX86AsmLexer();
 }
 
+#define GET_REGISTER_MATCHER
+#define GET_MATCHER_IMPLEMENTATION
 #include "X86GenAsmMatcher.inc"