ARMAsmParser.cpp revision 243830
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
10226633Sdim#include "MCTargetDesc/ARMBaseInfo.h"
11226633Sdim#include "MCTargetDesc/ARMAddressingModes.h"
12226633Sdim#include "MCTargetDesc/ARMMCExpr.h"
13202878Srdivacky#include "llvm/MC/MCParser/MCAsmLexer.h"
14202878Srdivacky#include "llvm/MC/MCParser/MCAsmParser.h"
15202878Srdivacky#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
16223017Sdim#include "llvm/MC/MCAsmInfo.h"
17218893Sdim#include "llvm/MC/MCContext.h"
18198090Srdivacky#include "llvm/MC/MCStreamer.h"
19198090Srdivacky#include "llvm/MC/MCExpr.h"
20198090Srdivacky#include "llvm/MC/MCInst.h"
21226633Sdim#include "llvm/MC/MCInstrDesc.h"
22226633Sdim#include "llvm/MC/MCRegisterInfo.h"
23224145Sdim#include "llvm/MC/MCSubtargetInfo.h"
24226633Sdim#include "llvm/MC/MCTargetAsmParser.h"
25226633Sdim#include "llvm/Support/MathExtras.h"
26198090Srdivacky#include "llvm/Support/SourceMgr.h"
27226633Sdim#include "llvm/Support/TargetRegistry.h"
28212904Sdim#include "llvm/Support/raw_ostream.h"
29226633Sdim#include "llvm/ADT/BitVector.h"
30224145Sdim#include "llvm/ADT/OwningPtr.h"
31226633Sdim#include "llvm/ADT/STLExtras.h"
32202878Srdivacky#include "llvm/ADT/SmallVector.h"
33212904Sdim#include "llvm/ADT/StringSwitch.h"
34202878Srdivacky#include "llvm/ADT/Twine.h"
35224145Sdim
36198090Srdivackyusing namespace llvm;
37198090Srdivacky
38218893Sdimnamespace {
39218893Sdim
40218893Sdimclass ARMOperand;
41218893Sdim
42234353Sdimenum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
43234353Sdim
44226633Sdimclass ARMAsmParser : public MCTargetAsmParser {
45224145Sdim  MCSubtargetInfo &STI;
46198090Srdivacky  MCAsmParser &Parser;
47234353Sdim  const MCRegisterInfo *MRI;
48198090Srdivacky
49234353Sdim  // Map of register aliases registers via the .req directive.
50234353Sdim  StringMap<unsigned> RegisterReqs;
51234353Sdim
52226633Sdim  struct {
53226633Sdim    ARMCC::CondCodes Cond;    // Condition for IT block.
54226633Sdim    unsigned Mask:4;          // Condition mask for instructions.
55226633Sdim                              // Starting at first 1 (from lsb).
56226633Sdim                              //   '1'  condition as indicated in IT.
57226633Sdim                              //   '0'  inverse of condition (else).
58226633Sdim                              // Count of instructions in IT block is
59226633Sdim                              // 4 - trailingzeroes(mask)
60226633Sdim
61226633Sdim    bool FirstCond;           // Explicit flag for when we're parsing the
62226633Sdim                              // First instruction in the IT block. It's
63226633Sdim                              // implied in the mask, so needs special
64226633Sdim                              // handling.
65226633Sdim
66226633Sdim    unsigned CurPosition;     // Current position in parsing of IT
67226633Sdim                              // block. In range [0,3]. Initialized
68226633Sdim                              // according to count of instructions in block.
69226633Sdim                              // ~0U if no active IT block.
70226633Sdim  } ITState;
71226633Sdim  bool inITBlock() { return ITState.CurPosition != ~0U;}
72226633Sdim  void forwardITPosition() {
73226633Sdim    if (!inITBlock()) return;
74226633Sdim    // Move to the next instruction in the IT block, if there is one. If not,
75226633Sdim    // mark the block as done.
76226633Sdim    unsigned TZ = CountTrailingZeros_32(ITState.Mask);
77226633Sdim    if (++ITState.CurPosition == 5 - TZ)
78226633Sdim      ITState.CurPosition = ~0U; // Done with the IT block after this.
79226633Sdim  }
80226633Sdim
81226633Sdim
82198090Srdivacky  MCAsmParser &getParser() const { return Parser; }
83198090Srdivacky  MCAsmLexer &getLexer() const { return Parser.getLexer(); }
84198090Srdivacky
85234982Sdim  bool Warning(SMLoc L, const Twine &Msg,
86234982Sdim               ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
87234982Sdim    return Parser.Warning(L, Msg, Ranges);
88234982Sdim  }
89234982Sdim  bool Error(SMLoc L, const Twine &Msg,
90234982Sdim             ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
91234982Sdim    return Parser.Error(L, Msg, Ranges);
92234982Sdim  }
93198090Srdivacky
94226633Sdim  int tryParseRegister();
95226633Sdim  bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
96226633Sdim  int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
97226633Sdim  bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
98226633Sdim  bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
99226633Sdim  bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
100226633Sdim  bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
101226633Sdim  bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
102226633Sdim                              unsigned &ShiftAmount);
103226633Sdim  bool parseDirectiveWord(unsigned Size, SMLoc L);
104226633Sdim  bool parseDirectiveThumb(SMLoc L);
105234353Sdim  bool parseDirectiveARM(SMLoc L);
106226633Sdim  bool parseDirectiveThumbFunc(SMLoc L);
107226633Sdim  bool parseDirectiveCode(SMLoc L);
108226633Sdim  bool parseDirectiveSyntax(SMLoc L);
109234353Sdim  bool parseDirectiveReq(StringRef Name, SMLoc L);
110234353Sdim  bool parseDirectiveUnreq(SMLoc L);
111234353Sdim  bool parseDirectiveArch(SMLoc L);
112234353Sdim  bool parseDirectiveEabiAttr(SMLoc L);
113198090Srdivacky
114226633Sdim  StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
115226633Sdim                          bool &CarrySetting, unsigned &ProcessorIMod,
116226633Sdim                          StringRef &ITMask);
117226633Sdim  void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
118218893Sdim                             bool &CanAcceptPredicationCode);
119198090Srdivacky
120224145Sdim  bool isThumb() const {
121224145Sdim    // FIXME: Can tablegen auto-generate this?
122224145Sdim    return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
123224145Sdim  }
124224145Sdim  bool isThumbOne() const {
125224145Sdim    return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
126224145Sdim  }
127226633Sdim  bool isThumbTwo() const {
128226633Sdim    return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
129226633Sdim  }
130226633Sdim  bool hasV6Ops() const {
131226633Sdim    return STI.getFeatureBits() & ARM::HasV6Ops;
132226633Sdim  }
133226633Sdim  bool hasV7Ops() const {
134226633Sdim    return STI.getFeatureBits() & ARM::HasV7Ops;
135226633Sdim  }
136224145Sdim  void SwitchMode() {
137224145Sdim    unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
138224145Sdim    setAvailableFeatures(FB);
139224145Sdim  }
140226633Sdim  bool isMClass() const {
141226633Sdim    return STI.getFeatureBits() & ARM::FeatureMClass;
142226633Sdim  }
143224145Sdim
144198090Srdivacky  /// @name Auto-generated Match Functions
145198090Srdivacky  /// {
146198090Srdivacky
147218893Sdim#define GET_ASSEMBLER_HEADER
148218893Sdim#include "ARMGenAsmMatcher.inc"
149198090Srdivacky
150198090Srdivacky  /// }
151198090Srdivacky
152226633Sdim  OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
153226633Sdim  OperandMatchResultTy parseCoprocNumOperand(
154218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
155226633Sdim  OperandMatchResultTy parseCoprocRegOperand(
156218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
157226633Sdim  OperandMatchResultTy parseCoprocOptionOperand(
158218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
159226633Sdim  OperandMatchResultTy parseMemBarrierOptOperand(
160218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
161226633Sdim  OperandMatchResultTy parseProcIFlagsOperand(
162218893Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
163226633Sdim  OperandMatchResultTy parseMSRMaskOperand(
164221345Sdim    SmallVectorImpl<MCParsedAsmOperand*>&);
165226633Sdim  OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
166226633Sdim                                   StringRef Op, int Low, int High);
167226633Sdim  OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
168226633Sdim    return parsePKHImm(O, "lsl", 0, 31);
169226633Sdim  }
170226633Sdim  OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
171226633Sdim    return parsePKHImm(O, "asr", 1, 32);
172226633Sdim  }
173226633Sdim  OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
174226633Sdim  OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
175226633Sdim  OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
176226633Sdim  OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
177226633Sdim  OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
178226633Sdim  OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
179226633Sdim  OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
180234353Sdim  OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
181234353Sdim  OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
182198090Srdivacky
183221345Sdim  // Asm Match Converter Methods
184243830Sdim  void cvtT2LdrdPre(MCInst &Inst, const SmallVectorImpl<MCParsedAsmOperand*> &);
185243830Sdim  void cvtT2StrdPre(MCInst &Inst, const SmallVectorImpl<MCParsedAsmOperand*> &);
186243830Sdim  void cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst,
187221345Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
188243830Sdim  void cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst,
189221345Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
190243830Sdim  void cvtLdWriteBackRegAddrMode2(MCInst &Inst,
191221345Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
192243830Sdim  void cvtLdWriteBackRegAddrModeImm12(MCInst &Inst,
193221345Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
194243830Sdim  void cvtStWriteBackRegAddrModeImm12(MCInst &Inst,
195226633Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
196243830Sdim  void cvtStWriteBackRegAddrMode2(MCInst &Inst,
197226633Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
198243830Sdim  void cvtStWriteBackRegAddrMode3(MCInst &Inst,
199226633Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
200243830Sdim  void cvtLdExtTWriteBackImm(MCInst &Inst,
201226633Sdim                             const SmallVectorImpl<MCParsedAsmOperand*> &);
202243830Sdim  void cvtLdExtTWriteBackReg(MCInst &Inst,
203226633Sdim                             const SmallVectorImpl<MCParsedAsmOperand*> &);
204243830Sdim  void cvtStExtTWriteBackImm(MCInst &Inst,
205226633Sdim                             const SmallVectorImpl<MCParsedAsmOperand*> &);
206243830Sdim  void cvtStExtTWriteBackReg(MCInst &Inst,
207226633Sdim                             const SmallVectorImpl<MCParsedAsmOperand*> &);
208243830Sdim  void cvtLdrdPre(MCInst &Inst, const SmallVectorImpl<MCParsedAsmOperand*> &);
209243830Sdim  void cvtStrdPre(MCInst &Inst, const SmallVectorImpl<MCParsedAsmOperand*> &);
210243830Sdim  void cvtLdWriteBackRegAddrMode3(MCInst &Inst,
211226633Sdim                                  const SmallVectorImpl<MCParsedAsmOperand*> &);
212243830Sdim  void cvtThumbMultiply(MCInst &Inst,
213226633Sdim                        const SmallVectorImpl<MCParsedAsmOperand*> &);
214243830Sdim  void cvtVLDwbFixed(MCInst &Inst,
215234353Sdim                     const SmallVectorImpl<MCParsedAsmOperand*> &);
216243830Sdim  void cvtVLDwbRegister(MCInst &Inst,
217234353Sdim                        const SmallVectorImpl<MCParsedAsmOperand*> &);
218243830Sdim  void cvtVSTwbFixed(MCInst &Inst,
219234353Sdim                     const SmallVectorImpl<MCParsedAsmOperand*> &);
220243830Sdim  void cvtVSTwbRegister(MCInst &Inst,
221234353Sdim                        const SmallVectorImpl<MCParsedAsmOperand*> &);
222226633Sdim  bool validateInstruction(MCInst &Inst,
223226633Sdim                           const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
224234353Sdim  bool processInstruction(MCInst &Inst,
225226633Sdim                          const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
226226633Sdim  bool shouldOmitCCOutOperand(StringRef Mnemonic,
227226633Sdim                              SmallVectorImpl<MCParsedAsmOperand*> &Operands);
228226633Sdim
229198090Srdivackypublic:
230226633Sdim  enum ARMMatchResultTy {
231226633Sdim    Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
232226633Sdim    Match_RequiresNotITBlock,
233226633Sdim    Match_RequiresV6,
234239462Sdim    Match_RequiresThumb2,
235239462Sdim#define GET_OPERAND_DIAGNOSTIC_TYPES
236239462Sdim#include "ARMGenAsmMatcher.inc"
237239462Sdim
238226633Sdim  };
239226633Sdim
240224145Sdim  ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
241226633Sdim    : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
242224145Sdim    MCAsmParserExtension::Initialize(_Parser);
243198090Srdivacky
244234353Sdim    // Cache the MCRegisterInfo.
245234353Sdim    MRI = &getContext().getRegisterInfo();
246234353Sdim
247224145Sdim    // Initialize the set of available features.
248224145Sdim    setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
249226633Sdim
250226633Sdim    // Not in an ITBlock to start with.
251226633Sdim    ITState.CurPosition = ~0U;
252224145Sdim  }
253224145Sdim
254226633Sdim  // Implementation of the MCTargetAsmParser interface:
255226633Sdim  bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
256243830Sdim  bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
257243830Sdim                        SMLoc NameLoc,
258226633Sdim                        SmallVectorImpl<MCParsedAsmOperand*> &Operands);
259226633Sdim  bool ParseDirective(AsmToken DirectiveID);
260226633Sdim
261226633Sdim  unsigned checkTargetMatchPredicate(MCInst &Inst);
262226633Sdim
263243830Sdim  bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
264226633Sdim                               SmallVectorImpl<MCParsedAsmOperand*> &Operands,
265243830Sdim                               MCStreamer &Out, unsigned &ErrorInfo,
266243830Sdim                               bool MatchingInlineAsm);
267198090Srdivacky};
268218893Sdim} // end anonymous namespace
269218893Sdim
270218893Sdimnamespace {
271218893Sdim
272198090Srdivacky/// ARMOperand - Instances of this class represent a parsed ARM machine
273198090Srdivacky/// instruction.
274218893Sdimclass ARMOperand : public MCParsedAsmOperand {
275206124Srdivacky  enum KindTy {
276226633Sdim    k_CondCode,
277226633Sdim    k_CCOut,
278226633Sdim    k_ITCondMask,
279226633Sdim    k_CoprocNum,
280226633Sdim    k_CoprocReg,
281226633Sdim    k_CoprocOption,
282226633Sdim    k_Immediate,
283226633Sdim    k_MemBarrierOpt,
284226633Sdim    k_Memory,
285226633Sdim    k_PostIndexRegister,
286226633Sdim    k_MSRMask,
287226633Sdim    k_ProcIFlags,
288226633Sdim    k_VectorIndex,
289226633Sdim    k_Register,
290226633Sdim    k_RegisterList,
291226633Sdim    k_DPRRegisterList,
292226633Sdim    k_SPRRegisterList,
293234353Sdim    k_VectorList,
294234353Sdim    k_VectorListAllLanes,
295234353Sdim    k_VectorListIndexed,
296226633Sdim    k_ShiftedRegister,
297226633Sdim    k_ShiftedImmediate,
298226633Sdim    k_ShifterImmediate,
299226633Sdim    k_RotateImmediate,
300226633Sdim    k_BitfieldDescriptor,
301226633Sdim    k_Token
302198090Srdivacky  } Kind;
303198090Srdivacky
304206124Srdivacky  SMLoc StartLoc, EndLoc;
305218893Sdim  SmallVector<unsigned, 8> Registers;
306198090Srdivacky
307198090Srdivacky  union {
308198090Srdivacky    struct {
309212904Sdim      ARMCC::CondCodes Val;
310212904Sdim    } CC;
311212904Sdim
312212904Sdim    struct {
313226633Sdim      unsigned Val;
314226633Sdim    } Cop;
315218893Sdim
316218893Sdim    struct {
317218893Sdim      unsigned Val;
318226633Sdim    } CoprocOption;
319218893Sdim
320218893Sdim    struct {
321226633Sdim      unsigned Mask:4;
322226633Sdim    } ITMask;
323226633Sdim
324226633Sdim    struct {
325226633Sdim      ARM_MB::MemBOpt Val;
326226633Sdim    } MBOpt;
327226633Sdim
328226633Sdim    struct {
329218893Sdim      ARM_PROC::IFlags Val;
330218893Sdim    } IFlags;
331218893Sdim
332218893Sdim    struct {
333218893Sdim      unsigned Val;
334218893Sdim    } MMask;
335218893Sdim
336218893Sdim    struct {
337198090Srdivacky      const char *Data;
338198090Srdivacky      unsigned Length;
339198090Srdivacky    } Tok;
340198090Srdivacky
341198090Srdivacky    struct {
342198090Srdivacky      unsigned RegNum;
343198090Srdivacky    } Reg;
344198090Srdivacky
345234353Sdim    // A vector register list is a sequential list of 1 to 4 registers.
346198090Srdivacky    struct {
347234353Sdim      unsigned RegNum;
348234353Sdim      unsigned Count;
349234353Sdim      unsigned LaneIndex;
350234353Sdim      bool isDoubleSpaced;
351234353Sdim    } VectorList;
352234353Sdim
353234353Sdim    struct {
354226633Sdim      unsigned Val;
355226633Sdim    } VectorIndex;
356226633Sdim
357226633Sdim    struct {
358198090Srdivacky      const MCExpr *Val;
359198090Srdivacky    } Imm;
360218893Sdim
361218893Sdim    /// Combined record for all forms of ARM address expressions.
362198090Srdivacky    struct {
363198090Srdivacky      unsigned BaseRegNum;
364226633Sdim      // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
365226633Sdim      // was specified.
366226633Sdim      const MCConstantExpr *OffsetImm;  // Offset immediate value
367226633Sdim      unsigned OffsetRegNum;    // Offset register num, when OffsetImm == NULL
368226633Sdim      ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
369226633Sdim      unsigned ShiftImm;        // shift for OffsetReg.
370226633Sdim      unsigned Alignment;       // 0 = no alignment specified
371234353Sdim                                // n = alignment in bytes (2, 4, 8, 16, or 32)
372226633Sdim      unsigned isNegative : 1;  // Negated OffsetReg? (~'U' bit)
373226633Sdim    } Memory;
374221345Sdim
375221345Sdim    struct {
376226633Sdim      unsigned RegNum;
377226633Sdim      bool isAdd;
378221345Sdim      ARM_AM::ShiftOpc ShiftTy;
379226633Sdim      unsigned ShiftImm;
380226633Sdim    } PostIdxReg;
381226633Sdim
382226633Sdim    struct {
383226633Sdim      bool isASR;
384224145Sdim      unsigned Imm;
385226633Sdim    } ShifterImm;
386224145Sdim    struct {
387224145Sdim      ARM_AM::ShiftOpc ShiftTy;
388224145Sdim      unsigned SrcReg;
389224145Sdim      unsigned ShiftReg;
390224145Sdim      unsigned ShiftImm;
391226633Sdim    } RegShiftedReg;
392226633Sdim    struct {
393226633Sdim      ARM_AM::ShiftOpc ShiftTy;
394226633Sdim      unsigned SrcReg;
395226633Sdim      unsigned ShiftImm;
396226633Sdim    } RegShiftedImm;
397226633Sdim    struct {
398226633Sdim      unsigned Imm;
399226633Sdim    } RotImm;
400226633Sdim    struct {
401226633Sdim      unsigned LSB;
402226633Sdim      unsigned Width;
403226633Sdim    } Bitfield;
404218893Sdim  };
405198090Srdivacky
406218893Sdim  ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
407218893Sdimpublic:
408206124Srdivacky  ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
409206124Srdivacky    Kind = o.Kind;
410206124Srdivacky    StartLoc = o.StartLoc;
411206124Srdivacky    EndLoc = o.EndLoc;
412206124Srdivacky    switch (Kind) {
413226633Sdim    case k_CondCode:
414212904Sdim      CC = o.CC;
415212904Sdim      break;
416226633Sdim    case k_ITCondMask:
417226633Sdim      ITMask = o.ITMask;
418226633Sdim      break;
419226633Sdim    case k_Token:
420212904Sdim      Tok = o.Tok;
421206124Srdivacky      break;
422226633Sdim    case k_CCOut:
423226633Sdim    case k_Register:
424206124Srdivacky      Reg = o.Reg;
425206124Srdivacky      break;
426226633Sdim    case k_RegisterList:
427226633Sdim    case k_DPRRegisterList:
428226633Sdim    case k_SPRRegisterList:
429218893Sdim      Registers = o.Registers;
430218893Sdim      break;
431234353Sdim    case k_VectorList:
432234353Sdim    case k_VectorListAllLanes:
433234353Sdim    case k_VectorListIndexed:
434234353Sdim      VectorList = o.VectorList;
435234353Sdim      break;
436226633Sdim    case k_CoprocNum:
437226633Sdim    case k_CoprocReg:
438218893Sdim      Cop = o.Cop;
439218893Sdim      break;
440226633Sdim    case k_CoprocOption:
441226633Sdim      CoprocOption = o.CoprocOption;
442226633Sdim      break;
443226633Sdim    case k_Immediate:
444206124Srdivacky      Imm = o.Imm;
445206124Srdivacky      break;
446226633Sdim    case k_MemBarrierOpt:
447218893Sdim      MBOpt = o.MBOpt;
448218893Sdim      break;
449226633Sdim    case k_Memory:
450226633Sdim      Memory = o.Memory;
451206124Srdivacky      break;
452226633Sdim    case k_PostIndexRegister:
453226633Sdim      PostIdxReg = o.PostIdxReg;
454226633Sdim      break;
455226633Sdim    case k_MSRMask:
456218893Sdim      MMask = o.MMask;
457218893Sdim      break;
458226633Sdim    case k_ProcIFlags:
459218893Sdim      IFlags = o.IFlags;
460221345Sdim      break;
461226633Sdim    case k_ShifterImmediate:
462226633Sdim      ShifterImm = o.ShifterImm;
463221345Sdim      break;
464226633Sdim    case k_ShiftedRegister:
465226633Sdim      RegShiftedReg = o.RegShiftedReg;
466224145Sdim      break;
467226633Sdim    case k_ShiftedImmediate:
468226633Sdim      RegShiftedImm = o.RegShiftedImm;
469226633Sdim      break;
470226633Sdim    case k_RotateImmediate:
471226633Sdim      RotImm = o.RotImm;
472226633Sdim      break;
473226633Sdim    case k_BitfieldDescriptor:
474226633Sdim      Bitfield = o.Bitfield;
475226633Sdim      break;
476226633Sdim    case k_VectorIndex:
477226633Sdim      VectorIndex = o.VectorIndex;
478226633Sdim      break;
479206124Srdivacky    }
480206124Srdivacky  }
481218893Sdim
482206124Srdivacky  /// getStartLoc - Get the location of the first token of this operand.
483206124Srdivacky  SMLoc getStartLoc() const { return StartLoc; }
484206124Srdivacky  /// getEndLoc - Get the location of the last token of this operand.
485206124Srdivacky  SMLoc getEndLoc() const { return EndLoc; }
486243830Sdim  /// getLocRange - Get the range between the first and last token of this
487243830Sdim  /// operand.
488234982Sdim  SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
489234982Sdim
490212904Sdim  ARMCC::CondCodes getCondCode() const {
491226633Sdim    assert(Kind == k_CondCode && "Invalid access!");
492212904Sdim    return CC.Val;
493212904Sdim  }
494212904Sdim
495218893Sdim  unsigned getCoproc() const {
496226633Sdim    assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
497218893Sdim    return Cop.Val;
498218893Sdim  }
499218893Sdim
500198090Srdivacky  StringRef getToken() const {
501226633Sdim    assert(Kind == k_Token && "Invalid access!");
502198090Srdivacky    return StringRef(Tok.Data, Tok.Length);
503198090Srdivacky  }
504198090Srdivacky
505198090Srdivacky  unsigned getReg() const {
506226633Sdim    assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
507198090Srdivacky    return Reg.RegNum;
508198090Srdivacky  }
509198090Srdivacky
510218893Sdim  const SmallVectorImpl<unsigned> &getRegList() const {
511226633Sdim    assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
512226633Sdim            Kind == k_SPRRegisterList) && "Invalid access!");
513218893Sdim    return Registers;
514218893Sdim  }
515218893Sdim
516198090Srdivacky  const MCExpr *getImm() const {
517234353Sdim    assert(isImm() && "Invalid access!");
518198090Srdivacky    return Imm.Val;
519198090Srdivacky  }
520198090Srdivacky
521226633Sdim  unsigned getVectorIndex() const {
522226633Sdim    assert(Kind == k_VectorIndex && "Invalid access!");
523226633Sdim    return VectorIndex.Val;
524226633Sdim  }
525226633Sdim
526218893Sdim  ARM_MB::MemBOpt getMemBarrierOpt() const {
527226633Sdim    assert(Kind == k_MemBarrierOpt && "Invalid access!");
528218893Sdim    return MBOpt.Val;
529218893Sdim  }
530218893Sdim
531218893Sdim  ARM_PROC::IFlags getProcIFlags() const {
532226633Sdim    assert(Kind == k_ProcIFlags && "Invalid access!");
533218893Sdim    return IFlags.Val;
534218893Sdim  }
535218893Sdim
536218893Sdim  unsigned getMSRMask() const {
537226633Sdim    assert(Kind == k_MSRMask && "Invalid access!");
538218893Sdim    return MMask.Val;
539218893Sdim  }
540218893Sdim
541226633Sdim  bool isCoprocNum() const { return Kind == k_CoprocNum; }
542226633Sdim  bool isCoprocReg() const { return Kind == k_CoprocReg; }
543226633Sdim  bool isCoprocOption() const { return Kind == k_CoprocOption; }
544226633Sdim  bool isCondCode() const { return Kind == k_CondCode; }
545226633Sdim  bool isCCOut() const { return Kind == k_CCOut; }
546226633Sdim  bool isITMask() const { return Kind == k_ITCondMask; }
547226633Sdim  bool isITCondCode() const { return Kind == k_CondCode; }
548226633Sdim  bool isImm() const { return Kind == k_Immediate; }
549234353Sdim  bool isFPImm() const {
550234353Sdim    if (!isImm()) return false;
551234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
552234353Sdim    if (!CE) return false;
553234353Sdim    int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
554234353Sdim    return Val != -1;
555234353Sdim  }
556234353Sdim  bool isFBits16() const {
557234353Sdim    if (!isImm()) return false;
558234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
559234353Sdim    if (!CE) return false;
560234353Sdim    int64_t Value = CE->getValue();
561234353Sdim    return Value >= 0 && Value <= 16;
562234353Sdim  }
563234353Sdim  bool isFBits32() const {
564234353Sdim    if (!isImm()) return false;
565234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
566234353Sdim    if (!CE) return false;
567234353Sdim    int64_t Value = CE->getValue();
568234353Sdim    return Value >= 1 && Value <= 32;
569234353Sdim  }
570226633Sdim  bool isImm8s4() const {
571234353Sdim    if (!isImm()) return false;
572226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
573226633Sdim    if (!CE) return false;
574226633Sdim    int64_t Value = CE->getValue();
575226633Sdim    return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
576221345Sdim  }
577226633Sdim  bool isImm0_1020s4() const {
578234353Sdim    if (!isImm()) return false;
579226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
580226633Sdim    if (!CE) return false;
581226633Sdim    int64_t Value = CE->getValue();
582226633Sdim    return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
583218893Sdim  }
584226633Sdim  bool isImm0_508s4() const {
585234353Sdim    if (!isImm()) return false;
586226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
587226633Sdim    if (!CE) return false;
588226633Sdim    int64_t Value = CE->getValue();
589226633Sdim    return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
590218893Sdim  }
591234353Sdim  bool isImm0_508s4Neg() const {
592234353Sdim    if (!isImm()) return false;
593234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
594234353Sdim    if (!CE) return false;
595234353Sdim    int64_t Value = -CE->getValue();
596234353Sdim    // explicitly exclude zero. we want that to use the normal 0_508 version.
597234353Sdim    return ((Value & 3) == 0) && Value > 0 && Value <= 508;
598234353Sdim  }
599224145Sdim  bool isImm0_255() const {
600234353Sdim    if (!isImm()) return false;
601224145Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
602224145Sdim    if (!CE) return false;
603224145Sdim    int64_t Value = CE->getValue();
604224145Sdim    return Value >= 0 && Value < 256;
605224145Sdim  }
606234353Sdim  bool isImm0_4095() const {
607234353Sdim    if (!isImm()) return false;
608234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
609234353Sdim    if (!CE) return false;
610234353Sdim    int64_t Value = CE->getValue();
611234353Sdim    return Value >= 0 && Value < 4096;
612234353Sdim  }
613234353Sdim  bool isImm0_4095Neg() const {
614234353Sdim    if (!isImm()) return false;
615234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
616234353Sdim    if (!CE) return false;
617234353Sdim    int64_t Value = -CE->getValue();
618234353Sdim    return Value > 0 && Value < 4096;
619234353Sdim  }
620234353Sdim  bool isImm0_1() const {
621234353Sdim    if (!isImm()) return false;
622234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
623234353Sdim    if (!CE) return false;
624234353Sdim    int64_t Value = CE->getValue();
625234353Sdim    return Value >= 0 && Value < 2;
626234353Sdim  }
627234353Sdim  bool isImm0_3() const {
628234353Sdim    if (!isImm()) return false;
629234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
630234353Sdim    if (!CE) return false;
631234353Sdim    int64_t Value = CE->getValue();
632234353Sdim    return Value >= 0 && Value < 4;
633234353Sdim  }
634224145Sdim  bool isImm0_7() const {
635234353Sdim    if (!isImm()) return false;
636224145Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
637224145Sdim    if (!CE) return false;
638224145Sdim    int64_t Value = CE->getValue();
639224145Sdim    return Value >= 0 && Value < 8;
640224145Sdim  }
641224145Sdim  bool isImm0_15() const {
642234353Sdim    if (!isImm()) return false;
643224145Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
644224145Sdim    if (!CE) return false;
645224145Sdim    int64_t Value = CE->getValue();
646224145Sdim    return Value >= 0 && Value < 16;
647224145Sdim  }
648226633Sdim  bool isImm0_31() const {
649234353Sdim    if (!isImm()) return false;
650226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
651226633Sdim    if (!CE) return false;
652226633Sdim    int64_t Value = CE->getValue();
653226633Sdim    return Value >= 0 && Value < 32;
654226633Sdim  }
655234353Sdim  bool isImm0_63() const {
656234353Sdim    if (!isImm()) return false;
657234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
658234353Sdim    if (!CE) return false;
659234353Sdim    int64_t Value = CE->getValue();
660234353Sdim    return Value >= 0 && Value < 64;
661234353Sdim  }
662234353Sdim  bool isImm8() const {
663234353Sdim    if (!isImm()) return false;
664234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
665234353Sdim    if (!CE) return false;
666234353Sdim    int64_t Value = CE->getValue();
667234353Sdim    return Value == 8;
668234353Sdim  }
669234353Sdim  bool isImm16() const {
670234353Sdim    if (!isImm()) return false;
671234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
672234353Sdim    if (!CE) return false;
673234353Sdim    int64_t Value = CE->getValue();
674234353Sdim    return Value == 16;
675234353Sdim  }
676234353Sdim  bool isImm32() const {
677234353Sdim    if (!isImm()) return false;
678234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
679234353Sdim    if (!CE) return false;
680234353Sdim    int64_t Value = CE->getValue();
681234353Sdim    return Value == 32;
682234353Sdim  }
683234353Sdim  bool isShrImm8() const {
684234353Sdim    if (!isImm()) return false;
685234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
686234353Sdim    if (!CE) return false;
687234353Sdim    int64_t Value = CE->getValue();
688234353Sdim    return Value > 0 && Value <= 8;
689234353Sdim  }
690234353Sdim  bool isShrImm16() const {
691234353Sdim    if (!isImm()) return false;
692234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
693234353Sdim    if (!CE) return false;
694234353Sdim    int64_t Value = CE->getValue();
695234353Sdim    return Value > 0 && Value <= 16;
696234353Sdim  }
697234353Sdim  bool isShrImm32() const {
698234353Sdim    if (!isImm()) return false;
699234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
700234353Sdim    if (!CE) return false;
701234353Sdim    int64_t Value = CE->getValue();
702234353Sdim    return Value > 0 && Value <= 32;
703234353Sdim  }
704234353Sdim  bool isShrImm64() const {
705234353Sdim    if (!isImm()) return false;
706234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
707234353Sdim    if (!CE) return false;
708234353Sdim    int64_t Value = CE->getValue();
709234353Sdim    return Value > 0 && Value <= 64;
710234353Sdim  }
711234353Sdim  bool isImm1_7() const {
712234353Sdim    if (!isImm()) return false;
713234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
714234353Sdim    if (!CE) return false;
715234353Sdim    int64_t Value = CE->getValue();
716234353Sdim    return Value > 0 && Value < 8;
717234353Sdim  }
718234353Sdim  bool isImm1_15() const {
719234353Sdim    if (!isImm()) return false;
720234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
721234353Sdim    if (!CE) return false;
722234353Sdim    int64_t Value = CE->getValue();
723234353Sdim    return Value > 0 && Value < 16;
724234353Sdim  }
725234353Sdim  bool isImm1_31() const {
726234353Sdim    if (!isImm()) return false;
727234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
728234353Sdim    if (!CE) return false;
729234353Sdim    int64_t Value = CE->getValue();
730234353Sdim    return Value > 0 && Value < 32;
731234353Sdim  }
732226633Sdim  bool isImm1_16() const {
733234353Sdim    if (!isImm()) return false;
734226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
735226633Sdim    if (!CE) return false;
736226633Sdim    int64_t Value = CE->getValue();
737226633Sdim    return Value > 0 && Value < 17;
738226633Sdim  }
739226633Sdim  bool isImm1_32() const {
740234353Sdim    if (!isImm()) return false;
741226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
742226633Sdim    if (!CE) return false;
743226633Sdim    int64_t Value = CE->getValue();
744226633Sdim    return Value > 0 && Value < 33;
745226633Sdim  }
746234353Sdim  bool isImm0_32() const {
747234353Sdim    if (!isImm()) return false;
748234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
749234353Sdim    if (!CE) return false;
750234353Sdim    int64_t Value = CE->getValue();
751234353Sdim    return Value >= 0 && Value < 33;
752234353Sdim  }
753224145Sdim  bool isImm0_65535() const {
754234353Sdim    if (!isImm()) return false;
755224145Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
756224145Sdim    if (!CE) return false;
757224145Sdim    int64_t Value = CE->getValue();
758224145Sdim    return Value >= 0 && Value < 65536;
759224145Sdim  }
760226633Sdim  bool isImm0_65535Expr() const {
761234353Sdim    if (!isImm()) return false;
762224145Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
763226633Sdim    // If it's not a constant expression, it'll generate a fixup and be
764226633Sdim    // handled later.
765226633Sdim    if (!CE) return true;
766226633Sdim    int64_t Value = CE->getValue();
767226633Sdim    return Value >= 0 && Value < 65536;
768226633Sdim  }
769226633Sdim  bool isImm24bit() const {
770234353Sdim    if (!isImm()) return false;
771226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
772224145Sdim    if (!CE) return false;
773224145Sdim    int64_t Value = CE->getValue();
774226633Sdim    return Value >= 0 && Value <= 0xffffff;
775224145Sdim  }
776226633Sdim  bool isImmThumbSR() const {
777234353Sdim    if (!isImm()) return false;
778226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
779226633Sdim    if (!CE) return false;
780226633Sdim    int64_t Value = CE->getValue();
781226633Sdim    return Value > 0 && Value < 33;
782226633Sdim  }
783226633Sdim  bool isPKHLSLImm() const {
784234353Sdim    if (!isImm()) return false;
785226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
786221345Sdim    if (!CE) return false;
787221345Sdim    int64_t Value = CE->getValue();
788226633Sdim    return Value >= 0 && Value < 32;
789226633Sdim  }
790226633Sdim  bool isPKHASRImm() const {
791234353Sdim    if (!isImm()) return false;
792226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
793226633Sdim    if (!CE) return false;
794226633Sdim    int64_t Value = CE->getValue();
795226633Sdim    return Value > 0 && Value <= 32;
796221345Sdim  }
797239462Sdim  bool isAdrLabel() const {
798239462Sdim    // If we have an immediate that's not a constant, treat it as a label
799239462Sdim    // reference needing a fixup. If it is a constant, but it can't fit
800239462Sdim    // into shift immediate encoding, we reject it.
801239462Sdim    if (isImm() && !isa<MCConstantExpr>(getImm())) return true;
802239462Sdim    else return (isARMSOImm() || isARMSOImmNeg());
803239462Sdim  }
804226633Sdim  bool isARMSOImm() const {
805234353Sdim    if (!isImm()) return false;
806226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
807226633Sdim    if (!CE) return false;
808226633Sdim    int64_t Value = CE->getValue();
809226633Sdim    return ARM_AM::getSOImmVal(Value) != -1;
810226633Sdim  }
811234353Sdim  bool isARMSOImmNot() const {
812234353Sdim    if (!isImm()) return false;
813234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
814234353Sdim    if (!CE) return false;
815234353Sdim    int64_t Value = CE->getValue();
816234353Sdim    return ARM_AM::getSOImmVal(~Value) != -1;
817234353Sdim  }
818234353Sdim  bool isARMSOImmNeg() const {
819234353Sdim    if (!isImm()) return false;
820234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
821234353Sdim    if (!CE) return false;
822234353Sdim    int64_t Value = CE->getValue();
823234353Sdim    // Only use this when not representable as a plain so_imm.
824234353Sdim    return ARM_AM::getSOImmVal(Value) == -1 &&
825234353Sdim      ARM_AM::getSOImmVal(-Value) != -1;
826234353Sdim  }
827226633Sdim  bool isT2SOImm() const {
828234353Sdim    if (!isImm()) return false;
829226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
830221345Sdim    if (!CE) return false;
831221345Sdim    int64_t Value = CE->getValue();
832226633Sdim    return ARM_AM::getT2SOImmVal(Value) != -1;
833221345Sdim  }
834234353Sdim  bool isT2SOImmNot() const {
835234353Sdim    if (!isImm()) return false;
836234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
837234353Sdim    if (!CE) return false;
838234353Sdim    int64_t Value = CE->getValue();
839234353Sdim    return ARM_AM::getT2SOImmVal(~Value) != -1;
840234353Sdim  }
841234353Sdim  bool isT2SOImmNeg() const {
842234353Sdim    if (!isImm()) return false;
843234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
844234353Sdim    if (!CE) return false;
845234353Sdim    int64_t Value = CE->getValue();
846234353Sdim    // Only use this when not representable as a plain so_imm.
847234353Sdim    return ARM_AM::getT2SOImmVal(Value) == -1 &&
848234353Sdim      ARM_AM::getT2SOImmVal(-Value) != -1;
849234353Sdim  }
850226633Sdim  bool isSetEndImm() const {
851234353Sdim    if (!isImm()) return false;
852226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
853218893Sdim    if (!CE) return false;
854218893Sdim    int64_t Value = CE->getValue();
855226633Sdim    return Value == 1 || Value == 0;
856218893Sdim  }
857226633Sdim  bool isReg() const { return Kind == k_Register; }
858226633Sdim  bool isRegList() const { return Kind == k_RegisterList; }
859226633Sdim  bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
860226633Sdim  bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
861226633Sdim  bool isToken() const { return Kind == k_Token; }
862226633Sdim  bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
863243830Sdim  bool isMem() const { return Kind == k_Memory; }
864226633Sdim  bool isShifterImm() const { return Kind == k_ShifterImmediate; }
865226633Sdim  bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
866226633Sdim  bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
867226633Sdim  bool isRotImm() const { return Kind == k_RotateImmediate; }
868226633Sdim  bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
869226633Sdim  bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
870226633Sdim  bool isPostIdxReg() const {
871234353Sdim    return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
872226633Sdim  }
873226633Sdim  bool isMemNoOffset(bool alignOK = false) const {
874243830Sdim    if (!isMem())
875221345Sdim      return false;
876226633Sdim    // No offset of any kind.
877226633Sdim    return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
878226633Sdim     (alignOK || Memory.Alignment == 0);
879226633Sdim  }
880234353Sdim  bool isMemPCRelImm12() const {
881243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
882234353Sdim      return false;
883234353Sdim    // Base register must be PC.
884234353Sdim    if (Memory.BaseRegNum != ARM::PC)
885234353Sdim      return false;
886234353Sdim    // Immediate offset in range [-4095, 4095].
887234353Sdim    if (!Memory.OffsetImm) return true;
888234353Sdim    int64_t Val = Memory.OffsetImm->getValue();
889234353Sdim    return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
890234353Sdim  }
891226633Sdim  bool isAlignedMemory() const {
892226633Sdim    return isMemNoOffset(true);
893226633Sdim  }
894226633Sdim  bool isAddrMode2() const {
895243830Sdim    if (!isMem() || Memory.Alignment != 0) return false;
896226633Sdim    // Check for register offset.
897226633Sdim    if (Memory.OffsetRegNum) return true;
898226633Sdim    // Immediate offset in range [-4095, 4095].
899226633Sdim    if (!Memory.OffsetImm) return true;
900226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
901226633Sdim    return Val > -4096 && Val < 4096;
902226633Sdim  }
903226633Sdim  bool isAM2OffsetImm() const {
904234353Sdim    if (!isImm()) return false;
905226633Sdim    // Immediate offset in range [-4095, 4095].
906226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
907221345Sdim    if (!CE) return false;
908226633Sdim    int64_t Val = CE->getValue();
909226633Sdim    return Val > -4096 && Val < 4096;
910226633Sdim  }
911226633Sdim  bool isAddrMode3() const {
912234353Sdim    // If we have an immediate that's not a constant, treat it as a label
913234353Sdim    // reference needing a fixup. If it is a constant, it's something else
914234353Sdim    // and we reject it.
915234353Sdim    if (isImm() && !isa<MCConstantExpr>(getImm()))
916234353Sdim      return true;
917243830Sdim    if (!isMem() || Memory.Alignment != 0) return false;
918226633Sdim    // No shifts are legal for AM3.
919226633Sdim    if (Memory.ShiftType != ARM_AM::no_shift) return false;
920226633Sdim    // Check for register offset.
921226633Sdim    if (Memory.OffsetRegNum) return true;
922226633Sdim    // Immediate offset in range [-255, 255].
923226633Sdim    if (!Memory.OffsetImm) return true;
924226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
925239462Sdim    // The #-0 offset is encoded as INT32_MIN, and we have to check
926239462Sdim    // for this too.
927239462Sdim    return (Val > -256 && Val < 256) || Val == INT32_MIN;
928226633Sdim  }
929226633Sdim  bool isAM3Offset() const {
930226633Sdim    if (Kind != k_Immediate && Kind != k_PostIndexRegister)
931221345Sdim      return false;
932226633Sdim    if (Kind == k_PostIndexRegister)
933226633Sdim      return PostIdxReg.ShiftTy == ARM_AM::no_shift;
934226633Sdim    // Immediate offset in range [-255, 255].
935226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
936226633Sdim    if (!CE) return false;
937226633Sdim    int64_t Val = CE->getValue();
938226633Sdim    // Special case, #-0 is INT32_MIN.
939226633Sdim    return (Val > -256 && Val < 256) || Val == INT32_MIN;
940226633Sdim  }
941226633Sdim  bool isAddrMode5() const {
942234353Sdim    // If we have an immediate that's not a constant, treat it as a label
943234353Sdim    // reference needing a fixup. If it is a constant, it's something else
944234353Sdim    // and we reject it.
945234353Sdim    if (isImm() && !isa<MCConstantExpr>(getImm()))
946234353Sdim      return true;
947243830Sdim    if (!isMem() || Memory.Alignment != 0) return false;
948226633Sdim    // Check for register offset.
949226633Sdim    if (Memory.OffsetRegNum) return false;
950226633Sdim    // Immediate offset in range [-1020, 1020] and a multiple of 4.
951226633Sdim    if (!Memory.OffsetImm) return true;
952226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
953226633Sdim    return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
954234353Sdim      Val == INT32_MIN;
955226633Sdim  }
956226633Sdim  bool isMemTBB() const {
957243830Sdim    if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
958226633Sdim        Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
959226633Sdim      return false;
960221345Sdim    return true;
961221345Sdim  }
962226633Sdim  bool isMemTBH() const {
963243830Sdim    if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
964226633Sdim        Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
965226633Sdim        Memory.Alignment != 0 )
966218893Sdim      return false;
967218893Sdim    return true;
968218893Sdim  }
969226633Sdim  bool isMemRegOffset() const {
970243830Sdim    if (!isMem() || !Memory.OffsetRegNum || Memory.Alignment != 0)
971218893Sdim      return false;
972226633Sdim    return true;
973226633Sdim  }
974226633Sdim  bool isT2MemRegOffset() const {
975243830Sdim    if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
976226633Sdim        Memory.Alignment != 0)
977226633Sdim      return false;
978226633Sdim    // Only lsl #{0, 1, 2, 3} allowed.
979226633Sdim    if (Memory.ShiftType == ARM_AM::no_shift)
980226633Sdim      return true;
981226633Sdim    if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
982226633Sdim      return false;
983226633Sdim    return true;
984226633Sdim  }
985226633Sdim  bool isMemThumbRR() const {
986226633Sdim    // Thumb reg+reg addressing is simple. Just two registers, a base and
987226633Sdim    // an offset. No shifts, negations or any other complicating factors.
988243830Sdim    if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
989226633Sdim        Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
990226633Sdim      return false;
991226633Sdim    return isARMLowRegister(Memory.BaseRegNum) &&
992226633Sdim      (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
993226633Sdim  }
994226633Sdim  bool isMemThumbRIs4() const {
995243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 ||
996226633Sdim        !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
997226633Sdim      return false;
998226633Sdim    // Immediate offset, multiple of 4 in range [0, 124].
999226633Sdim    if (!Memory.OffsetImm) return true;
1000226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1001226633Sdim    return Val >= 0 && Val <= 124 && (Val % 4) == 0;
1002226633Sdim  }
1003226633Sdim  bool isMemThumbRIs2() const {
1004243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 ||
1005226633Sdim        !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
1006226633Sdim      return false;
1007226633Sdim    // Immediate offset, multiple of 4 in range [0, 62].
1008226633Sdim    if (!Memory.OffsetImm) return true;
1009226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1010226633Sdim    return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1011226633Sdim  }
1012226633Sdim  bool isMemThumbRIs1() const {
1013243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 ||
1014226633Sdim        !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
1015226633Sdim      return false;
1016226633Sdim    // Immediate offset in range [0, 31].
1017226633Sdim    if (!Memory.OffsetImm) return true;
1018226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1019226633Sdim    return Val >= 0 && Val <= 31;
1020226633Sdim  }
1021226633Sdim  bool isMemThumbSPI() const {
1022243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 ||
1023226633Sdim        Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
1024226633Sdim      return false;
1025226633Sdim    // Immediate offset, multiple of 4 in range [0, 1020].
1026226633Sdim    if (!Memory.OffsetImm) return true;
1027226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1028226633Sdim    return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
1029226633Sdim  }
1030226633Sdim  bool isMemImm8s4Offset() const {
1031234353Sdim    // If we have an immediate that's not a constant, treat it as a label
1032234353Sdim    // reference needing a fixup. If it is a constant, it's something else
1033234353Sdim    // and we reject it.
1034234353Sdim    if (isImm() && !isa<MCConstantExpr>(getImm()))
1035234353Sdim      return true;
1036243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1037226633Sdim      return false;
1038226633Sdim    // Immediate offset a multiple of 4 in range [-1020, 1020].
1039226633Sdim    if (!Memory.OffsetImm) return true;
1040226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1041239462Sdim    // Special case, #-0 is INT32_MIN.
1042239462Sdim    return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || Val == INT32_MIN;
1043226633Sdim  }
1044226633Sdim  bool isMemImm0_1020s4Offset() const {
1045243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1046226633Sdim      return false;
1047226633Sdim    // Immediate offset a multiple of 4 in range [0, 1020].
1048226633Sdim    if (!Memory.OffsetImm) return true;
1049226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1050226633Sdim    return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1051226633Sdim  }
1052226633Sdim  bool isMemImm8Offset() const {
1053243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1054226633Sdim      return false;
1055234353Sdim    // Base reg of PC isn't allowed for these encodings.
1056234353Sdim    if (Memory.BaseRegNum == ARM::PC) return false;
1057226633Sdim    // Immediate offset in range [-255, 255].
1058226633Sdim    if (!Memory.OffsetImm) return true;
1059226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1060226633Sdim    return (Val == INT32_MIN) || (Val > -256 && Val < 256);
1061226633Sdim  }
1062226633Sdim  bool isMemPosImm8Offset() const {
1063243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1064226633Sdim      return false;
1065226633Sdim    // Immediate offset in range [0, 255].
1066226633Sdim    if (!Memory.OffsetImm) return true;
1067226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1068226633Sdim    return Val >= 0 && Val < 256;
1069226633Sdim  }
1070226633Sdim  bool isMemNegImm8Offset() const {
1071243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1072226633Sdim      return false;
1073234353Sdim    // Base reg of PC isn't allowed for these encodings.
1074234353Sdim    if (Memory.BaseRegNum == ARM::PC) return false;
1075226633Sdim    // Immediate offset in range [-255, -1].
1076234353Sdim    if (!Memory.OffsetImm) return false;
1077226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1078234353Sdim    return (Val == INT32_MIN) || (Val > -256 && Val < 0);
1079226633Sdim  }
1080226633Sdim  bool isMemUImm12Offset() const {
1081243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1082226633Sdim      return false;
1083226633Sdim    // Immediate offset in range [0, 4095].
1084226633Sdim    if (!Memory.OffsetImm) return true;
1085226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1086226633Sdim    return (Val >= 0 && Val < 4096);
1087226633Sdim  }
1088226633Sdim  bool isMemImm12Offset() const {
1089226633Sdim    // If we have an immediate that's not a constant, treat it as a label
1090226633Sdim    // reference needing a fixup. If it is a constant, it's something else
1091226633Sdim    // and we reject it.
1092234353Sdim    if (isImm() && !isa<MCConstantExpr>(getImm()))
1093226633Sdim      return true;
1094226633Sdim
1095243830Sdim    if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
1096226633Sdim      return false;
1097226633Sdim    // Immediate offset in range [-4095, 4095].
1098226633Sdim    if (!Memory.OffsetImm) return true;
1099226633Sdim    int64_t Val = Memory.OffsetImm->getValue();
1100226633Sdim    return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
1101226633Sdim  }
1102226633Sdim  bool isPostIdxImm8() const {
1103234353Sdim    if (!isImm()) return false;
1104226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1105218893Sdim    if (!CE) return false;
1106226633Sdim    int64_t Val = CE->getValue();
1107226633Sdim    return (Val > -256 && Val < 256) || (Val == INT32_MIN);
1108226633Sdim  }
1109226633Sdim  bool isPostIdxImm8s4() const {
1110234353Sdim    if (!isImm()) return false;
1111226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1112226633Sdim    if (!CE) return false;
1113226633Sdim    int64_t Val = CE->getValue();
1114226633Sdim    return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1115226633Sdim      (Val == INT32_MIN);
1116226633Sdim  }
1117218893Sdim
1118226633Sdim  bool isMSRMask() const { return Kind == k_MSRMask; }
1119226633Sdim  bool isProcIFlags() const { return Kind == k_ProcIFlags; }
1120226633Sdim
1121234353Sdim  // NEON operands.
1122234353Sdim  bool isSingleSpacedVectorList() const {
1123234353Sdim    return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1124234353Sdim  }
1125234353Sdim  bool isDoubleSpacedVectorList() const {
1126234353Sdim    return Kind == k_VectorList && VectorList.isDoubleSpaced;
1127234353Sdim  }
1128234353Sdim  bool isVecListOneD() const {
1129234353Sdim    if (!isSingleSpacedVectorList()) return false;
1130234353Sdim    return VectorList.Count == 1;
1131234353Sdim  }
1132234353Sdim
1133234353Sdim  bool isVecListDPair() const {
1134234353Sdim    if (!isSingleSpacedVectorList()) return false;
1135234353Sdim    return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1136234353Sdim              .contains(VectorList.RegNum));
1137234353Sdim  }
1138234353Sdim
1139234353Sdim  bool isVecListThreeD() const {
1140234353Sdim    if (!isSingleSpacedVectorList()) return false;
1141234353Sdim    return VectorList.Count == 3;
1142234353Sdim  }
1143234353Sdim
1144234353Sdim  bool isVecListFourD() const {
1145234353Sdim    if (!isSingleSpacedVectorList()) return false;
1146234353Sdim    return VectorList.Count == 4;
1147234353Sdim  }
1148234353Sdim
1149234353Sdim  bool isVecListDPairSpaced() const {
1150234353Sdim    if (isSingleSpacedVectorList()) return false;
1151234353Sdim    return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1152234353Sdim              .contains(VectorList.RegNum));
1153234353Sdim  }
1154234353Sdim
1155234353Sdim  bool isVecListThreeQ() const {
1156234353Sdim    if (!isDoubleSpacedVectorList()) return false;
1157234353Sdim    return VectorList.Count == 3;
1158234353Sdim  }
1159234353Sdim
1160234353Sdim  bool isVecListFourQ() const {
1161234353Sdim    if (!isDoubleSpacedVectorList()) return false;
1162234353Sdim    return VectorList.Count == 4;
1163234353Sdim  }
1164234353Sdim
1165234353Sdim  bool isSingleSpacedVectorAllLanes() const {
1166234353Sdim    return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1167234353Sdim  }
1168234353Sdim  bool isDoubleSpacedVectorAllLanes() const {
1169234353Sdim    return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1170234353Sdim  }
1171234353Sdim  bool isVecListOneDAllLanes() const {
1172234353Sdim    if (!isSingleSpacedVectorAllLanes()) return false;
1173234353Sdim    return VectorList.Count == 1;
1174234353Sdim  }
1175234353Sdim
1176234353Sdim  bool isVecListDPairAllLanes() const {
1177234353Sdim    if (!isSingleSpacedVectorAllLanes()) return false;
1178234353Sdim    return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1179234353Sdim              .contains(VectorList.RegNum));
1180234353Sdim  }
1181234353Sdim
1182234353Sdim  bool isVecListDPairSpacedAllLanes() const {
1183234353Sdim    if (!isDoubleSpacedVectorAllLanes()) return false;
1184234353Sdim    return VectorList.Count == 2;
1185234353Sdim  }
1186234353Sdim
1187234353Sdim  bool isVecListThreeDAllLanes() const {
1188234353Sdim    if (!isSingleSpacedVectorAllLanes()) return false;
1189234353Sdim    return VectorList.Count == 3;
1190234353Sdim  }
1191234353Sdim
1192234353Sdim  bool isVecListThreeQAllLanes() const {
1193234353Sdim    if (!isDoubleSpacedVectorAllLanes()) return false;
1194234353Sdim    return VectorList.Count == 3;
1195234353Sdim  }
1196234353Sdim
1197234353Sdim  bool isVecListFourDAllLanes() const {
1198234353Sdim    if (!isSingleSpacedVectorAllLanes()) return false;
1199234353Sdim    return VectorList.Count == 4;
1200234353Sdim  }
1201234353Sdim
1202234353Sdim  bool isVecListFourQAllLanes() const {
1203234353Sdim    if (!isDoubleSpacedVectorAllLanes()) return false;
1204234353Sdim    return VectorList.Count == 4;
1205234353Sdim  }
1206234353Sdim
1207234353Sdim  bool isSingleSpacedVectorIndexed() const {
1208234353Sdim    return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1209234353Sdim  }
1210234353Sdim  bool isDoubleSpacedVectorIndexed() const {
1211234353Sdim    return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1212234353Sdim  }
1213234353Sdim  bool isVecListOneDByteIndexed() const {
1214234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1215234353Sdim    return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1216234353Sdim  }
1217234353Sdim
1218234353Sdim  bool isVecListOneDHWordIndexed() const {
1219234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1220234353Sdim    return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1221234353Sdim  }
1222234353Sdim
1223234353Sdim  bool isVecListOneDWordIndexed() const {
1224234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1225234353Sdim    return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1226234353Sdim  }
1227234353Sdim
1228234353Sdim  bool isVecListTwoDByteIndexed() const {
1229234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1230234353Sdim    return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1231234353Sdim  }
1232234353Sdim
1233234353Sdim  bool isVecListTwoDHWordIndexed() const {
1234234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1235234353Sdim    return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1236234353Sdim  }
1237234353Sdim
1238234353Sdim  bool isVecListTwoQWordIndexed() const {
1239234353Sdim    if (!isDoubleSpacedVectorIndexed()) return false;
1240234353Sdim    return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1241234353Sdim  }
1242234353Sdim
1243234353Sdim  bool isVecListTwoQHWordIndexed() const {
1244234353Sdim    if (!isDoubleSpacedVectorIndexed()) return false;
1245234353Sdim    return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1246234353Sdim  }
1247234353Sdim
1248234353Sdim  bool isVecListTwoDWordIndexed() const {
1249234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1250234353Sdim    return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1251234353Sdim  }
1252234353Sdim
1253234353Sdim  bool isVecListThreeDByteIndexed() const {
1254234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1255234353Sdim    return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1256234353Sdim  }
1257234353Sdim
1258234353Sdim  bool isVecListThreeDHWordIndexed() const {
1259234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1260234353Sdim    return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1261234353Sdim  }
1262234353Sdim
1263234353Sdim  bool isVecListThreeQWordIndexed() const {
1264234353Sdim    if (!isDoubleSpacedVectorIndexed()) return false;
1265234353Sdim    return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1266234353Sdim  }
1267234353Sdim
1268234353Sdim  bool isVecListThreeQHWordIndexed() const {
1269234353Sdim    if (!isDoubleSpacedVectorIndexed()) return false;
1270234353Sdim    return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1271234353Sdim  }
1272234353Sdim
1273234353Sdim  bool isVecListThreeDWordIndexed() const {
1274234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1275234353Sdim    return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1276234353Sdim  }
1277234353Sdim
1278234353Sdim  bool isVecListFourDByteIndexed() const {
1279234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1280234353Sdim    return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1281234353Sdim  }
1282234353Sdim
1283234353Sdim  bool isVecListFourDHWordIndexed() const {
1284234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1285234353Sdim    return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1286234353Sdim  }
1287234353Sdim
1288234353Sdim  bool isVecListFourQWordIndexed() const {
1289234353Sdim    if (!isDoubleSpacedVectorIndexed()) return false;
1290234353Sdim    return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1291234353Sdim  }
1292234353Sdim
1293234353Sdim  bool isVecListFourQHWordIndexed() const {
1294234353Sdim    if (!isDoubleSpacedVectorIndexed()) return false;
1295234353Sdim    return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1296234353Sdim  }
1297234353Sdim
1298234353Sdim  bool isVecListFourDWordIndexed() const {
1299234353Sdim    if (!isSingleSpacedVectorIndexed()) return false;
1300234353Sdim    return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1301234353Sdim  }
1302234353Sdim
1303226633Sdim  bool isVectorIndex8() const {
1304226633Sdim    if (Kind != k_VectorIndex) return false;
1305226633Sdim    return VectorIndex.Val < 8;
1306218893Sdim  }
1307226633Sdim  bool isVectorIndex16() const {
1308226633Sdim    if (Kind != k_VectorIndex) return false;
1309226633Sdim    return VectorIndex.Val < 4;
1310226633Sdim  }
1311226633Sdim  bool isVectorIndex32() const {
1312226633Sdim    if (Kind != k_VectorIndex) return false;
1313226633Sdim    return VectorIndex.Val < 2;
1314226633Sdim  }
1315218893Sdim
1316234353Sdim  bool isNEONi8splat() const {
1317234353Sdim    if (!isImm()) return false;
1318234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1319234353Sdim    // Must be a constant.
1320234353Sdim    if (!CE) return false;
1321234353Sdim    int64_t Value = CE->getValue();
1322234353Sdim    // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1323234353Sdim    // value.
1324234353Sdim    return Value >= 0 && Value < 256;
1325234353Sdim  }
1326226633Sdim
1327234353Sdim  bool isNEONi16splat() const {
1328234353Sdim    if (!isImm()) return false;
1329234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1330234353Sdim    // Must be a constant.
1331234353Sdim    if (!CE) return false;
1332234353Sdim    int64_t Value = CE->getValue();
1333234353Sdim    // i16 value in the range [0,255] or [0x0100, 0xff00]
1334234353Sdim    return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1335234353Sdim  }
1336226633Sdim
1337234353Sdim  bool isNEONi32splat() const {
1338234353Sdim    if (!isImm()) return false;
1339234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1340234353Sdim    // Must be a constant.
1341234353Sdim    if (!CE) return false;
1342234353Sdim    int64_t Value = CE->getValue();
1343234353Sdim    // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1344234353Sdim    return (Value >= 0 && Value < 256) ||
1345234353Sdim      (Value >= 0x0100 && Value <= 0xff00) ||
1346234353Sdim      (Value >= 0x010000 && Value <= 0xff0000) ||
1347234353Sdim      (Value >= 0x01000000 && Value <= 0xff000000);
1348234353Sdim  }
1349234353Sdim
1350234353Sdim  bool isNEONi32vmov() const {
1351234353Sdim    if (!isImm()) return false;
1352234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1353234353Sdim    // Must be a constant.
1354234353Sdim    if (!CE) return false;
1355234353Sdim    int64_t Value = CE->getValue();
1356234353Sdim    // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1357234353Sdim    // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1358234353Sdim    return (Value >= 0 && Value < 256) ||
1359234353Sdim      (Value >= 0x0100 && Value <= 0xff00) ||
1360234353Sdim      (Value >= 0x010000 && Value <= 0xff0000) ||
1361234353Sdim      (Value >= 0x01000000 && Value <= 0xff000000) ||
1362234353Sdim      (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1363234353Sdim      (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1364234353Sdim  }
1365234353Sdim  bool isNEONi32vmovNeg() const {
1366234353Sdim    if (!isImm()) return false;
1367234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1368234353Sdim    // Must be a constant.
1369234353Sdim    if (!CE) return false;
1370234353Sdim    int64_t Value = ~CE->getValue();
1371234353Sdim    // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1372234353Sdim    // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1373234353Sdim    return (Value >= 0 && Value < 256) ||
1374234353Sdim      (Value >= 0x0100 && Value <= 0xff00) ||
1375234353Sdim      (Value >= 0x010000 && Value <= 0xff0000) ||
1376234353Sdim      (Value >= 0x01000000 && Value <= 0xff000000) ||
1377234353Sdim      (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1378234353Sdim      (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1379234353Sdim  }
1380234353Sdim
1381234353Sdim  bool isNEONi64splat() const {
1382234353Sdim    if (!isImm()) return false;
1383234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1384234353Sdim    // Must be a constant.
1385234353Sdim    if (!CE) return false;
1386234353Sdim    uint64_t Value = CE->getValue();
1387234353Sdim    // i64 value with each byte being either 0 or 0xff.
1388234353Sdim    for (unsigned i = 0; i < 8; ++i)
1389234353Sdim      if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1390234353Sdim    return true;
1391234353Sdim  }
1392234353Sdim
1393212904Sdim  void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1394218893Sdim    // Add as immediates when possible.  Null MCExpr = 0.
1395218893Sdim    if (Expr == 0)
1396218893Sdim      Inst.addOperand(MCOperand::CreateImm(0));
1397218893Sdim    else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
1398212904Sdim      Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1399212904Sdim    else
1400212904Sdim      Inst.addOperand(MCOperand::CreateExpr(Expr));
1401212904Sdim  }
1402212904Sdim
1403212904Sdim  void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1404212904Sdim    assert(N == 2 && "Invalid number of operands!");
1405212904Sdim    Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1406218893Sdim    unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1407218893Sdim    Inst.addOperand(MCOperand::CreateReg(RegNum));
1408212904Sdim  }
1409212904Sdim
1410218893Sdim  void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1411218893Sdim    assert(N == 1 && "Invalid number of operands!");
1412218893Sdim    Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1413218893Sdim  }
1414218893Sdim
1415218893Sdim  void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1416218893Sdim    assert(N == 1 && "Invalid number of operands!");
1417218893Sdim    Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1418218893Sdim  }
1419218893Sdim
1420226633Sdim  void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1421226633Sdim    assert(N == 1 && "Invalid number of operands!");
1422226633Sdim    Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1423226633Sdim  }
1424226633Sdim
1425226633Sdim  void addITMaskOperands(MCInst &Inst, unsigned N) const {
1426226633Sdim    assert(N == 1 && "Invalid number of operands!");
1427226633Sdim    Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1428226633Sdim  }
1429226633Sdim
1430226633Sdim  void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1431226633Sdim    assert(N == 1 && "Invalid number of operands!");
1432226633Sdim    Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1433226633Sdim  }
1434226633Sdim
1435218893Sdim  void addCCOutOperands(MCInst &Inst, unsigned N) const {
1436218893Sdim    assert(N == 1 && "Invalid number of operands!");
1437218893Sdim    Inst.addOperand(MCOperand::CreateReg(getReg()));
1438218893Sdim  }
1439218893Sdim
1440198090Srdivacky  void addRegOperands(MCInst &Inst, unsigned N) const {
1441198090Srdivacky    assert(N == 1 && "Invalid number of operands!");
1442198090Srdivacky    Inst.addOperand(MCOperand::CreateReg(getReg()));
1443198090Srdivacky  }
1444198090Srdivacky
1445226633Sdim  void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
1446224145Sdim    assert(N == 3 && "Invalid number of operands!");
1447234353Sdim    assert(isRegShiftedReg() &&
1448234353Sdim           "addRegShiftedRegOperands() on non RegShiftedReg!");
1449226633Sdim    Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1450226633Sdim    Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
1451224145Sdim    Inst.addOperand(MCOperand::CreateImm(
1452226633Sdim      ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
1453224145Sdim  }
1454224145Sdim
1455226633Sdim  void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
1456226633Sdim    assert(N == 2 && "Invalid number of operands!");
1457234353Sdim    assert(isRegShiftedImm() &&
1458234353Sdim           "addRegShiftedImmOperands() on non RegShiftedImm!");
1459226633Sdim    Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
1460239462Sdim    // Shift of #32 is encoded as 0 where permitted
1461239462Sdim    unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm);
1462221345Sdim    Inst.addOperand(MCOperand::CreateImm(
1463239462Sdim      ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm)));
1464221345Sdim  }
1465221345Sdim
1466226633Sdim  void addShifterImmOperands(MCInst &Inst, unsigned N) const {
1467226633Sdim    assert(N == 1 && "Invalid number of operands!");
1468226633Sdim    Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1469226633Sdim                                         ShifterImm.Imm));
1470226633Sdim  }
1471226633Sdim
1472218893Sdim  void addRegListOperands(MCInst &Inst, unsigned N) const {
1473218893Sdim    assert(N == 1 && "Invalid number of operands!");
1474218893Sdim    const SmallVectorImpl<unsigned> &RegList = getRegList();
1475218893Sdim    for (SmallVectorImpl<unsigned>::const_iterator
1476218893Sdim           I = RegList.begin(), E = RegList.end(); I != E; ++I)
1477218893Sdim      Inst.addOperand(MCOperand::CreateReg(*I));
1478218893Sdim  }
1479218893Sdim
1480218893Sdim  void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1481218893Sdim    addRegListOperands(Inst, N);
1482218893Sdim  }
1483218893Sdim
1484218893Sdim  void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1485218893Sdim    addRegListOperands(Inst, N);
1486218893Sdim  }
1487218893Sdim
1488226633Sdim  void addRotImmOperands(MCInst &Inst, unsigned N) const {
1489226633Sdim    assert(N == 1 && "Invalid number of operands!");
1490226633Sdim    // Encoded as val>>3. The printer handles display as 8, 16, 24.
1491226633Sdim    Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1492226633Sdim  }
1493226633Sdim
1494226633Sdim  void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1495226633Sdim    assert(N == 1 && "Invalid number of operands!");
1496226633Sdim    // Munge the lsb/width into a bitfield mask.
1497226633Sdim    unsigned lsb = Bitfield.LSB;
1498226633Sdim    unsigned width = Bitfield.Width;
1499226633Sdim    // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1500226633Sdim    uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1501226633Sdim                      (32 - (lsb + width)));
1502226633Sdim    Inst.addOperand(MCOperand::CreateImm(Mask));
1503226633Sdim  }
1504226633Sdim
1505212904Sdim  void addImmOperands(MCInst &Inst, unsigned N) const {
1506212904Sdim    assert(N == 1 && "Invalid number of operands!");
1507212904Sdim    addExpr(Inst, getImm());
1508212904Sdim  }
1509212904Sdim
1510234353Sdim  void addFBits16Operands(MCInst &Inst, unsigned N) const {
1511234353Sdim    assert(N == 1 && "Invalid number of operands!");
1512234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1513234353Sdim    Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1514234353Sdim  }
1515234353Sdim
1516234353Sdim  void addFBits32Operands(MCInst &Inst, unsigned N) const {
1517234353Sdim    assert(N == 1 && "Invalid number of operands!");
1518234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1519234353Sdim    Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1520234353Sdim  }
1521234353Sdim
1522226633Sdim  void addFPImmOperands(MCInst &Inst, unsigned N) const {
1523226633Sdim    assert(N == 1 && "Invalid number of operands!");
1524234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1525234353Sdim    int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1526234353Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1527226633Sdim  }
1528226633Sdim
1529226633Sdim  void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1530226633Sdim    assert(N == 1 && "Invalid number of operands!");
1531226633Sdim    // FIXME: We really want to scale the value here, but the LDRD/STRD
1532226633Sdim    // instruction don't encode operands that way yet.
1533226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1534226633Sdim    Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1535226633Sdim  }
1536226633Sdim
1537226633Sdim  void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1538226633Sdim    assert(N == 1 && "Invalid number of operands!");
1539226633Sdim    // The immediate is scaled by four in the encoding and is stored
1540226633Sdim    // in the MCInst as such. Lop off the low two bits here.
1541226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1542226633Sdim    Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1543226633Sdim  }
1544226633Sdim
1545234353Sdim  void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
1546226633Sdim    assert(N == 1 && "Invalid number of operands!");
1547226633Sdim    // The immediate is scaled by four in the encoding and is stored
1548226633Sdim    // in the MCInst as such. Lop off the low two bits here.
1549226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1550234353Sdim    Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
1551226633Sdim  }
1552226633Sdim
1553234353Sdim  void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1554224145Sdim    assert(N == 1 && "Invalid number of operands!");
1555234353Sdim    // The immediate is scaled by four in the encoding and is stored
1556234353Sdim    // in the MCInst as such. Lop off the low two bits here.
1557234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1558234353Sdim    Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1559224145Sdim  }
1560224145Sdim
1561226633Sdim  void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1562226633Sdim    assert(N == 1 && "Invalid number of operands!");
1563226633Sdim    // The constant encodes as the immediate-1, and we store in the instruction
1564226633Sdim    // the bits as encoded, so subtract off one here.
1565226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1566226633Sdim    Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1567226633Sdim  }
1568226633Sdim
1569226633Sdim  void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1570226633Sdim    assert(N == 1 && "Invalid number of operands!");
1571226633Sdim    // The constant encodes as the immediate-1, and we store in the instruction
1572226633Sdim    // the bits as encoded, so subtract off one here.
1573226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1574226633Sdim    Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1575226633Sdim  }
1576226633Sdim
1577226633Sdim  void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1578226633Sdim    assert(N == 1 && "Invalid number of operands!");
1579226633Sdim    // The constant encodes as the immediate, except for 32, which encodes as
1580226633Sdim    // zero.
1581226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1582226633Sdim    unsigned Imm = CE->getValue();
1583226633Sdim    Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1584226633Sdim  }
1585226633Sdim
1586226633Sdim  void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1587226633Sdim    assert(N == 1 && "Invalid number of operands!");
1588226633Sdim    // An ASR value of 32 encodes as 0, so that's how we want to add it to
1589226633Sdim    // the instruction as well.
1590226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1591226633Sdim    int Val = CE->getValue();
1592226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1593226633Sdim  }
1594226633Sdim
1595234353Sdim  void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1596226633Sdim    assert(N == 1 && "Invalid number of operands!");
1597234353Sdim    // The operand is actually a t2_so_imm, but we have its bitwise
1598234353Sdim    // negation in the assembly source, so twiddle it here.
1599234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1600234353Sdim    Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1601226633Sdim  }
1602226633Sdim
1603234353Sdim  void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1604224145Sdim    assert(N == 1 && "Invalid number of operands!");
1605234353Sdim    // The operand is actually a t2_so_imm, but we have its
1606234353Sdim    // negation in the assembly source, so twiddle it here.
1607234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1608234353Sdim    Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1609224145Sdim  }
1610224145Sdim
1611234353Sdim  void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
1612226633Sdim    assert(N == 1 && "Invalid number of operands!");
1613234353Sdim    // The operand is actually an imm0_4095, but we have its
1614234353Sdim    // negation in the assembly source, so twiddle it here.
1615234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1616234353Sdim    Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1617226633Sdim  }
1618226633Sdim
1619234353Sdim  void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1620234353Sdim    assert(N == 1 && "Invalid number of operands!");
1621234353Sdim    // The operand is actually a so_imm, but we have its bitwise
1622234353Sdim    // negation in the assembly source, so twiddle it here.
1623234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1624234353Sdim    Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1625234353Sdim  }
1626234353Sdim
1627234353Sdim  void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1628234353Sdim    assert(N == 1 && "Invalid number of operands!");
1629234353Sdim    // The operand is actually a so_imm, but we have its
1630234353Sdim    // negation in the assembly source, so twiddle it here.
1631234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1632234353Sdim    Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1633234353Sdim  }
1634234353Sdim
1635218893Sdim  void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1636218893Sdim    assert(N == 1 && "Invalid number of operands!");
1637218893Sdim    Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1638218893Sdim  }
1639218893Sdim
1640226633Sdim  void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1641226633Sdim    assert(N == 1 && "Invalid number of operands!");
1642226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1643226633Sdim  }
1644221345Sdim
1645234353Sdim  void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1646234353Sdim    assert(N == 1 && "Invalid number of operands!");
1647234353Sdim    int32_t Imm = Memory.OffsetImm->getValue();
1648234353Sdim    // FIXME: Handle #-0
1649234353Sdim    if (Imm == INT32_MIN) Imm = 0;
1650234353Sdim    Inst.addOperand(MCOperand::CreateImm(Imm));
1651234353Sdim  }
1652234353Sdim
1653239462Sdim  void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1654239462Sdim    assert(N == 1 && "Invalid number of operands!");
1655239462Sdim    assert(isImm() && "Not an immediate!");
1656239462Sdim
1657239462Sdim    // If we have an immediate that's not a constant, treat it as a label
1658239462Sdim    // reference needing a fixup.
1659239462Sdim    if (!isa<MCConstantExpr>(getImm())) {
1660239462Sdim      Inst.addOperand(MCOperand::CreateExpr(getImm()));
1661239462Sdim      return;
1662239462Sdim    }
1663239462Sdim
1664239462Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1665239462Sdim    int Val = CE->getValue();
1666239462Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1667239462Sdim  }
1668239462Sdim
1669226633Sdim  void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1670226633Sdim    assert(N == 2 && "Invalid number of operands!");
1671226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1672226633Sdim    Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1673221345Sdim  }
1674221345Sdim
1675226633Sdim  void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1676226633Sdim    assert(N == 3 && "Invalid number of operands!");
1677226633Sdim    int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1678226633Sdim    if (!Memory.OffsetRegNum) {
1679226633Sdim      ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1680226633Sdim      // Special case for #-0
1681226633Sdim      if (Val == INT32_MIN) Val = 0;
1682226633Sdim      if (Val < 0) Val = -Val;
1683226633Sdim      Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1684226633Sdim    } else {
1685226633Sdim      // For register offset, we encode the shift type and negation flag
1686226633Sdim      // here.
1687226633Sdim      Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1688226633Sdim                              Memory.ShiftImm, Memory.ShiftType);
1689226633Sdim    }
1690226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1691226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1692226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1693226633Sdim  }
1694221345Sdim
1695226633Sdim  void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1696226633Sdim    assert(N == 2 && "Invalid number of operands!");
1697226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1698226633Sdim    assert(CE && "non-constant AM2OffsetImm operand!");
1699226633Sdim    int32_t Val = CE->getValue();
1700226633Sdim    ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1701226633Sdim    // Special case for #-0
1702226633Sdim    if (Val == INT32_MIN) Val = 0;
1703226633Sdim    if (Val < 0) Val = -Val;
1704226633Sdim    Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1705226633Sdim    Inst.addOperand(MCOperand::CreateReg(0));
1706226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1707226633Sdim  }
1708221345Sdim
1709226633Sdim  void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1710226633Sdim    assert(N == 3 && "Invalid number of operands!");
1711234353Sdim    // If we have an immediate that's not a constant, treat it as a label
1712234353Sdim    // reference needing a fixup. If it is a constant, it's something else
1713234353Sdim    // and we reject it.
1714234353Sdim    if (isImm()) {
1715234353Sdim      Inst.addOperand(MCOperand::CreateExpr(getImm()));
1716234353Sdim      Inst.addOperand(MCOperand::CreateReg(0));
1717234353Sdim      Inst.addOperand(MCOperand::CreateImm(0));
1718234353Sdim      return;
1719234353Sdim    }
1720234353Sdim
1721226633Sdim    int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1722226633Sdim    if (!Memory.OffsetRegNum) {
1723226633Sdim      ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1724226633Sdim      // Special case for #-0
1725226633Sdim      if (Val == INT32_MIN) Val = 0;
1726226633Sdim      if (Val < 0) Val = -Val;
1727226633Sdim      Val = ARM_AM::getAM3Opc(AddSub, Val);
1728226633Sdim    } else {
1729226633Sdim      // For register offset, we encode the shift type and negation flag
1730226633Sdim      // here.
1731226633Sdim      Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
1732226633Sdim    }
1733226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1734226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1735226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1736226633Sdim  }
1737221345Sdim
1738226633Sdim  void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1739226633Sdim    assert(N == 2 && "Invalid number of operands!");
1740226633Sdim    if (Kind == k_PostIndexRegister) {
1741226633Sdim      int32_t Val =
1742226633Sdim        ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1743226633Sdim      Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1744226633Sdim      Inst.addOperand(MCOperand::CreateImm(Val));
1745221345Sdim      return;
1746221345Sdim    }
1747221345Sdim
1748226633Sdim    // Constant offset.
1749226633Sdim    const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1750226633Sdim    int32_t Val = CE->getValue();
1751226633Sdim    ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1752226633Sdim    // Special case for #-0
1753226633Sdim    if (Val == INT32_MIN) Val = 0;
1754226633Sdim    if (Val < 0) Val = -Val;
1755226633Sdim    Val = ARM_AM::getAM3Opc(AddSub, Val);
1756221345Sdim    Inst.addOperand(MCOperand::CreateReg(0));
1757226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1758226633Sdim  }
1759221345Sdim
1760226633Sdim  void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1761226633Sdim    assert(N == 2 && "Invalid number of operands!");
1762234353Sdim    // If we have an immediate that's not a constant, treat it as a label
1763234353Sdim    // reference needing a fixup. If it is a constant, it's something else
1764234353Sdim    // and we reject it.
1765234353Sdim    if (isImm()) {
1766234353Sdim      Inst.addOperand(MCOperand::CreateExpr(getImm()));
1767234353Sdim      Inst.addOperand(MCOperand::CreateImm(0));
1768234353Sdim      return;
1769234353Sdim    }
1770234353Sdim
1771226633Sdim    // The lower two bits are always zero and as such are not encoded.
1772226633Sdim    int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1773226633Sdim    ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1774226633Sdim    // Special case for #-0
1775226633Sdim    if (Val == INT32_MIN) Val = 0;
1776226633Sdim    if (Val < 0) Val = -Val;
1777226633Sdim    Val = ARM_AM::getAM5Opc(AddSub, Val);
1778226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1779226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1780226633Sdim  }
1781221345Sdim
1782226633Sdim  void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1783226633Sdim    assert(N == 2 && "Invalid number of operands!");
1784234353Sdim    // If we have an immediate that's not a constant, treat it as a label
1785234353Sdim    // reference needing a fixup. If it is a constant, it's something else
1786234353Sdim    // and we reject it.
1787234353Sdim    if (isImm()) {
1788234353Sdim      Inst.addOperand(MCOperand::CreateExpr(getImm()));
1789234353Sdim      Inst.addOperand(MCOperand::CreateImm(0));
1790234353Sdim      return;
1791234353Sdim    }
1792234353Sdim
1793226633Sdim    int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1794226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1795226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1796221345Sdim  }
1797221345Sdim
1798226633Sdim  void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1799226633Sdim    assert(N == 2 && "Invalid number of operands!");
1800226633Sdim    // The lower two bits are always zero and as such are not encoded.
1801226633Sdim    int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1802226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1803226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1804226633Sdim  }
1805221345Sdim
1806226633Sdim  void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1807226633Sdim    assert(N == 2 && "Invalid number of operands!");
1808226633Sdim    int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1809226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1810226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1811226633Sdim  }
1812221345Sdim
1813226633Sdim  void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1814226633Sdim    addMemImm8OffsetOperands(Inst, N);
1815226633Sdim  }
1816226633Sdim
1817226633Sdim  void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1818226633Sdim    addMemImm8OffsetOperands(Inst, N);
1819226633Sdim  }
1820226633Sdim
1821226633Sdim  void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1822226633Sdim    assert(N == 2 && "Invalid number of operands!");
1823226633Sdim    // If this is an immediate, it's a label reference.
1824234353Sdim    if (isImm()) {
1825226633Sdim      addExpr(Inst, getImm());
1826226633Sdim      Inst.addOperand(MCOperand::CreateImm(0));
1827221345Sdim      return;
1828221345Sdim    }
1829221345Sdim
1830226633Sdim    // Otherwise, it's a normal memory reg+offset.
1831226633Sdim    int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1832226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1833226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1834226633Sdim  }
1835221345Sdim
1836226633Sdim  void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1837226633Sdim    assert(N == 2 && "Invalid number of operands!");
1838226633Sdim    // If this is an immediate, it's a label reference.
1839234353Sdim    if (isImm()) {
1840226633Sdim      addExpr(Inst, getImm());
1841226633Sdim      Inst.addOperand(MCOperand::CreateImm(0));
1842226633Sdim      return;
1843226633Sdim    }
1844221345Sdim
1845226633Sdim    // Otherwise, it's a normal memory reg+offset.
1846226633Sdim    int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1847226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1848226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1849221345Sdim  }
1850221345Sdim
1851226633Sdim  void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1852226633Sdim    assert(N == 2 && "Invalid number of operands!");
1853226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1854226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1855226633Sdim  }
1856218893Sdim
1857226633Sdim  void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1858226633Sdim    assert(N == 2 && "Invalid number of operands!");
1859226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1860226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1861226633Sdim  }
1862218893Sdim
1863226633Sdim  void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1864226633Sdim    assert(N == 3 && "Invalid number of operands!");
1865234353Sdim    unsigned Val =
1866234353Sdim      ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1867234353Sdim                        Memory.ShiftImm, Memory.ShiftType);
1868226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1869226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1870226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1871226633Sdim  }
1872218893Sdim
1873226633Sdim  void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1874226633Sdim    assert(N == 3 && "Invalid number of operands!");
1875226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1876226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1877226633Sdim    Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
1878218893Sdim  }
1879218893Sdim
1880226633Sdim  void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1881226633Sdim    assert(N == 2 && "Invalid number of operands!");
1882226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1883226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1884218893Sdim  }
1885218893Sdim
1886226633Sdim  void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1887226633Sdim    assert(N == 2 && "Invalid number of operands!");
1888226633Sdim    int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1889226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1890226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1891218893Sdim  }
1892218893Sdim
1893226633Sdim  void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1894226633Sdim    assert(N == 2 && "Invalid number of operands!");
1895226633Sdim    int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1896226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1897226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1898226633Sdim  }
1899226633Sdim
1900226633Sdim  void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1901226633Sdim    assert(N == 2 && "Invalid number of operands!");
1902226633Sdim    int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1903226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1904226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1905226633Sdim  }
1906226633Sdim
1907226633Sdim  void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1908226633Sdim    assert(N == 2 && "Invalid number of operands!");
1909226633Sdim    int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1910226633Sdim    Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1911226633Sdim    Inst.addOperand(MCOperand::CreateImm(Val));
1912226633Sdim  }
1913226633Sdim
1914226633Sdim  void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1915226633Sdim    assert(N == 1 && "Invalid number of operands!");
1916226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1917226633Sdim    assert(CE && "non-constant post-idx-imm8 operand!");
1918226633Sdim    int Imm = CE->getValue();
1919226633Sdim    bool isAdd = Imm >= 0;
1920226633Sdim    if (Imm == INT32_MIN) Imm = 0;
1921226633Sdim    Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1922226633Sdim    Inst.addOperand(MCOperand::CreateImm(Imm));
1923226633Sdim  }
1924226633Sdim
1925226633Sdim  void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1926226633Sdim    assert(N == 1 && "Invalid number of operands!");
1927226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1928226633Sdim    assert(CE && "non-constant post-idx-imm8s4 operand!");
1929226633Sdim    int Imm = CE->getValue();
1930226633Sdim    bool isAdd = Imm >= 0;
1931226633Sdim    if (Imm == INT32_MIN) Imm = 0;
1932226633Sdim    // Immediate is scaled by 4.
1933226633Sdim    Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1934226633Sdim    Inst.addOperand(MCOperand::CreateImm(Imm));
1935226633Sdim  }
1936226633Sdim
1937226633Sdim  void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1938226633Sdim    assert(N == 2 && "Invalid number of operands!");
1939226633Sdim    Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1940226633Sdim    Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1941226633Sdim  }
1942226633Sdim
1943226633Sdim  void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1944226633Sdim    assert(N == 2 && "Invalid number of operands!");
1945226633Sdim    Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1946226633Sdim    // The sign, shift type, and shift amount are encoded in a single operand
1947226633Sdim    // using the AM2 encoding helpers.
1948226633Sdim    ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1949226633Sdim    unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1950226633Sdim                                     PostIdxReg.ShiftTy);
1951226633Sdim    Inst.addOperand(MCOperand::CreateImm(Imm));
1952226633Sdim  }
1953226633Sdim
1954218893Sdim  void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1955218893Sdim    assert(N == 1 && "Invalid number of operands!");
1956218893Sdim    Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1957218893Sdim  }
1958218893Sdim
1959218893Sdim  void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1960218893Sdim    assert(N == 1 && "Invalid number of operands!");
1961218893Sdim    Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1962218893Sdim  }
1963218893Sdim
1964234353Sdim  void addVecListOperands(MCInst &Inst, unsigned N) const {
1965234353Sdim    assert(N == 1 && "Invalid number of operands!");
1966234353Sdim    Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1967234353Sdim  }
1968234353Sdim
1969234353Sdim  void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1970234353Sdim    assert(N == 2 && "Invalid number of operands!");
1971234353Sdim    Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1972234353Sdim    Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1973234353Sdim  }
1974234353Sdim
1975226633Sdim  void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1976226633Sdim    assert(N == 1 && "Invalid number of operands!");
1977226633Sdim    Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1978226633Sdim  }
1979226633Sdim
1980226633Sdim  void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1981226633Sdim    assert(N == 1 && "Invalid number of operands!");
1982226633Sdim    Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1983226633Sdim  }
1984226633Sdim
1985226633Sdim  void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1986226633Sdim    assert(N == 1 && "Invalid number of operands!");
1987226633Sdim    Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1988226633Sdim  }
1989226633Sdim
1990234353Sdim  void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1991234353Sdim    assert(N == 1 && "Invalid number of operands!");
1992234353Sdim    // The immediate encodes the type of constant as well as the value.
1993234353Sdim    // Mask in that this is an i8 splat.
1994234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1995234353Sdim    Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1996234353Sdim  }
1997234353Sdim
1998234353Sdim  void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1999234353Sdim    assert(N == 1 && "Invalid number of operands!");
2000234353Sdim    // The immediate encodes the type of constant as well as the value.
2001234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2002234353Sdim    unsigned Value = CE->getValue();
2003234353Sdim    if (Value >= 256)
2004234353Sdim      Value = (Value >> 8) | 0xa00;
2005234353Sdim    else
2006234353Sdim      Value |= 0x800;
2007234353Sdim    Inst.addOperand(MCOperand::CreateImm(Value));
2008234353Sdim  }
2009234353Sdim
2010234353Sdim  void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
2011234353Sdim    assert(N == 1 && "Invalid number of operands!");
2012234353Sdim    // The immediate encodes the type of constant as well as the value.
2013234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2014234353Sdim    unsigned Value = CE->getValue();
2015234353Sdim    if (Value >= 256 && Value <= 0xff00)
2016234353Sdim      Value = (Value >> 8) | 0x200;
2017234353Sdim    else if (Value > 0xffff && Value <= 0xff0000)
2018234353Sdim      Value = (Value >> 16) | 0x400;
2019234353Sdim    else if (Value > 0xffffff)
2020234353Sdim      Value = (Value >> 24) | 0x600;
2021234353Sdim    Inst.addOperand(MCOperand::CreateImm(Value));
2022234353Sdim  }
2023234353Sdim
2024234353Sdim  void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
2025234353Sdim    assert(N == 1 && "Invalid number of operands!");
2026234353Sdim    // The immediate encodes the type of constant as well as the value.
2027234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2028234353Sdim    unsigned Value = CE->getValue();
2029234353Sdim    if (Value >= 256 && Value <= 0xffff)
2030234353Sdim      Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2031234353Sdim    else if (Value > 0xffff && Value <= 0xffffff)
2032234353Sdim      Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2033234353Sdim    else if (Value > 0xffffff)
2034234353Sdim      Value = (Value >> 24) | 0x600;
2035234353Sdim    Inst.addOperand(MCOperand::CreateImm(Value));
2036234353Sdim  }
2037234353Sdim
2038234353Sdim  void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2039234353Sdim    assert(N == 1 && "Invalid number of operands!");
2040234353Sdim    // The immediate encodes the type of constant as well as the value.
2041234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2042234353Sdim    unsigned Value = ~CE->getValue();
2043234353Sdim    if (Value >= 256 && Value <= 0xffff)
2044234353Sdim      Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2045234353Sdim    else if (Value > 0xffff && Value <= 0xffffff)
2046234353Sdim      Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2047234353Sdim    else if (Value > 0xffffff)
2048234353Sdim      Value = (Value >> 24) | 0x600;
2049234353Sdim    Inst.addOperand(MCOperand::CreateImm(Value));
2050234353Sdim  }
2051234353Sdim
2052234353Sdim  void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2053234353Sdim    assert(N == 1 && "Invalid number of operands!");
2054234353Sdim    // The immediate encodes the type of constant as well as the value.
2055234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2056234353Sdim    uint64_t Value = CE->getValue();
2057234353Sdim    unsigned Imm = 0;
2058234353Sdim    for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2059234353Sdim      Imm |= (Value & 1) << i;
2060234353Sdim    }
2061234353Sdim    Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
2062234353Sdim  }
2063234353Sdim
2064224145Sdim  virtual void print(raw_ostream &OS) const;
2065212904Sdim
2066226633Sdim  static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
2067226633Sdim    ARMOperand *Op = new ARMOperand(k_ITCondMask);
2068226633Sdim    Op->ITMask.Mask = Mask;
2069226633Sdim    Op->StartLoc = S;
2070226633Sdim    Op->EndLoc = S;
2071226633Sdim    return Op;
2072226633Sdim  }
2073226633Sdim
2074218893Sdim  static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
2075226633Sdim    ARMOperand *Op = new ARMOperand(k_CondCode);
2076212904Sdim    Op->CC.Val = CC;
2077212904Sdim    Op->StartLoc = S;
2078212904Sdim    Op->EndLoc = S;
2079218893Sdim    return Op;
2080212904Sdim  }
2081212904Sdim
2082218893Sdim  static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
2083226633Sdim    ARMOperand *Op = new ARMOperand(k_CoprocNum);
2084218893Sdim    Op->Cop.Val = CopVal;
2085218893Sdim    Op->StartLoc = S;
2086218893Sdim    Op->EndLoc = S;
2087218893Sdim    return Op;
2088218893Sdim  }
2089218893Sdim
2090218893Sdim  static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
2091226633Sdim    ARMOperand *Op = new ARMOperand(k_CoprocReg);
2092218893Sdim    Op->Cop.Val = CopVal;
2093218893Sdim    Op->StartLoc = S;
2094218893Sdim    Op->EndLoc = S;
2095218893Sdim    return Op;
2096218893Sdim  }
2097218893Sdim
2098226633Sdim  static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2099226633Sdim    ARMOperand *Op = new ARMOperand(k_CoprocOption);
2100226633Sdim    Op->Cop.Val = Val;
2101226633Sdim    Op->StartLoc = S;
2102226633Sdim    Op->EndLoc = E;
2103226633Sdim    return Op;
2104226633Sdim  }
2105226633Sdim
2106218893Sdim  static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
2107226633Sdim    ARMOperand *Op = new ARMOperand(k_CCOut);
2108218893Sdim    Op->Reg.RegNum = RegNum;
2109218893Sdim    Op->StartLoc = S;
2110218893Sdim    Op->EndLoc = S;
2111218893Sdim    return Op;
2112218893Sdim  }
2113218893Sdim
2114218893Sdim  static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
2115226633Sdim    ARMOperand *Op = new ARMOperand(k_Token);
2116206124Srdivacky    Op->Tok.Data = Str.data();
2117206124Srdivacky    Op->Tok.Length = Str.size();
2118206124Srdivacky    Op->StartLoc = S;
2119206124Srdivacky    Op->EndLoc = S;
2120218893Sdim    return Op;
2121198090Srdivacky  }
2122198090Srdivacky
2123218893Sdim  static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
2124226633Sdim    ARMOperand *Op = new ARMOperand(k_Register);
2125206124Srdivacky    Op->Reg.RegNum = RegNum;
2126206124Srdivacky    Op->StartLoc = S;
2127206124Srdivacky    Op->EndLoc = E;
2128218893Sdim    return Op;
2129198090Srdivacky  }
2130198090Srdivacky
2131224145Sdim  static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2132224145Sdim                                           unsigned SrcReg,
2133224145Sdim                                           unsigned ShiftReg,
2134224145Sdim                                           unsigned ShiftImm,
2135224145Sdim                                           SMLoc S, SMLoc E) {
2136226633Sdim    ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
2137226633Sdim    Op->RegShiftedReg.ShiftTy = ShTy;
2138226633Sdim    Op->RegShiftedReg.SrcReg = SrcReg;
2139226633Sdim    Op->RegShiftedReg.ShiftReg = ShiftReg;
2140226633Sdim    Op->RegShiftedReg.ShiftImm = ShiftImm;
2141224145Sdim    Op->StartLoc = S;
2142224145Sdim    Op->EndLoc = E;
2143224145Sdim    return Op;
2144224145Sdim  }
2145224145Sdim
2146226633Sdim  static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2147226633Sdim                                            unsigned SrcReg,
2148226633Sdim                                            unsigned ShiftImm,
2149226633Sdim                                            SMLoc S, SMLoc E) {
2150226633Sdim    ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
2151226633Sdim    Op->RegShiftedImm.ShiftTy = ShTy;
2152226633Sdim    Op->RegShiftedImm.SrcReg = SrcReg;
2153226633Sdim    Op->RegShiftedImm.ShiftImm = ShiftImm;
2154226633Sdim    Op->StartLoc = S;
2155226633Sdim    Op->EndLoc = E;
2156226633Sdim    return Op;
2157226633Sdim  }
2158226633Sdim
2159226633Sdim  static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
2160221345Sdim                                   SMLoc S, SMLoc E) {
2161226633Sdim    ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
2162226633Sdim    Op->ShifterImm.isASR = isASR;
2163226633Sdim    Op->ShifterImm.Imm = Imm;
2164221345Sdim    Op->StartLoc = S;
2165221345Sdim    Op->EndLoc = E;
2166221345Sdim    return Op;
2167221345Sdim  }
2168221345Sdim
2169226633Sdim  static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
2170226633Sdim    ARMOperand *Op = new ARMOperand(k_RotateImmediate);
2171226633Sdim    Op->RotImm.Imm = Imm;
2172226633Sdim    Op->StartLoc = S;
2173226633Sdim    Op->EndLoc = E;
2174226633Sdim    return Op;
2175226633Sdim  }
2176226633Sdim
2177226633Sdim  static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2178226633Sdim                                    SMLoc S, SMLoc E) {
2179226633Sdim    ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
2180226633Sdim    Op->Bitfield.LSB = LSB;
2181226633Sdim    Op->Bitfield.Width = Width;
2182226633Sdim    Op->StartLoc = S;
2183226633Sdim    Op->EndLoc = E;
2184226633Sdim    return Op;
2185226633Sdim  }
2186226633Sdim
2187218893Sdim  static ARMOperand *
2188218893Sdim  CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
2189218893Sdim                SMLoc StartLoc, SMLoc EndLoc) {
2190226633Sdim    KindTy Kind = k_RegisterList;
2191218893Sdim
2192226633Sdim    if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
2193226633Sdim      Kind = k_DPRRegisterList;
2194226633Sdim    else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
2195226633Sdim             contains(Regs.front().first))
2196226633Sdim      Kind = k_SPRRegisterList;
2197218893Sdim
2198218893Sdim    ARMOperand *Op = new ARMOperand(Kind);
2199218893Sdim    for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
2200218893Sdim           I = Regs.begin(), E = Regs.end(); I != E; ++I)
2201218893Sdim      Op->Registers.push_back(I->first);
2202218893Sdim    array_pod_sort(Op->Registers.begin(), Op->Registers.end());
2203218893Sdim    Op->StartLoc = StartLoc;
2204218893Sdim    Op->EndLoc = EndLoc;
2205218893Sdim    return Op;
2206218893Sdim  }
2207218893Sdim
2208234353Sdim  static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
2209234353Sdim                                      bool isDoubleSpaced, SMLoc S, SMLoc E) {
2210234353Sdim    ARMOperand *Op = new ARMOperand(k_VectorList);
2211234353Sdim    Op->VectorList.RegNum = RegNum;
2212234353Sdim    Op->VectorList.Count = Count;
2213234353Sdim    Op->VectorList.isDoubleSpaced = isDoubleSpaced;
2214234353Sdim    Op->StartLoc = S;
2215234353Sdim    Op->EndLoc = E;
2216234353Sdim    return Op;
2217234353Sdim  }
2218234353Sdim
2219234353Sdim  static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
2220234353Sdim                                              bool isDoubleSpaced,
2221234353Sdim                                              SMLoc S, SMLoc E) {
2222234353Sdim    ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2223234353Sdim    Op->VectorList.RegNum = RegNum;
2224234353Sdim    Op->VectorList.Count = Count;
2225234353Sdim    Op->VectorList.isDoubleSpaced = isDoubleSpaced;
2226234353Sdim    Op->StartLoc = S;
2227234353Sdim    Op->EndLoc = E;
2228234353Sdim    return Op;
2229234353Sdim  }
2230234353Sdim
2231234353Sdim  static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
2232234353Sdim                                             unsigned Index,
2233234353Sdim                                             bool isDoubleSpaced,
2234234353Sdim                                             SMLoc S, SMLoc E) {
2235234353Sdim    ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2236234353Sdim    Op->VectorList.RegNum = RegNum;
2237234353Sdim    Op->VectorList.Count = Count;
2238234353Sdim    Op->VectorList.LaneIndex = Index;
2239234353Sdim    Op->VectorList.isDoubleSpaced = isDoubleSpaced;
2240234353Sdim    Op->StartLoc = S;
2241234353Sdim    Op->EndLoc = E;
2242234353Sdim    return Op;
2243234353Sdim  }
2244234353Sdim
2245226633Sdim  static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2246226633Sdim                                       MCContext &Ctx) {
2247226633Sdim    ARMOperand *Op = new ARMOperand(k_VectorIndex);
2248226633Sdim    Op->VectorIndex.Val = Idx;
2249226633Sdim    Op->StartLoc = S;
2250226633Sdim    Op->EndLoc = E;
2251226633Sdim    return Op;
2252226633Sdim  }
2253226633Sdim
2254218893Sdim  static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
2255226633Sdim    ARMOperand *Op = new ARMOperand(k_Immediate);
2256206124Srdivacky    Op->Imm.Val = Val;
2257206124Srdivacky    Op->StartLoc = S;
2258206124Srdivacky    Op->EndLoc = E;
2259218893Sdim    return Op;
2260198090Srdivacky  }
2261198090Srdivacky
2262226633Sdim  static ARMOperand *CreateMem(unsigned BaseRegNum,
2263226633Sdim                               const MCConstantExpr *OffsetImm,
2264226633Sdim                               unsigned OffsetRegNum,
2265226633Sdim                               ARM_AM::ShiftOpc ShiftType,
2266226633Sdim                               unsigned ShiftImm,
2267226633Sdim                               unsigned Alignment,
2268226633Sdim                               bool isNegative,
2269218893Sdim                               SMLoc S, SMLoc E) {
2270226633Sdim    ARMOperand *Op = new ARMOperand(k_Memory);
2271226633Sdim    Op->Memory.BaseRegNum = BaseRegNum;
2272226633Sdim    Op->Memory.OffsetImm = OffsetImm;
2273226633Sdim    Op->Memory.OffsetRegNum = OffsetRegNum;
2274226633Sdim    Op->Memory.ShiftType = ShiftType;
2275226633Sdim    Op->Memory.ShiftImm = ShiftImm;
2276226633Sdim    Op->Memory.Alignment = Alignment;
2277226633Sdim    Op->Memory.isNegative = isNegative;
2278226633Sdim    Op->StartLoc = S;
2279226633Sdim    Op->EndLoc = E;
2280226633Sdim    return Op;
2281226633Sdim  }
2282218893Sdim
2283226633Sdim  static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2284226633Sdim                                      ARM_AM::ShiftOpc ShiftTy,
2285226633Sdim                                      unsigned ShiftImm,
2286226633Sdim                                      SMLoc S, SMLoc E) {
2287226633Sdim    ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
2288226633Sdim    Op->PostIdxReg.RegNum = RegNum;
2289226633Sdim    Op->PostIdxReg.isAdd = isAdd;
2290226633Sdim    Op->PostIdxReg.ShiftTy = ShiftTy;
2291226633Sdim    Op->PostIdxReg.ShiftImm = ShiftImm;
2292206124Srdivacky    Op->StartLoc = S;
2293206124Srdivacky    Op->EndLoc = E;
2294218893Sdim    return Op;
2295198090Srdivacky  }
2296218893Sdim
2297218893Sdim  static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
2298226633Sdim    ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
2299218893Sdim    Op->MBOpt.Val = Opt;
2300218893Sdim    Op->StartLoc = S;
2301218893Sdim    Op->EndLoc = S;
2302218893Sdim    return Op;
2303218893Sdim  }
2304218893Sdim
2305218893Sdim  static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
2306226633Sdim    ARMOperand *Op = new ARMOperand(k_ProcIFlags);
2307218893Sdim    Op->IFlags.Val = IFlags;
2308218893Sdim    Op->StartLoc = S;
2309218893Sdim    Op->EndLoc = S;
2310218893Sdim    return Op;
2311218893Sdim  }
2312218893Sdim
2313218893Sdim  static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
2314226633Sdim    ARMOperand *Op = new ARMOperand(k_MSRMask);
2315218893Sdim    Op->MMask.Val = MMask;
2316218893Sdim    Op->StartLoc = S;
2317218893Sdim    Op->EndLoc = S;
2318218893Sdim    return Op;
2319218893Sdim  }
2320198090Srdivacky};
2321198090Srdivacky
2322198090Srdivacky} // end anonymous namespace.
2323198090Srdivacky
2324224145Sdimvoid ARMOperand::print(raw_ostream &OS) const {
2325212904Sdim  switch (Kind) {
2326226633Sdim  case k_CondCode:
2327218893Sdim    OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
2328212904Sdim    break;
2329226633Sdim  case k_CCOut:
2330218893Sdim    OS << "<ccout " << getReg() << ">";
2331218893Sdim    break;
2332226633Sdim  case k_ITCondMask: {
2333239462Sdim    static const char *const MaskStr[] = {
2334234353Sdim      "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2335234353Sdim      "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2336234353Sdim    };
2337226633Sdim    assert((ITMask.Mask & 0xf) == ITMask.Mask);
2338226633Sdim    OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2339226633Sdim    break;
2340226633Sdim  }
2341226633Sdim  case k_CoprocNum:
2342218893Sdim    OS << "<coprocessor number: " << getCoproc() << ">";
2343218893Sdim    break;
2344226633Sdim  case k_CoprocReg:
2345218893Sdim    OS << "<coprocessor register: " << getCoproc() << ">";
2346218893Sdim    break;
2347226633Sdim  case k_CoprocOption:
2348226633Sdim    OS << "<coprocessor option: " << CoprocOption.Val << ">";
2349226633Sdim    break;
2350226633Sdim  case k_MSRMask:
2351218893Sdim    OS << "<mask: " << getMSRMask() << ">";
2352218893Sdim    break;
2353226633Sdim  case k_Immediate:
2354212904Sdim    getImm()->print(OS);
2355212904Sdim    break;
2356226633Sdim  case k_MemBarrierOpt:
2357218893Sdim    OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2358218893Sdim    break;
2359226633Sdim  case k_Memory:
2360218893Sdim    OS << "<memory "
2361226633Sdim       << " base:" << Memory.BaseRegNum;
2362218893Sdim    OS << ">";
2363212904Sdim    break;
2364226633Sdim  case k_PostIndexRegister:
2365226633Sdim    OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2366226633Sdim       << PostIdxReg.RegNum;
2367226633Sdim    if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2368226633Sdim      OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2369226633Sdim         << PostIdxReg.ShiftImm;
2370226633Sdim    OS << ">";
2371226633Sdim    break;
2372226633Sdim  case k_ProcIFlags: {
2373218893Sdim    OS << "<ARM_PROC::";
2374218893Sdim    unsigned IFlags = getProcIFlags();
2375218893Sdim    for (int i=2; i >= 0; --i)
2376218893Sdim      if (IFlags & (1 << i))
2377218893Sdim        OS << ARM_PROC::IFlagsToString(1 << i);
2378218893Sdim    OS << ">";
2379218893Sdim    break;
2380218893Sdim  }
2381226633Sdim  case k_Register:
2382212904Sdim    OS << "<register " << getReg() << ">";
2383212904Sdim    break;
2384226633Sdim  case k_ShifterImmediate:
2385226633Sdim    OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2386226633Sdim       << " #" << ShifterImm.Imm << ">";
2387221345Sdim    break;
2388226633Sdim  case k_ShiftedRegister:
2389226633Sdim    OS << "<so_reg_reg "
2390234353Sdim       << RegShiftedReg.SrcReg << " "
2391234353Sdim       << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2392234353Sdim       << " " << RegShiftedReg.ShiftReg << ">";
2393224145Sdim    break;
2394226633Sdim  case k_ShiftedImmediate:
2395226633Sdim    OS << "<so_reg_imm "
2396234353Sdim       << RegShiftedImm.SrcReg << " "
2397234353Sdim       << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2398234353Sdim       << " #" << RegShiftedImm.ShiftImm << ">";
2399226633Sdim    break;
2400226633Sdim  case k_RotateImmediate:
2401226633Sdim    OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2402226633Sdim    break;
2403226633Sdim  case k_BitfieldDescriptor:
2404226633Sdim    OS << "<bitfield " << "lsb: " << Bitfield.LSB
2405226633Sdim       << ", width: " << Bitfield.Width << ">";
2406226633Sdim    break;
2407226633Sdim  case k_RegisterList:
2408226633Sdim  case k_DPRRegisterList:
2409226633Sdim  case k_SPRRegisterList: {
2410218893Sdim    OS << "<register_list ";
2411218893Sdim
2412218893Sdim    const SmallVectorImpl<unsigned> &RegList = getRegList();
2413218893Sdim    for (SmallVectorImpl<unsigned>::const_iterator
2414218893Sdim           I = RegList.begin(), E = RegList.end(); I != E; ) {
2415218893Sdim      OS << *I;
2416218893Sdim      if (++I < E) OS << ", ";
2417218893Sdim    }
2418218893Sdim
2419218893Sdim    OS << ">";
2420218893Sdim    break;
2421218893Sdim  }
2422234353Sdim  case k_VectorList:
2423234353Sdim    OS << "<vector_list " << VectorList.Count << " * "
2424234353Sdim       << VectorList.RegNum << ">";
2425234353Sdim    break;
2426234353Sdim  case k_VectorListAllLanes:
2427234353Sdim    OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2428234353Sdim       << VectorList.RegNum << ">";
2429234353Sdim    break;
2430234353Sdim  case k_VectorListIndexed:
2431234353Sdim    OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2432234353Sdim       << VectorList.Count << " * " << VectorList.RegNum << ">";
2433234353Sdim    break;
2434226633Sdim  case k_Token:
2435212904Sdim    OS << "'" << getToken() << "'";
2436212904Sdim    break;
2437226633Sdim  case k_VectorIndex:
2438226633Sdim    OS << "<vectorindex " << getVectorIndex() << ">";
2439226633Sdim    break;
2440212904Sdim  }
2441212904Sdim}
2442212904Sdim
2443212904Sdim/// @name Auto-generated Match Functions
2444212904Sdim/// {
2445212904Sdim
2446212904Sdimstatic unsigned MatchRegisterName(StringRef Name);
2447212904Sdim
2448212904Sdim/// }
2449212904Sdim
2450218893Sdimbool ARMAsmParser::ParseRegister(unsigned &RegNo,
2451218893Sdim                                 SMLoc &StartLoc, SMLoc &EndLoc) {
2452234353Sdim  StartLoc = Parser.getTok().getLoc();
2453226633Sdim  RegNo = tryParseRegister();
2454234353Sdim  EndLoc = Parser.getTok().getLoc();
2455218893Sdim
2456218893Sdim  return (RegNo == (unsigned)-1);
2457218893Sdim}
2458218893Sdim
2459198892Srdivacky/// Try to parse a register name.  The token must be an Identifier when called,
2460218893Sdim/// and if it is a register name the token is eaten and the register number is
2461218893Sdim/// returned.  Otherwise return -1.
2462218893Sdim///
2463226633Sdimint ARMAsmParser::tryParseRegister() {
2464202878Srdivacky  const AsmToken &Tok = Parser.getTok();
2465226633Sdim  if (Tok.isNot(AsmToken::Identifier)) return -1;
2466198090Srdivacky
2467234353Sdim  std::string lowerCase = Tok.getString().lower();
2468218893Sdim  unsigned RegNum = MatchRegisterName(lowerCase);
2469218893Sdim  if (!RegNum) {
2470218893Sdim    RegNum = StringSwitch<unsigned>(lowerCase)
2471218893Sdim      .Case("r13", ARM::SP)
2472218893Sdim      .Case("r14", ARM::LR)
2473218893Sdim      .Case("r15", ARM::PC)
2474218893Sdim      .Case("ip", ARM::R12)
2475234353Sdim      // Additional register name aliases for 'gas' compatibility.
2476234353Sdim      .Case("a1", ARM::R0)
2477234353Sdim      .Case("a2", ARM::R1)
2478234353Sdim      .Case("a3", ARM::R2)
2479234353Sdim      .Case("a4", ARM::R3)
2480234353Sdim      .Case("v1", ARM::R4)
2481234353Sdim      .Case("v2", ARM::R5)
2482234353Sdim      .Case("v3", ARM::R6)
2483234353Sdim      .Case("v4", ARM::R7)
2484234353Sdim      .Case("v5", ARM::R8)
2485234353Sdim      .Case("v6", ARM::R9)
2486234353Sdim      .Case("v7", ARM::R10)
2487234353Sdim      .Case("v8", ARM::R11)
2488234353Sdim      .Case("sb", ARM::R9)
2489234353Sdim      .Case("sl", ARM::R10)
2490234353Sdim      .Case("fp", ARM::R11)
2491218893Sdim      .Default(0);
2492218893Sdim  }
2493234353Sdim  if (!RegNum) {
2494234353Sdim    // Check for aliases registered via .req. Canonicalize to lower case.
2495234353Sdim    // That's more consistent since register names are case insensitive, and
2496234353Sdim    // it's how the original entry was passed in from MC/MCParser/AsmParser.
2497234353Sdim    StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
2498234353Sdim    // If no match, return failure.
2499234353Sdim    if (Entry == RegisterReqs.end())
2500234353Sdim      return -1;
2501234353Sdim    Parser.Lex(); // Eat identifier token.
2502234353Sdim    return Entry->getValue();
2503234353Sdim  }
2504198090Srdivacky
2505202878Srdivacky  Parser.Lex(); // Eat identifier token.
2506226633Sdim
2507218893Sdim  return RegNum;
2508218893Sdim}
2509198090Srdivacky
2510224145Sdim// Try to parse a shifter  (e.g., "lsl <amt>"). On success, return 0.
2511224145Sdim// If a recoverable error occurs, return 1. If an irrecoverable error
2512224145Sdim// occurs, return -1. An irrecoverable error is one where tokens have been
2513224145Sdim// consumed in the process of trying to parse the shifter (i.e., when it is
2514224145Sdim// indeed a shifter operand, but malformed).
2515226633Sdimint ARMAsmParser::tryParseShiftRegister(
2516221345Sdim                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2517221345Sdim  SMLoc S = Parser.getTok().getLoc();
2518221345Sdim  const AsmToken &Tok = Parser.getTok();
2519221345Sdim  assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2520221345Sdim
2521234353Sdim  std::string lowerCase = Tok.getString().lower();
2522221345Sdim  ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
2523234353Sdim      .Case("asl", ARM_AM::lsl)
2524221345Sdim      .Case("lsl", ARM_AM::lsl)
2525221345Sdim      .Case("lsr", ARM_AM::lsr)
2526221345Sdim      .Case("asr", ARM_AM::asr)
2527221345Sdim      .Case("ror", ARM_AM::ror)
2528221345Sdim      .Case("rrx", ARM_AM::rrx)
2529221345Sdim      .Default(ARM_AM::no_shift);
2530221345Sdim
2531221345Sdim  if (ShiftTy == ARM_AM::no_shift)
2532224145Sdim    return 1;
2533221345Sdim
2534224145Sdim  Parser.Lex(); // Eat the operator.
2535221345Sdim
2536224145Sdim  // The source register for the shift has already been added to the
2537224145Sdim  // operand list, so we need to pop it off and combine it into the shifted
2538224145Sdim  // register operand instead.
2539224145Sdim  OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
2540224145Sdim  if (!PrevOp->isReg())
2541224145Sdim    return Error(PrevOp->getStartLoc(), "shift must be of a register");
2542224145Sdim  int SrcReg = PrevOp->getReg();
2543224145Sdim  int64_t Imm = 0;
2544224145Sdim  int ShiftReg = 0;
2545224145Sdim  if (ShiftTy == ARM_AM::rrx) {
2546224145Sdim    // RRX Doesn't have an explicit shift amount. The encoder expects
2547224145Sdim    // the shift register to be the same as the source register. Seems odd,
2548224145Sdim    // but OK.
2549224145Sdim    ShiftReg = SrcReg;
2550224145Sdim  } else {
2551224145Sdim    // Figure out if this is shifted by a constant or a register (for non-RRX).
2552234353Sdim    if (Parser.getTok().is(AsmToken::Hash) ||
2553234353Sdim        Parser.getTok().is(AsmToken::Dollar)) {
2554224145Sdim      Parser.Lex(); // Eat hash.
2555224145Sdim      SMLoc ImmLoc = Parser.getTok().getLoc();
2556224145Sdim      const MCExpr *ShiftExpr = 0;
2557224145Sdim      if (getParser().ParseExpression(ShiftExpr)) {
2558224145Sdim        Error(ImmLoc, "invalid immediate shift value");
2559224145Sdim        return -1;
2560224145Sdim      }
2561224145Sdim      // The expression must be evaluatable as an immediate.
2562224145Sdim      const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
2563224145Sdim      if (!CE) {
2564224145Sdim        Error(ImmLoc, "invalid immediate shift value");
2565224145Sdim        return -1;
2566224145Sdim      }
2567224145Sdim      // Range check the immediate.
2568224145Sdim      // lsl, ror: 0 <= imm <= 31
2569224145Sdim      // lsr, asr: 0 <= imm <= 32
2570224145Sdim      Imm = CE->getValue();
2571224145Sdim      if (Imm < 0 ||
2572224145Sdim          ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2573224145Sdim          ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
2574224145Sdim        Error(ImmLoc, "immediate shift value out of range");
2575224145Sdim        return -1;
2576224145Sdim      }
2577234353Sdim      // shift by zero is a nop. Always send it through as lsl.
2578234353Sdim      // ('as' compatibility)
2579234353Sdim      if (Imm == 0)
2580234353Sdim        ShiftTy = ARM_AM::lsl;
2581224145Sdim    } else if (Parser.getTok().is(AsmToken::Identifier)) {
2582226633Sdim      ShiftReg = tryParseRegister();
2583224145Sdim      SMLoc L = Parser.getTok().getLoc();
2584224145Sdim      if (ShiftReg == -1) {
2585224145Sdim        Error (L, "expected immediate or register in shift operand");
2586224145Sdim        return -1;
2587224145Sdim      }
2588224145Sdim    } else {
2589224145Sdim      Error (Parser.getTok().getLoc(),
2590224145Sdim                    "expected immediate or register in shift operand");
2591224145Sdim      return -1;
2592224145Sdim    }
2593224145Sdim  }
2594224145Sdim
2595226633Sdim  if (ShiftReg && ShiftTy != ARM_AM::rrx)
2596226633Sdim    Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
2597226633Sdim                                                         ShiftReg, Imm,
2598221345Sdim                                               S, Parser.getTok().getLoc()));
2599226633Sdim  else
2600226633Sdim    Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2601226633Sdim                                               S, Parser.getTok().getLoc()));
2602221345Sdim
2603224145Sdim  return 0;
2604221345Sdim}
2605221345Sdim
2606221345Sdim
2607218893Sdim/// Try to parse a register name.  The token must be an Identifier when called.
2608218893Sdim/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2609218893Sdim/// if there is a "writeback". 'true' if it's not a register.
2610218893Sdim///
2611218893Sdim/// TODO this is likely to change to allow different register types and or to
2612218893Sdim/// parse for a specific register type.
2613218893Sdimbool ARMAsmParser::
2614226633SdimtryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2615218893Sdim  SMLoc S = Parser.getTok().getLoc();
2616226633Sdim  int RegNo = tryParseRegister();
2617218893Sdim  if (RegNo == -1)
2618218893Sdim    return true;
2619218893Sdim
2620218893Sdim  Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
2621218893Sdim
2622218893Sdim  const AsmToken &ExclaimTok = Parser.getTok();
2623218893Sdim  if (ExclaimTok.is(AsmToken::Exclaim)) {
2624218893Sdim    Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2625218893Sdim                                               ExclaimTok.getLoc()));
2626218893Sdim    Parser.Lex(); // Eat exclaim token
2627226633Sdim    return false;
2628218893Sdim  }
2629218893Sdim
2630226633Sdim  // Also check for an index operand. This is only legal for vector registers,
2631226633Sdim  // but that'll get caught OK in operand matching, so we don't need to
2632226633Sdim  // explicitly filter everything else out here.
2633226633Sdim  if (Parser.getTok().is(AsmToken::LBrac)) {
2634226633Sdim    SMLoc SIdx = Parser.getTok().getLoc();
2635226633Sdim    Parser.Lex(); // Eat left bracket token.
2636226633Sdim
2637226633Sdim    const MCExpr *ImmVal;
2638226633Sdim    if (getParser().ParseExpression(ImmVal))
2639234353Sdim      return true;
2640226633Sdim    const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2641234353Sdim    if (!MCE)
2642234353Sdim      return TokError("immediate value expected for vector index");
2643226633Sdim
2644226633Sdim    SMLoc E = Parser.getTok().getLoc();
2645234353Sdim    if (Parser.getTok().isNot(AsmToken::RBrac))
2646234353Sdim      return Error(E, "']' expected");
2647226633Sdim
2648226633Sdim    Parser.Lex(); // Eat right bracket token.
2649226633Sdim
2650226633Sdim    Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2651226633Sdim                                                     SIdx, E,
2652226633Sdim                                                     getContext()));
2653226633Sdim  }
2654226633Sdim
2655218893Sdim  return false;
2656218893Sdim}
2657218893Sdim
2658218893Sdim/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2659218893Sdim/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2660218893Sdim/// "c5", ...
2661218893Sdimstatic int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
2662218893Sdim  // Use the same layout as the tablegen'erated register name matcher. Ugly,
2663218893Sdim  // but efficient.
2664218893Sdim  switch (Name.size()) {
2665234353Sdim  default: return -1;
2666218893Sdim  case 2:
2667218893Sdim    if (Name[0] != CoprocOp)
2668218893Sdim      return -1;
2669218893Sdim    switch (Name[1]) {
2670218893Sdim    default:  return -1;
2671218893Sdim    case '0': return 0;
2672218893Sdim    case '1': return 1;
2673218893Sdim    case '2': return 2;
2674218893Sdim    case '3': return 3;
2675218893Sdim    case '4': return 4;
2676218893Sdim    case '5': return 5;
2677218893Sdim    case '6': return 6;
2678218893Sdim    case '7': return 7;
2679218893Sdim    case '8': return 8;
2680218893Sdim    case '9': return 9;
2681198892Srdivacky    }
2682218893Sdim  case 3:
2683218893Sdim    if (Name[0] != CoprocOp || Name[1] != '1')
2684218893Sdim      return -1;
2685218893Sdim    switch (Name[2]) {
2686218893Sdim    default:  return -1;
2687218893Sdim    case '0': return 10;
2688218893Sdim    case '1': return 11;
2689218893Sdim    case '2': return 12;
2690218893Sdim    case '3': return 13;
2691218893Sdim    case '4': return 14;
2692218893Sdim    case '5': return 15;
2693218893Sdim    }
2694198090Srdivacky  }
2695218893Sdim}
2696198090Srdivacky
2697226633Sdim/// parseITCondCode - Try to parse a condition code for an IT instruction.
2698226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
2699226633SdimparseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2700226633Sdim  SMLoc S = Parser.getTok().getLoc();
2701226633Sdim  const AsmToken &Tok = Parser.getTok();
2702226633Sdim  if (!Tok.is(AsmToken::Identifier))
2703226633Sdim    return MatchOperand_NoMatch;
2704239462Sdim  unsigned CC = StringSwitch<unsigned>(Tok.getString().lower())
2705226633Sdim    .Case("eq", ARMCC::EQ)
2706226633Sdim    .Case("ne", ARMCC::NE)
2707226633Sdim    .Case("hs", ARMCC::HS)
2708226633Sdim    .Case("cs", ARMCC::HS)
2709226633Sdim    .Case("lo", ARMCC::LO)
2710226633Sdim    .Case("cc", ARMCC::LO)
2711226633Sdim    .Case("mi", ARMCC::MI)
2712226633Sdim    .Case("pl", ARMCC::PL)
2713226633Sdim    .Case("vs", ARMCC::VS)
2714226633Sdim    .Case("vc", ARMCC::VC)
2715226633Sdim    .Case("hi", ARMCC::HI)
2716226633Sdim    .Case("ls", ARMCC::LS)
2717226633Sdim    .Case("ge", ARMCC::GE)
2718226633Sdim    .Case("lt", ARMCC::LT)
2719226633Sdim    .Case("gt", ARMCC::GT)
2720226633Sdim    .Case("le", ARMCC::LE)
2721226633Sdim    .Case("al", ARMCC::AL)
2722226633Sdim    .Default(~0U);
2723226633Sdim  if (CC == ~0U)
2724226633Sdim    return MatchOperand_NoMatch;
2725226633Sdim  Parser.Lex(); // Eat the token.
2726226633Sdim
2727226633Sdim  Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2728226633Sdim
2729226633Sdim  return MatchOperand_Success;
2730226633Sdim}
2731226633Sdim
2732226633Sdim/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
2733218893Sdim/// token must be an Identifier when called, and if it is a coprocessor
2734218893Sdim/// number, the token is eaten and the operand is added to the operand list.
2735218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
2736226633SdimparseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2737218893Sdim  SMLoc S = Parser.getTok().getLoc();
2738218893Sdim  const AsmToken &Tok = Parser.getTok();
2739226633Sdim  if (Tok.isNot(AsmToken::Identifier))
2740226633Sdim    return MatchOperand_NoMatch;
2741218893Sdim
2742218893Sdim  int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
2743218893Sdim  if (Num == -1)
2744218893Sdim    return MatchOperand_NoMatch;
2745218893Sdim
2746218893Sdim  Parser.Lex(); // Eat identifier token.
2747218893Sdim  Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
2748218893Sdim  return MatchOperand_Success;
2749198090Srdivacky}
2750198090Srdivacky
2751226633Sdim/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
2752218893Sdim/// token must be an Identifier when called, and if it is a coprocessor
2753218893Sdim/// number, the token is eaten and the operand is added to the operand list.
2754218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
2755226633SdimparseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2756218893Sdim  SMLoc S = Parser.getTok().getLoc();
2757218893Sdim  const AsmToken &Tok = Parser.getTok();
2758226633Sdim  if (Tok.isNot(AsmToken::Identifier))
2759226633Sdim    return MatchOperand_NoMatch;
2760198090Srdivacky
2761218893Sdim  int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2762218893Sdim  if (Reg == -1)
2763218893Sdim    return MatchOperand_NoMatch;
2764218893Sdim
2765202878Srdivacky  Parser.Lex(); // Eat identifier token.
2766218893Sdim  Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
2767218893Sdim  return MatchOperand_Success;
2768218893Sdim}
2769198090Srdivacky
2770226633Sdim/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2771226633Sdim/// coproc_option : '{' imm0_255 '}'
2772226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
2773226633SdimparseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2774218893Sdim  SMLoc S = Parser.getTok().getLoc();
2775198090Srdivacky
2776226633Sdim  // If this isn't a '{', this isn't a coprocessor immediate operand.
2777226633Sdim  if (Parser.getTok().isNot(AsmToken::LCurly))
2778226633Sdim    return MatchOperand_NoMatch;
2779226633Sdim  Parser.Lex(); // Eat the '{'
2780218893Sdim
2781226633Sdim  const MCExpr *Expr;
2782226633Sdim  SMLoc Loc = Parser.getTok().getLoc();
2783226633Sdim  if (getParser().ParseExpression(Expr)) {
2784226633Sdim    Error(Loc, "illegal expression");
2785226633Sdim    return MatchOperand_ParseFail;
2786226633Sdim  }
2787226633Sdim  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2788226633Sdim  if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2789226633Sdim    Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2790226633Sdim    return MatchOperand_ParseFail;
2791226633Sdim  }
2792226633Sdim  int Val = CE->getValue();
2793218893Sdim
2794226633Sdim  // Check for and consume the closing '}'
2795226633Sdim  if (Parser.getTok().isNot(AsmToken::RCurly))
2796226633Sdim    return MatchOperand_ParseFail;
2797226633Sdim  SMLoc E = Parser.getTok().getLoc();
2798226633Sdim  Parser.Lex(); // Eat the '}'
2799198090Srdivacky
2800226633Sdim  Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2801226633Sdim  return MatchOperand_Success;
2802226633Sdim}
2803198090Srdivacky
2804226633Sdim// For register list parsing, we need to map from raw GPR register numbering
2805226633Sdim// to the enumeration values. The enumeration values aren't sorted by
2806226633Sdim// register number due to our using "sp", "lr" and "pc" as canonical names.
2807226633Sdimstatic unsigned getNextRegister(unsigned Reg) {
2808226633Sdim  // If this is a GPR, we need to do it manually, otherwise we can rely
2809226633Sdim  // on the sort ordering of the enumeration since the other reg-classes
2810226633Sdim  // are sane.
2811226633Sdim  if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2812226633Sdim    return Reg + 1;
2813226633Sdim  switch(Reg) {
2814234353Sdim  default: llvm_unreachable("Invalid GPR number!");
2815226633Sdim  case ARM::R0:  return ARM::R1;  case ARM::R1:  return ARM::R2;
2816226633Sdim  case ARM::R2:  return ARM::R3;  case ARM::R3:  return ARM::R4;
2817226633Sdim  case ARM::R4:  return ARM::R5;  case ARM::R5:  return ARM::R6;
2818226633Sdim  case ARM::R6:  return ARM::R7;  case ARM::R7:  return ARM::R8;
2819226633Sdim  case ARM::R8:  return ARM::R9;  case ARM::R9:  return ARM::R10;
2820226633Sdim  case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2821226633Sdim  case ARM::R12: return ARM::SP;  case ARM::SP:  return ARM::LR;
2822226633Sdim  case ARM::LR:  return ARM::PC;  case ARM::PC:  return ARM::R0;
2823198090Srdivacky  }
2824226633Sdim}
2825198090Srdivacky
2826234353Sdim// Return the low-subreg of a given Q register.
2827234353Sdimstatic unsigned getDRegFromQReg(unsigned QReg) {
2828234353Sdim  switch (QReg) {
2829234353Sdim  default: llvm_unreachable("expected a Q register!");
2830234353Sdim  case ARM::Q0:  return ARM::D0;
2831234353Sdim  case ARM::Q1:  return ARM::D2;
2832234353Sdim  case ARM::Q2:  return ARM::D4;
2833234353Sdim  case ARM::Q3:  return ARM::D6;
2834234353Sdim  case ARM::Q4:  return ARM::D8;
2835234353Sdim  case ARM::Q5:  return ARM::D10;
2836234353Sdim  case ARM::Q6:  return ARM::D12;
2837234353Sdim  case ARM::Q7:  return ARM::D14;
2838234353Sdim  case ARM::Q8:  return ARM::D16;
2839234353Sdim  case ARM::Q9:  return ARM::D18;
2840234353Sdim  case ARM::Q10: return ARM::D20;
2841234353Sdim  case ARM::Q11: return ARM::D22;
2842234353Sdim  case ARM::Q12: return ARM::D24;
2843234353Sdim  case ARM::Q13: return ARM::D26;
2844234353Sdim  case ARM::Q14: return ARM::D28;
2845234353Sdim  case ARM::Q15: return ARM::D30;
2846234353Sdim  }
2847234353Sdim}
2848234353Sdim
2849226633Sdim/// Parse a register list.
2850226633Sdimbool ARMAsmParser::
2851226633SdimparseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2852226633Sdim  assert(Parser.getTok().is(AsmToken::LCurly) &&
2853226633Sdim         "Token is not a Left Curly Brace");
2854226633Sdim  SMLoc S = Parser.getTok().getLoc();
2855226633Sdim  Parser.Lex(); // Eat '{' token.
2856226633Sdim  SMLoc RegLoc = Parser.getTok().getLoc();
2857218893Sdim
2858226633Sdim  // Check the first register in the list to see what register class
2859226633Sdim  // this is a list of.
2860226633Sdim  int Reg = tryParseRegister();
2861226633Sdim  if (Reg == -1)
2862226633Sdim    return Error(RegLoc, "register expected");
2863218893Sdim
2864234353Sdim  // The reglist instructions have at most 16 registers, so reserve
2865234353Sdim  // space for that many.
2866234353Sdim  SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2867234353Sdim
2868234353Sdim  // Allow Q regs and just interpret them as the two D sub-registers.
2869234353Sdim  if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2870234353Sdim    Reg = getDRegFromQReg(Reg);
2871234353Sdim    Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2872234353Sdim    ++Reg;
2873234353Sdim  }
2874234353Sdim  const MCRegisterClass *RC;
2875226633Sdim  if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2876226633Sdim    RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2877226633Sdim  else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2878226633Sdim    RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2879226633Sdim  else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2880226633Sdim    RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2881226633Sdim  else
2882226633Sdim    return Error(RegLoc, "invalid register in register list");
2883218893Sdim
2884234353Sdim  // Store the register.
2885226633Sdim  Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2886218893Sdim
2887226633Sdim  // This starts immediately after the first register token in the list,
2888226633Sdim  // so we can see either a comma or a minus (range separator) as a legal
2889226633Sdim  // next token.
2890226633Sdim  while (Parser.getTok().is(AsmToken::Comma) ||
2891226633Sdim         Parser.getTok().is(AsmToken::Minus)) {
2892226633Sdim    if (Parser.getTok().is(AsmToken::Minus)) {
2893234353Sdim      Parser.Lex(); // Eat the minus.
2894226633Sdim      SMLoc EndLoc = Parser.getTok().getLoc();
2895226633Sdim      int EndReg = tryParseRegister();
2896226633Sdim      if (EndReg == -1)
2897226633Sdim        return Error(EndLoc, "register expected");
2898234353Sdim      // Allow Q regs and just interpret them as the two D sub-registers.
2899234353Sdim      if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2900234353Sdim        EndReg = getDRegFromQReg(EndReg) + 1;
2901226633Sdim      // If the register is the same as the start reg, there's nothing
2902226633Sdim      // more to do.
2903226633Sdim      if (Reg == EndReg)
2904226633Sdim        continue;
2905226633Sdim      // The register must be in the same register class as the first.
2906226633Sdim      if (!RC->contains(EndReg))
2907226633Sdim        return Error(EndLoc, "invalid register in register list");
2908226633Sdim      // Ranges must go from low to high.
2909239462Sdim      if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg))
2910226633Sdim        return Error(EndLoc, "bad range in register list");
2911218893Sdim
2912226633Sdim      // Add all the registers in the range to the register list.
2913226633Sdim      while (Reg != EndReg) {
2914226633Sdim        Reg = getNextRegister(Reg);
2915226633Sdim        Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2916226633Sdim      }
2917226633Sdim      continue;
2918218893Sdim    }
2919226633Sdim    Parser.Lex(); // Eat the comma.
2920226633Sdim    RegLoc = Parser.getTok().getLoc();
2921226633Sdim    int OldReg = Reg;
2922234353Sdim    const AsmToken RegTok = Parser.getTok();
2923226633Sdim    Reg = tryParseRegister();
2924226633Sdim    if (Reg == -1)
2925226633Sdim      return Error(RegLoc, "register expected");
2926234353Sdim    // Allow Q regs and just interpret them as the two D sub-registers.
2927234353Sdim    bool isQReg = false;
2928234353Sdim    if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2929234353Sdim      Reg = getDRegFromQReg(Reg);
2930234353Sdim      isQReg = true;
2931234353Sdim    }
2932226633Sdim    // The register must be in the same register class as the first.
2933226633Sdim    if (!RC->contains(Reg))
2934226633Sdim      return Error(RegLoc, "invalid register in register list");
2935226633Sdim    // List must be monotonically increasing.
2936239462Sdim    if (MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) {
2937234353Sdim      if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2938234353Sdim        Warning(RegLoc, "register list not in ascending order");
2939234353Sdim      else
2940234353Sdim        return Error(RegLoc, "register list not in ascending order");
2941234353Sdim    }
2942239462Sdim    if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) {
2943234353Sdim      Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2944234353Sdim              ") in register list");
2945234353Sdim      continue;
2946234353Sdim    }
2947226633Sdim    // VFP register lists must also be contiguous.
2948226633Sdim    // It's OK to use the enumeration values directly here rather, as the
2949226633Sdim    // VFP register classes have the enum sorted properly.
2950226633Sdim    if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2951226633Sdim        Reg != OldReg + 1)
2952226633Sdim      return Error(RegLoc, "non-contiguous register range");
2953226633Sdim    Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2954234353Sdim    if (isQReg)
2955234353Sdim      Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
2956226633Sdim  }
2957218893Sdim
2958226633Sdim  SMLoc E = Parser.getTok().getLoc();
2959226633Sdim  if (Parser.getTok().isNot(AsmToken::RCurly))
2960226633Sdim    return Error(E, "'}' expected");
2961226633Sdim  Parser.Lex(); // Eat '}' token.
2962218893Sdim
2963234353Sdim  // Push the register list operand.
2964218893Sdim  Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
2965234353Sdim
2966234353Sdim  // The ARM system instruction variants for LDM/STM have a '^' token here.
2967234353Sdim  if (Parser.getTok().is(AsmToken::Caret)) {
2968234353Sdim    Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2969234353Sdim    Parser.Lex(); // Eat '^' token.
2970234353Sdim  }
2971234353Sdim
2972198090Srdivacky  return false;
2973198090Srdivacky}
2974198090Srdivacky
2975234353Sdim// Helper function to parse the lane index for vector lists.
2976234353SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
2977234353SdimparseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2978234353Sdim  Index = 0; // Always return a defined index value.
2979234353Sdim  if (Parser.getTok().is(AsmToken::LBrac)) {
2980234353Sdim    Parser.Lex(); // Eat the '['.
2981234353Sdim    if (Parser.getTok().is(AsmToken::RBrac)) {
2982234353Sdim      // "Dn[]" is the 'all lanes' syntax.
2983234353Sdim      LaneKind = AllLanes;
2984234353Sdim      Parser.Lex(); // Eat the ']'.
2985234353Sdim      return MatchOperand_Success;
2986234353Sdim    }
2987234353Sdim
2988234353Sdim    // There's an optional '#' token here. Normally there wouldn't be, but
2989234353Sdim    // inline assemble puts one in, and it's friendly to accept that.
2990234353Sdim    if (Parser.getTok().is(AsmToken::Hash))
2991234353Sdim      Parser.Lex(); // Eat the '#'
2992234353Sdim
2993234353Sdim    const MCExpr *LaneIndex;
2994234353Sdim    SMLoc Loc = Parser.getTok().getLoc();
2995234353Sdim    if (getParser().ParseExpression(LaneIndex)) {
2996234353Sdim      Error(Loc, "illegal expression");
2997234353Sdim      return MatchOperand_ParseFail;
2998234353Sdim    }
2999234353Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
3000234353Sdim    if (!CE) {
3001234353Sdim      Error(Loc, "lane index must be empty or an integer");
3002234353Sdim      return MatchOperand_ParseFail;
3003234353Sdim    }
3004234353Sdim    if (Parser.getTok().isNot(AsmToken::RBrac)) {
3005234353Sdim      Error(Parser.getTok().getLoc(), "']' expected");
3006234353Sdim      return MatchOperand_ParseFail;
3007234353Sdim    }
3008234353Sdim    Parser.Lex(); // Eat the ']'.
3009234353Sdim    int64_t Val = CE->getValue();
3010234353Sdim
3011234353Sdim    // FIXME: Make this range check context sensitive for .8, .16, .32.
3012234353Sdim    if (Val < 0 || Val > 7) {
3013234353Sdim      Error(Parser.getTok().getLoc(), "lane index out of range");
3014234353Sdim      return MatchOperand_ParseFail;
3015234353Sdim    }
3016234353Sdim    Index = Val;
3017234353Sdim    LaneKind = IndexedLane;
3018234353Sdim    return MatchOperand_Success;
3019234353Sdim  }
3020234353Sdim  LaneKind = NoLanes;
3021234353Sdim  return MatchOperand_Success;
3022234353Sdim}
3023234353Sdim
3024234353Sdim// parse a vector register list
3025234353SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3026234353SdimparseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3027234353Sdim  VectorLaneTy LaneKind;
3028234353Sdim  unsigned LaneIndex;
3029234353Sdim  SMLoc S = Parser.getTok().getLoc();
3030234353Sdim  // As an extension (to match gas), support a plain D register or Q register
3031234353Sdim  // (without encosing curly braces) as a single or double entry list,
3032234353Sdim  // respectively.
3033234353Sdim  if (Parser.getTok().is(AsmToken::Identifier)) {
3034234353Sdim    int Reg = tryParseRegister();
3035234353Sdim    if (Reg == -1)
3036234353Sdim      return MatchOperand_NoMatch;
3037234353Sdim    SMLoc E = Parser.getTok().getLoc();
3038234353Sdim    if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
3039234353Sdim      OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
3040234353Sdim      if (Res != MatchOperand_Success)
3041234353Sdim        return Res;
3042234353Sdim      switch (LaneKind) {
3043234353Sdim      case NoLanes:
3044234353Sdim        E = Parser.getTok().getLoc();
3045234353Sdim        Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
3046234353Sdim        break;
3047234353Sdim      case AllLanes:
3048234353Sdim        E = Parser.getTok().getLoc();
3049234353Sdim        Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3050234353Sdim                                                                S, E));
3051234353Sdim        break;
3052234353Sdim      case IndexedLane:
3053234353Sdim        Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
3054234353Sdim                                                               LaneIndex,
3055234353Sdim                                                               false, S, E));
3056234353Sdim        break;
3057234353Sdim      }
3058234353Sdim      return MatchOperand_Success;
3059234353Sdim    }
3060234353Sdim    if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3061234353Sdim      Reg = getDRegFromQReg(Reg);
3062234353Sdim      OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
3063234353Sdim      if (Res != MatchOperand_Success)
3064234353Sdim        return Res;
3065234353Sdim      switch (LaneKind) {
3066234353Sdim      case NoLanes:
3067234353Sdim        E = Parser.getTok().getLoc();
3068234353Sdim        Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3069234353Sdim                                   &ARMMCRegisterClasses[ARM::DPairRegClassID]);
3070234353Sdim        Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
3071234353Sdim        break;
3072234353Sdim      case AllLanes:
3073234353Sdim        E = Parser.getTok().getLoc();
3074234353Sdim        Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3075234353Sdim                                   &ARMMCRegisterClasses[ARM::DPairRegClassID]);
3076234353Sdim        Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3077234353Sdim                                                                S, E));
3078234353Sdim        break;
3079234353Sdim      case IndexedLane:
3080234353Sdim        Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
3081234353Sdim                                                               LaneIndex,
3082234353Sdim                                                               false, S, E));
3083234353Sdim        break;
3084234353Sdim      }
3085234353Sdim      return MatchOperand_Success;
3086234353Sdim    }
3087234353Sdim    Error(S, "vector register expected");
3088234353Sdim    return MatchOperand_ParseFail;
3089234353Sdim  }
3090234353Sdim
3091234353Sdim  if (Parser.getTok().isNot(AsmToken::LCurly))
3092234353Sdim    return MatchOperand_NoMatch;
3093234353Sdim
3094234353Sdim  Parser.Lex(); // Eat '{' token.
3095234353Sdim  SMLoc RegLoc = Parser.getTok().getLoc();
3096234353Sdim
3097234353Sdim  int Reg = tryParseRegister();
3098234353Sdim  if (Reg == -1) {
3099234353Sdim    Error(RegLoc, "register expected");
3100234353Sdim    return MatchOperand_ParseFail;
3101234353Sdim  }
3102234353Sdim  unsigned Count = 1;
3103234353Sdim  int Spacing = 0;
3104234353Sdim  unsigned FirstReg = Reg;
3105234353Sdim  // The list is of D registers, but we also allow Q regs and just interpret
3106234353Sdim  // them as the two D sub-registers.
3107234353Sdim  if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3108234353Sdim    FirstReg = Reg = getDRegFromQReg(Reg);
3109234353Sdim    Spacing = 1; // double-spacing requires explicit D registers, otherwise
3110234353Sdim                 // it's ambiguous with four-register single spaced.
3111234353Sdim    ++Reg;
3112234353Sdim    ++Count;
3113234353Sdim  }
3114234353Sdim  if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
3115234353Sdim    return MatchOperand_ParseFail;
3116234353Sdim
3117234353Sdim  while (Parser.getTok().is(AsmToken::Comma) ||
3118234353Sdim         Parser.getTok().is(AsmToken::Minus)) {
3119234353Sdim    if (Parser.getTok().is(AsmToken::Minus)) {
3120234353Sdim      if (!Spacing)
3121234353Sdim        Spacing = 1; // Register range implies a single spaced list.
3122234353Sdim      else if (Spacing == 2) {
3123234353Sdim        Error(Parser.getTok().getLoc(),
3124234353Sdim              "sequential registers in double spaced list");
3125234353Sdim        return MatchOperand_ParseFail;
3126234353Sdim      }
3127234353Sdim      Parser.Lex(); // Eat the minus.
3128234353Sdim      SMLoc EndLoc = Parser.getTok().getLoc();
3129234353Sdim      int EndReg = tryParseRegister();
3130234353Sdim      if (EndReg == -1) {
3131234353Sdim        Error(EndLoc, "register expected");
3132234353Sdim        return MatchOperand_ParseFail;
3133234353Sdim      }
3134234353Sdim      // Allow Q regs and just interpret them as the two D sub-registers.
3135234353Sdim      if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3136234353Sdim        EndReg = getDRegFromQReg(EndReg) + 1;
3137234353Sdim      // If the register is the same as the start reg, there's nothing
3138234353Sdim      // more to do.
3139234353Sdim      if (Reg == EndReg)
3140234353Sdim        continue;
3141234353Sdim      // The register must be in the same register class as the first.
3142234353Sdim      if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3143234353Sdim        Error(EndLoc, "invalid register in register list");
3144234353Sdim        return MatchOperand_ParseFail;
3145234353Sdim      }
3146234353Sdim      // Ranges must go from low to high.
3147234353Sdim      if (Reg > EndReg) {
3148234353Sdim        Error(EndLoc, "bad range in register list");
3149234353Sdim        return MatchOperand_ParseFail;
3150234353Sdim      }
3151234353Sdim      // Parse the lane specifier if present.
3152234353Sdim      VectorLaneTy NextLaneKind;
3153234353Sdim      unsigned NextLaneIndex;
3154234353Sdim      if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
3155234353Sdim        return MatchOperand_ParseFail;
3156234353Sdim      if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
3157234353Sdim        Error(EndLoc, "mismatched lane index in register list");
3158234353Sdim        return MatchOperand_ParseFail;
3159234353Sdim      }
3160234353Sdim      EndLoc = Parser.getTok().getLoc();
3161234353Sdim
3162234353Sdim      // Add all the registers in the range to the register list.
3163234353Sdim      Count += EndReg - Reg;
3164234353Sdim      Reg = EndReg;
3165234353Sdim      continue;
3166234353Sdim    }
3167234353Sdim    Parser.Lex(); // Eat the comma.
3168234353Sdim    RegLoc = Parser.getTok().getLoc();
3169234353Sdim    int OldReg = Reg;
3170234353Sdim    Reg = tryParseRegister();
3171234353Sdim    if (Reg == -1) {
3172234353Sdim      Error(RegLoc, "register expected");
3173234353Sdim      return MatchOperand_ParseFail;
3174234353Sdim    }
3175234353Sdim    // vector register lists must be contiguous.
3176234353Sdim    // It's OK to use the enumeration values directly here rather, as the
3177234353Sdim    // VFP register classes have the enum sorted properly.
3178234353Sdim    //
3179234353Sdim    // The list is of D registers, but we also allow Q regs and just interpret
3180234353Sdim    // them as the two D sub-registers.
3181234353Sdim    if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3182234353Sdim      if (!Spacing)
3183234353Sdim        Spacing = 1; // Register range implies a single spaced list.
3184234353Sdim      else if (Spacing == 2) {
3185234353Sdim        Error(RegLoc,
3186234353Sdim              "invalid register in double-spaced list (must be 'D' register')");
3187234353Sdim        return MatchOperand_ParseFail;
3188234353Sdim      }
3189234353Sdim      Reg = getDRegFromQReg(Reg);
3190234353Sdim      if (Reg != OldReg + 1) {
3191234353Sdim        Error(RegLoc, "non-contiguous register range");
3192234353Sdim        return MatchOperand_ParseFail;
3193234353Sdim      }
3194234353Sdim      ++Reg;
3195234353Sdim      Count += 2;
3196234353Sdim      // Parse the lane specifier if present.
3197234353Sdim      VectorLaneTy NextLaneKind;
3198234353Sdim      unsigned NextLaneIndex;
3199234353Sdim      SMLoc EndLoc = Parser.getTok().getLoc();
3200234353Sdim      if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
3201234353Sdim        return MatchOperand_ParseFail;
3202234353Sdim      if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
3203234353Sdim        Error(EndLoc, "mismatched lane index in register list");
3204234353Sdim        return MatchOperand_ParseFail;
3205234353Sdim      }
3206234353Sdim      continue;
3207234353Sdim    }
3208234353Sdim    // Normal D register.
3209234353Sdim    // Figure out the register spacing (single or double) of the list if
3210234353Sdim    // we don't know it already.
3211234353Sdim    if (!Spacing)
3212234353Sdim      Spacing = 1 + (Reg == OldReg + 2);
3213234353Sdim
3214234353Sdim    // Just check that it's contiguous and keep going.
3215234353Sdim    if (Reg != OldReg + Spacing) {
3216234353Sdim      Error(RegLoc, "non-contiguous register range");
3217234353Sdim      return MatchOperand_ParseFail;
3218234353Sdim    }
3219234353Sdim    ++Count;
3220234353Sdim    // Parse the lane specifier if present.
3221234353Sdim    VectorLaneTy NextLaneKind;
3222234353Sdim    unsigned NextLaneIndex;
3223234353Sdim    SMLoc EndLoc = Parser.getTok().getLoc();
3224234353Sdim    if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
3225234353Sdim      return MatchOperand_ParseFail;
3226234353Sdim    if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
3227234353Sdim      Error(EndLoc, "mismatched lane index in register list");
3228234353Sdim      return MatchOperand_ParseFail;
3229234353Sdim    }
3230234353Sdim  }
3231234353Sdim
3232234353Sdim  SMLoc E = Parser.getTok().getLoc();
3233234353Sdim  if (Parser.getTok().isNot(AsmToken::RCurly)) {
3234234353Sdim    Error(E, "'}' expected");
3235234353Sdim    return MatchOperand_ParseFail;
3236234353Sdim  }
3237234353Sdim  Parser.Lex(); // Eat '}' token.
3238234353Sdim
3239234353Sdim  switch (LaneKind) {
3240234353Sdim  case NoLanes:
3241234353Sdim    // Two-register operands have been converted to the
3242234353Sdim    // composite register classes.
3243234353Sdim    if (Count == 2) {
3244234353Sdim      const MCRegisterClass *RC = (Spacing == 1) ?
3245234353Sdim        &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3246234353Sdim        &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3247234353Sdim      FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3248234353Sdim    }
3249234353Sdim
3250234353Sdim    Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3251234353Sdim                                                    (Spacing == 2), S, E));
3252234353Sdim    break;
3253234353Sdim  case AllLanes:
3254234353Sdim    // Two-register operands have been converted to the
3255234353Sdim    // composite register classes.
3256234353Sdim    if (Count == 2) {
3257234353Sdim      const MCRegisterClass *RC = (Spacing == 1) ?
3258234353Sdim        &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3259234353Sdim        &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3260234353Sdim      FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3261234353Sdim    }
3262234353Sdim    Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
3263234353Sdim                                                            (Spacing == 2),
3264234353Sdim                                                            S, E));
3265234353Sdim    break;
3266234353Sdim  case IndexedLane:
3267234353Sdim    Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
3268234353Sdim                                                           LaneIndex,
3269234353Sdim                                                           (Spacing == 2),
3270234353Sdim                                                           S, E));
3271234353Sdim    break;
3272234353Sdim  }
3273234353Sdim  return MatchOperand_Success;
3274234353Sdim}
3275234353Sdim
3276226633Sdim/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
3277218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3278226633SdimparseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3279218893Sdim  SMLoc S = Parser.getTok().getLoc();
3280218893Sdim  const AsmToken &Tok = Parser.getTok();
3281239462Sdim  unsigned Opt;
3282218893Sdim
3283239462Sdim  if (Tok.is(AsmToken::Identifier)) {
3284239462Sdim    StringRef OptStr = Tok.getString();
3285218893Sdim
3286239462Sdim    Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()).lower())
3287239462Sdim      .Case("sy",    ARM_MB::SY)
3288239462Sdim      .Case("st",    ARM_MB::ST)
3289239462Sdim      .Case("sh",    ARM_MB::ISH)
3290239462Sdim      .Case("ish",   ARM_MB::ISH)
3291239462Sdim      .Case("shst",  ARM_MB::ISHST)
3292239462Sdim      .Case("ishst", ARM_MB::ISHST)
3293239462Sdim      .Case("nsh",   ARM_MB::NSH)
3294239462Sdim      .Case("un",    ARM_MB::NSH)
3295239462Sdim      .Case("nshst", ARM_MB::NSHST)
3296239462Sdim      .Case("unst",  ARM_MB::NSHST)
3297239462Sdim      .Case("osh",   ARM_MB::OSH)
3298239462Sdim      .Case("oshst", ARM_MB::OSHST)
3299239462Sdim      .Default(~0U);
3300218893Sdim
3301239462Sdim    if (Opt == ~0U)
3302239462Sdim      return MatchOperand_NoMatch;
3303239462Sdim
3304239462Sdim    Parser.Lex(); // Eat identifier token.
3305239462Sdim  } else if (Tok.is(AsmToken::Hash) ||
3306239462Sdim             Tok.is(AsmToken::Dollar) ||
3307239462Sdim             Tok.is(AsmToken::Integer)) {
3308239462Sdim    if (Parser.getTok().isNot(AsmToken::Integer))
3309239462Sdim      Parser.Lex(); // Eat the '#'.
3310239462Sdim    SMLoc Loc = Parser.getTok().getLoc();
3311239462Sdim
3312239462Sdim    const MCExpr *MemBarrierID;
3313239462Sdim    if (getParser().ParseExpression(MemBarrierID)) {
3314239462Sdim      Error(Loc, "illegal expression");
3315239462Sdim      return MatchOperand_ParseFail;
3316239462Sdim    }
3317239462Sdim
3318239462Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(MemBarrierID);
3319239462Sdim    if (!CE) {
3320239462Sdim      Error(Loc, "constant expression expected");
3321239462Sdim      return MatchOperand_ParseFail;
3322239462Sdim    }
3323239462Sdim
3324239462Sdim    int Val = CE->getValue();
3325239462Sdim    if (Val & ~0xf) {
3326239462Sdim      Error(Loc, "immediate value out of range");
3327239462Sdim      return MatchOperand_ParseFail;
3328239462Sdim    }
3329239462Sdim
3330239462Sdim    Opt = ARM_MB::RESERVED_0 + Val;
3331239462Sdim  } else
3332239462Sdim    return MatchOperand_ParseFail;
3333239462Sdim
3334218893Sdim  Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
3335218893Sdim  return MatchOperand_Success;
3336218893Sdim}
3337218893Sdim
3338226633Sdim/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
3339218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3340226633SdimparseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3341218893Sdim  SMLoc S = Parser.getTok().getLoc();
3342218893Sdim  const AsmToken &Tok = Parser.getTok();
3343239462Sdim  if (!Tok.is(AsmToken::Identifier))
3344239462Sdim    return MatchOperand_NoMatch;
3345218893Sdim  StringRef IFlagsStr = Tok.getString();
3346218893Sdim
3347226633Sdim  // An iflags string of "none" is interpreted to mean that none of the AIF
3348226633Sdim  // bits are set.  Not a terribly useful instruction, but a valid encoding.
3349218893Sdim  unsigned IFlags = 0;
3350226633Sdim  if (IFlagsStr != "none") {
3351226633Sdim        for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3352226633Sdim      unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3353226633Sdim        .Case("a", ARM_PROC::A)
3354226633Sdim        .Case("i", ARM_PROC::I)
3355226633Sdim        .Case("f", ARM_PROC::F)
3356226633Sdim        .Default(~0U);
3357218893Sdim
3358226633Sdim      // If some specific iflag is already set, it means that some letter is
3359226633Sdim      // present more than once, this is not acceptable.
3360226633Sdim      if (Flag == ~0U || (IFlags & Flag))
3361226633Sdim        return MatchOperand_NoMatch;
3362218893Sdim
3363226633Sdim      IFlags |= Flag;
3364226633Sdim    }
3365218893Sdim  }
3366218893Sdim
3367218893Sdim  Parser.Lex(); // Eat identifier token.
3368218893Sdim  Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3369218893Sdim  return MatchOperand_Success;
3370218893Sdim}
3371218893Sdim
3372226633Sdim/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
3373218893SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3374226633SdimparseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3375218893Sdim  SMLoc S = Parser.getTok().getLoc();
3376218893Sdim  const AsmToken &Tok = Parser.getTok();
3377243830Sdim  if (!Tok.is(AsmToken::Identifier))
3378243830Sdim    return MatchOperand_NoMatch;
3379218893Sdim  StringRef Mask = Tok.getString();
3380218893Sdim
3381226633Sdim  if (isMClass()) {
3382226633Sdim    // See ARMv6-M 10.1.1
3383234353Sdim    std::string Name = Mask.lower();
3384234353Sdim    unsigned FlagsVal = StringSwitch<unsigned>(Name)
3385239462Sdim      // Note: in the documentation:
3386239462Sdim      //  ARM deprecates using MSR APSR without a _<bits> qualifier as an alias
3387239462Sdim      //  for MSR APSR_nzcvq.
3388239462Sdim      // but we do make it an alias here.  This is so to get the "mask encoding"
3389239462Sdim      // bits correct on MSR APSR writes.
3390239462Sdim      //
3391239462Sdim      // FIXME: Note the 0xc00 "mask encoding" bits version of the registers
3392239462Sdim      // should really only be allowed when writing a special register.  Note
3393239462Sdim      // they get dropped in the MRS instruction reading a special register as
3394239462Sdim      // the SYSm field is only 8 bits.
3395239462Sdim      //
3396239462Sdim      // FIXME: the _g and _nzcvqg versions are only allowed if the processor
3397239462Sdim      // includes the DSP extension but that is not checked.
3398239462Sdim      .Case("apsr", 0x800)
3399239462Sdim      .Case("apsr_nzcvq", 0x800)
3400239462Sdim      .Case("apsr_g", 0x400)
3401239462Sdim      .Case("apsr_nzcvqg", 0xc00)
3402239462Sdim      .Case("iapsr", 0x801)
3403239462Sdim      .Case("iapsr_nzcvq", 0x801)
3404239462Sdim      .Case("iapsr_g", 0x401)
3405239462Sdim      .Case("iapsr_nzcvqg", 0xc01)
3406239462Sdim      .Case("eapsr", 0x802)
3407239462Sdim      .Case("eapsr_nzcvq", 0x802)
3408239462Sdim      .Case("eapsr_g", 0x402)
3409239462Sdim      .Case("eapsr_nzcvqg", 0xc02)
3410239462Sdim      .Case("xpsr", 0x803)
3411239462Sdim      .Case("xpsr_nzcvq", 0x803)
3412239462Sdim      .Case("xpsr_g", 0x403)
3413239462Sdim      .Case("xpsr_nzcvqg", 0xc03)
3414239462Sdim      .Case("ipsr", 0x805)
3415239462Sdim      .Case("epsr", 0x806)
3416239462Sdim      .Case("iepsr", 0x807)
3417239462Sdim      .Case("msp", 0x808)
3418239462Sdim      .Case("psp", 0x809)
3419239462Sdim      .Case("primask", 0x810)
3420239462Sdim      .Case("basepri", 0x811)
3421239462Sdim      .Case("basepri_max", 0x812)
3422239462Sdim      .Case("faultmask", 0x813)
3423239462Sdim      .Case("control", 0x814)
3424226633Sdim      .Default(~0U);
3425234353Sdim
3426226633Sdim    if (FlagsVal == ~0U)
3427226633Sdim      return MatchOperand_NoMatch;
3428226633Sdim
3429239462Sdim    if (!hasV7Ops() && FlagsVal >= 0x811 && FlagsVal <= 0x813)
3430226633Sdim      // basepri, basepri_max and faultmask only valid for V7m.
3431226633Sdim      return MatchOperand_NoMatch;
3432234353Sdim
3433226633Sdim    Parser.Lex(); // Eat identifier token.
3434226633Sdim    Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3435226633Sdim    return MatchOperand_Success;
3436226633Sdim  }
3437226633Sdim
3438218893Sdim  // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3439218893Sdim  size_t Start = 0, Next = Mask.find('_');
3440218893Sdim  StringRef Flags = "";
3441234353Sdim  std::string SpecReg = Mask.slice(Start, Next).lower();
3442218893Sdim  if (Next != StringRef::npos)
3443218893Sdim    Flags = Mask.slice(Next+1, Mask.size());
3444218893Sdim
3445218893Sdim  // FlagsVal contains the complete mask:
3446218893Sdim  // 3-0: Mask
3447218893Sdim  // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3448218893Sdim  unsigned FlagsVal = 0;
3449218893Sdim
3450218893Sdim  if (SpecReg == "apsr") {
3451218893Sdim    FlagsVal = StringSwitch<unsigned>(Flags)
3452226633Sdim    .Case("nzcvq",  0x8) // same as CPSR_f
3453218893Sdim    .Case("g",      0x4) // same as CPSR_s
3454218893Sdim    .Case("nzcvqg", 0xc) // same as CPSR_fs
3455218893Sdim    .Default(~0U);
3456218893Sdim
3457218893Sdim    if (FlagsVal == ~0U) {
3458218893Sdim      if (!Flags.empty())
3459218893Sdim        return MatchOperand_NoMatch;
3460218893Sdim      else
3461226633Sdim        FlagsVal = 8; // No flag
3462218893Sdim    }
3463218893Sdim  } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
3464234353Sdim    // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
3465234353Sdim    if (Flags == "all" || Flags == "")
3466223017Sdim      Flags = "fc";
3467218893Sdim    for (int i = 0, e = Flags.size(); i != e; ++i) {
3468218893Sdim      unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3469218893Sdim      .Case("c", 1)
3470218893Sdim      .Case("x", 2)
3471218893Sdim      .Case("s", 4)
3472218893Sdim      .Case("f", 8)
3473218893Sdim      .Default(~0U);
3474218893Sdim
3475218893Sdim      // If some specific flag is already set, it means that some letter is
3476218893Sdim      // present more than once, this is not acceptable.
3477218893Sdim      if (FlagsVal == ~0U || (FlagsVal & Flag))
3478218893Sdim        return MatchOperand_NoMatch;
3479218893Sdim      FlagsVal |= Flag;
3480218893Sdim    }
3481218893Sdim  } else // No match for special register.
3482218893Sdim    return MatchOperand_NoMatch;
3483218893Sdim
3484234353Sdim  // Special register without flags is NOT equivalent to "fc" flags.
3485234353Sdim  // NOTE: This is a divergence from gas' behavior.  Uncommenting the following
3486234353Sdim  // two lines would enable gas compatibility at the expense of breaking
3487234353Sdim  // round-tripping.
3488234353Sdim  //
3489234353Sdim  // if (!FlagsVal)
3490234353Sdim  //  FlagsVal = 0x9;
3491218893Sdim
3492218893Sdim  // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3493218893Sdim  if (SpecReg == "spsr")
3494218893Sdim    FlagsVal |= 16;
3495218893Sdim
3496218893Sdim  Parser.Lex(); // Eat identifier token.
3497218893Sdim  Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3498218893Sdim  return MatchOperand_Success;
3499218893Sdim}
3500218893Sdim
3501221345SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3502226633SdimparsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3503226633Sdim            int Low, int High) {
3504226633Sdim  const AsmToken &Tok = Parser.getTok();
3505226633Sdim  if (Tok.isNot(AsmToken::Identifier)) {
3506226633Sdim    Error(Parser.getTok().getLoc(), Op + " operand expected.");
3507226633Sdim    return MatchOperand_ParseFail;
3508226633Sdim  }
3509226633Sdim  StringRef ShiftName = Tok.getString();
3510234353Sdim  std::string LowerOp = Op.lower();
3511234353Sdim  std::string UpperOp = Op.upper();
3512226633Sdim  if (ShiftName != LowerOp && ShiftName != UpperOp) {
3513226633Sdim    Error(Parser.getTok().getLoc(), Op + " operand expected.");
3514226633Sdim    return MatchOperand_ParseFail;
3515226633Sdim  }
3516226633Sdim  Parser.Lex(); // Eat shift type token.
3517221345Sdim
3518226633Sdim  // There must be a '#' and a shift amount.
3519234353Sdim  if (Parser.getTok().isNot(AsmToken::Hash) &&
3520234353Sdim      Parser.getTok().isNot(AsmToken::Dollar)) {
3521226633Sdim    Error(Parser.getTok().getLoc(), "'#' expected");
3522226633Sdim    return MatchOperand_ParseFail;
3523226633Sdim  }
3524226633Sdim  Parser.Lex(); // Eat hash token.
3525221345Sdim
3526226633Sdim  const MCExpr *ShiftAmount;
3527226633Sdim  SMLoc Loc = Parser.getTok().getLoc();
3528226633Sdim  if (getParser().ParseExpression(ShiftAmount)) {
3529226633Sdim    Error(Loc, "illegal expression");
3530226633Sdim    return MatchOperand_ParseFail;
3531226633Sdim  }
3532226633Sdim  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3533226633Sdim  if (!CE) {
3534226633Sdim    Error(Loc, "constant expression expected");
3535226633Sdim    return MatchOperand_ParseFail;
3536226633Sdim  }
3537226633Sdim  int Val = CE->getValue();
3538226633Sdim  if (Val < Low || Val > High) {
3539226633Sdim    Error(Loc, "immediate value out of range");
3540226633Sdim    return MatchOperand_ParseFail;
3541226633Sdim  }
3542226633Sdim
3543226633Sdim  Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3544226633Sdim
3545221345Sdim  return MatchOperand_Success;
3546221345Sdim}
3547221345Sdim
3548221345SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3549226633SdimparseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3550226633Sdim  const AsmToken &Tok = Parser.getTok();
3551226633Sdim  SMLoc S = Tok.getLoc();
3552226633Sdim  if (Tok.isNot(AsmToken::Identifier)) {
3553226633Sdim    Error(Tok.getLoc(), "'be' or 'le' operand expected");
3554226633Sdim    return MatchOperand_ParseFail;
3555226633Sdim  }
3556226633Sdim  int Val = StringSwitch<int>(Tok.getString())
3557226633Sdim    .Case("be", 1)
3558226633Sdim    .Case("le", 0)
3559226633Sdim    .Default(-1);
3560226633Sdim  Parser.Lex(); // Eat the token.
3561221345Sdim
3562226633Sdim  if (Val == -1) {
3563226633Sdim    Error(Tok.getLoc(), "'be' or 'le' operand expected");
3564226633Sdim    return MatchOperand_ParseFail;
3565226633Sdim  }
3566226633Sdim  Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3567226633Sdim                                                                  getContext()),
3568226633Sdim                                           S, Parser.getTok().getLoc()));
3569226633Sdim  return MatchOperand_Success;
3570226633Sdim}
3571226633Sdim
3572226633Sdim/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3573226633Sdim/// instructions. Legal values are:
3574226633Sdim///     lsl #n  'n' in [0,31]
3575226633Sdim///     asr #n  'n' in [1,32]
3576226633Sdim///             n == 32 encoded as n == 0.
3577226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3578226633SdimparseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3579226633Sdim  const AsmToken &Tok = Parser.getTok();
3580226633Sdim  SMLoc S = Tok.getLoc();
3581226633Sdim  if (Tok.isNot(AsmToken::Identifier)) {
3582226633Sdim    Error(S, "shift operator 'asr' or 'lsl' expected");
3583226633Sdim    return MatchOperand_ParseFail;
3584226633Sdim  }
3585226633Sdim  StringRef ShiftName = Tok.getString();
3586226633Sdim  bool isASR;
3587226633Sdim  if (ShiftName == "lsl" || ShiftName == "LSL")
3588226633Sdim    isASR = false;
3589226633Sdim  else if (ShiftName == "asr" || ShiftName == "ASR")
3590226633Sdim    isASR = true;
3591226633Sdim  else {
3592226633Sdim    Error(S, "shift operator 'asr' or 'lsl' expected");
3593226633Sdim    return MatchOperand_ParseFail;
3594226633Sdim  }
3595226633Sdim  Parser.Lex(); // Eat the operator.
3596226633Sdim
3597226633Sdim  // A '#' and a shift amount.
3598234353Sdim  if (Parser.getTok().isNot(AsmToken::Hash) &&
3599234353Sdim      Parser.getTok().isNot(AsmToken::Dollar)) {
3600226633Sdim    Error(Parser.getTok().getLoc(), "'#' expected");
3601226633Sdim    return MatchOperand_ParseFail;
3602226633Sdim  }
3603226633Sdim  Parser.Lex(); // Eat hash token.
3604226633Sdim
3605226633Sdim  const MCExpr *ShiftAmount;
3606226633Sdim  SMLoc E = Parser.getTok().getLoc();
3607226633Sdim  if (getParser().ParseExpression(ShiftAmount)) {
3608226633Sdim    Error(E, "malformed shift expression");
3609226633Sdim    return MatchOperand_ParseFail;
3610226633Sdim  }
3611226633Sdim  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3612226633Sdim  if (!CE) {
3613226633Sdim    Error(E, "shift amount must be an immediate");
3614226633Sdim    return MatchOperand_ParseFail;
3615226633Sdim  }
3616226633Sdim
3617226633Sdim  int64_t Val = CE->getValue();
3618226633Sdim  if (isASR) {
3619226633Sdim    // Shift amount must be in [1,32]
3620226633Sdim    if (Val < 1 || Val > 32) {
3621226633Sdim      Error(E, "'asr' shift amount must be in range [1,32]");
3622226633Sdim      return MatchOperand_ParseFail;
3623226633Sdim    }
3624226633Sdim    // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3625226633Sdim    if (isThumb() && Val == 32) {
3626226633Sdim      Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3627226633Sdim      return MatchOperand_ParseFail;
3628226633Sdim    }
3629226633Sdim    if (Val == 32) Val = 0;
3630226633Sdim  } else {
3631226633Sdim    // Shift amount must be in [1,32]
3632226633Sdim    if (Val < 0 || Val > 31) {
3633226633Sdim      Error(E, "'lsr' shift amount must be in range [0,31]");
3634226633Sdim      return MatchOperand_ParseFail;
3635226633Sdim    }
3636226633Sdim  }
3637226633Sdim
3638226633Sdim  E = Parser.getTok().getLoc();
3639226633Sdim  Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3640226633Sdim
3641226633Sdim  return MatchOperand_Success;
3642226633Sdim}
3643226633Sdim
3644226633Sdim/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3645226633Sdim/// of instructions. Legal values are:
3646226633Sdim///     ror #n  'n' in {0, 8, 16, 24}
3647226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3648226633SdimparseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3649226633Sdim  const AsmToken &Tok = Parser.getTok();
3650226633Sdim  SMLoc S = Tok.getLoc();
3651226633Sdim  if (Tok.isNot(AsmToken::Identifier))
3652221345Sdim    return MatchOperand_NoMatch;
3653226633Sdim  StringRef ShiftName = Tok.getString();
3654226633Sdim  if (ShiftName != "ror" && ShiftName != "ROR")
3655226633Sdim    return MatchOperand_NoMatch;
3656226633Sdim  Parser.Lex(); // Eat the operator.
3657221345Sdim
3658226633Sdim  // A '#' and a rotate amount.
3659234353Sdim  if (Parser.getTok().isNot(AsmToken::Hash) &&
3660234353Sdim      Parser.getTok().isNot(AsmToken::Dollar)) {
3661226633Sdim    Error(Parser.getTok().getLoc(), "'#' expected");
3662226633Sdim    return MatchOperand_ParseFail;
3663226633Sdim  }
3664226633Sdim  Parser.Lex(); // Eat hash token.
3665226633Sdim
3666226633Sdim  const MCExpr *ShiftAmount;
3667226633Sdim  SMLoc E = Parser.getTok().getLoc();
3668226633Sdim  if (getParser().ParseExpression(ShiftAmount)) {
3669226633Sdim    Error(E, "malformed rotate expression");
3670226633Sdim    return MatchOperand_ParseFail;
3671226633Sdim  }
3672226633Sdim  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3673226633Sdim  if (!CE) {
3674226633Sdim    Error(E, "rotate amount must be an immediate");
3675226633Sdim    return MatchOperand_ParseFail;
3676226633Sdim  }
3677226633Sdim
3678226633Sdim  int64_t Val = CE->getValue();
3679226633Sdim  // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3680226633Sdim  // normally, zero is represented in asm by omitting the rotate operand
3681226633Sdim  // entirely.
3682226633Sdim  if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3683226633Sdim    Error(E, "'ror' rotate amount must be 8, 16, or 24");
3684226633Sdim    return MatchOperand_ParseFail;
3685226633Sdim  }
3686226633Sdim
3687226633Sdim  E = Parser.getTok().getLoc();
3688226633Sdim  Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3689226633Sdim
3690221345Sdim  return MatchOperand_Success;
3691221345Sdim}
3692221345Sdim
3693226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3694226633SdimparseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3695226633Sdim  SMLoc S = Parser.getTok().getLoc();
3696226633Sdim  // The bitfield descriptor is really two operands, the LSB and the width.
3697234353Sdim  if (Parser.getTok().isNot(AsmToken::Hash) &&
3698234353Sdim      Parser.getTok().isNot(AsmToken::Dollar)) {
3699226633Sdim    Error(Parser.getTok().getLoc(), "'#' expected");
3700226633Sdim    return MatchOperand_ParseFail;
3701226633Sdim  }
3702226633Sdim  Parser.Lex(); // Eat hash token.
3703226633Sdim
3704226633Sdim  const MCExpr *LSBExpr;
3705226633Sdim  SMLoc E = Parser.getTok().getLoc();
3706226633Sdim  if (getParser().ParseExpression(LSBExpr)) {
3707226633Sdim    Error(E, "malformed immediate expression");
3708226633Sdim    return MatchOperand_ParseFail;
3709226633Sdim  }
3710226633Sdim  const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3711226633Sdim  if (!CE) {
3712226633Sdim    Error(E, "'lsb' operand must be an immediate");
3713226633Sdim    return MatchOperand_ParseFail;
3714226633Sdim  }
3715226633Sdim
3716226633Sdim  int64_t LSB = CE->getValue();
3717226633Sdim  // The LSB must be in the range [0,31]
3718226633Sdim  if (LSB < 0 || LSB > 31) {
3719226633Sdim    Error(E, "'lsb' operand must be in the range [0,31]");
3720226633Sdim    return MatchOperand_ParseFail;
3721226633Sdim  }
3722226633Sdim  E = Parser.getTok().getLoc();
3723226633Sdim
3724226633Sdim  // Expect another immediate operand.
3725226633Sdim  if (Parser.getTok().isNot(AsmToken::Comma)) {
3726226633Sdim    Error(Parser.getTok().getLoc(), "too few operands");
3727226633Sdim    return MatchOperand_ParseFail;
3728226633Sdim  }
3729226633Sdim  Parser.Lex(); // Eat hash token.
3730234353Sdim  if (Parser.getTok().isNot(AsmToken::Hash) &&
3731234353Sdim      Parser.getTok().isNot(AsmToken::Dollar)) {
3732226633Sdim    Error(Parser.getTok().getLoc(), "'#' expected");
3733226633Sdim    return MatchOperand_ParseFail;
3734226633Sdim  }
3735226633Sdim  Parser.Lex(); // Eat hash token.
3736226633Sdim
3737226633Sdim  const MCExpr *WidthExpr;
3738226633Sdim  if (getParser().ParseExpression(WidthExpr)) {
3739226633Sdim    Error(E, "malformed immediate expression");
3740226633Sdim    return MatchOperand_ParseFail;
3741226633Sdim  }
3742226633Sdim  CE = dyn_cast<MCConstantExpr>(WidthExpr);
3743226633Sdim  if (!CE) {
3744226633Sdim    Error(E, "'width' operand must be an immediate");
3745226633Sdim    return MatchOperand_ParseFail;
3746226633Sdim  }
3747226633Sdim
3748226633Sdim  int64_t Width = CE->getValue();
3749226633Sdim  // The LSB must be in the range [1,32-lsb]
3750226633Sdim  if (Width < 1 || Width > 32 - LSB) {
3751226633Sdim    Error(E, "'width' operand must be in the range [1,32-lsb]");
3752226633Sdim    return MatchOperand_ParseFail;
3753226633Sdim  }
3754226633Sdim  E = Parser.getTok().getLoc();
3755226633Sdim
3756226633Sdim  Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3757226633Sdim
3758226633Sdim  return MatchOperand_Success;
3759226633Sdim}
3760226633Sdim
3761226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3762226633SdimparsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3763226633Sdim  // Check for a post-index addressing register operand. Specifically:
3764226633Sdim  // postidx_reg := '+' register {, shift}
3765226633Sdim  //              | '-' register {, shift}
3766226633Sdim  //              | register {, shift}
3767226633Sdim
3768226633Sdim  // This method must return MatchOperand_NoMatch without consuming any tokens
3769226633Sdim  // in the case where there is no match, as other alternatives take other
3770226633Sdim  // parse methods.
3771226633Sdim  AsmToken Tok = Parser.getTok();
3772226633Sdim  SMLoc S = Tok.getLoc();
3773226633Sdim  bool haveEaten = false;
3774226633Sdim  bool isAdd = true;
3775226633Sdim  int Reg = -1;
3776226633Sdim  if (Tok.is(AsmToken::Plus)) {
3777226633Sdim    Parser.Lex(); // Eat the '+' token.
3778226633Sdim    haveEaten = true;
3779226633Sdim  } else if (Tok.is(AsmToken::Minus)) {
3780226633Sdim    Parser.Lex(); // Eat the '-' token.
3781226633Sdim    isAdd = false;
3782226633Sdim    haveEaten = true;
3783226633Sdim  }
3784226633Sdim  if (Parser.getTok().is(AsmToken::Identifier))
3785226633Sdim    Reg = tryParseRegister();
3786226633Sdim  if (Reg == -1) {
3787226633Sdim    if (!haveEaten)
3788226633Sdim      return MatchOperand_NoMatch;
3789226633Sdim    Error(Parser.getTok().getLoc(), "register expected");
3790226633Sdim    return MatchOperand_ParseFail;
3791226633Sdim  }
3792226633Sdim  SMLoc E = Parser.getTok().getLoc();
3793226633Sdim
3794226633Sdim  ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3795226633Sdim  unsigned ShiftImm = 0;
3796226633Sdim  if (Parser.getTok().is(AsmToken::Comma)) {
3797226633Sdim    Parser.Lex(); // Eat the ','.
3798226633Sdim    if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3799226633Sdim      return MatchOperand_ParseFail;
3800226633Sdim  }
3801226633Sdim
3802226633Sdim  Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3803226633Sdim                                                  ShiftImm, S, E));
3804226633Sdim
3805226633Sdim  return MatchOperand_Success;
3806226633Sdim}
3807226633Sdim
3808226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
3809226633SdimparseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3810226633Sdim  // Check for a post-index addressing register operand. Specifically:
3811226633Sdim  // am3offset := '+' register
3812226633Sdim  //              | '-' register
3813226633Sdim  //              | register
3814226633Sdim  //              | # imm
3815226633Sdim  //              | # + imm
3816226633Sdim  //              | # - imm
3817226633Sdim
3818226633Sdim  // This method must return MatchOperand_NoMatch without consuming any tokens
3819226633Sdim  // in the case where there is no match, as other alternatives take other
3820226633Sdim  // parse methods.
3821226633Sdim  AsmToken Tok = Parser.getTok();
3822226633Sdim  SMLoc S = Tok.getLoc();
3823226633Sdim
3824226633Sdim  // Do immediates first, as we always parse those if we have a '#'.
3825234353Sdim  if (Parser.getTok().is(AsmToken::Hash) ||
3826234353Sdim      Parser.getTok().is(AsmToken::Dollar)) {
3827226633Sdim    Parser.Lex(); // Eat the '#'.
3828226633Sdim    // Explicitly look for a '-', as we need to encode negative zero
3829226633Sdim    // differently.
3830226633Sdim    bool isNegative = Parser.getTok().is(AsmToken::Minus);
3831226633Sdim    const MCExpr *Offset;
3832226633Sdim    if (getParser().ParseExpression(Offset))
3833226633Sdim      return MatchOperand_ParseFail;
3834226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3835226633Sdim    if (!CE) {
3836226633Sdim      Error(S, "constant expression expected");
3837226633Sdim      return MatchOperand_ParseFail;
3838226633Sdim    }
3839226633Sdim    SMLoc E = Tok.getLoc();
3840226633Sdim    // Negative zero is encoded as the flag value INT32_MIN.
3841226633Sdim    int32_t Val = CE->getValue();
3842226633Sdim    if (isNegative && Val == 0)
3843226633Sdim      Val = INT32_MIN;
3844226633Sdim
3845226633Sdim    Operands.push_back(
3846226633Sdim      ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3847226633Sdim
3848226633Sdim    return MatchOperand_Success;
3849226633Sdim  }
3850226633Sdim
3851226633Sdim
3852226633Sdim  bool haveEaten = false;
3853226633Sdim  bool isAdd = true;
3854226633Sdim  int Reg = -1;
3855226633Sdim  if (Tok.is(AsmToken::Plus)) {
3856226633Sdim    Parser.Lex(); // Eat the '+' token.
3857226633Sdim    haveEaten = true;
3858226633Sdim  } else if (Tok.is(AsmToken::Minus)) {
3859226633Sdim    Parser.Lex(); // Eat the '-' token.
3860226633Sdim    isAdd = false;
3861226633Sdim    haveEaten = true;
3862226633Sdim  }
3863226633Sdim  if (Parser.getTok().is(AsmToken::Identifier))
3864226633Sdim    Reg = tryParseRegister();
3865226633Sdim  if (Reg == -1) {
3866226633Sdim    if (!haveEaten)
3867226633Sdim      return MatchOperand_NoMatch;
3868226633Sdim    Error(Parser.getTok().getLoc(), "register expected");
3869226633Sdim    return MatchOperand_ParseFail;
3870226633Sdim  }
3871226633Sdim  SMLoc E = Parser.getTok().getLoc();
3872226633Sdim
3873226633Sdim  Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3874226633Sdim                                                  0, S, E));
3875226633Sdim
3876226633Sdim  return MatchOperand_Success;
3877226633Sdim}
3878226633Sdim
3879226633Sdim/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3880221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3881221345Sdim/// when they refer multiple MIOperands inside a single one.
3882243830Sdimvoid ARMAsmParser::
3883243830SdimcvtT2LdrdPre(MCInst &Inst,
3884226633Sdim             const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3885226633Sdim  // Rt, Rt2
3886226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3887226633Sdim  ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3888226633Sdim  // Create a writeback register dummy placeholder.
3889226633Sdim  Inst.addOperand(MCOperand::CreateReg(0));
3890226633Sdim  // addr
3891226633Sdim  ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3892226633Sdim  // pred
3893226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3894226633Sdim}
3895226633Sdim
3896226633Sdim/// cvtT2StrdPre - Convert parsed operands to MCInst.
3897226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3898226633Sdim/// when they refer multiple MIOperands inside a single one.
3899243830Sdimvoid ARMAsmParser::
3900243830SdimcvtT2StrdPre(MCInst &Inst,
3901226633Sdim             const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3902226633Sdim  // Create a writeback register dummy placeholder.
3903226633Sdim  Inst.addOperand(MCOperand::CreateReg(0));
3904226633Sdim  // Rt, Rt2
3905226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3906226633Sdim  ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3907226633Sdim  // addr
3908226633Sdim  ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3909226633Sdim  // pred
3910226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3911226633Sdim}
3912226633Sdim
3913226633Sdim/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3914226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3915226633Sdim/// when they refer multiple MIOperands inside a single one.
3916243830Sdimvoid ARMAsmParser::
3917243830SdimcvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst,
3918221345Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3919221345Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3920221345Sdim
3921221345Sdim  // Create a writeback register dummy placeholder.
3922221345Sdim  Inst.addOperand(MCOperand::CreateImm(0));
3923221345Sdim
3924226633Sdim  ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3925221345Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3926221345Sdim}
3927221345Sdim
3928226633Sdim/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3929221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3930221345Sdim/// when they refer multiple MIOperands inside a single one.
3931243830Sdimvoid ARMAsmParser::
3932243830SdimcvtStWriteBackRegT2AddrModeImm8(MCInst &Inst,
3933221345Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3934221345Sdim  // Create a writeback register dummy placeholder.
3935221345Sdim  Inst.addOperand(MCOperand::CreateImm(0));
3936221345Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3937226633Sdim  ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3938221345Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3939221345Sdim}
3940221345Sdim
3941226633Sdim/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
3942221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3943221345Sdim/// when they refer multiple MIOperands inside a single one.
3944243830Sdimvoid ARMAsmParser::
3945243830SdimcvtLdWriteBackRegAddrMode2(MCInst &Inst,
3946221345Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3947221345Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3948221345Sdim
3949221345Sdim  // Create a writeback register dummy placeholder.
3950221345Sdim  Inst.addOperand(MCOperand::CreateImm(0));
3951221345Sdim
3952226633Sdim  ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3953221345Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3954221345Sdim}
3955221345Sdim
3956226633Sdim/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3957221345Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3958221345Sdim/// when they refer multiple MIOperands inside a single one.
3959243830Sdimvoid ARMAsmParser::
3960243830SdimcvtLdWriteBackRegAddrModeImm12(MCInst &Inst,
3961221345Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3962226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3963226633Sdim
3964221345Sdim  // Create a writeback register dummy placeholder.
3965221345Sdim  Inst.addOperand(MCOperand::CreateImm(0));
3966226633Sdim
3967226633Sdim  ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3968226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3969226633Sdim}
3970226633Sdim
3971226633Sdim
3972226633Sdim/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3973226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3974226633Sdim/// when they refer multiple MIOperands inside a single one.
3975243830Sdimvoid ARMAsmParser::
3976243830SdimcvtStWriteBackRegAddrModeImm12(MCInst &Inst,
3977226633Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3978226633Sdim  // Create a writeback register dummy placeholder.
3979226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
3980221345Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3981226633Sdim  ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3982221345Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3983221345Sdim}
3984221345Sdim
3985226633Sdim/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
3986226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3987226633Sdim/// when they refer multiple MIOperands inside a single one.
3988243830Sdimvoid ARMAsmParser::
3989243830SdimcvtStWriteBackRegAddrMode2(MCInst &Inst,
3990226633Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3991226633Sdim  // Create a writeback register dummy placeholder.
3992226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
3993226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3994226633Sdim  ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3995226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3996226633Sdim}
3997226633Sdim
3998226633Sdim/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3999226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4000226633Sdim/// when they refer multiple MIOperands inside a single one.
4001243830Sdimvoid ARMAsmParser::
4002243830SdimcvtStWriteBackRegAddrMode3(MCInst &Inst,
4003226633Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4004226633Sdim  // Create a writeback register dummy placeholder.
4005226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4006226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4007226633Sdim  ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4008226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4009226633Sdim}
4010226633Sdim
4011226633Sdim/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
4012226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4013226633Sdim/// when they refer multiple MIOperands inside a single one.
4014243830Sdimvoid ARMAsmParser::
4015243830SdimcvtLdExtTWriteBackImm(MCInst &Inst,
4016226633Sdim                      const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4017226633Sdim  // Rt
4018226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4019226633Sdim  // Create a writeback register dummy placeholder.
4020226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4021226633Sdim  // addr
4022226633Sdim  ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4023226633Sdim  // offset
4024226633Sdim  ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
4025226633Sdim  // pred
4026226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4027226633Sdim}
4028226633Sdim
4029226633Sdim/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
4030226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4031226633Sdim/// when they refer multiple MIOperands inside a single one.
4032243830Sdimvoid ARMAsmParser::
4033243830SdimcvtLdExtTWriteBackReg(MCInst &Inst,
4034226633Sdim                      const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4035226633Sdim  // Rt
4036226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4037226633Sdim  // Create a writeback register dummy placeholder.
4038226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4039226633Sdim  // addr
4040226633Sdim  ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4041226633Sdim  // offset
4042226633Sdim  ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
4043226633Sdim  // pred
4044226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4045226633Sdim}
4046226633Sdim
4047226633Sdim/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
4048226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4049226633Sdim/// when they refer multiple MIOperands inside a single one.
4050243830Sdimvoid ARMAsmParser::
4051243830SdimcvtStExtTWriteBackImm(MCInst &Inst,
4052226633Sdim                      const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4053226633Sdim  // Create a writeback register dummy placeholder.
4054226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4055226633Sdim  // Rt
4056226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4057226633Sdim  // addr
4058226633Sdim  ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4059226633Sdim  // offset
4060226633Sdim  ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
4061226633Sdim  // pred
4062226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4063226633Sdim}
4064226633Sdim
4065226633Sdim/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
4066226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4067226633Sdim/// when they refer multiple MIOperands inside a single one.
4068243830Sdimvoid ARMAsmParser::
4069243830SdimcvtStExtTWriteBackReg(MCInst &Inst,
4070226633Sdim                      const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4071226633Sdim  // Create a writeback register dummy placeholder.
4072226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4073226633Sdim  // Rt
4074226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4075226633Sdim  // addr
4076226633Sdim  ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4077226633Sdim  // offset
4078226633Sdim  ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
4079226633Sdim  // pred
4080226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4081226633Sdim}
4082226633Sdim
4083226633Sdim/// cvtLdrdPre - Convert parsed operands to MCInst.
4084226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4085226633Sdim/// when they refer multiple MIOperands inside a single one.
4086243830Sdimvoid ARMAsmParser::
4087243830SdimcvtLdrdPre(MCInst &Inst,
4088226633Sdim           const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4089226633Sdim  // Rt, Rt2
4090226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4091226633Sdim  ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4092226633Sdim  // Create a writeback register dummy placeholder.
4093226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4094226633Sdim  // addr
4095226633Sdim  ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4096226633Sdim  // pred
4097226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4098226633Sdim}
4099226633Sdim
4100226633Sdim/// cvtStrdPre - Convert parsed operands to MCInst.
4101226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4102226633Sdim/// when they refer multiple MIOperands inside a single one.
4103243830Sdimvoid ARMAsmParser::
4104243830SdimcvtStrdPre(MCInst &Inst,
4105226633Sdim           const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4106226633Sdim  // Create a writeback register dummy placeholder.
4107226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4108226633Sdim  // Rt, Rt2
4109226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4110226633Sdim  ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4111226633Sdim  // addr
4112226633Sdim  ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4113226633Sdim  // pred
4114226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4115226633Sdim}
4116226633Sdim
4117226633Sdim/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
4118226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4119226633Sdim/// when they refer multiple MIOperands inside a single one.
4120243830Sdimvoid ARMAsmParser::
4121243830SdimcvtLdWriteBackRegAddrMode3(MCInst &Inst,
4122226633Sdim                         const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4123226633Sdim  ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4124226633Sdim  // Create a writeback register dummy placeholder.
4125226633Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4126226633Sdim  ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4127226633Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4128226633Sdim}
4129226633Sdim
4130243830Sdim/// cvtThumbMultiply - Convert parsed operands to MCInst.
4131226633Sdim/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4132226633Sdim/// when they refer multiple MIOperands inside a single one.
4133243830Sdimvoid ARMAsmParser::
4134243830SdimcvtThumbMultiply(MCInst &Inst,
4135226633Sdim           const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4136226633Sdim  ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4137226633Sdim  ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
4138234353Sdim  // If we have a three-operand form, make sure to set Rn to be the operand
4139234353Sdim  // that isn't the same as Rd.
4140234353Sdim  unsigned RegOp = 4;
4141234353Sdim  if (Operands.size() == 6 &&
4142234353Sdim      ((ARMOperand*)Operands[4])->getReg() ==
4143234353Sdim        ((ARMOperand*)Operands[3])->getReg())
4144234353Sdim    RegOp = 5;
4145234353Sdim  ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4146234353Sdim  Inst.addOperand(Inst.getOperand(0));
4147226633Sdim  ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4148226633Sdim}
4149226633Sdim
4150243830Sdimvoid ARMAsmParser::
4151243830SdimcvtVLDwbFixed(MCInst &Inst,
4152234353Sdim              const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4153234353Sdim  // Vd
4154234353Sdim  ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
4155234353Sdim  // Create a writeback register dummy placeholder.
4156234353Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4157234353Sdim  // Vn
4158234353Sdim  ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4159234353Sdim  // pred
4160234353Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4161234353Sdim}
4162234353Sdim
4163243830Sdimvoid ARMAsmParser::
4164243830SdimcvtVLDwbRegister(MCInst &Inst,
4165234353Sdim                 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4166234353Sdim  // Vd
4167234353Sdim  ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
4168234353Sdim  // Create a writeback register dummy placeholder.
4169234353Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4170234353Sdim  // Vn
4171234353Sdim  ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4172234353Sdim  // Vm
4173234353Sdim  ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4174234353Sdim  // pred
4175234353Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4176234353Sdim}
4177234353Sdim
4178243830Sdimvoid ARMAsmParser::
4179243830SdimcvtVSTwbFixed(MCInst &Inst,
4180234353Sdim              const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4181234353Sdim  // Create a writeback register dummy placeholder.
4182234353Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4183234353Sdim  // Vn
4184234353Sdim  ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4185234353Sdim  // Vt
4186234353Sdim  ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
4187234353Sdim  // pred
4188234353Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4189234353Sdim}
4190234353Sdim
4191243830Sdimvoid ARMAsmParser::
4192243830SdimcvtVSTwbRegister(MCInst &Inst,
4193234353Sdim                 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4194234353Sdim  // Create a writeback register dummy placeholder.
4195234353Sdim  Inst.addOperand(MCOperand::CreateImm(0));
4196234353Sdim  // Vn
4197234353Sdim  ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4198234353Sdim  // Vm
4199234353Sdim  ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4200234353Sdim  // Vt
4201234353Sdim  ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
4202234353Sdim  // pred
4203234353Sdim  ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4204234353Sdim}
4205234353Sdim
4206218893Sdim/// Parse an ARM memory expression, return false if successful else return true
4207198892Srdivacky/// or an error.  The first token must be a '[' when called.
4208218893Sdimbool ARMAsmParser::
4209226633SdimparseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4210206124Srdivacky  SMLoc S, E;
4211202878Srdivacky  assert(Parser.getTok().is(AsmToken::LBrac) &&
4212218893Sdim         "Token is not a Left Bracket");
4213206124Srdivacky  S = Parser.getTok().getLoc();
4214202878Srdivacky  Parser.Lex(); // Eat left bracket token.
4215198090Srdivacky
4216202878Srdivacky  const AsmToken &BaseRegTok = Parser.getTok();
4217226633Sdim  int BaseRegNum = tryParseRegister();
4218226633Sdim  if (BaseRegNum == -1)
4219226633Sdim    return Error(BaseRegTok.getLoc(), "register expected");
4220198090Srdivacky
4221218893Sdim  // The next token must either be a comma or a closing bracket.
4222218893Sdim  const AsmToken &Tok = Parser.getTok();
4223218893Sdim  if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
4224226633Sdim    return Error(Tok.getLoc(), "malformed memory operand");
4225218893Sdim
4226226633Sdim  if (Tok.is(AsmToken::RBrac)) {
4227226633Sdim    E = Tok.getLoc();
4228226633Sdim    Parser.Lex(); // Eat right bracket token.
4229198090Srdivacky
4230226633Sdim    Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
4231226633Sdim                                             0, 0, false, S, E));
4232218893Sdim
4233226633Sdim    // If there's a pre-indexing writeback marker, '!', just add it as a token
4234226633Sdim    // operand. It's rather odd, but syntactically valid.
4235226633Sdim    if (Parser.getTok().is(AsmToken::Exclaim)) {
4236226633Sdim      Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4237226633Sdim      Parser.Lex(); // Eat the '!'.
4238218893Sdim    }
4239198090Srdivacky
4240226633Sdim    return false;
4241226633Sdim  }
4242221345Sdim
4243226633Sdim  assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4244226633Sdim  Parser.Lex(); // Eat the comma.
4245218893Sdim
4246226633Sdim  // If we have a ':', it's an alignment specifier.
4247226633Sdim  if (Parser.getTok().is(AsmToken::Colon)) {
4248226633Sdim    Parser.Lex(); // Eat the ':'.
4249226633Sdim    E = Parser.getTok().getLoc();
4250198090Srdivacky
4251226633Sdim    const MCExpr *Expr;
4252226633Sdim    if (getParser().ParseExpression(Expr))
4253226633Sdim     return true;
4254198090Srdivacky
4255226633Sdim    // The expression has to be a constant. Memory references with relocations
4256226633Sdim    // don't come through here, as they use the <label> forms of the relevant
4257226633Sdim    // instructions.
4258226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4259226633Sdim    if (!CE)
4260226633Sdim      return Error (E, "constant expression expected");
4261218893Sdim
4262226633Sdim    unsigned Align = 0;
4263226633Sdim    switch (CE->getValue()) {
4264226633Sdim    default:
4265234353Sdim      return Error(E,
4266234353Sdim                   "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4267234353Sdim    case 16:  Align = 2; break;
4268234353Sdim    case 32:  Align = 4; break;
4269226633Sdim    case 64:  Align = 8; break;
4270226633Sdim    case 128: Align = 16; break;
4271226633Sdim    case 256: Align = 32; break;
4272226633Sdim    }
4273218893Sdim
4274226633Sdim    // Now we should have the closing ']'
4275226633Sdim    E = Parser.getTok().getLoc();
4276226633Sdim    if (Parser.getTok().isNot(AsmToken::RBrac))
4277226633Sdim      return Error(E, "']' expected");
4278226633Sdim    Parser.Lex(); // Eat right bracket token.
4279218893Sdim
4280226633Sdim    // Don't worry about range checking the value here. That's handled by
4281226633Sdim    // the is*() predicates.
4282226633Sdim    Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4283226633Sdim                                             ARM_AM::no_shift, 0, Align,
4284226633Sdim                                             false, S, E));
4285226633Sdim
4286226633Sdim    // If there's a pre-indexing writeback marker, '!', just add it as a token
4287226633Sdim    // operand.
4288226633Sdim    if (Parser.getTok().is(AsmToken::Exclaim)) {
4289226633Sdim      Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4290226633Sdim      Parser.Lex(); // Eat the '!'.
4291198090Srdivacky    }
4292198090Srdivacky
4293226633Sdim    return false;
4294198090Srdivacky  }
4295198090Srdivacky
4296226633Sdim  // If we have a '#', it's an immediate offset, else assume it's a register
4297234353Sdim  // offset. Be friendly and also accept a plain integer (without a leading
4298234353Sdim  // hash) for gas compatibility.
4299234353Sdim  if (Parser.getTok().is(AsmToken::Hash) ||
4300234353Sdim      Parser.getTok().is(AsmToken::Dollar) ||
4301234353Sdim      Parser.getTok().is(AsmToken::Integer)) {
4302234353Sdim    if (Parser.getTok().isNot(AsmToken::Integer))
4303234353Sdim      Parser.Lex(); // Eat the '#'.
4304226633Sdim    E = Parser.getTok().getLoc();
4305218893Sdim
4306226633Sdim    bool isNegative = getParser().getTok().is(AsmToken::Minus);
4307226633Sdim    const MCExpr *Offset;
4308226633Sdim    if (getParser().ParseExpression(Offset))
4309226633Sdim     return true;
4310198090Srdivacky
4311226633Sdim    // The expression has to be a constant. Memory references with relocations
4312226633Sdim    // don't come through here, as they use the <label> forms of the relevant
4313226633Sdim    // instructions.
4314226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4315226633Sdim    if (!CE)
4316226633Sdim      return Error (E, "constant expression expected");
4317226633Sdim
4318226633Sdim    // If the constant was #-0, represent it as INT32_MIN.
4319226633Sdim    int32_t Val = CE->getValue();
4320226633Sdim    if (isNegative && Val == 0)
4321226633Sdim      CE = MCConstantExpr::Create(INT32_MIN, getContext());
4322226633Sdim
4323226633Sdim    // Now we should have the closing ']'
4324226633Sdim    E = Parser.getTok().getLoc();
4325226633Sdim    if (Parser.getTok().isNot(AsmToken::RBrac))
4326226633Sdim      return Error(E, "']' expected");
4327226633Sdim    Parser.Lex(); // Eat right bracket token.
4328226633Sdim
4329226633Sdim    // Don't worry about range checking the value here. That's handled by
4330226633Sdim    // the is*() predicates.
4331226633Sdim    Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
4332226633Sdim                                             ARM_AM::no_shift, 0, 0,
4333226633Sdim                                             false, S, E));
4334226633Sdim
4335226633Sdim    // If there's a pre-indexing writeback marker, '!', just add it as a token
4336226633Sdim    // operand.
4337226633Sdim    if (Parser.getTok().is(AsmToken::Exclaim)) {
4338226633Sdim      Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4339226633Sdim      Parser.Lex(); // Eat the '!'.
4340206124Srdivacky    }
4341226633Sdim
4342226633Sdim    return false;
4343198892Srdivacky  }
4344218893Sdim
4345226633Sdim  // The register offset is optionally preceded by a '+' or '-'
4346226633Sdim  bool isNegative = false;
4347226633Sdim  if (Parser.getTok().is(AsmToken::Minus)) {
4348226633Sdim    isNegative = true;
4349226633Sdim    Parser.Lex(); // Eat the '-'.
4350226633Sdim  } else if (Parser.getTok().is(AsmToken::Plus)) {
4351226633Sdim    // Nothing to do.
4352226633Sdim    Parser.Lex(); // Eat the '+'.
4353226633Sdim  }
4354198892Srdivacky
4355226633Sdim  E = Parser.getTok().getLoc();
4356226633Sdim  int OffsetRegNum = tryParseRegister();
4357226633Sdim  if (OffsetRegNum == -1)
4358226633Sdim    return Error(E, "register expected");
4359226633Sdim
4360226633Sdim  // If there's a shift operator, handle it.
4361226633Sdim  ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
4362226633Sdim  unsigned ShiftImm = 0;
4363226633Sdim  if (Parser.getTok().is(AsmToken::Comma)) {
4364226633Sdim    Parser.Lex(); // Eat the ','.
4365226633Sdim    if (parseMemRegOffsetShift(ShiftType, ShiftImm))
4366226633Sdim      return true;
4367198892Srdivacky  }
4368218893Sdim
4369226633Sdim  // Now we should have the closing ']'
4370226633Sdim  E = Parser.getTok().getLoc();
4371226633Sdim  if (Parser.getTok().isNot(AsmToken::RBrac))
4372226633Sdim    return Error(E, "']' expected");
4373226633Sdim  Parser.Lex(); // Eat right bracket token.
4374198892Srdivacky
4375226633Sdim  Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
4376226633Sdim                                           ShiftType, ShiftImm, 0, isNegative,
4377226633Sdim                                           S, E));
4378226633Sdim
4379226633Sdim  // If there's a pre-indexing writeback marker, '!', just add it as a token
4380226633Sdim  // operand.
4381226633Sdim  if (Parser.getTok().is(AsmToken::Exclaim)) {
4382226633Sdim    Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4383226633Sdim    Parser.Lex(); // Eat the '!'.
4384198892Srdivacky  }
4385226633Sdim
4386198892Srdivacky  return false;
4387198892Srdivacky}
4388198892Srdivacky
4389226633Sdim/// parseMemRegOffsetShift - one of these two:
4390198090Srdivacky///   ( lsl | lsr | asr | ror ) , # shift_amount
4391198090Srdivacky///   rrx
4392226633Sdim/// return true if it parses a shift otherwise it returns false.
4393226633Sdimbool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4394226633Sdim                                          unsigned &Amount) {
4395226633Sdim  SMLoc Loc = Parser.getTok().getLoc();
4396202878Srdivacky  const AsmToken &Tok = Parser.getTok();
4397198090Srdivacky  if (Tok.isNot(AsmToken::Identifier))
4398198090Srdivacky    return true;
4399210299Sed  StringRef ShiftName = Tok.getString();
4400234353Sdim  if (ShiftName == "lsl" || ShiftName == "LSL" ||
4401234353Sdim      ShiftName == "asl" || ShiftName == "ASL")
4402221345Sdim    St = ARM_AM::lsl;
4403198090Srdivacky  else if (ShiftName == "lsr" || ShiftName == "LSR")
4404221345Sdim    St = ARM_AM::lsr;
4405198090Srdivacky  else if (ShiftName == "asr" || ShiftName == "ASR")
4406221345Sdim    St = ARM_AM::asr;
4407198090Srdivacky  else if (ShiftName == "ror" || ShiftName == "ROR")
4408221345Sdim    St = ARM_AM::ror;
4409198090Srdivacky  else if (ShiftName == "rrx" || ShiftName == "RRX")
4410221345Sdim    St = ARM_AM::rrx;
4411198090Srdivacky  else
4412226633Sdim    return Error(Loc, "illegal shift operator");
4413202878Srdivacky  Parser.Lex(); // Eat shift type token.
4414198090Srdivacky
4415226633Sdim  // rrx stands alone.
4416226633Sdim  Amount = 0;
4417226633Sdim  if (St != ARM_AM::rrx) {
4418226633Sdim    Loc = Parser.getTok().getLoc();
4419226633Sdim    // A '#' and a shift amount.
4420226633Sdim    const AsmToken &HashTok = Parser.getTok();
4421234353Sdim    if (HashTok.isNot(AsmToken::Hash) &&
4422234353Sdim        HashTok.isNot(AsmToken::Dollar))
4423226633Sdim      return Error(HashTok.getLoc(), "'#' expected");
4424226633Sdim    Parser.Lex(); // Eat hash token.
4425198090Srdivacky
4426226633Sdim    const MCExpr *Expr;
4427226633Sdim    if (getParser().ParseExpression(Expr))
4428226633Sdim      return true;
4429226633Sdim    // Range check the immediate.
4430226633Sdim    // lsl, ror: 0 <= imm <= 31
4431226633Sdim    // lsr, asr: 0 <= imm <= 32
4432226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4433226633Sdim    if (!CE)
4434226633Sdim      return Error(Loc, "shift amount must be an immediate");
4435226633Sdim    int64_t Imm = CE->getValue();
4436226633Sdim    if (Imm < 0 ||
4437226633Sdim        ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4438226633Sdim        ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4439226633Sdim      return Error(Loc, "immediate shift value out of range");
4440243830Sdim    // If <ShiftTy> #0, turn it into a no_shift.
4441243830Sdim    if (Imm == 0)
4442243830Sdim      St = ARM_AM::lsl;
4443243830Sdim    // For consistency, treat lsr #32 and asr #32 as having immediate value 0.
4444243830Sdim    if (Imm == 32)
4445243830Sdim      Imm = 0;
4446226633Sdim    Amount = Imm;
4447226633Sdim  }
4448198090Srdivacky
4449198090Srdivacky  return false;
4450198090Srdivacky}
4451198090Srdivacky
4452226633Sdim/// parseFPImm - A floating point immediate expression operand.
4453226633SdimARMAsmParser::OperandMatchResultTy ARMAsmParser::
4454226633SdimparseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4455234353Sdim  // Anything that can accept a floating point constant as an operand
4456234353Sdim  // needs to go through here, as the regular ParseExpression is
4457234353Sdim  // integer only.
4458234353Sdim  //
4459234353Sdim  // This routine still creates a generic Immediate operand, containing
4460234353Sdim  // a bitcast of the 64-bit floating point value. The various operands
4461234353Sdim  // that accept floats can check whether the value is valid for them
4462234353Sdim  // via the standard is*() predicates.
4463234353Sdim
4464226633Sdim  SMLoc S = Parser.getTok().getLoc();
4465226633Sdim
4466234353Sdim  if (Parser.getTok().isNot(AsmToken::Hash) &&
4467234353Sdim      Parser.getTok().isNot(AsmToken::Dollar))
4468226633Sdim    return MatchOperand_NoMatch;
4469234353Sdim
4470234353Sdim  // Disambiguate the VMOV forms that can accept an FP immediate.
4471234353Sdim  // vmov.f32 <sreg>, #imm
4472234353Sdim  // vmov.f64 <dreg>, #imm
4473234353Sdim  // vmov.f32 <dreg>, #imm  @ vector f32x2
4474234353Sdim  // vmov.f32 <qreg>, #imm  @ vector f32x4
4475234353Sdim  //
4476234353Sdim  // There are also the NEON VMOV instructions which expect an
4477234353Sdim  // integer constant. Make sure we don't try to parse an FPImm
4478234353Sdim  // for these:
4479234353Sdim  // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4480234353Sdim  ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4481234353Sdim  if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4482234353Sdim                           TyOp->getToken() != ".f64"))
4483234353Sdim    return MatchOperand_NoMatch;
4484234353Sdim
4485226633Sdim  Parser.Lex(); // Eat the '#'.
4486226633Sdim
4487226633Sdim  // Handle negation, as that still comes through as a separate token.
4488226633Sdim  bool isNegative = false;
4489226633Sdim  if (Parser.getTok().is(AsmToken::Minus)) {
4490226633Sdim    isNegative = true;
4491226633Sdim    Parser.Lex();
4492226633Sdim  }
4493226633Sdim  const AsmToken &Tok = Parser.getTok();
4494234353Sdim  SMLoc Loc = Tok.getLoc();
4495226633Sdim  if (Tok.is(AsmToken::Real)) {
4496234353Sdim    APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
4497226633Sdim    uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4498226633Sdim    // If we had a '-' in front, toggle the sign bit.
4499234353Sdim    IntVal ^= (uint64_t)isNegative << 31;
4500226633Sdim    Parser.Lex(); // Eat the token.
4501234353Sdim    Operands.push_back(ARMOperand::CreateImm(
4502234353Sdim          MCConstantExpr::Create(IntVal, getContext()),
4503234353Sdim          S, Parser.getTok().getLoc()));
4504226633Sdim    return MatchOperand_Success;
4505226633Sdim  }
4506234353Sdim  // Also handle plain integers. Instructions which allow floating point
4507234353Sdim  // immediates also allow a raw encoded 8-bit value.
4508226633Sdim  if (Tok.is(AsmToken::Integer)) {
4509226633Sdim    int64_t Val = Tok.getIntVal();
4510226633Sdim    Parser.Lex(); // Eat the token.
4511226633Sdim    if (Val > 255 || Val < 0) {
4512234353Sdim      Error(Loc, "encoded floating point value out of range");
4513226633Sdim      return MatchOperand_ParseFail;
4514226633Sdim    }
4515234353Sdim    double RealVal = ARM_AM::getFPImmFloat(Val);
4516234353Sdim    Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4517234353Sdim    Operands.push_back(ARMOperand::CreateImm(
4518234353Sdim        MCConstantExpr::Create(Val, getContext()), S,
4519234353Sdim        Parser.getTok().getLoc()));
4520226633Sdim    return MatchOperand_Success;
4521226633Sdim  }
4522226633Sdim
4523234353Sdim  Error(Loc, "invalid floating point immediate");
4524226633Sdim  return MatchOperand_ParseFail;
4525226633Sdim}
4526234353Sdim
4527198892Srdivacky/// Parse a arm instruction operand.  For now this parses the operand regardless
4528198892Srdivacky/// of the mnemonic.
4529226633Sdimbool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
4530218893Sdim                                StringRef Mnemonic) {
4531206124Srdivacky  SMLoc S, E;
4532218893Sdim
4533218893Sdim  // Check if the current operand has a custom associated parser, if so, try to
4534218893Sdim  // custom parse the operand, or fallback to the general approach.
4535218893Sdim  OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4536218893Sdim  if (ResTy == MatchOperand_Success)
4537218893Sdim    return false;
4538218893Sdim  // If there wasn't a custom match, try the generic matcher below. Otherwise,
4539218893Sdim  // there was a match, but an error occurred, in which case, just return that
4540218893Sdim  // the operand parsing failed.
4541218893Sdim  if (ResTy == MatchOperand_ParseFail)
4542218893Sdim    return true;
4543218893Sdim
4544198090Srdivacky  switch (getLexer().getKind()) {
4545218893Sdim  default:
4546218893Sdim    Error(Parser.getTok().getLoc(), "unexpected token in operand");
4547218893Sdim    return true;
4548224145Sdim  case AsmToken::Identifier: {
4549226633Sdim    if (!tryParseRegisterWithWriteBack(Operands))
4550198090Srdivacky      return false;
4551226633Sdim    int Res = tryParseShiftRegister(Operands);
4552224145Sdim    if (Res == 0) // success
4553221345Sdim      return false;
4554224145Sdim    else if (Res == -1) // irrecoverable error
4555224145Sdim      return true;
4556234353Sdim    // If this is VMRS, check for the apsr_nzcv operand.
4557234353Sdim    if (Mnemonic == "vmrs" &&
4558234353Sdim        Parser.getTok().getString().equals_lower("apsr_nzcv")) {
4559226633Sdim      S = Parser.getTok().getLoc();
4560226633Sdim      Parser.Lex();
4561234353Sdim      Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
4562226633Sdim      return false;
4563226633Sdim    }
4564218893Sdim
4565218893Sdim    // Fall though for the Identifier case that is not a register or a
4566218893Sdim    // special name.
4567224145Sdim  }
4568234353Sdim  case AsmToken::LParen:  // parenthesized expressions like (_strcmp-4)
4569218893Sdim  case AsmToken::Integer: // things like 1f and 2b as a branch targets
4570234353Sdim  case AsmToken::String:  // quoted label names.
4571218893Sdim  case AsmToken::Dot: {   // . as a branch target
4572198396Srdivacky    // This was not a register so parse other operands that start with an
4573198396Srdivacky    // identifier (like labels) as expressions and create them as immediates.
4574198396Srdivacky    const MCExpr *IdVal;
4575206124Srdivacky    S = Parser.getTok().getLoc();
4576198396Srdivacky    if (getParser().ParseExpression(IdVal))
4577198396Srdivacky      return true;
4578206124Srdivacky    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4579218893Sdim    Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4580198396Srdivacky    return false;
4581218893Sdim  }
4582198090Srdivacky  case AsmToken::LBrac:
4583226633Sdim    return parseMemory(Operands);
4584198090Srdivacky  case AsmToken::LCurly:
4585226633Sdim    return parseRegisterList(Operands);
4586234353Sdim  case AsmToken::Dollar:
4587226633Sdim  case AsmToken::Hash: {
4588198090Srdivacky    // #42 -> immediate.
4589206124Srdivacky    S = Parser.getTok().getLoc();
4590202878Srdivacky    Parser.Lex();
4591234982Sdim
4592234982Sdim    if (Parser.getTok().isNot(AsmToken::Colon)) {
4593234982Sdim      bool isNegative = Parser.getTok().is(AsmToken::Minus);
4594234982Sdim      const MCExpr *ImmVal;
4595234982Sdim      if (getParser().ParseExpression(ImmVal))
4596234982Sdim        return true;
4597234982Sdim      const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
4598234982Sdim      if (CE) {
4599234982Sdim        int32_t Val = CE->getValue();
4600234982Sdim        if (isNegative && Val == 0)
4601234982Sdim          ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
4602234982Sdim      }
4603234982Sdim      E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4604234982Sdim      Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4605234982Sdim      return false;
4606226633Sdim    }
4607234982Sdim    // w/ a ':' after the '#', it's just like a plain ':'.
4608234982Sdim    // FALLTHROUGH
4609226633Sdim  }
4610218893Sdim  case AsmToken::Colon: {
4611218893Sdim    // ":lower16:" and ":upper16:" expression prefixes
4612218893Sdim    // FIXME: Check it's an expression prefix,
4613218893Sdim    // e.g. (FOO - :lower16:BAR) isn't legal.
4614218893Sdim    ARMMCExpr::VariantKind RefKind;
4615226633Sdim    if (parsePrefix(RefKind))
4616218893Sdim      return true;
4617218893Sdim
4618218893Sdim    const MCExpr *SubExprVal;
4619218893Sdim    if (getParser().ParseExpression(SubExprVal))
4620218893Sdim      return true;
4621218893Sdim
4622218893Sdim    const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4623243830Sdim                                              getContext());
4624218893Sdim    E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4625218893Sdim    Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
4626218893Sdim    return false;
4627198090Srdivacky  }
4628218893Sdim  }
4629198090Srdivacky}
4630198090Srdivacky
4631226633Sdim// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
4632218893Sdim//  :lower16: and :upper16:.
4633226633Sdimbool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
4634218893Sdim  RefKind = ARMMCExpr::VK_ARM_None;
4635212904Sdim
4636218893Sdim  // :lower16: and :upper16: modifiers
4637218893Sdim  assert(getLexer().is(AsmToken::Colon) && "expected a :");
4638218893Sdim  Parser.Lex(); // Eat ':'
4639212904Sdim
4640218893Sdim  if (getLexer().isNot(AsmToken::Identifier)) {
4641218893Sdim    Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4642218893Sdim    return true;
4643218893Sdim  }
4644218893Sdim
4645218893Sdim  StringRef IDVal = Parser.getTok().getIdentifier();
4646218893Sdim  if (IDVal == "lower16") {
4647218893Sdim    RefKind = ARMMCExpr::VK_ARM_LO16;
4648218893Sdim  } else if (IDVal == "upper16") {
4649218893Sdim    RefKind = ARMMCExpr::VK_ARM_HI16;
4650218893Sdim  } else {
4651218893Sdim    Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4652218893Sdim    return true;
4653218893Sdim  }
4654218893Sdim  Parser.Lex();
4655218893Sdim
4656218893Sdim  if (getLexer().isNot(AsmToken::Colon)) {
4657218893Sdim    Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4658218893Sdim    return true;
4659218893Sdim  }
4660218893Sdim  Parser.Lex(); // Eat the last ':'
4661218893Sdim  return false;
4662218893Sdim}
4663218893Sdim
4664218893Sdim/// \brief Given a mnemonic, split out possible predication code and carry
4665218893Sdim/// setting letters to form a canonical mnemonic and flags.
4666218893Sdim//
4667218893Sdim// FIXME: Would be nice to autogen this.
4668226633Sdim// FIXME: This is a bit of a maze of special cases.
4669226633SdimStringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
4670226633Sdim                                      unsigned &PredicationCode,
4671226633Sdim                                      bool &CarrySetting,
4672226633Sdim                                      unsigned &ProcessorIMod,
4673226633Sdim                                      StringRef &ITMask) {
4674218893Sdim  PredicationCode = ARMCC::AL;
4675218893Sdim  CarrySetting = false;
4676218893Sdim  ProcessorIMod = 0;
4677218893Sdim
4678218893Sdim  // Ignore some mnemonics we know aren't predicated forms.
4679212904Sdim  //
4680218893Sdim  // FIXME: Would be nice to autogen this.
4681226633Sdim  if ((Mnemonic == "movs" && isThumb()) ||
4682226633Sdim      Mnemonic == "teq"   || Mnemonic == "vceq"   || Mnemonic == "svc"   ||
4683226633Sdim      Mnemonic == "mls"   || Mnemonic == "smmls"  || Mnemonic == "vcls"  ||
4684226633Sdim      Mnemonic == "vmls"  || Mnemonic == "vnmls"  || Mnemonic == "vacge" ||
4685226633Sdim      Mnemonic == "vcge"  || Mnemonic == "vclt"   || Mnemonic == "vacgt" ||
4686226633Sdim      Mnemonic == "vcgt"  || Mnemonic == "vcle"   || Mnemonic == "smlal" ||
4687226633Sdim      Mnemonic == "umaal" || Mnemonic == "umlal"  || Mnemonic == "vabal" ||
4688234353Sdim      Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4689234353Sdim      Mnemonic == "fmuls")
4690218893Sdim    return Mnemonic;
4691218893Sdim
4692224145Sdim  // First, split out any predication code. Ignore mnemonics we know aren't
4693224145Sdim  // predicated but do have a carry-set and so weren't caught above.
4694226633Sdim  if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
4695226633Sdim      Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
4696226633Sdim      Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
4697226633Sdim      Mnemonic != "sbcs" && Mnemonic != "rscs") {
4698224145Sdim    unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4699224145Sdim      .Case("eq", ARMCC::EQ)
4700224145Sdim      .Case("ne", ARMCC::NE)
4701224145Sdim      .Case("hs", ARMCC::HS)
4702224145Sdim      .Case("cs", ARMCC::HS)
4703224145Sdim      .Case("lo", ARMCC::LO)
4704224145Sdim      .Case("cc", ARMCC::LO)
4705224145Sdim      .Case("mi", ARMCC::MI)
4706224145Sdim      .Case("pl", ARMCC::PL)
4707224145Sdim      .Case("vs", ARMCC::VS)
4708224145Sdim      .Case("vc", ARMCC::VC)
4709224145Sdim      .Case("hi", ARMCC::HI)
4710224145Sdim      .Case("ls", ARMCC::LS)
4711224145Sdim      .Case("ge", ARMCC::GE)
4712224145Sdim      .Case("lt", ARMCC::LT)
4713224145Sdim      .Case("gt", ARMCC::GT)
4714224145Sdim      .Case("le", ARMCC::LE)
4715224145Sdim      .Case("al", ARMCC::AL)
4716224145Sdim      .Default(~0U);
4717224145Sdim    if (CC != ~0U) {
4718224145Sdim      Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4719224145Sdim      PredicationCode = CC;
4720224145Sdim    }
4721218893Sdim  }
4722212904Sdim
4723218893Sdim  // Next, determine if we have a carry setting bit. We explicitly ignore all
4724218893Sdim  // the instructions we know end in 's'.
4725218893Sdim  if (Mnemonic.endswith("s") &&
4726226633Sdim      !(Mnemonic == "cps" || Mnemonic == "mls" ||
4727226633Sdim        Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4728226633Sdim        Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4729226633Sdim        Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
4730234353Sdim        Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
4731234353Sdim        Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
4732234353Sdim        Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
4733234353Sdim        Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
4734234353Sdim        Mnemonic == "vfms" || Mnemonic == "vfnms" ||
4735226633Sdim        (Mnemonic == "movs" && isThumb()))) {
4736218893Sdim    Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4737218893Sdim    CarrySetting = true;
4738218893Sdim  }
4739198090Srdivacky
4740218893Sdim  // The "cps" instruction can have a interrupt mode operand which is glued into
4741218893Sdim  // the mnemonic. Check if this is the case, split it and parse the imod op
4742218893Sdim  if (Mnemonic.startswith("cps")) {
4743218893Sdim    // Split out any imod code.
4744218893Sdim    unsigned IMod =
4745218893Sdim      StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4746218893Sdim      .Case("ie", ARM_PROC::IE)
4747218893Sdim      .Case("id", ARM_PROC::ID)
4748218893Sdim      .Default(~0U);
4749218893Sdim    if (IMod != ~0U) {
4750218893Sdim      Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4751218893Sdim      ProcessorIMod = IMod;
4752218893Sdim    }
4753218893Sdim  }
4754212904Sdim
4755226633Sdim  // The "it" instruction has the condition mask on the end of the mnemonic.
4756226633Sdim  if (Mnemonic.startswith("it")) {
4757226633Sdim    ITMask = Mnemonic.slice(2, Mnemonic.size());
4758226633Sdim    Mnemonic = Mnemonic.slice(0, 2);
4759226633Sdim  }
4760226633Sdim
4761218893Sdim  return Mnemonic;
4762218893Sdim}
4763218893Sdim
4764218893Sdim/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4765218893Sdim/// inclusion of carry set or predication code operands.
4766218893Sdim//
4767218893Sdim// FIXME: It would be nice to autogen this.
4768218893Sdimvoid ARMAsmParser::
4769226633SdimgetMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
4770218893Sdim                      bool &CanAcceptPredicationCode) {
4771218893Sdim  if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4772218893Sdim      Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
4773226633Sdim      Mnemonic == "add" || Mnemonic == "adc" ||
4774218893Sdim      Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
4775226633Sdim      Mnemonic == "orr" || Mnemonic == "mvn" ||
4776218893Sdim      Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
4777226633Sdim      Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
4778234353Sdim      Mnemonic == "vfm" || Mnemonic == "vfnm" ||
4779226633Sdim      (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
4780226633Sdim                      Mnemonic == "mla" || Mnemonic == "smlal" ||
4781226633Sdim                      Mnemonic == "umlal" || Mnemonic == "umull"))) {
4782218893Sdim    CanAcceptCarrySet = true;
4783226633Sdim  } else
4784218893Sdim    CanAcceptCarrySet = false;
4785218893Sdim
4786218893Sdim  if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4787218893Sdim      Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4788218893Sdim      Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4789218893Sdim      Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
4790226633Sdim      Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4791226633Sdim      (Mnemonic == "clrex" && !isThumb()) ||
4792226633Sdim      (Mnemonic == "nop" && isThumbOne()) ||
4793226633Sdim      ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4794226633Sdim        Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4795226633Sdim        Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
4796226633Sdim      ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4797226633Sdim       !isThumb()) ||
4798226633Sdim      Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
4799218893Sdim    CanAcceptPredicationCode = false;
4800226633Sdim  } else
4801218893Sdim    CanAcceptPredicationCode = true;
4802218893Sdim
4803226633Sdim  if (isThumb()) {
4804218893Sdim    if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
4805224145Sdim        Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
4806218893Sdim      CanAcceptPredicationCode = false;
4807226633Sdim  }
4808218893Sdim}
4809218893Sdim
4810226633Sdimbool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4811226633Sdim                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4812226633Sdim  // FIXME: This is all horribly hacky. We really need a better way to deal
4813226633Sdim  // with optional operands like this in the matcher table.
4814226633Sdim
4815226633Sdim  // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4816226633Sdim  // another does not. Specifically, the MOVW instruction does not. So we
4817226633Sdim  // special case it here and remove the defaulted (non-setting) cc_out
4818226633Sdim  // operand if that's the instruction we're trying to match.
4819226633Sdim  //
4820226633Sdim  // We do this as post-processing of the explicit operands rather than just
4821226633Sdim  // conditionally adding the cc_out in the first place because we need
4822226633Sdim  // to check the type of the parsed immediate operand.
4823226633Sdim  if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
4824226633Sdim      !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4825226633Sdim      static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4826226633Sdim      static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4827226633Sdim    return true;
4828226633Sdim
4829226633Sdim  // Register-register 'add' for thumb does not have a cc_out operand
4830226633Sdim  // when there are only two register operands.
4831226633Sdim  if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4832226633Sdim      static_cast<ARMOperand*>(Operands[3])->isReg() &&
4833226633Sdim      static_cast<ARMOperand*>(Operands[4])->isReg() &&
4834226633Sdim      static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4835226633Sdim    return true;
4836226633Sdim  // Register-register 'add' for thumb does not have a cc_out operand
4837226633Sdim  // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4838226633Sdim  // have to check the immediate range here since Thumb2 has a variant
4839226633Sdim  // that can handle a different range and has a cc_out operand.
4840226633Sdim  if (((isThumb() && Mnemonic == "add") ||
4841226633Sdim       (isThumbTwo() && Mnemonic == "sub")) &&
4842226633Sdim      Operands.size() == 6 &&
4843226633Sdim      static_cast<ARMOperand*>(Operands[3])->isReg() &&
4844226633Sdim      static_cast<ARMOperand*>(Operands[4])->isReg() &&
4845226633Sdim      static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
4846226633Sdim      static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4847234353Sdim      ((Mnemonic == "add" &&static_cast<ARMOperand*>(Operands[5])->isReg()) ||
4848226633Sdim       static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
4849226633Sdim    return true;
4850226633Sdim  // For Thumb2, add/sub immediate does not have a cc_out operand for the
4851226633Sdim  // imm0_4095 variant. That's the least-preferred variant when
4852226633Sdim  // selecting via the generic "add" mnemonic, so to know that we
4853226633Sdim  // should remove the cc_out operand, we have to explicitly check that
4854226633Sdim  // it's not one of the other variants. Ugh.
4855226633Sdim  if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4856226633Sdim      Operands.size() == 6 &&
4857226633Sdim      static_cast<ARMOperand*>(Operands[3])->isReg() &&
4858226633Sdim      static_cast<ARMOperand*>(Operands[4])->isReg() &&
4859226633Sdim      static_cast<ARMOperand*>(Operands[5])->isImm()) {
4860226633Sdim    // Nest conditions rather than one big 'if' statement for readability.
4861226633Sdim    //
4862226633Sdim    // If either register is a high reg, it's either one of the SP
4863226633Sdim    // variants (handled above) or a 32-bit encoding, so we just
4864234353Sdim    // check against T3. If the second register is the PC, this is an
4865234353Sdim    // alternate form of ADR, which uses encoding T4, so check for that too.
4866226633Sdim    if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4867226633Sdim         !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
4868234353Sdim        static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
4869226633Sdim        static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4870226633Sdim      return false;
4871226633Sdim    // If both registers are low, we're in an IT block, and the immediate is
4872226633Sdim    // in range, we should use encoding T1 instead, which has a cc_out.
4873226633Sdim    if (inITBlock() &&
4874226633Sdim        isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
4875226633Sdim        isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4876226633Sdim        static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4877226633Sdim      return false;
4878226633Sdim
4879226633Sdim    // Otherwise, we use encoding T4, which does not have a cc_out
4880226633Sdim    // operand.
4881226633Sdim    return true;
4882226633Sdim  }
4883226633Sdim
4884226633Sdim  // The thumb2 multiply instruction doesn't have a CCOut register, so
4885226633Sdim  // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4886226633Sdim  // use the 16-bit encoding or not.
4887226633Sdim  if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4888226633Sdim      static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4889226633Sdim      static_cast<ARMOperand*>(Operands[3])->isReg() &&
4890226633Sdim      static_cast<ARMOperand*>(Operands[4])->isReg() &&
4891226633Sdim      static_cast<ARMOperand*>(Operands[5])->isReg() &&
4892226633Sdim      // If the registers aren't low regs, the destination reg isn't the
4893226633Sdim      // same as one of the source regs, or the cc_out operand is zero
4894226633Sdim      // outside of an IT block, we have to use the 32-bit encoding, so
4895226633Sdim      // remove the cc_out operand.
4896226633Sdim      (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4897226633Sdim       !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4898234353Sdim       !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
4899226633Sdim       !inITBlock() ||
4900226633Sdim       (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4901226633Sdim        static_cast<ARMOperand*>(Operands[5])->getReg() &&
4902226633Sdim        static_cast<ARMOperand*>(Operands[3])->getReg() !=
4903226633Sdim        static_cast<ARMOperand*>(Operands[4])->getReg())))
4904226633Sdim    return true;
4905226633Sdim
4906234353Sdim  // Also check the 'mul' syntax variant that doesn't specify an explicit
4907234353Sdim  // destination register.
4908234353Sdim  if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4909234353Sdim      static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4910234353Sdim      static_cast<ARMOperand*>(Operands[3])->isReg() &&
4911234353Sdim      static_cast<ARMOperand*>(Operands[4])->isReg() &&
4912234353Sdim      // If the registers aren't low regs  or the cc_out operand is zero
4913234353Sdim      // outside of an IT block, we have to use the 32-bit encoding, so
4914234353Sdim      // remove the cc_out operand.
4915234353Sdim      (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4916234353Sdim       !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4917234353Sdim       !inITBlock()))
4918234353Sdim    return true;
4919226633Sdim
4920226633Sdim
4921234353Sdim
4922226633Sdim  // Register-register 'add/sub' for thumb does not have a cc_out operand
4923226633Sdim  // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4924226633Sdim  // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4925226633Sdim  // right, this will result in better diagnostics (which operand is off)
4926226633Sdim  // anyway.
4927226633Sdim  if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4928226633Sdim      (Operands.size() == 5 || Operands.size() == 6) &&
4929226633Sdim      static_cast<ARMOperand*>(Operands[3])->isReg() &&
4930226633Sdim      static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
4931234353Sdim      static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4932234353Sdim      (static_cast<ARMOperand*>(Operands[4])->isImm() ||
4933234353Sdim       (Operands.size() == 6 &&
4934234353Sdim        static_cast<ARMOperand*>(Operands[5])->isImm())))
4935226633Sdim    return true;
4936226633Sdim
4937226633Sdim  return false;
4938226633Sdim}
4939226633Sdim
4940234353Sdimstatic bool isDataTypeToken(StringRef Tok) {
4941234353Sdim  return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4942234353Sdim    Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4943234353Sdim    Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4944234353Sdim    Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4945234353Sdim    Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4946234353Sdim    Tok == ".f" || Tok == ".d";
4947234353Sdim}
4948234353Sdim
4949234353Sdim// FIXME: This bit should probably be handled via an explicit match class
4950234353Sdim// in the .td files that matches the suffix instead of having it be
4951234353Sdim// a literal string token the way it is now.
4952234353Sdimstatic bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4953234353Sdim  return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4954234353Sdim}
4955234353Sdim
4956234353Sdimstatic void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
4957218893Sdim/// Parse an arm instruction mnemonic followed by its operands.
4958243830Sdimbool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
4959243830Sdim                                    SMLoc NameLoc,
4960218893Sdim                               SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4961234353Sdim  // Apply mnemonic aliases before doing anything else, as the destination
4962234353Sdim  // mnemnonic may include suffices and we want to handle them normally.
4963234353Sdim  // The generic tblgen'erated code does this later, at the start of
4964234353Sdim  // MatchInstructionImpl(), but that's too late for aliases that include
4965234353Sdim  // any sort of suffix.
4966234353Sdim  unsigned AvailableFeatures = getAvailableFeatures();
4967234353Sdim  applyMnemonicAliases(Name, AvailableFeatures);
4968234353Sdim
4969234353Sdim  // First check for the ARM-specific .req directive.
4970234353Sdim  if (Parser.getTok().is(AsmToken::Identifier) &&
4971234353Sdim      Parser.getTok().getIdentifier() == ".req") {
4972234353Sdim    parseDirectiveReq(Name, NameLoc);
4973234353Sdim    // We always return 'error' for this, as we're done with this
4974234353Sdim    // statement and don't need to match the 'instruction."
4975234353Sdim    return true;
4976234353Sdim  }
4977234353Sdim
4978218893Sdim  // Create the leading tokens for the mnemonic, split by '.' characters.
4979218893Sdim  size_t Start = 0, Next = Name.find('.');
4980226633Sdim  StringRef Mnemonic = Name.slice(Start, Next);
4981218893Sdim
4982218893Sdim  // Split out the predication code and carry setting flag from the mnemonic.
4983218893Sdim  unsigned PredicationCode;
4984218893Sdim  unsigned ProcessorIMod;
4985218893Sdim  bool CarrySetting;
4986226633Sdim  StringRef ITMask;
4987226633Sdim  Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
4988226633Sdim                           ProcessorIMod, ITMask);
4989218893Sdim
4990226633Sdim  // In Thumb1, only the branch (B) instruction can be predicated.
4991226633Sdim  if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4992226633Sdim    Parser.EatToEndOfStatement();
4993226633Sdim    return Error(NameLoc, "conditional execution not supported in Thumb1");
4994226633Sdim  }
4995218893Sdim
4996226633Sdim  Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4997226633Sdim
4998226633Sdim  // Handle the IT instruction ITMask. Convert it to a bitmask. This
4999226633Sdim  // is the mask as it will be for the IT encoding if the conditional
5000226633Sdim  // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
5001226633Sdim  // where the conditional bit0 is zero, the instruction post-processing
5002226633Sdim  // will adjust the mask accordingly.
5003226633Sdim  if (Mnemonic == "it") {
5004226633Sdim    SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
5005226633Sdim    if (ITMask.size() > 3) {
5006226633Sdim      Parser.EatToEndOfStatement();
5007226633Sdim      return Error(Loc, "too many conditions on IT instruction");
5008226633Sdim    }
5009226633Sdim    unsigned Mask = 8;
5010226633Sdim    for (unsigned i = ITMask.size(); i != 0; --i) {
5011226633Sdim      char pos = ITMask[i - 1];
5012226633Sdim      if (pos != 't' && pos != 'e') {
5013226633Sdim        Parser.EatToEndOfStatement();
5014226633Sdim        return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
5015226633Sdim      }
5016226633Sdim      Mask >>= 1;
5017226633Sdim      if (ITMask[i - 1] == 't')
5018226633Sdim        Mask |= 8;
5019226633Sdim    }
5020226633Sdim    Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
5021226633Sdim  }
5022226633Sdim
5023226633Sdim  // FIXME: This is all a pretty gross hack. We should automatically handle
5024226633Sdim  // optional operands like this via tblgen.
5025226633Sdim
5026218893Sdim  // Next, add the CCOut and ConditionCode operands, if needed.
5027218893Sdim  //
5028218893Sdim  // For mnemonics which can ever incorporate a carry setting bit or predication
5029218893Sdim  // code, our matching model involves us always generating CCOut and
5030218893Sdim  // ConditionCode operands to match the mnemonic "as written" and then we let
5031218893Sdim  // the matcher deal with finding the right instruction or generating an
5032218893Sdim  // appropriate error.
5033218893Sdim  bool CanAcceptCarrySet, CanAcceptPredicationCode;
5034226633Sdim  getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
5035218893Sdim
5036224145Sdim  // If we had a carry-set on an instruction that can't do that, issue an
5037224145Sdim  // error.
5038224145Sdim  if (!CanAcceptCarrySet && CarrySetting) {
5039224145Sdim    Parser.EatToEndOfStatement();
5040226633Sdim    return Error(NameLoc, "instruction '" + Mnemonic +
5041224145Sdim                 "' can not set flags, but 's' suffix specified");
5042224145Sdim  }
5043226633Sdim  // If we had a predication code on an instruction that can't do that, issue an
5044226633Sdim  // error.
5045226633Sdim  if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
5046226633Sdim    Parser.EatToEndOfStatement();
5047226633Sdim    return Error(NameLoc, "instruction '" + Mnemonic +
5048226633Sdim                 "' is not predicable, but condition code specified");
5049226633Sdim  }
5050224145Sdim
5051218893Sdim  // Add the carry setting operand, if necessary.
5052226633Sdim  if (CanAcceptCarrySet) {
5053226633Sdim    SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
5054218893Sdim    Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
5055226633Sdim                                               Loc));
5056226633Sdim  }
5057218893Sdim
5058218893Sdim  // Add the predication code operand, if necessary.
5059218893Sdim  if (CanAcceptPredicationCode) {
5060226633Sdim    SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
5061226633Sdim                                      CarrySetting);
5062218893Sdim    Operands.push_back(ARMOperand::CreateCondCode(
5063226633Sdim                         ARMCC::CondCodes(PredicationCode), Loc));
5064218893Sdim  }
5065218893Sdim
5066218893Sdim  // Add the processor imod operand, if necessary.
5067218893Sdim  if (ProcessorIMod) {
5068218893Sdim    Operands.push_back(ARMOperand::CreateImm(
5069218893Sdim          MCConstantExpr::Create(ProcessorIMod, getContext()),
5070218893Sdim                                 NameLoc, NameLoc));
5071218893Sdim  }
5072218893Sdim
5073212904Sdim  // Add the remaining tokens in the mnemonic.
5074212904Sdim  while (Next != StringRef::npos) {
5075212904Sdim    Start = Next;
5076212904Sdim    Next = Name.find('.', Start + 1);
5077218893Sdim    StringRef ExtraToken = Name.slice(Start, Next);
5078212904Sdim
5079234353Sdim    // Some NEON instructions have an optional datatype suffix that is
5080234353Sdim    // completely ignored. Check for that.
5081234353Sdim    if (isDataTypeToken(ExtraToken) &&
5082234353Sdim        doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
5083234353Sdim      continue;
5084234353Sdim
5085226633Sdim    if (ExtraToken != ".n") {
5086226633Sdim      SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5087226633Sdim      Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
5088226633Sdim    }
5089212904Sdim  }
5090212904Sdim
5091212904Sdim  // Read the remaining operands.
5092198090Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement)) {
5093198090Srdivacky    // Read the first operand.
5094226633Sdim    if (parseOperand(Operands, Mnemonic)) {
5095218893Sdim      Parser.EatToEndOfStatement();
5096218893Sdim      return true;
5097218893Sdim    }
5098198090Srdivacky
5099198090Srdivacky    while (getLexer().is(AsmToken::Comma)) {
5100202878Srdivacky      Parser.Lex();  // Eat the comma.
5101198090Srdivacky
5102198090Srdivacky      // Parse and remember the operand.
5103226633Sdim      if (parseOperand(Operands, Mnemonic)) {
5104218893Sdim        Parser.EatToEndOfStatement();
5105218893Sdim        return true;
5106218893Sdim      }
5107198090Srdivacky    }
5108198090Srdivacky  }
5109218893Sdim
5110218893Sdim  if (getLexer().isNot(AsmToken::EndOfStatement)) {
5111226633Sdim    SMLoc Loc = getLexer().getLoc();
5112218893Sdim    Parser.EatToEndOfStatement();
5113226633Sdim    return Error(Loc, "unexpected token in argument list");
5114218893Sdim  }
5115218893Sdim
5116218893Sdim  Parser.Lex(); // Consume the EndOfStatement
5117226633Sdim
5118226633Sdim  // Some instructions, mostly Thumb, have forms for the same mnemonic that
5119226633Sdim  // do and don't have a cc_out optional-def operand. With some spot-checks
5120226633Sdim  // of the operand list, we can figure out which variant we're trying to
5121226633Sdim  // parse and adjust accordingly before actually matching. We shouldn't ever
5122226633Sdim  // try to remove a cc_out operand that was explicitly set on the the
5123226633Sdim  // mnemonic, of course (CarrySetting == true). Reason number #317 the
5124226633Sdim  // table driven matcher doesn't fit well with the ARM instruction set.
5125226633Sdim  if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
5126226633Sdim    ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5127226633Sdim    Operands.erase(Operands.begin() + 1);
5128226633Sdim    delete Op;
5129226633Sdim  }
5130226633Sdim
5131226633Sdim  // ARM mode 'blx' need special handling, as the register operand version
5132226633Sdim  // is predicable, but the label operand version is not. So, we can't rely
5133226633Sdim  // on the Mnemonic based checking to correctly figure out when to put
5134226633Sdim  // a k_CondCode operand in the list. If we're trying to match the label
5135226633Sdim  // version, remove the k_CondCode operand here.
5136226633Sdim  if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5137226633Sdim      static_cast<ARMOperand*>(Operands[2])->isImm()) {
5138226633Sdim    ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5139226633Sdim    Operands.erase(Operands.begin() + 1);
5140226633Sdim    delete Op;
5141226633Sdim  }
5142226633Sdim
5143226633Sdim  // The vector-compare-to-zero instructions have a literal token "#0" at
5144226633Sdim  // the end that comes to here as an immediate operand. Convert it to a
5145226633Sdim  // token to play nicely with the matcher.
5146226633Sdim  if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5147226633Sdim      Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5148226633Sdim      static_cast<ARMOperand*>(Operands[5])->isImm()) {
5149226633Sdim    ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5150226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5151226633Sdim    if (CE && CE->getValue() == 0) {
5152226633Sdim      Operands.erase(Operands.begin() + 5);
5153226633Sdim      Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5154226633Sdim      delete Op;
5155226633Sdim    }
5156226633Sdim  }
5157226633Sdim  // VCMP{E} does the same thing, but with a different operand count.
5158226633Sdim  if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5159226633Sdim      static_cast<ARMOperand*>(Operands[4])->isImm()) {
5160226633Sdim    ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5161226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5162226633Sdim    if (CE && CE->getValue() == 0) {
5163226633Sdim      Operands.erase(Operands.begin() + 4);
5164226633Sdim      Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5165226633Sdim      delete Op;
5166226633Sdim    }
5167226633Sdim  }
5168226633Sdim  // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
5169234353Sdim  // end. Convert it to a token here. Take care not to convert those
5170234353Sdim  // that should hit the Thumb2 encoding.
5171226633Sdim  if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
5172234353Sdim      static_cast<ARMOperand*>(Operands[3])->isReg() &&
5173234353Sdim      static_cast<ARMOperand*>(Operands[4])->isReg() &&
5174226633Sdim      static_cast<ARMOperand*>(Operands[5])->isImm()) {
5175226633Sdim    ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5176226633Sdim    const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5177234353Sdim    if (CE && CE->getValue() == 0 &&
5178234353Sdim        (isThumbOne() ||
5179234353Sdim         // The cc_out operand matches the IT block.
5180234353Sdim         ((inITBlock() != CarrySetting) &&
5181234353Sdim         // Neither register operand is a high register.
5182234353Sdim         (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
5183234353Sdim          isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
5184226633Sdim      Operands.erase(Operands.begin() + 5);
5185226633Sdim      Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5186226633Sdim      delete Op;
5187226633Sdim    }
5188226633Sdim  }
5189226633Sdim
5190202375Srdivacky  return false;
5191198090Srdivacky}
5192198090Srdivacky
5193226633Sdim// Validate context-sensitive operand constraints.
5194226633Sdim
5195226633Sdim// return 'true' if register list contains non-low GPR registers,
5196226633Sdim// 'false' otherwise. If Reg is in the register list or is HiReg, set
5197226633Sdim// 'containsReg' to true.
5198226633Sdimstatic bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5199226633Sdim                                 unsigned HiReg, bool &containsReg) {
5200226633Sdim  containsReg = false;
5201226633Sdim  for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5202226633Sdim    unsigned OpReg = Inst.getOperand(i).getReg();
5203226633Sdim    if (OpReg == Reg)
5204226633Sdim      containsReg = true;
5205226633Sdim    // Anything other than a low register isn't legal here.
5206226633Sdim    if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5207226633Sdim      return true;
5208226633Sdim  }
5209226633Sdim  return false;
5210226633Sdim}
5211226633Sdim
5212226633Sdim// Check if the specified regisgter is in the register list of the inst,
5213226633Sdim// starting at the indicated operand number.
5214226633Sdimstatic bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5215226633Sdim  for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5216226633Sdim    unsigned OpReg = Inst.getOperand(i).getReg();
5217226633Sdim    if (OpReg == Reg)
5218226633Sdim      return true;
5219226633Sdim  }
5220226633Sdim  return false;
5221226633Sdim}
5222226633Sdim
5223226633Sdim// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5224226633Sdim// the ARMInsts array) instead. Getting that here requires awkward
5225226633Sdim// API changes, though. Better way?
5226226633Sdimnamespace llvm {
5227234353Sdimextern const MCInstrDesc ARMInsts[];
5228226633Sdim}
5229234353Sdimstatic const MCInstrDesc &getInstDesc(unsigned Opcode) {
5230226633Sdim  return ARMInsts[Opcode];
5231226633Sdim}
5232226633Sdim
5233226633Sdim// FIXME: We would really like to be able to tablegen'erate this.
5234218893Sdimbool ARMAsmParser::
5235226633SdimvalidateInstruction(MCInst &Inst,
5236226633Sdim                    const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5237234353Sdim  const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
5238226633Sdim  SMLoc Loc = Operands[0]->getStartLoc();
5239226633Sdim  // Check the IT block state first.
5240234353Sdim  // NOTE: BKPT instruction has the interesting property of being
5241234353Sdim  // allowed in IT blocks, but not being predicable.  It just always
5242226633Sdim  // executes.
5243234353Sdim  if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5244234353Sdim      Inst.getOpcode() != ARM::BKPT) {
5245226633Sdim    unsigned bit = 1;
5246226633Sdim    if (ITState.FirstCond)
5247226633Sdim      ITState.FirstCond = false;
5248226633Sdim    else
5249226633Sdim      bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
5250226633Sdim    // The instruction must be predicable.
5251226633Sdim    if (!MCID.isPredicable())
5252226633Sdim      return Error(Loc, "instructions in IT block must be predicable");
5253226633Sdim    unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5254226633Sdim    unsigned ITCond = bit ? ITState.Cond :
5255226633Sdim      ARMCC::getOppositeCondition(ITState.Cond);
5256226633Sdim    if (Cond != ITCond) {
5257226633Sdim      // Find the condition code Operand to get its SMLoc information.
5258226633Sdim      SMLoc CondLoc;
5259226633Sdim      for (unsigned i = 1; i < Operands.size(); ++i)
5260226633Sdim        if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5261226633Sdim          CondLoc = Operands[i]->getStartLoc();
5262226633Sdim      return Error(CondLoc, "incorrect condition in IT block; got '" +
5263226633Sdim                   StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5264226633Sdim                   "', but expected '" +
5265226633Sdim                   ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5266226633Sdim    }
5267226633Sdim  // Check for non-'al' condition codes outside of the IT block.
5268226633Sdim  } else if (isThumbTwo() && MCID.isPredicable() &&
5269226633Sdim             Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
5270226633Sdim             ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5271226633Sdim             Inst.getOpcode() != ARM::t2B)
5272226633Sdim    return Error(Loc, "predicated instructions must be in IT block");
5273226633Sdim
5274226633Sdim  switch (Inst.getOpcode()) {
5275226633Sdim  case ARM::LDRD:
5276226633Sdim  case ARM::LDRD_PRE:
5277226633Sdim  case ARM::LDRD_POST:
5278226633Sdim  case ARM::LDREXD: {
5279226633Sdim    // Rt2 must be Rt + 1.
5280239462Sdim    unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
5281239462Sdim    unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
5282226633Sdim    if (Rt2 != Rt + 1)
5283226633Sdim      return Error(Operands[3]->getStartLoc(),
5284226633Sdim                   "destination operands must be sequential");
5285226633Sdim    return false;
5286226633Sdim  }
5287226633Sdim  case ARM::STRD: {
5288226633Sdim    // Rt2 must be Rt + 1.
5289239462Sdim    unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
5290239462Sdim    unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
5291226633Sdim    if (Rt2 != Rt + 1)
5292226633Sdim      return Error(Operands[3]->getStartLoc(),
5293226633Sdim                   "source operands must be sequential");
5294226633Sdim    return false;
5295226633Sdim  }
5296226633Sdim  case ARM::STRD_PRE:
5297226633Sdim  case ARM::STRD_POST:
5298226633Sdim  case ARM::STREXD: {
5299226633Sdim    // Rt2 must be Rt + 1.
5300239462Sdim    unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg());
5301239462Sdim    unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(2).getReg());
5302226633Sdim    if (Rt2 != Rt + 1)
5303226633Sdim      return Error(Operands[3]->getStartLoc(),
5304226633Sdim                   "source operands must be sequential");
5305226633Sdim    return false;
5306226633Sdim  }
5307226633Sdim  case ARM::SBFX:
5308226633Sdim  case ARM::UBFX: {
5309226633Sdim    // width must be in range [1, 32-lsb]
5310226633Sdim    unsigned lsb = Inst.getOperand(2).getImm();
5311226633Sdim    unsigned widthm1 = Inst.getOperand(3).getImm();
5312226633Sdim    if (widthm1 >= 32 - lsb)
5313226633Sdim      return Error(Operands[5]->getStartLoc(),
5314226633Sdim                   "bitfield width must be in range [1,32-lsb]");
5315226633Sdim    return false;
5316226633Sdim  }
5317226633Sdim  case ARM::tLDMIA: {
5318226633Sdim    // If we're parsing Thumb2, the .w variant is available and handles
5319226633Sdim    // most cases that are normally illegal for a Thumb1 LDM
5320226633Sdim    // instruction. We'll make the transformation in processInstruction()
5321226633Sdim    // if necessary.
5322226633Sdim    //
5323226633Sdim    // Thumb LDM instructions are writeback iff the base register is not
5324226633Sdim    // in the register list.
5325226633Sdim    unsigned Rn = Inst.getOperand(0).getReg();
5326226633Sdim    bool hasWritebackToken =
5327226633Sdim      (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5328226633Sdim       static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
5329226633Sdim    bool listContainsBase;
5330226633Sdim    if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
5331226633Sdim      return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5332226633Sdim                   "registers must be in range r0-r7");
5333226633Sdim    // If we should have writeback, then there should be a '!' token.
5334226633Sdim    if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
5335226633Sdim      return Error(Operands[2]->getStartLoc(),
5336226633Sdim                   "writeback operator '!' expected");
5337226633Sdim    // If we should not have writeback, there must not be a '!'. This is
5338226633Sdim    // true even for the 32-bit wide encodings.
5339226633Sdim    if (listContainsBase && hasWritebackToken)
5340226633Sdim      return Error(Operands[3]->getStartLoc(),
5341226633Sdim                   "writeback operator '!' not allowed when base register "
5342226633Sdim                   "in register list");
5343226633Sdim
5344226633Sdim    break;
5345226633Sdim  }
5346226633Sdim  case ARM::t2LDMIA_UPD: {
5347226633Sdim    if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5348226633Sdim      return Error(Operands[4]->getStartLoc(),
5349226633Sdim                   "writeback operator '!' not allowed when base register "
5350226633Sdim                   "in register list");
5351226633Sdim    break;
5352226633Sdim  }
5353243830Sdim  case ARM::tMUL: {
5354243830Sdim    // The second source operand must be the same register as the destination
5355243830Sdim    // operand.
5356243830Sdim    //
5357243830Sdim    // In this case, we must directly check the parsed operands because the
5358243830Sdim    // cvtThumbMultiply() function is written in such a way that it guarantees
5359243830Sdim    // this first statement is always true for the new Inst.  Essentially, the
5360243830Sdim    // destination is unconditionally copied into the second source operand
5361243830Sdim    // without checking to see if it matches what we actually parsed.
5362243830Sdim    if (Operands.size() == 6 &&
5363243830Sdim        (((ARMOperand*)Operands[3])->getReg() !=
5364243830Sdim         ((ARMOperand*)Operands[5])->getReg()) &&
5365243830Sdim        (((ARMOperand*)Operands[3])->getReg() !=
5366243830Sdim         ((ARMOperand*)Operands[4])->getReg())) {
5367243830Sdim      return Error(Operands[3]->getStartLoc(),
5368243830Sdim                   "destination register must match source register");
5369243830Sdim    }
5370243830Sdim    break;
5371243830Sdim  }
5372234353Sdim  // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5373234353Sdim  // so only issue a diagnostic for thumb1. The instructions will be
5374234353Sdim  // switched to the t2 encodings in processInstruction() if necessary.
5375226633Sdim  case ARM::tPOP: {
5376226633Sdim    bool listContainsBase;
5377234353Sdim    if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5378234353Sdim        !isThumbTwo())
5379226633Sdim      return Error(Operands[2]->getStartLoc(),
5380226633Sdim                   "registers must be in range r0-r7 or pc");
5381226633Sdim    break;
5382226633Sdim  }
5383226633Sdim  case ARM::tPUSH: {
5384226633Sdim    bool listContainsBase;
5385234353Sdim    if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5386234353Sdim        !isThumbTwo())
5387226633Sdim      return Error(Operands[2]->getStartLoc(),
5388226633Sdim                   "registers must be in range r0-r7 or lr");
5389226633Sdim    break;
5390226633Sdim  }
5391226633Sdim  case ARM::tSTMIA_UPD: {
5392226633Sdim    bool listContainsBase;
5393226633Sdim    if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
5394226633Sdim      return Error(Operands[4]->getStartLoc(),
5395226633Sdim                   "registers must be in range r0-r7");
5396226633Sdim    break;
5397226633Sdim  }
5398239462Sdim  case ARM::tADDrSP: {
5399239462Sdim    // If the non-SP source operand and the destination operand are not the
5400239462Sdim    // same, we need thumb2 (for the wide encoding), or we have an error.
5401239462Sdim    if (!isThumbTwo() &&
5402239462Sdim        Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
5403239462Sdim      return Error(Operands[4]->getStartLoc(),
5404239462Sdim                   "source register must be the same as destination");
5405239462Sdim    }
5406239462Sdim    break;
5407226633Sdim  }
5408239462Sdim  }
5409226633Sdim
5410226633Sdim  return false;
5411226633Sdim}
5412226633Sdim
5413234353Sdimstatic unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
5414234353Sdim  switch(Opc) {
5415234353Sdim  default: llvm_unreachable("unexpected opcode!");
5416234353Sdim  // VST1LN
5417234353Sdim  case ARM::VST1LNdWB_fixed_Asm_8:  Spacing = 1; return ARM::VST1LNd8_UPD;
5418234353Sdim  case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5419234353Sdim  case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5420234353Sdim  case ARM::VST1LNdWB_register_Asm_8:  Spacing = 1; return ARM::VST1LNd8_UPD;
5421234353Sdim  case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5422234353Sdim  case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5423234353Sdim  case ARM::VST1LNdAsm_8:  Spacing = 1; return ARM::VST1LNd8;
5424234353Sdim  case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5425234353Sdim  case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
5426234353Sdim
5427234353Sdim  // VST2LN
5428234353Sdim  case ARM::VST2LNdWB_fixed_Asm_8:  Spacing = 1; return ARM::VST2LNd8_UPD;
5429234353Sdim  case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5430234353Sdim  case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5431234353Sdim  case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5432234353Sdim  case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
5433234353Sdim
5434234353Sdim  case ARM::VST2LNdWB_register_Asm_8:  Spacing = 1; return ARM::VST2LNd8_UPD;
5435234353Sdim  case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5436234353Sdim  case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5437234353Sdim  case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5438234353Sdim  case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
5439234353Sdim
5440234353Sdim  case ARM::VST2LNdAsm_8:  Spacing = 1; return ARM::VST2LNd8;
5441234353Sdim  case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5442234353Sdim  case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5443234353Sdim  case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5444234353Sdim  case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
5445234353Sdim
5446234353Sdim  // VST3LN
5447234353Sdim  case ARM::VST3LNdWB_fixed_Asm_8:  Spacing = 1; return ARM::VST3LNd8_UPD;
5448234353Sdim  case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5449234353Sdim  case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5450234353Sdim  case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5451234353Sdim  case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5452234353Sdim  case ARM::VST3LNdWB_register_Asm_8:  Spacing = 1; return ARM::VST3LNd8_UPD;
5453234353Sdim  case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5454234353Sdim  case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5455234353Sdim  case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5456234353Sdim  case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5457234353Sdim  case ARM::VST3LNdAsm_8:  Spacing = 1; return ARM::VST3LNd8;
5458234353Sdim  case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5459234353Sdim  case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5460234353Sdim  case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5461234353Sdim  case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
5462234353Sdim
5463234353Sdim  // VST3
5464234353Sdim  case ARM::VST3dWB_fixed_Asm_8:  Spacing = 1; return ARM::VST3d8_UPD;
5465234353Sdim  case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5466234353Sdim  case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5467234353Sdim  case ARM::VST3qWB_fixed_Asm_8:  Spacing = 2; return ARM::VST3q8_UPD;
5468234353Sdim  case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5469234353Sdim  case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5470234353Sdim  case ARM::VST3dWB_register_Asm_8:  Spacing = 1; return ARM::VST3d8_UPD;
5471234353Sdim  case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5472234353Sdim  case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5473234353Sdim  case ARM::VST3qWB_register_Asm_8:  Spacing = 2; return ARM::VST3q8_UPD;
5474234353Sdim  case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5475234353Sdim  case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5476234353Sdim  case ARM::VST3dAsm_8:  Spacing = 1; return ARM::VST3d8;
5477234353Sdim  case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5478234353Sdim  case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5479234353Sdim  case ARM::VST3qAsm_8:  Spacing = 2; return ARM::VST3q8;
5480234353Sdim  case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5481234353Sdim  case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
5482234353Sdim
5483234353Sdim  // VST4LN
5484234353Sdim  case ARM::VST4LNdWB_fixed_Asm_8:  Spacing = 1; return ARM::VST4LNd8_UPD;
5485234353Sdim  case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5486234353Sdim  case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5487234353Sdim  case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5488234353Sdim  case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5489234353Sdim  case ARM::VST4LNdWB_register_Asm_8:  Spacing = 1; return ARM::VST4LNd8_UPD;
5490234353Sdim  case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5491234353Sdim  case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5492234353Sdim  case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5493234353Sdim  case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5494234353Sdim  case ARM::VST4LNdAsm_8:  Spacing = 1; return ARM::VST4LNd8;
5495234353Sdim  case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5496234353Sdim  case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5497234353Sdim  case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5498234353Sdim  case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5499234353Sdim
5500234353Sdim  // VST4
5501234353Sdim  case ARM::VST4dWB_fixed_Asm_8:  Spacing = 1; return ARM::VST4d8_UPD;
5502234353Sdim  case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5503234353Sdim  case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5504234353Sdim  case ARM::VST4qWB_fixed_Asm_8:  Spacing = 2; return ARM::VST4q8_UPD;
5505234353Sdim  case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5506234353Sdim  case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5507234353Sdim  case ARM::VST4dWB_register_Asm_8:  Spacing = 1; return ARM::VST4d8_UPD;
5508234353Sdim  case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5509234353Sdim  case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5510234353Sdim  case ARM::VST4qWB_register_Asm_8:  Spacing = 2; return ARM::VST4q8_UPD;
5511234353Sdim  case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5512234353Sdim  case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5513234353Sdim  case ARM::VST4dAsm_8:  Spacing = 1; return ARM::VST4d8;
5514234353Sdim  case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5515234353Sdim  case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5516234353Sdim  case ARM::VST4qAsm_8:  Spacing = 2; return ARM::VST4q8;
5517234353Sdim  case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5518234353Sdim  case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
5519234353Sdim  }
5520234353Sdim}
5521234353Sdim
5522234353Sdimstatic unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
5523234353Sdim  switch(Opc) {
5524234353Sdim  default: llvm_unreachable("unexpected opcode!");
5525234353Sdim  // VLD1LN
5526234353Sdim  case ARM::VLD1LNdWB_fixed_Asm_8:  Spacing = 1; return ARM::VLD1LNd8_UPD;
5527234353Sdim  case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5528234353Sdim  case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5529234353Sdim  case ARM::VLD1LNdWB_register_Asm_8:  Spacing = 1; return ARM::VLD1LNd8_UPD;
5530234353Sdim  case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5531234353Sdim  case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5532234353Sdim  case ARM::VLD1LNdAsm_8:  Spacing = 1; return ARM::VLD1LNd8;
5533234353Sdim  case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5534234353Sdim  case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
5535234353Sdim
5536234353Sdim  // VLD2LN
5537234353Sdim  case ARM::VLD2LNdWB_fixed_Asm_8:  Spacing = 1; return ARM::VLD2LNd8_UPD;
5538234353Sdim  case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5539234353Sdim  case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5540234353Sdim  case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5541234353Sdim  case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5542234353Sdim  case ARM::VLD2LNdWB_register_Asm_8:  Spacing = 1; return ARM::VLD2LNd8_UPD;
5543234353Sdim  case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5544234353Sdim  case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5545234353Sdim  case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5546234353Sdim  case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5547234353Sdim  case ARM::VLD2LNdAsm_8:  Spacing = 1; return ARM::VLD2LNd8;
5548234353Sdim  case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5549234353Sdim  case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5550234353Sdim  case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5551234353Sdim  case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
5552234353Sdim
5553234353Sdim  // VLD3DUP
5554234353Sdim  case ARM::VLD3DUPdWB_fixed_Asm_8:  Spacing = 1; return ARM::VLD3DUPd8_UPD;
5555234353Sdim  case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5556234353Sdim  case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5557234353Sdim  case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5558234353Sdim  case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5559234353Sdim  case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5560234353Sdim  case ARM::VLD3DUPdWB_register_Asm_8:  Spacing = 1; return ARM::VLD3DUPd8_UPD;
5561234353Sdim  case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5562234353Sdim  case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5563234353Sdim  case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5564234353Sdim  case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5565234353Sdim  case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5566234353Sdim  case ARM::VLD3DUPdAsm_8:  Spacing = 1; return ARM::VLD3DUPd8;
5567234353Sdim  case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5568234353Sdim  case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5569234353Sdim  case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5570234353Sdim  case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5571234353Sdim  case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5572234353Sdim
5573234353Sdim  // VLD3LN
5574234353Sdim  case ARM::VLD3LNdWB_fixed_Asm_8:  Spacing = 1; return ARM::VLD3LNd8_UPD;
5575234353Sdim  case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5576234353Sdim  case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5577234353Sdim  case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5578234353Sdim  case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5579234353Sdim  case ARM::VLD3LNdWB_register_Asm_8:  Spacing = 1; return ARM::VLD3LNd8_UPD;
5580234353Sdim  case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5581234353Sdim  case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5582234353Sdim  case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5583234353Sdim  case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5584234353Sdim  case ARM::VLD3LNdAsm_8:  Spacing = 1; return ARM::VLD3LNd8;
5585234353Sdim  case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5586234353Sdim  case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5587234353Sdim  case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5588234353Sdim  case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
5589234353Sdim
5590234353Sdim  // VLD3
5591234353Sdim  case ARM::VLD3dWB_fixed_Asm_8:  Spacing = 1; return ARM::VLD3d8_UPD;
5592234353Sdim  case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5593234353Sdim  case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5594234353Sdim  case ARM::VLD3qWB_fixed_Asm_8:  Spacing = 2; return ARM::VLD3q8_UPD;
5595234353Sdim  case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5596234353Sdim  case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5597234353Sdim  case ARM::VLD3dWB_register_Asm_8:  Spacing = 1; return ARM::VLD3d8_UPD;
5598234353Sdim  case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5599234353Sdim  case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5600234353Sdim  case ARM::VLD3qWB_register_Asm_8:  Spacing = 2; return ARM::VLD3q8_UPD;
5601234353Sdim  case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5602234353Sdim  case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5603234353Sdim  case ARM::VLD3dAsm_8:  Spacing = 1; return ARM::VLD3d8;
5604234353Sdim  case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5605234353Sdim  case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5606234353Sdim  case ARM::VLD3qAsm_8:  Spacing = 2; return ARM::VLD3q8;
5607234353Sdim  case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5608234353Sdim  case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
5609234353Sdim
5610234353Sdim  // VLD4LN
5611234353Sdim  case ARM::VLD4LNdWB_fixed_Asm_8:  Spacing = 1; return ARM::VLD4LNd8_UPD;
5612234353Sdim  case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5613234353Sdim  case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5614234353Sdim  case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5615234353Sdim  case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5616234353Sdim  case ARM::VLD4LNdWB_register_Asm_8:  Spacing = 1; return ARM::VLD4LNd8_UPD;
5617234353Sdim  case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5618234353Sdim  case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5619234353Sdim  case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5620234353Sdim  case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5621234353Sdim  case ARM::VLD4LNdAsm_8:  Spacing = 1; return ARM::VLD4LNd8;
5622234353Sdim  case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5623234353Sdim  case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5624234353Sdim  case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5625234353Sdim  case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5626234353Sdim
5627234353Sdim  // VLD4DUP
5628234353Sdim  case ARM::VLD4DUPdWB_fixed_Asm_8:  Spacing = 1; return ARM::VLD4DUPd8_UPD;
5629234353Sdim  case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5630234353Sdim  case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5631234353Sdim  case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5632234353Sdim  case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5633234353Sdim  case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5634234353Sdim  case ARM::VLD4DUPdWB_register_Asm_8:  Spacing = 1; return ARM::VLD4DUPd8_UPD;
5635234353Sdim  case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5636234353Sdim  case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5637234353Sdim  case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5638234353Sdim  case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5639234353Sdim  case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5640234353Sdim  case ARM::VLD4DUPdAsm_8:  Spacing = 1; return ARM::VLD4DUPd8;
5641234353Sdim  case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5642234353Sdim  case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5643234353Sdim  case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5644234353Sdim  case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5645234353Sdim  case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5646234353Sdim
5647234353Sdim  // VLD4
5648234353Sdim  case ARM::VLD4dWB_fixed_Asm_8:  Spacing = 1; return ARM::VLD4d8_UPD;
5649234353Sdim  case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5650234353Sdim  case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5651234353Sdim  case ARM::VLD4qWB_fixed_Asm_8:  Spacing = 2; return ARM::VLD4q8_UPD;
5652234353Sdim  case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5653234353Sdim  case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5654234353Sdim  case ARM::VLD4dWB_register_Asm_8:  Spacing = 1; return ARM::VLD4d8_UPD;
5655234353Sdim  case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5656234353Sdim  case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5657234353Sdim  case ARM::VLD4qWB_register_Asm_8:  Spacing = 2; return ARM::VLD4q8_UPD;
5658234353Sdim  case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5659234353Sdim  case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5660234353Sdim  case ARM::VLD4dAsm_8:  Spacing = 1; return ARM::VLD4d8;
5661234353Sdim  case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5662234353Sdim  case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5663234353Sdim  case ARM::VLD4qAsm_8:  Spacing = 2; return ARM::VLD4q8;
5664234353Sdim  case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5665234353Sdim  case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
5666234353Sdim  }
5667234353Sdim}
5668234353Sdim
5669234353Sdimbool ARMAsmParser::
5670226633SdimprocessInstruction(MCInst &Inst,
5671226633Sdim                   const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5672226633Sdim  switch (Inst.getOpcode()) {
5673243830Sdim  // Alias for alternate form of 'ADR Rd, #imm' instruction.
5674243830Sdim  case ARM::ADDri: {
5675243830Sdim    if (Inst.getOperand(1).getReg() != ARM::PC ||
5676243830Sdim        Inst.getOperand(5).getReg() != 0)
5677243830Sdim      return false;
5678243830Sdim    MCInst TmpInst;
5679243830Sdim    TmpInst.setOpcode(ARM::ADR);
5680243830Sdim    TmpInst.addOperand(Inst.getOperand(0));
5681243830Sdim    TmpInst.addOperand(Inst.getOperand(2));
5682243830Sdim    TmpInst.addOperand(Inst.getOperand(3));
5683243830Sdim    TmpInst.addOperand(Inst.getOperand(4));
5684243830Sdim    Inst = TmpInst;
5685243830Sdim    return true;
5686243830Sdim  }
5687234353Sdim  // Aliases for alternate PC+imm syntax of LDR instructions.
5688234353Sdim  case ARM::t2LDRpcrel:
5689234353Sdim    Inst.setOpcode(ARM::t2LDRpci);
5690234353Sdim    return true;
5691234353Sdim  case ARM::t2LDRBpcrel:
5692234353Sdim    Inst.setOpcode(ARM::t2LDRBpci);
5693234353Sdim    return true;
5694234353Sdim  case ARM::t2LDRHpcrel:
5695234353Sdim    Inst.setOpcode(ARM::t2LDRHpci);
5696234353Sdim    return true;
5697234353Sdim  case ARM::t2LDRSBpcrel:
5698234353Sdim    Inst.setOpcode(ARM::t2LDRSBpci);
5699234353Sdim    return true;
5700234353Sdim  case ARM::t2LDRSHpcrel:
5701234353Sdim    Inst.setOpcode(ARM::t2LDRSHpci);
5702234353Sdim    return true;
5703234353Sdim  // Handle NEON VST complex aliases.
5704234353Sdim  case ARM::VST1LNdWB_register_Asm_8:
5705234353Sdim  case ARM::VST1LNdWB_register_Asm_16:
5706234353Sdim  case ARM::VST1LNdWB_register_Asm_32: {
5707234353Sdim    MCInst TmpInst;
5708234353Sdim    // Shuffle the operands around so the lane index operand is in the
5709234353Sdim    // right place.
5710234353Sdim    unsigned Spacing;
5711234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5712234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5713234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5714234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5715234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rm
5716234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5717234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5718234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5719234353Sdim    TmpInst.addOperand(Inst.getOperand(6));
5720234353Sdim    Inst = TmpInst;
5721234353Sdim    return true;
5722234353Sdim  }
5723234353Sdim
5724234353Sdim  case ARM::VST2LNdWB_register_Asm_8:
5725234353Sdim  case ARM::VST2LNdWB_register_Asm_16:
5726234353Sdim  case ARM::VST2LNdWB_register_Asm_32:
5727234353Sdim  case ARM::VST2LNqWB_register_Asm_16:
5728234353Sdim  case ARM::VST2LNqWB_register_Asm_32: {
5729234353Sdim    MCInst TmpInst;
5730234353Sdim    // Shuffle the operands around so the lane index operand is in the
5731234353Sdim    // right place.
5732234353Sdim    unsigned Spacing;
5733234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5734234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5735234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5736234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5737234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rm
5738234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5739234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5740234353Sdim                                            Spacing));
5741234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5742234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5743234353Sdim    TmpInst.addOperand(Inst.getOperand(6));
5744234353Sdim    Inst = TmpInst;
5745234353Sdim    return true;
5746234353Sdim  }
5747234353Sdim
5748234353Sdim  case ARM::VST3LNdWB_register_Asm_8:
5749234353Sdim  case ARM::VST3LNdWB_register_Asm_16:
5750234353Sdim  case ARM::VST3LNdWB_register_Asm_32:
5751234353Sdim  case ARM::VST3LNqWB_register_Asm_16:
5752234353Sdim  case ARM::VST3LNqWB_register_Asm_32: {
5753234353Sdim    MCInst TmpInst;
5754234353Sdim    // Shuffle the operands around so the lane index operand is in the
5755234353Sdim    // right place.
5756234353Sdim    unsigned Spacing;
5757234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5758234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5759234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5760234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5761234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rm
5762234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5763234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5764234353Sdim                                            Spacing));
5765234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5766234353Sdim                                            Spacing * 2));
5767234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5768234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5769234353Sdim    TmpInst.addOperand(Inst.getOperand(6));
5770234353Sdim    Inst = TmpInst;
5771234353Sdim    return true;
5772234353Sdim  }
5773234353Sdim
5774234353Sdim  case ARM::VST4LNdWB_register_Asm_8:
5775234353Sdim  case ARM::VST4LNdWB_register_Asm_16:
5776234353Sdim  case ARM::VST4LNdWB_register_Asm_32:
5777234353Sdim  case ARM::VST4LNqWB_register_Asm_16:
5778234353Sdim  case ARM::VST4LNqWB_register_Asm_32: {
5779234353Sdim    MCInst TmpInst;
5780234353Sdim    // Shuffle the operands around so the lane index operand is in the
5781234353Sdim    // right place.
5782234353Sdim    unsigned Spacing;
5783234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5784234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5785234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5786234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5787234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rm
5788234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5789234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5790234353Sdim                                            Spacing));
5791234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5792234353Sdim                                            Spacing * 2));
5793234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5794234353Sdim                                            Spacing * 3));
5795234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5796234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5797234353Sdim    TmpInst.addOperand(Inst.getOperand(6));
5798234353Sdim    Inst = TmpInst;
5799234353Sdim    return true;
5800234353Sdim  }
5801234353Sdim
5802234353Sdim  case ARM::VST1LNdWB_fixed_Asm_8:
5803234353Sdim  case ARM::VST1LNdWB_fixed_Asm_16:
5804234353Sdim  case ARM::VST1LNdWB_fixed_Asm_32: {
5805234353Sdim    MCInst TmpInst;
5806234353Sdim    // Shuffle the operands around so the lane index operand is in the
5807234353Sdim    // right place.
5808234353Sdim    unsigned Spacing;
5809234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5810234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5811234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5812234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5813234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5814234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5815234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5816234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5817234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
5818234353Sdim    Inst = TmpInst;
5819234353Sdim    return true;
5820234353Sdim  }
5821234353Sdim
5822234353Sdim  case ARM::VST2LNdWB_fixed_Asm_8:
5823234353Sdim  case ARM::VST2LNdWB_fixed_Asm_16:
5824234353Sdim  case ARM::VST2LNdWB_fixed_Asm_32:
5825234353Sdim  case ARM::VST2LNqWB_fixed_Asm_16:
5826234353Sdim  case ARM::VST2LNqWB_fixed_Asm_32: {
5827234353Sdim    MCInst TmpInst;
5828234353Sdim    // Shuffle the operands around so the lane index operand is in the
5829234353Sdim    // right place.
5830234353Sdim    unsigned Spacing;
5831234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5832234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5833234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5834234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5835234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5836234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5837234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5838234353Sdim                                            Spacing));
5839234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5840234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5841234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
5842234353Sdim    Inst = TmpInst;
5843234353Sdim    return true;
5844234353Sdim  }
5845234353Sdim
5846234353Sdim  case ARM::VST3LNdWB_fixed_Asm_8:
5847234353Sdim  case ARM::VST3LNdWB_fixed_Asm_16:
5848234353Sdim  case ARM::VST3LNdWB_fixed_Asm_32:
5849234353Sdim  case ARM::VST3LNqWB_fixed_Asm_16:
5850234353Sdim  case ARM::VST3LNqWB_fixed_Asm_32: {
5851234353Sdim    MCInst TmpInst;
5852234353Sdim    // Shuffle the operands around so the lane index operand is in the
5853234353Sdim    // right place.
5854234353Sdim    unsigned Spacing;
5855234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5856234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5857234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5858234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5859234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5860234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5861234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5862234353Sdim                                            Spacing));
5863234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5864234353Sdim                                            Spacing * 2));
5865234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5866234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5867234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
5868234353Sdim    Inst = TmpInst;
5869234353Sdim    return true;
5870234353Sdim  }
5871234353Sdim
5872234353Sdim  case ARM::VST4LNdWB_fixed_Asm_8:
5873234353Sdim  case ARM::VST4LNdWB_fixed_Asm_16:
5874234353Sdim  case ARM::VST4LNdWB_fixed_Asm_32:
5875234353Sdim  case ARM::VST4LNqWB_fixed_Asm_16:
5876234353Sdim  case ARM::VST4LNqWB_fixed_Asm_32: {
5877234353Sdim    MCInst TmpInst;
5878234353Sdim    // Shuffle the operands around so the lane index operand is in the
5879234353Sdim    // right place.
5880234353Sdim    unsigned Spacing;
5881234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5882234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5883234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5884234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5885234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5886234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5887234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5888234353Sdim                                            Spacing));
5889234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5890234353Sdim                                            Spacing * 2));
5891234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5892234353Sdim                                            Spacing * 3));
5893234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5894234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5895234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
5896234353Sdim    Inst = TmpInst;
5897234353Sdim    return true;
5898234353Sdim  }
5899234353Sdim
5900234353Sdim  case ARM::VST1LNdAsm_8:
5901234353Sdim  case ARM::VST1LNdAsm_16:
5902234353Sdim  case ARM::VST1LNdAsm_32: {
5903234353Sdim    MCInst TmpInst;
5904234353Sdim    // Shuffle the operands around so the lane index operand is in the
5905234353Sdim    // right place.
5906234353Sdim    unsigned Spacing;
5907234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5908234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5909234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5910234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5911234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5912234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5913234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
5914234353Sdim    Inst = TmpInst;
5915234353Sdim    return true;
5916234353Sdim  }
5917234353Sdim
5918234353Sdim  case ARM::VST2LNdAsm_8:
5919234353Sdim  case ARM::VST2LNdAsm_16:
5920234353Sdim  case ARM::VST2LNdAsm_32:
5921234353Sdim  case ARM::VST2LNqAsm_16:
5922234353Sdim  case ARM::VST2LNqAsm_32: {
5923234353Sdim    MCInst TmpInst;
5924234353Sdim    // Shuffle the operands around so the lane index operand is in the
5925234353Sdim    // right place.
5926234353Sdim    unsigned Spacing;
5927234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5928234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5929234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5930234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5931234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5932234353Sdim                                            Spacing));
5933234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5934234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5935234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
5936234353Sdim    Inst = TmpInst;
5937234353Sdim    return true;
5938234353Sdim  }
5939234353Sdim
5940234353Sdim  case ARM::VST3LNdAsm_8:
5941234353Sdim  case ARM::VST3LNdAsm_16:
5942234353Sdim  case ARM::VST3LNdAsm_32:
5943234353Sdim  case ARM::VST3LNqAsm_16:
5944234353Sdim  case ARM::VST3LNqAsm_32: {
5945234353Sdim    MCInst TmpInst;
5946234353Sdim    // Shuffle the operands around so the lane index operand is in the
5947234353Sdim    // right place.
5948234353Sdim    unsigned Spacing;
5949234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5950234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5951234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5952234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5953234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5954234353Sdim                                            Spacing));
5955234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5956234353Sdim                                            Spacing * 2));
5957234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5958234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5959234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
5960234353Sdim    Inst = TmpInst;
5961234353Sdim    return true;
5962234353Sdim  }
5963234353Sdim
5964234353Sdim  case ARM::VST4LNdAsm_8:
5965234353Sdim  case ARM::VST4LNdAsm_16:
5966234353Sdim  case ARM::VST4LNdAsm_32:
5967234353Sdim  case ARM::VST4LNqAsm_16:
5968234353Sdim  case ARM::VST4LNqAsm_32: {
5969234353Sdim    MCInst TmpInst;
5970234353Sdim    // Shuffle the operands around so the lane index operand is in the
5971234353Sdim    // right place.
5972234353Sdim    unsigned Spacing;
5973234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5974234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
5975234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
5976234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
5977234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5978234353Sdim                                            Spacing));
5979234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5980234353Sdim                                            Spacing * 2));
5981234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5982234353Sdim                                            Spacing * 3));
5983234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
5984234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5985234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
5986234353Sdim    Inst = TmpInst;
5987234353Sdim    return true;
5988234353Sdim  }
5989234353Sdim
5990234353Sdim  // Handle NEON VLD complex aliases.
5991234353Sdim  case ARM::VLD1LNdWB_register_Asm_8:
5992234353Sdim  case ARM::VLD1LNdWB_register_Asm_16:
5993234353Sdim  case ARM::VLD1LNdWB_register_Asm_32: {
5994234353Sdim    MCInst TmpInst;
5995234353Sdim    // Shuffle the operands around so the lane index operand is in the
5996234353Sdim    // right place.
5997234353Sdim    unsigned Spacing;
5998234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
5999234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6000234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6001234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6002234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6003234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rm
6004234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6005234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6006234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6007234353Sdim    TmpInst.addOperand(Inst.getOperand(6));
6008234353Sdim    Inst = TmpInst;
6009234353Sdim    return true;
6010234353Sdim  }
6011234353Sdim
6012234353Sdim  case ARM::VLD2LNdWB_register_Asm_8:
6013234353Sdim  case ARM::VLD2LNdWB_register_Asm_16:
6014234353Sdim  case ARM::VLD2LNdWB_register_Asm_32:
6015234353Sdim  case ARM::VLD2LNqWB_register_Asm_16:
6016234353Sdim  case ARM::VLD2LNqWB_register_Asm_32: {
6017234353Sdim    MCInst TmpInst;
6018234353Sdim    // Shuffle the operands around so the lane index operand is in the
6019234353Sdim    // right place.
6020234353Sdim    unsigned Spacing;
6021234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6022234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6023234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6024234353Sdim                                            Spacing));
6025234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6026234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6027234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6028234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rm
6029234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6030234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6031234353Sdim                                            Spacing));
6032234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6033234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6034234353Sdim    TmpInst.addOperand(Inst.getOperand(6));
6035234353Sdim    Inst = TmpInst;
6036234353Sdim    return true;
6037234353Sdim  }
6038234353Sdim
6039234353Sdim  case ARM::VLD3LNdWB_register_Asm_8:
6040234353Sdim  case ARM::VLD3LNdWB_register_Asm_16:
6041234353Sdim  case ARM::VLD3LNdWB_register_Asm_32:
6042234353Sdim  case ARM::VLD3LNqWB_register_Asm_16:
6043234353Sdim  case ARM::VLD3LNqWB_register_Asm_32: {
6044234353Sdim    MCInst TmpInst;
6045234353Sdim    // Shuffle the operands around so the lane index operand is in the
6046234353Sdim    // right place.
6047234353Sdim    unsigned Spacing;
6048234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6049234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6050234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6051234353Sdim                                            Spacing));
6052234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6053234353Sdim                                            Spacing * 2));
6054234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6055234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6056234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6057234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rm
6058234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6059234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6060234353Sdim                                            Spacing));
6061234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6062234353Sdim                                            Spacing * 2));
6063234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6064234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6065234353Sdim    TmpInst.addOperand(Inst.getOperand(6));
6066234353Sdim    Inst = TmpInst;
6067234353Sdim    return true;
6068234353Sdim  }
6069234353Sdim
6070234353Sdim  case ARM::VLD4LNdWB_register_Asm_8:
6071234353Sdim  case ARM::VLD4LNdWB_register_Asm_16:
6072234353Sdim  case ARM::VLD4LNdWB_register_Asm_32:
6073234353Sdim  case ARM::VLD4LNqWB_register_Asm_16:
6074234353Sdim  case ARM::VLD4LNqWB_register_Asm_32: {
6075234353Sdim    MCInst TmpInst;
6076234353Sdim    // Shuffle the operands around so the lane index operand is in the
6077234353Sdim    // right place.
6078234353Sdim    unsigned Spacing;
6079234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6080234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6081234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6082234353Sdim                                            Spacing));
6083234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6084234353Sdim                                            Spacing * 2));
6085234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6086234353Sdim                                            Spacing * 3));
6087234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6088234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6089234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6090234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rm
6091234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6092234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6093234353Sdim                                            Spacing));
6094234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6095234353Sdim                                            Spacing * 2));
6096234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6097234353Sdim                                            Spacing * 3));
6098234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6099234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6100234353Sdim    TmpInst.addOperand(Inst.getOperand(6));
6101234353Sdim    Inst = TmpInst;
6102234353Sdim    return true;
6103234353Sdim  }
6104234353Sdim
6105234353Sdim  case ARM::VLD1LNdWB_fixed_Asm_8:
6106234353Sdim  case ARM::VLD1LNdWB_fixed_Asm_16:
6107234353Sdim  case ARM::VLD1LNdWB_fixed_Asm_32: {
6108234353Sdim    MCInst TmpInst;
6109234353Sdim    // Shuffle the operands around so the lane index operand is in the
6110234353Sdim    // right place.
6111234353Sdim    unsigned Spacing;
6112234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6113234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6114234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6115234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6116234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6117234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6118234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6119234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6120234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6121234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6122234353Sdim    Inst = TmpInst;
6123234353Sdim    return true;
6124234353Sdim  }
6125234353Sdim
6126234353Sdim  case ARM::VLD2LNdWB_fixed_Asm_8:
6127234353Sdim  case ARM::VLD2LNdWB_fixed_Asm_16:
6128234353Sdim  case ARM::VLD2LNdWB_fixed_Asm_32:
6129234353Sdim  case ARM::VLD2LNqWB_fixed_Asm_16:
6130234353Sdim  case ARM::VLD2LNqWB_fixed_Asm_32: {
6131234353Sdim    MCInst TmpInst;
6132234353Sdim    // Shuffle the operands around so the lane index operand is in the
6133234353Sdim    // right place.
6134234353Sdim    unsigned Spacing;
6135234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6136234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6137234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6138234353Sdim                                            Spacing));
6139234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6140234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6141234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6142234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6143234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6144234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6145234353Sdim                                            Spacing));
6146234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6147234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6148234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6149234353Sdim    Inst = TmpInst;
6150234353Sdim    return true;
6151234353Sdim  }
6152234353Sdim
6153234353Sdim  case ARM::VLD3LNdWB_fixed_Asm_8:
6154234353Sdim  case ARM::VLD3LNdWB_fixed_Asm_16:
6155234353Sdim  case ARM::VLD3LNdWB_fixed_Asm_32:
6156234353Sdim  case ARM::VLD3LNqWB_fixed_Asm_16:
6157234353Sdim  case ARM::VLD3LNqWB_fixed_Asm_32: {
6158234353Sdim    MCInst TmpInst;
6159234353Sdim    // Shuffle the operands around so the lane index operand is in the
6160234353Sdim    // right place.
6161234353Sdim    unsigned Spacing;
6162234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6163234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6164234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6165234353Sdim                                            Spacing));
6166234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6167234353Sdim                                            Spacing * 2));
6168234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6169234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6170234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6171234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6172234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6173234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6174234353Sdim                                            Spacing));
6175234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6176234353Sdim                                            Spacing * 2));
6177234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6178234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6179234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6180234353Sdim    Inst = TmpInst;
6181234353Sdim    return true;
6182234353Sdim  }
6183234353Sdim
6184234353Sdim  case ARM::VLD4LNdWB_fixed_Asm_8:
6185234353Sdim  case ARM::VLD4LNdWB_fixed_Asm_16:
6186234353Sdim  case ARM::VLD4LNdWB_fixed_Asm_32:
6187234353Sdim  case ARM::VLD4LNqWB_fixed_Asm_16:
6188234353Sdim  case ARM::VLD4LNqWB_fixed_Asm_32: {
6189234353Sdim    MCInst TmpInst;
6190234353Sdim    // Shuffle the operands around so the lane index operand is in the
6191234353Sdim    // right place.
6192234353Sdim    unsigned Spacing;
6193234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6194234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6195234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6196234353Sdim                                            Spacing));
6197234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6198234353Sdim                                            Spacing * 2));
6199234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6200234353Sdim                                            Spacing * 3));
6201234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6202234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6203234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6204234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6205234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6206234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6207234353Sdim                                            Spacing));
6208234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6209234353Sdim                                            Spacing * 2));
6210234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6211234353Sdim                                            Spacing * 3));
6212234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6213234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6214234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6215234353Sdim    Inst = TmpInst;
6216234353Sdim    return true;
6217234353Sdim  }
6218234353Sdim
6219234353Sdim  case ARM::VLD1LNdAsm_8:
6220234353Sdim  case ARM::VLD1LNdAsm_16:
6221234353Sdim  case ARM::VLD1LNdAsm_32: {
6222234353Sdim    MCInst TmpInst;
6223234353Sdim    // Shuffle the operands around so the lane index operand is in the
6224234353Sdim    // right place.
6225234353Sdim    unsigned Spacing;
6226234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6227234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6228234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6229234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6230234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6231234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6232234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6233234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6234234353Sdim    Inst = TmpInst;
6235234353Sdim    return true;
6236234353Sdim  }
6237234353Sdim
6238234353Sdim  case ARM::VLD2LNdAsm_8:
6239234353Sdim  case ARM::VLD2LNdAsm_16:
6240234353Sdim  case ARM::VLD2LNdAsm_32:
6241234353Sdim  case ARM::VLD2LNqAsm_16:
6242234353Sdim  case ARM::VLD2LNqAsm_32: {
6243234353Sdim    MCInst TmpInst;
6244234353Sdim    // Shuffle the operands around so the lane index operand is in the
6245234353Sdim    // right place.
6246234353Sdim    unsigned Spacing;
6247234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6248234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6249234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6250234353Sdim                                            Spacing));
6251234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6252234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6253234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6254234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6255234353Sdim                                            Spacing));
6256234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6257234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6258234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6259234353Sdim    Inst = TmpInst;
6260234353Sdim    return true;
6261234353Sdim  }
6262234353Sdim
6263234353Sdim  case ARM::VLD3LNdAsm_8:
6264234353Sdim  case ARM::VLD3LNdAsm_16:
6265234353Sdim  case ARM::VLD3LNdAsm_32:
6266234353Sdim  case ARM::VLD3LNqAsm_16:
6267234353Sdim  case ARM::VLD3LNqAsm_32: {
6268234353Sdim    MCInst TmpInst;
6269234353Sdim    // Shuffle the operands around so the lane index operand is in the
6270234353Sdim    // right place.
6271234353Sdim    unsigned Spacing;
6272234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6273234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6274234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6275234353Sdim                                            Spacing));
6276234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6277234353Sdim                                            Spacing * 2));
6278234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6279234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6280234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6281234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6282234353Sdim                                            Spacing));
6283234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6284234353Sdim                                            Spacing * 2));
6285234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6286234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6287234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6288234353Sdim    Inst = TmpInst;
6289234353Sdim    return true;
6290234353Sdim  }
6291234353Sdim
6292234353Sdim  case ARM::VLD4LNdAsm_8:
6293234353Sdim  case ARM::VLD4LNdAsm_16:
6294234353Sdim  case ARM::VLD4LNdAsm_32:
6295234353Sdim  case ARM::VLD4LNqAsm_16:
6296234353Sdim  case ARM::VLD4LNqAsm_32: {
6297234353Sdim    MCInst TmpInst;
6298234353Sdim    // Shuffle the operands around so the lane index operand is in the
6299234353Sdim    // right place.
6300234353Sdim    unsigned Spacing;
6301234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6302234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6303234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6304234353Sdim                                            Spacing));
6305234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6306234353Sdim                                            Spacing * 2));
6307234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6308234353Sdim                                            Spacing * 3));
6309234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rn
6310234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // alignment
6311234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6312234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6313234353Sdim                                            Spacing));
6314234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6315234353Sdim                                            Spacing * 2));
6316234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6317234353Sdim                                            Spacing * 3));
6318234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // lane
6319234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6320234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6321234353Sdim    Inst = TmpInst;
6322234353Sdim    return true;
6323234353Sdim  }
6324234353Sdim
6325234353Sdim  // VLD3DUP single 3-element structure to all lanes instructions.
6326234353Sdim  case ARM::VLD3DUPdAsm_8:
6327234353Sdim  case ARM::VLD3DUPdAsm_16:
6328234353Sdim  case ARM::VLD3DUPdAsm_32:
6329234353Sdim  case ARM::VLD3DUPqAsm_8:
6330234353Sdim  case ARM::VLD3DUPqAsm_16:
6331234353Sdim  case ARM::VLD3DUPqAsm_32: {
6332234353Sdim    MCInst TmpInst;
6333234353Sdim    unsigned Spacing;
6334234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6335234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6336234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6337234353Sdim                                            Spacing));
6338234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6339234353Sdim                                            Spacing * 2));
6340234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6341234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6342234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6343234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6344234353Sdim    Inst = TmpInst;
6345234353Sdim    return true;
6346234353Sdim  }
6347234353Sdim
6348234353Sdim  case ARM::VLD3DUPdWB_fixed_Asm_8:
6349234353Sdim  case ARM::VLD3DUPdWB_fixed_Asm_16:
6350234353Sdim  case ARM::VLD3DUPdWB_fixed_Asm_32:
6351234353Sdim  case ARM::VLD3DUPqWB_fixed_Asm_8:
6352234353Sdim  case ARM::VLD3DUPqWB_fixed_Asm_16:
6353234353Sdim  case ARM::VLD3DUPqWB_fixed_Asm_32: {
6354234353Sdim    MCInst TmpInst;
6355234353Sdim    unsigned Spacing;
6356234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6357234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6358234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6359234353Sdim                                            Spacing));
6360234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6361234353Sdim                                            Spacing * 2));
6362234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6363234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6364234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6365234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6366234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6367234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6368234353Sdim    Inst = TmpInst;
6369234353Sdim    return true;
6370234353Sdim  }
6371234353Sdim
6372234353Sdim  case ARM::VLD3DUPdWB_register_Asm_8:
6373234353Sdim  case ARM::VLD3DUPdWB_register_Asm_16:
6374234353Sdim  case ARM::VLD3DUPdWB_register_Asm_32:
6375234353Sdim  case ARM::VLD3DUPqWB_register_Asm_8:
6376234353Sdim  case ARM::VLD3DUPqWB_register_Asm_16:
6377234353Sdim  case ARM::VLD3DUPqWB_register_Asm_32: {
6378234353Sdim    MCInst TmpInst;
6379234353Sdim    unsigned Spacing;
6380234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6381234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6382234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6383234353Sdim                                            Spacing));
6384234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6385234353Sdim                                            Spacing * 2));
6386234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6387234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6388234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6389234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // Rm
6390234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6391234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6392234353Sdim    Inst = TmpInst;
6393234353Sdim    return true;
6394234353Sdim  }
6395234353Sdim
6396234353Sdim  // VLD3 multiple 3-element structure instructions.
6397234353Sdim  case ARM::VLD3dAsm_8:
6398234353Sdim  case ARM::VLD3dAsm_16:
6399234353Sdim  case ARM::VLD3dAsm_32:
6400234353Sdim  case ARM::VLD3qAsm_8:
6401234353Sdim  case ARM::VLD3qAsm_16:
6402234353Sdim  case ARM::VLD3qAsm_32: {
6403234353Sdim    MCInst TmpInst;
6404234353Sdim    unsigned Spacing;
6405234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6406234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6407234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6408234353Sdim                                            Spacing));
6409234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6410234353Sdim                                            Spacing * 2));
6411234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6412234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6413234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6414234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6415234353Sdim    Inst = TmpInst;
6416234353Sdim    return true;
6417234353Sdim  }
6418234353Sdim
6419234353Sdim  case ARM::VLD3dWB_fixed_Asm_8:
6420234353Sdim  case ARM::VLD3dWB_fixed_Asm_16:
6421234353Sdim  case ARM::VLD3dWB_fixed_Asm_32:
6422234353Sdim  case ARM::VLD3qWB_fixed_Asm_8:
6423234353Sdim  case ARM::VLD3qWB_fixed_Asm_16:
6424234353Sdim  case ARM::VLD3qWB_fixed_Asm_32: {
6425234353Sdim    MCInst TmpInst;
6426234353Sdim    unsigned Spacing;
6427234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6428234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6429234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6430234353Sdim                                            Spacing));
6431234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6432234353Sdim                                            Spacing * 2));
6433234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6434234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6435234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6436234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6437234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6438234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6439234353Sdim    Inst = TmpInst;
6440234353Sdim    return true;
6441234353Sdim  }
6442234353Sdim
6443234353Sdim  case ARM::VLD3dWB_register_Asm_8:
6444234353Sdim  case ARM::VLD3dWB_register_Asm_16:
6445234353Sdim  case ARM::VLD3dWB_register_Asm_32:
6446234353Sdim  case ARM::VLD3qWB_register_Asm_8:
6447234353Sdim  case ARM::VLD3qWB_register_Asm_16:
6448234353Sdim  case ARM::VLD3qWB_register_Asm_32: {
6449234353Sdim    MCInst TmpInst;
6450234353Sdim    unsigned Spacing;
6451234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6452234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6453234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6454234353Sdim                                            Spacing));
6455234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6456234353Sdim                                            Spacing * 2));
6457234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6458234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6459234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6460234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // Rm
6461234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6462234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6463234353Sdim    Inst = TmpInst;
6464234353Sdim    return true;
6465234353Sdim  }
6466234353Sdim
6467234353Sdim  // VLD4DUP single 3-element structure to all lanes instructions.
6468234353Sdim  case ARM::VLD4DUPdAsm_8:
6469234353Sdim  case ARM::VLD4DUPdAsm_16:
6470234353Sdim  case ARM::VLD4DUPdAsm_32:
6471234353Sdim  case ARM::VLD4DUPqAsm_8:
6472234353Sdim  case ARM::VLD4DUPqAsm_16:
6473234353Sdim  case ARM::VLD4DUPqAsm_32: {
6474234353Sdim    MCInst TmpInst;
6475234353Sdim    unsigned Spacing;
6476234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6477234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6478234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6479234353Sdim                                            Spacing));
6480234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6481234353Sdim                                            Spacing * 2));
6482234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6483234353Sdim                                            Spacing * 3));
6484234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6485234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6486234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6487234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6488234353Sdim    Inst = TmpInst;
6489234353Sdim    return true;
6490234353Sdim  }
6491234353Sdim
6492234353Sdim  case ARM::VLD4DUPdWB_fixed_Asm_8:
6493234353Sdim  case ARM::VLD4DUPdWB_fixed_Asm_16:
6494234353Sdim  case ARM::VLD4DUPdWB_fixed_Asm_32:
6495234353Sdim  case ARM::VLD4DUPqWB_fixed_Asm_8:
6496234353Sdim  case ARM::VLD4DUPqWB_fixed_Asm_16:
6497234353Sdim  case ARM::VLD4DUPqWB_fixed_Asm_32: {
6498234353Sdim    MCInst TmpInst;
6499234353Sdim    unsigned Spacing;
6500234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6501234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6502234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6503234353Sdim                                            Spacing));
6504234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6505234353Sdim                                            Spacing * 2));
6506234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6507234353Sdim                                            Spacing * 3));
6508234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6509234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6510234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6511234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6512234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6513234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6514234353Sdim    Inst = TmpInst;
6515234353Sdim    return true;
6516234353Sdim  }
6517234353Sdim
6518234353Sdim  case ARM::VLD4DUPdWB_register_Asm_8:
6519234353Sdim  case ARM::VLD4DUPdWB_register_Asm_16:
6520234353Sdim  case ARM::VLD4DUPdWB_register_Asm_32:
6521234353Sdim  case ARM::VLD4DUPqWB_register_Asm_8:
6522234353Sdim  case ARM::VLD4DUPqWB_register_Asm_16:
6523234353Sdim  case ARM::VLD4DUPqWB_register_Asm_32: {
6524234353Sdim    MCInst TmpInst;
6525234353Sdim    unsigned Spacing;
6526234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6527234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6528234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6529234353Sdim                                            Spacing));
6530234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6531234353Sdim                                            Spacing * 2));
6532234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6533234353Sdim                                            Spacing * 3));
6534234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6535234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6536234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6537234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // Rm
6538234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6539234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6540234353Sdim    Inst = TmpInst;
6541234353Sdim    return true;
6542234353Sdim  }
6543234353Sdim
6544234353Sdim  // VLD4 multiple 4-element structure instructions.
6545234353Sdim  case ARM::VLD4dAsm_8:
6546234353Sdim  case ARM::VLD4dAsm_16:
6547234353Sdim  case ARM::VLD4dAsm_32:
6548234353Sdim  case ARM::VLD4qAsm_8:
6549234353Sdim  case ARM::VLD4qAsm_16:
6550234353Sdim  case ARM::VLD4qAsm_32: {
6551234353Sdim    MCInst TmpInst;
6552234353Sdim    unsigned Spacing;
6553234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6554234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6555234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6556234353Sdim                                            Spacing));
6557234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6558234353Sdim                                            Spacing * 2));
6559234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6560234353Sdim                                            Spacing * 3));
6561234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6562234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6563234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6564234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6565234353Sdim    Inst = TmpInst;
6566234353Sdim    return true;
6567234353Sdim  }
6568234353Sdim
6569234353Sdim  case ARM::VLD4dWB_fixed_Asm_8:
6570234353Sdim  case ARM::VLD4dWB_fixed_Asm_16:
6571234353Sdim  case ARM::VLD4dWB_fixed_Asm_32:
6572234353Sdim  case ARM::VLD4qWB_fixed_Asm_8:
6573234353Sdim  case ARM::VLD4qWB_fixed_Asm_16:
6574234353Sdim  case ARM::VLD4qWB_fixed_Asm_32: {
6575234353Sdim    MCInst TmpInst;
6576234353Sdim    unsigned Spacing;
6577234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6578234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6579234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6580234353Sdim                                            Spacing));
6581234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6582234353Sdim                                            Spacing * 2));
6583234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6584234353Sdim                                            Spacing * 3));
6585234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6586234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6587234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6588234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6589234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6590234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6591234353Sdim    Inst = TmpInst;
6592234353Sdim    return true;
6593234353Sdim  }
6594234353Sdim
6595234353Sdim  case ARM::VLD4dWB_register_Asm_8:
6596234353Sdim  case ARM::VLD4dWB_register_Asm_16:
6597234353Sdim  case ARM::VLD4dWB_register_Asm_32:
6598234353Sdim  case ARM::VLD4qWB_register_Asm_8:
6599234353Sdim  case ARM::VLD4qWB_register_Asm_16:
6600234353Sdim  case ARM::VLD4qWB_register_Asm_32: {
6601234353Sdim    MCInst TmpInst;
6602234353Sdim    unsigned Spacing;
6603234353Sdim    TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6604234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6605234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6606234353Sdim                                            Spacing));
6607234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6608234353Sdim                                            Spacing * 2));
6609234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6610234353Sdim                                            Spacing * 3));
6611234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6612234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6613234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6614234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // Rm
6615234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6616234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6617234353Sdim    Inst = TmpInst;
6618234353Sdim    return true;
6619234353Sdim  }
6620234353Sdim
6621234353Sdim  // VST3 multiple 3-element structure instructions.
6622234353Sdim  case ARM::VST3dAsm_8:
6623234353Sdim  case ARM::VST3dAsm_16:
6624234353Sdim  case ARM::VST3dAsm_32:
6625234353Sdim  case ARM::VST3qAsm_8:
6626234353Sdim  case ARM::VST3qAsm_16:
6627234353Sdim  case ARM::VST3qAsm_32: {
6628234353Sdim    MCInst TmpInst;
6629234353Sdim    unsigned Spacing;
6630234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6631234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6632234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6633234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6634234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6635234353Sdim                                            Spacing));
6636234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6637234353Sdim                                            Spacing * 2));
6638234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6639234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6640234353Sdim    Inst = TmpInst;
6641234353Sdim    return true;
6642234353Sdim  }
6643234353Sdim
6644234353Sdim  case ARM::VST3dWB_fixed_Asm_8:
6645234353Sdim  case ARM::VST3dWB_fixed_Asm_16:
6646234353Sdim  case ARM::VST3dWB_fixed_Asm_32:
6647234353Sdim  case ARM::VST3qWB_fixed_Asm_8:
6648234353Sdim  case ARM::VST3qWB_fixed_Asm_16:
6649234353Sdim  case ARM::VST3qWB_fixed_Asm_32: {
6650234353Sdim    MCInst TmpInst;
6651234353Sdim    unsigned Spacing;
6652234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6653234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6654234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6655234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6656234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6657234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6658234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6659234353Sdim                                            Spacing));
6660234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6661234353Sdim                                            Spacing * 2));
6662234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6663234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6664234353Sdim    Inst = TmpInst;
6665234353Sdim    return true;
6666234353Sdim  }
6667234353Sdim
6668234353Sdim  case ARM::VST3dWB_register_Asm_8:
6669234353Sdim  case ARM::VST3dWB_register_Asm_16:
6670234353Sdim  case ARM::VST3dWB_register_Asm_32:
6671234353Sdim  case ARM::VST3qWB_register_Asm_8:
6672234353Sdim  case ARM::VST3qWB_register_Asm_16:
6673234353Sdim  case ARM::VST3qWB_register_Asm_32: {
6674234353Sdim    MCInst TmpInst;
6675234353Sdim    unsigned Spacing;
6676234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6677234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6678234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6679234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6680234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // Rm
6681234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6682234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6683234353Sdim                                            Spacing));
6684234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6685234353Sdim                                            Spacing * 2));
6686234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6687234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6688234353Sdim    Inst = TmpInst;
6689234353Sdim    return true;
6690234353Sdim  }
6691234353Sdim
6692234353Sdim  // VST4 multiple 3-element structure instructions.
6693234353Sdim  case ARM::VST4dAsm_8:
6694234353Sdim  case ARM::VST4dAsm_16:
6695234353Sdim  case ARM::VST4dAsm_32:
6696234353Sdim  case ARM::VST4qAsm_8:
6697234353Sdim  case ARM::VST4qAsm_16:
6698234353Sdim  case ARM::VST4qAsm_32: {
6699234353Sdim    MCInst TmpInst;
6700234353Sdim    unsigned Spacing;
6701234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6702234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6703234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6704234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6705234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6706234353Sdim                                            Spacing));
6707234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6708234353Sdim                                            Spacing * 2));
6709234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6710234353Sdim                                            Spacing * 3));
6711234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6712234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6713234353Sdim    Inst = TmpInst;
6714234353Sdim    return true;
6715234353Sdim  }
6716234353Sdim
6717234353Sdim  case ARM::VST4dWB_fixed_Asm_8:
6718234353Sdim  case ARM::VST4dWB_fixed_Asm_16:
6719234353Sdim  case ARM::VST4dWB_fixed_Asm_32:
6720234353Sdim  case ARM::VST4qWB_fixed_Asm_8:
6721234353Sdim  case ARM::VST4qWB_fixed_Asm_16:
6722234353Sdim  case ARM::VST4qWB_fixed_Asm_32: {
6723234353Sdim    MCInst TmpInst;
6724234353Sdim    unsigned Spacing;
6725234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6726234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6727234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6728234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6729234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6730234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6731234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6732234353Sdim                                            Spacing));
6733234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6734234353Sdim                                            Spacing * 2));
6735234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6736234353Sdim                                            Spacing * 3));
6737234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6738234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6739234353Sdim    Inst = TmpInst;
6740234353Sdim    return true;
6741234353Sdim  }
6742234353Sdim
6743234353Sdim  case ARM::VST4dWB_register_Asm_8:
6744234353Sdim  case ARM::VST4dWB_register_Asm_16:
6745234353Sdim  case ARM::VST4dWB_register_Asm_32:
6746234353Sdim  case ARM::VST4qWB_register_Asm_8:
6747234353Sdim  case ARM::VST4qWB_register_Asm_16:
6748234353Sdim  case ARM::VST4qWB_register_Asm_32: {
6749234353Sdim    MCInst TmpInst;
6750234353Sdim    unsigned Spacing;
6751234353Sdim    TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6752234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6753234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6754234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // alignment
6755234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // Rm
6756234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Vd
6757234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6758234353Sdim                                            Spacing));
6759234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6760234353Sdim                                            Spacing * 2));
6761234353Sdim    TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6762234353Sdim                                            Spacing * 3));
6763234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6764234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6765234353Sdim    Inst = TmpInst;
6766234353Sdim    return true;
6767234353Sdim  }
6768234353Sdim
6769234353Sdim  // Handle encoding choice for the shift-immediate instructions.
6770234353Sdim  case ARM::t2LSLri:
6771234353Sdim  case ARM::t2LSRri:
6772234353Sdim  case ARM::t2ASRri: {
6773234353Sdim    if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6774234353Sdim        Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6775234353Sdim        Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
6776234353Sdim        !(static_cast<ARMOperand*>(Operands[3])->isToken() &&
6777234353Sdim         static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) {
6778234353Sdim      unsigned NewOpc;
6779234353Sdim      switch (Inst.getOpcode()) {
6780234353Sdim      default: llvm_unreachable("unexpected opcode");
6781234353Sdim      case ARM::t2LSLri: NewOpc = ARM::tLSLri; break;
6782234353Sdim      case ARM::t2LSRri: NewOpc = ARM::tLSRri; break;
6783234353Sdim      case ARM::t2ASRri: NewOpc = ARM::tASRri; break;
6784234353Sdim      }
6785234353Sdim      // The Thumb1 operands aren't in the same order. Awesome, eh?
6786234353Sdim      MCInst TmpInst;
6787234353Sdim      TmpInst.setOpcode(NewOpc);
6788234353Sdim      TmpInst.addOperand(Inst.getOperand(0));
6789234353Sdim      TmpInst.addOperand(Inst.getOperand(5));
6790234353Sdim      TmpInst.addOperand(Inst.getOperand(1));
6791234353Sdim      TmpInst.addOperand(Inst.getOperand(2));
6792234353Sdim      TmpInst.addOperand(Inst.getOperand(3));
6793234353Sdim      TmpInst.addOperand(Inst.getOperand(4));
6794234353Sdim      Inst = TmpInst;
6795234353Sdim      return true;
6796234353Sdim    }
6797234353Sdim    return false;
6798234353Sdim  }
6799234353Sdim
6800234353Sdim  // Handle the Thumb2 mode MOV complex aliases.
6801234353Sdim  case ARM::t2MOVsr:
6802234353Sdim  case ARM::t2MOVSsr: {
6803234353Sdim    // Which instruction to expand to depends on the CCOut operand and
6804234353Sdim    // whether we're in an IT block if the register operands are low
6805234353Sdim    // registers.
6806234353Sdim    bool isNarrow = false;
6807234353Sdim    if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6808234353Sdim        isARMLowRegister(Inst.getOperand(1).getReg()) &&
6809234353Sdim        isARMLowRegister(Inst.getOperand(2).getReg()) &&
6810234353Sdim        Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6811234353Sdim        inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6812234353Sdim      isNarrow = true;
6813234353Sdim    MCInst TmpInst;
6814234353Sdim    unsigned newOpc;
6815234353Sdim    switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6816234353Sdim    default: llvm_unreachable("unexpected opcode!");
6817234353Sdim    case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6818234353Sdim    case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6819234353Sdim    case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6820234353Sdim    case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR   : ARM::t2RORrr; break;
6821234353Sdim    }
6822234353Sdim    TmpInst.setOpcode(newOpc);
6823234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Rd
6824234353Sdim    if (isNarrow)
6825234353Sdim      TmpInst.addOperand(MCOperand::CreateReg(
6826234353Sdim          Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6827234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6828234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rm
6829234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6830234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
6831234353Sdim    if (!isNarrow)
6832234353Sdim      TmpInst.addOperand(MCOperand::CreateReg(
6833234353Sdim          Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6834234353Sdim    Inst = TmpInst;
6835234353Sdim    return true;
6836234353Sdim  }
6837234353Sdim  case ARM::t2MOVsi:
6838234353Sdim  case ARM::t2MOVSsi: {
6839234353Sdim    // Which instruction to expand to depends on the CCOut operand and
6840234353Sdim    // whether we're in an IT block if the register operands are low
6841234353Sdim    // registers.
6842234353Sdim    bool isNarrow = false;
6843234353Sdim    if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6844234353Sdim        isARMLowRegister(Inst.getOperand(1).getReg()) &&
6845234353Sdim        inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6846234353Sdim      isNarrow = true;
6847234353Sdim    MCInst TmpInst;
6848234353Sdim    unsigned newOpc;
6849234353Sdim    switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6850234353Sdim    default: llvm_unreachable("unexpected opcode!");
6851234353Sdim    case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6852234353Sdim    case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6853234353Sdim    case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6854234353Sdim    case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
6855234353Sdim    case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
6856234353Sdim    }
6857239462Sdim    unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6858239462Sdim    if (Amount == 32) Amount = 0;
6859234353Sdim    TmpInst.setOpcode(newOpc);
6860234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Rd
6861234353Sdim    if (isNarrow)
6862234353Sdim      TmpInst.addOperand(MCOperand::CreateReg(
6863234353Sdim          Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6864234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6865234353Sdim    if (newOpc != ARM::t2RRX)
6866239462Sdim      TmpInst.addOperand(MCOperand::CreateImm(Amount));
6867234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6868234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6869234353Sdim    if (!isNarrow)
6870234353Sdim      TmpInst.addOperand(MCOperand::CreateReg(
6871234353Sdim          Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6872234353Sdim    Inst = TmpInst;
6873234353Sdim    return true;
6874234353Sdim  }
6875234353Sdim  // Handle the ARM mode MOV complex aliases.
6876234353Sdim  case ARM::ASRr:
6877234353Sdim  case ARM::LSRr:
6878234353Sdim  case ARM::LSLr:
6879234353Sdim  case ARM::RORr: {
6880234353Sdim    ARM_AM::ShiftOpc ShiftTy;
6881234353Sdim    switch(Inst.getOpcode()) {
6882234353Sdim    default: llvm_unreachable("unexpected opcode!");
6883234353Sdim    case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6884234353Sdim    case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6885234353Sdim    case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6886234353Sdim    case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6887234353Sdim    }
6888234353Sdim    unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6889234353Sdim    MCInst TmpInst;
6890234353Sdim    TmpInst.setOpcode(ARM::MOVsr);
6891234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Rd
6892234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6893234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // Rm
6894234353Sdim    TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6895234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6896234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6897234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6898234353Sdim    Inst = TmpInst;
6899234353Sdim    return true;
6900234353Sdim  }
6901234353Sdim  case ARM::ASRi:
6902234353Sdim  case ARM::LSRi:
6903234353Sdim  case ARM::LSLi:
6904234353Sdim  case ARM::RORi: {
6905234353Sdim    ARM_AM::ShiftOpc ShiftTy;
6906234353Sdim    switch(Inst.getOpcode()) {
6907234353Sdim    default: llvm_unreachable("unexpected opcode!");
6908234353Sdim    case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6909234353Sdim    case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6910234353Sdim    case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6911234353Sdim    case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6912234353Sdim    }
6913234353Sdim    // A shift by zero is a plain MOVr, not a MOVsi.
6914234353Sdim    unsigned Amt = Inst.getOperand(2).getImm();
6915234353Sdim    unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
6916239462Sdim    // A shift by 32 should be encoded as 0 when permitted
6917239462Sdim    if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr))
6918239462Sdim      Amt = 0;
6919234353Sdim    unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
6920234353Sdim    MCInst TmpInst;
6921234353Sdim    TmpInst.setOpcode(Opc);
6922234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Rd
6923234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6924234353Sdim    if (Opc == ARM::MOVsi)
6925234353Sdim      TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6926234353Sdim    TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6927234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
6928234353Sdim    TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6929234353Sdim    Inst = TmpInst;
6930234353Sdim    return true;
6931234353Sdim  }
6932234353Sdim  case ARM::RRXi: {
6933234353Sdim    unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6934234353Sdim    MCInst TmpInst;
6935234353Sdim    TmpInst.setOpcode(ARM::MOVsi);
6936234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Rd
6937234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6938234353Sdim    TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6939234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6940234353Sdim    TmpInst.addOperand(Inst.getOperand(3));
6941234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6942234353Sdim    Inst = TmpInst;
6943234353Sdim    return true;
6944234353Sdim  }
6945234353Sdim  case ARM::t2LDMIA_UPD: {
6946234353Sdim    // If this is a load of a single register, then we should use
6947234353Sdim    // a post-indexed LDR instruction instead, per the ARM ARM.
6948234353Sdim    if (Inst.getNumOperands() != 5)
6949234353Sdim      return false;
6950234353Sdim    MCInst TmpInst;
6951234353Sdim    TmpInst.setOpcode(ARM::t2LDR_POST);
6952234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rt
6953234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6954234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6955234353Sdim    TmpInst.addOperand(MCOperand::CreateImm(4));
6956234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6957234353Sdim    TmpInst.addOperand(Inst.getOperand(3));
6958234353Sdim    Inst = TmpInst;
6959234353Sdim    return true;
6960234353Sdim  }
6961234353Sdim  case ARM::t2STMDB_UPD: {
6962234353Sdim    // If this is a store of a single register, then we should use
6963234353Sdim    // a pre-indexed STR instruction instead, per the ARM ARM.
6964234353Sdim    if (Inst.getNumOperands() != 5)
6965234353Sdim      return false;
6966234353Sdim    MCInst TmpInst;
6967234353Sdim    TmpInst.setOpcode(ARM::t2STR_PRE);
6968234353Sdim    TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6969234353Sdim    TmpInst.addOperand(Inst.getOperand(4)); // Rt
6970234353Sdim    TmpInst.addOperand(Inst.getOperand(1)); // Rn
6971234353Sdim    TmpInst.addOperand(MCOperand::CreateImm(-4));
6972234353Sdim    TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6973234353Sdim    TmpInst.addOperand(Inst.getOperand(3));
6974234353Sdim    Inst = TmpInst;
6975234353Sdim    return true;
6976234353Sdim  }
6977226633Sdim  case ARM::LDMIA_UPD:
6978226633Sdim    // If this is a load of a single register via a 'pop', then we should use
6979226633Sdim    // a post-indexed LDR instruction instead, per the ARM ARM.
6980226633Sdim    if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6981226633Sdim        Inst.getNumOperands() == 5) {
6982226633Sdim      MCInst TmpInst;
6983226633Sdim      TmpInst.setOpcode(ARM::LDR_POST_IMM);
6984226633Sdim      TmpInst.addOperand(Inst.getOperand(4)); // Rt
6985226633Sdim      TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6986226633Sdim      TmpInst.addOperand(Inst.getOperand(1)); // Rn
6987226633Sdim      TmpInst.addOperand(MCOperand::CreateReg(0));  // am2offset
6988226633Sdim      TmpInst.addOperand(MCOperand::CreateImm(4));
6989226633Sdim      TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6990226633Sdim      TmpInst.addOperand(Inst.getOperand(3));
6991226633Sdim      Inst = TmpInst;
6992234353Sdim      return true;
6993226633Sdim    }
6994226633Sdim    break;
6995226633Sdim  case ARM::STMDB_UPD:
6996226633Sdim    // If this is a store of a single register via a 'push', then we should use
6997226633Sdim    // a pre-indexed STR instruction instead, per the ARM ARM.
6998226633Sdim    if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6999226633Sdim        Inst.getNumOperands() == 5) {
7000226633Sdim      MCInst TmpInst;
7001226633Sdim      TmpInst.setOpcode(ARM::STR_PRE_IMM);
7002226633Sdim      TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
7003226633Sdim      TmpInst.addOperand(Inst.getOperand(4)); // Rt
7004226633Sdim      TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
7005226633Sdim      TmpInst.addOperand(MCOperand::CreateImm(-4));
7006226633Sdim      TmpInst.addOperand(Inst.getOperand(2)); // CondCode
7007226633Sdim      TmpInst.addOperand(Inst.getOperand(3));
7008226633Sdim      Inst = TmpInst;
7009226633Sdim    }
7010226633Sdim    break;
7011234353Sdim  case ARM::t2ADDri12:
7012234353Sdim    // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
7013234353Sdim    // mnemonic was used (not "addw"), encoding T3 is preferred.
7014234353Sdim    if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
7015234353Sdim        ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
7016234353Sdim      break;
7017234353Sdim    Inst.setOpcode(ARM::t2ADDri);
7018234353Sdim    Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7019234353Sdim    break;
7020234353Sdim  case ARM::t2SUBri12:
7021234353Sdim    // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
7022234353Sdim    // mnemonic was used (not "subw"), encoding T3 is preferred.
7023234353Sdim    if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
7024234353Sdim        ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
7025234353Sdim      break;
7026234353Sdim    Inst.setOpcode(ARM::t2SUBri);
7027234353Sdim    Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7028234353Sdim    break;
7029226633Sdim  case ARM::tADDi8:
7030226633Sdim    // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
7031226633Sdim    // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
7032226633Sdim    // to encoding T2 if <Rd> is specified and encoding T2 is preferred
7033226633Sdim    // to encoding T1 if <Rd> is omitted."
7034234353Sdim    if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
7035226633Sdim      Inst.setOpcode(ARM::tADDi3);
7036234353Sdim      return true;
7037234353Sdim    }
7038226633Sdim    break;
7039226633Sdim  case ARM::tSUBi8:
7040226633Sdim    // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
7041226633Sdim    // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
7042226633Sdim    // to encoding T2 if <Rd> is specified and encoding T2 is preferred
7043226633Sdim    // to encoding T1 if <Rd> is omitted."
7044234353Sdim    if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
7045226633Sdim      Inst.setOpcode(ARM::tSUBi3);
7046234353Sdim      return true;
7047234353Sdim    }
7048226633Sdim    break;
7049234353Sdim  case ARM::t2ADDri:
7050234353Sdim  case ARM::t2SUBri: {
7051234353Sdim    // If the destination and first source operand are the same, and
7052234353Sdim    // the flags are compatible with the current IT status, use encoding T2
7053234353Sdim    // instead of T3. For compatibility with the system 'as'. Make sure the
7054234353Sdim    // wide encoding wasn't explicit.
7055234353Sdim    if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
7056234353Sdim        !isARMLowRegister(Inst.getOperand(0).getReg()) ||
7057234353Sdim        (unsigned)Inst.getOperand(2).getImm() > 255 ||
7058234353Sdim        ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
7059234353Sdim        (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
7060234353Sdim        (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7061234353Sdim         static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
7062234353Sdim      break;
7063234353Sdim    MCInst TmpInst;
7064234353Sdim    TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
7065234353Sdim                      ARM::tADDi8 : ARM::tSUBi8);
7066234353Sdim    TmpInst.addOperand(Inst.getOperand(0));
7067234353Sdim    TmpInst.addOperand(Inst.getOperand(5));
7068234353Sdim    TmpInst.addOperand(Inst.getOperand(0));
7069234353Sdim    TmpInst.addOperand(Inst.getOperand(2));
7070234353Sdim    TmpInst.addOperand(Inst.getOperand(3));
7071234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
7072234353Sdim    Inst = TmpInst;
7073234353Sdim    return true;
7074234353Sdim  }
7075234353Sdim  case ARM::t2ADDrr: {
7076234353Sdim    // If the destination and first source operand are the same, and
7077234353Sdim    // there's no setting of the flags, use encoding T2 instead of T3.
7078234353Sdim    // Note that this is only for ADD, not SUB. This mirrors the system
7079234353Sdim    // 'as' behaviour. Make sure the wide encoding wasn't explicit.
7080234353Sdim    if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
7081234353Sdim        Inst.getOperand(5).getReg() != 0 ||
7082234353Sdim        (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7083234353Sdim         static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
7084234353Sdim      break;
7085234353Sdim    MCInst TmpInst;
7086234353Sdim    TmpInst.setOpcode(ARM::tADDhirr);
7087234353Sdim    TmpInst.addOperand(Inst.getOperand(0));
7088234353Sdim    TmpInst.addOperand(Inst.getOperand(0));
7089234353Sdim    TmpInst.addOperand(Inst.getOperand(2));
7090234353Sdim    TmpInst.addOperand(Inst.getOperand(3));
7091234353Sdim    TmpInst.addOperand(Inst.getOperand(4));
7092234353Sdim    Inst = TmpInst;
7093234353Sdim    return true;
7094234353Sdim  }
7095239462Sdim  case ARM::tADDrSP: {
7096239462Sdim    // If the non-SP source operand and the destination operand are not the
7097239462Sdim    // same, we need to use the 32-bit encoding if it's available.
7098239462Sdim    if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
7099239462Sdim      Inst.setOpcode(ARM::t2ADDrr);
7100239462Sdim      Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7101239462Sdim      return true;
7102239462Sdim    }
7103239462Sdim    break;
7104239462Sdim  }
7105226633Sdim  case ARM::tB:
7106226633Sdim    // A Thumb conditional branch outside of an IT block is a tBcc.
7107234353Sdim    if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
7108226633Sdim      Inst.setOpcode(ARM::tBcc);
7109234353Sdim      return true;
7110234353Sdim    }
7111226633Sdim    break;
7112226633Sdim  case ARM::t2B:
7113226633Sdim    // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
7114234353Sdim    if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
7115226633Sdim      Inst.setOpcode(ARM::t2Bcc);
7116234353Sdim      return true;
7117234353Sdim    }
7118226633Sdim    break;
7119226633Sdim  case ARM::t2Bcc:
7120226633Sdim    // If the conditional is AL or we're in an IT block, we really want t2B.
7121234353Sdim    if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
7122226633Sdim      Inst.setOpcode(ARM::t2B);
7123234353Sdim      return true;
7124234353Sdim    }
7125226633Sdim    break;
7126226633Sdim  case ARM::tBcc:
7127226633Sdim    // If the conditional is AL, we really want tB.
7128234353Sdim    if (Inst.getOperand(1).getImm() == ARMCC::AL) {
7129226633Sdim      Inst.setOpcode(ARM::tB);
7130234353Sdim      return true;
7131234353Sdim    }
7132226633Sdim    break;
7133226633Sdim  case ARM::tLDMIA: {
7134226633Sdim    // If the register list contains any high registers, or if the writeback
7135226633Sdim    // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
7136226633Sdim    // instead if we're in Thumb2. Otherwise, this should have generated
7137226633Sdim    // an error in validateInstruction().
7138226633Sdim    unsigned Rn = Inst.getOperand(0).getReg();
7139226633Sdim    bool hasWritebackToken =
7140226633Sdim      (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7141226633Sdim       static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
7142226633Sdim    bool listContainsBase;
7143226633Sdim    if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
7144226633Sdim        (!listContainsBase && !hasWritebackToken) ||
7145226633Sdim        (listContainsBase && hasWritebackToken)) {
7146226633Sdim      // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7147226633Sdim      assert (isThumbTwo());
7148226633Sdim      Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
7149226633Sdim      // If we're switching to the updating version, we need to insert
7150226633Sdim      // the writeback tied operand.
7151226633Sdim      if (hasWritebackToken)
7152226633Sdim        Inst.insert(Inst.begin(),
7153226633Sdim                    MCOperand::CreateReg(Inst.getOperand(0).getReg()));
7154234353Sdim      return true;
7155226633Sdim    }
7156226633Sdim    break;
7157226633Sdim  }
7158226633Sdim  case ARM::tSTMIA_UPD: {
7159226633Sdim    // If the register list contains any high registers, we need to use
7160226633Sdim    // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7161226633Sdim    // should have generated an error in validateInstruction().
7162226633Sdim    unsigned Rn = Inst.getOperand(0).getReg();
7163226633Sdim    bool listContainsBase;
7164226633Sdim    if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
7165226633Sdim      // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7166226633Sdim      assert (isThumbTwo());
7167226633Sdim      Inst.setOpcode(ARM::t2STMIA_UPD);
7168234353Sdim      return true;
7169226633Sdim    }
7170226633Sdim    break;
7171226633Sdim  }
7172234353Sdim  case ARM::tPOP: {
7173234353Sdim    bool listContainsBase;
7174234353Sdim    // If the register list contains any high registers, we need to use
7175234353Sdim    // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7176234353Sdim    // should have generated an error in validateInstruction().
7177234353Sdim    if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
7178234353Sdim      return false;
7179234353Sdim    assert (isThumbTwo());
7180234353Sdim    Inst.setOpcode(ARM::t2LDMIA_UPD);
7181234353Sdim    // Add the base register and writeback operands.
7182234353Sdim    Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7183234353Sdim    Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7184234353Sdim    return true;
7185234353Sdim  }
7186234353Sdim  case ARM::tPUSH: {
7187234353Sdim    bool listContainsBase;
7188234353Sdim    if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
7189234353Sdim      return false;
7190234353Sdim    assert (isThumbTwo());
7191234353Sdim    Inst.setOpcode(ARM::t2STMDB_UPD);
7192234353Sdim    // Add the base register and writeback operands.
7193234353Sdim    Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7194234353Sdim    Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7195234353Sdim    return true;
7196234353Sdim  }
7197226633Sdim  case ARM::t2MOVi: {
7198226633Sdim    // If we can use the 16-bit encoding and the user didn't explicitly
7199226633Sdim    // request the 32-bit variant, transform it here.
7200226633Sdim    if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7201234353Sdim        (unsigned)Inst.getOperand(1).getImm() <= 255 &&
7202226633Sdim        ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
7203226633Sdim         Inst.getOperand(4).getReg() == ARM::CPSR) ||
7204226633Sdim        (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
7205226633Sdim        (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7206226633Sdim         static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7207226633Sdim      // The operands aren't in the same order for tMOVi8...
7208226633Sdim      MCInst TmpInst;
7209226633Sdim      TmpInst.setOpcode(ARM::tMOVi8);
7210226633Sdim      TmpInst.addOperand(Inst.getOperand(0));
7211226633Sdim      TmpInst.addOperand(Inst.getOperand(4));
7212226633Sdim      TmpInst.addOperand(Inst.getOperand(1));
7213226633Sdim      TmpInst.addOperand(Inst.getOperand(2));
7214226633Sdim      TmpInst.addOperand(Inst.getOperand(3));
7215226633Sdim      Inst = TmpInst;
7216234353Sdim      return true;
7217226633Sdim    }
7218226633Sdim    break;
7219226633Sdim  }
7220226633Sdim  case ARM::t2MOVr: {
7221226633Sdim    // If we can use the 16-bit encoding and the user didn't explicitly
7222226633Sdim    // request the 32-bit variant, transform it here.
7223226633Sdim    if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7224226633Sdim        isARMLowRegister(Inst.getOperand(1).getReg()) &&
7225226633Sdim        Inst.getOperand(2).getImm() == ARMCC::AL &&
7226226633Sdim        Inst.getOperand(4).getReg() == ARM::CPSR &&
7227226633Sdim        (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7228226633Sdim         static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7229226633Sdim      // The operands aren't the same for tMOV[S]r... (no cc_out)
7230226633Sdim      MCInst TmpInst;
7231226633Sdim      TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7232226633Sdim      TmpInst.addOperand(Inst.getOperand(0));
7233226633Sdim      TmpInst.addOperand(Inst.getOperand(1));
7234226633Sdim      TmpInst.addOperand(Inst.getOperand(2));
7235226633Sdim      TmpInst.addOperand(Inst.getOperand(3));
7236226633Sdim      Inst = TmpInst;
7237234353Sdim      return true;
7238226633Sdim    }
7239226633Sdim    break;
7240226633Sdim  }
7241226633Sdim  case ARM::t2SXTH:
7242226633Sdim  case ARM::t2SXTB:
7243226633Sdim  case ARM::t2UXTH:
7244226633Sdim  case ARM::t2UXTB: {
7245226633Sdim    // If we can use the 16-bit encoding and the user didn't explicitly
7246226633Sdim    // request the 32-bit variant, transform it here.
7247226633Sdim    if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7248226633Sdim        isARMLowRegister(Inst.getOperand(1).getReg()) &&
7249226633Sdim        Inst.getOperand(2).getImm() == 0 &&
7250226633Sdim        (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7251226633Sdim         static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7252226633Sdim      unsigned NewOpc;
7253226633Sdim      switch (Inst.getOpcode()) {
7254226633Sdim      default: llvm_unreachable("Illegal opcode!");
7255226633Sdim      case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7256226633Sdim      case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7257226633Sdim      case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7258226633Sdim      case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7259226633Sdim      }
7260226633Sdim      // The operands aren't the same for thumb1 (no rotate operand).
7261226633Sdim      MCInst TmpInst;
7262226633Sdim      TmpInst.setOpcode(NewOpc);
7263226633Sdim      TmpInst.addOperand(Inst.getOperand(0));
7264226633Sdim      TmpInst.addOperand(Inst.getOperand(1));
7265226633Sdim      TmpInst.addOperand(Inst.getOperand(3));
7266226633Sdim      TmpInst.addOperand(Inst.getOperand(4));
7267226633Sdim      Inst = TmpInst;
7268234353Sdim      return true;
7269226633Sdim    }
7270226633Sdim    break;
7271226633Sdim  }
7272234353Sdim  case ARM::MOVsi: {
7273234353Sdim    ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
7274239462Sdim    // rrx shifts and asr/lsr of #32 is encoded as 0
7275239462Sdim    if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr)
7276239462Sdim      return false;
7277234353Sdim    if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7278234353Sdim      // Shifting by zero is accepted as a vanilla 'MOVr'
7279234353Sdim      MCInst TmpInst;
7280234353Sdim      TmpInst.setOpcode(ARM::MOVr);
7281234353Sdim      TmpInst.addOperand(Inst.getOperand(0));
7282234353Sdim      TmpInst.addOperand(Inst.getOperand(1));
7283234353Sdim      TmpInst.addOperand(Inst.getOperand(3));
7284234353Sdim      TmpInst.addOperand(Inst.getOperand(4));
7285234353Sdim      TmpInst.addOperand(Inst.getOperand(5));
7286234353Sdim      Inst = TmpInst;
7287234353Sdim      return true;
7288234353Sdim    }
7289234353Sdim    return false;
7290234353Sdim  }
7291234353Sdim  case ARM::ANDrsi:
7292234353Sdim  case ARM::ORRrsi:
7293234353Sdim  case ARM::EORrsi:
7294234353Sdim  case ARM::BICrsi:
7295234353Sdim  case ARM::SUBrsi:
7296234353Sdim  case ARM::ADDrsi: {
7297234353Sdim    unsigned newOpc;
7298234353Sdim    ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7299234353Sdim    if (SOpc == ARM_AM::rrx) return false;
7300234353Sdim    switch (Inst.getOpcode()) {
7301234353Sdim    default: llvm_unreachable("unexpected opcode!");
7302234353Sdim    case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7303234353Sdim    case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7304234353Sdim    case ARM::EORrsi: newOpc = ARM::EORrr; break;
7305234353Sdim    case ARM::BICrsi: newOpc = ARM::BICrr; break;
7306234353Sdim    case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7307234353Sdim    case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7308234353Sdim    }
7309234353Sdim    // If the shift is by zero, use the non-shifted instruction definition.
7310239462Sdim    // The exception is for right shifts, where 0 == 32
7311239462Sdim    if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0 &&
7312239462Sdim        !(SOpc == ARM_AM::lsr || SOpc == ARM_AM::asr)) {
7313234353Sdim      MCInst TmpInst;
7314234353Sdim      TmpInst.setOpcode(newOpc);
7315234353Sdim      TmpInst.addOperand(Inst.getOperand(0));
7316234353Sdim      TmpInst.addOperand(Inst.getOperand(1));
7317234353Sdim      TmpInst.addOperand(Inst.getOperand(2));
7318234353Sdim      TmpInst.addOperand(Inst.getOperand(4));
7319234353Sdim      TmpInst.addOperand(Inst.getOperand(5));
7320234353Sdim      TmpInst.addOperand(Inst.getOperand(6));
7321234353Sdim      Inst = TmpInst;
7322234353Sdim      return true;
7323234353Sdim    }
7324234353Sdim    return false;
7325234353Sdim  }
7326234353Sdim  case ARM::ITasm:
7327226633Sdim  case ARM::t2IT: {
7328226633Sdim    // The mask bits for all but the first condition are represented as
7329226633Sdim    // the low bit of the condition code value implies 't'. We currently
7330226633Sdim    // always have 1 implies 't', so XOR toggle the bits if the low bit
7331239462Sdim    // of the condition code is zero.
7332226633Sdim    MCOperand &MO = Inst.getOperand(1);
7333226633Sdim    unsigned Mask = MO.getImm();
7334226633Sdim    unsigned OrigMask = Mask;
7335226633Sdim    unsigned TZ = CountTrailingZeros_32(Mask);
7336226633Sdim    if ((Inst.getOperand(0).getImm() & 1) == 0) {
7337226633Sdim      assert(Mask && TZ <= 3 && "illegal IT mask value!");
7338226633Sdim      for (unsigned i = 3; i != TZ; --i)
7339226633Sdim        Mask ^= 1 << i;
7340239462Sdim    }
7341226633Sdim    MO.setImm(Mask);
7342226633Sdim
7343226633Sdim    // Set up the IT block state according to the IT instruction we just
7344226633Sdim    // matched.
7345226633Sdim    assert(!inITBlock() && "nested IT blocks?!");
7346226633Sdim    ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7347226633Sdim    ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7348226633Sdim    ITState.CurPosition = 0;
7349226633Sdim    ITState.FirstCond = true;
7350226633Sdim    break;
7351226633Sdim  }
7352239462Sdim  case ARM::t2LSLrr:
7353239462Sdim  case ARM::t2LSRrr:
7354239462Sdim  case ARM::t2ASRrr:
7355239462Sdim  case ARM::t2SBCrr:
7356239462Sdim  case ARM::t2RORrr:
7357239462Sdim  case ARM::t2BICrr:
7358239462Sdim  {
7359239462Sdim    // Assemblers should use the narrow encodings of these instructions when permissible.
7360239462Sdim    if ((isARMLowRegister(Inst.getOperand(1).getReg()) &&
7361239462Sdim         isARMLowRegister(Inst.getOperand(2).getReg())) &&
7362239462Sdim        Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
7363239462Sdim        ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) ||
7364239462Sdim         (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) &&
7365239462Sdim        (!static_cast<ARMOperand*>(Operands[3])->isToken() ||
7366239462Sdim         !static_cast<ARMOperand*>(Operands[3])->getToken().equals_lower(".w"))) {
7367239462Sdim      unsigned NewOpc;
7368239462Sdim      switch (Inst.getOpcode()) {
7369239462Sdim        default: llvm_unreachable("unexpected opcode");
7370239462Sdim        case ARM::t2LSLrr: NewOpc = ARM::tLSLrr; break;
7371239462Sdim        case ARM::t2LSRrr: NewOpc = ARM::tLSRrr; break;
7372239462Sdim        case ARM::t2ASRrr: NewOpc = ARM::tASRrr; break;
7373239462Sdim        case ARM::t2SBCrr: NewOpc = ARM::tSBC; break;
7374239462Sdim        case ARM::t2RORrr: NewOpc = ARM::tROR; break;
7375239462Sdim        case ARM::t2BICrr: NewOpc = ARM::tBIC; break;
7376239462Sdim      }
7377239462Sdim      MCInst TmpInst;
7378239462Sdim      TmpInst.setOpcode(NewOpc);
7379239462Sdim      TmpInst.addOperand(Inst.getOperand(0));
7380239462Sdim      TmpInst.addOperand(Inst.getOperand(5));
7381239462Sdim      TmpInst.addOperand(Inst.getOperand(1));
7382239462Sdim      TmpInst.addOperand(Inst.getOperand(2));
7383239462Sdim      TmpInst.addOperand(Inst.getOperand(3));
7384239462Sdim      TmpInst.addOperand(Inst.getOperand(4));
7385239462Sdim      Inst = TmpInst;
7386239462Sdim      return true;
7387239462Sdim    }
7388239462Sdim    return false;
7389226633Sdim  }
7390239462Sdim  case ARM::t2ANDrr:
7391239462Sdim  case ARM::t2EORrr:
7392239462Sdim  case ARM::t2ADCrr:
7393239462Sdim  case ARM::t2ORRrr:
7394239462Sdim  {
7395239462Sdim    // Assemblers should use the narrow encodings of these instructions when permissible.
7396239462Sdim    // These instructions are special in that they are commutable, so shorter encodings
7397239462Sdim    // are available more often.
7398239462Sdim    if ((isARMLowRegister(Inst.getOperand(1).getReg()) &&
7399239462Sdim         isARMLowRegister(Inst.getOperand(2).getReg())) &&
7400239462Sdim        (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() ||
7401239462Sdim         Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) &&
7402239462Sdim        ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) ||
7403239462Sdim         (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) &&
7404239462Sdim        (!static_cast<ARMOperand*>(Operands[3])->isToken() ||
7405239462Sdim         !static_cast<ARMOperand*>(Operands[3])->getToken().equals_lower(".w"))) {
7406239462Sdim      unsigned NewOpc;
7407239462Sdim      switch (Inst.getOpcode()) {
7408239462Sdim        default: llvm_unreachable("unexpected opcode");
7409239462Sdim        case ARM::t2ADCrr: NewOpc = ARM::tADC; break;
7410239462Sdim        case ARM::t2ANDrr: NewOpc = ARM::tAND; break;
7411239462Sdim        case ARM::t2EORrr: NewOpc = ARM::tEOR; break;
7412239462Sdim        case ARM::t2ORRrr: NewOpc = ARM::tORR; break;
7413239462Sdim      }
7414239462Sdim      MCInst TmpInst;
7415239462Sdim      TmpInst.setOpcode(NewOpc);
7416239462Sdim      TmpInst.addOperand(Inst.getOperand(0));
7417239462Sdim      TmpInst.addOperand(Inst.getOperand(5));
7418239462Sdim      if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) {
7419239462Sdim        TmpInst.addOperand(Inst.getOperand(1));
7420239462Sdim        TmpInst.addOperand(Inst.getOperand(2));
7421239462Sdim      } else {
7422239462Sdim        TmpInst.addOperand(Inst.getOperand(2));
7423239462Sdim        TmpInst.addOperand(Inst.getOperand(1));
7424239462Sdim      }
7425239462Sdim      TmpInst.addOperand(Inst.getOperand(3));
7426239462Sdim      TmpInst.addOperand(Inst.getOperand(4));
7427239462Sdim      Inst = TmpInst;
7428239462Sdim      return true;
7429239462Sdim    }
7430239462Sdim    return false;
7431239462Sdim  }
7432239462Sdim  }
7433234353Sdim  return false;
7434226633Sdim}
7435226633Sdim
7436226633Sdimunsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7437226633Sdim  // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7438226633Sdim  // suffix depending on whether they're in an IT block or not.
7439226633Sdim  unsigned Opc = Inst.getOpcode();
7440234353Sdim  const MCInstrDesc &MCID = getInstDesc(Opc);
7441226633Sdim  if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7442226633Sdim    assert(MCID.hasOptionalDef() &&
7443226633Sdim           "optionally flag setting instruction missing optional def operand");
7444226633Sdim    assert(MCID.NumOperands == Inst.getNumOperands() &&
7445226633Sdim           "operand count mismatch!");
7446226633Sdim    // Find the optional-def operand (cc_out).
7447226633Sdim    unsigned OpNo;
7448226633Sdim    for (OpNo = 0;
7449226633Sdim         !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7450226633Sdim         ++OpNo)
7451226633Sdim      ;
7452226633Sdim    // If we're parsing Thumb1, reject it completely.
7453226633Sdim    if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7454226633Sdim      return Match_MnemonicFail;
7455226633Sdim    // If we're parsing Thumb2, which form is legal depends on whether we're
7456226633Sdim    // in an IT block.
7457226633Sdim    if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7458226633Sdim        !inITBlock())
7459226633Sdim      return Match_RequiresITBlock;
7460226633Sdim    if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7461226633Sdim        inITBlock())
7462226633Sdim      return Match_RequiresNotITBlock;
7463226633Sdim  }
7464226633Sdim  // Some high-register supporting Thumb1 encodings only allow both registers
7465226633Sdim  // to be from r0-r7 when in Thumb2.
7466226633Sdim  else if (Opc == ARM::tADDhirr && isThumbOne() &&
7467226633Sdim           isARMLowRegister(Inst.getOperand(1).getReg()) &&
7468226633Sdim           isARMLowRegister(Inst.getOperand(2).getReg()))
7469226633Sdim    return Match_RequiresThumb2;
7470226633Sdim  // Others only require ARMv6 or later.
7471226633Sdim  else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
7472226633Sdim           isARMLowRegister(Inst.getOperand(0).getReg()) &&
7473226633Sdim           isARMLowRegister(Inst.getOperand(1).getReg()))
7474226633Sdim    return Match_RequiresV6;
7475226633Sdim  return Match_Success;
7476226633Sdim}
7477226633Sdim
7478239462Sdimstatic const char *getSubtargetFeatureName(unsigned Val);
7479226633Sdimbool ARMAsmParser::
7480243830SdimMatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
7481218893Sdim                        SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7482243830Sdim                        MCStreamer &Out, unsigned &ErrorInfo,
7483243830Sdim                        bool MatchingInlineAsm) {
7484218893Sdim  MCInst Inst;
7485226633Sdim  unsigned MatchResult;
7486243830Sdim  MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
7487243830Sdim                                     MatchingInlineAsm);
7488218893Sdim  switch (MatchResult) {
7489226633Sdim  default: break;
7490218893Sdim  case Match_Success:
7491226633Sdim    // Context sensitive operand constraints aren't handled by the matcher,
7492226633Sdim    // so check them here.
7493226633Sdim    if (validateInstruction(Inst, Operands)) {
7494226633Sdim      // Still progress the IT block, otherwise one wrong condition causes
7495226633Sdim      // nasty cascading errors.
7496226633Sdim      forwardITPosition();
7497226633Sdim      return true;
7498226633Sdim    }
7499226633Sdim
7500226633Sdim    // Some instructions need post-processing to, for example, tweak which
7501234353Sdim    // encoding is selected. Loop on it while changes happen so the
7502234353Sdim    // individual transformations can chain off each other. E.g.,
7503234353Sdim    // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7504234353Sdim    while (processInstruction(Inst, Operands))
7505234353Sdim      ;
7506226633Sdim
7507226633Sdim    // Only move forward at the very end so that everything in validate
7508226633Sdim    // and process gets a consistent answer about whether we're in an IT
7509226633Sdim    // block.
7510226633Sdim    forwardITPosition();
7511226633Sdim
7512234353Sdim    // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7513234353Sdim    // doesn't actually encode.
7514234353Sdim    if (Inst.getOpcode() == ARM::ITasm)
7515234353Sdim      return false;
7516234353Sdim
7517234353Sdim    Inst.setLoc(IDLoc);
7518218893Sdim    Out.EmitInstruction(Inst);
7519218893Sdim    return false;
7520239462Sdim  case Match_MissingFeature: {
7521239462Sdim    assert(ErrorInfo && "Unknown missing feature!");
7522239462Sdim    // Special case the error message for the very common case where only
7523239462Sdim    // a single subtarget feature is missing (Thumb vs. ARM, e.g.).
7524239462Sdim    std::string Msg = "instruction requires:";
7525239462Sdim    unsigned Mask = 1;
7526239462Sdim    for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
7527239462Sdim      if (ErrorInfo & Mask) {
7528239462Sdim        Msg += " ";
7529239462Sdim        Msg += getSubtargetFeatureName(ErrorInfo & Mask);
7530239462Sdim      }
7531239462Sdim      Mask <<= 1;
7532239462Sdim    }
7533239462Sdim    return Error(IDLoc, Msg);
7534239462Sdim  }
7535218893Sdim  case Match_InvalidOperand: {
7536218893Sdim    SMLoc ErrorLoc = IDLoc;
7537218893Sdim    if (ErrorInfo != ~0U) {
7538218893Sdim      if (ErrorInfo >= Operands.size())
7539218893Sdim        return Error(IDLoc, "too few operands for instruction");
7540218893Sdim
7541218893Sdim      ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7542218893Sdim      if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7543218893Sdim    }
7544218893Sdim
7545218893Sdim    return Error(ErrorLoc, "invalid operand for instruction");
7546218893Sdim  }
7547218893Sdim  case Match_MnemonicFail:
7548234982Sdim    return Error(IDLoc, "invalid instruction",
7549234982Sdim                 ((ARMOperand*)Operands[0])->getLocRange());
7550226633Sdim  case Match_RequiresNotITBlock:
7551226633Sdim    return Error(IDLoc, "flag setting instruction only valid outside IT block");
7552226633Sdim  case Match_RequiresITBlock:
7553226633Sdim    return Error(IDLoc, "instruction only valid inside IT block");
7554226633Sdim  case Match_RequiresV6:
7555226633Sdim    return Error(IDLoc, "instruction variant requires ARMv6 or later");
7556226633Sdim  case Match_RequiresThumb2:
7557226633Sdim    return Error(IDLoc, "instruction variant requires Thumb2");
7558239462Sdim  case Match_ImmRange0_15: {
7559239462Sdim    SMLoc ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7560239462Sdim    if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7561239462Sdim    return Error(ErrorLoc, "immediate operand must be in the range [0,15]");
7562218893Sdim  }
7563239462Sdim  }
7564218893Sdim
7565218893Sdim  llvm_unreachable("Implement any new match types added!");
7566218893Sdim}
7567218893Sdim
7568226633Sdim/// parseDirective parses the arm specific directives
7569198090Srdivackybool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7570198090Srdivacky  StringRef IDVal = DirectiveID.getIdentifier();
7571198090Srdivacky  if (IDVal == ".word")
7572226633Sdim    return parseDirectiveWord(4, DirectiveID.getLoc());
7573198396Srdivacky  else if (IDVal == ".thumb")
7574226633Sdim    return parseDirectiveThumb(DirectiveID.getLoc());
7575234353Sdim  else if (IDVal == ".arm")
7576234353Sdim    return parseDirectiveARM(DirectiveID.getLoc());
7577198396Srdivacky  else if (IDVal == ".thumb_func")
7578226633Sdim    return parseDirectiveThumbFunc(DirectiveID.getLoc());
7579198396Srdivacky  else if (IDVal == ".code")
7580226633Sdim    return parseDirectiveCode(DirectiveID.getLoc());
7581198396Srdivacky  else if (IDVal == ".syntax")
7582226633Sdim    return parseDirectiveSyntax(DirectiveID.getLoc());
7583234353Sdim  else if (IDVal == ".unreq")
7584234353Sdim    return parseDirectiveUnreq(DirectiveID.getLoc());
7585234353Sdim  else if (IDVal == ".arch")
7586234353Sdim    return parseDirectiveArch(DirectiveID.getLoc());
7587234353Sdim  else if (IDVal == ".eabi_attribute")
7588234353Sdim    return parseDirectiveEabiAttr(DirectiveID.getLoc());
7589198090Srdivacky  return true;
7590198090Srdivacky}
7591198090Srdivacky
7592226633Sdim/// parseDirectiveWord
7593198090Srdivacky///  ::= .word [ expression (, expression)* ]
7594226633Sdimbool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
7595198090Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement)) {
7596198090Srdivacky    for (;;) {
7597198090Srdivacky      const MCExpr *Value;
7598198090Srdivacky      if (getParser().ParseExpression(Value))
7599198090Srdivacky        return true;
7600198090Srdivacky
7601202878Srdivacky      getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
7602198090Srdivacky
7603198090Srdivacky      if (getLexer().is(AsmToken::EndOfStatement))
7604198090Srdivacky        break;
7605218893Sdim
7606198090Srdivacky      // FIXME: Improve diagnostic.
7607198090Srdivacky      if (getLexer().isNot(AsmToken::Comma))
7608198090Srdivacky        return Error(L, "unexpected token in directive");
7609202878Srdivacky      Parser.Lex();
7610198090Srdivacky    }
7611198090Srdivacky  }
7612198090Srdivacky
7613202878Srdivacky  Parser.Lex();
7614198090Srdivacky  return false;
7615198090Srdivacky}
7616198090Srdivacky
7617226633Sdim/// parseDirectiveThumb
7618198396Srdivacky///  ::= .thumb
7619226633Sdimbool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
7620198396Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement))
7621198396Srdivacky    return Error(L, "unexpected token in directive");
7622202878Srdivacky  Parser.Lex();
7623198396Srdivacky
7624234353Sdim  if (!isThumb())
7625234353Sdim    SwitchMode();
7626234353Sdim  getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7627198396Srdivacky  return false;
7628198396Srdivacky}
7629198396Srdivacky
7630234353Sdim/// parseDirectiveARM
7631234353Sdim///  ::= .arm
7632234353Sdimbool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7633234353Sdim  if (getLexer().isNot(AsmToken::EndOfStatement))
7634234353Sdim    return Error(L, "unexpected token in directive");
7635234353Sdim  Parser.Lex();
7636234353Sdim
7637234353Sdim  if (isThumb())
7638234353Sdim    SwitchMode();
7639234353Sdim  getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
7640234353Sdim  return false;
7641234353Sdim}
7642234353Sdim
7643226633Sdim/// parseDirectiveThumbFunc
7644198396Srdivacky///  ::= .thumbfunc symbol_name
7645226633Sdimbool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
7646223017Sdim  const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7647223017Sdim  bool isMachO = MAI.hasSubsectionsViaSymbols();
7648223017Sdim  StringRef Name;
7649234353Sdim  bool needFuncName = true;
7650223017Sdim
7651234353Sdim  // Darwin asm has (optionally) function name after .thumb_func direction
7652223017Sdim  // ELF doesn't
7653223017Sdim  if (isMachO) {
7654223017Sdim    const AsmToken &Tok = Parser.getTok();
7655234353Sdim    if (Tok.isNot(AsmToken::EndOfStatement)) {
7656234353Sdim      if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7657234353Sdim        return Error(L, "unexpected token in .thumb_func directive");
7658234353Sdim      Name = Tok.getIdentifier();
7659234353Sdim      Parser.Lex(); // Consume the identifier token.
7660234353Sdim      needFuncName = false;
7661234353Sdim    }
7662223017Sdim  }
7663223017Sdim
7664198396Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement))
7665198396Srdivacky    return Error(L, "unexpected token in directive");
7666198396Srdivacky
7667234353Sdim  // Eat the end of statement and any blank lines that follow.
7668234353Sdim  while (getLexer().is(AsmToken::EndOfStatement))
7669234353Sdim    Parser.Lex();
7670234353Sdim
7671223017Sdim  // FIXME: assuming function name will be the line following .thumb_func
7672234353Sdim  // We really should be checking the next symbol definition even if there's
7673234353Sdim  // stuff in between.
7674234353Sdim  if (needFuncName) {
7675234353Sdim    Name = Parser.getTok().getIdentifier();
7676223017Sdim  }
7677223017Sdim
7678218893Sdim  // Mark symbol as a thumb symbol.
7679218893Sdim  MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7680218893Sdim  getParser().getStreamer().EmitThumbFunc(Func);
7681198396Srdivacky  return false;
7682198396Srdivacky}
7683198396Srdivacky
7684226633Sdim/// parseDirectiveSyntax
7685198396Srdivacky///  ::= .syntax unified | divided
7686226633Sdimbool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
7687202878Srdivacky  const AsmToken &Tok = Parser.getTok();
7688198396Srdivacky  if (Tok.isNot(AsmToken::Identifier))
7689198396Srdivacky    return Error(L, "unexpected token in .syntax directive");
7690210299Sed  StringRef Mode = Tok.getString();
7691210299Sed  if (Mode == "unified" || Mode == "UNIFIED")
7692202878Srdivacky    Parser.Lex();
7693210299Sed  else if (Mode == "divided" || Mode == "DIVIDED")
7694218893Sdim    return Error(L, "'.syntax divided' arm asssembly not supported");
7695198396Srdivacky  else
7696198396Srdivacky    return Error(L, "unrecognized syntax mode in .syntax directive");
7697198396Srdivacky
7698198396Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement))
7699202878Srdivacky    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
7700202878Srdivacky  Parser.Lex();
7701198396Srdivacky
7702198396Srdivacky  // TODO tell the MC streamer the mode
7703198396Srdivacky  // getParser().getStreamer().Emit???();
7704198396Srdivacky  return false;
7705198396Srdivacky}
7706198396Srdivacky
7707226633Sdim/// parseDirectiveCode
7708198396Srdivacky///  ::= .code 16 | 32
7709226633Sdimbool ARMAsmParser::parseDirectiveCode(SMLoc L) {
7710202878Srdivacky  const AsmToken &Tok = Parser.getTok();
7711198396Srdivacky  if (Tok.isNot(AsmToken::Integer))
7712198396Srdivacky    return Error(L, "unexpected token in .code directive");
7713202878Srdivacky  int64_t Val = Parser.getTok().getIntVal();
7714210299Sed  if (Val == 16)
7715202878Srdivacky    Parser.Lex();
7716210299Sed  else if (Val == 32)
7717202878Srdivacky    Parser.Lex();
7718198396Srdivacky  else
7719198396Srdivacky    return Error(L, "invalid operand to .code directive");
7720198396Srdivacky
7721198396Srdivacky  if (getLexer().isNot(AsmToken::EndOfStatement))
7722202878Srdivacky    return Error(Parser.getTok().getLoc(), "unexpected token in directive");
7723202878Srdivacky  Parser.Lex();
7724198396Srdivacky
7725224145Sdim  if (Val == 16) {
7726224145Sdim    if (!isThumb())
7727224145Sdim      SwitchMode();
7728218893Sdim    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7729224145Sdim  } else {
7730224145Sdim    if (isThumb())
7731224145Sdim      SwitchMode();
7732224145Sdim    getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
7733218893Sdim  }
7734218893Sdim
7735198396Srdivacky  return false;
7736198396Srdivacky}
7737198396Srdivacky
7738234353Sdim/// parseDirectiveReq
7739234353Sdim///  ::= name .req registername
7740234353Sdimbool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7741234353Sdim  Parser.Lex(); // Eat the '.req' token.
7742234353Sdim  unsigned Reg;
7743234353Sdim  SMLoc SRegLoc, ERegLoc;
7744234353Sdim  if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7745234353Sdim    Parser.EatToEndOfStatement();
7746234353Sdim    return Error(SRegLoc, "register name expected");
7747234353Sdim  }
7748234353Sdim
7749234353Sdim  // Shouldn't be anything else.
7750234353Sdim  if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7751234353Sdim    Parser.EatToEndOfStatement();
7752234353Sdim    return Error(Parser.getTok().getLoc(),
7753234353Sdim                 "unexpected input in .req directive.");
7754234353Sdim  }
7755234353Sdim
7756234353Sdim  Parser.Lex(); // Consume the EndOfStatement
7757234353Sdim
7758234353Sdim  if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7759234353Sdim    return Error(SRegLoc, "redefinition of '" + Name +
7760234353Sdim                          "' does not match original.");
7761234353Sdim
7762234353Sdim  return false;
7763234353Sdim}
7764234353Sdim
7765234353Sdim/// parseDirectiveUneq
7766234353Sdim///  ::= .unreq registername
7767234353Sdimbool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7768234353Sdim  if (Parser.getTok().isNot(AsmToken::Identifier)) {
7769234353Sdim    Parser.EatToEndOfStatement();
7770234353Sdim    return Error(L, "unexpected input in .unreq directive.");
7771234353Sdim  }
7772234353Sdim  RegisterReqs.erase(Parser.getTok().getIdentifier());
7773234353Sdim  Parser.Lex(); // Eat the identifier.
7774234353Sdim  return false;
7775234353Sdim}
7776234353Sdim
7777234353Sdim/// parseDirectiveArch
7778234353Sdim///  ::= .arch token
7779234353Sdimbool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7780234353Sdim  return true;
7781234353Sdim}
7782234353Sdim
7783234353Sdim/// parseDirectiveEabiAttr
7784234353Sdim///  ::= .eabi_attribute int, int
7785234353Sdimbool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7786234353Sdim  return true;
7787234353Sdim}
7788234353Sdim
7789207618Srdivackyextern "C" void LLVMInitializeARMAsmLexer();
7790207618Srdivacky
7791198892Srdivacky/// Force static initialization.
7792198090Srdivackyextern "C" void LLVMInitializeARMAsmParser() {
7793226633Sdim  RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7794226633Sdim  RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
7795207618Srdivacky  LLVMInitializeARMAsmLexer();
7796198090Srdivacky}
7797212904Sdim
7798218893Sdim#define GET_REGISTER_MATCHER
7799239462Sdim#define GET_SUBTARGET_FEATURE_NAME
7800218893Sdim#define GET_MATCHER_IMPLEMENTATION
7801212904Sdim#include "ARMGenAsmMatcher.inc"
7802