fix a bug where we had an implicit assumption that the
[oota-llvm.git] / lib / Target / X86 / AsmParser / X86AsmParser.cpp
index 18fb173e1c1a178b99637ca4923f70aa53f765c9..0837b69d3f91344e1e65f6c8cf9a469c2abe7a16 100644 (file)
@@ -51,21 +51,21 @@ private:
 
   bool ParseDirectiveWord(unsigned Size, SMLoc L);
 
-  bool MatchInstruction(SMLoc IDLoc,
-                        const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
-                        MCInst &Inst);
+  bool MatchAndEmitInstruction(SMLoc IDLoc,
+                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+                               MCStreamer &Out);
 
   /// @name Auto-generated Matcher Functions
   /// {
-  
+
 #define GET_ASSEMBLER_HEADER
 #include "X86GenAsmMatcher.inc"
-  
+
   /// }
 
 public:
-  X86ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
-    : TargetAsmParser(T), Parser(_Parser), TM(TM) {
+  X86ATTAsmParser(const Target &T, MCAsmParser &parser, TargetMachine &TM)
+    : TargetAsmParser(T), Parser(parser), TM(TM) {
 
     // Initialize the set of available features.
     setAvailableFeatures(ComputeAvailableFeatures(
@@ -80,16 +80,16 @@ public:
 
 class X86_32ATTAsmParser : public X86ATTAsmParser {
 public:
-  X86_32ATTAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &TM)
-    : X86ATTAsmParser(T, _Parser, TM) {
+  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) {
+  X86_64ATTAsmParser(const Target &T, MCAsmParser &Parser, TargetMachine &TM)
+    : X86ATTAsmParser(T, Parser, TM) {
     Is64Bit = true;
   }
 };
@@ -377,7 +377,7 @@ bool X86ATTAsmParser::ParseRegister(unsigned &RegNo,
   // If the match failed, try the register name as lowercase.
   if (RegNo == 0)
     RegNo = MatchRegisterName(LowercaseString(Tok.getString()));
-  
+
   // FIXME: This should be done using Requires<In32BitMode> and
   // Requires<In64BitMode> so "eiz" usage in 64-bit instructions
   // can be also checked.
@@ -620,81 +620,7 @@ X86Operand *X86ATTAsmParser::ParseMemOperand(unsigned SegReg, SMLoc MemStart) {
 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")
-    // Floating point stack cmov aliases.
-    .Case("fcmovz", "fcmove")
-    .Case("fcmova", "fcmovnbe")
-    .Case("fcmovnae", "fcmovb")
-    .Case("fcmovna", "fcmovbe")
-    .Case("fcmovae", "fcmovnb")
-    .Case("fwait", "wait")
-    .Case("movzx", "movzb")  // FIXME: Not correct.
-    .Case("fildq", "fildll")
-    .Default(Name);
+  StringRef PatchedName = Name;
 
   // FIXME: Hack to recognize cmp<comparison code>{ss,sd,ps,pd}.
   const MCExpr *ExtraImmOp = 0;
@@ -770,19 +696,20 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
       PatchedName = "vpclmulqdq";
     }
   }
-  
+
   Operands.push_back(X86Operand::CreateToken(PatchedName, NameLoc));
 
   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";
-  
-  
+    Name == "lock" || Name == "rep" ||
+    Name == "repe" || Name == "repz" ||
+    Name == "repne" || Name == "repnz";
+
+
   // 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
@@ -815,20 +742,29 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
         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
 
+  // Hack to allow 'movq <largeimm>, <reg>' as an alias for movabsq.
+  if ((Name == "movq" || Name == "mov") && Operands.size() == 3 &&
+      static_cast<X86Operand*>(Operands[2])->isReg() &&
+      static_cast<X86Operand*>(Operands[1])->isImm() &&
+      !static_cast<X86Operand*>(Operands[1])->isImmSExti64i32()) {
+    delete Operands[0];
+    Operands[0] = X86Operand::CreateToken("movabsq", NameLoc);
+  }
+
   // FIXME: Hack to handle recognize s{hr,ar,hl} $1, <op>.  Canonicalize to
   // "shift <op>".
   if ((Name.startswith("shr") || Name.startswith("sar") ||
-       Name.startswith("shl")) &&
+       Name.startswith("shl") || Name.startswith("sal")) &&
       Operands.size() == 3) {
     X86Operand *Op1 = static_cast<X86Operand*>(Operands[1]);
     if (Op1->isImm() && isa<MCConstantExpr>(Op1->getImm()) &&
@@ -837,7 +773,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
       Operands.erase(Operands.begin() + 1);
     }
   }
-  
+
   // FIXME: Hack to handle recognize "rc[lr] <op>" -> "rcl $1, <op>".
   if ((Name.startswith("rcl") || Name.startswith("rcr")) &&
       Operands.size() == 2) {
@@ -845,7 +781,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
     Operands.push_back(X86Operand::CreateImm(One, NameLoc, NameLoc));
     std::swap(Operands[1], Operands[2]);
   }
-  
+
   // FIXME: Hack to handle recognize "sh[lr]d op,op" -> "shld $1, op,op".
   if ((Name.startswith("shld") || Name.startswith("shrd")) &&
       Operands.size() == 3) {
@@ -853,7 +789,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
     Operands.insert(Operands.begin()+1,
                     X86Operand::CreateImm(One, NameLoc, NameLoc));
   }
-  
+
 
   // FIXME: Hack to handle recognize "in[bwl] <op>".  Canonicalize it to
   // "inb <op>, %al".
@@ -869,7 +805,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
     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") &&
@@ -885,7 +821,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
     Operands.push_back(X86Operand::CreateReg(Reg, Loc, Loc));
     std::swap(Operands[1], Operands[2]);
   }
-  
+
   // FIXME: Hack to handle "out[bwl]? %al, (%dx)" -> "outb %al, %dx".
   if ((Name == "outb" || Name == "outw" || Name == "outl" || Name == "out") &&
       Operands.size() == 3) {
@@ -899,7 +835,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
       delete &Op;
     }
   }
-  
+
   // 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") ||
@@ -911,16 +847,17 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
     Operands.erase(Operands.begin() + 2);
   }
 
