ARMAsmParser.cpp revision b3cb6967949493a2e1b10d015ac08b746736764e
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 {
1098462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    CondCode,
110cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    Immediate,
1118462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    Memory,
1128462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    Register,
1138462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    Token
114a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  } Kind;
115a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
116762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc StartLoc, EndLoc;
117a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
118a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  union {
119a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    struct {
1208462b30548fb5969250858036638c73c16b65b43Daniel Dunbar      ARMCC::CondCodes Val;
1218462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    } CC;
1228462b30548fb5969250858036638c73c16b65b43Daniel Dunbar
1238462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    struct {
124a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      const char *Data;
125a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned Length;
126a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    } Tok;
127a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
128a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    struct {
129a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned RegNum;
13099e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby      bool Writeback;
131a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    } Reg;
132a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
133cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    struct {
134cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby      const MCExpr *Val;
135cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    } Imm;
136762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
137a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    // This is for all forms of ARM address expressions
138a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    struct {
139a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned BaseRegNum;
140a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned OffsetRegNum; // used when OffsetIsReg is true
1419c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      const MCExpr *Offset; // used when OffsetIsReg is false
142a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
1439c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      enum ShiftType ShiftType;  // used when OffsetRegShifted is true
1449c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      unsigned
1459c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        OffsetRegShifted : 1, // only used when OffsetIsReg is true
1469c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Preindexed : 1,
1479c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Postindexed : 1,
1489c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        OffsetIsReg : 1,
1499c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Negative : 1, // only used when OffsetIsReg is true
1509c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Writeback : 1;
151a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    } Mem;
152a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
153a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  };
154762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
155762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  ARMOperand(KindTy K, SMLoc S, SMLoc E)
156762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    : Kind(K), StartLoc(S), EndLoc(E) {}
157762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
158762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
159762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Kind = o.Kind;
160762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    StartLoc = o.StartLoc;
161762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    EndLoc = o.EndLoc;
162762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    switch (Kind) {
1638462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    case CondCode:
1648462b30548fb5969250858036638c73c16b65b43Daniel Dunbar      CC = o.CC;
1658462b30548fb5969250858036638c73c16b65b43Daniel Dunbar      break;
166762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    case Token:
1678462b30548fb5969250858036638c73c16b65b43Daniel Dunbar      Tok = o.Tok;
168762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      break;
169762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    case Register:
170762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      Reg = o.Reg;
171762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      break;
172762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    case Immediate:
173762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      Imm = o.Imm;
174762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      break;
175762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    case Memory:
176762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      Mem = o.Mem;
177762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      break;
178762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    }
179762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  }
180762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
181762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  /// getStartLoc - Get the location of the first token of this operand.
182762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc getStartLoc() const { return StartLoc; }
183762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  /// getEndLoc - Get the location of the last token of this operand.
184762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc getEndLoc() const { return EndLoc; }
185a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
1868462b30548fb5969250858036638c73c16b65b43Daniel Dunbar  ARMCC::CondCodes getCondCode() const {
1878462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    assert(Kind == CondCode && "Invalid access!");
1888462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    return CC.Val;
1898462b30548fb5969250858036638c73c16b65b43Daniel Dunbar  }
1908462b30548fb5969250858036638c73c16b65b43Daniel Dunbar
191a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  StringRef getToken() const {
192a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    assert(Kind == Token && "Invalid access!");
193a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return StringRef(Tok.Data, Tok.Length);
194a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
195a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
196a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  unsigned getReg() const {
197a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    assert(Kind == Register && "Invalid access!");
198a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Reg.RegNum;
199a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
200a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
201cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  const MCExpr *getImm() const {
202cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    assert(Kind == Immediate && "Invalid access!");
203cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    return Imm.Val;
204cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  }
205cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby
2068462b30548fb5969250858036638c73c16b65b43Daniel Dunbar  bool isCondCode() const { return Kind == CondCode; }
2078462b30548fb5969250858036638c73c16b65b43Daniel Dunbar
2083483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  bool isImm() const { return Kind == Immediate; }
209a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
210a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool isReg() const { return Kind == Register; }
211a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
2123483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  bool isToken() const {return Kind == Token; }
2133483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
2143483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
2153483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    // Add as immediates when possible.
2163483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
2173483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
2183483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    else
2193483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar      Inst.addOperand(MCOperand::CreateExpr(Expr));
2203483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  }
2213483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
2228462b30548fb5969250858036638c73c16b65b43Daniel Dunbar  void addCondCodeOperands(MCInst &Inst, unsigned N) const {
2238462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    assert(N == 1 && "Invalid number of operands!");
2248462b30548fb5969250858036638c73c16b65b43Daniel Dunbar    Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
2258462b30548fb5969250858036638c73c16b65b43Daniel Dunbar  }
2268462b30548fb5969250858036638c73c16b65b43Daniel Dunbar
227a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  void addRegOperands(MCInst &Inst, unsigned N) const {
228a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    assert(N == 1 && "Invalid number of operands!");
229a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Inst.addOperand(MCOperand::CreateReg(getReg()));
230a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
231a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
2323483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  void addImmOperands(MCInst &Inst, unsigned N) const {
2333483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    assert(N == 1 && "Invalid number of operands!");
2343483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar    addExpr(Inst, getImm());
2353483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar  }
2363483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
237b3cb6967949493a2e1b10d015ac08b746736764eDaniel Dunbar  virtual void dump(raw_ostream &OS) const {}
238b3cb6967949493a2e1b10d015ac08b746736764eDaniel Dunbar
239762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  static void CreateToken(OwningPtr<ARMOperand> &Op, StringRef Str,
240762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          SMLoc S) {
241762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op.reset(new ARMOperand);
242762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Kind = Token;
243762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Tok.Data = Str.data();
244762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Tok.Length = Str.size();
245762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->StartLoc = S;
246762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->EndLoc = S;
247a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
248a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
249762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  static void CreateReg(OwningPtr<ARMOperand> &Op, unsigned RegNum,
250762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        bool Writeback, SMLoc S, SMLoc E) {
251762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op.reset(new ARMOperand);
252762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Kind = Register;
253762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Reg.RegNum = RegNum;
254762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Reg.Writeback = Writeback;
255762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
256762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->StartLoc = S;
257762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->EndLoc = E;
258a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
259a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
260762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  static void CreateImm(OwningPtr<ARMOperand> &Op, const MCExpr *Val,
261762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        SMLoc S, SMLoc E) {
262762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op.reset(new ARMOperand);
263762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Kind = Immediate;
264762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Imm.Val = Val;
265762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
266762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->StartLoc = S;
267762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->EndLoc = E;
268cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  }
269cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby
270762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  static void CreateMem(OwningPtr<ARMOperand> &Op,
271762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        unsigned BaseRegNum, bool OffsetIsReg,
272762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        const MCExpr *Offset, unsigned OffsetRegNum,
273762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        bool OffsetRegShifted, enum ShiftType ShiftType,
274762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        const MCExpr *ShiftAmount, bool Preindexed,
275762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        bool Postindexed, bool Negative, bool Writeback,
276762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                        SMLoc S, SMLoc E) {
277762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op.reset(new ARMOperand);
278762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Kind = Memory;
279762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.BaseRegNum = BaseRegNum;
280762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.OffsetIsReg = OffsetIsReg;
281762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Offset = Offset;
282762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.OffsetRegNum = OffsetRegNum;
283762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.OffsetRegShifted = OffsetRegShifted;
284762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.ShiftType = ShiftType;
285762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.ShiftAmount = ShiftAmount;
286762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Preindexed = Preindexed;
287762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Postindexed = Postindexed;
288762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Negative = Negative;
289762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->Mem.Writeback = Writeback;
290762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
291762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->StartLoc = S;
292762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Op->EndLoc = E;
293a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
294a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby};
295a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
296a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby} // end anonymous namespace.
297a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
2983483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
2993483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar/// @name Auto-generated Match Functions
3003483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar/// {
3013483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
3023483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbarstatic unsigned MatchRegisterName(StringRef Name);
3033483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
3043483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar/// }
3053483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
3069c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Try to parse a register name.  The token must be an Identifier when called,
3079c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// and if it is a register name a Reg operand is created, the token is eaten
3089c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// and false is returned.  Else true is returned and no token is eaten.
3099c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// TODO this is likely to change to allow different register types and or to
3109c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// parse for a specific register type.
311762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::MaybeParseRegister
312762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  (OwningPtr<ARMOperand> &Op, bool ParseWriteBack) {
313762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc S, E;
31418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
315a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
316a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
317a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // FIXME: Validate register for the current architecture; we have to do
318a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // validation later, so maybe there is no need for this here.
319d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int RegNum;
320a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
321a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  RegNum = MatchRegisterName(Tok.getString());
322d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RegNum == -1)
323a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return true;
324762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
325762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  S = Tok.getLoc();
326762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
327b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat identifier token.
328762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
329762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  E = Parser.getTok().getLoc();
330a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
33199e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby  bool Writeback = false;
3329c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (ParseWriteBack) {
33318b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &ExclaimTok = Parser.getTok();
3349c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (ExclaimTok.is(AsmToken::Exclaim)) {
335762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      E = ExclaimTok.getLoc();
3369c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      Writeback = true;
337b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat exclaim token
3389c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    }
33999e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby  }
34099e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby
341762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  ARMOperand::CreateReg(Op, RegNum, Writeback, S, E);
34299e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby
343a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return false;
344a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
345a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
3469c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse a register list, return false if successful else return true or an
3479c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// error.  The first token must be a '{' when called.
348762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::ParseRegisterList(OwningPtr<ARMOperand> &Op) {
349762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc S, E;
35018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  assert(Parser.getTok().is(AsmToken::LCurly) &&
351cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby         "Token is not an Left Curly Brace");
352762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  S = Parser.getTok().getLoc();
353b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat left curly brace token.
354d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
35518b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &RegTok = Parser.getTok();
356d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  SMLoc RegLoc = RegTok.getLoc();
357d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RegTok.isNot(AsmToken::Identifier))
358d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return Error(RegLoc, "register expected");
359d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int RegNum = MatchRegisterName(RegTok.getString());
360d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RegNum == -1)
361d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return Error(RegLoc, "register expected");
362b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat identifier token.
363d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  unsigned RegList = 1 << RegNum;
364d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
365d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int HighRegNum = RegNum;
366d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  // TODO ranges like "{Rn-Rm}"
36718b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  while (Parser.getTok().is(AsmToken::Comma)) {
368b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat comma token.
369d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
37018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &RegTok = Parser.getTok();
371d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    SMLoc RegLoc = RegTok.getLoc();
372d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    if (RegTok.isNot(AsmToken::Identifier))
373d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      return Error(RegLoc, "register expected");
374d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    int RegNum = MatchRegisterName(RegTok.getString());
375d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    if (RegNum == -1)
376d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      return Error(RegLoc, "register expected");
377d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
378d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    if (RegList & (1 << RegNum))
379d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      Warning(RegLoc, "register duplicated in register list");
380d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    else if (RegNum <= HighRegNum)
381d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      Warning(RegLoc, "register not in ascending order in register list");
382d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    RegList |= 1 << RegNum;
383d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    HighRegNum = RegNum;
384d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
385b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat identifier token.
386d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  }
38718b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &RCurlyTok = Parser.getTok();
388d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RCurlyTok.isNot(AsmToken::RCurly))
389d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return Error(RCurlyTok.getLoc(), "'}' expected");
390762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  E = RCurlyTok.getLoc();
391b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat left curly brace token.
392d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
393d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  return false;
394d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby}
395d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
3969c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse an arm memory expression, return false if successful else return true
3979c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// or an error.  The first token must be a '[' when called.
3989c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// TODO Only preindexing and postindexing addressing are started, unindexed
3999c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// with option, etc are still to do.
400762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::ParseMemory(OwningPtr<ARMOperand> &Op) {
401762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc S, E;
40218b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  assert(Parser.getTok().is(AsmToken::LBrac) &&
4036bd266e56799703cd2773cadc4da8bc3c5107fdfKevin Enderby         "Token is not an Left Bracket");
404762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  S = Parser.getTok().getLoc();
405b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat left bracket token.
406a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
40718b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &BaseRegTok = Parser.getTok();
408a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (BaseRegTok.isNot(AsmToken::Identifier))
409a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Error(BaseRegTok.getLoc(), "register expected");
4109c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (MaybeParseRegister(Op, false))
411a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Error(BaseRegTok.getLoc(), "register expected");
412762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  int BaseRegNum = Op->getReg();
413a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
414a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Preindexed = false;
415a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Postindexed = false;
416a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool OffsetIsReg = false;
417a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Negative = false;
418a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Writeback = false;
419a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
4209c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // First look for preindexed address forms, that is after the "[Rn" we now
4219c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // have to see if the next token is a comma.
42218b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
423a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (Tok.is(AsmToken::Comma)) {
424a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Preindexed = true;
425b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat comma token.
4269c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    int OffsetRegNum;
4279c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    bool OffsetRegShifted;
428a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    enum ShiftType ShiftType;
429a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *ShiftAmount;
430a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *Offset;
4319c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
432762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                            Offset, OffsetIsReg, OffsetRegNum, E))
4339c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      return true;
43418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &RBracTok = Parser.getTok();
435a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    if (RBracTok.isNot(AsmToken::RBrac))
436a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      return Error(RBracTok.getLoc(), "']' expected");
437762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = RBracTok.getLoc();
438b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat right bracket token.
439a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
44018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &ExclaimTok = Parser.getTok();
441a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    if (ExclaimTok.is(AsmToken::Exclaim)) {
442762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      E = ExclaimTok.getLoc();
443a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      Writeback = true;
444b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat exclaim token
445a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    }
446762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
447762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          OffsetRegShifted, ShiftType, ShiftAmount,
448762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          Preindexed, Postindexed, Negative, Writeback, S, E);
449a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return false;
450a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
451a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // The "[Rn" we have so far was not followed by a comma.
452a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (Tok.is(AsmToken::RBrac)) {
4539c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // This is a post indexing addressing forms, that is a ']' follows after
4549c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // the "[Rn".
455a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Postindexed = true;
456a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Writeback = true;
457762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = Tok.getLoc();
458b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat right bracket token.
459a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
460e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby    int OffsetRegNum = 0;
461a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    bool OffsetRegShifted = false;
462a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    enum ShiftType ShiftType;
463a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *ShiftAmount;
464a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *Offset;
465a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
46618b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &NextTok = Parser.getTok();
467e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby    if (NextTok.isNot(AsmToken::EndOfStatement)) {
468e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby      if (NextTok.isNot(AsmToken::Comma))
4693472766f9eb7d66f234c390ce1b3a8b76f0ee9ceDuncan Sands        return Error(NextTok.getLoc(), "',' expected");
470b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat comma token.
4719c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
472762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                              ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
473762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                              E))
4749c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        return true;
475a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    }
476e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby
477762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    ARMOperand::CreateMem(Op, BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
478762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          OffsetRegShifted, ShiftType, ShiftAmount,
479762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                          Preindexed, Postindexed, Negative, Writeback, S, E);
480a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return false;
481a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
482a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
483a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return true;
484a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
485a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
4869c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
4879c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// we will parse the following (were +/- means that a plus or minus is
4889c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// optional):
4899c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby///   +/-Rm
4909c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby///   +/-Rm, shift
4919c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby///   #offset
4929c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// we return false on success or an error otherwise.
4939c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderbybool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
494762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                                        bool &OffsetRegShifted,
4959c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        enum ShiftType &ShiftType,
4969c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        const MCExpr *&ShiftAmount,
4979c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        const MCExpr *&Offset,
4989c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        bool &OffsetIsReg,
499762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                                        int &OffsetRegNum,
500762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                                        SMLoc &E) {
501762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  OwningPtr<ARMOperand> Op;
5029c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  Negative = false;
5039c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  OffsetRegShifted = false;
5049c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  OffsetIsReg = false;
5059c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  OffsetRegNum = -1;
50618b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &NextTok = Parser.getTok();
507762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  E = NextTok.getLoc();
5089c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (NextTok.is(AsmToken::Plus))
509b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat plus token.
5109c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  else if (NextTok.is(AsmToken::Minus)) {
5119c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    Negative = true;
512b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat minus token
5139c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
5149c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // See if there is a register following the "[Rn," or "[Rn]," we have so far.
51518b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &OffsetRegTok = Parser.getTok();
5169c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (OffsetRegTok.is(AsmToken::Identifier)) {
5179c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    OffsetIsReg = !MaybeParseRegister(Op, false);
518762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    if (OffsetIsReg) {
519762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      E = Op->getEndLoc();
520762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      OffsetRegNum = Op->getReg();
521762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    }
5229c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
5239c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // If we parsed a register as the offset then their can be a shift after that
5249c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (OffsetRegNum != -1) {
5259c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // Look for a comma then a shift
52618b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &Tok = Parser.getTok();
5279c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (Tok.is(AsmToken::Comma)) {
528b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat comma token.
5299c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
53018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan      const AsmToken &Tok = Parser.getTok();
531762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      if (ParseShift(ShiftType, ShiftAmount, E))
5323472766f9eb7d66f234c390ce1b3a8b76f0ee9ceDuncan Sands        return Error(Tok.getLoc(), "shift expected");
5339c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      OffsetRegShifted = true;
5349c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    }
5359c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
5369c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
5379c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // Look for #offset following the "[Rn," or "[Rn],"
53818b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &HashTok = Parser.getTok();
5399c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (HashTok.isNot(AsmToken::Hash))
5409c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      return Error(HashTok.getLoc(), "'#' expected");
541762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
542b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat hash token.
5439c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
5449c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (getParser().ParseExpression(Offset))
5459c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby     return true;
546762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5479c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
5489c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  return false;
5499c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby}
5509c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
551a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// ParseShift as one of these two:
552a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby///   ( lsl | lsr | asr | ror ) , # shift_amount
553a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby///   rrx
554a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// and returns true if it parses a shift otherwise it returns false.
555762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::ParseShift(ShiftType &St,
556762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                              const MCExpr *&ShiftAmount,
557762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan                              SMLoc &E) {
55818b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
559a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (Tok.isNot(AsmToken::Identifier))
560a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return true;
56138e59891ee4417a9be2f8146ce0ba3269e38ac21Benjamin Kramer  StringRef ShiftName = Tok.getString();
562a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (ShiftName == "lsl" || ShiftName == "LSL")
5639c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Lsl;
564a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "lsr" || ShiftName == "LSR")
5659c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Lsr;
566a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "asr" || ShiftName == "ASR")
5679c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Asr;
568a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "ror" || ShiftName == "ROR")
5699c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Ror;
570a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "rrx" || ShiftName == "RRX")
5719c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Rrx;
572a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else
573a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return true;
574b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat shift type token.
575a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
5769c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // Rrx stands alone.
5779c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (St == Rrx)
5789c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    return false;
579a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
5809c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // Otherwise, there must be a '#' and a shift amount.
58118b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &HashTok = Parser.getTok();
5829c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (HashTok.isNot(AsmToken::Hash))
5839c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    return Error(HashTok.getLoc(), "'#' expected");
584b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat hash token.
5859c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
5869c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (getParser().ParseExpression(ShiftAmount))
5879c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    return true;
588a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
589a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return false;
590a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
591a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
5929c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse a arm instruction operand.  For now this parses the operand regardless
5939c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// of the mnemonic.
594762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callananbool ARMAsmParser::ParseOperand(OwningPtr<ARMOperand> &Op) {
595762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  SMLoc S, E;
596762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
597a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  switch (getLexer().getKind()) {
598a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  case AsmToken::Identifier:
5999c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (!MaybeParseRegister(Op, true))
600a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      return false;
601515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    // This was not a register so parse other operands that start with an
602515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    // identifier (like labels) as expressions and create them as immediates.
603515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    const MCExpr *IdVal;
604762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    S = Parser.getTok().getLoc();
605515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    if (getParser().ParseExpression(IdVal))
606515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby      return true;
607762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
608762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    ARMOperand::CreateImm(Op, IdVal, S, E);
609515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return false;
610a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  case AsmToken::LBrac:
611515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseMemory(Op);
612d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  case AsmToken::LCurly:
613515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseRegisterList(Op);
614d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  case AsmToken::Hash:
615079469f649d8da3923b9f747d7062c84e01cc4aeKevin Enderby    // #42 -> immediate.
616079469f649d8da3923b9f747d7062c84e01cc4aeKevin Enderby    // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
617762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    S = Parser.getTok().getLoc();
618b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
619515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    const MCExpr *ImmVal;
620515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    if (getParser().ParseExpression(ImmVal))
621cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby      return true;
622762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
623762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    ARMOperand::CreateImm(Op, ImmVal, S, E);
624cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    return false;
625a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  default:
62618b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    return Error(Parser.getTok().getLoc(), "unexpected token in operand");
627a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
628a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
629a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
6309c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse an arm instruction mnemonic followed by its operands.
63138e59891ee4417a9be2f8146ce0ba3269e38ac21Benjamin Kramerbool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
6329898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
633762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  OwningPtr<ARMOperand> Op;
634762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  ARMOperand::CreateToken(Op, Name, NameLoc);
635762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan
636762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan  Operands.push_back(Op.take());
637a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
638a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement)) {
639a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
640a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    // Read the first operand.
641762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    OwningPtr<ARMOperand> Op;
6429898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner    if (ParseOperand(Op)) return true;
643762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan    Operands.push_back(Op.take());
644a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
645a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    while (getLexer().is(AsmToken::Comma)) {
646b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex();  // Eat the comma.
647a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
648a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      // Parse and remember the operand.
6499898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner      if (ParseOperand(Op)) return true;
650762647673379dbcff6bbba6167b0b1b0d658ba9dSean Callanan      Operands.push_back(Op.take());
651a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    }
652a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
6539898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner  return false;
654ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
655ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
656515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirective parses the arm specific directives
657ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbybool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
658ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  StringRef IDVal = DirectiveID.getIdentifier();
659ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  if (IDVal == ".word")
660ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    return ParseDirectiveWord(4, DirectiveID.getLoc());
661515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".thumb")
662515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveThumb(DirectiveID.getLoc());
663515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".thumb_func")
664515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveThumbFunc(DirectiveID.getLoc());
665515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".code")
666515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveCode(DirectiveID.getLoc());
667515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".syntax")
668515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveSyntax(DirectiveID.getLoc());
669ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  return true;
670ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
671ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
672ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby/// ParseDirectiveWord
673ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby///  ::= .word [ expression (, expression)* ]
674ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbybool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
675ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement)) {
676ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    for (;;) {
677ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      const MCExpr *Value;
678ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      if (getParser().ParseExpression(Value))
679ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby        return true;
680ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
681aaec205b87637cd0d59d4f11630db603686eb73dChris Lattner      getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
682ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
683ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      if (getLexer().is(AsmToken::EndOfStatement))
684ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby        break;
685ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
686ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      // FIXME: Improve diagnostic.
687ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      if (getLexer().isNot(AsmToken::Comma))
688ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby        return Error(L, "unexpected token in directive");
689b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex();
690ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    }
691ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  }
692ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
693b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
694ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  return false;
695ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
696ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
697515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveThumb
698515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .thumb
699515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
700515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
701515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in directive");
702b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
703515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
704515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO: set thumb mode
705515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO: tell the MC streamer the mode
706515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
707515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
708515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
709515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
710515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveThumbFunc
711515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .thumbfunc symbol_name
712515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
71318b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
714515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
715515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in .syntax directive");
71618b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
717b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Consume the identifier token.
718515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
719515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
720515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in directive");
721b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
722515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
723515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO: mark symbol as a thumb symbol
724515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
725515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
726515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
727515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
728515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveSyntax
729515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .syntax unified | divided
730515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
73118b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
732515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Tok.isNot(AsmToken::Identifier))
733515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in .syntax directive");
73438e59891ee4417a9be2f8146ce0ba3269e38ac21Benjamin Kramer  StringRef Mode = Tok.getString();
73558c86910b31c569a5709466c82e2fabae2014a56Duncan Sands  if (Mode == "unified" || Mode == "UNIFIED")
736b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
73758c86910b31c569a5709466c82e2fabae2014a56Duncan Sands  else if (Mode == "divided" || Mode == "DIVIDED")
738b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
739515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else
740515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unrecognized syntax mode in .syntax directive");
741515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
742515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
74318b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
744b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
745515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
746515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO tell the MC streamer the mode
747515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
748515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
749515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
750515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
751515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveCode
752515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .code 16 | 32
753515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
75418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
755515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Tok.isNot(AsmToken::Integer))
756515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in .code directive");
75718b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  int64_t Val = Parser.getTok().getIntVal();
75858c86910b31c569a5709466c82e2fabae2014a56Duncan Sands  if (Val == 16)
759b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
76058c86910b31c569a5709466c82e2fabae2014a56Duncan Sands  else if (Val == 32)
761b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
762515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else
763515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "invalid operand to .code directive");
764515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
765515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
76618b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
767b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
768515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
769515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO tell the MC streamer the mode
770515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
771515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
772515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
773515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
77490b7097f92f6b4f6b27cd88c7c88a21b777f5795Sean Callananextern "C" void LLVMInitializeARMAsmLexer();
77590b7097f92f6b4f6b27cd88c7c88a21b777f5795Sean Callanan
7769c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Force static initialization.
777ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbyextern "C" void LLVMInitializeARMAsmParser() {
778ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
779ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
78090b7097f92f6b4f6b27cd88c7c88a21b777f5795Sean Callanan  LLVMInitializeARMAsmLexer();
781ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
7823483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar
7833483acabf012b847b13b969ebd9ce5c4d16d9eb7Daniel Dunbar#include "ARMGenAsmMatcher.inc"
784