ARMAsmParser.cpp revision c6ef277a0b8f43af22d86aea9d5053749cacfbbb
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"
11c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/MC/MCParser/MCAsmLexer.h"
12c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/MC/MCParser/MCAsmParser.h"
13c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
14ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/MC/MCStreamer.h"
15ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/MC/MCExpr.h"
16ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/MC/MCInst.h"
17ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/Target/TargetRegistry.h"
18ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby#include "llvm/Target/TargetAsmParser.h"
19c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/Support/Compiler.h"
20c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/Support/SourceMgr.h"
21c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/ADT/SmallVector.h"
22c6ef277a0b8f43af22d86aea9d5053749cacfbbbChris Lattner#include "llvm/ADT/Twine.h"
23ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbyusing namespace llvm;
24ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
25ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbynamespace {
26ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbystruct ARMOperand;
27ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
28a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby// The shift types for register controlled shifts in arm memory addressing
29a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderbyenum ShiftType {
30a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Lsl,
31a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Lsr,
32a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Asr,
33a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Ror,
34a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  Rrx
35a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby};
36a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
37ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbyclass ARMAsmParser : public TargetAsmParser {
38ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  MCAsmParser &Parser;
39ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
40ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbyprivate:
41ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  MCAsmParser &getParser() const { return Parser; }
42ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
43ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
44ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
45ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
46ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
47ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
48ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
499c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  bool MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack);
50a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
51d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  bool ParseRegisterList(ARMOperand &Op);
52d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
53a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool ParseMemory(ARMOperand &Op);
54a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
559c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  bool ParseMemoryOffsetReg(bool &Negative,
569c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            bool &OffsetRegShifted,
579c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            enum ShiftType &ShiftType,
589c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            const MCExpr *&ShiftAmount,
599c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            const MCExpr *&Offset,
609c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            bool &OffsetIsReg,
6160131c0d0bb04d0ae3c13cbd055616c71d86e8eaKevin Enderby                            int &OffsetRegNum);
629c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
639c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  bool ParseShift(enum ShiftType &St, const MCExpr *&ShiftAmount);
64a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
65a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool ParseOperand(ARMOperand &Op);
66a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
67ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  bool ParseDirectiveWord(unsigned Size, SMLoc L);
68ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
69515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool ParseDirectiveThumb(SMLoc L);
70515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
71515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool ParseDirectiveThumbFunc(SMLoc L);
72515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
73515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool ParseDirectiveCode(SMLoc L);
74515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
75515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool ParseDirectiveSyntax(SMLoc L);
76515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
77a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // TODO - For now hacked versions of the next two are in here in this file to
78a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // allow some parser testing until the table gen versions are implemented.
79a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
80a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  /// @name Auto-generated Match Functions
81a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  /// {
829898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner  bool MatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
83a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                        MCInst &Inst);
84a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
85d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  /// MatchRegisterName - Match the given string to a register name and return
86d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  /// its register number, or -1 if there is no match.  To allow return values
87d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  /// to be used directly in register lists, arm registers have values between
88d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  /// 0 and 15.
89d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int MatchRegisterName(const StringRef &Name);
90a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
91a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  /// }
92a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
93a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
94ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbypublic:
95ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  ARMAsmParser(const Target &T, MCAsmParser &_Parser)
96ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    : TargetAsmParser(T), Parser(_Parser) {}
97ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
98f007e853e26845cd6866b52d646455fc69f4e0afChris Lattner  virtual bool ParseInstruction(const StringRef &Name, SMLoc NameLoc,
999898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner                                SmallVectorImpl<MCParsedAsmOperand*> &Operands);
100ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
101ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  virtual bool ParseDirective(AsmToken DirectiveID);
102ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby};
103ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
104a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// ARMOperand - Instances of this class represent a parsed ARM machine
105a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// instruction.
1067659389d0d4d315d30877592221da6a6f663114aChris Lattnerstruct ARMOperand : public MCParsedAsmOperand {
107a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  enum {
108a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Token,
109a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Register,
110cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    Immediate,
111a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Memory
112a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  } Kind;
113a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
114a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
115a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  union {
116a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    struct {
117a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      const char *Data;
118a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned Length;
119a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    } Tok;
120a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
121a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    struct {
122a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned RegNum;
12399e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby      bool Writeback;
124a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    } Reg;
125a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
126cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    struct {
127cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby      const MCExpr *Val;
128cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    } Imm;
129cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby
130a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    // This is for all forms of ARM address expressions
131a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    struct {
132a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned BaseRegNum;
133a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      unsigned OffsetRegNum; // used when OffsetIsReg is true
1349c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      const MCExpr *Offset; // used when OffsetIsReg is false
135a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      const MCExpr *ShiftAmount; // used when OffsetRegShifted is true
1369c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      enum ShiftType ShiftType;  // used when OffsetRegShifted is true
1379c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      unsigned
1389c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        OffsetRegShifted : 1, // only used when OffsetIsReg is true
1399c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Preindexed : 1,
1409c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Postindexed : 1,
1419c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        OffsetIsReg : 1,
1429c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Negative : 1, // only used when OffsetIsReg is true
1439c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        Writeback : 1;
144a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    } Mem;
145a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
146a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  };
147a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
148a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  StringRef getToken() const {
149a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    assert(Kind == Token && "Invalid access!");
150a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return StringRef(Tok.Data, Tok.Length);
151a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
152a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
153a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  unsigned getReg() const {
154a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    assert(Kind == Register && "Invalid access!");
155a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Reg.RegNum;
156a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
157a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
158cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  const MCExpr *getImm() const {
159cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    assert(Kind == Immediate && "Invalid access!");
160cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    return Imm.Val;
161cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  }
162cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby
163a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool isToken() const {return Kind == Token; }
164a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
165a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool isReg() const { return Kind == Register; }
166a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
167a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  void addRegOperands(MCInst &Inst, unsigned N) const {
168a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    assert(N == 1 && "Invalid number of operands!");
169a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Inst.addOperand(MCOperand::CreateReg(getReg()));
170a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
171a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
172a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  static ARMOperand CreateToken(StringRef Str) {
173a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    ARMOperand Res;
174a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Kind = Token;
175a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Tok.Data = Str.data();
176a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Tok.Length = Str.size();
177a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Res;
178a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
179a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
18099e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby  static ARMOperand CreateReg(unsigned RegNum, bool Writeback) {
181a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    ARMOperand Res;
182a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Kind = Register;
183a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Reg.RegNum = RegNum;
18499e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby    Res.Reg.Writeback = Writeback;
185a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Res;
186a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
187a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
188cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  static ARMOperand CreateImm(const MCExpr *Val) {
189cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    ARMOperand Res;
190cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    Res.Kind = Immediate;
191cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    Res.Imm.Val = Val;
192cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    return Res;
193cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby  }
194cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby
195a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  static ARMOperand CreateMem(unsigned BaseRegNum, bool OffsetIsReg,
196a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                              const MCExpr *Offset, unsigned OffsetRegNum,
197a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                              bool OffsetRegShifted, enum ShiftType ShiftType,
198a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                              const MCExpr *ShiftAmount, bool Preindexed,
199a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                              bool Postindexed, bool Negative, bool Writeback) {
200a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    ARMOperand Res;
201a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Kind = Memory;
202a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.BaseRegNum = BaseRegNum;
203a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.OffsetIsReg = OffsetIsReg;
204a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.Offset = Offset;
205a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.OffsetRegNum = OffsetRegNum;
206a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.OffsetRegShifted = OffsetRegShifted;
207a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.ShiftType = ShiftType;
208a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.ShiftAmount = ShiftAmount;
209a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.Preindexed = Preindexed;
210a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.Postindexed = Postindexed;
211a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.Negative = Negative;
212a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Res.Mem.Writeback = Writeback;
213a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Res;
214a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
215a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby};
216a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
217a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby} // end anonymous namespace.
218a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
2199c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Try to parse a register name.  The token must be an Identifier when called,
2209c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// and if it is a register name a Reg operand is created, the token is eaten
2219c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// and false is returned.  Else true is returned and no token is eaten.
2229c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// TODO this is likely to change to allow different register types and or to
2239c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// parse for a specific register type.
2249c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderbybool ARMAsmParser::MaybeParseRegister(ARMOperand &Op, bool ParseWriteBack) {
22518b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
226a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
227a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
228a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // FIXME: Validate register for the current architecture; we have to do
229a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // validation later, so maybe there is no need for this here.
230d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int RegNum;
231a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
232a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  RegNum = MatchRegisterName(Tok.getString());
233d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RegNum == -1)
234a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return true;
235b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat identifier token.
236a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
23799e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby  bool Writeback = false;
2389c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (ParseWriteBack) {
23918b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &ExclaimTok = Parser.getTok();
2409c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (ExclaimTok.is(AsmToken::Exclaim)) {
2419c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      Writeback = true;
242b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat exclaim token
2439c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    }
24499e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby  }
24599e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby
24699e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby  Op = ARMOperand::CreateReg(RegNum, Writeback);
24799e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby
248a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return false;
249a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
250a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
2519c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse a register list, return false if successful else return true or an
2529c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// error.  The first token must be a '{' when called.
253d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderbybool ARMAsmParser::ParseRegisterList(ARMOperand &Op) {
25418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  assert(Parser.getTok().is(AsmToken::LCurly) &&
255cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby         "Token is not an Left Curly Brace");
256b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat left curly brace token.
257d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
25818b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &RegTok = Parser.getTok();
259d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  SMLoc RegLoc = RegTok.getLoc();
260d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RegTok.isNot(AsmToken::Identifier))
261d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return Error(RegLoc, "register expected");
262d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int RegNum = MatchRegisterName(RegTok.getString());
263d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RegNum == -1)
264d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return Error(RegLoc, "register expected");
265b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat identifier token.
266d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  unsigned RegList = 1 << RegNum;
267d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
268d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  int HighRegNum = RegNum;
269d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  // TODO ranges like "{Rn-Rm}"
27018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  while (Parser.getTok().is(AsmToken::Comma)) {
271b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat comma token.
272d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
27318b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &RegTok = Parser.getTok();
274d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    SMLoc RegLoc = RegTok.getLoc();
275d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    if (RegTok.isNot(AsmToken::Identifier))
276d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      return Error(RegLoc, "register expected");
277d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    int RegNum = MatchRegisterName(RegTok.getString());
278d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    if (RegNum == -1)
279d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      return Error(RegLoc, "register expected");
280d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
281d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    if (RegList & (1 << RegNum))
282d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      Warning(RegLoc, "register duplicated in register list");
283d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    else if (RegNum <= HighRegNum)
284d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      Warning(RegLoc, "register not in ascending order in register list");
285d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    RegList |= 1 << RegNum;
286d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    HighRegNum = RegNum;
287d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
288b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat identifier token.
289d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  }
29018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &RCurlyTok = Parser.getTok();
291d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (RCurlyTok.isNot(AsmToken::RCurly))
292d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return Error(RCurlyTok.getLoc(), "'}' expected");
293b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat left curly brace token.
294d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
295d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  return false;
296d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby}
297d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby
2989c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse an arm memory expression, return false if successful else return true
2999c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// or an error.  The first token must be a '[' when called.
3009c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// TODO Only preindexing and postindexing addressing are started, unindexed
3019c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// with option, etc are still to do.
302a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderbybool ARMAsmParser::ParseMemory(ARMOperand &Op) {
30318b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  assert(Parser.getTok().is(AsmToken::LBrac) &&
3046bd266e56799703cd2773cadc4da8bc3c5107fdfKevin Enderby         "Token is not an Left Bracket");
305b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat left bracket token.
306a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
30718b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &BaseRegTok = Parser.getTok();
308a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (BaseRegTok.isNot(AsmToken::Identifier))
309a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Error(BaseRegTok.getLoc(), "register expected");
3109c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (MaybeParseRegister(Op, false))
311a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return Error(BaseRegTok.getLoc(), "register expected");
3129c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  int BaseRegNum = Op.getReg();
313a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
314a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Preindexed = false;
315a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Postindexed = false;
316a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool OffsetIsReg = false;
317a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Negative = false;
318a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  bool Writeback = false;
319a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
3209c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // First look for preindexed address forms, that is after the "[Rn" we now
3219c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // have to see if the next token is a comma.
32218b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
323a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (Tok.is(AsmToken::Comma)) {
324a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Preindexed = true;
325b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat comma token.
3269c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    int OffsetRegNum;
3279c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    bool OffsetRegShifted;
328a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    enum ShiftType ShiftType;
329a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *ShiftAmount;
330a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *Offset;
3319c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
3329c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                            Offset, OffsetIsReg, OffsetRegNum))
3339c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      return true;
33418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &RBracTok = Parser.getTok();
335a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    if (RBracTok.isNot(AsmToken::RBrac))
336a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      return Error(RBracTok.getLoc(), "']' expected");
337b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat right bracket token.
338a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
33918b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &ExclaimTok = Parser.getTok();
340a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    if (ExclaimTok.is(AsmToken::Exclaim)) {
341a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      Writeback = true;
342b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat exclaim token
343a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    }
344a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
345a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                               OffsetRegShifted, ShiftType, ShiftAmount,
346a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                               Preindexed, Postindexed, Negative, Writeback);
347a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return false;
348a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
349a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  // The "[Rn" we have so far was not followed by a comma.
350a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (Tok.is(AsmToken::RBrac)) {
3519c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // This is a post indexing addressing forms, that is a ']' follows after
3529c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // the "[Rn".
353a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Postindexed = true;
354a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Writeback = true;
355b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat right bracket token.
356a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
357e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby    int OffsetRegNum = 0;
358a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    bool OffsetRegShifted = false;
359a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    enum ShiftType ShiftType;
360a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *ShiftAmount;
361a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    const MCExpr *Offset;
362a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
36318b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &NextTok = Parser.getTok();
364e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby    if (NextTok.isNot(AsmToken::EndOfStatement)) {
365e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby      if (NextTok.isNot(AsmToken::Comma))
366e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby	return Error(NextTok.getLoc(), "',' expected");
367b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat comma token.
3689c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      if(ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
3699c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                              ShiftAmount, Offset, OffsetIsReg, OffsetRegNum))
3709c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby        return true;
371a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    }
372e2a98dd2a4f007d5d9d3c71460cfbe0a825b8993Kevin Enderby
373a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    Op = ARMOperand::CreateMem(BaseRegNum, OffsetIsReg, Offset, OffsetRegNum,
374a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                               OffsetRegShifted, ShiftType, ShiftAmount,
375a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby                               Preindexed, Postindexed, Negative, Writeback);
376a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return false;
377a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
378a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
379a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return true;
380a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
381a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
3829c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
3839c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// we will parse the following (were +/- means that a plus or minus is
3849c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// optional):
3859c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby///   +/-Rm
3869c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby///   +/-Rm, shift
3879c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby///   #offset
3889c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// we return false on success or an error otherwise.
3899c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderbybool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
3909c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby					bool &OffsetRegShifted,
3919c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        enum ShiftType &ShiftType,
3929c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        const MCExpr *&ShiftAmount,
3939c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        const MCExpr *&Offset,
3949c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby                                        bool &OffsetIsReg,
39560131c0d0bb04d0ae3c13cbd055616c71d86e8eaKevin Enderby                                        int &OffsetRegNum) {
3969c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  ARMOperand Op;
3979c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  Negative = false;
3989c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  OffsetRegShifted = false;
3999c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  OffsetIsReg = false;
4009c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  OffsetRegNum = -1;
40118b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &NextTok = Parser.getTok();
4029c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (NextTok.is(AsmToken::Plus))
403b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat plus token.
4049c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  else if (NextTok.is(AsmToken::Minus)) {
4059c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    Negative = true;
406b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat minus token
4079c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
4089c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // See if there is a register following the "[Rn," or "[Rn]," we have so far.
40918b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &OffsetRegTok = Parser.getTok();
4109c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (OffsetRegTok.is(AsmToken::Identifier)) {
4119c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    OffsetIsReg = !MaybeParseRegister(Op, false);
4129c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (OffsetIsReg)
4139c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      OffsetRegNum = Op.getReg();
4149c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
4159c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // If we parsed a register as the offset then their can be a shift after that
4169c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (OffsetRegNum != -1) {
4179c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // Look for a comma then a shift
41818b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &Tok = Parser.getTok();
4199c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (Tok.is(AsmToken::Comma)) {
420b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex(); // Eat comma token.
4219c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
42218b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan      const AsmToken &Tok = Parser.getTok();
4239c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      if (ParseShift(ShiftType, ShiftAmount))
4249c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby	return Error(Tok.getLoc(), "shift expected");
4259c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      OffsetRegShifted = true;
4269c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    }
4279c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
4289c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
4299c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    // Look for #offset following the "[Rn," or "[Rn],"
43018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    const AsmToken &HashTok = Parser.getTok();
4319c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (HashTok.isNot(AsmToken::Hash))
4329c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby      return Error(HashTok.getLoc(), "'#' expected");
433b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex(); // Eat hash token.
4349c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
4359c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (getParser().ParseExpression(Offset))
4369c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby     return true;
4379c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  }
4389c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  return false;
4399c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby}
4409c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
441a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// ParseShift as one of these two:
442a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby///   ( lsl | lsr | asr | ror ) , # shift_amount
443a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby///   rrx
444a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby/// and returns true if it parses a shift otherwise it returns false.
4459c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderbybool ARMAsmParser::ParseShift(ShiftType &St, const MCExpr *&ShiftAmount) {
44618b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
447a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (Tok.isNot(AsmToken::Identifier))
448a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return true;
449a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  const StringRef &ShiftName = Tok.getString();
450a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (ShiftName == "lsl" || ShiftName == "LSL")
4519c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Lsl;
452a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "lsr" || ShiftName == "LSR")
4539c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Lsr;
454a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "asr" || ShiftName == "ASR")
4559c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Asr;
456a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "ror" || ShiftName == "ROR")
4579c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Ror;
458a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else if (ShiftName == "rrx" || ShiftName == "RRX")
4599c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    St = Rrx;
460a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  else
461a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return true;
462b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat shift type token.
463a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
4649c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // Rrx stands alone.
4659c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (St == Rrx)
4669c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    return false;
467a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
4689c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  // Otherwise, there must be a '#' and a shift amount.
46918b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &HashTok = Parser.getTok();
4709c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (HashTok.isNot(AsmToken::Hash))
4719c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    return Error(HashTok.getLoc(), "'#' expected");
472b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Eat hash token.
4739c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby
4749c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby  if (getParser().ParseExpression(ShiftAmount))
4759c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    return true;
476a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
477a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return false;
478a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
479a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
4809c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// A hack to allow some testing, to be replaced by a real table gen version.
481d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderbyint ARMAsmParser::MatchRegisterName(const StringRef &Name) {
482d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  if (Name == "r0" || Name == "R0")
483d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 0;
484d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r1" || Name == "R1")
485a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return 1;
486d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r2" || Name == "R2")
487a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return 2;
488d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r3" || Name == "R3")
489a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return 3;
490d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r3" || Name == "R3")
491d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 3;
492d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r4" || Name == "R4")
493d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 4;
494d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r5" || Name == "R5")
495d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 5;
496d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r6" || Name == "R6")
497d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 6;
498d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r7" || Name == "R7")
499d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 7;
500d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r8" || Name == "R8")
501d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 8;
502d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r9" || Name == "R9")
503d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 9;
504d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r10" || Name == "R10")
505d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 10;
506d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r11" || Name == "R11" || Name == "fp")
507d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 11;
508d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r12" || Name == "R12" || Name == "ip")
509d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 12;
510d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r13" || Name == "R13" || Name == "sp")
51199e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby    return 13;
512d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r14" || Name == "R14" || Name == "lr")
513d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      return 14;
514d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  else if (Name == "r15" || Name == "R15" || Name == "pc")
515d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby    return 15;
516d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  return -1;
517a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
518a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
5199c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// A hack to allow some testing, to be replaced by a real table gen version.
5209898671a74d3fc924347e679c45edaa685b3fe6eChris Lattnerbool ARMAsmParser::
5219898671a74d3fc924347e679c45edaa685b3fe6eChris LattnerMatchInstruction(const SmallVectorImpl<MCParsedAsmOperand*> &Operands,
5229898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner                 MCInst &Inst) {
5239898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner  ARMOperand &Op0 = *(ARMOperand*)Operands[0];
524a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  assert(Op0.Kind == ARMOperand::Token && "First operand not a Token");
525a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  const StringRef &Mnemonic = Op0.getToken();
526a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (Mnemonic == "add" ||
52799e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby      Mnemonic == "stmfd" ||
52899e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby      Mnemonic == "str" ||
52999e6d4e8392497d950d48b03f45c79b7dd131327Kevin Enderby      Mnemonic == "ldmfd" ||
530d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby      Mnemonic == "ldr" ||
531cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby      Mnemonic == "mov" ||
532515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby      Mnemonic == "sub" ||
533515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby      Mnemonic == "bl" ||
534515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby      Mnemonic == "push" ||
535515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby      Mnemonic == "blx" ||
5362685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar      Mnemonic == "pop") {
5372685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar    // Hard-coded to a valid instruction, till we have a real matcher.
5382685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar    Inst = MCInst();
5392685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar    Inst.setOpcode(ARM::MOVr);
5402685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar    Inst.addOperand(MCOperand::CreateReg(2));
5412685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar    Inst.addOperand(MCOperand::CreateReg(2));
5422685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar    Inst.addOperand(MCOperand::CreateImm(0));
5432685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar    Inst.addOperand(MCOperand::CreateImm(0));
5442685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar    Inst.addOperand(MCOperand::CreateReg(0));
545a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    return false;
5462685a29a8d4ced7791bb671e28f9fe51c74eb3bbDaniel Dunbar  }
547a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
548a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  return true;
549a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
550a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
5519c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse a arm instruction operand.  For now this parses the operand regardless
5529c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// of the mnemonic.
553a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderbybool ARMAsmParser::ParseOperand(ARMOperand &Op) {
554a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  switch (getLexer().getKind()) {
555a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  case AsmToken::Identifier:
5569c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby    if (!MaybeParseRegister(Op, true))
557a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      return false;
558515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    // This was not a register so parse other operands that start with an
559515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    // identifier (like labels) as expressions and create them as immediates.
560515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    const MCExpr *IdVal;
561515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    if (getParser().ParseExpression(IdVal))
562515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby      return true;
563515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    Op = ARMOperand::CreateImm(IdVal);
564515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return false;
565a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  case AsmToken::LBrac:
566515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseMemory(Op);
567d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  case AsmToken::LCurly:
568515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseRegisterList(Op);
569d7894f105a3c397a3d7f5c5136eee39f5865e64bKevin Enderby  case AsmToken::Hash:
570079469f649d8da3923b9f747d7062c84e01cc4aeKevin Enderby    // #42 -> immediate.
571079469f649d8da3923b9f747d7062c84e01cc4aeKevin Enderby    // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
572b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
573515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    const MCExpr *ImmVal;
574515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    if (getParser().ParseExpression(ImmVal))
575cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby      return true;
576515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    Op = ARMOperand::CreateImm(ImmVal);
577cfe072401658bbe9336b200b79526b65c5213b74Kevin Enderby    return false;
578a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  default:
57918b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    return Error(Parser.getTok().getLoc(), "unexpected token in operand");
580a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
581a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby}
582a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
5839c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Parse an arm instruction mnemonic followed by its operands.
584f007e853e26845cd6866b52d646455fc69f4e0afChris Lattnerbool ARMAsmParser::ParseInstruction(const StringRef &Name, SMLoc NameLoc,
5859898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5869898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner  Operands.push_back(new ARMOperand(ARMOperand::CreateToken(Name)));
587a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
58818b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  SMLoc Loc = Parser.getTok().getLoc();
589a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement)) {
590a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
591a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    // Read the first operand.
5929898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner    ARMOperand Op;
5939898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner    if (ParseOperand(Op)) return true;
5949898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner    Operands.push_back(new ARMOperand(Op));
595a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
596a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    while (getLexer().is(AsmToken::Comma)) {
597b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex();  // Eat the comma.
598a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby
599a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby      // Parse and remember the operand.
6009898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner      if (ParseOperand(Op)) return true;
6019898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner      Operands.push_back(new ARMOperand(Op));
602a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby    }
603a7ba3a81c008142a91d799e2ec3152cfd6bbb15fKevin Enderby  }
6049898671a74d3fc924347e679c45edaa685b3fe6eChris Lattner  return false;
605ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
606ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
607515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirective parses the arm specific directives
608ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbybool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
609ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  StringRef IDVal = DirectiveID.getIdentifier();
610ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  if (IDVal == ".word")
611ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    return ParseDirectiveWord(4, DirectiveID.getLoc());
612515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".thumb")
613515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveThumb(DirectiveID.getLoc());
614515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".thumb_func")
615515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveThumbFunc(DirectiveID.getLoc());
616515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".code")
617515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveCode(DirectiveID.getLoc());
618515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (IDVal == ".syntax")
619515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return ParseDirectiveSyntax(DirectiveID.getLoc());
620ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  return true;
621ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
622ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
623ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby/// ParseDirectiveWord
624ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby///  ::= .word [ expression (, expression)* ]
625ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbybool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
626ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement)) {
627ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    for (;;) {
628ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      const MCExpr *Value;
629ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      if (getParser().ParseExpression(Value))
630ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby        return true;
631ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
632aaec205b87637cd0d59d4f11630db603686eb73dChris Lattner      getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
633ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
634ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      if (getLexer().is(AsmToken::EndOfStatement))
635ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby        break;
636ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
637ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      // FIXME: Improve diagnostic.
638ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby      if (getLexer().isNot(AsmToken::Comma))
639ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby        return Error(L, "unexpected token in directive");
640b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan      Parser.Lex();
641ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby    }
642ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  }
643ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
644b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
645ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  return false;
646ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
647ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby
648515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveThumb
649515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .thumb
650515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
651515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
652515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in directive");
653b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
654515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
655515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO: set thumb mode
656515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO: tell the MC streamer the mode
657515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
658515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
659515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
660515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
661515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveThumbFunc
662515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .thumbfunc symbol_name
663515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
66418b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
665515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
666515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in .syntax directive");
66718b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  StringRef ATTRIBUTE_UNUSED SymbolName = Parser.getTok().getIdentifier();
668b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex(); // Consume the identifier token.
669515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
670515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
671515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in directive");
672b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
673515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
674515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO: mark symbol as a thumb symbol
675515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
676515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
677515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
678515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
679515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveSyntax
680515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .syntax unified | divided
681515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
68218b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
683515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Tok.isNot(AsmToken::Identifier))
684515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in .syntax directive");
685515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  const StringRef &Mode = Tok.getString();
686515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool unified_syntax;
687515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Mode == "unified" || Mode == "UNIFIED") {
688b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
689515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    unified_syntax = true;
690515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  }
691515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (Mode == "divided" || Mode == "DIVIDED") {
692b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
693515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    unified_syntax = false;
694515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  }
695515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else
696515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unrecognized syntax mode in .syntax directive");
697515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
698515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
69918b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
700b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
701515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
702515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO tell the MC streamer the mode
703515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
704515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
705515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
706515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
707515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby/// ParseDirectiveCode
708515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby///  ::= .code 16 | 32
709515d509360d81946247fd0f937034cdf1f237c72Kevin Enderbybool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
71018b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  const AsmToken &Tok = Parser.getTok();
711515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Tok.isNot(AsmToken::Integer))
712515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "unexpected token in .code directive");
71318b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan  int64_t Val = Parser.getTok().getIntVal();
714515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  bool thumb_mode;
715515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (Val == 16) {
716b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
717515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    thumb_mode = true;
718515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  }
719515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else if (Val == 32) {
720b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan    Parser.Lex();
721515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    thumb_mode = false;
722515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  }
723515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  else
724515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby    return Error(L, "invalid operand to .code directive");
725515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
726515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  if (getLexer().isNot(AsmToken::EndOfStatement))
72718b8323de70e3461b5d035e3f9e4f6dfaf5e674bSean Callanan    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
728b9a25b7744ed12b80031426978decce3d4cebbd7Sean Callanan  Parser.Lex();
729515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
730515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // TODO tell the MC streamer the mode
731515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  // getParser().getStreamer().Emit???();
732515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby  return false;
733515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby}
734515d509360d81946247fd0f937034cdf1f237c72Kevin Enderby
7359c41fa87eac369d84f8bfc2245084cd39f281ee4Kevin Enderby/// Force static initialization.
736ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderbyextern "C" void LLVMInitializeARMAsmParser() {
737ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
738ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby  RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
739ca9c42c4daa8f4ffd9411e11c05fb53ee1bfaf70Kevin Enderby}
740