-  // FIXME: Hack to handle "f{mul*,add*} st(0), $op" the same as
-  // "f{mul*,add*} $op", since they commute.
-  if ((Name.startswith("fmul") || Name.startswith("fadd")) &&
+  // FIXME: Hack to handle "f{mulp,addp} st(0), $op" the same as
+  // "f{mulp,addp} $op", since they commute.  We also allow fdivrp/fsubrp even
+  // though they don't commute, solely because gas does support this.
+  if ((Name=="fmulp" || Name=="faddp" || Name=="fsubrp" || Name=="fdivrp") &&
       Operands.size() == 3 &&
       static_cast<X86Operand*>(Operands[1])->isReg() &&
       static_cast<X86Operand*>(Operands[1])->getReg() == X86::ST0) {
     delete Operands[1];
     Operands.erase(Operands.begin() + 1);
   }
-  
+
   // FIXME: Hack to handle "imul <imm>, B" which is an alias for "imul <imm>, B,
   // B".
   if (Name.startswith("imul") && Operands.size() == 3 &&
@@ -930,7 +867,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
     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.
@@ -939,51 +876,32 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
     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]);
-    }
-  
+
   // The assembler accepts these instructions with no operand as a synonym for
   // an instruction acting on st(1).  e.g. "fxch" -> "fxch %st(1)".
   if ((Name == "fxch" || Name == "fucom" || Name == "fucomp" ||
-       Name == "faddp" || Name == "fsubp" || Name == "fsubrp" || 
+       Name == "faddp" || Name == "fsubp" || Name == "fsubrp" ||
        Name == "fmulp" || Name == "fdivp" || Name == "fdivrp") &&
       Operands.size() == 1) {
     Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
                                              NameLoc, NameLoc));
   }
-  
+
   // The assembler accepts these instructions with two few operands as a synonym
   // for taking %st(1),%st(0) or X, %st(0).
-  if ((Name == "fcomi" || Name == "fucomi") && Operands.size() < 3) {
+  if ((Name == "fcomi" || Name == "fucomi" || Name == "fucompi" ||
+       Name == "fcompi" ) &&
+      Operands.size() < 3) {
     if (Operands.size() == 1)
       Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(1)"),
                                                NameLoc, NameLoc));
     Operands.push_back(X86Operand::CreateReg(MatchRegisterName("st(0)"),
                                              NameLoc, NameLoc));
   }
