ARMAsmParser.cpp revision 221345
1198090Srdivacky//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2198090Srdivacky//
3198090Srdivacky//                     The LLVM Compiler Infrastructure
4198090Srdivacky//
5198090Srdivacky// This file is distributed under the University of Illinois Open Source
6198090Srdivacky// License. See LICENSE.TXT for details.
7198090Srdivacky//
8198090Srdivacky//===----------------------------------------------------------------------===//
9198090Srdivacky
10198090Srdivacky#include "ARM.h"
11218893Sdim#include "ARMAddressingModes.h"
12218893Sdim#include "ARMMCExpr.h"
13218893Sdim#include "ARMBaseRegisterInfo.h"
14212904Sdim#include "ARMSubtarget.h"
15202878Srdivacky#include "llvm/MC/MCParser/MCAsmLexer.h"
16202878Srdivacky#include "llvm/MC/MCParser/MCAsmParser.h"
17202878Srdivacky#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
18218893Sdim#include "llvm/MC/MCContext.h"
19198090Srdivacky#include "llvm/MC/MCStreamer.h"
20198090Srdivacky#include "llvm/MC/MCExpr.h"
21198090Srdivacky#include "llvm/MC/MCInst.h"
22202878Srdivacky#include "llvm/Target/TargetRegistry.h"
23202878Srdivacky#include "llvm/Target/TargetAsmParser.h"
24198090Srdivacky#include "llvm/Support/SourceMgr.h"
25212904Sdim#include "llvm/Support/raw_ostream.h"
26202878Srdivacky#include "llvm/ADT/SmallVector.h"
27218893Sdim#include "llvm/ADT/StringExtras.h"
28212904Sdim#include "llvm/ADT/StringSwitch.h"
29202878Srdivacky#include "llvm/ADT/Twine.h"
30198090Srdivackyusing namespace llvm;
31198090Srdivacky
32218893Sdimnamespace {
33218893Sdim
34218893Sdimclass ARMOperand;
35218893Sdim
36198090Srdivackyclass ARMAsmParser : public TargetAsmParser {
37198090Srdivacky  MCAsmParser &Parser;
38212904Sdim  TargetMachine &TM;
39198090Srdivacky
40198090Srdivacky  MCAsmParser &getParser() const { return Parser; }
41198090Srdivacky  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
42198090Srdivacky
43198090Srdivacky  void Warning(SMLoc L, const Twine &Msg) { Parser.Warning(L, Msg); }
44198090Srdivacky  bool Error(SMLoc L, const Twine &Msg) { return Parser.Error(L, Msg); }
45198090Srdivacky
46218893Sdim  int TryParseRegister();
47218893Sdim  virtual bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
48218893Sdim  bool TryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
49221345Sdim  bool TryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
50218893Sdim  bool ParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
51221345Sdim  bool ParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &,
52221345Sdim                   ARMII::AddrMode AddrMode);
53218893Sdim  bool ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
54218893Sdim  bool ParsePrefix(ARMMCExpr::VariantKind &RefKind);
55218893Sdim  const MCExpr *ApplyPrefixToExpr(const MCExpr *E,
56218893Sdim                                  MCSymbolRefExpr::VariantKind Variant);
57198090Srdivacky
58198090Srdivacky
59198892Srdivacky  bool ParseMemoryOffsetReg(bool &Negative,
60198892Srdivacky                            bool &OffsetRegShifted,
61221345Sdim                            enum ARM_AM::ShiftOpc &ShiftType,
62198892Srdivacky                            const MCExpr *&ShiftAmount,
63198892Srdivacky                            const MCExpr *&Offset,
64198892Srdivacky                            bool &OffsetIsReg,
65206124Srdivacky                            int &OffsetRegNum,
66206124Srdivacky                            SMLoc &E);
67221345Sdim  bool ParseShift(enum ARM_AM::ShiftOpc &St,
68221345Sdim                  const MCExpr *&ShiftAmount, SMLoc &E);
69198090Srdivacky  bool ParseDirectiveWord(unsigned Size, SMLoc L);
70198396Srdivacky  bool ParseDirectiveThumb(SMLoc L);
71198396Srdivacky  bool ParseDirectiveThumbFunc(SMLoc L);
72198396Srdivacky  bool ParseDirectiveCode(SMLoc L);
73198396Srdivacky  bool ParseDirectiveSyntax(SMLoc L);
74198396Srdivacky
75218893Sdim  bool MatchAndEmitInstruction(SMLoc IDLoc,
76218893Sdim                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
77218893Sdim                               MCStreamer &Out);
78218893Sdim  void GetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
79218893Sdim                             bool &CanAcceptPredicationCode);
80198090Srdivacky
81198090Srdivacky  /// @name Auto-generated Match Functions
82198090Srdivacky  /// {
83198090Srdivacky
84218893Sdim#define GET_ASSEMBLER_HEADER
85218893Sdim#include "ARMGenAsmMatcher.inc"
86198090Srdivacky
87198090Srdivacky  /// }
88198090Srdivacky
89218893Sdim  OperandMatchResultTy tryParseCoprocNumOperand(
90218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
91218893Sdim  OperandMatchResultTy tryParseCoprocRegOperand(
92218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
93218893Sdim  OperandMatchResultTy tryParseMemBarrierOptOperand(
94218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
95218893Sdim  OperandMatchResultTy tryParseProcIFlagsOperand(
96218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
97218893Sdim  OperandMatchResultTy tryParseMSRMaskOperand(
98218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
99221345Sdim  OperandMatchResultTy tryParseMemMode2Operand(
100221345Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
101221345Sdim  OperandMatchResultTy tryParseMemMode3Operand(
102221345Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
103198090Srdivacky
104221345Sdim  // Asm Match Converter Methods
105221345Sdim  bool CvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
106221345Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
107221345Sdim  bool CvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
108221345Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
109221345Sdim  bool CvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
110221345Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
111221345Sdim  bool CvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
112221345Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
113221345Sdim
114198090Srdivackypublic:
115212904Sdim  ARMAsmParser(const Target &T, MCAsmParser &_Parser, TargetMachine &_TM)
116218893Sdim    : TargetAsmParser(T), Parser(_Parser), TM(_TM) {
117221345Sdim      MCAsmParserExtension::Initialize(_Parser);
118218893Sdim      // Initialize the set of available features.
119218893Sdim      setAvailableFeatures(ComputeAvailableFeatures(
120218893Sdim          &TM.getSubtarget<ARMSubtarget>()));
121218893Sdim    }
122198090Srdivacky
123210299Sed  virtual bool ParseInstruction(StringRef Name, SMLoc NameLoc,
124202375Srdivacky                                SmallVectorImpl<MCParsedAsmOperand*> &Operands);
125198090Srdivacky  virtual bool ParseDirective(AsmToken DirectiveID);
126198090Srdivacky};
127218893Sdim} // end anonymous namespace
128218893Sdim
129218893Sdimnamespace {
130218893Sdim
131198090Srdivacky/// ARMOperand - Instances of this class represent a parsed ARM machine
132198090Srdivacky/// instruction.
133218893Sdimclass ARMOperand : public MCParsedAsmOperand {
134206124Srdivacky  enum KindTy {
135212904Sdim    CondCode,
136218893Sdim    CCOut,
137218893Sdim    CoprocNum,
138218893Sdim    CoprocReg,
139212904Sdim    Immediate,
140218893Sdim    MemBarrierOpt,
141212904Sdim    Memory,
142218893Sdim    MSRMask,
143218893Sdim    ProcIFlags,
144198090Srdivacky    Register,
145218893Sdim    RegisterList,
146218893Sdim    DPRRegisterList,
147218893Sdim    SPRRegisterList,
148221345Sdim    Shifter,
149212904Sdim    Token
150198090Srdivacky  } Kind;
151198090Srdivacky
152206124Srdivacky  SMLoc StartLoc, EndLoc;
153218893Sdim  SmallVector<unsigned, 8> Registers;
154198090Srdivacky
155198090Srdivacky  union {
156198090Srdivacky    struct {
157212904Sdim      ARMCC::CondCodes Val;
158212904Sdim    } CC;
159212904Sdim
160212904Sdim    struct {
161218893Sdim      ARM_MB::MemBOpt Val;
162218893Sdim    } MBOpt;
163218893Sdim
164218893Sdim    struct {
165218893Sdim      unsigned Val;
166218893Sdim    } Cop;
167218893Sdim
168218893Sdim    struct {
169218893Sdim      ARM_PROC::IFlags Val;
170218893Sdim    } IFlags;
171218893Sdim
172218893Sdim    struct {
173218893Sdim      unsigned Val;
174218893Sdim    } MMask;
175218893Sdim
176218893Sdim    struct {
177198090Srdivacky      const char *Data;
178198090Srdivacky      unsigned Length;
179198090Srdivacky    } Tok;
180198090Srdivacky
181198090Srdivacky    struct {
182198090Srdivacky      unsigned RegNum;
183198090Srdivacky    } Reg;
184198090Srdivacky
185198090Srdivacky    struct {
186198090Srdivacky      const MCExpr *Val;
187198090Srdivacky    } Imm;
188218893Sdim
189218893Sdim    /// Combined record for all forms of ARM address expressions.
190198090Srdivacky    struct {
191221345Sdim      ARMII::AddrMode AddrMode;
192198090Srdivacky      unsigned BaseRegNum;
193218893Sdim      union {
194218893Sdim        unsigned RegNum;     ///< Offset register num, when OffsetIsReg.
195218893Sdim        const MCExpr *Value; ///< Offset value, when !OffsetIsReg.
196218893Sdim      } Offset;
197218893Sdim      const MCExpr *ShiftAmount;     // used when OffsetRegShifted is true
198221345Sdim      enum ARM_AM::ShiftOpc ShiftType; // used when OffsetRegShifted is true
199218893Sdim      unsigned OffsetRegShifted : 1; // only used when OffsetIsReg is true
200218893Sdim      unsigned Preindexed       : 1;
201218893Sdim      unsigned Postindexed      : 1;
202218893Sdim      unsigned OffsetIsReg      : 1;
203218893Sdim      unsigned Negative         : 1; // only used when OffsetIsReg is true
204218893Sdim      unsigned Writeback        : 1;
205198090Srdivacky    } Mem;
206221345Sdim
207221345Sdim    struct {
208221345Sdim      ARM_AM::ShiftOpc ShiftTy;
209221345Sdim      unsigned RegNum;
210221345Sdim    } Shift;
211218893Sdim  };
212198090Srdivacky
213218893Sdim  ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
214218893Sdimpublic:
215206124Srdivacky  ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
216206124Srdivacky    Kind = o.Kind;
217206124Srdivacky    StartLoc = o.StartLoc;
218206124Srdivacky    EndLoc = o.EndLoc;
219206124Srdivacky    switch (Kind) {
220212904Sdim    case CondCode:
221212904Sdim      CC = o.CC;
222212904Sdim      break;
223206124Srdivacky    case Token:
224212904Sdim      Tok = o.Tok;
225206124Srdivacky      break;
226218893Sdim    case CCOut:
227206124Srdivacky    case Register:
228206124Srdivacky      Reg = o.Reg;
229206124Srdivacky      break;
230218893Sdim    case RegisterList:
231218893Sdim    case DPRRegisterList:
232218893Sdim    case SPRRegisterList:
233218893Sdim      Registers = o.Registers;
234218893Sdim      break;
235218893Sdim    case CoprocNum:
236218893Sdim    case CoprocReg:
237218893Sdim      Cop = o.Cop;
238218893Sdim      break;
239206124Srdivacky    case Immediate:
240206124Srdivacky      Imm = o.Imm;
241206124Srdivacky      break;
242218893Sdim    case MemBarrierOpt:
243218893Sdim      MBOpt = o.MBOpt;
244218893Sdim      break;
245206124Srdivacky    case Memory:
246206124Srdivacky      Mem = o.Mem;
247206124Srdivacky      break;
248218893Sdim    case MSRMask:
249218893Sdim      MMask = o.MMask;
250218893Sdim      break;
251218893Sdim    case ProcIFlags:
252218893Sdim      IFlags = o.IFlags;
253221345Sdim      break;
254221345Sdim    case Shifter:
255221345Sdim      Shift = o.Shift;
256221345Sdim      break;
257206124Srdivacky    }
258206124Srdivacky  }
259218893Sdim
260206124Srdivacky  /// getStartLoc - Get the location of the first token of this operand.
261206124Srdivacky  SMLoc getStartLoc() const { return StartLoc; }
262206124Srdivacky  /// getEndLoc - Get the location of the last token of this operand.
263206124Srdivacky  SMLoc getEndLoc() const { return EndLoc; }
264198090Srdivacky
265212904Sdim  ARMCC::CondCodes getCondCode() const {
266212904Sdim    assert(Kind == CondCode && "Invalid access!");
267212904Sdim    return CC.Val;
268212904Sdim  }
269212904Sdim
270218893Sdim  unsigned getCoproc() const {
271218893Sdim    assert((Kind == CoprocNum || Kind == CoprocReg) && "Invalid access!");
272218893Sdim    return Cop.Val;
273218893Sdim  }
274218893Sdim
275198090Srdivacky  StringRef getToken() const {
276198090Srdivacky    assert(Kind == Token && "Invalid access!");
277198090Srdivacky    return StringRef(Tok.Data, Tok.Length);
278198090Srdivacky  }
279198090Srdivacky
280198090Srdivacky  unsigned getReg() const {
281218893Sdim    assert((Kind == Register || Kind == CCOut) && "Invalid access!");
282198090Srdivacky    return Reg.RegNum;
283198090Srdivacky  }
284198090Srdivacky
285218893Sdim  const SmallVectorImpl<unsigned> &getRegList() const {
286218893Sdim    assert((Kind == RegisterList || Kind == DPRRegisterList ||
287218893Sdim            Kind == SPRRegisterList) && "Invalid access!");
288218893Sdim    return Registers;
289218893Sdim  }
290218893Sdim
291198090Srdivacky  const MCExpr *getImm() const {
292198090Srdivacky    assert(Kind == Immediate && "Invalid access!");
293198090Srdivacky    return Imm.Val;
294198090Srdivacky  }
295198090Srdivacky
296218893Sdim  ARM_MB::MemBOpt getMemBarrierOpt() const {
297218893Sdim    assert(Kind == MemBarrierOpt && "Invalid access!");
298218893Sdim    return MBOpt.Val;
299218893Sdim  }
300218893Sdim
301218893Sdim  ARM_PROC::IFlags getProcIFlags() const {
302218893Sdim    assert(Kind == ProcIFlags && "Invalid access!");
303218893Sdim    return IFlags.Val;
304218893Sdim  }
305218893Sdim
306218893Sdim  unsigned getMSRMask() const {
307218893Sdim    assert(Kind == MSRMask && "Invalid access!");
308218893Sdim    return MMask.Val;
309218893Sdim  }
310218893Sdim
311218893Sdim  /// @name Memory Operand Accessors
312218893Sdim  /// @{
313221345Sdim  ARMII::AddrMode getMemAddrMode() const {
314221345Sdim    return Mem.AddrMode;
315221345Sdim  }
316218893Sdim  unsigned getMemBaseRegNum() const {
317218893Sdim    return Mem.BaseRegNum;
318218893Sdim  }
319218893Sdim  unsigned getMemOffsetRegNum() const {
320218893Sdim    assert(Mem.OffsetIsReg && "Invalid access!");
321218893Sdim    return Mem.Offset.RegNum;
322218893Sdim  }
323218893Sdim  const MCExpr *getMemOffset() const {
324218893Sdim    assert(!Mem.OffsetIsReg && "Invalid access!");
325218893Sdim    return Mem.Offset.Value;
326218893Sdim  }
327218893Sdim  unsigned getMemOffsetRegShifted() const {
328218893Sdim    assert(Mem.OffsetIsReg && "Invalid access!");
329218893Sdim    return Mem.OffsetRegShifted;
330218893Sdim  }
331218893Sdim  const MCExpr *getMemShiftAmount() const {
332218893Sdim    assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!");
333218893Sdim    return Mem.ShiftAmount;
334218893Sdim  }
335221345Sdim  enum ARM_AM::ShiftOpc getMemShiftType() const {
336218893Sdim    assert(Mem.OffsetIsReg && Mem.OffsetRegShifted && "Invalid access!");
337218893Sdim    return Mem.ShiftType;
338218893Sdim  }
339218893Sdim  bool getMemPreindexed() const { return Mem.Preindexed; }
340218893Sdim  bool getMemPostindexed() const { return Mem.Postindexed; }
341218893Sdim  bool getMemOffsetIsReg() const { return Mem.OffsetIsReg; }
342218893Sdim  bool getMemNegative() const { return Mem.Negative; }
343218893Sdim  bool getMemWriteback() const { return Mem.Writeback; }
344218893Sdim
345218893Sdim  /// @}
346218893Sdim
347218893Sdim  bool isCoprocNum() const { return Kind == CoprocNum; }
348218893Sdim  bool isCoprocReg() const { return Kind == CoprocReg; }
349212904Sdim  bool isCondCode() const { return Kind == CondCode; }
350218893Sdim  bool isCCOut() const { return Kind == CCOut; }
351212904Sdim  bool isImm() const { return Kind == Immediate; }
352198090Srdivacky  bool isReg() const { return Kind == Register; }
353218893Sdim  bool isRegList() const { return Kind == RegisterList; }
354218893Sdim  bool isDPRRegList() const { return Kind == DPRRegisterList; }
355218893Sdim  bool isSPRRegList() const { return Kind == SPRRegisterList; }
356218893Sdim  bool isToken() const { return Kind == Token; }
357218893Sdim  bool isMemBarrierOpt() const { return Kind == MemBarrierOpt; }
358218893Sdim  bool isMemory() const { return Kind == Memory; }
359221345Sdim  bool isShifter() const { return Kind == Shifter; }
360221345Sdim  bool isMemMode2() const {
361221345Sdim    if (getMemAddrMode() != ARMII::AddrMode2)
362221345Sdim      return false;
363221345Sdim
364221345Sdim    if (getMemOffsetIsReg())
365221345Sdim      return true;
366221345Sdim
367221345Sdim    if (getMemNegative() &&
368221345Sdim        !(getMemPostindexed() || getMemPreindexed()))
369221345Sdim      return false;
370221345Sdim
371221345Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
372221345Sdim    if (!CE) return false;
373221345Sdim    int64_t Value = CE->getValue();
374221345Sdim
375221345Sdim    // The offset must be in the range 0-4095 (imm12).
376221345Sdim    if (Value > 4095 || Value < -4095)
377221345Sdim      return false;
378221345Sdim
379221345Sdim    return true;
380221345Sdim  }
381221345Sdim  bool isMemMode3() const {
382221345Sdim    if (getMemAddrMode() != ARMII::AddrMode3)
383221345Sdim      return false;
384221345Sdim
385221345Sdim    if (getMemOffsetIsReg()) {
386221345Sdim      if (getMemOffsetRegShifted())
387221345Sdim        return false; // No shift with offset reg allowed
388221345Sdim      return true;
389221345Sdim    }
390221345Sdim
391221345Sdim    if (getMemNegative() &&
392221345Sdim        !(getMemPostindexed() || getMemPreindexed()))
393221345Sdim      return false;
394221345Sdim
395221345Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
396221345Sdim    if (!CE) return false;
397221345Sdim    int64_t Value = CE->getValue();
398221345Sdim
399221345Sdim    // The offset must be in the range 0-255 (imm8).
400221345Sdim    if (Value > 255 || Value < -255)
401221345Sdim      return false;
402221345Sdim
403221345Sdim    return true;
404221345Sdim  }
405218893Sdim  bool isMemMode5() const {
406218893Sdim    if (!isMemory() || getMemOffsetIsReg() || getMemWriteback() ||
407218893Sdim        getMemNegative())
408218893Sdim      return false;
409198090Srdivacky
410218893Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
411218893Sdim    if (!CE) return false;
412212904Sdim
413218893Sdim    // The offset must be a multiple of 4 in the range 0-1020.
414218893Sdim    int64_t Value = CE->getValue();
415218893Sdim    return ((Value & 0x3) == 0 && Value <= 1020 && Value >= -1020);
416218893Sdim  }
417221345Sdim  bool isMemMode7() const {
418221345Sdim    if (!isMemory() ||
419221345Sdim        getMemPreindexed() ||
420221345Sdim        getMemPostindexed() ||
421221345Sdim        getMemOffsetIsReg() ||
422221345Sdim        getMemNegative() ||
423221345Sdim        getMemWriteback())
424221345Sdim      return false;
425221345Sdim
426221345Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
427221345Sdim    if (!CE) return false;
428221345Sdim
429221345Sdim    if (CE->getValue())
430221345Sdim      return false;
431221345Sdim
432221345Sdim    return true;
433221345Sdim  }
434218893Sdim  bool isMemModeRegThumb() const {
435218893Sdim    if (!isMemory() || !getMemOffsetIsReg() || getMemWriteback())
436218893Sdim      return false;
437218893Sdim    return true;
438218893Sdim  }
439218893Sdim  bool isMemModeImmThumb() const {
440218893Sdim    if (!isMemory() || getMemOffsetIsReg() || getMemWriteback())
441218893Sdim      return false;
442218893Sdim
443218893Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
444218893Sdim    if (!CE) return false;
445218893Sdim
446218893Sdim    // The offset must be a multiple of 4 in the range 0-124.
447218893Sdim    uint64_t Value = CE->getValue();
448218893Sdim    return ((Value & 0x3) == 0 && Value <= 124);
449218893Sdim  }
450218893Sdim  bool isMSRMask() const { return Kind == MSRMask; }
451218893Sdim  bool isProcIFlags() const { return Kind == ProcIFlags; }
452218893Sdim
453212904Sdim  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
454218893Sdim    // Add as immediates when possible.  Null MCExpr = 0.
455218893Sdim    if (Expr == 0)
456218893Sdim      Inst.addOperand(MCOperand::CreateImm(0));
457218893Sdim    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
458212904Sdim      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
459212904Sdim    else
460212904Sdim      Inst.addOperand(MCOperand::CreateExpr(Expr));
461212904Sdim  }
462212904Sdim
463212904Sdim  void addCondCodeOperands(MCInst &Inst, unsigned N) const {
464212904Sdim    assert(N == 2 && "Invalid number of operands!");
465212904Sdim    Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
466218893Sdim    unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
467218893Sdim    Inst.addOperand(MCOperand::CreateReg(RegNum));
468212904Sdim  }
469212904Sdim
470218893Sdim  void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
471218893Sdim    assert(N == 1 && "Invalid number of operands!");
472218893Sdim    Inst.addOperand(MCOperand::CreateImm(getCoproc()));
473218893Sdim  }
474218893Sdim
475218893Sdim  void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
476218893Sdim    assert(N == 1 && "Invalid number of operands!");
477218893Sdim    Inst.addOperand(MCOperand::CreateImm(getCoproc()));
478218893Sdim  }
479218893Sdim
480218893Sdim  void addCCOutOperands(MCInst &Inst, unsigned N) const {
481218893Sdim    assert(N == 1 && "Invalid number of operands!");
482218893Sdim    Inst.addOperand(MCOperand::CreateReg(getReg()));
483218893Sdim  }
484218893Sdim
485198090Srdivacky  void addRegOperands(MCInst &Inst, unsigned N) const {
486198090Srdivacky    assert(N == 1 && "Invalid number of operands!");
487198090Srdivacky    Inst.addOperand(MCOperand::CreateReg(getReg()));
488198090Srdivacky  }
489198090Srdivacky
490221345Sdim  void addShifterOperands(MCInst &Inst, unsigned N) const {
491221345Sdim    assert(N == 1 && "Invalid number of operands!");
492221345Sdim    Inst.addOperand(MCOperand::CreateImm(
493221345Sdim      ARM_AM::getSORegOpc(Shift.ShiftTy, 0)));
494221345Sdim  }
495221345Sdim
496218893Sdim  void addRegListOperands(MCInst &Inst, unsigned N) const {
497218893Sdim    assert(N == 1 && "Invalid number of operands!");
498218893Sdim    const SmallVectorImpl<unsigned> &RegList = getRegList();
499218893Sdim    for (SmallVectorImpl<unsigned>::const_iterator
500218893Sdim           I = RegList.begin(), E = RegList.end(); I != E; ++I)
501218893Sdim      Inst.addOperand(MCOperand::CreateReg(*I));
502218893Sdim  }
503218893Sdim
504218893Sdim  void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
505218893Sdim    addRegListOperands(Inst, N);
506218893Sdim  }
507218893Sdim
508218893Sdim  void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
509218893Sdim    addRegListOperands(Inst, N);
510218893Sdim  }
511218893Sdim
512212904Sdim  void addImmOperands(MCInst &Inst, unsigned N) const {
513212904Sdim    assert(N == 1 && "Invalid number of operands!");
514212904Sdim    addExpr(Inst, getImm());
515212904Sdim  }
516212904Sdim
517218893Sdim  void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
518218893Sdim    assert(N == 1 && "Invalid number of operands!");
519218893Sdim    Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
520218893Sdim  }
521218893Sdim
522221345Sdim  void addMemMode7Operands(MCInst &Inst, unsigned N) const {
523221345Sdim    assert(N == 1 && isMemMode7() && "Invalid number of operands!");
524221345Sdim    Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
525221345Sdim
526221345Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
527221345Sdim    (void)CE;
528221345Sdim    assert((CE || CE->getValue() == 0) &&
529221345Sdim           "No offset operand support in mode 7");
530221345Sdim  }
531221345Sdim
532221345Sdim  void addMemMode2Operands(MCInst &Inst, unsigned N) const {
533221345Sdim    assert(isMemMode2() && "Invalid mode or number of operands!");
534221345Sdim    Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
535221345Sdim    unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);
536221345Sdim
537221345Sdim    if (getMemOffsetIsReg()) {
538221345Sdim      Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
539221345Sdim
540221345Sdim      ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;
541221345Sdim      ARM_AM::ShiftOpc ShOpc = ARM_AM::no_shift;
542221345Sdim      int64_t ShiftAmount = 0;
543221345Sdim
544221345Sdim      if (getMemOffsetRegShifted()) {
545221345Sdim        ShOpc = getMemShiftType();
546221345Sdim        const MCConstantExpr *CE =
547221345Sdim                   dyn_cast<MCConstantExpr>(getMemShiftAmount());
548221345Sdim        ShiftAmount = CE->getValue();
549221345Sdim      }
550221345Sdim
551221345Sdim      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(AMOpc, ShiftAmount,
552221345Sdim                                           ShOpc, IdxMode)));
553221345Sdim      return;
554221345Sdim    }
555221345Sdim
556221345Sdim    // Create a operand placeholder to always yield the same number of operands.
557221345Sdim    Inst.addOperand(MCOperand::CreateReg(0));
558221345Sdim
559221345Sdim    // FIXME: #-0 is encoded differently than #0. Does the parser preserve
560221345Sdim    // the difference?
561221345Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
562221345Sdim    assert(CE && "Non-constant mode 2 offset operand!");
563221345Sdim    int64_t Offset = CE->getValue();
564221345Sdim
565221345Sdim    if (Offset >= 0)
566221345Sdim      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::add,
567221345Sdim                                           Offset, ARM_AM::no_shift, IdxMode)));
568221345Sdim    else
569221345Sdim      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM2Opc(ARM_AM::sub,
570221345Sdim                                          -Offset, ARM_AM::no_shift, IdxMode)));
571221345Sdim  }
572221345Sdim
573221345Sdim  void addMemMode3Operands(MCInst &Inst, unsigned N) const {
574221345Sdim    assert(isMemMode3() && "Invalid mode or number of operands!");
575221345Sdim    Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
576221345Sdim    unsigned IdxMode = (getMemPreindexed() | getMemPostindexed() << 1);
577221345Sdim
578221345Sdim    if (getMemOffsetIsReg()) {
579221345Sdim      Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
580221345Sdim
581221345Sdim      ARM_AM::AddrOpc AMOpc = getMemNegative() ? ARM_AM::sub : ARM_AM::add;
582221345Sdim      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(AMOpc, 0,
583221345Sdim                                                             IdxMode)));
584221345Sdim      return;
585221345Sdim    }
586221345Sdim
587221345Sdim    // Create a operand placeholder to always yield the same number of operands.
588221345Sdim    Inst.addOperand(MCOperand::CreateReg(0));
589221345Sdim
590221345Sdim    // FIXME: #-0 is encoded differently than #0. Does the parser preserve
591221345Sdim    // the difference?
592221345Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
593221345Sdim    assert(CE && "Non-constant mode 3 offset operand!");
594221345Sdim    int64_t Offset = CE->getValue();
595221345Sdim
596221345Sdim    if (Offset >= 0)
597221345Sdim      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::add,
598221345Sdim                                           Offset, IdxMode)));
599221345Sdim    else
600221345Sdim      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM3Opc(ARM_AM::sub,
601221345Sdim                                           -Offset, IdxMode)));
602221345Sdim  }
603221345Sdim
604218893Sdim  void addMemMode5Operands(MCInst &Inst, unsigned N) const {
605218893Sdim    assert(N == 2 && isMemMode5() && "Invalid number of operands!");
606218893Sdim
607218893Sdim    Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
608218893Sdim    assert(!getMemOffsetIsReg() && "Invalid mode 5 operand");
609218893Sdim
610218893Sdim    // FIXME: #-0 is encoded differently than #0. Does the parser preserve
611218893Sdim    // the difference?
612218893Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
613218893Sdim    assert(CE && "Non-constant mode 5 offset operand!");
614218893Sdim
615218893Sdim    // The MCInst offset operand doesn't include the low two bits (like
616218893Sdim    // the instruction encoding).
617218893Sdim    int64_t Offset = CE->getValue() / 4;
618218893Sdim    if (Offset >= 0)
619218893Sdim      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::add,
620218893Sdim                                                             Offset)));
621218893Sdim    else
622218893Sdim      Inst.addOperand(MCOperand::CreateImm(ARM_AM::getAM5Opc(ARM_AM::sub,
623218893Sdim                                                             -Offset)));
624218893Sdim  }
625218893Sdim
626218893Sdim  void addMemModeRegThumbOperands(MCInst &Inst, unsigned N) const {
627218893Sdim    assert(N == 2 && isMemModeRegThumb() && "Invalid number of operands!");
628218893Sdim    Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
629218893Sdim    Inst.addOperand(MCOperand::CreateReg(getMemOffsetRegNum()));
630218893Sdim  }
631218893Sdim
632218893Sdim  void addMemModeImmThumbOperands(MCInst &Inst, unsigned N) const {
633218893Sdim    assert(N == 2 && isMemModeImmThumb() && "Invalid number of operands!");
634218893Sdim    Inst.addOperand(MCOperand::CreateReg(getMemBaseRegNum()));
635218893Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getMemOffset());
636218893Sdim    assert(CE && "Non-constant mode offset operand!");
637218893Sdim    Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
638218893Sdim  }
639218893Sdim
640218893Sdim  void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
641218893Sdim    assert(N == 1 && "Invalid number of operands!");
642218893Sdim    Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
643218893Sdim  }
644218893Sdim
645218893Sdim  void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
646218893Sdim    assert(N == 1 && "Invalid number of operands!");
647218893Sdim    Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
648218893Sdim  }
649218893Sdim
650212904Sdim  virtual void dump(raw_ostream &OS) const;
651212904Sdim
652218893Sdim  static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
653218893Sdim    ARMOperand *Op = new ARMOperand(CondCode);
654212904Sdim    Op->CC.Val = CC;
655212904Sdim    Op->StartLoc = S;
656212904Sdim    Op->EndLoc = S;
657218893Sdim    return Op;
658212904Sdim  }
659212904Sdim
660218893Sdim  static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
661218893Sdim    ARMOperand *Op = new ARMOperand(CoprocNum);
662218893Sdim    Op->Cop.Val = CopVal;
663218893Sdim    Op->StartLoc = S;
664218893Sdim    Op->EndLoc = S;
665218893Sdim    return Op;
666218893Sdim  }
667218893Sdim
668218893Sdim  static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
669218893Sdim    ARMOperand *Op = new ARMOperand(CoprocReg);
670218893Sdim    Op->Cop.Val = CopVal;
671218893Sdim    Op->StartLoc = S;
672218893Sdim    Op->EndLoc = S;
673218893Sdim    return Op;
674218893Sdim  }
675218893Sdim
676218893Sdim  static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
677218893Sdim    ARMOperand *Op = new ARMOperand(CCOut);
678218893Sdim    Op->Reg.RegNum = RegNum;
679218893Sdim    Op->StartLoc = S;
680218893Sdim    Op->EndLoc = S;
681218893Sdim    return Op;
682218893Sdim  }
683218893Sdim
684218893Sdim  static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
685218893Sdim    ARMOperand *Op = new ARMOperand(Token);
686206124Srdivacky    Op->Tok.Data = Str.data();
687206124Srdivacky    Op->Tok.Length = Str.size();
688206124Srdivacky    Op->StartLoc = S;
689206124Srdivacky    Op->EndLoc = S;
690218893Sdim    return Op;
691198090Srdivacky  }
692198090Srdivacky
693218893Sdim  static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
694218893Sdim    ARMOperand *Op = new ARMOperand(Register);
695206124Srdivacky    Op->Reg.RegNum = RegNum;
696206124Srdivacky    Op->StartLoc = S;
697206124Srdivacky    Op->EndLoc = E;
698218893Sdim    return Op;
699198090Srdivacky  }
700198090Srdivacky
701221345Sdim  static ARMOperand *CreateShifter(ARM_AM::ShiftOpc ShTy,
702221345Sdim                                   SMLoc S, SMLoc E) {
703221345Sdim    ARMOperand *Op = new ARMOperand(Shifter);
704221345Sdim    Op->Shift.ShiftTy = ShTy;
705221345Sdim    Op->StartLoc = S;
706221345Sdim    Op->EndLoc = E;
707221345Sdim    return Op;
708221345Sdim  }
709221345Sdim
710218893Sdim  static ARMOperand *
711218893Sdim  CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
712218893Sdim                SMLoc StartLoc, SMLoc EndLoc) {
713218893Sdim    KindTy Kind = RegisterList;
714218893Sdim
715218893Sdim    if (ARM::DPRRegClass.contains(Regs.front().first))
716218893Sdim      Kind = DPRRegisterList;
717218893Sdim    else if (ARM::SPRRegClass.contains(Regs.front().first))
718218893Sdim      Kind = SPRRegisterList;
719218893Sdim
720218893Sdim    ARMOperand *Op = new ARMOperand(Kind);
721218893Sdim    for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
722218893Sdim           I = Regs.begin(), E = Regs.end(); I != E; ++I)
723218893Sdim      Op->Registers.push_back(I->first);
724218893Sdim    array_pod_sort(Op->Registers.begin(), Op->Registers.end());
725218893Sdim    Op->StartLoc = StartLoc;
726218893Sdim    Op->EndLoc = EndLoc;
727218893Sdim    return Op;
728218893Sdim  }
729218893Sdim
730218893Sdim  static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
731218893Sdim    ARMOperand *Op = new ARMOperand(Immediate);
732206124Srdivacky    Op->Imm.Val = Val;
733206124Srdivacky    Op->StartLoc = S;
734206124Srdivacky    Op->EndLoc = E;
735218893Sdim    return Op;
736198090Srdivacky  }
737198090Srdivacky
738221345Sdim  static ARMOperand *CreateMem(ARMII::AddrMode AddrMode, unsigned BaseRegNum,
739221345Sdim                               bool OffsetIsReg, const MCExpr *Offset,
740221345Sdim                               int OffsetRegNum, bool OffsetRegShifted,
741221345Sdim                               enum ARM_AM::ShiftOpc ShiftType,
742218893Sdim                               const MCExpr *ShiftAmount, bool Preindexed,
743218893Sdim                               bool Postindexed, bool Negative, bool Writeback,
744218893Sdim                               SMLoc S, SMLoc E) {
745218893Sdim    assert((OffsetRegNum == -1 || OffsetIsReg) &&
746218893Sdim           "OffsetRegNum must imply OffsetIsReg!");
747218893Sdim    assert((!OffsetRegShifted || OffsetIsReg) &&
748218893Sdim           "OffsetRegShifted must imply OffsetIsReg!");
749218893Sdim    assert((Offset || OffsetIsReg) &&
750218893Sdim           "Offset must exists unless register offset is used!");
751218893Sdim    assert((!ShiftAmount || (OffsetIsReg && OffsetRegShifted)) &&
752218893Sdim           "Cannot have shift amount without shifted register offset!");
753218893Sdim    assert((!Offset || !OffsetIsReg) &&
754218893Sdim           "Cannot have expression offset and register offset!");
755218893Sdim
756218893Sdim    ARMOperand *Op = new ARMOperand(Memory);
757221345Sdim    Op->Mem.AddrMode = AddrMode;
758206124Srdivacky    Op->Mem.BaseRegNum = BaseRegNum;
759206124Srdivacky    Op->Mem.OffsetIsReg = OffsetIsReg;
760218893Sdim    if (OffsetIsReg)
761218893Sdim      Op->Mem.Offset.RegNum = OffsetRegNum;
762218893Sdim    else
763218893Sdim      Op->Mem.Offset.Value = Offset;
764206124Srdivacky    Op->Mem.OffsetRegShifted = OffsetRegShifted;
765206124Srdivacky    Op->Mem.ShiftType = ShiftType;
766206124Srdivacky    Op->Mem.ShiftAmount = ShiftAmount;
767206124Srdivacky    Op->Mem.Preindexed = Preindexed;
768206124Srdivacky    Op->Mem.Postindexed = Postindexed;
769206124Srdivacky    Op->Mem.Negative = Negative;
770206124Srdivacky    Op->Mem.Writeback = Writeback;
771218893Sdim
772206124Srdivacky    Op->StartLoc = S;
773206124Srdivacky    Op->EndLoc = E;
774218893Sdim    return Op;
775198090Srdivacky  }
776218893Sdim
777218893Sdim  static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
778218893Sdim    ARMOperand *Op = new ARMOperand(MemBarrierOpt);
779218893Sdim    Op->MBOpt.Val = Opt;
780218893Sdim    Op->StartLoc = S;
781218893Sdim    Op->EndLoc = S;
782218893Sdim    return Op;
783218893Sdim  }
784218893Sdim
785218893Sdim  static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
786218893Sdim    ARMOperand *Op = new ARMOperand(ProcIFlags);
787218893Sdim    Op->IFlags.Val = IFlags;
788218893Sdim    Op->StartLoc = S;
789218893Sdim    Op->EndLoc = S;
790218893Sdim    return Op;
791218893Sdim  }
792218893Sdim
793218893Sdim  static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
794218893Sdim    ARMOperand *Op = new ARMOperand(MSRMask);
795218893Sdim    Op->MMask.Val = MMask;
796218893Sdim    Op->StartLoc = S;
797218893Sdim    Op->EndLoc = S;
798218893Sdim    return Op;
799218893Sdim  }
800198090Srdivacky};
801198090Srdivacky
802198090Srdivacky} // end anonymous namespace.
803198090Srdivacky
804212904Sdimvoid ARMOperand::dump(raw_ostream &OS) const {
805212904Sdim  switch (Kind) {
806212904Sdim  case CondCode:
807218893Sdim    OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
808212904Sdim    break;
809218893Sdim  case CCOut:
810218893Sdim    OS << "<ccout " << getReg() << ">";
811218893Sdim    break;
812218893Sdim  case CoprocNum:
813218893Sdim    OS << "<coprocessor number: " << getCoproc() << ">";
814218893Sdim    break;
815218893Sdim  case CoprocReg:
816218893Sdim    OS << "<coprocessor register: " << getCoproc() << ">";
817218893Sdim    break;
818218893Sdim  case MSRMask:
819218893Sdim    OS << "<mask: " << getMSRMask() << ">";
820218893Sdim    break;
821212904Sdim  case Immediate:
822212904Sdim    getImm()->print(OS);
823212904Sdim    break;
824218893Sdim  case MemBarrierOpt:
825218893Sdim    OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
826218893Sdim    break;
827212904Sdim  case Memory:
828218893Sdim    OS << "<memory "
829221345Sdim       << "am:" << ARMII::AddrModeToString(getMemAddrMode())
830221345Sdim       << " base:" << getMemBaseRegNum();
831218893Sdim    if (getMemOffsetIsReg()) {
832218893Sdim      OS << " offset:<register " << getMemOffsetRegNum();
833218893Sdim      if (getMemOffsetRegShifted()) {
834218893Sdim        OS << " offset-shift-type:" << getMemShiftType();
835218893Sdim        OS << " offset-shift-amount:" << *getMemShiftAmount();
836218893Sdim      }
837218893Sdim    } else {
838218893Sdim      OS << " offset:" << *getMemOffset();
839218893Sdim    }
840218893Sdim    if (getMemOffsetIsReg())
841218893Sdim      OS << " (offset-is-reg)";
842218893Sdim    if (getMemPreindexed())
843218893Sdim      OS << " (pre-indexed)";
844218893Sdim    if (getMemPostindexed())
845218893Sdim      OS << " (post-indexed)";
846218893Sdim    if (getMemNegative())
847218893Sdim      OS << " (negative)";
848218893Sdim    if (getMemWriteback())
849218893Sdim      OS << " (writeback)";
850218893Sdim    OS << ">";
851212904Sdim    break;
852218893Sdim  case ProcIFlags: {
853218893Sdim    OS << "<ARM_PROC::";
854218893Sdim    unsigned IFlags = getProcIFlags();
855218893Sdim    for (int i=2; i >= 0; --i)
856218893Sdim      if (IFlags & (1 << i))
857218893Sdim        OS << ARM_PROC::IFlagsToString(1 << i);
858218893Sdim    OS << ">";
859218893Sdim    break;
860218893Sdim  }
861212904Sdim  case Register:
862212904Sdim    OS << "<register " << getReg() << ">";
863212904Sdim    break;
864221345Sdim  case Shifter:
865221345Sdim    OS << "<shifter " << getShiftOpcStr(Shift.ShiftTy) << ">";
866221345Sdim    break;
867218893Sdim  case RegisterList:
868218893Sdim  case DPRRegisterList:
869218893Sdim  case SPRRegisterList: {
870218893Sdim    OS << "<register_list ";
871218893Sdim
872218893Sdim    const SmallVectorImpl<unsigned> &RegList = getRegList();
873218893Sdim    for (SmallVectorImpl<unsigned>::const_iterator
874218893Sdim           I = RegList.begin(), E = RegList.end(); I != E; ) {
875218893Sdim      OS << *I;
876218893Sdim      if (++I < E) OS << ", ";
877218893Sdim    }
878218893Sdim
879218893Sdim    OS << ">";
880218893Sdim    break;
881218893Sdim  }
882212904Sdim  case Token:
883212904Sdim    OS << "'" << getToken() << "'";
884212904Sdim    break;
885212904Sdim  }
886212904Sdim}
887212904Sdim
888212904Sdim/// @name Auto-generated Match Functions
889212904Sdim/// {
890212904Sdim
891212904Sdimstatic unsigned MatchRegisterName(StringRef Name);
892212904Sdim
893212904Sdim/// }
894212904Sdim
895218893Sdimbool ARMAsmParser::ParseRegister(unsigned &RegNo,
896218893Sdim                                 SMLoc &StartLoc, SMLoc &EndLoc) {
897218893Sdim  RegNo = TryParseRegister();
898218893Sdim
899218893Sdim  return (RegNo == (unsigned)-1);
900218893Sdim}
901218893Sdim
902198892Srdivacky/// Try to parse a register name.  The token must be an Identifier when called,
903218893Sdim/// and if it is a register name the token is eaten and the register number is
904218893Sdim/// returned.  Otherwise return -1.
905218893Sdim///
906218893Sdimint ARMAsmParser::TryParseRegister() {
907202878Srdivacky  const AsmToken &Tok = Parser.getTok();
908198090Srdivacky  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
909198090Srdivacky
910198090Srdivacky  // FIXME: Validate register for the current architecture; we have to do
911198090Srdivacky  // validation later, so maybe there is no need for this here.
912218893Sdim  std::string upperCase = Tok.getString().str();
913218893Sdim  std::string lowerCase = LowercaseString(upperCase);
914218893Sdim  unsigned RegNum = MatchRegisterName(lowerCase);
915218893Sdim  if (!RegNum) {
916218893Sdim    RegNum = StringSwitch<unsigned>(lowerCase)
917218893Sdim      .Case("r13", ARM::SP)
918218893Sdim      .Case("r14", ARM::LR)
919218893Sdim      .Case("r15", ARM::PC)
920218893Sdim      .Case("ip", ARM::R12)
921218893Sdim      .Default(0);
922218893Sdim  }
923218893Sdim  if (!RegNum) return -1;
924198090Srdivacky
925202878Srdivacky  Parser.Lex(); // Eat identifier token.
926218893Sdim  return RegNum;
927218893Sdim}
928198090Srdivacky
929221345Sdim/// Try to parse a register name.  The token must be an Identifier when called,
930221345Sdim/// and if it is a register name the token is eaten and the register number is
931221345Sdim/// returned.  Otherwise return -1.
932221345Sdim///
933221345Sdimbool ARMAsmParser::TryParseShiftRegister(
934221345Sdim                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
935221345Sdim  SMLoc S = Parser.getTok().getLoc();
936221345Sdim  const AsmToken &Tok = Parser.getTok();
937221345Sdim  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
938221345Sdim
939221345Sdim  std::string upperCase = Tok.getString().str();
940221345Sdim  std::string lowerCase = LowercaseString(upperCase);
941221345Sdim  ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
942221345Sdim      .Case("lsl", ARM_AM::lsl)
943221345Sdim      .Case("lsr", ARM_AM::lsr)
944221345Sdim      .Case("asr", ARM_AM::asr)
945221345Sdim      .Case("ror", ARM_AM::ror)
946221345Sdim      .Case("rrx", ARM_AM::rrx)
947221345Sdim      .Default(ARM_AM::no_shift);
948221345Sdim
949221345Sdim  if (ShiftTy == ARM_AM::no_shift)
950221345Sdim    return true;
951221345Sdim
952221345Sdim  Parser.Lex(); // Eat shift-type operand;
953221345Sdim  int RegNum = TryParseRegister();
954221345Sdim  if (RegNum == -1)
955221345Sdim    return Error(Parser.getTok().getLoc(), "register expected");
956221345Sdim
957221345Sdim  Operands.push_back(ARMOperand::CreateReg(RegNum,S, Parser.getTok().getLoc()));
958221345Sdim  Operands.push_back(ARMOperand::CreateShifter(ShiftTy,
959221345Sdim                                               S, Parser.getTok().getLoc()));
960221345Sdim
961221345Sdim  return false;
962221345Sdim}
963221345Sdim
964221345Sdim
965218893Sdim/// Try to parse a register name.  The token must be an Identifier when called.
966218893Sdim/// If it's a register, an AsmOperand is created. Another AsmOperand is created
967218893Sdim/// if there is a "writeback". 'true' if it's not a register.
968218893Sdim///
969218893Sdim/// TODO this is likely to change to allow different register types and or to
970218893Sdim/// parse for a specific register type.
971218893Sdimbool ARMAsmParser::
972218893SdimTryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
973218893Sdim  SMLoc S = Parser.getTok().getLoc();
974218893Sdim  int RegNo = TryParseRegister();
975218893Sdim  if (RegNo == -1)
976218893Sdim    return true;
977218893Sdim
978218893Sdim  Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
979218893Sdim
980218893Sdim  const AsmToken &ExclaimTok = Parser.getTok();
981218893Sdim  if (ExclaimTok.is(AsmToken::Exclaim)) {
982218893Sdim    Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
983218893Sdim                                               ExclaimTok.getLoc()));
984218893Sdim    Parser.Lex(); // Eat exclaim token
985218893Sdim  }
986218893Sdim
987218893Sdim  return false;
988218893Sdim}
989218893Sdim
990218893Sdim/// MatchCoprocessorOperandName - Try to parse an coprocessor related
991218893Sdim/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
992218893Sdim/// "c5", ...
993218893Sdimstatic int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
994218893Sdim  // Use the same layout as the tablegen'erated register name matcher. Ugly,
995218893Sdim  // but efficient.
996218893Sdim  switch (Name.size()) {
997218893Sdim  default: break;
998218893Sdim  case 2:
999218893Sdim    if (Name[0] != CoprocOp)
1000218893Sdim      return -1;
1001218893Sdim    switch (Name[1]) {
1002218893Sdim    default:  return -1;
1003218893Sdim    case '0': return 0;
1004218893Sdim    case '1': return 1;
1005218893Sdim    case '2': return 2;
1006218893Sdim    case '3': return 3;
1007218893Sdim    case '4': return 4;
1008218893Sdim    case '5': return 5;
1009218893Sdim    case '6': return 6;
1010218893Sdim    case '7': return 7;
1011218893Sdim    case '8': return 8;
1012218893Sdim    case '9': return 9;
1013198892Srdivacky    }
1014218893Sdim    break;
1015218893Sdim  case 3:
1016218893Sdim    if (Name[0] != CoprocOp || Name[1] != '1')
1017218893Sdim      return -1;
1018218893Sdim    switch (Name[2]) {
1019218893Sdim    default:  return -1;
1020218893Sdim    case '0': return 10;
1021218893Sdim    case '1': return 11;
1022218893Sdim    case '2': return 12;
1023218893Sdim    case '3': return 13;
1024218893Sdim    case '4': return 14;
1025218893Sdim    case '5': return 15;
1026218893Sdim    }
1027218893Sdim    break;
1028198090Srdivacky  }
1029198090Srdivacky
1030218893Sdim  return -1;
1031218893Sdim}
1032198090Srdivacky
1033218893Sdim/// tryParseCoprocNumOperand - Try to parse an coprocessor number operand. The
1034218893Sdim/// token must be an Identifier when called, and if it is a coprocessor
1035218893Sdim/// number, the token is eaten and the operand is added to the operand list.
1036218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
1037218893SdimtryParseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1038218893Sdim  SMLoc S = Parser.getTok().getLoc();
1039218893Sdim  const AsmToken &Tok = Parser.getTok();
1040218893Sdim  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1041218893Sdim
1042218893Sdim  int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
1043218893Sdim  if (Num == -1)
1044218893Sdim    return MatchOperand_NoMatch;
1045218893Sdim
1046218893Sdim  Parser.Lex(); // Eat identifier token.
1047218893Sdim  Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
1048218893Sdim  return MatchOperand_Success;
1049198090Srdivacky}
1050198090Srdivacky
1051218893Sdim/// tryParseCoprocRegOperand - Try to parse an coprocessor register operand. The
1052218893Sdim/// token must be an Identifier when called, and if it is a coprocessor
1053218893Sdim/// number, the token is eaten and the operand is added to the operand list.
1054218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
1055218893SdimtryParseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1056218893Sdim  SMLoc S = Parser.getTok().getLoc();
1057218893Sdim  const AsmToken &Tok = Parser.getTok();
1058218893Sdim  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1059198090Srdivacky
1060218893Sdim  int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
1061218893Sdim  if (Reg == -1)
1062218893Sdim    return MatchOperand_NoMatch;
1063218893Sdim
1064202878Srdivacky  Parser.Lex(); // Eat identifier token.
1065218893Sdim  Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
1066218893Sdim  return MatchOperand_Success;
1067218893Sdim}
1068198090Srdivacky
1069218893Sdim/// Parse a register list, return it if successful else return null.  The first
1070218893Sdim/// token must be a '{' when called.
1071218893Sdimbool ARMAsmParser::
1072218893SdimParseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1073218893Sdim  assert(Parser.getTok().is(AsmToken::LCurly) &&
1074218893Sdim         "Token is not a Left Curly Brace");
1075218893Sdim  SMLoc S = Parser.getTok().getLoc();
1076198090Srdivacky
1077218893Sdim  // Read the rest of the registers in the list.
1078218893Sdim  unsigned PrevRegNum = 0;
1079218893Sdim  SmallVector<std::pair<unsigned, SMLoc>, 32> Registers;
1080218893Sdim
1081218893Sdim  do {
1082218893Sdim    bool IsRange = Parser.getTok().is(AsmToken::Minus);
1083218893Sdim    Parser.Lex(); // Eat non-identifier token.
1084218893Sdim
1085202878Srdivacky    const AsmToken &RegTok = Parser.getTok();
1086198090Srdivacky    SMLoc RegLoc = RegTok.getLoc();
1087218893Sdim    if (RegTok.isNot(AsmToken::Identifier)) {
1088218893Sdim      Error(RegLoc, "register expected");
1089218893Sdim      return true;
1090218893Sdim    }
1091198090Srdivacky
1092218893Sdim    int RegNum = TryParseRegister();
1093218893Sdim    if (RegNum == -1) {
1094218893Sdim      Error(RegLoc, "register expected");
1095218893Sdim      return true;
1096218893Sdim    }
1097198090Srdivacky
1098218893Sdim    if (IsRange) {
1099218893Sdim      int Reg = PrevRegNum;
1100218893Sdim      do {
1101218893Sdim        ++Reg;
1102218893Sdim        Registers.push_back(std::make_pair(Reg, RegLoc));
1103218893Sdim      } while (Reg != RegNum);
1104218893Sdim    } else {
1105218893Sdim      Registers.push_back(std::make_pair(RegNum, RegLoc));
1106218893Sdim    }
1107218893Sdim
1108218893Sdim    PrevRegNum = RegNum;
1109218893Sdim  } while (Parser.getTok().is(AsmToken::Comma) ||
1110218893Sdim           Parser.getTok().is(AsmToken::Minus));
1111218893Sdim
1112218893Sdim  // Process the right curly brace of the list.
1113218893Sdim  const AsmToken &RCurlyTok = Parser.getTok();
1114218893Sdim  if (RCurlyTok.isNot(AsmToken::RCurly)) {
1115218893Sdim    Error(RCurlyTok.getLoc(), "'}' expected");
1116218893Sdim    return true;
1117198090Srdivacky  }
1118198090Srdivacky
1119218893Sdim  SMLoc E = RCurlyTok.getLoc();
1120218893Sdim  Parser.Lex(); // Eat right curly brace token.
1121218893Sdim
1122218893Sdim  // Verify the register list.
1123218893Sdim  SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
1124218893Sdim    RI = Registers.begin(), RE = Registers.end();
1125218893Sdim
1126218893Sdim  unsigned HighRegNum = getARMRegisterNumbering(RI->first);
1127218893Sdim  bool EmittedWarning = false;
1128218893Sdim
1129218893Sdim  DenseMap<unsigned, bool> RegMap;
1130218893Sdim  RegMap[HighRegNum] = true;
1131218893Sdim
1132218893Sdim  for (++RI; RI != RE; ++RI) {
1133218893Sdim    const std::pair<unsigned, SMLoc> &RegInfo = *RI;
1134218893Sdim    unsigned Reg = getARMRegisterNumbering(RegInfo.first);
1135218893Sdim
1136218893Sdim    if (RegMap[Reg]) {
1137218893Sdim      Error(RegInfo.second, "register duplicated in register list");
1138218893Sdim      return true;
1139218893Sdim    }
1140218893Sdim
1141218893Sdim    if (!EmittedWarning && Reg < HighRegNum)
1142218893Sdim      Warning(RegInfo.second,
1143218893Sdim              "register not in ascending order in register list");
1144218893Sdim
1145218893Sdim    RegMap[Reg] = true;
1146218893Sdim    HighRegNum = std::max(Reg, HighRegNum);
1147218893Sdim  }
1148218893Sdim
1149218893Sdim  Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
1150198090Srdivacky  return false;
1151198090Srdivacky}
1152198090Srdivacky
1153218893Sdim/// tryParseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
1154218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
1155218893SdimtryParseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1156218893Sdim  SMLoc S = Parser.getTok().getLoc();
1157218893Sdim  const AsmToken &Tok = Parser.getTok();
1158218893Sdim  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1159218893Sdim  StringRef OptStr = Tok.getString();
1160218893Sdim
1161218893Sdim  unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
1162218893Sdim    .Case("sy",    ARM_MB::SY)
1163218893Sdim    .Case("st",    ARM_MB::ST)
1164218893Sdim    .Case("ish",   ARM_MB::ISH)
1165218893Sdim    .Case("ishst", ARM_MB::ISHST)
1166218893Sdim    .Case("nsh",   ARM_MB::NSH)
1167218893Sdim    .Case("nshst", ARM_MB::NSHST)
1168218893Sdim    .Case("osh",   ARM_MB::OSH)
1169218893Sdim    .Case("oshst", ARM_MB::OSHST)
1170218893Sdim    .Default(~0U);
1171218893Sdim
1172218893Sdim  if (Opt == ~0U)
1173218893Sdim    return MatchOperand_NoMatch;
1174218893Sdim
1175218893Sdim  Parser.Lex(); // Eat identifier token.
1176218893Sdim  Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
1177218893Sdim  return MatchOperand_Success;
1178218893Sdim}
1179218893Sdim
1180218893Sdim/// tryParseProcIFlagsOperand - Try to parse iflags from CPS instruction.
1181218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
1182218893SdimtryParseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1183218893Sdim  SMLoc S = Parser.getTok().getLoc();
1184218893Sdim  const AsmToken &Tok = Parser.getTok();
1185218893Sdim  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1186218893Sdim  StringRef IFlagsStr = Tok.getString();
1187218893Sdim
1188218893Sdim  unsigned IFlags = 0;
1189218893Sdim  for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
1190218893Sdim    unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
1191218893Sdim    .Case("a", ARM_PROC::A)
1192218893Sdim    .Case("i", ARM_PROC::I)
1193218893Sdim    .Case("f", ARM_PROC::F)
1194218893Sdim    .Default(~0U);
1195218893Sdim
1196218893Sdim    // If some specific iflag is already set, it means that some letter is
1197218893Sdim    // present more than once, this is not acceptable.
1198218893Sdim    if (Flag == ~0U || (IFlags & Flag))
1199218893Sdim      return MatchOperand_NoMatch;
1200218893Sdim
1201218893Sdim    IFlags |= Flag;
1202218893Sdim  }
1203218893Sdim
1204218893Sdim  Parser.Lex(); // Eat identifier token.
1205218893Sdim  Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
1206218893Sdim  return MatchOperand_Success;
1207218893Sdim}
1208218893Sdim
1209218893Sdim/// tryParseMSRMaskOperand - Try to parse mask flags from MSR instruction.
1210218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
1211218893SdimtryParseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1212218893Sdim  SMLoc S = Parser.getTok().getLoc();
1213218893Sdim  const AsmToken &Tok = Parser.getTok();
1214218893Sdim  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
1215218893Sdim  StringRef Mask = Tok.getString();
1216218893Sdim
1217218893Sdim  // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
1218218893Sdim  size_t Start = 0, Next = Mask.find('_');
1219218893Sdim  StringRef Flags = "";
1220218893Sdim  StringRef SpecReg = Mask.slice(Start, Next);
1221218893Sdim  if (Next != StringRef::npos)
1222218893Sdim    Flags = Mask.slice(Next+1, Mask.size());
1223218893Sdim
1224218893Sdim  // FlagsVal contains the complete mask:
1225218893Sdim  // 3-0: Mask
1226218893Sdim  // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
1227218893Sdim  unsigned FlagsVal = 0;
1228218893Sdim
1229218893Sdim  if (SpecReg == "apsr") {
1230218893Sdim    FlagsVal = StringSwitch<unsigned>(Flags)
1231218893Sdim    .Case("nzcvq",  0x8) // same as CPSR_c
1232218893Sdim    .Case("g",      0x4) // same as CPSR_s
1233218893Sdim    .Case("nzcvqg", 0xc) // same as CPSR_fs
1234218893Sdim    .Default(~0U);
1235218893Sdim
1236218893Sdim    if (FlagsVal == ~0U) {
1237218893Sdim      if (!Flags.empty())
1238218893Sdim        return MatchOperand_NoMatch;
1239218893Sdim      else
1240218893Sdim        FlagsVal = 0; // No flag
1241218893Sdim    }
1242218893Sdim  } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
1243218893Sdim    for (int i = 0, e = Flags.size(); i != e; ++i) {
1244218893Sdim      unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
1245218893Sdim      .Case("c", 1)
1246218893Sdim      .Case("x", 2)
1247218893Sdim      .Case("s", 4)
1248218893Sdim      .Case("f", 8)
1249218893Sdim      .Default(~0U);
1250218893Sdim
1251218893Sdim      // If some specific flag is already set, it means that some letter is
1252218893Sdim      // present more than once, this is not acceptable.
1253218893Sdim      if (FlagsVal == ~0U || (FlagsVal & Flag))
1254218893Sdim        return MatchOperand_NoMatch;
1255218893Sdim      FlagsVal |= Flag;
1256218893Sdim    }
1257218893Sdim  } else // No match for special register.
1258218893Sdim    return MatchOperand_NoMatch;
1259218893Sdim
1260218893Sdim  // Special register without flags are equivalent to "fc" flags.
1261218893Sdim  if (!FlagsVal)
1262218893Sdim    FlagsVal = 0x9;
1263218893Sdim
1264218893Sdim  // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
1265218893Sdim  if (SpecReg == "spsr")
1266218893Sdim    FlagsVal |= 16;
1267218893Sdim
1268218893Sdim  Parser.Lex(); // Eat identifier token.
1269218893Sdim  Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
1270218893Sdim  return MatchOperand_Success;
1271218893Sdim}
1272218893Sdim
1273221345Sdim/// tryParseMemMode2Operand - Try to parse memory addressing mode 2 operand.
1274221345SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
1275221345SdimtryParseMemMode2Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1276221345Sdim  assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\"");
1277221345Sdim
1278221345Sdim  if (ParseMemory(Operands, ARMII::AddrMode2))
1279221345Sdim    return MatchOperand_NoMatch;
1280221345Sdim
1281221345Sdim  return MatchOperand_Success;
1282221345Sdim}
1283221345Sdim
1284221345Sdim/// tryParseMemMode3Operand - Try to parse memory addressing mode 3 operand.
1285221345SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
1286221345SdimtryParseMemMode3Operand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1287221345Sdim  assert(Parser.getTok().is(AsmToken::LBrac) && "Token is not a \"[\"");
1288221345Sdim
1289221345Sdim  if (ParseMemory(Operands, ARMII::AddrMode3))
1290221345Sdim    return MatchOperand_NoMatch;
1291221345Sdim
1292221345Sdim  return MatchOperand_Success;
1293221345Sdim}
1294221345Sdim
1295221345Sdim/// CvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
1296221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
1297221345Sdim/// when they refer multiple MIOperands inside a single one.
1298221345Sdimbool ARMAsmParser::
1299221345SdimCvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
1300221345Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1301221345Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
1302221345Sdim
1303221345Sdim  // Create a writeback register dummy placeholder.
1304221345Sdim  Inst.addOperand(MCOperand::CreateImm(0));
1305221345Sdim
1306221345Sdim  ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);
1307221345Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
1308221345Sdim  return true;
1309221345Sdim}
1310221345Sdim
1311221345Sdim/// CvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
1312221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
1313221345Sdim/// when they refer multiple MIOperands inside a single one.
1314221345Sdimbool ARMAsmParser::
1315221345SdimCvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
1316221345Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1317221345Sdim  // Create a writeback register dummy placeholder.
1318221345Sdim  Inst.addOperand(MCOperand::CreateImm(0));
1319221345Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
1320221345Sdim  ((ARMOperand*)Operands[3])->addMemMode2Operands(Inst, 3);
1321221345Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
1322221345Sdim  return true;
1323221345Sdim}
1324221345Sdim
1325221345Sdim/// CvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
1326221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
1327221345Sdim/// when they refer multiple MIOperands inside a single one.
1328221345Sdimbool ARMAsmParser::
1329221345SdimCvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
1330221345Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1331221345Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
1332221345Sdim
1333221345Sdim  // Create a writeback register dummy placeholder.
1334221345Sdim  Inst.addOperand(MCOperand::CreateImm(0));
1335221345Sdim
1336221345Sdim  ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3);
1337221345Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
1338221345Sdim  return true;
1339221345Sdim}
1340221345Sdim
1341221345Sdim/// CvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
1342221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
1343221345Sdim/// when they refer multiple MIOperands inside a single one.
1344221345Sdimbool ARMAsmParser::
1345221345SdimCvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
1346221345Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1347221345Sdim  // Create a writeback register dummy placeholder.
1348221345Sdim  Inst.addOperand(MCOperand::CreateImm(0));
1349221345Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
1350221345Sdim  ((ARMOperand*)Operands[3])->addMemMode3Operands(Inst, 3);
1351221345Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
1352221345Sdim  return true;
1353221345Sdim}
1354221345Sdim
1355218893Sdim/// Parse an ARM memory expression, return false if successful else return true
1356198892Srdivacky/// or an error.  The first token must be a '[' when called.
1357218893Sdim///
1358198892Srdivacky/// TODO Only preindexing and postindexing addressing are started, unindexed
1359198892Srdivacky/// with option, etc are still to do.
1360218893Sdimbool ARMAsmParser::
1361221345SdimParseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1362221345Sdim            ARMII::AddrMode AddrMode = ARMII::AddrModeNone) {
1363206124Srdivacky  SMLoc S, E;
1364202878Srdivacky  assert(Parser.getTok().is(AsmToken::LBrac) &&
1365218893Sdim         "Token is not a Left Bracket");
1366206124Srdivacky  S = Parser.getTok().getLoc();
1367202878Srdivacky  Parser.Lex(); // Eat left bracket token.
1368198090Srdivacky
1369202878Srdivacky  const AsmToken &BaseRegTok = Parser.getTok();
1370218893Sdim  if (BaseRegTok.isNot(AsmToken::Identifier)) {
1371218893Sdim    Error(BaseRegTok.getLoc(), "register expected");
1372218893Sdim    return true;
1373218893Sdim  }
1374218893Sdim  int BaseRegNum = TryParseRegister();
1375218893Sdim  if (BaseRegNum == -1) {
1376218893Sdim    Error(BaseRegTok.getLoc(), "register expected");
1377218893Sdim    return true;
1378218893Sdim  }
1379198090Srdivacky
1380218893Sdim  // The next token must either be a comma or a closing bracket.
1381218893Sdim  const AsmToken &Tok = Parser.getTok();
1382218893Sdim  if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
1383218893Sdim    return true;
1384218893Sdim
1385198090Srdivacky  bool Preindexed = false;
1386198090Srdivacky  bool Postindexed = false;
1387198090Srdivacky  bool OffsetIsReg = false;
1388198090Srdivacky  bool Negative = false;
1389198090Srdivacky  bool Writeback = false;
1390218893Sdim  ARMOperand *WBOp = 0;
1391218893Sdim  int OffsetRegNum = -1;
1392218893Sdim  bool OffsetRegShifted = false;
1393221345Sdim  enum ARM_AM::ShiftOpc ShiftType = ARM_AM::lsl;
1394218893Sdim  const MCExpr *ShiftAmount = 0;
1395218893Sdim  const MCExpr *Offset = 0;
1396198090Srdivacky
1397198892Srdivacky  // First look for preindexed address forms, that is after the "[Rn" we now
1398198892Srdivacky  // have to see if the next token is a comma.
1399198090Srdivacky  if (Tok.is(AsmToken::Comma)) {
1400198090Srdivacky    Preindexed = true;
1401202878Srdivacky    Parser.Lex(); // Eat comma token.
1402218893Sdim
1403218893Sdim    if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType, ShiftAmount,
1404218893Sdim                             Offset, OffsetIsReg, OffsetRegNum, E))
1405198892Srdivacky      return true;
1406202878Srdivacky    const AsmToken &RBracTok = Parser.getTok();
1407218893Sdim    if (RBracTok.isNot(AsmToken::RBrac)) {
1408218893Sdim      Error(RBracTok.getLoc(), "']' expected");
1409218893Sdim      return true;
1410218893Sdim    }
1411206124Srdivacky    E = RBracTok.getLoc();
1412202878Srdivacky    Parser.Lex(); // Eat right bracket token.
1413198090Srdivacky
1414202878Srdivacky    const AsmToken &ExclaimTok = Parser.getTok();
1415198090Srdivacky    if (ExclaimTok.is(AsmToken::Exclaim)) {
1416221345Sdim      // None of addrmode3 instruction uses "!"
1417221345Sdim      if (AddrMode == ARMII::AddrMode3)
1418221345Sdim        return true;
1419221345Sdim
1420218893Sdim      WBOp = ARMOperand::CreateToken(ExclaimTok.getString(),
1421218893Sdim                                     ExclaimTok.getLoc());
1422198090Srdivacky      Writeback = true;
1423202878Srdivacky      Parser.Lex(); // Eat exclaim token
1424221345Sdim    } else { // In addressing mode 2, pre-indexed mode always end with "!"
1425221345Sdim      if (AddrMode == ARMII::AddrMode2)
1426221345Sdim        Preindexed = false;
1427198090Srdivacky    }
1428218893Sdim  } else {
1429218893Sdim    // The "[Rn" we have so far was not followed by a comma.
1430218893Sdim
1431218893Sdim    // If there's anything other than the right brace, this is a post indexing
1432218893Sdim    // addressing form.
1433206124Srdivacky    E = Tok.getLoc();
1434202878Srdivacky    Parser.Lex(); // Eat right bracket token.
1435198090Srdivacky
1436218893Sdim    const AsmToken &NextTok = Parser.getTok();
1437198090Srdivacky
1438198396Srdivacky    if (NextTok.isNot(AsmToken::EndOfStatement)) {
1439218893Sdim      Postindexed = true;
1440218893Sdim      Writeback = true;
1441218893Sdim
1442218893Sdim      if (NextTok.isNot(AsmToken::Comma)) {
1443218893Sdim        Error(NextTok.getLoc(), "',' expected");
1444218893Sdim        return true;
1445218893Sdim      }
1446218893Sdim
1447202878Srdivacky      Parser.Lex(); // Eat comma token.
1448218893Sdim
1449218893Sdim      if (ParseMemoryOffsetReg(Negative, OffsetRegShifted, ShiftType,
1450218893Sdim                               ShiftAmount, Offset, OffsetIsReg, OffsetRegNum,
1451218893Sdim                               E))
1452198892Srdivacky        return true;
1453198090Srdivacky    }
1454218893Sdim  }
1455198090Srdivacky
1456218893Sdim  // Force Offset to exist if used.
1457218893Sdim  if (!OffsetIsReg) {
1458218893Sdim    if (!Offset)
1459218893Sdim      Offset = MCConstantExpr::Create(0, getContext());
1460221345Sdim  } else {
1461221345Sdim    if (AddrMode == ARMII::AddrMode3 && OffsetRegShifted) {
1462221345Sdim      Error(E, "shift amount not supported");
1463221345Sdim      return true;
1464221345Sdim    }
1465198090Srdivacky  }
1466198090Srdivacky
1467221345Sdim  Operands.push_back(ARMOperand::CreateMem(AddrMode, BaseRegNum, OffsetIsReg,
1468221345Sdim                                     Offset, OffsetRegNum, OffsetRegShifted,
1469221345Sdim                                     ShiftType, ShiftAmount, Preindexed,
1470221345Sdim                                     Postindexed, Negative, Writeback, S, E));
1471218893Sdim  if (WBOp)
1472218893Sdim    Operands.push_back(WBOp);
1473218893Sdim
1474218893Sdim  return false;
1475198090Srdivacky}
1476198090Srdivacky
1477198892Srdivacky/// Parse the offset of a memory operand after we have seen "[Rn," or "[Rn],"
1478198892Srdivacky/// we will parse the following (were +/- means that a plus or minus is
1479198892Srdivacky/// optional):
1480198892Srdivacky///   +/-Rm
1481198892Srdivacky///   +/-Rm, shift
1482198892Srdivacky///   #offset
1483198892Srdivacky/// we return false on success or an error otherwise.
1484198892Srdivackybool ARMAsmParser::ParseMemoryOffsetReg(bool &Negative,
1485206124Srdivacky                                        bool &OffsetRegShifted,
1486221345Sdim                                        enum ARM_AM::ShiftOpc &ShiftType,
1487198892Srdivacky                                        const MCExpr *&ShiftAmount,
1488198892Srdivacky                                        const MCExpr *&Offset,
1489198892Srdivacky                                        bool &OffsetIsReg,
1490206124Srdivacky                                        int &OffsetRegNum,
1491206124Srdivacky                                        SMLoc &E) {
1492198892Srdivacky  Negative = false;
1493198892Srdivacky  OffsetRegShifted = false;
1494198892Srdivacky  OffsetIsReg = false;
1495198892Srdivacky  OffsetRegNum = -1;
1496202878Srdivacky  const AsmToken &NextTok = Parser.getTok();
1497206124Srdivacky  E = NextTok.getLoc();
1498198892Srdivacky  if (NextTok.is(AsmToken::Plus))
1499202878Srdivacky    Parser.Lex(); // Eat plus token.
1500198892Srdivacky  else if (NextTok.is(AsmToken::Minus)) {
1501198892Srdivacky    Negative = true;
1502202878Srdivacky    Parser.Lex(); // Eat minus token
1503198892Srdivacky  }
1504198892Srdivacky  // See if there is a register following the "[Rn," or "[Rn]," we have so far.
1505202878Srdivacky  const AsmToken &OffsetRegTok = Parser.getTok();
1506198892Srdivacky  if (OffsetRegTok.is(AsmToken::Identifier)) {
1507218893Sdim    SMLoc CurLoc = OffsetRegTok.getLoc();
1508218893Sdim    OffsetRegNum = TryParseRegister();
1509218893Sdim    if (OffsetRegNum != -1) {
1510218893Sdim      OffsetIsReg = true;
1511218893Sdim      E = CurLoc;
1512206124Srdivacky    }
1513198892Srdivacky  }
1514218893Sdim
1515218893Sdim  // If we parsed a register as the offset then there can be a shift after that.
1516198892Srdivacky  if (OffsetRegNum != -1) {
1517198892Srdivacky    // Look for a comma then a shift
1518202878Srdivacky    const AsmToken &Tok = Parser.getTok();
1519198892Srdivacky    if (Tok.is(AsmToken::Comma)) {
1520202878Srdivacky      Parser.Lex(); // Eat comma token.
1521198892Srdivacky
1522202878Srdivacky      const AsmToken &Tok = Parser.getTok();
1523206124Srdivacky      if (ParseShift(ShiftType, ShiftAmount, E))
1524210299Sed        return Error(Tok.getLoc(), "shift expected");
1525198892Srdivacky      OffsetRegShifted = true;
1526198892Srdivacky    }
1527198892Srdivacky  }
1528198892Srdivacky  else { // the "[Rn," or "[Rn,]" we have so far was not followed by "Rm"
1529198892Srdivacky    // Look for #offset following the "[Rn," or "[Rn],"
1530202878Srdivacky    const AsmToken &HashTok = Parser.getTok();
1531198892Srdivacky    if (HashTok.isNot(AsmToken::Hash))
1532198892Srdivacky      return Error(HashTok.getLoc(), "'#' expected");
1533218893Sdim
1534202878Srdivacky    Parser.Lex(); // Eat hash token.
1535198892Srdivacky
1536198892Srdivacky    if (getParser().ParseExpression(Offset))
1537198892Srdivacky     return true;
1538206124Srdivacky    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1539198892Srdivacky  }
1540198892Srdivacky  return false;
1541198892Srdivacky}
1542198892Srdivacky
1543198090Srdivacky/// ParseShift as one of these two:
1544198090Srdivacky///   ( lsl | lsr | asr | ror ) , # shift_amount
1545198090Srdivacky///   rrx
1546198090Srdivacky/// and returns true if it parses a shift otherwise it returns false.
1547221345Sdimbool ARMAsmParser::ParseShift(ARM_AM::ShiftOpc &St,
1548221345Sdim                              const MCExpr *&ShiftAmount, SMLoc &E) {
1549202878Srdivacky  const AsmToken &Tok = Parser.getTok();
1550198090Srdivacky  if (Tok.isNot(AsmToken::Identifier))
1551198090Srdivacky    return true;
1552210299Sed  StringRef ShiftName = Tok.getString();
1553198090Srdivacky  if (ShiftName == "lsl" || ShiftName == "LSL")
1554221345Sdim    St = ARM_AM::lsl;
1555198090Srdivacky  else if (ShiftName == "lsr" || ShiftName == "LSR")
1556221345Sdim    St = ARM_AM::lsr;
1557198090Srdivacky  else if (ShiftName == "asr" || ShiftName == "ASR")
1558221345Sdim    St = ARM_AM::asr;
1559198090Srdivacky  else if (ShiftName == "ror" || ShiftName == "ROR")
1560221345Sdim    St = ARM_AM::ror;
1561198090Srdivacky  else if (ShiftName == "rrx" || ShiftName == "RRX")
1562221345Sdim    St = ARM_AM::rrx;
1563198090Srdivacky  else
1564198090Srdivacky    return true;
1565202878Srdivacky  Parser.Lex(); // Eat shift type token.
1566198090Srdivacky
1567198892Srdivacky  // Rrx stands alone.
1568221345Sdim  if (St == ARM_AM::rrx)
1569198892Srdivacky    return false;
1570198090Srdivacky
1571198892Srdivacky  // Otherwise, there must be a '#' and a shift amount.
1572202878Srdivacky  const AsmToken &HashTok = Parser.getTok();
1573198892Srdivacky  if (HashTok.isNot(AsmToken::Hash))
1574198892Srdivacky    return Error(HashTok.getLoc(), "'#' expected");
1575202878Srdivacky  Parser.Lex(); // Eat hash token.
1576198090Srdivacky
1577198892Srdivacky  if (getParser().ParseExpression(ShiftAmount))
1578198892Srdivacky    return true;
1579198892Srdivacky
1580198090Srdivacky  return false;
1581198090Srdivacky}
1582198090Srdivacky
1583198892Srdivacky/// Parse a arm instruction operand.  For now this parses the operand regardless
1584198892Srdivacky/// of the mnemonic.
1585218893Sdimbool ARMAsmParser::ParseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1586218893Sdim                                StringRef Mnemonic) {
1587206124Srdivacky  SMLoc S, E;
1588218893Sdim
1589218893Sdim  // Check if the current operand has a custom associated parser, if so, try to
1590218893Sdim  // custom parse the operand, or fallback to the general approach.
1591218893Sdim  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
1592218893Sdim  if (ResTy == MatchOperand_Success)
1593218893Sdim    return false;
1594218893Sdim  // If there wasn't a custom match, try the generic matcher below. Otherwise,
1595218893Sdim  // there was a match, but an error occurred, in which case, just return that
1596218893Sdim  // the operand parsing failed.
1597218893Sdim  if (ResTy == MatchOperand_ParseFail)
1598218893Sdim    return true;
1599218893Sdim
1600198090Srdivacky  switch (getLexer().getKind()) {
1601218893Sdim  default:
1602218893Sdim    Error(Parser.getTok().getLoc(), "unexpected token in operand");
1603218893Sdim    return true;
1604198090Srdivacky  case AsmToken::Identifier:
1605218893Sdim    if (!TryParseRegisterWithWriteBack(Operands))
1606198090Srdivacky      return false;
1607221345Sdim    if (!TryParseShiftRegister(Operands))
1608221345Sdim      return false;
1609218893Sdim
1610221345Sdim
1611218893Sdim    // Fall though for the Identifier case that is not a register or a
1612218893Sdim    // special name.
1613218893Sdim  case AsmToken::Integer: // things like 1f and 2b as a branch targets
1614218893Sdim  case AsmToken::Dot: {   // . as a branch target
1615198396Srdivacky    // This was not a register so parse other operands that start with an
1616198396Srdivacky    // identifier (like labels) as expressions and create them as immediates.
1617198396Srdivacky    const MCExpr *IdVal;
1618206124Srdivacky    S = Parser.getTok().getLoc();
1619198396Srdivacky    if (getParser().ParseExpression(IdVal))
1620198396Srdivacky      return true;
1621206124Srdivacky    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1622218893Sdim    Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
1623198396Srdivacky    return false;
1624218893Sdim  }
1625198090Srdivacky  case AsmToken::LBrac:
1626218893Sdim    return ParseMemory(Operands);
1627198090Srdivacky  case AsmToken::LCurly:
1628218893Sdim    return ParseRegisterList(Operands);
1629198090Srdivacky  case AsmToken::Hash:
1630198090Srdivacky    // #42 -> immediate.
1631198090Srdivacky    // TODO: ":lower16:" and ":upper16:" modifiers after # before immediate
1632206124Srdivacky    S = Parser.getTok().getLoc();
1633202878Srdivacky    Parser.Lex();
1634198396Srdivacky    const MCExpr *ImmVal;
1635198396Srdivacky    if (getParser().ParseExpression(ImmVal))
1636198090Srdivacky      return true;
1637206124Srdivacky    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1638218893Sdim    Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
1639198090Srdivacky    return false;
1640218893Sdim  case AsmToken::Colon: {
1641218893Sdim    // ":lower16:" and ":upper16:" expression prefixes
1642218893Sdim    // FIXME: Check it's an expression prefix,
1643218893Sdim    // e.g. (FOO - :lower16:BAR) isn't legal.
1644218893Sdim    ARMMCExpr::VariantKind RefKind;
1645218893Sdim    if (ParsePrefix(RefKind))
1646218893Sdim      return true;
1647218893Sdim
1648218893Sdim    const MCExpr *SubExprVal;
1649218893Sdim    if (getParser().ParseExpression(SubExprVal))
1650218893Sdim      return true;
1651218893Sdim
1652218893Sdim    const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
1653218893Sdim                                                   getContext());
1654218893Sdim    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
1655218893Sdim    Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
1656218893Sdim    return false;
1657198090Srdivacky  }
1658218893Sdim  }
1659198090Srdivacky}
1660198090Srdivacky
1661218893Sdim// ParsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
1662218893Sdim//  :lower16: and :upper16:.
1663218893Sdimbool ARMAsmParser::ParsePrefix(ARMMCExpr::VariantKind &RefKind) {
1664218893Sdim  RefKind = ARMMCExpr::VK_ARM_None;
1665212904Sdim
1666218893Sdim  // :lower16: and :upper16: modifiers
1667218893Sdim  assert(getLexer().is(AsmToken::Colon) && "expected a :");
1668218893Sdim  Parser.Lex(); // Eat ':'
1669212904Sdim
1670218893Sdim  if (getLexer().isNot(AsmToken::Identifier)) {
1671218893Sdim    Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
1672218893Sdim    return true;
1673218893Sdim  }
1674218893Sdim
1675218893Sdim  StringRef IDVal = Parser.getTok().getIdentifier();
1676218893Sdim  if (IDVal == "lower16") {
1677218893Sdim    RefKind = ARMMCExpr::VK_ARM_LO16;
1678218893Sdim  } else if (IDVal == "upper16") {
1679218893Sdim    RefKind = ARMMCExpr::VK_ARM_HI16;
1680218893Sdim  } else {
1681218893Sdim    Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
1682218893Sdim    return true;
1683218893Sdim  }
1684218893Sdim  Parser.Lex();
1685218893Sdim
1686218893Sdim  if (getLexer().isNot(AsmToken::Colon)) {
1687218893Sdim    Error(Parser.getTok().getLoc(), "unexpected token after prefix");
1688218893Sdim    return true;
1689218893Sdim  }
1690218893Sdim  Parser.Lex(); // Eat the last ':'
1691218893Sdim  return false;
1692218893Sdim}
1693218893Sdim
1694218893Sdimconst MCExpr *
1695218893SdimARMAsmParser::ApplyPrefixToExpr(const MCExpr *E,
1696218893Sdim                                MCSymbolRefExpr::VariantKind Variant) {
1697218893Sdim  // Recurse over the given expression, rebuilding it to apply the given variant
1698218893Sdim  // to the leftmost symbol.
1699218893Sdim  if (Variant == MCSymbolRefExpr::VK_None)
1700218893Sdim    return E;
1701218893Sdim
1702218893Sdim  switch (E->getKind()) {
1703218893Sdim  case MCExpr::Target:
1704218893Sdim    llvm_unreachable("Can't handle target expr yet");
1705218893Sdim  case MCExpr::Constant:
1706218893Sdim    llvm_unreachable("Can't handle lower16/upper16 of constant yet");
1707218893Sdim
1708218893Sdim  case MCExpr::SymbolRef: {
1709218893Sdim    const MCSymbolRefExpr *SRE = cast<MCSymbolRefExpr>(E);
1710218893Sdim
1711218893Sdim    if (SRE->getKind() != MCSymbolRefExpr::VK_None)
1712218893Sdim      return 0;
1713218893Sdim
1714218893Sdim    return MCSymbolRefExpr::Create(&SRE->getSymbol(), Variant, getContext());
1715218893Sdim  }
1716218893Sdim
1717218893Sdim  case MCExpr::Unary:
1718218893Sdim    llvm_unreachable("Can't handle unary expressions yet");
1719218893Sdim
1720218893Sdim  case MCExpr::Binary: {
1721218893Sdim    const MCBinaryExpr *BE = cast<MCBinaryExpr>(E);
1722218893Sdim    const MCExpr *LHS = ApplyPrefixToExpr(BE->getLHS(), Variant);
1723218893Sdim    const MCExpr *RHS = BE->getRHS();
1724218893Sdim    if (!LHS)
1725218893Sdim      return 0;
1726218893Sdim
1727218893Sdim    return MCBinaryExpr::Create(BE->getOpcode(), LHS, RHS, getContext());
1728218893Sdim  }
1729218893Sdim  }
1730218893Sdim
1731218893Sdim  assert(0 && "Invalid expression kind!");
1732218893Sdim  return 0;
1733218893Sdim}
1734218893Sdim
1735218893Sdim/// \brief Given a mnemonic, split out possible predication code and carry
1736218893Sdim/// setting letters to form a canonical mnemonic and flags.
1737218893Sdim//
1738218893Sdim// FIXME: Would be nice to autogen this.
1739218893Sdimstatic StringRef SplitMnemonic(StringRef Mnemonic,
1740218893Sdim                               unsigned &PredicationCode,
1741218893Sdim                               bool &CarrySetting,
1742218893Sdim                               unsigned &ProcessorIMod) {
1743218893Sdim  PredicationCode = ARMCC::AL;
1744218893Sdim  CarrySetting = false;
1745218893Sdim  ProcessorIMod = 0;
1746218893Sdim
1747218893Sdim  // Ignore some mnemonics we know aren't predicated forms.
1748212904Sdim  //
1749218893Sdim  // FIXME: Would be nice to autogen this.
1750218893Sdim  if (Mnemonic == "teq" || Mnemonic == "vceq" ||
1751218893Sdim      Mnemonic == "movs" ||
1752218893Sdim      Mnemonic == "svc" ||
1753218893Sdim      (Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
1754218893Sdim       Mnemonic == "vmls" || Mnemonic == "vnmls") ||
1755218893Sdim      Mnemonic == "vacge" || Mnemonic == "vcge" ||
1756218893Sdim      Mnemonic == "vclt" ||
1757218893Sdim      Mnemonic == "vacgt" || Mnemonic == "vcgt" ||
1758218893Sdim      Mnemonic == "vcle" ||
1759218893Sdim      (Mnemonic == "smlal" || Mnemonic == "umaal" || Mnemonic == "umlal" ||
1760218893Sdim       Mnemonic == "vabal" || Mnemonic == "vmlal" || Mnemonic == "vpadal" ||
1761218893Sdim       Mnemonic == "vqdmlal"))
1762218893Sdim    return Mnemonic;
1763218893Sdim
1764218893Sdim  // First, split out any predication code.
1765218893Sdim  unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
1766212904Sdim    .Case("eq", ARMCC::EQ)
1767212904Sdim    .Case("ne", ARMCC::NE)
1768212904Sdim    .Case("hs", ARMCC::HS)
1769212904Sdim    .Case("lo", ARMCC::LO)
1770212904Sdim    .Case("mi", ARMCC::MI)
1771212904Sdim    .Case("pl", ARMCC::PL)
1772212904Sdim    .Case("vs", ARMCC::VS)
1773212904Sdim    .Case("vc", ARMCC::VC)
1774212904Sdim    .Case("hi", ARMCC::HI)
1775212904Sdim    .Case("ls", ARMCC::LS)
1776212904Sdim    .Case("ge", ARMCC::GE)
1777212904Sdim    .Case("lt", ARMCC::LT)
1778212904Sdim    .Case("gt", ARMCC::GT)
1779212904Sdim    .Case("le", ARMCC::LE)
1780212904Sdim    .Case("al", ARMCC::AL)
1781212904Sdim    .Default(~0U);
1782212904Sdim  if (CC != ~0U) {
1783218893Sdim    Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
1784218893Sdim    PredicationCode = CC;
1785218893Sdim  }
1786212904Sdim
1787218893Sdim  // Next, determine if we have a carry setting bit. We explicitly ignore all
1788218893Sdim  // the instructions we know end in 's'.
1789218893Sdim  if (Mnemonic.endswith("s") &&
1790218893Sdim      !(Mnemonic == "asrs" || Mnemonic == "cps" || Mnemonic == "mls" ||
1791218893Sdim        Mnemonic == "movs" || Mnemonic == "mrs" || Mnemonic == "smmls" ||
1792218893Sdim        Mnemonic == "vabs" || Mnemonic == "vcls" || Mnemonic == "vmls" ||
1793218893Sdim        Mnemonic == "vmrs" || Mnemonic == "vnmls" || Mnemonic == "vqabs" ||
1794218893Sdim        Mnemonic == "vrecps" || Mnemonic == "vrsqrts")) {
1795218893Sdim    Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
1796218893Sdim    CarrySetting = true;
1797218893Sdim  }
1798198090Srdivacky
1799218893Sdim  // The "cps" instruction can have a interrupt mode operand which is glued into
1800218893Sdim  // the mnemonic. Check if this is the case, split it and parse the imod op
1801218893Sdim  if (Mnemonic.startswith("cps")) {
1802218893Sdim    // Split out any imod code.
1803218893Sdim    unsigned IMod =
1804218893Sdim      StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
1805218893Sdim      .Case("ie", ARM_PROC::IE)
1806218893Sdim      .Case("id", ARM_PROC::ID)
1807218893Sdim      .Default(~0U);
1808218893Sdim    if (IMod != ~0U) {
1809218893Sdim      Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
1810218893Sdim      ProcessorIMod = IMod;
1811218893Sdim    }
1812218893Sdim  }
1813212904Sdim
1814218893Sdim  return Mnemonic;
1815218893Sdim}
1816218893Sdim
1817218893Sdim/// \brief Given a canonical mnemonic, determine if the instruction ever allows
1818218893Sdim/// inclusion of carry set or predication code operands.
1819218893Sdim//
1820218893Sdim// FIXME: It would be nice to autogen this.
1821218893Sdimvoid ARMAsmParser::
1822218893SdimGetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
1823218893Sdim                      bool &CanAcceptPredicationCode) {
1824218893Sdim  bool isThumb = TM.getSubtarget<ARMSubtarget>().isThumb();
1825218893Sdim
1826218893Sdim  if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
1827218893Sdim      Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
1828218893Sdim      Mnemonic == "smull" || Mnemonic == "add" || Mnemonic == "adc" ||
1829218893Sdim      Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
1830218893Sdim      Mnemonic == "umlal" || Mnemonic == "orr" || Mnemonic == "mov" ||
1831218893Sdim      Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
1832218893Sdim      Mnemonic == "sbc" || Mnemonic == "mla" || Mnemonic == "umull" ||
1833218893Sdim      Mnemonic == "eor" || Mnemonic == "smlal" || Mnemonic == "mvn") {
1834218893Sdim    CanAcceptCarrySet = true;
1835218893Sdim  } else {
1836218893Sdim    CanAcceptCarrySet = false;
1837218893Sdim  }
1838218893Sdim
1839218893Sdim  if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
1840218893Sdim      Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
1841218893Sdim      Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
1842218893Sdim      Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
1843218893Sdim      Mnemonic == "dsb" || Mnemonic == "movs" || Mnemonic == "isb" ||
1844218893Sdim      Mnemonic == "clrex" || Mnemonic.startswith("cps")) {
1845218893Sdim    CanAcceptPredicationCode = false;
1846218893Sdim  } else {
1847218893Sdim    CanAcceptPredicationCode = true;
1848218893Sdim  }
1849218893Sdim
1850218893Sdim  if (isThumb)
1851218893Sdim    if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
1852218893Sdim        Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
1853218893Sdim      CanAcceptPredicationCode = false;
1854218893Sdim}
1855218893Sdim
1856218893Sdim/// Parse an arm instruction mnemonic followed by its operands.
1857218893Sdimbool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
1858218893Sdim                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
1859218893Sdim  // Create the leading tokens for the mnemonic, split by '.' characters.
1860218893Sdim  size_t Start = 0, Next = Name.find('.');
1861218893Sdim  StringRef Head = Name.slice(Start, Next);
1862218893Sdim
1863218893Sdim  // Split out the predication code and carry setting flag from the mnemonic.
1864218893Sdim  unsigned PredicationCode;
1865218893Sdim  unsigned ProcessorIMod;
1866218893Sdim  bool CarrySetting;
1867218893Sdim  Head = SplitMnemonic(Head, PredicationCode, CarrySetting,
1868218893Sdim                       ProcessorIMod);
1869218893Sdim
1870218893Sdim  Operands.push_back(ARMOperand::CreateToken(Head, NameLoc));
1871218893Sdim
1872218893Sdim  // Next, add the CCOut and ConditionCode operands, if needed.
1873218893Sdim  //
1874218893Sdim  // For mnemonics which can ever incorporate a carry setting bit or predication
1875218893Sdim  // code, our matching model involves us always generating CCOut and
1876218893Sdim  // ConditionCode operands to match the mnemonic "as written" and then we let
1877218893Sdim  // the matcher deal with finding the right instruction or generating an
1878218893Sdim  // appropriate error.
1879218893Sdim  bool CanAcceptCarrySet, CanAcceptPredicationCode;
1880218893Sdim  GetMnemonicAcceptInfo(Head, CanAcceptCarrySet, CanAcceptPredicationCode);
1881218893Sdim
1882218893Sdim  // Add the carry setting operand, if necessary.
1883218893Sdim  //
1884218893Sdim  // FIXME: It would be awesome if we could somehow invent a location such that
1885218893Sdim  // match errors on this operand would print a nice diagnostic about how the
1886218893Sdim  // 's' character in the mnemonic resulted in a CCOut operand.
1887218893Sdim  if (CanAcceptCarrySet) {
1888218893Sdim    Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
1889218893Sdim                                               NameLoc));
1890218893Sdim  } else {
1891218893Sdim    // This mnemonic can't ever accept a carry set, but the user wrote one (or
1892218893Sdim    // misspelled another mnemonic).
1893218893Sdim
1894218893Sdim    // FIXME: Issue a nice error.
1895218893Sdim  }
1896218893Sdim
1897218893Sdim  // Add the predication code operand, if necessary.
1898218893Sdim  if (CanAcceptPredicationCode) {
1899218893Sdim    Operands.push_back(ARMOperand::CreateCondCode(
1900218893Sdim                         ARMCC::CondCodes(PredicationCode), NameLoc));
1901218893Sdim  } else {
1902218893Sdim    // This mnemonic can't ever accept a predication code, but the user wrote
1903218893Sdim    // one (or misspelled another mnemonic).
1904218893Sdim
1905218893Sdim    // FIXME: Issue a nice error.
1906218893Sdim  }
1907218893Sdim
1908218893Sdim  // Add the processor imod operand, if necessary.
1909218893Sdim  if (ProcessorIMod) {
1910218893Sdim    Operands.push_back(ARMOperand::CreateImm(
1911218893Sdim          MCConstantExpr::Create(ProcessorIMod, getContext()),
1912218893Sdim                                 NameLoc, NameLoc));
1913218893Sdim  } else {
1914218893Sdim    // This mnemonic can't ever accept a imod, but the user wrote
1915218893Sdim    // one (or misspelled another mnemonic).
1916218893Sdim
1917218893Sdim    // FIXME: Issue a nice error.
1918218893Sdim  }
1919218893Sdim
1920212904Sdim  // Add the remaining tokens in the mnemonic.
1921212904Sdim  while (Next != StringRef::npos) {
1922212904Sdim    Start = Next;
1923212904Sdim    Next = Name.find('.', Start + 1);
1924218893Sdim    StringRef ExtraToken = Name.slice(Start, Next);
1925212904Sdim
1926218893Sdim    Operands.push_back(ARMOperand::CreateToken(ExtraToken, NameLoc));
1927212904Sdim  }
1928212904Sdim
1929212904Sdim  // Read the remaining operands.
1930198090Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1931198090Srdivacky    // Read the first operand.
1932218893Sdim    if (ParseOperand(Operands, Head)) {
1933218893Sdim      Parser.EatToEndOfStatement();
1934218893Sdim      return true;
1935218893Sdim    }
1936198090Srdivacky
1937198090Srdivacky    while (getLexer().is(AsmToken::Comma)) {
1938202878Srdivacky      Parser.Lex();  // Eat the comma.
1939198090Srdivacky
1940198090Srdivacky      // Parse and remember the operand.
1941218893Sdim      if (ParseOperand(Operands, Head)) {
1942218893Sdim        Parser.EatToEndOfStatement();
1943218893Sdim        return true;
1944218893Sdim      }
1945198090Srdivacky    }
1946198090Srdivacky  }
1947218893Sdim
1948218893Sdim  if (getLexer().isNot(AsmToken::EndOfStatement)) {
1949218893Sdim    Parser.EatToEndOfStatement();
1950218893Sdim    return TokError("unexpected token in argument list");
1951218893Sdim  }
1952218893Sdim
1953218893Sdim  Parser.Lex(); // Consume the EndOfStatement
1954202375Srdivacky  return false;
1955198090Srdivacky}
1956198090Srdivacky
1957218893Sdimbool ARMAsmParser::
1958218893SdimMatchAndEmitInstruction(SMLoc IDLoc,
1959218893Sdim                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
1960218893Sdim                        MCStreamer &Out) {
1961218893Sdim  MCInst Inst;
1962218893Sdim  unsigned ErrorInfo;
1963218893Sdim  MatchResultTy MatchResult, MatchResult2;
1964218893Sdim  MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
1965218893Sdim  if (MatchResult != Match_Success) {
1966218893Sdim    // If we get a Match_InvalidOperand it might be some arithmetic instruction
1967218893Sdim    // that does not update the condition codes.  So try adding a CCOut operand
1968218893Sdim    // with a value of reg0.
1969218893Sdim    if (MatchResult == Match_InvalidOperand) {
1970218893Sdim      Operands.insert(Operands.begin() + 1,
1971218893Sdim                      ARMOperand::CreateCCOut(0,
1972218893Sdim                                  ((ARMOperand*)Operands[0])->getStartLoc()));
1973218893Sdim      MatchResult2 = MatchInstructionImpl(Operands, Inst, ErrorInfo);
1974218893Sdim      if (MatchResult2 == Match_Success)
1975218893Sdim        MatchResult = Match_Success;
1976218893Sdim      else {
1977218893Sdim        ARMOperand *CCOut = ((ARMOperand*)Operands[1]);
1978218893Sdim        Operands.erase(Operands.begin() + 1);
1979218893Sdim        delete CCOut;
1980218893Sdim      }
1981218893Sdim    }
1982218893Sdim    // If we get a Match_MnemonicFail it might be some arithmetic instruction
1983218893Sdim    // that updates the condition codes if it ends in 's'.  So see if the
1984218893Sdim    // mnemonic ends in 's' and if so try removing the 's' and adding a CCOut
1985218893Sdim    // operand with a value of CPSR.
1986218893Sdim    else if(MatchResult == Match_MnemonicFail) {
1987218893Sdim      // Get the instruction mnemonic, which is the first token.
1988218893Sdim      StringRef Mnemonic = ((ARMOperand*)Operands[0])->getToken();
1989218893Sdim      if (Mnemonic.substr(Mnemonic.size()-1) == "s") {
1990218893Sdim        // removed the 's' from the mnemonic for matching.
1991218893Sdim        StringRef MnemonicNoS = Mnemonic.slice(0, Mnemonic.size() - 1);
1992218893Sdim        SMLoc NameLoc = ((ARMOperand*)Operands[0])->getStartLoc();
1993218893Sdim        ARMOperand *OldMnemonic = ((ARMOperand*)Operands[0]);
1994218893Sdim        Operands.erase(Operands.begin());
1995218893Sdim        delete OldMnemonic;
1996218893Sdim        Operands.insert(Operands.begin(),
1997218893Sdim                        ARMOperand::CreateToken(MnemonicNoS, NameLoc));
1998218893Sdim        Operands.insert(Operands.begin() + 1,
1999218893Sdim                        ARMOperand::CreateCCOut(ARM::CPSR, NameLoc));
2000218893Sdim        MatchResult2 = MatchInstructionImpl(Operands, Inst, ErrorInfo);
2001218893Sdim        if (MatchResult2 == Match_Success)
2002218893Sdim          MatchResult = Match_Success;
2003218893Sdim        else {
2004218893Sdim          ARMOperand *OldMnemonic = ((ARMOperand*)Operands[0]);
2005218893Sdim          Operands.erase(Operands.begin());
2006218893Sdim          delete OldMnemonic;
2007218893Sdim          Operands.insert(Operands.begin(),
2008218893Sdim                          ARMOperand::CreateToken(Mnemonic, NameLoc));
2009218893Sdim          ARMOperand *CCOut = ((ARMOperand*)Operands[1]);
2010218893Sdim          Operands.erase(Operands.begin() + 1);
2011218893Sdim          delete CCOut;
2012218893Sdim        }
2013218893Sdim      }
2014218893Sdim    }
2015218893Sdim  }
2016218893Sdim  switch (MatchResult) {
2017218893Sdim  case Match_Success:
2018218893Sdim    Out.EmitInstruction(Inst);
2019218893Sdim    return false;
2020218893Sdim  case Match_MissingFeature:
2021218893Sdim    Error(IDLoc, "instruction requires a CPU feature not currently enabled");
2022218893Sdim    return true;
2023218893Sdim  case Match_InvalidOperand: {
2024218893Sdim    SMLoc ErrorLoc = IDLoc;
2025218893Sdim    if (ErrorInfo != ~0U) {
2026218893Sdim      if (ErrorInfo >= Operands.size())
2027218893Sdim        return Error(IDLoc, "too few operands for instruction");
2028218893Sdim
2029218893Sdim      ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
2030218893Sdim      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
2031218893Sdim    }
2032218893Sdim
2033218893Sdim    return Error(ErrorLoc, "invalid operand for instruction");
2034218893Sdim  }
2035218893Sdim  case Match_MnemonicFail:
2036218893Sdim    return Error(IDLoc, "unrecognized instruction mnemonic");
2037218893Sdim  case Match_ConversionFail:
2038218893Sdim    return Error(IDLoc, "unable to convert operands to instruction");
2039218893Sdim  }
2040218893Sdim
2041218893Sdim  llvm_unreachable("Implement any new match types added!");
2042218893Sdim  return true;
2043218893Sdim}
2044218893Sdim
2045198396Srdivacky/// ParseDirective parses the arm specific directives
2046198090Srdivackybool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
2047198090Srdivacky  StringRef IDVal = DirectiveID.getIdentifier();
2048198090Srdivacky  if (IDVal == ".word")
2049198090Srdivacky    return ParseDirectiveWord(4, DirectiveID.getLoc());
2050198396Srdivacky  else if (IDVal == ".thumb")
2051198396Srdivacky    return ParseDirectiveThumb(DirectiveID.getLoc());
2052198396Srdivacky  else if (IDVal == ".thumb_func")
2053198396Srdivacky    return ParseDirectiveThumbFunc(DirectiveID.getLoc());
2054198396Srdivacky  else if (IDVal == ".code")
2055198396Srdivacky    return ParseDirectiveCode(DirectiveID.getLoc());
2056198396Srdivacky  else if (IDVal == ".syntax")
2057198396Srdivacky    return ParseDirectiveSyntax(DirectiveID.getLoc());
2058198090Srdivacky  return true;
2059198090Srdivacky}
2060198090Srdivacky
2061198090Srdivacky/// ParseDirectiveWord
2062198090Srdivacky///  ::= .word [ expression (, expression)* ]
2063198090Srdivackybool ARMAsmParser::ParseDirectiveWord(unsigned Size, SMLoc L) {
2064198090Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement)) {
2065198090Srdivacky    for (;;) {
2066198090Srdivacky      const MCExpr *Value;
2067198090Srdivacky      if (getParser().ParseExpression(Value))
2068198090Srdivacky        return true;
2069198090Srdivacky
2070202878Srdivacky      getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
2071198090Srdivacky
2072198090Srdivacky      if (getLexer().is(AsmToken::EndOfStatement))
2073198090Srdivacky        break;
2074218893Sdim
2075198090Srdivacky      // FIXME: Improve diagnostic.
2076198090Srdivacky      if (getLexer().isNot(AsmToken::Comma))
2077198090Srdivacky        return Error(L, "unexpected token in directive");
2078202878Srdivacky      Parser.Lex();
2079198090Srdivacky    }
2080198090Srdivacky  }
2081198090Srdivacky
2082202878Srdivacky  Parser.Lex();
2083198090Srdivacky  return false;
2084198090Srdivacky}
2085198090Srdivacky
2086198396Srdivacky/// ParseDirectiveThumb
2087198396Srdivacky///  ::= .thumb
2088198396Srdivackybool ARMAsmParser::ParseDirectiveThumb(SMLoc L) {
2089198396Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement))
2090198396Srdivacky    return Error(L, "unexpected token in directive");
2091202878Srdivacky  Parser.Lex();
2092198396Srdivacky
2093198396Srdivacky  // TODO: set thumb mode
2094198396Srdivacky  // TODO: tell the MC streamer the mode
2095198396Srdivacky  // getParser().getStreamer().Emit???();
2096198396Srdivacky  return false;
2097198396Srdivacky}
2098198396Srdivacky
2099198396Srdivacky/// ParseDirectiveThumbFunc
2100198396Srdivacky///  ::= .thumbfunc symbol_name
2101198396Srdivackybool ARMAsmParser::ParseDirectiveThumbFunc(SMLoc L) {
2102202878Srdivacky  const AsmToken &Tok = Parser.getTok();
2103198396Srdivacky  if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
2104218893Sdim    return Error(L, "unexpected token in .thumb_func directive");
2105218893Sdim  StringRef Name = Tok.getString();
2106202878Srdivacky  Parser.Lex(); // Consume the identifier token.
2107198396Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement))
2108198396Srdivacky    return Error(L, "unexpected token in directive");
2109202878Srdivacky  Parser.Lex();
2110198396Srdivacky
2111218893Sdim  // Mark symbol as a thumb symbol.
2112218893Sdim  MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
2113218893Sdim  getParser().getStreamer().EmitThumbFunc(Func);
2114198396Srdivacky  return false;
2115198396Srdivacky}
2116198396Srdivacky
2117198396Srdivacky/// ParseDirectiveSyntax
2118198396Srdivacky///  ::= .syntax unified | divided
2119198396Srdivackybool ARMAsmParser::ParseDirectiveSyntax(SMLoc L) {
2120202878Srdivacky  const AsmToken &Tok = Parser.getTok();
2121198396Srdivacky  if (Tok.isNot(AsmToken::Identifier))
2122198396Srdivacky    return Error(L, "unexpected token in .syntax directive");
2123210299Sed  StringRef Mode = Tok.getString();
2124210299Sed  if (Mode == "unified" || Mode == "UNIFIED")
2125202878Srdivacky    Parser.Lex();
2126210299Sed  else if (Mode == "divided" || Mode == "DIVIDED")
2127218893Sdim    return Error(L, "'.syntax divided' arm asssembly not supported");
2128198396Srdivacky  else
2129198396Srdivacky    return Error(L, "unrecognized syntax mode in .syntax directive");
2130198396Srdivacky
2131198396Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement))
2132202878Srdivacky    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
2133202878Srdivacky  Parser.Lex();
2134198396Srdivacky
2135198396Srdivacky  // TODO tell the MC streamer the mode
2136198396Srdivacky  // getParser().getStreamer().Emit???();
2137198396Srdivacky  return false;
2138198396Srdivacky}
2139198396Srdivacky
2140198396Srdivacky/// ParseDirectiveCode
2141198396Srdivacky///  ::= .code 16 | 32
2142198396Srdivackybool ARMAsmParser::ParseDirectiveCode(SMLoc L) {
2143202878Srdivacky  const AsmToken &Tok = Parser.getTok();
2144198396Srdivacky  if (Tok.isNot(AsmToken::Integer))
2145198396Srdivacky    return Error(L, "unexpected token in .code directive");
2146202878Srdivacky  int64_t Val = Parser.getTok().getIntVal();
2147210299Sed  if (Val == 16)
2148202878Srdivacky    Parser.Lex();
2149210299Sed  else if (Val == 32)
2150202878Srdivacky    Parser.Lex();
2151198396Srdivacky  else
2152198396Srdivacky    return Error(L, "invalid operand to .code directive");
2153198396Srdivacky
2154198396Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement))
2155202878Srdivacky    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
2156202878Srdivacky  Parser.Lex();
2157198396Srdivacky
2158218893Sdim  // FIXME: We need to be able switch subtargets at this point so that
2159218893Sdim  // MatchInstructionImpl() will work when it gets the AvailableFeatures which
2160218893Sdim  // includes Feature_IsThumb or not to match the right instructions.  This is
2161218893Sdim  // blocked on the FIXME in llvm-mc.cpp when creating the TargetMachine.
2162218893Sdim  if (Val == 16){
2163218893Sdim    assert(TM.getSubtarget<ARMSubtarget>().isThumb() &&
2164218893Sdim	   "switching between arm/thumb not yet suppported via .code 16)");
2165218893Sdim    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
2166218893Sdim  }
2167218893Sdim  else{
2168218893Sdim    assert(!TM.getSubtarget<ARMSubtarget>().isThumb() &&
2169218893Sdim           "switching between thumb/arm not yet suppported via .code 32)");
2170218893Sdim    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
2171218893Sdim   }
2172218893Sdim
2173198396Srdivacky  return false;
2174198396Srdivacky}
2175198396Srdivacky
2176207618Srdivackyextern "C" void LLVMInitializeARMAsmLexer();
2177207618Srdivacky
2178198892Srdivacky/// Force static initialization.
2179198090Srdivackyextern "C" void LLVMInitializeARMAsmParser() {
2180198090Srdivacky  RegisterAsmParser<ARMAsmParser> X(TheARMTarget);
2181198090Srdivacky  RegisterAsmParser<ARMAsmParser> Y(TheThumbTarget);
2182207618Srdivacky  LLVMInitializeARMAsmLexer();
2183198090Srdivacky}
2184212904Sdim
2185218893Sdim#define GET_REGISTER_MATCHER
2186218893Sdim#define GET_MATCHER_IMPLEMENTATION
2187212904Sdim#include "ARMGenAsmMatcher.inc"
2188