MC/ARM: Split mnemonic on '.' characters.
[oota-llvm.git] / lib / Target / ARM / AsmParser / ARMAsmParser.cpp
1 //===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2 //
3 //                     The LLVM Compiler Infrastructure
4 //
5 // This file is distributed under the University of Illinois Open Source
6 // License. See LICENSE.TXT for details.
7 //
8 //===----------------------------------------------------------------------===//
9
10 #include "ARM.h"
11 #include "ARMSubtarget.h"
12 #include "llvm/MC/MCParser/MCAsmLexer.h"
13 #include "llvm/MC/MCParser/MCAsmParser.h"
14 #include "llvm/MC/MCParser/MCParsedAsmOperand.h"
15 #include "llvm/MC/MCStreamer.h"
16 #include "llvm/MC/MCExpr.h"
17 #include "llvm/MC/MCInst.h"
18 #include "llvm/Target/TargetRegistry.h"
19 #include "llvm/Target/TargetAsmParser.h"
20 #include "llvm/Support/Compiler.h"
21 #include "llvm/Support/SourceMgr.h"
22 #include "llvm/Support/raw_ostream.h"
23 #include "llvm/ADT/OwningPtr.h"
24 #include "llvm/ADT/SmallVector.h"
25 #include "llvm/ADT/Twine.h"
26 using namespace llvm;
27
28 namespace {
29 struct ARMOperand;
30
31 // The shift types for register controlled shifts in arm memory addressing
32 enum ShiftType {
33   Lsl,
34   Lsr,
35   Asr,
36   Ror,
37   Rrx
38 };
39
40 class ARMAsmParser : public TargetAsmParser {
41   MCAsmParser &Parser;
42   TargetMachine &TM;
43
44 private:
45   MCAsmParser &getParser() const { return Parser; }
46
47   MCAsmLexer &getLexer() const { return Parser.getLexer(); }
48
49   void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
50
51   bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
52
53   bool MaybeParseRegister(OwningPtr<ARMOperand> &Op, bool ParseWriteBack);
54
55   bool ParseRegisterList(OwningPtr<ARMOperand> &Op);
56
57   bool ParseMemory(OwningPtr<ARMOperand> &Op);
58
59   bool ParseMemoryOffsetReg(bool &Negative,
60                             bool &OffsetRegShifted,
61                             enum ShiftType &ShiftType,
62                             const MCExpr *&ShiftAmount,
63                             const MCExpr *&Offset,
64                             bool &OffsetIsReg,
65                             int &OffsetRegNum,
66                             SMLoc &E);
67
68   bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
69
70   bool ParseOperand(OwningPtr<ARMOperand> &Op);
71
72   bool ParseDirectiveWord(unsigned Size, SMLoc L);
73
74   bool ParseDirectiveThumb(SMLoc L);
75
76   bool ParseDirectiveThumbFunc(SMLoc L);
77
78   bool ParseDirectiveCode(SMLoc L);
79
80   bool ParseDirectiveSyntax(SMLoc L);
81
82   /// @name Auto-generated Match Functions
83   /// {
84
85   unsigned ComputeAvailableFeatures(const ARMSubtarget *Subtarget) const;
86
87   bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
88                         MCInst &Inst);
89
90   /// }
91
92
93 public:
94   ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
95     : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
96
97   virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
98                                 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
99
100   virtual bool ParseDirective(AsmToken DirectiveID);
101 };
102   
103 /// ARMOperand - Instances of this class represent a parsed ARM machine
104 /// instruction.
105 struct ARMOperand : public MCParsedAsmOperand {
106 private:
107   ARMOperand() {}
108 public:
109   enum KindTy {
110     CondCode,
111     Immediate,
112     Memory,
113     Register,
114     Token
115   } Kind;
116
117   SMLoc StartLoc, EndLoc;
118
119   union {
120     struct {
121       ARMCC::CondCodes Val;
122     } CC;
123
124     struct {
125       const char *Data;
126       unsigned Length;
127     } Tok;
128
129     struct {
130       unsigned RegNum;
131       bool Writeback;
132     } Reg;
133
134     struct {
135       const MCExpr *Val;
136     } Imm;
137     
138     // This is for all forms of ARM address expressions
139     struct {
140       unsigned BaseRegNum;
141       unsigned OffsetRegNum; // used when OffsetIsReg is true
142       const MCExpr *Offset; // used when OffsetIsReg is false
143       const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
144       enum ShiftType ShiftType;  // used when OffsetRegShifted is true
145       unsigned
146         OffsetRegShifted : 1, // only used when OffsetIsReg is true
147         Preindexed : 1,
148         Postindexed : 1,
149         OffsetIsReg : 1,
150         Negative : 1, // only used when OffsetIsReg is true
151         Writeback : 1;
152     } Mem;
153
154   };
155   
156   ARMOperand(KindTy K, SMLoc S, SMLoc E)
157     : Kind(K), StartLoc(S), EndLoc(E) {}
158   
159   ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
160     Kind = o.Kind;
161     StartLoc = o.StartLoc;
162     EndLoc = o.EndLoc;
163     switch (Kind) {
164     case CondCode:
165       CC = o.CC;
166       break;
167     case Token:
168       Tok = o.Tok;
169       break;
170     case Register:
171       Reg = o.Reg;
172       break;
173     case Immediate:
174       Imm = o.Imm;
175       break;
176     case Memory:
177       Mem = o.Mem;
178       break;
179     }
180   }
181   
182   /// getStartLoc - Get the location of the first token of this operand.
183   SMLoc getStartLoc() const { return StartLoc; }
184   /// getEndLoc - Get the location of the last token of this operand.
185   SMLoc getEndLoc() const { return EndLoc; }
186
187   ARMCC::CondCodes getCondCode() const {
188     assert(Kind == CondCode && "Invalid access!");
189     return CC.Val;
190   }
191
192   StringRef getToken() const {
193     assert(Kind == Token && "Invalid access!");
194     return StringRef(Tok.Data, Tok.Length);
195   }
196
197   unsigned getReg() const {
198     assert(Kind == Register && "Invalid access!");
199     return Reg.RegNum;
200   }
201
202   const MCExpr *getImm() const {
203     assert(Kind == Immediate && "Invalid access!");
204     return Imm.Val;
205   }
206
207   bool isCondCode() const { return Kind == CondCode; }
208
209   bool isImm() const { return Kind == Immediate; }
210
211   bool isReg() const { return Kind == Register; }
212
213   bool isToken() const {return Kind == Token; }
214
215   void addExpr(MCInst &Inst, const MCExpr *Expr) const {
216     // Add as immediates when possible.
217     if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
218       Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
219     else
220       Inst.addOperand(MCOperand::CreateExpr(Expr));
221   }
222
223   void addCondCodeOperands(MCInst &Inst, unsigned N) const {
224     assert(N == 1 && "Invalid number of operands!");
225     Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
226   }
227
228   void addRegOperands(MCInst &Inst, unsigned N) const {
229     assert(N == 1 && "Invalid number of operands!");
230     Inst.addOperand(MCOperand::CreateReg(getReg()));
231   }
232
233   void addImmOperands(MCInst &Inst, unsigned N) const {
234     assert(N == 1 && "Invalid number of operands!");
235     addExpr(Inst, getImm());
236   }
237
238   virtual void dump(raw_ostream &OS) const;
239
240   static void CreateToken(OwningPtr<ARMOperand> &Op, StringRef Str,
241                           SMLoc S) {
242     Op.reset(new ARMOperand);
243     Op->Kind = Token;
244     Op->Tok.Data = Str.data();
245     Op->Tok.Length = Str.size();
246     Op->StartLoc = S;
247     Op->EndLoc = S;
248   }
249
250   static void CreateReg(OwningPtr<ARMOperand> &Op, unsigned RegNum, 
251                         bool Writeback, SMLoc S, SMLoc E) {
252     Op.reset(new ARMOperand);
253     Op->Kind = Register;
254     Op->Reg.RegNum = RegNum;
255     Op->Reg.Writeback = Writeback;
256     
257     Op->StartLoc = S;
258     Op->EndLoc = E;
259   }
260
261   static void CreateImm(OwningPtr<ARMOperand> &Op, const MCExpr *Val,
262                         SMLoc S, SMLoc E) {
263     Op.reset(new ARMOperand);
264     Op->Kind = Immediate;
265     Op->Imm.Val = Val;
266     
267     Op->StartLoc = S;
268     Op->EndLoc = E;
269   }
270
271   static void CreateMem(OwningPtr<ARMOperand> &Op,
272                         unsigned BaseRegNum, bool OffsetIsReg,
273                         const MCExpr *Offset, unsigned OffsetRegNum,
274                         bool OffsetRegShifted, enum ShiftType ShiftType,
275                         const MCExpr *ShiftAmount, bool Preindexed,
276                         bool Postindexed, bool Negative, bool Writeback,
277                         SMLoc S, SMLoc E) {
278     Op.reset(new ARMOperand);
279     Op->Kind = Memory;
280     Op->Mem.BaseRegNum = BaseRegNum;
281     Op->Mem.OffsetIsReg = OffsetIsReg;
282     Op->Mem.Offset = Offset;
283     Op->Mem.OffsetRegNum = OffsetRegNum;
284     Op->Mem.OffsetRegShifted = OffsetRegShifted;
285     Op->Mem.ShiftType = ShiftType;
286     Op->Mem.ShiftAmount = ShiftAmount;
287     Op->Mem.Preindexed = Preindexed;
288     Op->Mem.Postindexed = Postindexed;
289     Op->Mem.Negative = Negative;
290     Op->Mem.Writeback = Writeback;
291     
292     Op->StartLoc = S;
293     Op->EndLoc = E;
294   }
295 };
296
297 } // end anonymous namespace.
298
299 void ARMOperand::dump(raw_ostream &OS) const {
300   switch (Kind) {
301   case CondCode:
302     OS << ARMCondCodeToString(getCondCode());
303     break;
304   case Immediate:
305     getImm()->print(OS);
306     break;
307   case Memory:
308     OS << "<memory>";
309     break;
310   case Register:
311     OS << "<register " << getReg() << ">";
312     break;
313   case Token:
314     OS << "'" << getToken() << "'";
315     break;
316   }
317 }
318
319 /// @name Auto-generated Match Functions
320 /// {
321
322 static unsigned MatchRegisterName(StringRef Name);
323
324 /// }
325
326 /// Try to parse a register name.  The token must be an Identifier when called,
327 /// and if it is a register name a Reg operand is created, the token is eaten
328 /// and false is returned.  Else true is returned and no token is eaten.
329 /// TODO this is likely to change to allow different register types and or to
330 /// parse for a specific register type.
331 bool ARMAsmParser::MaybeParseRegister
332   (OwningPtr<ARMOperand> &Op, bool ParseWriteBack) {
333   SMLoc S, E;
334   const AsmToken &Tok = Parser.getTok();
335   assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
336
337   // FIXME: Validate register for the current architecture; we have to do
338   // validation later, so maybe there is no need for this here.
339   int RegNum;
340
341   RegNum = MatchRegisterName(Tok.getString());
342   if (RegNum == -1)
343     return true;
344   
345   S = Tok.getLoc();
346   
347   Parser.Lex(); // Eat identifier token.
348     
349   E = Parser.getTok().getLoc();
350
351   bool Writeback = false;
352   if (ParseWriteBack) {
353     const AsmToken &ExclaimTok = Parser.getTok();
354     if (ExclaimTok.is(AsmToken::Exclaim)) {
355       E = ExclaimTok.getLoc();
356       Writeback = true;
357       Parser.Lex(); // Eat exclaim token
358     }
359   }
360
361   ARMOperand::CreateReg(Op, RegNum, Writeback, S, E);
362
363   return false;
364 }
365
366 /// Parse a register list, return false if successful else return true or an 
367 /// error.  The first token must be a '{' when called.
368 bool ARMAsmParser::ParseRegisterList(OwningPtr<ARMOperand> &Op) {
369   SMLoc S, E;
370   assert(Parser.getTok().is(AsmToken::LCurly) &&
371          "Token is not an Left Curly Brace");
372   S = Parser.getTok().getLoc();
373   Parser.Lex(); // Eat left curly brace token.
374
375   const AsmToken &RegTok = Parser.getTok();
376   SMLoc RegLoc = RegTok.getLoc();
377   if (RegTok.isNot(AsmToken::Identifier))
378     return Error(RegLoc, "register expected");
379   int RegNum = MatchRegisterName(RegTok.getString());
380   if (RegNum == -1)
381     return Error(RegLoc, "register expected");
382   Parser.Lex(); // Eat identifier token.
383   unsigned RegList = 1 << RegNum;
384
385   int HighRegNum = RegNum;
386   // TODO ranges like "{Rn-Rm}"
387   while (Parser.getTok().is(AsmToken::Comma)) {
388     Parser.Lex(); // Eat comma token.
389
390     const AsmToken &RegTok = Parser.getTok();
391     SMLoc RegLoc = RegTok.getLoc();
392     if (RegTok.isNot(AsmToken::Identifier))
393       return Error(RegLoc, "register expected");
394     int RegNum = MatchRegisterName(RegTok.getString());
395     if (RegNum == -1)
396       return Error(RegLoc, "register expected");
397
398     if (RegList & (1 << RegNum))
399       Warning(RegLoc, "register duplicated in register list");
400     else if (RegNum <= HighRegNum)
401       Warning(RegLoc, "register not in ascending order in register list");
402     RegList |= 1 << RegNum;
403     HighRegNum = RegNum;
404
405     Parser.Lex(); // Eat identifier token.
406   }
407   const AsmToken &RCurlyTok = Parser.getTok();
408   if (RCurlyTok.isNot(AsmToken::RCurly))
409     return Error(RCurlyTok.getLoc(), "'}' expected");
410   E = RCurlyTok.getLoc();
411   Parser.Lex(); // Eat left curly brace token.
412
413   return false;
414 }
415
416 /// Parse an arm memory expression, return false if successful else return true
417 /// or an error.  The first token must be a '[' when called.
418 /// TODO Only preindexing and postindexing addressing are started, unindexed
419 /// with option, etc are still to do.
420 bool ARMAsmParser::ParseMemory(OwningPtr<ARMOperand> &Op) {
421   SMLoc S, E;
422   assert(Parser.getTok().is(AsmToken::LBrac) &&
423          "Token is not an Left Bracket");
424   S = Parser.getTok().getLoc();
425   Parser.Lex(); // Eat left bracket token.
426
427   const AsmToken &BaseRegTok = Parser.getTok();
428   if (BaseRegTok.isNot(AsmToken::Identifier))
429     return Error(BaseRegTok.getLoc(), "register expected");
430   if (MaybeParseRegister(Op, false))
431     return Error(BaseRegTok.getLoc(), "register expected");
432   int BaseRegNum = Op->getReg();
433
434   bool Preindexed = false;
435   bool Postindexed = false;
436   bool OffsetIsReg = false;
437   bool Negative = false;
438   bool Writeback = false;
439
440   // First look for preindexed address forms, that is after the "[Rn" we now
441   // have to see if the next token is a comma.
442   const AsmToken &Tok = Parser.getTok();
443   if (Tok.is(AsmToken::Comma)) {
444     Preindexed = true;
445     Parser.Lex(); // Eat comma token.
446     int OffsetRegNum;
447     bool OffsetRegShifted;
448     enum ShiftType ShiftType;
449     const MCExpr *ShiftAmount;
450     const MCExpr *Offset;
451     if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
452                             Offset, OffsetIsReg, OffsetRegNum, E))
453       return true;
454     const AsmToken &RBracTok = Parser.getTok();
455     if (RBracTok.isNot(AsmToken::RBrac))
456       return Error(RBracTok.getLoc(), "']' expected");
457     E = RBracTok.getLoc();
458     Parser.Lex(); // Eat right bracket token.
459
460     const AsmToken &ExclaimTok = Parser.getTok();
461     if (ExclaimTok.is(AsmToken::Exclaim)) {
462       E = ExclaimTok.getLoc();
463       Writeback = true;
464       Parser.Lex(); // Eat exclaim token
465     }
466     ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
467                           OffsetRegShifted, ShiftType, ShiftAmount,
468                           Preindexed, Postindexed, Negative, Writeback, S, E);
469     return false;
470   }
471   // The "[Rn" we have so far was not followed by a comma.
472   else if (Tok.is(AsmToken::RBrac)) {
473     // This is a post indexing addressing forms, that is a ']' follows after
474     // the "[Rn".
475     Postindexed = true;
476     Writeback = true;
477     E = Tok.getLoc();
478     Parser.Lex(); // Eat right bracket token.
479
480     int OffsetRegNum = 0;
481     bool OffsetRegShifted = false;
482     enum ShiftType ShiftType;
483     const MCExpr *ShiftAmount;
484     const MCExpr *Offset;
485
486     const AsmToken &NextTok = Parser.getTok();
487     if (NextTok.isNot(AsmToken::EndOfStatement)) {
488       if (NextTok.isNot(AsmToken::Comma))
489         return Error(NextTok.getLoc(), "',' expected");
490       Parser.Lex(); // Eat comma token.
491       if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
492                               ShiftAmount, Offset, OffsetIsReg, OffsetRegNum, 
493                               E))
494         return true;
495     }
496
497     ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
498                           OffsetRegShifted, ShiftType, ShiftAmount,
499                           Preindexed, Postindexed, Negative, Writeback, S, E);
500     return false;
501   }
502
503   return true;
504 }
505
506 /// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
507 /// we will parse the following (were +/- means that a plus or minus is
508 /// optional):
509 ///   +/-Rm
510 ///   +/-Rm, shift
511 ///   #offset
512 /// we return false on success or an error otherwise.
513 bool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
514                                         bool &OffsetRegShifted,
515                                         enum ShiftType &ShiftType,
516                                         const MCExpr *&ShiftAmount,
517                                         const MCExpr *&Offset,
518                                         bool &OffsetIsReg,
519                                         int &OffsetRegNum,
520                                         SMLoc &E) {
521   OwningPtr<ARMOperand> Op;
522   Negative = false;
523   OffsetRegShifted = false;
524   OffsetIsReg = false;
525   OffsetRegNum = -1;
526   const AsmToken &NextTok = Parser.getTok();
527   E = NextTok.getLoc();
528   if (NextTok.is(AsmToken::Plus))
529     Parser.Lex(); // Eat plus token.
530   else if (NextTok.is(AsmToken::Minus)) {
531     Negative = true;
532     Parser.Lex(); // Eat minus token
533   }
534   // See if there is a register following the "[Rn," or "[Rn]," we have so far.
535   const AsmToken &OffsetRegTok = Parser.getTok();
536   if (OffsetRegTok.is(AsmToken::Identifier)) {
537     OffsetIsReg = !MaybeParseRegister(Op, false);
538     if (OffsetIsReg) {
539       E = Op->getEndLoc();
540       OffsetRegNum = Op->getReg();
541     }
542   }
543   // If we parsed a register as the offset then their can be a shift after that
544   if (OffsetRegNum != -1) {
545     // Look for a comma then a shift
546     const AsmToken &Tok = Parser.getTok();
547     if (Tok.is(AsmToken::Comma)) {
548       Parser.Lex(); // Eat comma token.
549
550       const AsmToken &Tok = Parser.getTok();
551       if (ParseShift(ShiftType, ShiftAmount, E))
552         return Error(Tok.getLoc(), "shift expected");
553       OffsetRegShifted = true;
554     }
555   }
556   else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
557     // Look for #offset following the "[Rn," or "[Rn],"
558     const AsmToken &HashTok = Parser.getTok();
559     if (HashTok.isNot(AsmToken::Hash))
560       return Error(HashTok.getLoc(), "'#' expected");
561     
562     Parser.Lex(); // Eat hash token.
563
564     if (getParser().ParseExpression(Offset))
565      return true;
566     E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
567   }
568   return false;
569 }
570
571 /// ParseShift as one of these two:
572 ///   ( lsl | lsr | asr | ror ) , # shift_amount
573 ///   rrx
574 /// and returns true if it parses a shift otherwise it returns false.
575 bool ARMAsmParser::ParseShift(ShiftType &St, 
576                               const MCExpr *&ShiftAmount, 
577                               SMLoc &E) {
578   const AsmToken &Tok = Parser.getTok();
579   if (Tok.isNot(AsmToken::Identifier))
580     return true;
581   StringRef ShiftName = Tok.getString();
582   if (ShiftName == "lsl" || ShiftName == "LSL")
583     St = Lsl;
584   else if (ShiftName == "lsr" || ShiftName == "LSR")
585     St = Lsr;
586   else if (ShiftName == "asr" || ShiftName == "ASR")
587     St = Asr;
588   else if (ShiftName == "ror" || ShiftName == "ROR")
589     St = Ror;
590   else if (ShiftName == "rrx" || ShiftName == "RRX")
591     St = Rrx;
592   else
593     return true;
594   Parser.Lex(); // Eat shift type token.
595
596   // Rrx stands alone.
597   if (St == Rrx)
598     return false;
599
600   // Otherwise, there must be a '#' and a shift amount.
601   const AsmToken &HashTok = Parser.getTok();
602   if (HashTok.isNot(AsmToken::Hash))
603     return Error(HashTok.getLoc(), "'#' expected");
604   Parser.Lex(); // Eat hash token.
605
606   if (getParser().ParseExpression(ShiftAmount))
607     return true;
608
609   return false;
610 }
611
612 /// Parse a arm instruction operand.  For now this parses the operand regardless
613 /// of the mnemonic.
614 bool ARMAsmParser::ParseOperand(OwningPtr<ARMOperand> &Op) {
615   SMLoc S, E;
616   
617   switch (getLexer().getKind()) {
618   case AsmToken::Identifier:
619     if (!MaybeParseRegister(Op, true))
620       return false;
621     // This was not a register so parse other operands that start with an
622     // identifier (like labels) as expressions and create them as immediates.
623     const MCExpr *IdVal;
624     S = Parser.getTok().getLoc();
625     if (getParser().ParseExpression(IdVal))
626       return true;
627     E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
628     ARMOperand::CreateImm(Op, IdVal, S, E);
629     return false;
630   case AsmToken::LBrac:
631     return ParseMemory(Op);
632   case AsmToken::LCurly:
633     return ParseRegisterList(Op);
634   case AsmToken::Hash:
635     // #42 -> immediate.
636     // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
637     S = Parser.getTok().getLoc();
638     Parser.Lex();
639     const MCExpr *ImmVal;
640     if (getParser().ParseExpression(ImmVal))
641       return true;
642     E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
643     ARMOperand::CreateImm(Op, ImmVal, S, E);
644     return false;
645   default:
646     return Error(Parser.getTok().getLoc(), "unexpected token in operand");
647   }
648 }
649
650 /// Parse an arm instruction mnemonic followed by its operands.
651 bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
652                                SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
653   OwningPtr<ARMOperand> Op;
654
655   // Create the leading tokens for the mnemonic, split by '.' characters.
656   size_t Start = 0, Next = Name.find('.');
657   StringRef Head = Name.slice(Start, Next);
658
659   ARMOperand::CreateToken(Op, Head, NameLoc);
660   Operands.push_back(Op.take());
661
662   while (Next != StringRef::npos) {
663     Start = Next;
664     Next = Name.find('.', Start + 1);
665     Head = Name.slice(Start, Next);
666
667     ARMOperand::CreateToken(Op, Head, NameLoc);
668     Operands.push_back(Op.take());
669   }
670
671   // Read the remaining operands.
672   if (getLexer().isNot(AsmToken::EndOfStatement)) {
673     // Read the first operand.
674     OwningPtr<ARMOperand> Op;
675     if (ParseOperand(Op)) return true;
676     Operands.push_back(Op.take());
677
678     while (getLexer().is(AsmToken::Comma)) {
679       Parser.Lex();  // Eat the comma.
680
681       // Parse and remember the operand.
682       if (ParseOperand(Op)) return true;
683       Operands.push_back(Op.take());
684     }
685   }
686   return false;
687 }
688
689 /// ParseDirective parses the arm specific directives
690 bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
691   StringRef IDVal = DirectiveID.getIdentifier();
692   if (IDVal == ".word")
693     return ParseDirectiveWord(4, DirectiveID.getLoc());
694   else if (IDVal == ".thumb")
695     return ParseDirectiveThumb(DirectiveID.getLoc());
696   else if (IDVal == ".thumb_func")
697     return ParseDirectiveThumbFunc(DirectiveID.getLoc());
698   else if (IDVal == ".code")
699     return ParseDirectiveCode(DirectiveID.getLoc());
700   else if (IDVal == ".syntax")
701     return ParseDirectiveSyntax(DirectiveID.getLoc());
702   return true;
703 }
704
705 /// ParseDirectiveWord
706 ///  ::= .word [ expression (, expression)* ]
707 bool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
708   if (getLexer().isNot(AsmToken::EndOfStatement)) {
709     for (;;) {
710       const MCExpr *Value;
711       if (getParser().ParseExpression(Value))
712         return true;
713
714       getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
715
716       if (getLexer().is(AsmToken::EndOfStatement))
717         break;
718       
719       // FIXME: Improve diagnostic.
720       if (getLexer().isNot(AsmToken::Comma))
721         return Error(L, "unexpected token in directive");
722       Parser.Lex();
723     }
724   }
725
726   Parser.Lex();
727   return false;
728 }
729
730 /// ParseDirectiveThumb
731 ///  ::= .thumb
732 bool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
733   if (getLexer().isNot(AsmToken::EndOfStatement))
734     return Error(L, "unexpected token in directive");
735   Parser.Lex();
736
737   // TODO: set thumb mode
738   // TODO: tell the MC streamer the mode
739   // getParser().getStreamer().Emit???();
740   return false;
741 }
742
743 /// ParseDirectiveThumbFunc
744 ///  ::= .thumbfunc symbol_name
745 bool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
746   const AsmToken &Tok = Parser.getTok();
747   if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
748     return Error(L, "unexpected token in .syntax directive");
749   StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
750   Parser.Lex(); // Consume the identifier token.
751
752   if (getLexer().isNot(AsmToken::EndOfStatement))
753     return Error(L, "unexpected token in directive");
754   Parser.Lex();
755
756   // TODO: mark symbol as a thumb symbol
757   // getParser().getStreamer().Emit???();
758   return false;
759 }
760
761 /// ParseDirectiveSyntax
762 ///  ::= .syntax unified | divided
763 bool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
764   const AsmToken &Tok = Parser.getTok();
765   if (Tok.isNot(AsmToken::Identifier))
766     return Error(L, "unexpected token in .syntax directive");
767   StringRef Mode = Tok.getString();
768   if (Mode == "unified" || Mode == "UNIFIED")
769     Parser.Lex();
770   else if (Mode == "divided" || Mode == "DIVIDED")
771     Parser.Lex();
772   else
773     return Error(L, "unrecognized syntax mode in .syntax directive");
774
775   if (getLexer().isNot(AsmToken::EndOfStatement))
776     return Error(Parser.getTok().getLoc(), "unexpected token in directive");
777   Parser.Lex();
778
779   // TODO tell the MC streamer the mode
780   // getParser().getStreamer().Emit???();
781   return false;
782 }
783
784 /// ParseDirectiveCode
785 ///  ::= .code 16 | 32
786 bool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
787   const AsmToken &Tok = Parser.getTok();
788   if (Tok.isNot(AsmToken::Integer))
789     return Error(L, "unexpected token in .code directive");
790   int64_t Val = Parser.getTok().getIntVal();
791   if (Val == 16)
792     Parser.Lex();
793   else if (Val == 32)
794     Parser.Lex();
795   else
796     return Error(L, "invalid operand to .code directive");
797
798   if (getLexer().isNot(AsmToken::EndOfStatement))
799     return Error(Parser.getTok().getLoc(), "unexpected token in directive");
800   Parser.Lex();
801
802   // TODO tell the MC streamer the mode
803   // getParser().getStreamer().Emit???();
804   return false;
805 }
806
807 extern "C" void LLVMInitializeARMAsmLexer();
808
809 /// Force static initialization.
810 extern "C" void LLVMInitializeARMAsmParser() {
811   RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
812   RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
813   LLVMInitializeARMAsmLexer();
814 }
815
816 #include "ARMGenAsmMatcher.inc"