-  
+
   // The assembler accepts various amounts of brokenness for fnstsw.
-  if (Name == "fnstsw") {
+  if (Name == "fnstsw" || Name == "fnstsww") {
     if (Operands.size() == 2 &&
         static_cast<X86Operand*>(Operands[1])->isReg()) {
       // "fnstsw al" and "fnstsw eax" -> "fnstw"
@@ -1000,50 +918,7 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
       Operands.push_back(X86Operand::CreateReg(MatchRegisterName("ax"),
                                                NameLoc, NameLoc));
   }
-  
-  // jmp $42,$5 -> ljmp, similarly for call.
-  if ((Name.startswith("call") || Name.startswith("jmp")) &&
-      Operands.size() == 3 &&
-      static_cast<X86Operand*>(Operands[1])->isImm() &&
-      static_cast<X86Operand*>(Operands[2])->isImm()) {
-    const char *NewOpName = StringSwitch<const char *>(Name)
-      .Case("jmp", "ljmp")
-      .Case("jmpw", "ljmpw")
-      .Case("jmpl", "ljmpl")
-      .Case("jmpq", "ljmpq")
-      .Case("call", "lcall")
-      .Case("callw", "lcallw")
-      .Case("calll", "lcalll")
-      .Case("callq", "lcallq")
-    .Default(0);
-    if (NewOpName) {
-      delete Operands[0];
-      Operands[0] = X86Operand::CreateToken(NewOpName, NameLoc);
-      Name = NewOpName;
-    }
-  }
-  
-  // lcall  and ljmp  -> lcalll and ljmpl
-  if ((Name == "lcall" || Name == "ljmp") && Operands.size() == 3) {
-    delete Operands[0];
-    Operands[0] = X86Operand::CreateToken(Name == "lcall" ? "lcalll" : "ljmpl",
-                                          NameLoc);
-  }
-  
-  // call foo is not ambiguous with callw.
-  if (Name == "call" && Operands.size() == 2) {
-    const char *NewName = Is64Bit ? "callq" : "calll";
-    delete Operands[0];
-    Operands[0] = X86Operand::CreateToken(NewName, NameLoc);
-    Name = NewName;
-  }
-  
-  // movsd -> movsl (when no operands are specified).
-  if (Name == "movsd" && Operands.size() == 1) {
-    delete Operands[0];
-    Operands[0] = X86Operand::CreateToken("movsl", NameLoc);
-  }
-  
+
   // fstp <mem> -> fstps <mem>.  Without this, we'll default to fstpl due to
   // suffix searching.
   if (Name == "fstp" && Operands.size() == 2 &&
@@ -1051,66 +926,59 @@ ParseInstruction(StringRef Name, SMLoc NameLoc,
     delete Operands[0];
     Operands[0] = X86Operand::CreateToken("fstps", NameLoc);
   }
-  
-  
-  // "clr <reg>" -> "xor <reg>, <reg>".
-  if ((Name == "clrb" || Name == "clrw" || Name == "clrl" || Name == "clrq" ||
-       Name == "clr") && Operands.size() == 2 &&
-      static_cast<X86Operand*>(Operands[1])->isReg()) {
-    unsigned RegNo = static_cast<X86Operand*>(Operands[1])->getReg();
-    Operands.push_back(X86Operand::CreateReg(RegNo, NameLoc, NameLoc));
-    delete Operands[0];
-    Operands[0] = X86Operand::CreateToken("xor", NameLoc);
-  }
-  
-  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();
-    }
+  // FIXME: Hack to handle recognize "aa[dm]" -> "aa[dm] $0xA".
+  if ((Name.startswith("aad") || Name.startswith("aam")) &&
+      Operands.size() == 1) {
+    const MCExpr *A = MCConstantExpr::Create(0xA, getParser().getContext());
+    Operands.push_back(X86Operand::CreateImm(A, NameLoc, NameLoc));
   }
 
-  Parser.Lex();
   return false;
 }
 
-
 bool X86ATTAsmParser::
-MatchInstruction(SMLoc IDLoc,
-                 const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
-                 MCInst &Inst) {
+MatchAndEmitInstruction(SMLoc IDLoc,
+                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
+                        MCStreamer &Out) {
   assert(!Operands.empty() && "Unexpect empty operand list!");
+  X86Operand *Op = static_cast<X86Operand*>(Operands[0]);
+  assert(Op->isToken() && "Leading operand should always be a mnemonic!");
+
+  // First, handle aliases that expand to multiple instructions.
+  // FIXME: This should be replaced with a real .td file alias mechanism.
+  if (Op->getToken() == "fstsw" || Op->getToken() == "fstcw" ||
+      Op->getToken() == "fstsww" || Op->getToken() == "fstcww" ||
+      Op->getToken() == "finit" || Op->getToken() == "fsave" ||
+      Op->getToken() == "fstenv" || Op->getToken() == "fclex") {
+    MCInst Inst;
+    Inst.setOpcode(X86::WAIT);
+    Out.EmitInstruction(Inst);
+
+    const char *Repl =
+      StringSwitch<const char*>(Op->getToken())
+        .Case("finit",  "fninit")
+        .Case("fsave",  "fnsave")
+        .Case("fstcw",  "fnstcw")
+        .Case("fstcww",  "fnstcw")
+        .Case("fstenv", "fnstenv")
+        .Case("fstsw",  "fnstsw")
+        .Case("fstsww", "fnstsw")
+        .Case("fclex",  "fnclex")
+        .Default(0);
+    assert(Repl && "Unknown wait-prefixed instruction");
+    delete Operands[0];
+    Operands[0] = X86Operand::CreateToken(Repl, IDLoc);
+  }
 
   bool WasOriginallyInvalidOperand = false;
   unsigned OrigErrorInfo;
-  
+  MCInst Inst;
+
   // First, try a direct match.
   switch (MatchInstructionImpl(Operands, Inst, OrigErrorInfo)) {
   case Match_Success:
+    Out.EmitInstruction(Inst);
     return false;
   case Match_MissingFeature:
     Error(IDLoc, "instruction requires a CPU feature not currently enabled");
@@ -1127,9 +995,6 @@ MatchInstruction(SMLoc IDLoc,
   // type. However, that requires substantially more matcher support than the
   // following hack.
 
-  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;
@@ -1157,8 +1022,10 @@ MatchInstruction(SMLoc IDLoc,
   unsigned NumSuccessfulMatches =
     (MatchB == Match_Success) + (MatchW == Match_Success) +
     (MatchL == Match_Success) + (MatchQ == Match_Success);
-  if (NumSuccessfulMatches == 1)
+  if (NumSuccessfulMatches == 1) {
+    Out.EmitInstruction(Inst);
     return false;
+  }
 
   // Otherwise, the match failed, try to produce a decent error message.
 
@@ -1190,15 +1057,15 @@ MatchInstruction(SMLoc IDLoc,
     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 + "'"); 
+      Error(IDLoc, "invalid instruction mnemonic '" + Base + "'");
       return true;
     }
 
@@ -1207,14 +1074,14 @@ MatchInstruction(SMLoc IDLoc,
     if (OrigErrorInfo != ~0U) {
       if (OrigErrorInfo >= Operands.size())
         return Error(IDLoc, "too few operands for instruction");
-      
+
       ErrorLoc = ((X86Operand*)Operands[OrigErrorInfo])->getStartLoc();
       if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
     }
 
     return Error(ErrorLoc, "invalid operand for instruction");
   }
-  
+
   // If one instruction matched with a missing feature, report this as a
   // missing feature.
   if ((MatchB == Match_MissingFeature) + (MatchW == Match_MissingFeature) +
@@ -1222,7 +1089,7 @@ MatchInstruction(SMLoc IDLoc,
     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) +
@@ -1230,7 +1097,7 @@ MatchInstruction(SMLoc IDLoc,
     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");
@@ -1238,6 +1105,41 @@ MatchInstruction(SMLoc IDLoc,
 }
 
 
+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;
+}
+
+
+
+
 extern "C" void LLVMInitializeX86AsmLexer();
 
 // Force static initialization.