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