ARMAsmParser.cpp revision 3483acabf012b847b13b969ebd9ce5c4d16d9eb7
1ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby//
3ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby//                     The LLVM Compiler Infrastructure
4ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby//
5ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby// This file is distributed under the University of Illinois Open Source
6ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby// License. See LICENSE.TXT for details.
7ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby//
8ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby//===----------------------------------------------------------------------===//
9ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
10ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "ARM.h"
113483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar#include "ARMSubtarget.h"
12c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/MC/MCParser/MCAsmLexer.h"
13c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/MC/MCParser/MCAsmParser.h"
14c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
15ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/MC/MCStreamer.h"
16ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/MC/MCExpr.h"
17ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/MC/MCInst.h"
18ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/Target/TargetRegistry.h"
19ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/Target/TargetAsmParser.h"
20c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/Support/Compiler.h"
21c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/Support/SourceMgr.h"
22762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan#include "llvm/ADT/OwningPtr.h"
23c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/ADT/SmallVector.h"
24c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/ADT/Twine.h"
25ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbyusing namespace llvm;
26ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
27ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbynamespace {
28ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbystruct ARMOperand;
29ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
30a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby// The shift types for register controlled shifts in arm memory addressing
31a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderbyenum ShiftType {
32a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Lsl,
33a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Lsr,
34a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Asr,
35a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Ror,
36a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Rrx
37a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby};
38a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
39ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbyclass ARMAsmParser : public TargetAsmParser {
40ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  MCAsmParser &Parser;
41d73ada7d24832bc2a4c3965b8f00ffd951341acfDaniel Dunbar  TargetMachine &TM;
42ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
43ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbyprivate:
44ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  MCAsmParser &getParser() const { return Parser; }
45ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
46ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
47ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
48ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
49ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
50ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
51ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
52762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  bool MaybeParseRegister(OwningPtr<ARMOperand> &Op, bool ParseWriteBack);
53a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
54762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  bool ParseRegisterList(OwningPtr<ARMOperand> &Op);
55d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
56762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  bool ParseMemory(OwningPtr<ARMOperand> &Op);
57a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
589c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  bool ParseMemoryOffsetReg(bool &Negative,
599c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            bool &OffsetRegShifted,
609c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            enum ShiftType &ShiftType,
619c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            const MCExpr *&ShiftAmount,
629c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            const MCExpr *&Offset,
639c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            bool &OffsetIsReg,
64762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                            int &OffsetRegNum,
65762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                            SMLoc &E);
669c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
67762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount, SMLoc &E);
68a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
69762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  bool ParseOperand(OwningPtr<ARMOperand> &Op);
70a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
71ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  bool ParseDirectiveWord(unsigned Size, SMLoc L);
72ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
73515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool ParseDirectiveThumb(SMLoc L);
74515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
75515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool ParseDirectiveThumbFunc(SMLoc L);
76515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
77515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool ParseDirectiveCode(SMLoc L);
78515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
79515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool ParseDirectiveSyntax(SMLoc L);
80515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
81a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  /// @name Auto-generated Match Functions
82a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  /// {
833483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
843483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  unsigned ComputeAvailableFeatures(const ARMSubtarget *Subtarget) const;
853483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
869898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner  bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
87a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                        MCInst &Inst);
88a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
89a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  /// }
90a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
91a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
92ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbypublic:
93d73ada7d24832bc2a4c3965b8f00ffd951341acfDaniel Dunbar  ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
94d73ada7d24832bc2a4c3965b8f00ffd951341acfDaniel Dunbar    : TargetAsmParser(T), Parser(_Parser), TM(_TM) {}
95ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
9638e59891ee4417a9be2f8146ce0ba3269e38ac21Benjamin Kramer  virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
979898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner                                SmallVectorImpl<MCParsedAsmOperand*> &Operands);
98ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
99ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  virtual bool ParseDirective(AsmToken DirectiveID);
100ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby};
101ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
102a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// ARMOperand - Instances of this class represent a parsed ARM machine
103a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// instruction.
1047659389d0d4d315d30877592221da6a6f663114aChris Lattnerstruct ARMOperand : public MCParsedAsmOperand {
105762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananprivate:
106762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  ARMOperand() {}
107762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananpublic:
108762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  enum KindTy {
109a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Token,
110a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Register,
111cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    Immediate,
112a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Memory
113a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  } Kind;
114a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
115762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc StartLoc, EndLoc;
116a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
117a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  union {
118a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    struct {
119a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      const char *Data;
120a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned Length;
121a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    } Tok;
122a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
123a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    struct {
124a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned RegNum;
12599e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby      bool Writeback;
126a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    } Reg;
127a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
128cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    struct {
129cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby      const MCExpr *Val;
130cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    } Imm;
131762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
132a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    // This is for all forms of ARM address expressions
133a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    struct {
134a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned BaseRegNum;
135a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned OffsetRegNum; // used when OffsetIsReg is true
1369c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      const MCExpr *Offset; // used when OffsetIsReg is false
137a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
1389c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      enum ShiftType ShiftType;  // used when OffsetRegShifted is true
1399c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      unsigned
1409c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        OffsetRegShifted : 1, // only used when OffsetIsReg is true
1419c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Preindexed : 1,
1429c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Postindexed : 1,
1439c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        OffsetIsReg : 1,
1449c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Negative : 1, // only used when OffsetIsReg is true
1459c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Writeback : 1;
146a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    } Mem;
147a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
148a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  };
149762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
150762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  ARMOperand(KindTy K, SMLoc S, SMLoc E)
151762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    : Kind(K), StartLoc(S), EndLoc(E) {}
152762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
153762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
154762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Kind = o.Kind;
155762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    StartLoc = o.StartLoc;
156762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    EndLoc = o.EndLoc;
157762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    switch (Kind) {
158762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    case Token:
159762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Tok = o.Tok;
160762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      break;
161762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    case Register:
162762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      Reg = o.Reg;
163762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      break;
164762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    case Immediate:
165762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      Imm = o.Imm;
166762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      break;
167762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    case Memory:
168762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      Mem = o.Mem;
169762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      break;
170762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    }
171762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  }
172762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
173762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  /// getStartLoc - Get the location of the first token of this operand.
174762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc getStartLoc() const { return StartLoc; }
175762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  /// getEndLoc - Get the location of the last token of this operand.
176762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc getEndLoc() const { return EndLoc; }
177a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
178a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  StringRef getToken() const {
179a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    assert(Kind == Token && "Invalid access!");
180a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return StringRef(Tok.Data, Tok.Length);
181a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
182a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
183a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  unsigned getReg() const {
184a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    assert(Kind == Register && "Invalid access!");
185a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Reg.RegNum;
186a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
187a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
188cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  const MCExpr *getImm() const {
189cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    assert(Kind == Immediate && "Invalid access!");
190cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    return Imm.Val;
191cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  }
192cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby
1933483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  bool isImm() const { return Kind == Immediate; }
194a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
195a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool isReg() const { return Kind == Register; }
196a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
1973483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  bool isToken() const {return Kind == Token; }
1983483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
1993483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
2003483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    // Add as immediates when possible.
2013483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
2023483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
2033483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    else
2043483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar      Inst.addOperand(MCOperand::CreateExpr(Expr));
2053483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  }
2063483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
207a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  void addRegOperands(MCInst &Inst, unsigned N) const {
208a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    assert(N == 1 && "Invalid number of operands!");
209a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Inst.addOperand(MCOperand::CreateReg(getReg()));
210a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
211a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
2123483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  void addImmOperands(MCInst &Inst, unsigned N) const {
2133483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    assert(N == 1 && "Invalid number of operands!");
2143483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    addExpr(Inst, getImm());
2153483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  }
2163483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
217762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  static void CreateToken(OwningPtr<ARMOperand> &Op, StringRef Str,
218762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          SMLoc S) {
219762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op.reset(new ARMOperand);
220762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Kind = Token;
221762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Tok.Data = Str.data();
222762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Tok.Length = Str.size();
223762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->StartLoc = S;
224762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->EndLoc = S;
225a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
226a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
227762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  static void CreateReg(OwningPtr<ARMOperand> &Op, unsigned RegNum,
228762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        bool Writeback, SMLoc S, SMLoc E) {
229762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op.reset(new ARMOperand);
230762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Kind = Register;
231762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Reg.RegNum = RegNum;
232762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Reg.Writeback = Writeback;
233762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
234762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->StartLoc = S;
235762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->EndLoc = E;
236a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
237a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
238762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  static void CreateImm(OwningPtr<ARMOperand> &Op, const MCExpr *Val,
239762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        SMLoc S, SMLoc E) {
240762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op.reset(new ARMOperand);
241762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Kind = Immediate;
242762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Imm.Val = Val;
243762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
244762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->StartLoc = S;
245762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->EndLoc = E;
246cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  }
247cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby
248762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  static void CreateMem(OwningPtr<ARMOperand> &Op,
249762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        unsigned BaseRegNum, bool OffsetIsReg,
250762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        const MCExpr *Offset, unsigned OffsetRegNum,
251762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        bool OffsetRegShifted, enum ShiftType ShiftType,
252762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        const MCExpr *ShiftAmount, bool Preindexed,
253762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        bool Postindexed, bool Negative, bool Writeback,
254762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        SMLoc S, SMLoc E) {
255762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op.reset(new ARMOperand);
256762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Kind = Memory;
257762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.BaseRegNum = BaseRegNum;
258762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.OffsetIsReg = OffsetIsReg;
259762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Offset = Offset;
260762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.OffsetRegNum = OffsetRegNum;
261762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.OffsetRegShifted = OffsetRegShifted;
262762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.ShiftType = ShiftType;
263762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.ShiftAmount = ShiftAmount;
264762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Preindexed = Preindexed;
265762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Postindexed = Postindexed;
266762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Negative = Negative;
267762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Writeback = Writeback;
268762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
269762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->StartLoc = S;
270762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->EndLoc = E;
271a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
272a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby};
273a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
274a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby} // end anonymous namespace.
275a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
2763483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
2773483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar/// @name Auto-generated Match Functions
2783483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar/// {
2793483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
2803483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbarstatic unsigned MatchRegisterName(StringRef Name);
2813483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
2823483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar/// }
2833483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
2849c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Try to parse a register name.  The token must be an Identifier when called,
2859c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// and if it is a register name a Reg operand is created, the token is eaten
2869c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// and false is returned.  Else true is returned and no token is eaten.
2879c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// TODO this is likely to change to allow different register types and or to
2889c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// parse for a specific register type.
289762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::MaybeParseRegister
290762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  (OwningPtr<ARMOperand> &Op, bool ParseWriteBack) {
291762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc S, E;
29218b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
293a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
294a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
295a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // FIXME: Validate register for the current architecture; we have to do
296a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // validation later, so maybe there is no need for this here.
297d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int RegNum;
298a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
299a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  RegNum = MatchRegisterName(Tok.getString());
300d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RegNum == -1)
301a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return true;
302762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
303762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  S = Tok.getLoc();
304762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
305b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat identifier token.
306762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
307762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  E = Parser.getTok().getLoc();
308a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
30999e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby  bool Writeback = false;
3109c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (ParseWriteBack) {
31118b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &ExclaimTok = Parser.getTok();
3129c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (ExclaimTok.is(AsmToken::Exclaim)) {
313762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      E = ExclaimTok.getLoc();
3149c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      Writeback = true;
315b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat exclaim token
3169c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    }
31799e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby  }
31899e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby
319762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  ARMOperand::CreateReg(Op, RegNum, Writeback, S, E);
32099e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby
321a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return false;
322a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
323a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
3249c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse a register list, return false if successful else return true or an
3259c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// error.  The first token must be a '{' when called.
326762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::ParseRegisterList(OwningPtr<ARMOperand> &Op) {
327762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc S, E;
32818b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  assert(Parser.getTok().is(AsmToken::LCurly) &&
329cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby         "Token is not an Left Curly Brace");
330762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  S = Parser.getTok().getLoc();
331b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat left curly brace token.
332d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
33318b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &RegTok = Parser.getTok();
334d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  SMLoc RegLoc = RegTok.getLoc();
335d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RegTok.isNot(AsmToken::Identifier))
336d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return Error(RegLoc, "register expected");
337d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int RegNum = MatchRegisterName(RegTok.getString());
338d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RegNum == -1)
339d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return Error(RegLoc, "register expected");
340b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat identifier token.
341d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  unsigned RegList = 1 << RegNum;
342d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
343d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int HighRegNum = RegNum;
344d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  // TODO ranges like "{Rn-Rm}"
34518b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  while (Parser.getTok().is(AsmToken::Comma)) {
346b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat comma token.
347d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
34818b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &RegTok = Parser.getTok();
349d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    SMLoc RegLoc = RegTok.getLoc();
350d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    if (RegTok.isNot(AsmToken::Identifier))
351d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      return Error(RegLoc, "register expected");
352d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    int RegNum = MatchRegisterName(RegTok.getString());
353d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    if (RegNum == -1)
354d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      return Error(RegLoc, "register expected");
355d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
356d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    if (RegList & (1 << RegNum))
357d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      Warning(RegLoc, "register duplicated in register list");
358d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    else if (RegNum <= HighRegNum)
359d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      Warning(RegLoc, "register not in ascending order in register list");
360d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    RegList |= 1 << RegNum;
361d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    HighRegNum = RegNum;
362d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
363b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat identifier token.
364d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  }
36518b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &RCurlyTok = Parser.getTok();
366d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RCurlyTok.isNot(AsmToken::RCurly))
367d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return Error(RCurlyTok.getLoc(), "'}' expected");
368762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  E = RCurlyTok.getLoc();
369b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat left curly brace token.
370d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
371d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  return false;
372d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby}
373d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
3749c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse an arm memory expression, return false if successful else return true
3759c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// or an error.  The first token must be a '[' when called.
3769c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// TODO Only preindexing and postindexing addressing are started, unindexed
3779c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// with option, etc are still to do.
378762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::ParseMemory(OwningPtr<ARMOperand> &Op) {
379762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc S, E;
38018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  assert(Parser.getTok().is(AsmToken::LBrac) &&
3816bd266e56799703cd2773cadc4da8bc3c5107fdfKevin Enderby         "Token is not an Left Bracket");
382762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  S = Parser.getTok().getLoc();
383b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat left bracket token.
384a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
38518b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &BaseRegTok = Parser.getTok();
386a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (BaseRegTok.isNot(AsmToken::Identifier))
387a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Error(BaseRegTok.getLoc(), "register expected");
3889c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (MaybeParseRegister(Op, false))
389a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Error(BaseRegTok.getLoc(), "register expected");
390762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  int BaseRegNum = Op->getReg();
391a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
392a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Preindexed = false;
393a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Postindexed = false;
394a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool OffsetIsReg = false;
395a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Negative = false;
396a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Writeback = false;
397a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
3989c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // First look for preindexed address forms, that is after the "[Rn" we now
3999c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // have to see if the next token is a comma.
40018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
401a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (Tok.is(AsmToken::Comma)) {
402a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Preindexed = true;
403b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat comma token.
4049c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    int OffsetRegNum;
4059c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    bool OffsetRegShifted;
406a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    enum ShiftType ShiftType;
407a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *ShiftAmount;
408a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *Offset;
4099c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
410762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                            Offset, OffsetIsReg, OffsetRegNum, E))
4119c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      return true;
41218b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &RBracTok = Parser.getTok();
413a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    if (RBracTok.isNot(AsmToken::RBrac))
414a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      return Error(RBracTok.getLoc(), "']' expected");
415762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = RBracTok.getLoc();
416b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat right bracket token.
417a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
41818b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &ExclaimTok = Parser.getTok();
419a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    if (ExclaimTok.is(AsmToken::Exclaim)) {
420762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      E = ExclaimTok.getLoc();
421a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      Writeback = true;
422b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat exclaim token
423a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    }
424762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
425762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          OffsetRegShifted, ShiftType, ShiftAmount,
426762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          Preindexed, Postindexed, Negative, Writeback, S, E);
427a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return false;
428a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
429a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // The "[Rn" we have so far was not followed by a comma.
430a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (Tok.is(AsmToken::RBrac)) {
4319c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // This is a post indexing addressing forms, that is a ']' follows after
4329c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // the "[Rn".
433a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Postindexed = true;
434a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Writeback = true;
435762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = Tok.getLoc();
436b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat right bracket token.
437a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
438e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby    int OffsetRegNum = 0;
439a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    bool OffsetRegShifted = false;
440a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    enum ShiftType ShiftType;
441a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *ShiftAmount;
442a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *Offset;
443a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
44418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &NextTok = Parser.getTok();
445e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby    if (NextTok.isNot(AsmToken::EndOfStatement)) {
446e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby      if (NextTok.isNot(AsmToken::Comma))
4473472766f9eb7d66f234c390ce1b3a8b76f0ee9ceDuncan Sands        return Error(NextTok.getLoc(), "',' expected");
448b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat comma token.
4499c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
450762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                              ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
451762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                              E))
4529c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        return true;
453a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    }
454e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby
455762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
456762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          OffsetRegShifted, ShiftType, ShiftAmount,
457762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          Preindexed, Postindexed, Negative, Writeback, S, E);
458a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return false;
459a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
460a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
461a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return true;
462a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
463a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
4649c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
4659c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// we will parse the following (were +/- means that a plus or minus is
4669c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// optional):
4679c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby///   +/-Rm
4689c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby///   +/-Rm, shift
4699c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby///   #offset
4709c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// we return false on success or an error otherwise.
4719c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderbybool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
472762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                                        bool &OffsetRegShifted,
4739c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        enum ShiftType &ShiftType,
4749c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        const MCExpr *&ShiftAmount,
4759c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        const MCExpr *&Offset,
4769c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        bool &OffsetIsReg,
477762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                                        int &OffsetRegNum,
478762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                                        SMLoc &E) {
479762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  OwningPtr<ARMOperand> Op;
4809c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  Negative = false;
4819c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  OffsetRegShifted = false;
4829c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  OffsetIsReg = false;
4839c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  OffsetRegNum = -1;
48418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &NextTok = Parser.getTok();
485762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  E = NextTok.getLoc();
4869c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (NextTok.is(AsmToken::Plus))
487b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat plus token.
4889c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  else if (NextTok.is(AsmToken::Minus)) {
4899c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    Negative = true;
490b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat minus token
4919c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
4929c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // See if there is a register following the "[Rn," or "[Rn]," we have so far.
49318b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &OffsetRegTok = Parser.getTok();
4949c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (OffsetRegTok.is(AsmToken::Identifier)) {
4959c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    OffsetIsReg = !MaybeParseRegister(Op, false);
496762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    if (OffsetIsReg) {
497762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      E = Op->getEndLoc();
498762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      OffsetRegNum = Op->getReg();
499762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    }
5009c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
5019c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // If we parsed a register as the offset then their can be a shift after that
5029c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (OffsetRegNum != -1) {
5039c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // Look for a comma then a shift
50418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &Tok = Parser.getTok();
5059c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (Tok.is(AsmToken::Comma)) {
506b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat comma token.
5079c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
50818b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan      const AsmToken &Tok = Parser.getTok();
509762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      if (ParseShift(ShiftType, ShiftAmount, E))
5103472766f9eb7d66f234c390ce1b3a8b76f0ee9ceDuncan Sands        return Error(Tok.getLoc(), "shift expected");
5119c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      OffsetRegShifted = true;
5129c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    }
5139c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
5149c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
5159c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // Look for #offset following the "[Rn," or "[Rn],"
51618b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &HashTok = Parser.getTok();
5179c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (HashTok.isNot(AsmToken::Hash))
5189c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      return Error(HashTok.getLoc(), "'#' expected");
519762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
520b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat hash token.
5219c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
5229c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (getParser().ParseExpression(Offset))
5239c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby     return true;
524762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5259c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
5269c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  return false;
5279c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby}
5289c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
529a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// ParseShift as one of these two:
530a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby///   ( lsl | lsr | asr | ror ) , # shift_amount
531a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby///   rrx
532a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// and returns true if it parses a shift otherwise it returns false.
533762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::ParseShift(ShiftType &St,
534762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                              const MCExpr *&ShiftAmount,
535762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                              SMLoc &E) {
53618b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
537a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (Tok.isNot(AsmToken::Identifier))
538a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return true;
53938e59891ee4417a9be2f8146ce0ba3269e38ac21Benjamin Kramer  StringRef ShiftName = Tok.getString();
540a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (ShiftName == "lsl" || ShiftName == "LSL")
5419c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Lsl;
542a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "lsr" || ShiftName == "LSR")
5439c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Lsr;
544a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "asr" || ShiftName == "ASR")
5459c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Asr;
546a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "ror" || ShiftName == "ROR")
5479c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Ror;
548a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "rrx" || ShiftName == "RRX")
5499c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Rrx;
550a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else
551a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return true;
552b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat shift type token.
553a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
5549c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // Rrx stands alone.
5559c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (St == Rrx)
5569c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    return false;
557a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
5589c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // Otherwise, there must be a '#' and a shift amount.
55918b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &HashTok = Parser.getTok();
5609c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (HashTok.isNot(AsmToken::Hash))
5619c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    return Error(HashTok.getLoc(), "'#' expected");
562b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat hash token.
5639c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
5649c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (getParser().ParseExpression(ShiftAmount))
5659c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    return true;
566a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
567a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return false;
568a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
569a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
5709c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse a arm instruction operand.  For now this parses the operand regardless
5719c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// of the mnemonic.
572762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::ParseOperand(OwningPtr<ARMOperand> &Op) {
573762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc S, E;
574762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
575a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  switch (getLexer().getKind()) {
576a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  case AsmToken::Identifier:
5779c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (!MaybeParseRegister(Op, true))
578a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      return false;
579515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    // This was not a register so parse other operands that start with an
580515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    // identifier (like labels) as expressions and create them as immediates.
581515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    const MCExpr *IdVal;
582762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    S = Parser.getTok().getLoc();
583515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    if (getParser().ParseExpression(IdVal))
584515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby      return true;
585762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
586762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    ARMOperand::CreateImm(Op, IdVal, S, E);
587515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return false;
588a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  case AsmToken::LBrac:
589515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseMemory(Op);
590d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  case AsmToken::LCurly:
591515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseRegisterList(Op);
592d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  case AsmToken::Hash:
593079469f649d8da3923b9f747d7062c84e01cc4aeKevin Enderby    // #42 -> immediate.
594079469f649d8da3923b9f747d7062c84e01cc4aeKevin Enderby    // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
595762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    S = Parser.getTok().getLoc();
596b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
597515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    const MCExpr *ImmVal;
598515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    if (getParser().ParseExpression(ImmVal))
599cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby      return true;
600762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
601762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    ARMOperand::CreateImm(Op, ImmVal, S, E);
602cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    return false;
603a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  default:
60418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    return Error(Parser.getTok().getLoc(), "unexpected token in operand");
605a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
606a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
607a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
6089c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse an arm instruction mnemonic followed by its operands.
60938e59891ee4417a9be2f8146ce0ba3269e38ac21Benjamin Kramerbool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
6109898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
611762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  OwningPtr<ARMOperand> Op;
612762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  ARMOperand::CreateToken(Op, Name, NameLoc);
613762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
614762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  Operands.push_back(Op.take());
615a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
616a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement)) {
617a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
618a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    // Read the first operand.
619762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    OwningPtr<ARMOperand> Op;
6209898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner    if (ParseOperand(Op)) return true;
621762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Operands.push_back(Op.take());
622a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
623a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    while (getLexer().is(AsmToken::Comma)) {
624b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex();  // Eat the comma.
625a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
626a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      // Parse and remember the operand.
6279898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner      if (ParseOperand(Op)) return true;
628762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      Operands.push_back(Op.take());
629a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    }
630a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
6319898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner  return false;
632ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
633ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
634515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirective parses the arm specific directives
635ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbybool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
636ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  StringRef IDVal = DirectiveID.getIdentifier();
637ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  if (IDVal == ".word")
638ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    return ParseDirectiveWord(4, DirectiveID.getLoc());
639515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".thumb")
640515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveThumb(DirectiveID.getLoc());
641515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".thumb_func")
642515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveThumbFunc(DirectiveID.getLoc());
643515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".code")
644515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveCode(DirectiveID.getLoc());
645515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".syntax")
646515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveSyntax(DirectiveID.getLoc());
647ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  return true;
648ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
649ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
650ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby/// ParseDirectiveWord
651ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby///  ::= .word [ expression (, expression)* ]
652ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbybool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
653ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement)) {
654ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    for (;;) {
655ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      const MCExpr *Value;
656ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      if (getParser().ParseExpression(Value))
657ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby        return true;
658ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
659aaec205b87637cd0d59d4f11630db603686eb73dChris Lattner      getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
660ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
661ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      if (getLexer().is(AsmToken::EndOfStatement))
662ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby        break;
663ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
664ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      // FIXME: Improve diagnostic.
665ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      if (getLexer().isNot(AsmToken::Comma))
666ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby        return Error(L, "unexpected token in directive");
667b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex();
668ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    }
669ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  }
670ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
671b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
672ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  return false;
673ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
674ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
675515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveThumb
676515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .thumb
677515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
678515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
679515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in directive");
680b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
681515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
682515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO: set thumb mode
683515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO: tell the MC streamer the mode
684515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
685515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
686515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
687515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
688515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveThumbFunc
689515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .thumbfunc symbol_name
690515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
69118b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
692515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
693515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in .syntax directive");
69418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
695b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Consume the identifier token.
696515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
697515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
698515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in directive");
699b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
700515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
701515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO: mark symbol as a thumb symbol
702515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
703515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
704515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
705515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
706515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveSyntax
707515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .syntax unified | divided
708515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
70918b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
710515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Tok.isNot(AsmToken::Identifier))
711515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in .syntax directive");
71238e59891ee4417a9be2f8146ce0ba3269e38ac21Benjamin Kramer  StringRef Mode = Tok.getString();
71358c86910b31c569a5709466c82e2fabae2014a56Duncan Sands  if (Mode == "unified" || Mode == "UNIFIED")
714b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
71558c86910b31c569a5709466c82e2fabae2014a56Duncan Sands  else if (Mode == "divided" || Mode == "DIVIDED")
716b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
717515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else
718515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unrecognized syntax mode in .syntax directive");
719515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
720515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
72118b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
722b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
723515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
724515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO tell the MC streamer the mode
725515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
726515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
727515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
728515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
729515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveCode
730515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .code 16 | 32
731515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
73218b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
733515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Tok.isNot(AsmToken::Integer))
734515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in .code directive");
73518b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  int64_t Val = Parser.getTok().getIntVal();
73658c86910b31c569a5709466c82e2fabae2014a56Duncan Sands  if (Val == 16)
737b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
73858c86910b31c569a5709466c82e2fabae2014a56Duncan Sands  else if (Val == 32)
739b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
740515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else
741515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "invalid operand to .code directive");
742515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
743515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
74418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
745b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
746515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
747515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO tell the MC streamer the mode
748515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
749515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
750515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
751515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
75290b7097f92f6b4f6b27cd88c7c88a21b777f5795Sean Callananextern "C" void LLVMInitializeARMAsmLexer();
75390b7097f92f6b4f6b27cd88c7c88a21b777f5795Sean Callanan
7549c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Force static initialization.
755ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbyextern "C" void LLVMInitializeARMAsmParser() {
756ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
757ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
75890b7097f92f6b4f6b27cd88c7c88a21b777f5795Sean Callanan  LLVMInitializeARMAsmLexer();
759ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
7603483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
7613483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar#include "ARMGenAsmMatcher.inc"
762