blob: d375e357aea3246e6c78fa92463f781b8dce530c [file] [log] [blame]
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00001//===-- ARMAsmParser.cpp - Parse ARM assembly to MCInst instructions ------===//
2//
3// The LLVM Compiler Infrastructure
4//
5// This file is distributed under the University of Illinois Open Source
6// License. See LICENSE.TXT for details.
7//
8//===----------------------------------------------------------------------===//
9
Evan Cheng94b95502011-07-26 00:24:13 +000010#include "MCTargetDesc/ARMBaseInfo.h"
Evan Chengee04a6d2011-07-20 23:34:39 +000011#include "MCTargetDesc/ARMAddressingModes.h"
12#include "MCTargetDesc/ARMMCExpr.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000013#include "llvm/MC/MCParser/MCAsmLexer.h"
14#include "llvm/MC/MCParser/MCAsmParser.h"
15#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Rafael Espindola64695402011-05-16 16:17:21 +000016#include "llvm/MC/MCAsmInfo.h"
Jim Grosbach642fc9c2010-11-05 22:33:53 +000017#include "llvm/MC/MCContext.h"
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000018#include "llvm/MC/MCStreamer.h"
19#include "llvm/MC/MCExpr.h"
20#include "llvm/MC/MCInst.h"
Evan Cheng78011362011-08-23 20:15:21 +000021#include "llvm/MC/MCInstrDesc.h"
Evan Cheng94b95502011-07-26 00:24:13 +000022#include "llvm/MC/MCRegisterInfo.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000023#include "llvm/MC/MCSubtargetInfo.h"
Evan Cheng94b95502011-07-26 00:24:13 +000024#include "llvm/MC/MCTargetAsmParser.h"
Jim Grosbach89df9962011-08-26 21:43:41 +000025#include "llvm/Support/MathExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000026#include "llvm/Support/SourceMgr.h"
Evan Cheng3e74d6f2011-08-24 18:08:43 +000027#include "llvm/Support/TargetRegistry.h"
Daniel Dunbarfa315de2010-08-11 06:37:12 +000028#include "llvm/Support/raw_ostream.h"
Jim Grosbach11e03e72011-08-22 18:50:36 +000029#include "llvm/ADT/BitVector.h"
Benjamin Kramer75ca4b92011-07-08 21:06:23 +000030#include "llvm/ADT/OwningPtr.h"
Evan Cheng94b95502011-07-26 00:24:13 +000031#include "llvm/ADT/STLExtras.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000032#include "llvm/ADT/SmallVector.h"
Daniel Dunbar345a9a62010-08-11 06:37:20 +000033#include "llvm/ADT/StringSwitch.h"
Chris Lattnerc6ef2772010-01-22 01:44:57 +000034#include "llvm/ADT/Twine.h"
Evan Chengebdeeab2011-07-08 01:53:10 +000035
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000036using namespace llvm;
37
Chris Lattner3a697562010-10-28 17:20:03 +000038namespace {
Bill Wendling146018f2010-11-06 21:42:12 +000039
40class ARMOperand;
Jim Grosbach16c74252010-10-29 14:46:02 +000041
Jim Grosbach7636bf62011-12-02 00:35:16 +000042enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbach98b05a52011-11-30 01:09:44 +000043
Evan Cheng94b95502011-07-26 00:24:13 +000044class ARMAsmParser : public MCTargetAsmParser {
Evan Chengffc0e732011-07-09 05:47:46 +000045 MCSubtargetInfo &STI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000046 MCAsmParser &Parser;
Jim Grosbach28f08c92012-03-05 19:33:30 +000047 const MCRegisterInfo *MRI;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000048
Jim Grosbacha39cda72011-12-14 02:16:11 +000049 // Map of register aliases registers via the .req directive.
50 StringMap<unsigned> RegisterReqs;
51
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000052 struct {
53 ARMCC::CondCodes Cond; // Condition for IT block.
54 unsigned Mask:4; // Condition mask for instructions.
55 // Starting at first 1 (from lsb).
56 // '1' condition as indicated in IT.
57 // '0' inverse of condition (else).
58 // Count of instructions in IT block is
59 // 4 - trailingzeroes(mask)
60
61 bool FirstCond; // Explicit flag for when we're parsing the
62 // First instruction in the IT block. It's
63 // implied in the mask, so needs special
64 // handling.
65
66 unsigned CurPosition; // Current position in parsing of IT
67 // block. In range [0,3]. Initialized
68 // according to count of instructions in block.
69 // ~0U if no active IT block.
70 } ITState;
71 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha1109882011-09-02 23:22:08 +000072 void forwardITPosition() {
73 if (!inITBlock()) return;
74 // Move to the next instruction in the IT block, if there is one. If not,
75 // mark the block as done.
76 unsigned TZ = CountTrailingZeros_32(ITState.Mask);
77 if (++ITState.CurPosition == 5 - TZ)
78 ITState.CurPosition = ~0U; // Done with the IT block after this.
79 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +000080
81
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000082 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000083 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
84
Benjamin Kramer362a05a2012-04-15 17:04:27 +000085 bool Warning(SMLoc L, const Twine &Msg,
86 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
87 return Parser.Warning(L, Msg, Ranges);
88 }
89 bool Error(SMLoc L, const Twine &Msg,
90 ArrayRef<SMRange> Ranges = ArrayRef<SMRange>()) {
91 return Parser.Error(L, Msg, Ranges);
92 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +000093
Jim Grosbach1355cf12011-07-26 17:10:22 +000094 int tryParseRegister();
95 bool tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach0d87ec22011-07-26 20:41:24 +000096 int tryParseShiftRegister(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000097 bool parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +000098 bool parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +000099 bool parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &, StringRef Mnemonic);
100 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000101 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
102 unsigned &ShiftAmount);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000103 bool parseDirectiveWord(unsigned Size, SMLoc L);
104 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach9a70df92011-12-07 18:04:19 +0000105 bool parseDirectiveARM(SMLoc L);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000106 bool parseDirectiveThumbFunc(SMLoc L);
107 bool parseDirectiveCode(SMLoc L);
108 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbacha39cda72011-12-14 02:16:11 +0000109 bool parseDirectiveReq(StringRef Name, SMLoc L);
110 bool parseDirectiveUnreq(SMLoc L);
Jason W Kimd7c9e082011-12-20 17:38:12 +0000111 bool parseDirectiveArch(SMLoc L);
112 bool parseDirectiveEabiAttr(SMLoc L);
Kevin Enderby515d5092009-10-15 20:48:48 +0000113
Jim Grosbach1355cf12011-07-26 17:10:22 +0000114 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach89df9962011-08-26 21:43:41 +0000115 bool &CarrySetting, unsigned &ProcessorIMod,
116 StringRef &ITMask);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000117 void getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +0000118 bool &CanAcceptPredicationCode);
Jim Grosbach16c74252010-10-29 14:46:02 +0000119
Evan Chengebdeeab2011-07-08 01:53:10 +0000120 bool isThumb() const {
121 // FIXME: Can tablegen auto-generate this?
Evan Chengffc0e732011-07-09 05:47:46 +0000122 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000123 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000124 bool isThumbOne() const {
Evan Chengffc0e732011-07-09 05:47:46 +0000125 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Chengebdeeab2011-07-08 01:53:10 +0000126 }
Jim Grosbach47a0d522011-08-16 20:45:50 +0000127 bool isThumbTwo() const {
128 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
129 }
Jim Grosbach194bd892011-08-16 22:20:01 +0000130 bool hasV6Ops() const {
131 return STI.getFeatureBits() & ARM::HasV6Ops;
132 }
James Molloyacad68d2011-09-28 14:21:38 +0000133 bool hasV7Ops() const {
134 return STI.getFeatureBits() & ARM::HasV7Ops;
135 }
Evan Cheng32869202011-07-08 22:36:29 +0000136 void SwitchMode() {
Evan Chengffc0e732011-07-09 05:47:46 +0000137 unsigned FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
138 setAvailableFeatures(FB);
Evan Cheng32869202011-07-08 22:36:29 +0000139 }
James Molloyacad68d2011-09-28 14:21:38 +0000140 bool isMClass() const {
141 return STI.getFeatureBits() & ARM::FeatureMClass;
142 }
Evan Chengebdeeab2011-07-08 01:53:10 +0000143
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000144 /// @name Auto-generated Match Functions
145 /// {
Daniel Dunbar3483aca2010-08-11 05:24:50 +0000146
Chris Lattner0692ee62010-09-06 19:11:01 +0000147#define GET_ASSEMBLER_HEADER
148#include "ARMGenAsmMatcher.inc"
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000149
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000150 /// }
151
Jim Grosbach89df9962011-08-26 21:43:41 +0000152 OperandMatchResultTy parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000153 OperandMatchResultTy parseCoprocNumOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000154 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000155 OperandMatchResultTy parseCoprocRegOperand(
Jim Grosbachf922c472011-02-12 01:34:40 +0000156 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000157 OperandMatchResultTy parseCoprocOptionOperand(
158 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000159 OperandMatchResultTy parseMemBarrierOptOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000160 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000161 OperandMatchResultTy parseProcIFlagsOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000162 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach43904292011-07-25 20:14:50 +0000163 OperandMatchResultTy parseMSRMaskOperand(
Bruno Cardoso Lopes8bba1a52011-02-18 19:49:06 +0000164 SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbachf6c05252011-07-21 17:23:04 +0000165 OperandMatchResultTy parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &O,
166 StringRef Op, int Low, int High);
167 OperandMatchResultTy parsePKHLSLImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
168 return parsePKHImm(O, "lsl", 0, 31);
169 }
170 OperandMatchResultTy parsePKHASRImm(SmallVectorImpl<MCParsedAsmOperand*> &O) {
171 return parsePKHImm(O, "asr", 1, 32);
172 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000173 OperandMatchResultTy parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach580f4a92011-07-25 22:20:28 +0000174 OperandMatchResultTy parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000175 OperandMatchResultTy parseRotImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000176 OperandMatchResultTy parseBitfield(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000177 OperandMatchResultTy parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach251bf252011-08-10 21:56:18 +0000178 OperandMatchResultTy parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach9d390362011-10-03 23:38:36 +0000179 OperandMatchResultTy parseFPImm(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach862019c2011-10-18 23:02:30 +0000180 OperandMatchResultTy parseVectorList(SmallVectorImpl<MCParsedAsmOperand*>&);
Jim Grosbach7636bf62011-12-02 00:35:16 +0000181 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000182
183 // Asm Match Converter Methods
Jim Grosbacha77295d2011-09-08 22:07:06 +0000184 bool cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
185 const SmallVectorImpl<MCParsedAsmOperand*> &);
186 bool cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
187 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbacheeec0252011-09-08 00:39:19 +0000188 bool cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
189 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbachee2c2a42011-09-16 21:55:56 +0000190 bool cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
191 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000192 bool cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000193 const SmallVectorImpl<MCParsedAsmOperand*> &);
Owen Anderson9ab0f252011-08-26 20:43:14 +0000194 bool cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
195 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach548340c2011-08-11 19:22:40 +0000196 bool cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
197 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000198 bool cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000199 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7b8f46c2011-08-11 21:17:22 +0000200 bool cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
201 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach7ce05792011-08-03 23:50:40 +0000202 bool cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
203 const SmallVectorImpl<MCParsedAsmOperand*> &);
204 bool cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
205 const SmallVectorImpl<MCParsedAsmOperand*> &);
206 bool cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
207 const SmallVectorImpl<MCParsedAsmOperand*> &);
208 bool cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
209 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000210 bool cvtLdrdPre(MCInst &Inst, unsigned Opcode,
211 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach14605d12011-08-11 20:28:23 +0000212 bool cvtStrdPre(MCInst &Inst, unsigned Opcode,
213 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach623a4542011-08-10 22:42:16 +0000214 bool cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
215 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach88ae2bc2011-08-19 22:07:46 +0000216 bool cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
217 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach12431322011-10-24 22:16:58 +0000218 bool cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
219 const SmallVectorImpl<MCParsedAsmOperand*> &);
220 bool cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
221 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach4334e032011-10-31 21:50:31 +0000222 bool cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
223 const SmallVectorImpl<MCParsedAsmOperand*> &);
224 bool cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
225 const SmallVectorImpl<MCParsedAsmOperand*> &);
Jim Grosbach189610f2011-07-26 18:25:39 +0000226
227 bool validateInstruction(MCInst &Inst,
228 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbach83ec8772011-11-10 23:42:14 +0000229 bool processInstruction(MCInst &Inst,
Jim Grosbachf8fce712011-08-11 17:35:48 +0000230 const SmallVectorImpl<MCParsedAsmOperand*> &Ops);
Jim Grosbachd54b4e62011-08-16 21:12:37 +0000231 bool shouldOmitCCOutOperand(StringRef Mnemonic,
232 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach189610f2011-07-26 18:25:39 +0000233
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000234public:
Jim Grosbach47a0d522011-08-16 20:45:50 +0000235 enum ARMMatchResultTy {
Jim Grosbach194bd892011-08-16 22:20:01 +0000236 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000237 Match_RequiresNotITBlock,
Jim Grosbach194bd892011-08-16 22:20:01 +0000238 Match_RequiresV6,
Jim Grosbach70c9bf32012-06-22 23:56:48 +0000239 Match_RequiresThumb2,
240#define GET_OPERAND_DIAGNOSTIC_TYPES
241#include "ARMGenAsmMatcher.inc"
242
Jim Grosbach47a0d522011-08-16 20:45:50 +0000243 };
244
Evan Chengffc0e732011-07-09 05:47:46 +0000245 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser)
Evan Cheng94b95502011-07-26 00:24:13 +0000246 : MCTargetAsmParser(), STI(_STI), Parser(_Parser) {
Evan Chengebdeeab2011-07-08 01:53:10 +0000247 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng32869202011-07-08 22:36:29 +0000248
Jim Grosbach28f08c92012-03-05 19:33:30 +0000249 // Cache the MCRegisterInfo.
250 MRI = &getContext().getRegisterInfo();
251
Evan Chengebdeeab2011-07-08 01:53:10 +0000252 // Initialize the set of available features.
Evan Chengffc0e732011-07-09 05:47:46 +0000253 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +0000254
255 // Not in an ITBlock to start with.
256 ITState.CurPosition = ~0U;
Evan Chengebdeeab2011-07-08 01:53:10 +0000257 }
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000258
Jim Grosbach1355cf12011-07-26 17:10:22 +0000259 // Implementation of the MCTargetAsmParser interface:
260 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc);
261 bool ParseInstruction(StringRef Name, SMLoc NameLoc,
Jim Grosbach189610f2011-07-26 18:25:39 +0000262 SmallVectorImpl<MCParsedAsmOperand*> &Operands);
Jim Grosbach1355cf12011-07-26 17:10:22 +0000263 bool ParseDirective(AsmToken DirectiveID);
264
Jim Grosbach47a0d522011-08-16 20:45:50 +0000265 unsigned checkTargetMatchPredicate(MCInst &Inst);
266
Jim Grosbach1355cf12011-07-26 17:10:22 +0000267 bool MatchAndEmitInstruction(SMLoc IDLoc,
268 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
269 MCStreamer &Out);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +0000270};
Jim Grosbach16c74252010-10-29 14:46:02 +0000271} // end anonymous namespace
272
Chris Lattner3a697562010-10-28 17:20:03 +0000273namespace {
274
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000275/// ARMOperand - Instances of this class represent a parsed ARM machine
276/// instruction.
Bill Wendling146018f2010-11-06 21:42:12 +0000277class ARMOperand : public MCParsedAsmOperand {
Sean Callanan76264762010-04-02 22:27:05 +0000278 enum KindTy {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000279 k_CondCode,
280 k_CCOut,
281 k_ITCondMask,
282 k_CoprocNum,
283 k_CoprocReg,
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000284 k_CoprocOption,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000285 k_Immediate,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000286 k_MemBarrierOpt,
287 k_Memory,
288 k_PostIndexRegister,
289 k_MSRMask,
290 k_ProcIFlags,
Jim Grosbach460a9052011-10-07 23:56:00 +0000291 k_VectorIndex,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000292 k_Register,
293 k_RegisterList,
294 k_DPRRegisterList,
295 k_SPRRegisterList,
Jim Grosbach862019c2011-10-18 23:02:30 +0000296 k_VectorList,
Jim Grosbach98b05a52011-11-30 01:09:44 +0000297 k_VectorListAllLanes,
Jim Grosbach7636bf62011-12-02 00:35:16 +0000298 k_VectorListIndexed,
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000299 k_ShiftedRegister,
300 k_ShiftedImmediate,
301 k_ShifterImmediate,
302 k_RotateImmediate,
303 k_BitfieldDescriptor,
304 k_Token
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000305 } Kind;
306
Sean Callanan76264762010-04-02 22:27:05 +0000307 SMLoc StartLoc, EndLoc;
Bill Wendling24d22d22010-11-18 21:50:54 +0000308 SmallVector<unsigned, 8> Registers;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000309
310 union {
311 struct {
Daniel Dunbar8462b302010-08-11 06:36:53 +0000312 ARMCC::CondCodes Val;
313 } CC;
314
315 struct {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000316 unsigned Val;
317 } Cop;
318
319 struct {
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000320 unsigned Val;
321 } CoprocOption;
322
323 struct {
Jim Grosbach89df9962011-08-26 21:43:41 +0000324 unsigned Mask:4;
325 } ITMask;
326
327 struct {
328 ARM_MB::MemBOpt Val;
329 } MBOpt;
330
331 struct {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000332 ARM_PROC::IFlags Val;
333 } IFlags;
334
335 struct {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000336 unsigned Val;
337 } MMask;
338
339 struct {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000340 const char *Data;
341 unsigned Length;
342 } Tok;
343
344 struct {
345 unsigned RegNum;
346 } Reg;
347
Jim Grosbach862019c2011-10-18 23:02:30 +0000348 // A vector register list is a sequential list of 1 to 4 registers.
349 struct {
350 unsigned RegNum;
351 unsigned Count;
Jim Grosbach7636bf62011-12-02 00:35:16 +0000352 unsigned LaneIndex;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +0000353 bool isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +0000354 } VectorList;
355
Bill Wendling8155e5b2010-11-06 22:19:43 +0000356 struct {
Jim Grosbach460a9052011-10-07 23:56:00 +0000357 unsigned Val;
358 } VectorIndex;
359
360 struct {
Kevin Enderbycfe07242009-10-13 22:19:02 +0000361 const MCExpr *Val;
362 } Imm;
Jim Grosbach16c74252010-10-29 14:46:02 +0000363
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +0000364 /// Combined record for all forms of ARM address expressions.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000365 struct {
366 unsigned BaseRegNum;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000367 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
368 // was specified.
369 const MCConstantExpr *OffsetImm; // Offset immediate value
370 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
371 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
Jim Grosbach57dcb852011-10-11 17:29:55 +0000372 unsigned ShiftImm; // shift for OffsetReg.
373 unsigned Alignment; // 0 = no alignment specified
Jim Grosbacheeaf1c12011-12-19 18:31:43 +0000374 // n = alignment in bytes (2, 4, 8, 16, or 32)
Jim Grosbach7ce05792011-08-03 23:50:40 +0000375 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
Jim Grosbache53c87b2011-10-11 15:59:20 +0000376 } Memory;
Owen Anderson00828302011-03-18 22:50:18 +0000377
378 struct {
Jim Grosbach7ce05792011-08-03 23:50:40 +0000379 unsigned RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000380 bool isAdd;
381 ARM_AM::ShiftOpc ShiftTy;
382 unsigned ShiftImm;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000383 } PostIdxReg;
384
385 struct {
Jim Grosbach580f4a92011-07-25 22:20:28 +0000386 bool isASR;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000387 unsigned Imm;
Jim Grosbach580f4a92011-07-25 22:20:28 +0000388 } ShifterImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000389 struct {
390 ARM_AM::ShiftOpc ShiftTy;
391 unsigned SrcReg;
392 unsigned ShiftReg;
393 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000394 } RegShiftedReg;
Owen Anderson92a20222011-07-21 18:54:16 +0000395 struct {
396 ARM_AM::ShiftOpc ShiftTy;
397 unsigned SrcReg;
398 unsigned ShiftImm;
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000399 } RegShiftedImm;
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000400 struct {
401 unsigned Imm;
402 } RotImm;
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000403 struct {
404 unsigned LSB;
405 unsigned Width;
406 } Bitfield;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000407 };
Jim Grosbach16c74252010-10-29 14:46:02 +0000408
Bill Wendling146018f2010-11-06 21:42:12 +0000409 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
410public:
Sean Callanan76264762010-04-02 22:27:05 +0000411 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
412 Kind = o.Kind;
413 StartLoc = o.StartLoc;
414 EndLoc = o.EndLoc;
415 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000416 case k_CondCode:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000417 CC = o.CC;
418 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000419 case k_ITCondMask:
Jim Grosbach89df9962011-08-26 21:43:41 +0000420 ITMask = o.ITMask;
421 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000422 case k_Token:
Daniel Dunbar8462b302010-08-11 06:36:53 +0000423 Tok = o.Tok;
Sean Callanan76264762010-04-02 22:27:05 +0000424 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000425 case k_CCOut:
426 case k_Register:
Sean Callanan76264762010-04-02 22:27:05 +0000427 Reg = o.Reg;
428 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000429 case k_RegisterList:
430 case k_DPRRegisterList:
431 case k_SPRRegisterList:
Bill Wendling24d22d22010-11-18 21:50:54 +0000432 Registers = o.Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000433 break;
Jim Grosbach862019c2011-10-18 23:02:30 +0000434 case k_VectorList:
Jim Grosbach98b05a52011-11-30 01:09:44 +0000435 case k_VectorListAllLanes:
Jim Grosbach7636bf62011-12-02 00:35:16 +0000436 case k_VectorListIndexed:
Jim Grosbach862019c2011-10-18 23:02:30 +0000437 VectorList = o.VectorList;
438 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000439 case k_CoprocNum:
440 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000441 Cop = o.Cop;
442 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000443 case k_CoprocOption:
444 CoprocOption = o.CoprocOption;
445 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000446 case k_Immediate:
Sean Callanan76264762010-04-02 22:27:05 +0000447 Imm = o.Imm;
448 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000449 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000450 MBOpt = o.MBOpt;
451 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000452 case k_Memory:
Jim Grosbache53c87b2011-10-11 15:59:20 +0000453 Memory = o.Memory;
Sean Callanan76264762010-04-02 22:27:05 +0000454 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000455 case k_PostIndexRegister:
Jim Grosbach7ce05792011-08-03 23:50:40 +0000456 PostIdxReg = o.PostIdxReg;
457 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000458 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000459 MMask = o.MMask;
460 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000461 case k_ProcIFlags:
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000462 IFlags = o.IFlags;
Owen Anderson00828302011-03-18 22:50:18 +0000463 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000464 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +0000465 ShifterImm = o.ShifterImm;
Owen Anderson00828302011-03-18 22:50:18 +0000466 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000467 case k_ShiftedRegister:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000468 RegShiftedReg = o.RegShiftedReg;
Jim Grosbache8606dc2011-07-13 17:50:29 +0000469 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000470 case k_ShiftedImmediate:
Jim Grosbachaf6981f2011-07-25 20:49:51 +0000471 RegShiftedImm = o.RegShiftedImm;
Owen Anderson92a20222011-07-21 18:54:16 +0000472 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000473 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +0000474 RotImm = o.RotImm;
475 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000476 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +0000477 Bitfield = o.Bitfield;
478 break;
Jim Grosbach460a9052011-10-07 23:56:00 +0000479 case k_VectorIndex:
480 VectorIndex = o.VectorIndex;
481 break;
Sean Callanan76264762010-04-02 22:27:05 +0000482 }
483 }
Jim Grosbach16c74252010-10-29 14:46:02 +0000484
Sean Callanan76264762010-04-02 22:27:05 +0000485 /// getStartLoc - Get the location of the first token of this operand.
486 SMLoc getStartLoc() const { return StartLoc; }
487 /// getEndLoc - Get the location of the last token of this operand.
488 SMLoc getEndLoc() const { return EndLoc; }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000489
Benjamin Kramer362a05a2012-04-15 17:04:27 +0000490 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
491
Daniel Dunbar8462b302010-08-11 06:36:53 +0000492 ARMCC::CondCodes getCondCode() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000493 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbar8462b302010-08-11 06:36:53 +0000494 return CC.Val;
495 }
496
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000497 unsigned getCoproc() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000498 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +0000499 return Cop.Val;
500 }
501
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000502 StringRef getToken() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000503 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000504 return StringRef(Tok.Data, Tok.Length);
505 }
506
507 unsigned getReg() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000508 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling7729e062010-11-09 22:44:22 +0000509 return Reg.RegNum;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +0000510 }
511
Bill Wendling5fa22a12010-11-09 23:28:44 +0000512 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000513 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
514 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling24d22d22010-11-18 21:50:54 +0000515 return Registers;
Bill Wendling8d5acb72010-11-06 19:56:04 +0000516 }
517
Kevin Enderbycfe07242009-10-13 22:19:02 +0000518 const MCExpr *getImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000519 assert(isImm() && "Invalid access!");
Kevin Enderbycfe07242009-10-13 22:19:02 +0000520 return Imm.Val;
521 }
522
Jim Grosbach460a9052011-10-07 23:56:00 +0000523 unsigned getVectorIndex() const {
524 assert(Kind == k_VectorIndex && "Invalid access!");
525 return VectorIndex.Val;
526 }
527
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000528 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000529 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +0000530 return MBOpt.Val;
531 }
532
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000533 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000534 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +0000535 return IFlags.Val;
536 }
537
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000538 unsigned getMSRMask() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000539 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +0000540 return MMask.Val;
541 }
542
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000543 bool isCoprocNum() const { return Kind == k_CoprocNum; }
544 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach9b8f2a02011-10-12 17:34:41 +0000545 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000546 bool isCondCode() const { return Kind == k_CondCode; }
547 bool isCCOut() const { return Kind == k_CCOut; }
548 bool isITMask() const { return Kind == k_ITCondMask; }
549 bool isITCondCode() const { return Kind == k_CondCode; }
550 bool isImm() const { return Kind == k_Immediate; }
Jim Grosbach51222d12012-01-20 18:09:51 +0000551 bool isFPImm() const {
552 if (!isImm()) return false;
553 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
554 if (!CE) return false;
555 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
556 return Val != -1;
557 }
Jim Grosbach4050bc42011-12-22 22:19:05 +0000558 bool isFBits16() const {
559 if (!isImm()) return false;
560 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
561 if (!CE) return false;
562 int64_t Value = CE->getValue();
563 return Value >= 0 && Value <= 16;
564 }
565 bool isFBits32() const {
566 if (!isImm()) return false;
567 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
568 if (!CE) return false;
569 int64_t Value = CE->getValue();
570 return Value >= 1 && Value <= 32;
571 }
Jim Grosbacha77295d2011-09-08 22:07:06 +0000572 bool isImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000573 if (!isImm()) return false;
Jim Grosbacha77295d2011-09-08 22:07:06 +0000574 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
575 if (!CE) return false;
576 int64_t Value = CE->getValue();
577 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
578 }
Jim Grosbach72f39f82011-08-24 21:22:15 +0000579 bool isImm0_1020s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000580 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000581 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
582 if (!CE) return false;
583 int64_t Value = CE->getValue();
584 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
585 }
586 bool isImm0_508s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000587 if (!isImm()) return false;
Jim Grosbach72f39f82011-08-24 21:22:15 +0000588 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
589 if (!CE) return false;
590 int64_t Value = CE->getValue();
591 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
592 }
Jim Grosbach4e53fe82012-04-05 20:57:13 +0000593 bool isImm0_508s4Neg() const {
594 if (!isImm()) return false;
595 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
596 if (!CE) return false;
597 int64_t Value = -CE->getValue();
598 // explicitly exclude zero. we want that to use the normal 0_508 version.
599 return ((Value & 3) == 0) && Value > 0 && Value <= 508;
600 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000601 bool isImm0_255() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000602 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000603 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
604 if (!CE) return false;
605 int64_t Value = CE->getValue();
606 return Value >= 0 && Value < 256;
607 }
Jim Grosbach4e53fe82012-04-05 20:57:13 +0000608 bool isImm0_4095() const {
609 if (!isImm()) return false;
610 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
611 if (!CE) return false;
612 int64_t Value = CE->getValue();
613 return Value >= 0 && Value < 4096;
614 }
615 bool isImm0_4095Neg() const {
616 if (!isImm()) return false;
617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
618 if (!CE) return false;
619 int64_t Value = -CE->getValue();
620 return Value > 0 && Value < 4096;
621 }
Jim Grosbach587f5062011-12-02 23:34:39 +0000622 bool isImm0_1() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000623 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000624 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
625 if (!CE) return false;
626 int64_t Value = CE->getValue();
627 return Value >= 0 && Value < 2;
628 }
629 bool isImm0_3() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000630 if (!isImm()) return false;
Jim Grosbach587f5062011-12-02 23:34:39 +0000631 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
632 if (!CE) return false;
633 int64_t Value = CE->getValue();
634 return Value >= 0 && Value < 4;
635 }
Jim Grosbach83ab0702011-07-13 22:01:08 +0000636 bool isImm0_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000637 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000638 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
639 if (!CE) return false;
640 int64_t Value = CE->getValue();
641 return Value >= 0 && Value < 8;
642 }
643 bool isImm0_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000644 if (!isImm()) return false;
Jim Grosbach83ab0702011-07-13 22:01:08 +0000645 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
646 if (!CE) return false;
647 int64_t Value = CE->getValue();
648 return Value >= 0 && Value < 16;
649 }
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000650 bool isImm0_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000651 if (!isImm()) return false;
Jim Grosbach7c6e42e2011-07-21 23:26:25 +0000652 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
653 if (!CE) return false;
654 int64_t Value = CE->getValue();
655 return Value >= 0 && Value < 32;
656 }
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000657 bool isImm0_63() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000658 if (!isImm()) return false;
Jim Grosbach730fe6c2011-12-08 01:30:04 +0000659 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
660 if (!CE) return false;
661 int64_t Value = CE->getValue();
662 return Value >= 0 && Value < 64;
663 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000664 bool isImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000665 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000666 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
667 if (!CE) return false;
668 int64_t Value = CE->getValue();
669 return Value == 8;
670 }
671 bool isImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000672 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000673 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
674 if (!CE) return false;
675 int64_t Value = CE->getValue();
676 return Value == 16;
677 }
678 bool isImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000679 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000680 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
681 if (!CE) return false;
682 int64_t Value = CE->getValue();
683 return Value == 32;
684 }
Jim Grosbach6b044c22011-12-08 22:06:06 +0000685 bool isShrImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000686 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000687 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
688 if (!CE) return false;
689 int64_t Value = CE->getValue();
690 return Value > 0 && Value <= 8;
691 }
692 bool isShrImm16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000693 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000694 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
695 if (!CE) return false;
696 int64_t Value = CE->getValue();
697 return Value > 0 && Value <= 16;
698 }
699 bool isShrImm32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000700 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000701 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
702 if (!CE) return false;
703 int64_t Value = CE->getValue();
704 return Value > 0 && Value <= 32;
705 }
706 bool isShrImm64() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000707 if (!isImm()) return false;
Jim Grosbach6b044c22011-12-08 22:06:06 +0000708 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
709 if (!CE) return false;
710 int64_t Value = CE->getValue();
711 return Value > 0 && Value <= 64;
712 }
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000713 bool isImm1_7() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000714 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000715 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
716 if (!CE) return false;
717 int64_t Value = CE->getValue();
718 return Value > 0 && Value < 8;
719 }
720 bool isImm1_15() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000721 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000722 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
723 if (!CE) return false;
724 int64_t Value = CE->getValue();
725 return Value > 0 && Value < 16;
726 }
727 bool isImm1_31() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000728 if (!isImm()) return false;
Jim Grosbach3b8991c2011-12-07 01:07:24 +0000729 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
730 if (!CE) return false;
731 int64_t Value = CE->getValue();
732 return Value > 0 && Value < 32;
733 }
Jim Grosbachf4943352011-07-25 23:09:14 +0000734 bool isImm1_16() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000735 if (!isImm()) return false;
Jim Grosbachf4943352011-07-25 23:09:14 +0000736 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
737 if (!CE) return false;
738 int64_t Value = CE->getValue();
739 return Value > 0 && Value < 17;
740 }
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000741 bool isImm1_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000742 if (!isImm()) return false;
Jim Grosbach4a5ffb32011-07-22 23:16:18 +0000743 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
744 if (!CE) return false;
745 int64_t Value = CE->getValue();
746 return Value > 0 && Value < 33;
747 }
Jim Grosbachee10ff82011-11-10 19:18:01 +0000748 bool isImm0_32() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000749 if (!isImm()) return false;
Jim Grosbachee10ff82011-11-10 19:18:01 +0000750 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
751 if (!CE) return false;
752 int64_t Value = CE->getValue();
753 return Value >= 0 && Value < 33;
754 }
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000755 bool isImm0_65535() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000756 if (!isImm()) return false;
Jim Grosbachfff76ee2011-07-13 20:10:10 +0000757 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
758 if (!CE) return false;
759 int64_t Value = CE->getValue();
760 return Value >= 0 && Value < 65536;
761 }
Jim Grosbachffa32252011-07-19 19:13:28 +0000762 bool isImm0_65535Expr() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000763 if (!isImm()) return false;
Jim Grosbachffa32252011-07-19 19:13:28 +0000764 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
765 // If it's not a constant expression, it'll generate a fixup and be
766 // handled later.
767 if (!CE) return true;
768 int64_t Value = CE->getValue();
769 return Value >= 0 && Value < 65536;
770 }
Jim Grosbached838482011-07-26 16:24:27 +0000771 bool isImm24bit() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000772 if (!isImm()) return false;
Jim Grosbached838482011-07-26 16:24:27 +0000773 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
774 if (!CE) return false;
775 int64_t Value = CE->getValue();
776 return Value >= 0 && Value <= 0xffffff;
777 }
Jim Grosbach70939ee2011-08-17 21:51:27 +0000778 bool isImmThumbSR() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000779 if (!isImm()) return false;
Jim Grosbach70939ee2011-08-17 21:51:27 +0000780 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
781 if (!CE) return false;
782 int64_t Value = CE->getValue();
783 return Value > 0 && Value < 33;
784 }
Jim Grosbachf6c05252011-07-21 17:23:04 +0000785 bool isPKHLSLImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000786 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000787 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
788 if (!CE) return false;
789 int64_t Value = CE->getValue();
790 return Value >= 0 && Value < 32;
791 }
792 bool isPKHASRImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000793 if (!isImm()) return false;
Jim Grosbachf6c05252011-07-21 17:23:04 +0000794 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
795 if (!CE) return false;
796 int64_t Value = CE->getValue();
797 return Value > 0 && Value <= 32;
798 }
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000799 bool isARMSOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000800 if (!isImm()) return false;
Jim Grosbach6bc1dbc2011-07-19 16:50:30 +0000801 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
802 if (!CE) return false;
803 int64_t Value = CE->getValue();
804 return ARM_AM::getSOImmVal(Value) != -1;
805 }
Jim Grosbache70ec842011-10-28 22:50:54 +0000806 bool isARMSOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000807 if (!isImm()) return false;
Jim Grosbache70ec842011-10-28 22:50:54 +0000808 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
809 if (!CE) return false;
810 int64_t Value = CE->getValue();
811 return ARM_AM::getSOImmVal(~Value) != -1;
812 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000813 bool isARMSOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000814 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000815 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
816 if (!CE) return false;
817 int64_t Value = CE->getValue();
Jim Grosbachad353c62012-03-30 19:59:02 +0000818 // Only use this when not representable as a plain so_imm.
819 return ARM_AM::getSOImmVal(Value) == -1 &&
820 ARM_AM::getSOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000821 }
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000822 bool isT2SOImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000823 if (!isImm()) return false;
Jim Grosbach6b8f1e32011-06-27 23:54:06 +0000824 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
825 if (!CE) return false;
826 int64_t Value = CE->getValue();
827 return ARM_AM::getT2SOImmVal(Value) != -1;
828 }
Jim Grosbach89a63372011-10-28 22:36:30 +0000829 bool isT2SOImmNot() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000830 if (!isImm()) return false;
Jim Grosbach89a63372011-10-28 22:36:30 +0000831 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
832 if (!CE) return false;
833 int64_t Value = CE->getValue();
834 return ARM_AM::getT2SOImmVal(~Value) != -1;
835 }
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000836 bool isT2SOImmNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000837 if (!isImm()) return false;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000838 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
839 if (!CE) return false;
840 int64_t Value = CE->getValue();
Jim Grosbachad353c62012-03-30 19:59:02 +0000841 // Only use this when not representable as a plain so_imm.
842 return ARM_AM::getT2SOImmVal(Value) == -1 &&
843 ARM_AM::getT2SOImmVal(-Value) != -1;
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +0000844 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000845 bool isSetEndImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000846 if (!isImm()) return false;
Jim Grosbachc27d4f92011-07-22 17:44:50 +0000847 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
848 if (!CE) return false;
849 int64_t Value = CE->getValue();
850 return Value == 1 || Value == 0;
851 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000852 bool isReg() const { return Kind == k_Register; }
853 bool isRegList() const { return Kind == k_RegisterList; }
854 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
855 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
856 bool isToken() const { return Kind == k_Token; }
857 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
858 bool isMemory() const { return Kind == k_Memory; }
859 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
860 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
861 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
862 bool isRotImm() const { return Kind == k_RotateImmediate; }
863 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
864 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000865 bool isPostIdxReg() const {
Jim Grosbach430052b2011-11-14 17:52:47 +0000866 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +0000867 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000868 bool isMemNoOffset(bool alignOK = false) const {
Jim Grosbachf6c35c52011-10-10 23:06:42 +0000869 if (!isMemory())
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000870 return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000871 // No offset of any kind.
Jim Grosbach57dcb852011-10-11 17:29:55 +0000872 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == 0 &&
873 (alignOK || Memory.Alignment == 0);
874 }
Jim Grosbach0b4c6732012-01-18 22:46:46 +0000875 bool isMemPCRelImm12() const {
876 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
877 return false;
878 // Base register must be PC.
879 if (Memory.BaseRegNum != ARM::PC)
880 return false;
881 // Immediate offset in range [-4095, 4095].
882 if (!Memory.OffsetImm) return true;
883 int64_t Val = Memory.OffsetImm->getValue();
884 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
885 }
Jim Grosbach57dcb852011-10-11 17:29:55 +0000886 bool isAlignedMemory() const {
887 return isMemNoOffset(true);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +0000888 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000889 bool isAddrMode2() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000890 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000891 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000892 if (Memory.OffsetRegNum) return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000893 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000894 if (!Memory.OffsetImm) return true;
895 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach7ce05792011-08-03 23:50:40 +0000896 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +0000897 }
Jim Grosbach039c2e12011-08-04 23:01:30 +0000898 bool isAM2OffsetImm() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +0000899 if (!isImm()) return false;
Jim Grosbach039c2e12011-08-04 23:01:30 +0000900 // Immediate offset in range [-4095, 4095].
901 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
902 if (!CE) return false;
903 int64_t Val = CE->getValue();
904 return Val > -4096 && Val < 4096;
905 }
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000906 bool isAddrMode3() const {
Jim Grosbach2f196742011-12-19 23:06:24 +0000907 // If we have an immediate that's not a constant, treat it as a label
908 // reference needing a fixup. If it is a constant, it's something else
909 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000910 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +0000911 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000912 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000913 // No shifts are legal for AM3.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000914 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000915 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000916 if (Memory.OffsetRegNum) return true;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000917 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000918 if (!Memory.OffsetImm) return true;
919 int64_t Val = Memory.OffsetImm->getValue();
Silviu Barangaca3cd412012-05-11 09:10:54 +0000920 // The #-0 offset is encoded as INT32_MIN, and we have to check
921 // for this too.
922 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000923 }
924 bool isAM3Offset() const {
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000925 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000926 return false;
Jim Grosbach21ff17c2011-10-07 23:24:09 +0000927 if (Kind == k_PostIndexRegister)
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000928 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
929 // Immediate offset in range [-255, 255].
930 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
931 if (!CE) return false;
932 int64_t Val = CE->getValue();
Jim Grosbach251bf252011-08-10 21:56:18 +0000933 // Special case, #-0 is INT32_MIN.
934 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach2fd2b872011-08-10 20:29:19 +0000935 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000936 bool isAddrMode5() const {
Jim Grosbach681460f2011-11-01 01:24:45 +0000937 // If we have an immediate that's not a constant, treat it as a label
938 // reference needing a fixup. If it is a constant, it's something else
939 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +0000940 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach681460f2011-11-01 01:24:45 +0000941 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +0000942 if (!isMemory() || Memory.Alignment != 0) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000943 // Check for register offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000944 if (Memory.OffsetRegNum) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +0000945 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000946 if (!Memory.OffsetImm) return true;
947 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +0000948 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbach681460f2011-11-01 01:24:45 +0000949 Val == INT32_MIN;
Bill Wendling87f4f9a2010-11-08 23:49:57 +0000950 }
Jim Grosbach7f739be2011-09-19 22:21:13 +0000951 bool isMemTBB() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000952 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000953 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach7f739be2011-09-19 22:21:13 +0000954 return false;
955 return true;
956 }
957 bool isMemTBH() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000958 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000959 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
960 Memory.Alignment != 0 )
Jim Grosbach7f739be2011-09-19 22:21:13 +0000961 return false;
962 return true;
963 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000964 bool isMemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000965 if (!isMemory() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendlingf4caf692010-12-14 03:36:38 +0000966 return false;
Daniel Dunbard3df5f32011-01-18 05:34:11 +0000967 return true;
Bill Wendlingf4caf692010-12-14 03:36:38 +0000968 }
Jim Grosbachab899c12011-09-07 23:10:15 +0000969 bool isT2MemRegOffset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +0000970 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
971 Memory.Alignment != 0)
Jim Grosbachab899c12011-09-07 23:10:15 +0000972 return false;
973 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000974 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbachab899c12011-09-07 23:10:15 +0000975 return true;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000976 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbachab899c12011-09-07 23:10:15 +0000977 return false;
978 return true;
979 }
Jim Grosbach7ce05792011-08-03 23:50:40 +0000980 bool isMemThumbRR() const {
981 // Thumb reg+reg addressing is simple. Just two registers, a base and
982 // an offset. No shifts, negations or any other complicating factors.
Jim Grosbache53c87b2011-10-11 15:59:20 +0000983 if (!isMemory() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000984 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendlingef4a68b2010-11-30 07:44:32 +0000985 return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +0000986 return isARMLowRegister(Memory.BaseRegNum) &&
987 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +0000988 }
989 bool isMemThumbRIs4() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000990 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +0000991 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach60f91a32011-08-19 17:55:24 +0000992 return false;
993 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbache53c87b2011-10-11 15:59:20 +0000994 if (!Memory.OffsetImm) return true;
995 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +0000996 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
997 }
Jim Grosbach38466302011-08-19 18:55:51 +0000998 bool isMemThumbRIs2() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +0000999 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +00001000 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach38466302011-08-19 18:55:51 +00001001 return false;
1002 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001003 if (!Memory.OffsetImm) return true;
1004 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach38466302011-08-19 18:55:51 +00001005 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1006 }
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001007 bool isMemThumbRIs1() const {
Jim Grosbache53c87b2011-10-11 15:59:20 +00001008 if (!isMemory() || Memory.OffsetRegNum != 0 ||
Jim Grosbach57dcb852011-10-11 17:29:55 +00001009 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001010 return false;
1011 // Immediate offset in range [0, 31].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001012 if (!Memory.OffsetImm) return true;
1013 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001014 return Val >= 0 && Val <= 31;
1015 }
Jim Grosbachecd85892011-08-19 18:13:48 +00001016 bool isMemThumbSPI() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001017 if (!isMemory() || Memory.OffsetRegNum != 0 ||
1018 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbachecd85892011-08-19 18:13:48 +00001019 return false;
1020 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001021 if (!Memory.OffsetImm) return true;
1022 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachecd85892011-08-19 18:13:48 +00001023 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001024 }
Jim Grosbacha77295d2011-09-08 22:07:06 +00001025 bool isMemImm8s4Offset() const {
Jim Grosbach2f196742011-12-19 23:06:24 +00001026 // If we have an immediate that's not a constant, treat it as a label
1027 // reference needing a fixup. If it is a constant, it's something else
1028 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001029 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach2f196742011-12-19 23:06:24 +00001030 return true;
Jim Grosbach57dcb852011-10-11 17:29:55 +00001031 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha77295d2011-09-08 22:07:06 +00001032 return false;
1033 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001034 if (!Memory.OffsetImm) return true;
1035 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha77295d2011-09-08 22:07:06 +00001036 return Val >= -1020 && Val <= 1020 && (Val & 3) == 0;
1037 }
Jim Grosbachb6aed502011-09-09 18:37:27 +00001038 bool isMemImm0_1020s4Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001039 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachb6aed502011-09-09 18:37:27 +00001040 return false;
1041 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001042 if (!Memory.OffsetImm) return true;
1043 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachb6aed502011-09-09 18:37:27 +00001044 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1045 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001046 bool isMemImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001047 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001048 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001049 // Base reg of PC isn't allowed for these encodings.
1050 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001051 // Immediate offset in range [-255, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001052 if (!Memory.OffsetImm) return true;
1053 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson4d2a0012011-09-23 22:25:02 +00001054 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001055 }
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001056 bool isMemPosImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001057 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001058 return false;
1059 // Immediate offset in range [0, 255].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001060 if (!Memory.OffsetImm) return true;
1061 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001062 return Val >= 0 && Val < 256;
1063 }
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001064 bool isMemNegImm8Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001065 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001066 return false;
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001067 // Base reg of PC isn't allowed for these encodings.
1068 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001069 // Immediate offset in range [-255, -1].
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001070 if (!Memory.OffsetImm) return false;
Jim Grosbache53c87b2011-10-11 15:59:20 +00001071 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachdf33e0d2011-12-06 04:49:29 +00001072 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001073 }
1074 bool isMemUImm12Offset() const {
Jim Grosbach57dcb852011-10-11 17:29:55 +00001075 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001076 return false;
1077 // Immediate offset in range [0, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001078 if (!Memory.OffsetImm) return true;
1079 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001080 return (Val >= 0 && Val < 4096);
1081 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001082 bool isMemImm12Offset() const {
Jim Grosbach09176e12011-08-08 20:59:31 +00001083 // If we have an immediate that's not a constant, treat it as a label
1084 // reference needing a fixup. If it is a constant, it's something else
1085 // and we reject it.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001086 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach09176e12011-08-08 20:59:31 +00001087 return true;
1088
Jim Grosbach57dcb852011-10-11 17:29:55 +00001089 if (!isMemory() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7ce05792011-08-03 23:50:40 +00001090 return false;
1091 // Immediate offset in range [-4095, 4095].
Jim Grosbache53c87b2011-10-11 15:59:20 +00001092 if (!Memory.OffsetImm) return true;
1093 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson0da10cf2011-08-29 19:36:44 +00001094 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001095 }
1096 bool isPostIdxImm8() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001097 if (!isImm()) return false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001098 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1099 if (!CE) return false;
1100 int64_t Val = CE->getValue();
Owen Anderson63553c72011-08-29 17:17:09 +00001101 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbach7ce05792011-08-03 23:50:40 +00001102 }
Jim Grosbach2bd01182011-10-11 21:55:36 +00001103 bool isPostIdxImm8s4() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001104 if (!isImm()) return false;
Jim Grosbach2bd01182011-10-11 21:55:36 +00001105 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1106 if (!CE) return false;
1107 int64_t Val = CE->getValue();
1108 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1109 (Val == INT32_MIN);
1110 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00001111
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001112 bool isMSRMask() const { return Kind == k_MSRMask; }
1113 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001114
Jim Grosbach0e387b22011-10-17 22:26:03 +00001115 // NEON operands.
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001116 bool isSingleSpacedVectorList() const {
1117 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1118 }
1119 bool isDoubleSpacedVectorList() const {
1120 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1121 }
Jim Grosbach862019c2011-10-18 23:02:30 +00001122 bool isVecListOneD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001123 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach862019c2011-10-18 23:02:30 +00001124 return VectorList.Count == 1;
1125 }
1126
Jim Grosbach28f08c92012-03-05 19:33:30 +00001127 bool isVecListDPair() const {
1128 if (!isSingleSpacedVectorList()) return false;
1129 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1130 .contains(VectorList.RegNum));
1131 }
1132
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001133 bool isVecListThreeD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001134 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachcdcfa282011-10-21 20:02:19 +00001135 return VectorList.Count == 3;
1136 }
1137
Jim Grosbachb6310312011-10-21 20:35:01 +00001138 bool isVecListFourD() const {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00001139 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachb6310312011-10-21 20:35:01 +00001140 return VectorList.Count == 4;
1141 }
1142
Jim Grosbachc3384c92012-03-05 21:43:40 +00001143 bool isVecListDPairSpaced() const {
Kevin Enderby9f2e1602012-03-20 17:41:51 +00001144 if (isSingleSpacedVectorList()) return false;
Jim Grosbachc3384c92012-03-05 21:43:40 +00001145 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1146 .contains(VectorList.RegNum));
1147 }
1148
Jim Grosbachc387fc62012-01-23 23:20:46 +00001149 bool isVecListThreeQ() const {
1150 if (!isDoubleSpacedVectorList()) return false;
1151 return VectorList.Count == 3;
1152 }
1153
Jim Grosbach7945ead2012-01-24 00:43:12 +00001154 bool isVecListFourQ() const {
1155 if (!isDoubleSpacedVectorList()) return false;
1156 return VectorList.Count == 4;
1157 }
1158
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001159 bool isSingleSpacedVectorAllLanes() const {
1160 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1161 }
1162 bool isDoubleSpacedVectorAllLanes() const {
1163 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1164 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00001165 bool isVecListOneDAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001166 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach98b05a52011-11-30 01:09:44 +00001167 return VectorList.Count == 1;
1168 }
1169
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001170 bool isVecListDPairAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001171 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachc0fc4502012-03-06 22:01:44 +00001172 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1173 .contains(VectorList.RegNum));
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001174 }
1175
Jim Grosbach4d0983a2012-03-06 23:10:38 +00001176 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbach3471d4f2011-12-21 00:38:54 +00001177 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach13af2222011-11-30 18:21:25 +00001178 return VectorList.Count == 2;
1179 }
1180
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00001181 bool isVecListThreeDAllLanes() const {
1182 if (!isSingleSpacedVectorAllLanes()) return false;
1183 return VectorList.Count == 3;
1184 }
1185
1186 bool isVecListThreeQAllLanes() const {
1187 if (!isDoubleSpacedVectorAllLanes()) return false;
1188 return VectorList.Count == 3;
1189 }
1190
Jim Grosbacha57a36a2012-01-25 00:01:08 +00001191 bool isVecListFourDAllLanes() const {
1192 if (!isSingleSpacedVectorAllLanes()) return false;
1193 return VectorList.Count == 4;
1194 }
1195
1196 bool isVecListFourQAllLanes() const {
1197 if (!isDoubleSpacedVectorAllLanes()) return false;
1198 return VectorList.Count == 4;
1199 }
1200
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001201 bool isSingleSpacedVectorIndexed() const {
1202 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1203 }
1204 bool isDoubleSpacedVectorIndexed() const {
1205 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1206 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00001207 bool isVecListOneDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001208 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach7636bf62011-12-02 00:35:16 +00001209 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1210 }
1211
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001212 bool isVecListOneDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001213 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001214 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1215 }
1216
1217 bool isVecListOneDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001218 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001219 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1220 }
1221
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001222 bool isVecListTwoDByteIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001223 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00001224 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1225 }
1226
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001227 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001228 if (!isSingleSpacedVectorIndexed()) return false;
1229 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1230 }
1231
1232 bool isVecListTwoQWordIndexed() const {
1233 if (!isDoubleSpacedVectorIndexed()) return false;
1234 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1235 }
1236
1237 bool isVecListTwoQHWordIndexed() const {
1238 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001239 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1240 }
1241
1242 bool isVecListTwoDWordIndexed() const {
Jim Grosbach95fad1c2011-12-20 19:21:26 +00001243 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach799ca9d2011-12-14 23:35:06 +00001244 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1245 }
1246
Jim Grosbach3a678af2012-01-23 21:53:26 +00001247 bool isVecListThreeDByteIndexed() const {
1248 if (!isSingleSpacedVectorIndexed()) return false;
1249 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1250 }
1251
1252 bool isVecListThreeDHWordIndexed() const {
1253 if (!isSingleSpacedVectorIndexed()) return false;
1254 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1255 }
1256
1257 bool isVecListThreeQWordIndexed() const {
1258 if (!isDoubleSpacedVectorIndexed()) return false;
1259 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1260 }
1261
1262 bool isVecListThreeQHWordIndexed() const {
1263 if (!isDoubleSpacedVectorIndexed()) return false;
1264 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1265 }
1266
1267 bool isVecListThreeDWordIndexed() const {
1268 if (!isSingleSpacedVectorIndexed()) return false;
1269 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1270 }
1271
Jim Grosbache983a132012-01-24 18:37:25 +00001272 bool isVecListFourDByteIndexed() const {
1273 if (!isSingleSpacedVectorIndexed()) return false;
1274 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1275 }
1276
1277 bool isVecListFourDHWordIndexed() const {
1278 if (!isSingleSpacedVectorIndexed()) return false;
1279 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1280 }
1281
1282 bool isVecListFourQWordIndexed() const {
1283 if (!isDoubleSpacedVectorIndexed()) return false;
1284 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1285 }
1286
1287 bool isVecListFourQHWordIndexed() const {
1288 if (!isDoubleSpacedVectorIndexed()) return false;
1289 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1290 }
1291
1292 bool isVecListFourDWordIndexed() const {
1293 if (!isSingleSpacedVectorIndexed()) return false;
1294 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1295 }
1296
Jim Grosbach460a9052011-10-07 23:56:00 +00001297 bool isVectorIndex8() const {
1298 if (Kind != k_VectorIndex) return false;
1299 return VectorIndex.Val < 8;
1300 }
1301 bool isVectorIndex16() const {
1302 if (Kind != k_VectorIndex) return false;
1303 return VectorIndex.Val < 4;
1304 }
1305 bool isVectorIndex32() const {
1306 if (Kind != k_VectorIndex) return false;
1307 return VectorIndex.Val < 2;
1308 }
1309
Jim Grosbach0e387b22011-10-17 22:26:03 +00001310 bool isNEONi8splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001311 if (!isImm()) return false;
Jim Grosbach0e387b22011-10-17 22:26:03 +00001312 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1313 // Must be a constant.
1314 if (!CE) return false;
1315 int64_t Value = CE->getValue();
1316 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1317 // value.
Jim Grosbach0e387b22011-10-17 22:26:03 +00001318 return Value >= 0 && Value < 256;
1319 }
Jim Grosbach460a9052011-10-07 23:56:00 +00001320
Jim Grosbachea461102011-10-17 23:09:09 +00001321 bool isNEONi16splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001322 if (!isImm()) return false;
Jim Grosbachea461102011-10-17 23:09:09 +00001323 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1324 // Must be a constant.
1325 if (!CE) return false;
1326 int64_t Value = CE->getValue();
1327 // i16 value in the range [0,255] or [0x0100, 0xff00]
1328 return (Value >= 0 && Value < 256) || (Value >= 0x0100 && Value <= 0xff00);
1329 }
1330
Jim Grosbach6248a542011-10-18 00:22:00 +00001331 bool isNEONi32splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001332 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001333 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1334 // Must be a constant.
1335 if (!CE) return false;
1336 int64_t Value = CE->getValue();
1337 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X.
1338 return (Value >= 0 && Value < 256) ||
1339 (Value >= 0x0100 && Value <= 0xff00) ||
1340 (Value >= 0x010000 && Value <= 0xff0000) ||
1341 (Value >= 0x01000000 && Value <= 0xff000000);
1342 }
1343
1344 bool isNEONi32vmov() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001345 if (!isImm()) return false;
Jim Grosbach6248a542011-10-18 00:22:00 +00001346 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1347 // Must be a constant.
1348 if (!CE) return false;
1349 int64_t Value = CE->getValue();
1350 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1351 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1352 return (Value >= 0 && Value < 256) ||
1353 (Value >= 0x0100 && Value <= 0xff00) ||
1354 (Value >= 0x010000 && Value <= 0xff0000) ||
1355 (Value >= 0x01000000 && Value <= 0xff000000) ||
1356 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1357 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1358 }
Jim Grosbach9b087852011-12-19 23:51:07 +00001359 bool isNEONi32vmovNeg() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001360 if (!isImm()) return false;
Jim Grosbach9b087852011-12-19 23:51:07 +00001361 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1362 // Must be a constant.
1363 if (!CE) return false;
1364 int64_t Value = ~CE->getValue();
1365 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1366 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
1367 return (Value >= 0 && Value < 256) ||
1368 (Value >= 0x0100 && Value <= 0xff00) ||
1369 (Value >= 0x010000 && Value <= 0xff0000) ||
1370 (Value >= 0x01000000 && Value <= 0xff000000) ||
1371 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1372 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1373 }
Jim Grosbach6248a542011-10-18 00:22:00 +00001374
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001375 bool isNEONi64splat() const {
Jim Grosbach21bcca82011-12-22 22:02:35 +00001376 if (!isImm()) return false;
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00001377 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1378 // Must be a constant.
1379 if (!CE) return false;
1380 uint64_t Value = CE->getValue();
1381 // i64 value with each byte being either 0 or 0xff.
1382 for (unsigned i = 0; i < 8; ++i)
1383 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1384 return true;
1385 }
1386
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001387 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner14b93852010-10-29 00:27:31 +00001388 // Add as immediates when possible. Null MCExpr = 0.
1389 if (Expr == 0)
1390 Inst.addOperand(MCOperand::CreateImm(0));
1391 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001392 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1393 else
1394 Inst.addOperand(MCOperand::CreateExpr(Expr));
1395 }
1396
Daniel Dunbar8462b302010-08-11 06:36:53 +00001397 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar345a9a62010-08-11 06:37:20 +00001398 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbar8462b302010-08-11 06:36:53 +00001399 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach04f74942010-12-06 18:30:57 +00001400 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1401 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbar8462b302010-08-11 06:36:53 +00001402 }
1403
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00001404 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1405 assert(N == 1 && "Invalid number of operands!");
1406 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1407 }
1408
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00001409 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
1411 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1412 }
1413
1414 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
1416 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1417 }
1418
Jim Grosbach89df9962011-08-26 21:43:41 +00001419 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1420 assert(N == 1 && "Invalid number of operands!");
1421 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1422 }
1423
1424 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1425 assert(N == 1 && "Invalid number of operands!");
1426 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1427 }
1428
Jim Grosbachd67641b2010-12-06 18:21:12 +00001429 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1430 assert(N == 1 && "Invalid number of operands!");
1431 Inst.addOperand(MCOperand::CreateReg(getReg()));
1432 }
1433
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00001434 void addRegOperands(MCInst &Inst, unsigned N) const {
1435 assert(N == 1 && "Invalid number of operands!");
1436 Inst.addOperand(MCOperand::CreateReg(getReg()));
1437 }
1438
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001439 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbache8606dc2011-07-13 17:50:29 +00001440 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001441 assert(isRegShiftedReg() &&
1442 "addRegShiftedRegOperands() on non RegShiftedReg!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001443 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1444 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001445 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001446 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbache8606dc2011-07-13 17:50:29 +00001447 }
1448
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001449 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson152d4a42011-07-21 23:38:37 +00001450 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001451 assert(isRegShiftedImm() &&
1452 "addRegShiftedImmOperands() on non RegShiftedImm!");
Jim Grosbachaf6981f2011-07-25 20:49:51 +00001453 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Richard Bartonb56e4112012-04-25 18:00:18 +00001454 // Shift of #32 is encoded as 0 where permitted
1455 unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm);
Owen Anderson92a20222011-07-21 18:54:16 +00001456 Inst.addOperand(MCOperand::CreateImm(
Richard Bartonb56e4112012-04-25 18:00:18 +00001457 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm)));
Owen Anderson92a20222011-07-21 18:54:16 +00001458 }
1459
Jim Grosbach580f4a92011-07-25 22:20:28 +00001460 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson00828302011-03-18 22:50:18 +00001461 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach580f4a92011-07-25 22:20:28 +00001462 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1463 ShifterImm.Imm));
Owen Anderson00828302011-03-18 22:50:18 +00001464 }
1465
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001466 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling7729e062010-11-09 22:44:22 +00001467 assert(N == 1 && "Invalid number of operands!");
Bill Wendling5fa22a12010-11-09 23:28:44 +00001468 const SmallVectorImpl<unsigned> &RegList = getRegList();
1469 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00001470 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1471 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling87f4f9a2010-11-08 23:49:57 +00001472 }
1473
Bill Wendling0f630752010-11-17 04:32:08 +00001474 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1475 addRegListOperands(Inst, N);
1476 }
1477
1478 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1479 addRegListOperands(Inst, N);
1480 }
1481
Jim Grosbach7e1547e2011-07-27 20:15:40 +00001482 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1483 assert(N == 1 && "Invalid number of operands!");
1484 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1485 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1486 }
1487
Jim Grosbach293a2ee2011-07-28 21:34:26 +00001488 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1489 assert(N == 1 && "Invalid number of operands!");
1490 // Munge the lsb/width into a bitfield mask.
1491 unsigned lsb = Bitfield.LSB;
1492 unsigned width = Bitfield.Width;
1493 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1494 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1495 (32 - (lsb + width)));
1496 Inst.addOperand(MCOperand::CreateImm(Mask));
1497 }
1498
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001499 void addImmOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 addExpr(Inst, getImm());
1502 }
Jim Grosbach16c74252010-10-29 14:46:02 +00001503
Jim Grosbach4050bc42011-12-22 22:19:05 +00001504 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1505 assert(N == 1 && "Invalid number of operands!");
1506 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1507 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1508 }
1509
1510 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1511 assert(N == 1 && "Invalid number of operands!");
1512 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1513 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1514 }
1515
Jim Grosbach9d390362011-10-03 23:38:36 +00001516 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1517 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach51222d12012-01-20 18:09:51 +00001518 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1519 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1520 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach9d390362011-10-03 23:38:36 +00001521 }
1522
Jim Grosbacha77295d2011-09-08 22:07:06 +00001523 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1524 assert(N == 1 && "Invalid number of operands!");
1525 // FIXME: We really want to scale the value here, but the LDRD/STRD
1526 // instruction don't encode operands that way yet.
1527 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1528 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1529 }
1530
Jim Grosbach72f39f82011-08-24 21:22:15 +00001531 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533 // The immediate is scaled by four in the encoding and is stored
1534 // in the MCInst as such. Lop off the low two bits here.
1535 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1536 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1537 }
1538
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001539 void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
1540 assert(N == 1 && "Invalid number of operands!");
1541 // The immediate is scaled by four in the encoding and is stored
1542 // in the MCInst as such. Lop off the low two bits here.
1543 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1544 Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
1545 }
1546
Jim Grosbach72f39f82011-08-24 21:22:15 +00001547 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1548 assert(N == 1 && "Invalid number of operands!");
1549 // The immediate is scaled by four in the encoding and is stored
1550 // in the MCInst as such. Lop off the low two bits here.
1551 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1552 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1553 }
1554
Jim Grosbachf4943352011-07-25 23:09:14 +00001555 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1556 assert(N == 1 && "Invalid number of operands!");
1557 // The constant encodes as the immediate-1, and we store in the instruction
1558 // the bits as encoded, so subtract off one here.
1559 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1560 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1561 }
1562
Jim Grosbach4a5ffb32011-07-22 23:16:18 +00001563 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1564 assert(N == 1 && "Invalid number of operands!");
1565 // The constant encodes as the immediate-1, and we store in the instruction
1566 // the bits as encoded, so subtract off one here.
1567 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1568 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1569 }
1570
Jim Grosbach70939ee2011-08-17 21:51:27 +00001571 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1572 assert(N == 1 && "Invalid number of operands!");
1573 // The constant encodes as the immediate, except for 32, which encodes as
1574 // zero.
1575 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1576 unsigned Imm = CE->getValue();
1577 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1578 }
1579
Jim Grosbachf6c05252011-07-21 17:23:04 +00001580 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1581 assert(N == 1 && "Invalid number of operands!");
1582 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1583 // the instruction as well.
1584 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1585 int Val = CE->getValue();
1586 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1587 }
1588
Jim Grosbach89a63372011-10-28 22:36:30 +00001589 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 1 && "Invalid number of operands!");
1591 // The operand is actually a t2_so_imm, but we have its bitwise
1592 // negation in the assembly source, so twiddle it here.
1593 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1594 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1595 }
1596
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001597 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1598 assert(N == 1 && "Invalid number of operands!");
1599 // The operand is actually a t2_so_imm, but we have its
1600 // negation in the assembly source, so twiddle it here.
1601 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1602 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1603 }
1604
Jim Grosbach4e53fe82012-04-05 20:57:13 +00001605 void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
1606 assert(N == 1 && "Invalid number of operands!");
1607 // The operand is actually an imm0_4095, but we have its
1608 // negation in the assembly source, so twiddle it here.
1609 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1610 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1611 }
1612
Jim Grosbache70ec842011-10-28 22:50:54 +00001613 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1614 assert(N == 1 && "Invalid number of operands!");
1615 // The operand is actually a so_imm, but we have its bitwise
1616 // negation in the assembly source, so twiddle it here.
1617 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1618 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1619 }
1620
Jim Grosbach3bc8a3d2011-12-08 00:31:07 +00001621 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
1622 assert(N == 1 && "Invalid number of operands!");
1623 // The operand is actually a so_imm, but we have its
1624 // negation in the assembly source, so twiddle it here.
1625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1626 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1627 }
1628
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00001629 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
1630 assert(N == 1 && "Invalid number of operands!");
1631 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
1632 }
1633
Jim Grosbach7ce05792011-08-03 23:50:40 +00001634 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
1635 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001636 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopes505f3cd2011-03-24 21:04:58 +00001637 }
1638
Jim Grosbach0b4c6732012-01-18 22:46:46 +00001639 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
1640 assert(N == 1 && "Invalid number of operands!");
1641 int32_t Imm = Memory.OffsetImm->getValue();
1642 // FIXME: Handle #-0
1643 if (Imm == INT32_MIN) Imm = 0;
1644 Inst.addOperand(MCOperand::CreateImm(Imm));
1645 }
1646
Jim Grosbach57dcb852011-10-11 17:29:55 +00001647 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
1648 assert(N == 2 && "Invalid number of operands!");
1649 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1650 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
1651 }
1652
Jim Grosbach7ce05792011-08-03 23:50:40 +00001653 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
1654 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001655 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1656 if (!Memory.OffsetRegNum) {
Jim Grosbach7ce05792011-08-03 23:50:40 +00001657 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1658 // Special case for #-0
1659 if (Val == INT32_MIN) Val = 0;
1660 if (Val < 0) Val = -Val;
1661 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1662 } else {
1663 // For register offset, we encode the shift type and negation flag
1664 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001665 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1666 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001667 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001668 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1669 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001670 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00001671 }
1672
Jim Grosbach039c2e12011-08-04 23:01:30 +00001673 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
1674 assert(N == 2 && "Invalid number of operands!");
1675 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1676 assert(CE && "non-constant AM2OffsetImm operand!");
1677 int32_t Val = CE->getValue();
1678 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1679 // Special case for #-0
1680 if (Val == INT32_MIN) Val = 0;
1681 if (Val < 0) Val = -Val;
1682 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
1683 Inst.addOperand(MCOperand::CreateReg(0));
1684 Inst.addOperand(MCOperand::CreateImm(Val));
1685 }
1686
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001687 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
1688 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001689 // If we have an immediate that's not a constant, treat it as a label
1690 // reference needing a fixup. If it is a constant, it's something else
1691 // and we reject it.
1692 if (isImm()) {
1693 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1694 Inst.addOperand(MCOperand::CreateReg(0));
1695 Inst.addOperand(MCOperand::CreateImm(0));
1696 return;
1697 }
1698
Jim Grosbache53c87b2011-10-11 15:59:20 +00001699 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1700 if (!Memory.OffsetRegNum) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001701 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1702 // Special case for #-0
1703 if (Val == INT32_MIN) Val = 0;
1704 if (Val < 0) Val = -Val;
1705 Val = ARM_AM::getAM3Opc(AddSub, Val);
1706 } else {
1707 // For register offset, we encode the shift type and negation flag
1708 // here.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001709 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001710 }
Jim Grosbache53c87b2011-10-11 15:59:20 +00001711 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1712 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001713 Inst.addOperand(MCOperand::CreateImm(Val));
1714 }
1715
1716 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
1717 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach21ff17c2011-10-07 23:24:09 +00001718 if (Kind == k_PostIndexRegister) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001719 int32_t Val =
1720 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
1721 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1722 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach251bf252011-08-10 21:56:18 +00001723 return;
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001724 }
1725
1726 // Constant offset.
1727 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
1728 int32_t Val = CE->getValue();
1729 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1730 // Special case for #-0
1731 if (Val == INT32_MIN) Val = 0;
1732 if (Val < 0) Val = -Val;
Jim Grosbach251bf252011-08-10 21:56:18 +00001733 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach2fd2b872011-08-10 20:29:19 +00001734 Inst.addOperand(MCOperand::CreateReg(0));
1735 Inst.addOperand(MCOperand::CreateImm(Val));
1736 }
1737
Jim Grosbach7ce05792011-08-03 23:50:40 +00001738 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
1739 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach681460f2011-11-01 01:24:45 +00001740 // If we have an immediate that's not a constant, treat it as a label
1741 // reference needing a fixup. If it is a constant, it's something else
1742 // and we reject it.
1743 if (isImm()) {
1744 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1745 Inst.addOperand(MCOperand::CreateImm(0));
1746 return;
1747 }
1748
Jim Grosbach7ce05792011-08-03 23:50:40 +00001749 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001750 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001751 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
1752 // Special case for #-0
1753 if (Val == INT32_MIN) Val = 0;
1754 if (Val < 0) Val = -Val;
1755 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001756 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001757 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00001758 }
1759
Jim Grosbacha77295d2011-09-08 22:07:06 +00001760 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
1761 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach2f196742011-12-19 23:06:24 +00001762 // If we have an immediate that's not a constant, treat it as a label
1763 // reference needing a fixup. If it is a constant, it's something else
1764 // and we reject it.
1765 if (isImm()) {
1766 Inst.addOperand(MCOperand::CreateExpr(getImm()));
1767 Inst.addOperand(MCOperand::CreateImm(0));
1768 return;
1769 }
1770
Jim Grosbache53c87b2011-10-11 15:59:20 +00001771 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1772 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha77295d2011-09-08 22:07:06 +00001773 Inst.addOperand(MCOperand::CreateImm(Val));
1774 }
1775
Jim Grosbachb6aed502011-09-09 18:37:27 +00001776 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
1777 assert(N == 2 && "Invalid number of operands!");
1778 // The lower two bits are always zero and as such are not encoded.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001779 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
1780 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachb6aed502011-09-09 18:37:27 +00001781 Inst.addOperand(MCOperand::CreateImm(Val));
1782 }
1783
Jim Grosbach7ce05792011-08-03 23:50:40 +00001784 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1785 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001786 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1787 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001788 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner14b93852010-10-29 00:27:31 +00001789 }
Daniel Dunbar3483aca2010-08-11 05:24:50 +00001790
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001791 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
1792 addMemImm8OffsetOperands(Inst, N);
1793 }
1794
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001795 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachf0eee6e2011-09-07 23:39:14 +00001796 addMemImm8OffsetOperands(Inst, N);
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001797 }
1798
1799 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1800 assert(N == 2 && "Invalid number of operands!");
1801 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001802 if (isImm()) {
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001803 addExpr(Inst, getImm());
1804 Inst.addOperand(MCOperand::CreateImm(0));
1805 return;
1806 }
1807
1808 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001809 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1810 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha8307dd2011-09-07 20:58:57 +00001811 Inst.addOperand(MCOperand::CreateImm(Val));
1812 }
1813
Jim Grosbach7ce05792011-08-03 23:50:40 +00001814 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1815 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach09176e12011-08-08 20:59:31 +00001816 // If this is an immediate, it's a label reference.
Jim Grosbach21bcca82011-12-22 22:02:35 +00001817 if (isImm()) {
Jim Grosbach09176e12011-08-08 20:59:31 +00001818 addExpr(Inst, getImm());
1819 Inst.addOperand(MCOperand::CreateImm(0));
1820 return;
1821 }
1822
1823 // Otherwise, it's a normal memory reg+offset.
Jim Grosbache53c87b2011-10-11 15:59:20 +00001824 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
1825 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001826 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendlingf4caf692010-12-14 03:36:38 +00001827 }
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001828
Jim Grosbach7f739be2011-09-19 22:21:13 +00001829 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
1830 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001831 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1832 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001833 }
1834
1835 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
1836 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001837 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1838 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7f739be2011-09-19 22:21:13 +00001839 }
1840
Jim Grosbach7ce05792011-08-03 23:50:40 +00001841 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1842 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach430052b2011-11-14 17:52:47 +00001843 unsigned Val =
1844 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
1845 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbache53c87b2011-10-11 15:59:20 +00001846 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1847 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001848 Inst.addOperand(MCOperand::CreateImm(Val));
1849 }
1850
Jim Grosbachab899c12011-09-07 23:10:15 +00001851 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
1852 assert(N == 3 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001853 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1854 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
1855 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbachab899c12011-09-07 23:10:15 +00001856 }
1857
Jim Grosbach7ce05792011-08-03 23:50:40 +00001858 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
1859 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001860 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
1861 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach7ce05792011-08-03 23:50:40 +00001862 }
1863
Jim Grosbach60f91a32011-08-19 17:55:24 +00001864 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
1865 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001866 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1867 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach60f91a32011-08-19 17:55:24 +00001868 Inst.addOperand(MCOperand::CreateImm(Val));
1869 }
1870
Jim Grosbach38466302011-08-19 18:55:51 +00001871 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
1872 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001873 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
1874 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach38466302011-08-19 18:55:51 +00001875 Inst.addOperand(MCOperand::CreateImm(Val));
1876 }
1877
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001878 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
1879 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001880 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
1881 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach48ff5ff2011-08-19 18:49:59 +00001882 Inst.addOperand(MCOperand::CreateImm(Val));
1883 }
1884
Jim Grosbachecd85892011-08-19 18:13:48 +00001885 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
1886 assert(N == 2 && "Invalid number of operands!");
Jim Grosbache53c87b2011-10-11 15:59:20 +00001887 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
1888 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachecd85892011-08-19 18:13:48 +00001889 Inst.addOperand(MCOperand::CreateImm(Val));
1890 }
1891
Jim Grosbach7ce05792011-08-03 23:50:40 +00001892 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
1893 assert(N == 1 && "Invalid number of operands!");
1894 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1895 assert(CE && "non-constant post-idx-imm8 operand!");
1896 int Imm = CE->getValue();
1897 bool isAdd = Imm >= 0;
Owen Anderson63553c72011-08-29 17:17:09 +00001898 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00001899 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
1900 Inst.addOperand(MCOperand::CreateImm(Imm));
1901 }
1902
Jim Grosbach2bd01182011-10-11 21:55:36 +00001903 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
1904 assert(N == 1 && "Invalid number of operands!");
1905 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1906 assert(CE && "non-constant post-idx-imm8s4 operand!");
1907 int Imm = CE->getValue();
1908 bool isAdd = Imm >= 0;
1909 if (Imm == INT32_MIN) Imm = 0;
1910 // Immediate is scaled by 4.
1911 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
1912 Inst.addOperand(MCOperand::CreateImm(Imm));
1913 }
1914
Jim Grosbach7ce05792011-08-03 23:50:40 +00001915 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
1916 assert(N == 2 && "Invalid number of operands!");
1917 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00001918 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
1919 }
1920
1921 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
1922 assert(N == 2 && "Invalid number of operands!");
1923 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
1924 // The sign, shift type, and shift amount are encoded in a single operand
1925 // using the AM2 encoding helpers.
1926 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
1927 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
1928 PostIdxReg.ShiftTy);
1929 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendlingef4a68b2010-11-30 07:44:32 +00001930 }
1931
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00001932 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
1933 assert(N == 1 && "Invalid number of operands!");
1934 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
1935 }
1936
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00001937 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
1938 assert(N == 1 && "Invalid number of operands!");
1939 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
1940 }
1941
Jim Grosbach6029b6d2011-11-29 23:51:09 +00001942 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach862019c2011-10-18 23:02:30 +00001943 assert(N == 1 && "Invalid number of operands!");
1944 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1945 }
1946
Jim Grosbach7636bf62011-12-02 00:35:16 +00001947 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
1948 assert(N == 2 && "Invalid number of operands!");
1949 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
1950 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
1951 }
1952
Jim Grosbach460a9052011-10-07 23:56:00 +00001953 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
1954 assert(N == 1 && "Invalid number of operands!");
1955 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1956 }
1957
1958 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
1959 assert(N == 1 && "Invalid number of operands!");
1960 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1961 }
1962
1963 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
1964 assert(N == 1 && "Invalid number of operands!");
1965 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
1966 }
1967
Jim Grosbach0e387b22011-10-17 22:26:03 +00001968 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
1969 assert(N == 1 && "Invalid number of operands!");
1970 // The immediate encodes the type of constant as well as the value.
1971 // Mask in that this is an i8 splat.
1972 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1973 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
1974 }
1975
Jim Grosbachea461102011-10-17 23:09:09 +00001976 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
1977 assert(N == 1 && "Invalid number of operands!");
1978 // The immediate encodes the type of constant as well as the value.
1979 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1980 unsigned Value = CE->getValue();
1981 if (Value >= 256)
1982 Value = (Value >> 8) | 0xa00;
1983 else
1984 Value |= 0x800;
1985 Inst.addOperand(MCOperand::CreateImm(Value));
1986 }
1987
Jim Grosbach6248a542011-10-18 00:22:00 +00001988 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
1989 assert(N == 1 && "Invalid number of operands!");
1990 // The immediate encodes the type of constant as well as the value.
1991 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1992 unsigned Value = CE->getValue();
1993 if (Value >= 256 && Value <= 0xff00)
1994 Value = (Value >> 8) | 0x200;
1995 else if (Value > 0xffff && Value <= 0xff0000)
1996 Value = (Value >> 16) | 0x400;
1997 else if (Value > 0xffffff)
1998 Value = (Value >> 24) | 0x600;
1999 Inst.addOperand(MCOperand::CreateImm(Value));
2000 }
2001
2002 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
2003 assert(N == 1 && "Invalid number of operands!");
2004 // The immediate encodes the type of constant as well as the value.
2005 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2006 unsigned Value = CE->getValue();
2007 if (Value >= 256 && Value <= 0xffff)
2008 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2009 else if (Value > 0xffff && Value <= 0xffffff)
2010 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2011 else if (Value > 0xffffff)
2012 Value = (Value >> 24) | 0x600;
2013 Inst.addOperand(MCOperand::CreateImm(Value));
2014 }
2015
Jim Grosbach9b087852011-12-19 23:51:07 +00002016 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2017 assert(N == 1 && "Invalid number of operands!");
2018 // The immediate encodes the type of constant as well as the value.
2019 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2020 unsigned Value = ~CE->getValue();
2021 if (Value >= 256 && Value <= 0xffff)
2022 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2023 else if (Value > 0xffff && Value <= 0xffffff)
2024 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2025 else if (Value > 0xffffff)
2026 Value = (Value >> 24) | 0x600;
2027 Inst.addOperand(MCOperand::CreateImm(Value));
2028 }
2029
Jim Grosbachf2f5bc62011-10-18 16:18:11 +00002030 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2031 assert(N == 1 && "Invalid number of operands!");
2032 // The immediate encodes the type of constant as well as the value.
2033 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2034 uint64_t Value = CE->getValue();
2035 unsigned Imm = 0;
2036 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2037 Imm |= (Value & 1) << i;
2038 }
2039 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
2040 }
2041
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002042 virtual void print(raw_ostream &OS) const;
Daniel Dunbarb3cb6962010-08-11 06:37:04 +00002043
Jim Grosbach89df9962011-08-26 21:43:41 +00002044 static ARMOperand *CreateITMask(unsigned Mask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002045 ARMOperand *Op = new ARMOperand(k_ITCondMask);
Jim Grosbach89df9962011-08-26 21:43:41 +00002046 Op->ITMask.Mask = Mask;
2047 Op->StartLoc = S;
2048 Op->EndLoc = S;
2049 return Op;
2050 }
2051
Chris Lattner3a697562010-10-28 17:20:03 +00002052 static ARMOperand *CreateCondCode(ARMCC::CondCodes CC, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002053 ARMOperand *Op = new ARMOperand(k_CondCode);
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002054 Op->CC.Val = CC;
2055 Op->StartLoc = S;
2056 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002057 return Op;
Daniel Dunbar345a9a62010-08-11 06:37:20 +00002058 }
2059
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002060 static ARMOperand *CreateCoprocNum(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002061 ARMOperand *Op = new ARMOperand(k_CoprocNum);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002062 Op->Cop.Val = CopVal;
2063 Op->StartLoc = S;
2064 Op->EndLoc = S;
2065 return Op;
2066 }
2067
2068 static ARMOperand *CreateCoprocReg(unsigned CopVal, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002069 ARMOperand *Op = new ARMOperand(k_CoprocReg);
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002070 Op->Cop.Val = CopVal;
2071 Op->StartLoc = S;
2072 Op->EndLoc = S;
2073 return Op;
2074 }
2075
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002076 static ARMOperand *CreateCoprocOption(unsigned Val, SMLoc S, SMLoc E) {
2077 ARMOperand *Op = new ARMOperand(k_CoprocOption);
2078 Op->Cop.Val = Val;
2079 Op->StartLoc = S;
2080 Op->EndLoc = E;
2081 return Op;
2082 }
2083
Jim Grosbachd67641b2010-12-06 18:21:12 +00002084 static ARMOperand *CreateCCOut(unsigned RegNum, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002085 ARMOperand *Op = new ARMOperand(k_CCOut);
Jim Grosbachd67641b2010-12-06 18:21:12 +00002086 Op->Reg.RegNum = RegNum;
2087 Op->StartLoc = S;
2088 Op->EndLoc = S;
2089 return Op;
2090 }
2091
Chris Lattner3a697562010-10-28 17:20:03 +00002092 static ARMOperand *CreateToken(StringRef Str, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002093 ARMOperand *Op = new ARMOperand(k_Token);
Sean Callanan76264762010-04-02 22:27:05 +00002094 Op->Tok.Data = Str.data();
2095 Op->Tok.Length = Str.size();
2096 Op->StartLoc = S;
2097 Op->EndLoc = S;
Chris Lattner3a697562010-10-28 17:20:03 +00002098 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002099 }
2100
Bill Wendling50d0f582010-11-18 23:43:05 +00002101 static ARMOperand *CreateReg(unsigned RegNum, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002102 ARMOperand *Op = new ARMOperand(k_Register);
Sean Callanan76264762010-04-02 22:27:05 +00002103 Op->Reg.RegNum = RegNum;
Sean Callanan76264762010-04-02 22:27:05 +00002104 Op->StartLoc = S;
2105 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002106 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002107 }
2108
Jim Grosbache8606dc2011-07-13 17:50:29 +00002109 static ARMOperand *CreateShiftedRegister(ARM_AM::ShiftOpc ShTy,
2110 unsigned SrcReg,
2111 unsigned ShiftReg,
2112 unsigned ShiftImm,
2113 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002114 ARMOperand *Op = new ARMOperand(k_ShiftedRegister);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002115 Op->RegShiftedReg.ShiftTy = ShTy;
2116 Op->RegShiftedReg.SrcReg = SrcReg;
2117 Op->RegShiftedReg.ShiftReg = ShiftReg;
2118 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002119 Op->StartLoc = S;
2120 Op->EndLoc = E;
2121 return Op;
2122 }
2123
Owen Anderson92a20222011-07-21 18:54:16 +00002124 static ARMOperand *CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy,
2125 unsigned SrcReg,
2126 unsigned ShiftImm,
2127 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002128 ARMOperand *Op = new ARMOperand(k_ShiftedImmediate);
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002129 Op->RegShiftedImm.ShiftTy = ShTy;
2130 Op->RegShiftedImm.SrcReg = SrcReg;
2131 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Anderson92a20222011-07-21 18:54:16 +00002132 Op->StartLoc = S;
2133 Op->EndLoc = E;
2134 return Op;
2135 }
2136
Jim Grosbach580f4a92011-07-25 22:20:28 +00002137 static ARMOperand *CreateShifterImm(bool isASR, unsigned Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002138 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002139 ARMOperand *Op = new ARMOperand(k_ShifterImmediate);
Jim Grosbach580f4a92011-07-25 22:20:28 +00002140 Op->ShifterImm.isASR = isASR;
2141 Op->ShifterImm.Imm = Imm;
Owen Anderson00828302011-03-18 22:50:18 +00002142 Op->StartLoc = S;
2143 Op->EndLoc = E;
2144 return Op;
2145 }
2146
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002147 static ARMOperand *CreateRotImm(unsigned Imm, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002148 ARMOperand *Op = new ARMOperand(k_RotateImmediate);
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002149 Op->RotImm.Imm = Imm;
2150 Op->StartLoc = S;
2151 Op->EndLoc = E;
2152 return Op;
2153 }
2154
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002155 static ARMOperand *CreateBitfield(unsigned LSB, unsigned Width,
2156 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002157 ARMOperand *Op = new ARMOperand(k_BitfieldDescriptor);
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002158 Op->Bitfield.LSB = LSB;
2159 Op->Bitfield.Width = Width;
2160 Op->StartLoc = S;
2161 Op->EndLoc = E;
2162 return Op;
2163 }
2164
Bill Wendling7729e062010-11-09 22:44:22 +00002165 static ARMOperand *
Bill Wendling5fa22a12010-11-09 23:28:44 +00002166 CreateRegList(const SmallVectorImpl<std::pair<unsigned, SMLoc> > &Regs,
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002167 SMLoc StartLoc, SMLoc EndLoc) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002168 KindTy Kind = k_RegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002169
Jim Grosbachd300b942011-09-13 22:56:44 +00002170 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002171 Kind = k_DPRRegisterList;
Jim Grosbachd300b942011-09-13 22:56:44 +00002172 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Evan Cheng275944a2011-07-25 21:32:49 +00002173 contains(Regs.front().first))
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002174 Kind = k_SPRRegisterList;
Bill Wendling0f630752010-11-17 04:32:08 +00002175
2176 ARMOperand *Op = new ARMOperand(Kind);
Bill Wendling5fa22a12010-11-09 23:28:44 +00002177 for (SmallVectorImpl<std::pair<unsigned, SMLoc> >::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002178 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Bill Wendling24d22d22010-11-18 21:50:54 +00002179 Op->Registers.push_back(I->first);
Bill Wendlingcb21d1c2010-11-19 00:38:19 +00002180 array_pod_sort(Op->Registers.begin(), Op->Registers.end());
Matt Beaumont-Gaycc8d10e2010-11-10 00:08:58 +00002181 Op->StartLoc = StartLoc;
2182 Op->EndLoc = EndLoc;
Bill Wendling8d5acb72010-11-06 19:56:04 +00002183 return Op;
2184 }
2185
Jim Grosbach862019c2011-10-18 23:02:30 +00002186 static ARMOperand *CreateVectorList(unsigned RegNum, unsigned Count,
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002187 bool isDoubleSpaced, SMLoc S, SMLoc E) {
Jim Grosbach862019c2011-10-18 23:02:30 +00002188 ARMOperand *Op = new ARMOperand(k_VectorList);
2189 Op->VectorList.RegNum = RegNum;
2190 Op->VectorList.Count = Count;
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00002191 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach862019c2011-10-18 23:02:30 +00002192 Op->StartLoc = S;
2193 Op->EndLoc = E;
2194 return Op;
2195 }
2196
Jim Grosbach98b05a52011-11-30 01:09:44 +00002197 static ARMOperand *CreateVectorListAllLanes(unsigned RegNum, unsigned Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002198 bool isDoubleSpaced,
Jim Grosbach98b05a52011-11-30 01:09:44 +00002199 SMLoc S, SMLoc E) {
2200 ARMOperand *Op = new ARMOperand(k_VectorListAllLanes);
2201 Op->VectorList.RegNum = RegNum;
2202 Op->VectorList.Count = Count;
Jim Grosbach3471d4f2011-12-21 00:38:54 +00002203 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002204 Op->StartLoc = S;
2205 Op->EndLoc = E;
2206 return Op;
2207 }
2208
Jim Grosbach7636bf62011-12-02 00:35:16 +00002209 static ARMOperand *CreateVectorListIndexed(unsigned RegNum, unsigned Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002210 unsigned Index,
2211 bool isDoubleSpaced,
2212 SMLoc S, SMLoc E) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00002213 ARMOperand *Op = new ARMOperand(k_VectorListIndexed);
2214 Op->VectorList.RegNum = RegNum;
2215 Op->VectorList.Count = Count;
2216 Op->VectorList.LaneIndex = Index;
Jim Grosbach95fad1c2011-12-20 19:21:26 +00002217 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002218 Op->StartLoc = S;
2219 Op->EndLoc = E;
2220 return Op;
2221 }
2222
Jim Grosbach460a9052011-10-07 23:56:00 +00002223 static ARMOperand *CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E,
2224 MCContext &Ctx) {
2225 ARMOperand *Op = new ARMOperand(k_VectorIndex);
2226 Op->VectorIndex.Val = Idx;
2227 Op->StartLoc = S;
2228 Op->EndLoc = E;
2229 return Op;
2230 }
2231
Chris Lattner3a697562010-10-28 17:20:03 +00002232 static ARMOperand *CreateImm(const MCExpr *Val, SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002233 ARMOperand *Op = new ARMOperand(k_Immediate);
Sean Callanan76264762010-04-02 22:27:05 +00002234 Op->Imm.Val = Val;
Sean Callanan76264762010-04-02 22:27:05 +00002235 Op->StartLoc = S;
2236 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002237 return Op;
Kevin Enderbycfe07242009-10-13 22:19:02 +00002238 }
2239
Jim Grosbach7ce05792011-08-03 23:50:40 +00002240 static ARMOperand *CreateMem(unsigned BaseRegNum,
2241 const MCConstantExpr *OffsetImm,
2242 unsigned OffsetRegNum,
2243 ARM_AM::ShiftOpc ShiftType,
Jim Grosbach0d6fac32011-08-05 22:03:36 +00002244 unsigned ShiftImm,
Jim Grosbach57dcb852011-10-11 17:29:55 +00002245 unsigned Alignment,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002246 bool isNegative,
Chris Lattner3a697562010-10-28 17:20:03 +00002247 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002248 ARMOperand *Op = new ARMOperand(k_Memory);
Jim Grosbache53c87b2011-10-11 15:59:20 +00002249 Op->Memory.BaseRegNum = BaseRegNum;
2250 Op->Memory.OffsetImm = OffsetImm;
2251 Op->Memory.OffsetRegNum = OffsetRegNum;
2252 Op->Memory.ShiftType = ShiftType;
2253 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbach57dcb852011-10-11 17:29:55 +00002254 Op->Memory.Alignment = Alignment;
Jim Grosbache53c87b2011-10-11 15:59:20 +00002255 Op->Memory.isNegative = isNegative;
Jim Grosbach7ce05792011-08-03 23:50:40 +00002256 Op->StartLoc = S;
2257 Op->EndLoc = E;
2258 return Op;
2259 }
Jim Grosbach16c74252010-10-29 14:46:02 +00002260
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002261 static ARMOperand *CreatePostIdxReg(unsigned RegNum, bool isAdd,
2262 ARM_AM::ShiftOpc ShiftTy,
2263 unsigned ShiftImm,
Jim Grosbach7ce05792011-08-03 23:50:40 +00002264 SMLoc S, SMLoc E) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002265 ARMOperand *Op = new ARMOperand(k_PostIndexRegister);
Jim Grosbach7ce05792011-08-03 23:50:40 +00002266 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002267 Op->PostIdxReg.isAdd = isAdd;
2268 Op->PostIdxReg.ShiftTy = ShiftTy;
2269 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan76264762010-04-02 22:27:05 +00002270 Op->StartLoc = S;
2271 Op->EndLoc = E;
Chris Lattner3a697562010-10-28 17:20:03 +00002272 return Op;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002273 }
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002274
2275 static ARMOperand *CreateMemBarrierOpt(ARM_MB::MemBOpt Opt, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002276 ARMOperand *Op = new ARMOperand(k_MemBarrierOpt);
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002277 Op->MBOpt.Val = Opt;
2278 Op->StartLoc = S;
2279 Op->EndLoc = S;
2280 return Op;
2281 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002282
2283 static ARMOperand *CreateProcIFlags(ARM_PROC::IFlags IFlags, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002284 ARMOperand *Op = new ARMOperand(k_ProcIFlags);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002285 Op->IFlags.Val = IFlags;
2286 Op->StartLoc = S;
2287 Op->EndLoc = S;
2288 return Op;
2289 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002290
2291 static ARMOperand *CreateMSRMask(unsigned MMask, SMLoc S) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002292 ARMOperand *Op = new ARMOperand(k_MSRMask);
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002293 Op->MMask.Val = MMask;
2294 Op->StartLoc = S;
2295 Op->EndLoc = S;
2296 return Op;
2297 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002298};
2299
2300} // end anonymous namespace.
2301
Jim Grosbachb7f689b2011-07-13 15:34:57 +00002302void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002303 switch (Kind) {
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002304 case k_CondCode:
Daniel Dunbar6a5c22e2011-01-10 15:26:21 +00002305 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002306 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002307 case k_CCOut:
Jim Grosbachd67641b2010-12-06 18:21:12 +00002308 OS << "<ccout " << getReg() << ">";
2309 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002310 case k_ITCondMask: {
Craig Topper032f4412012-05-24 04:11:15 +00002311 static const char *const MaskStr[] = {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002312 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2313 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2314 };
Jim Grosbach89df9962011-08-26 21:43:41 +00002315 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2316 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2317 break;
2318 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002319 case k_CoprocNum:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002320 OS << "<coprocessor number: " << getCoproc() << ">";
2321 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002322 case k_CoprocReg:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002323 OS << "<coprocessor register: " << getCoproc() << ">";
2324 break;
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002325 case k_CoprocOption:
2326 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2327 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002328 case k_MSRMask:
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00002329 OS << "<mask: " << getMSRMask() << ">";
2330 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002331 case k_Immediate:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002332 getImm()->print(OS);
2333 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002334 case k_MemBarrierOpt:
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00002335 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt()) << ">";
2336 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002337 case k_Memory:
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002338 OS << "<memory "
Jim Grosbache53c87b2011-10-11 15:59:20 +00002339 << " base:" << Memory.BaseRegNum;
Daniel Dunbar6ec56202011-01-18 05:55:21 +00002340 OS << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002341 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002342 case k_PostIndexRegister:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00002343 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2344 << PostIdxReg.RegNum;
2345 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2346 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2347 << PostIdxReg.ShiftImm;
2348 OS << ">";
Jim Grosbach7ce05792011-08-03 23:50:40 +00002349 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002350 case k_ProcIFlags: {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00002351 OS << "<ARM_PROC::";
2352 unsigned IFlags = getProcIFlags();
2353 for (int i=2; i >= 0; --i)
2354 if (IFlags & (1 << i))
2355 OS << ARM_PROC::IFlagsToString(1 << i);
2356 OS << ">";
2357 break;
2358 }
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002359 case k_Register:
Bill Wendling50d0f582010-11-18 23:43:05 +00002360 OS << "<register " << getReg() << ">";
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002361 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002362 case k_ShifterImmediate:
Jim Grosbach580f4a92011-07-25 22:20:28 +00002363 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2364 << " #" << ShifterImm.Imm << ">";
Jim Grosbache8606dc2011-07-13 17:50:29 +00002365 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002366 case k_ShiftedRegister:
Owen Anderson92a20222011-07-21 18:54:16 +00002367 OS << "<so_reg_reg "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002368 << RegShiftedReg.SrcReg << " "
2369 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2370 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson00828302011-03-18 22:50:18 +00002371 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002372 case k_ShiftedImmediate:
Owen Anderson92a20222011-07-21 18:54:16 +00002373 OS << "<so_reg_imm "
Jim Grosbachefed3d12011-11-16 21:46:50 +00002374 << RegShiftedImm.SrcReg << " "
2375 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2376 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Anderson92a20222011-07-21 18:54:16 +00002377 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002378 case k_RotateImmediate:
Jim Grosbach7e1547e2011-07-27 20:15:40 +00002379 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2380 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002381 case k_BitfieldDescriptor:
Jim Grosbach293a2ee2011-07-28 21:34:26 +00002382 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2383 << ", width: " << Bitfield.Width << ">";
2384 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002385 case k_RegisterList:
2386 case k_DPRRegisterList:
2387 case k_SPRRegisterList: {
Bill Wendling8d5acb72010-11-06 19:56:04 +00002388 OS << "<register_list ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002389
Bill Wendling5fa22a12010-11-09 23:28:44 +00002390 const SmallVectorImpl<unsigned> &RegList = getRegList();
2391 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling7729e062010-11-09 22:44:22 +00002392 I = RegList.begin(), E = RegList.end(); I != E; ) {
2393 OS << *I;
2394 if (++I < E) OS << ", ";
Bill Wendling8d5acb72010-11-06 19:56:04 +00002395 }
2396
2397 OS << ">";
2398 break;
2399 }
Jim Grosbach862019c2011-10-18 23:02:30 +00002400 case k_VectorList:
2401 OS << "<vector_list " << VectorList.Count << " * "
2402 << VectorList.RegNum << ">";
2403 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002404 case k_VectorListAllLanes:
2405 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2406 << VectorList.RegNum << ">";
2407 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002408 case k_VectorListIndexed:
2409 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2410 << VectorList.Count << " * " << VectorList.RegNum << ">";
2411 break;
Jim Grosbach21ff17c2011-10-07 23:24:09 +00002412 case k_Token:
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002413 OS << "'" << getToken() << "'";
2414 break;
Jim Grosbach460a9052011-10-07 23:56:00 +00002415 case k_VectorIndex:
2416 OS << "<vectorindex " << getVectorIndex() << ">";
2417 break;
Daniel Dunbarfa315de2010-08-11 06:37:12 +00002418 }
2419}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00002420
2421/// @name Auto-generated Match Functions
2422/// {
2423
2424static unsigned MatchRegisterName(StringRef Name);
2425
2426/// }
2427
Bob Wilson69df7232011-02-03 21:46:10 +00002428bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2429 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbacha39cda72011-12-14 02:16:11 +00002430 StartLoc = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002431 RegNo = tryParseRegister();
Jim Grosbacha39cda72011-12-14 02:16:11 +00002432 EndLoc = Parser.getTok().getLoc();
Roman Divackybf755322011-01-27 17:14:22 +00002433
2434 return (RegNo == (unsigned)-1);
2435}
2436
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002437/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattnere5658fa2010-10-30 04:09:10 +00002438/// and if it is a register name the token is eaten and the register number is
2439/// returned. Otherwise return -1.
2440///
Jim Grosbach1355cf12011-07-26 17:10:22 +00002441int ARMAsmParser::tryParseRegister() {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002442 const AsmToken &Tok = Parser.getTok();
Jim Grosbach7ce05792011-08-03 23:50:40 +00002443 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002444
Benjamin Kramer59085362011-11-06 20:37:06 +00002445 std::string lowerCase = Tok.getString().lower();
Owen Anderson0c9f2502011-01-13 22:50:36 +00002446 unsigned RegNum = MatchRegisterName(lowerCase);
2447 if (!RegNum) {
2448 RegNum = StringSwitch<unsigned>(lowerCase)
2449 .Case("r13", ARM::SP)
2450 .Case("r14", ARM::LR)
2451 .Case("r15", ARM::PC)
2452 .Case("ip", ARM::R12)
Jim Grosbach40e28552011-12-08 19:27:38 +00002453 // Additional register name aliases for 'gas' compatibility.
2454 .Case("a1", ARM::R0)
2455 .Case("a2", ARM::R1)
2456 .Case("a3", ARM::R2)
2457 .Case("a4", ARM::R3)
2458 .Case("v1", ARM::R4)
2459 .Case("v2", ARM::R5)
2460 .Case("v3", ARM::R6)
2461 .Case("v4", ARM::R7)
2462 .Case("v5", ARM::R8)
2463 .Case("v6", ARM::R9)
2464 .Case("v7", ARM::R10)
2465 .Case("v8", ARM::R11)
2466 .Case("sb", ARM::R9)
2467 .Case("sl", ARM::R10)
2468 .Case("fp", ARM::R11)
Owen Anderson0c9f2502011-01-13 22:50:36 +00002469 .Default(0);
2470 }
Jim Grosbacha39cda72011-12-14 02:16:11 +00002471 if (!RegNum) {
Jim Grosbachaee718b2011-12-20 23:11:00 +00002472 // Check for aliases registered via .req. Canonicalize to lower case.
2473 // That's more consistent since register names are case insensitive, and
2474 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2475 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbacha39cda72011-12-14 02:16:11 +00002476 // If no match, return failure.
2477 if (Entry == RegisterReqs.end())
2478 return -1;
2479 Parser.Lex(); // Eat identifier token.
2480 return Entry->getValue();
2481 }
Bob Wilson69df7232011-02-03 21:46:10 +00002482
Chris Lattnere5658fa2010-10-30 04:09:10 +00002483 Parser.Lex(); // Eat identifier token.
Jim Grosbach460a9052011-10-07 23:56:00 +00002484
Chris Lattnere5658fa2010-10-30 04:09:10 +00002485 return RegNum;
2486}
Jim Grosbachd4462a52010-11-01 16:44:21 +00002487
Jim Grosbach19906722011-07-13 18:49:30 +00002488// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
2489// If a recoverable error occurs, return 1. If an irrecoverable error
2490// occurs, return -1. An irrecoverable error is one where tokens have been
2491// consumed in the process of trying to parse the shifter (i.e., when it is
2492// indeed a shifter operand, but malformed).
Jim Grosbach0d87ec22011-07-26 20:41:24 +00002493int ARMAsmParser::tryParseShiftRegister(
Owen Anderson00828302011-03-18 22:50:18 +00002494 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2495 SMLoc S = Parser.getTok().getLoc();
2496 const AsmToken &Tok = Parser.getTok();
2497 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2498
Benjamin Kramer59085362011-11-06 20:37:06 +00002499 std::string lowerCase = Tok.getString().lower();
Owen Anderson00828302011-03-18 22:50:18 +00002500 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbachaf4edea2011-12-07 23:40:58 +00002501 .Case("asl", ARM_AM::lsl)
Owen Anderson00828302011-03-18 22:50:18 +00002502 .Case("lsl", ARM_AM::lsl)
2503 .Case("lsr", ARM_AM::lsr)
2504 .Case("asr", ARM_AM::asr)
2505 .Case("ror", ARM_AM::ror)
2506 .Case("rrx", ARM_AM::rrx)
2507 .Default(ARM_AM::no_shift);
2508
2509 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbach19906722011-07-13 18:49:30 +00002510 return 1;
Owen Anderson00828302011-03-18 22:50:18 +00002511
Jim Grosbache8606dc2011-07-13 17:50:29 +00002512 Parser.Lex(); // Eat the operator.
Owen Anderson00828302011-03-18 22:50:18 +00002513
Jim Grosbache8606dc2011-07-13 17:50:29 +00002514 // The source register for the shift has already been added to the
2515 // operand list, so we need to pop it off and combine it into the shifted
2516 // register operand instead.
Benjamin Kramereac07962011-07-14 18:41:22 +00002517 OwningPtr<ARMOperand> PrevOp((ARMOperand*)Operands.pop_back_val());
Jim Grosbache8606dc2011-07-13 17:50:29 +00002518 if (!PrevOp->isReg())
2519 return Error(PrevOp->getStartLoc(), "shift must be of a register");
2520 int SrcReg = PrevOp->getReg();
2521 int64_t Imm = 0;
2522 int ShiftReg = 0;
2523 if (ShiftTy == ARM_AM::rrx) {
2524 // RRX Doesn't have an explicit shift amount. The encoder expects
2525 // the shift register to be the same as the source register. Seems odd,
2526 // but OK.
2527 ShiftReg = SrcReg;
2528 } else {
2529 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00002530 if (Parser.getTok().is(AsmToken::Hash) ||
2531 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbache8606dc2011-07-13 17:50:29 +00002532 Parser.Lex(); // Eat hash.
2533 SMLoc ImmLoc = Parser.getTok().getLoc();
2534 const MCExpr *ShiftExpr = 0;
Jim Grosbach19906722011-07-13 18:49:30 +00002535 if (getParser().ParseExpression(ShiftExpr)) {
2536 Error(ImmLoc, "invalid immediate shift value");
2537 return -1;
2538 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002539 // The expression must be evaluatable as an immediate.
2540 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbach19906722011-07-13 18:49:30 +00002541 if (!CE) {
2542 Error(ImmLoc, "invalid immediate shift value");
2543 return -1;
2544 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002545 // Range check the immediate.
2546 // lsl, ror: 0 <= imm <= 31
2547 // lsr, asr: 0 <= imm <= 32
2548 Imm = CE->getValue();
2549 if (Imm < 0 ||
2550 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
2551 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbach19906722011-07-13 18:49:30 +00002552 Error(ImmLoc, "immediate shift value out of range");
2553 return -1;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002554 }
Jim Grosbachde626ad2011-12-22 17:37:00 +00002555 // shift by zero is a nop. Always send it through as lsl.
2556 // ('as' compatibility)
2557 if (Imm == 0)
2558 ShiftTy = ARM_AM::lsl;
Jim Grosbache8606dc2011-07-13 17:50:29 +00002559 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach1355cf12011-07-26 17:10:22 +00002560 ShiftReg = tryParseRegister();
Jim Grosbache8606dc2011-07-13 17:50:29 +00002561 SMLoc L = Parser.getTok().getLoc();
Jim Grosbach19906722011-07-13 18:49:30 +00002562 if (ShiftReg == -1) {
2563 Error (L, "expected immediate or register in shift operand");
2564 return -1;
2565 }
2566 } else {
2567 Error (Parser.getTok().getLoc(),
Jim Grosbache8606dc2011-07-13 17:50:29 +00002568 "expected immediate or register in shift operand");
Jim Grosbach19906722011-07-13 18:49:30 +00002569 return -1;
2570 }
Jim Grosbache8606dc2011-07-13 17:50:29 +00002571 }
2572
Owen Anderson92a20222011-07-21 18:54:16 +00002573 if (ShiftReg && ShiftTy != ARM_AM::rrx)
2574 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachaf6981f2011-07-25 20:49:51 +00002575 ShiftReg, Imm,
Owen Anderson00828302011-03-18 22:50:18 +00002576 S, Parser.getTok().getLoc()));
Owen Anderson92a20222011-07-21 18:54:16 +00002577 else
2578 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
2579 S, Parser.getTok().getLoc()));
Owen Anderson00828302011-03-18 22:50:18 +00002580
Jim Grosbach19906722011-07-13 18:49:30 +00002581 return 0;
Owen Anderson00828302011-03-18 22:50:18 +00002582}
2583
2584
Bill Wendling50d0f582010-11-18 23:43:05 +00002585/// Try to parse a register name. The token must be an Identifier when called.
2586/// If it's a register, an AsmOperand is created. Another AsmOperand is created
2587/// if there is a "writeback". 'true' if it's not a register.
Chris Lattner3a697562010-10-28 17:20:03 +00002588///
Kevin Enderby9c41fa82009-10-30 22:55:57 +00002589/// TODO this is likely to change to allow different register types and or to
2590/// parse for a specific register type.
Bill Wendling50d0f582010-11-18 23:43:05 +00002591bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002592tryParseRegisterWithWriteBack(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Chris Lattnere5658fa2010-10-30 04:09:10 +00002593 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach1355cf12011-07-26 17:10:22 +00002594 int RegNo = tryParseRegister();
Bill Wendlinge7176102010-11-06 22:36:58 +00002595 if (RegNo == -1)
Bill Wendling50d0f582010-11-18 23:43:05 +00002596 return true;
Jim Grosbachd4462a52010-11-01 16:44:21 +00002597
Bill Wendling50d0f582010-11-18 23:43:05 +00002598 Operands.push_back(ARMOperand::CreateReg(RegNo, S, Parser.getTok().getLoc()));
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002599
Chris Lattnere5658fa2010-10-30 04:09:10 +00002600 const AsmToken &ExclaimTok = Parser.getTok();
2601 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling50d0f582010-11-18 23:43:05 +00002602 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
2603 ExclaimTok.getLoc()));
Chris Lattnere5658fa2010-10-30 04:09:10 +00002604 Parser.Lex(); // Eat exclaim token
Jim Grosbach460a9052011-10-07 23:56:00 +00002605 return false;
2606 }
2607
2608 // Also check for an index operand. This is only legal for vector registers,
2609 // but that'll get caught OK in operand matching, so we don't need to
2610 // explicitly filter everything else out here.
2611 if (Parser.getTok().is(AsmToken::LBrac)) {
2612 SMLoc SIdx = Parser.getTok().getLoc();
2613 Parser.Lex(); // Eat left bracket token.
2614
2615 const MCExpr *ImmVal;
Jim Grosbach460a9052011-10-07 23:56:00 +00002616 if (getParser().ParseExpression(ImmVal))
Jim Grosbach24dda212012-01-31 23:51:09 +00002617 return true;
Jim Grosbach460a9052011-10-07 23:56:00 +00002618 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002619 if (!MCE)
2620 return TokError("immediate value expected for vector index");
Jim Grosbach460a9052011-10-07 23:56:00 +00002621
2622 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachef4d3eb2012-01-26 15:56:45 +00002623 if (Parser.getTok().isNot(AsmToken::RBrac))
2624 return Error(E, "']' expected");
Jim Grosbach460a9052011-10-07 23:56:00 +00002625
2626 Parser.Lex(); // Eat right bracket token.
2627
2628 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
2629 SIdx, E,
2630 getContext()));
Kevin Enderby99e6d4e2009-10-07 18:01:35 +00002631 }
2632
Bill Wendling50d0f582010-11-18 23:43:05 +00002633 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00002634}
2635
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002636/// MatchCoprocessorOperandName - Try to parse an coprocessor related
2637/// instruction with a symbolic operand name. Example: "p1", "p7", "c3",
2638/// "c5", ...
2639static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002640 // Use the same layout as the tablegen'erated register name matcher. Ugly,
2641 // but efficient.
2642 switch (Name.size()) {
David Blaikie4d6ccb52012-01-20 21:51:11 +00002643 default: return -1;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002644 case 2:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002645 if (Name[0] != CoprocOp)
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002646 return -1;
2647 switch (Name[1]) {
2648 default: return -1;
2649 case '0': return 0;
2650 case '1': return 1;
2651 case '2': return 2;
2652 case '3': return 3;
2653 case '4': return 4;
2654 case '5': return 5;
2655 case '6': return 6;
2656 case '7': return 7;
2657 case '8': return 8;
2658 case '9': return 9;
2659 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002660 case 3:
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002661 if (Name[0] != CoprocOp || Name[1] != '1')
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002662 return -1;
2663 switch (Name[2]) {
2664 default: return -1;
2665 case '0': return 10;
2666 case '1': return 11;
2667 case '2': return 12;
2668 case '3': return 13;
2669 case '4': return 14;
2670 case '5': return 15;
2671 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002672 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002673}
2674
Jim Grosbach89df9962011-08-26 21:43:41 +00002675/// parseITCondCode - Try to parse a condition code for an IT instruction.
2676ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2677parseITCondCode(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2678 SMLoc S = Parser.getTok().getLoc();
2679 const AsmToken &Tok = Parser.getTok();
2680 if (!Tok.is(AsmToken::Identifier))
2681 return MatchOperand_NoMatch;
Richard Barton04a09a42012-04-27 17:34:01 +00002682 unsigned CC = StringSwitch<unsigned>(Tok.getString().lower())
Jim Grosbach89df9962011-08-26 21:43:41 +00002683 .Case("eq", ARMCC::EQ)
2684 .Case("ne", ARMCC::NE)
2685 .Case("hs", ARMCC::HS)
2686 .Case("cs", ARMCC::HS)
2687 .Case("lo", ARMCC::LO)
2688 .Case("cc", ARMCC::LO)
2689 .Case("mi", ARMCC::MI)
2690 .Case("pl", ARMCC::PL)
2691 .Case("vs", ARMCC::VS)
2692 .Case("vc", ARMCC::VC)
2693 .Case("hi", ARMCC::HI)
2694 .Case("ls", ARMCC::LS)
2695 .Case("ge", ARMCC::GE)
2696 .Case("lt", ARMCC::LT)
2697 .Case("gt", ARMCC::GT)
2698 .Case("le", ARMCC::LE)
2699 .Case("al", ARMCC::AL)
2700 .Default(~0U);
2701 if (CC == ~0U)
2702 return MatchOperand_NoMatch;
2703 Parser.Lex(); // Eat the token.
2704
2705 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
2706
2707 return MatchOperand_Success;
2708}
2709
Jim Grosbach43904292011-07-25 20:14:50 +00002710/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002711/// token must be an Identifier when called, and if it is a coprocessor
2712/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002713ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002714parseCoprocNumOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002715 SMLoc S = Parser.getTok().getLoc();
2716 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002717 if (Tok.isNot(AsmToken::Identifier))
2718 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002719
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002720 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002721 if (Num == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002722 return MatchOperand_NoMatch;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002723
2724 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002725 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002726 return MatchOperand_Success;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002727}
2728
Jim Grosbach43904292011-07-25 20:14:50 +00002729/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002730/// token must be an Identifier when called, and if it is a coprocessor
2731/// number, the token is eaten and the operand is added to the operand list.
Jim Grosbachf922c472011-02-12 01:34:40 +00002732ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00002733parseCoprocRegOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002734 SMLoc S = Parser.getTok().getLoc();
2735 const AsmToken &Tok = Parser.getTok();
Jim Grosbachc66e7af2011-10-12 20:54:17 +00002736 if (Tok.isNot(AsmToken::Identifier))
2737 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002738
2739 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
2740 if (Reg == -1)
Jim Grosbachf922c472011-02-12 01:34:40 +00002741 return MatchOperand_NoMatch;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00002742
2743 Parser.Lex(); // Eat identifier token.
2744 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00002745 return MatchOperand_Success;
Owen Andersone4e5e2a2011-01-13 21:46:02 +00002746}
2747
Jim Grosbach9b8f2a02011-10-12 17:34:41 +00002748/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
2749/// coproc_option : '{' imm0_255 '}'
2750ARMAsmParser::OperandMatchResultTy ARMAsmParser::
2751parseCoprocOptionOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
2752 SMLoc S = Parser.getTok().getLoc();
2753
2754 // If this isn't a '{', this isn't a coprocessor immediate operand.
2755 if (Parser.getTok().isNot(AsmToken::LCurly))
2756 return MatchOperand_NoMatch;
2757 Parser.Lex(); // Eat the '{'
2758
2759 const MCExpr *Expr;
2760 SMLoc Loc = Parser.getTok().getLoc();
2761 if (getParser().ParseExpression(Expr)) {
2762 Error(Loc, "illegal expression");
2763 return MatchOperand_ParseFail;
2764 }
2765 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
2766 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
2767 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
2768 return MatchOperand_ParseFail;
2769 }
2770 int Val = CE->getValue();
2771
2772 // Check for and consume the closing '}'
2773 if (Parser.getTok().isNot(AsmToken::RCurly))
2774 return MatchOperand_ParseFail;
2775 SMLoc E = Parser.getTok().getLoc();
2776 Parser.Lex(); // Eat the '}'
2777
2778 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
2779 return MatchOperand_Success;
2780}
2781
Jim Grosbachd0588e22011-09-14 18:08:35 +00002782// For register list parsing, we need to map from raw GPR register numbering
2783// to the enumeration values. The enumeration values aren't sorted by
2784// register number due to our using "sp", "lr" and "pc" as canonical names.
2785static unsigned getNextRegister(unsigned Reg) {
2786 // If this is a GPR, we need to do it manually, otherwise we can rely
2787 // on the sort ordering of the enumeration since the other reg-classes
2788 // are sane.
2789 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2790 return Reg + 1;
2791 switch(Reg) {
Craig Topperbc219812012-02-07 02:50:20 +00002792 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbachd0588e22011-09-14 18:08:35 +00002793 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
2794 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
2795 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
2796 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
2797 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
2798 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
2799 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
2800 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
2801 }
2802}
2803
Jim Grosbachce485e72011-11-11 21:27:40 +00002804// Return the low-subreg of a given Q register.
2805static unsigned getDRegFromQReg(unsigned QReg) {
2806 switch (QReg) {
2807 default: llvm_unreachable("expected a Q register!");
2808 case ARM::Q0: return ARM::D0;
2809 case ARM::Q1: return ARM::D2;
2810 case ARM::Q2: return ARM::D4;
2811 case ARM::Q3: return ARM::D6;
2812 case ARM::Q4: return ARM::D8;
2813 case ARM::Q5: return ARM::D10;
2814 case ARM::Q6: return ARM::D12;
2815 case ARM::Q7: return ARM::D14;
2816 case ARM::Q8: return ARM::D16;
Jim Grosbach25e0a872011-11-15 21:01:30 +00002817 case ARM::Q9: return ARM::D18;
Jim Grosbachce485e72011-11-11 21:27:40 +00002818 case ARM::Q10: return ARM::D20;
2819 case ARM::Q11: return ARM::D22;
2820 case ARM::Q12: return ARM::D24;
2821 case ARM::Q13: return ARM::D26;
2822 case ARM::Q14: return ARM::D28;
2823 case ARM::Q15: return ARM::D30;
2824 }
2825}
2826
Jim Grosbachd0588e22011-09-14 18:08:35 +00002827/// Parse a register list.
Bill Wendling50d0f582010-11-18 23:43:05 +00002828bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00002829parseRegisterList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan18b83232010-01-19 21:44:56 +00002830 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00002831 "Token is not a Left Curly Brace");
Bill Wendlinge7176102010-11-06 22:36:58 +00002832 SMLoc S = Parser.getTok().getLoc();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002833 Parser.Lex(); // Eat '{' token.
2834 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002835
Jim Grosbachd0588e22011-09-14 18:08:35 +00002836 // Check the first register in the list to see what register class
2837 // this is a list of.
2838 int Reg = tryParseRegister();
2839 if (Reg == -1)
2840 return Error(RegLoc, "register expected");
2841
Jim Grosbachce485e72011-11-11 21:27:40 +00002842 // The reglist instructions have at most 16 registers, so reserve
2843 // space for that many.
2844 SmallVector<std::pair<unsigned, SMLoc>, 16> Registers;
2845
2846 // Allow Q regs and just interpret them as the two D sub-registers.
2847 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2848 Reg = getDRegFromQReg(Reg);
2849 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2850 ++Reg;
2851 }
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00002852 const MCRegisterClass *RC;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002853 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2854 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
2855 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
2856 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
2857 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
2858 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
2859 else
2860 return Error(RegLoc, "invalid register in register list");
2861
Jim Grosbachce485e72011-11-11 21:27:40 +00002862 // Store the register.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002863 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002864
Jim Grosbachd0588e22011-09-14 18:08:35 +00002865 // This starts immediately after the first register token in the list,
2866 // so we can see either a comma or a minus (range separator) as a legal
2867 // next token.
2868 while (Parser.getTok().is(AsmToken::Comma) ||
2869 Parser.getTok().is(AsmToken::Minus)) {
2870 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache43862b2011-11-15 23:19:15 +00002871 Parser.Lex(); // Eat the minus.
Jim Grosbachd0588e22011-09-14 18:08:35 +00002872 SMLoc EndLoc = Parser.getTok().getLoc();
2873 int EndReg = tryParseRegister();
2874 if (EndReg == -1)
2875 return Error(EndLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002876 // Allow Q regs and just interpret them as the two D sub-registers.
2877 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
2878 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbachd0588e22011-09-14 18:08:35 +00002879 // If the register is the same as the start reg, there's nothing
2880 // more to do.
2881 if (Reg == EndReg)
2882 continue;
2883 // The register must be in the same register class as the first.
2884 if (!RC->contains(EndReg))
2885 return Error(EndLoc, "invalid register in register list");
2886 // Ranges must go from low to high.
2887 if (getARMRegisterNumbering(Reg) > getARMRegisterNumbering(EndReg))
2888 return Error(EndLoc, "bad range in register list");
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002889
Jim Grosbachd0588e22011-09-14 18:08:35 +00002890 // Add all the registers in the range to the register list.
2891 while (Reg != EndReg) {
2892 Reg = getNextRegister(Reg);
2893 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
2894 }
2895 continue;
2896 }
2897 Parser.Lex(); // Eat the comma.
2898 RegLoc = Parser.getTok().getLoc();
2899 int OldReg = Reg;
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002900 const AsmToken RegTok = Parser.getTok();
Jim Grosbachd0588e22011-09-14 18:08:35 +00002901 Reg = tryParseRegister();
2902 if (Reg == -1)
Jim Grosbach2d539692011-09-12 23:36:42 +00002903 return Error(RegLoc, "register expected");
Jim Grosbachce485e72011-11-11 21:27:40 +00002904 // Allow Q regs and just interpret them as the two D sub-registers.
2905 bool isQReg = false;
2906 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
2907 Reg = getDRegFromQReg(Reg);
2908 isQReg = true;
2909 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002910 // The register must be in the same register class as the first.
2911 if (!RC->contains(Reg))
2912 return Error(RegLoc, "invalid register in register list");
2913 // List must be monotonically increasing.
Jim Grosbachbe7cf2b2012-03-16 20:48:38 +00002914 if (getARMRegisterNumbering(Reg) < getARMRegisterNumbering(OldReg)) {
2915 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
2916 Warning(RegLoc, "register list not in ascending order");
2917 else
2918 return Error(RegLoc, "register list not in ascending order");
2919 }
Jim Grosbacha62d11e2011-12-08 21:34:20 +00002920 if (getARMRegisterNumbering(Reg) == getARMRegisterNumbering(OldReg)) {
2921 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
2922 ") in register list");
2923 continue;
2924 }
Jim Grosbachd0588e22011-09-14 18:08:35 +00002925 // VFP register lists must also be contiguous.
2926 // It's OK to use the enumeration values directly here rather, as the
2927 // VFP register classes have the enum sorted properly.
2928 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
2929 Reg != OldReg + 1)
2930 return Error(RegLoc, "non-contiguous register range");
2931 Registers.push_back(std::pair<unsigned, SMLoc>(Reg, RegLoc));
Jim Grosbachce485e72011-11-11 21:27:40 +00002932 if (isQReg)
2933 Registers.push_back(std::pair<unsigned, SMLoc>(++Reg, RegLoc));
Bill Wendlinge7176102010-11-06 22:36:58 +00002934 }
2935
Jim Grosbachd0588e22011-09-14 18:08:35 +00002936 SMLoc E = Parser.getTok().getLoc();
2937 if (Parser.getTok().isNot(AsmToken::RCurly))
2938 return Error(E, "'}' expected");
2939 Parser.Lex(); // Eat '}' token.
2940
Jim Grosbach27debd62011-12-13 21:48:29 +00002941 // Push the register list operand.
Bill Wendling50d0f582010-11-18 23:43:05 +00002942 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach27debd62011-12-13 21:48:29 +00002943
2944 // The ARM system instruction variants for LDM/STM have a '^' token here.
2945 if (Parser.getTok().is(AsmToken::Caret)) {
2946 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
2947 Parser.Lex(); // Eat '^' token.
2948 }
2949
Bill Wendling50d0f582010-11-18 23:43:05 +00002950 return false;
Kevin Enderbyd7894f12009-10-09 21:12:28 +00002951}
2952
Jim Grosbach98b05a52011-11-30 01:09:44 +00002953// Helper function to parse the lane index for vector lists.
2954ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach7636bf62011-12-02 00:35:16 +00002955parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index) {
2956 Index = 0; // Always return a defined index value.
Jim Grosbach98b05a52011-11-30 01:09:44 +00002957 if (Parser.getTok().is(AsmToken::LBrac)) {
2958 Parser.Lex(); // Eat the '['.
2959 if (Parser.getTok().is(AsmToken::RBrac)) {
2960 // "Dn[]" is the 'all lanes' syntax.
2961 LaneKind = AllLanes;
2962 Parser.Lex(); // Eat the ']'.
2963 return MatchOperand_Success;
2964 }
Jim Grosbachceee9842012-03-19 20:39:53 +00002965
2966 // There's an optional '#' token here. Normally there wouldn't be, but
2967 // inline assemble puts one in, and it's friendly to accept that.
2968 if (Parser.getTok().is(AsmToken::Hash))
2969 Parser.Lex(); // Eat the '#'
2970
Jim Grosbachc9313252011-12-21 01:19:23 +00002971 const MCExpr *LaneIndex;
2972 SMLoc Loc = Parser.getTok().getLoc();
2973 if (getParser().ParseExpression(LaneIndex)) {
2974 Error(Loc, "illegal expression");
2975 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00002976 }
Jim Grosbachc9313252011-12-21 01:19:23 +00002977 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
2978 if (!CE) {
2979 Error(Loc, "lane index must be empty or an integer");
2980 return MatchOperand_ParseFail;
2981 }
2982 if (Parser.getTok().isNot(AsmToken::RBrac)) {
2983 Error(Parser.getTok().getLoc(), "']' expected");
2984 return MatchOperand_ParseFail;
2985 }
2986 Parser.Lex(); // Eat the ']'.
2987 int64_t Val = CE->getValue();
2988
2989 // FIXME: Make this range check context sensitive for .8, .16, .32.
2990 if (Val < 0 || Val > 7) {
2991 Error(Parser.getTok().getLoc(), "lane index out of range");
2992 return MatchOperand_ParseFail;
2993 }
2994 Index = Val;
2995 LaneKind = IndexedLane;
2996 return MatchOperand_Success;
Jim Grosbach98b05a52011-11-30 01:09:44 +00002997 }
2998 LaneKind = NoLanes;
2999 return MatchOperand_Success;
3000}
3001
Jim Grosbach862019c2011-10-18 23:02:30 +00003002// parse a vector register list
3003ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3004parseVectorList(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003005 VectorLaneTy LaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003006 unsigned LaneIndex;
Jim Grosbach5c984e42011-11-15 21:45:55 +00003007 SMLoc S = Parser.getTok().getLoc();
3008 // As an extension (to match gas), support a plain D register or Q register
3009 // (without encosing curly braces) as a single or double entry list,
3010 // respectively.
3011 if (Parser.getTok().is(AsmToken::Identifier)) {
3012 int Reg = tryParseRegister();
3013 if (Reg == -1)
3014 return MatchOperand_NoMatch;
3015 SMLoc E = Parser.getTok().getLoc();
3016 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00003017 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003018 if (Res != MatchOperand_Success)
3019 return Res;
3020 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003021 case NoLanes:
3022 E = Parser.getTok().getLoc();
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003023 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003024 break;
3025 case AllLanes:
3026 E = Parser.getTok().getLoc();
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003027 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3028 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003029 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003030 case IndexedLane:
3031 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003032 LaneIndex,
3033 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003034 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003035 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003036 return MatchOperand_Success;
3037 }
3038 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3039 Reg = getDRegFromQReg(Reg);
Jim Grosbach7636bf62011-12-02 00:35:16 +00003040 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex);
Jim Grosbach98b05a52011-11-30 01:09:44 +00003041 if (Res != MatchOperand_Success)
3042 return Res;
3043 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003044 case NoLanes:
3045 E = Parser.getTok().getLoc();
Jim Grosbach28f08c92012-03-05 19:33:30 +00003046 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003047 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003048 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003049 break;
3050 case AllLanes:
3051 E = Parser.getTok().getLoc();
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003052 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3053 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003054 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3055 S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003056 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003057 case IndexedLane:
3058 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003059 LaneIndex,
3060 false, S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003061 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003062 }
Jim Grosbach5c984e42011-11-15 21:45:55 +00003063 return MatchOperand_Success;
3064 }
3065 Error(S, "vector register expected");
3066 return MatchOperand_ParseFail;
3067 }
3068
3069 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbach862019c2011-10-18 23:02:30 +00003070 return MatchOperand_NoMatch;
3071
Jim Grosbach862019c2011-10-18 23:02:30 +00003072 Parser.Lex(); // Eat '{' token.
3073 SMLoc RegLoc = Parser.getTok().getLoc();
3074
3075 int Reg = tryParseRegister();
3076 if (Reg == -1) {
3077 Error(RegLoc, "register expected");
3078 return MatchOperand_ParseFail;
3079 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003080 unsigned Count = 1;
Jim Grosbach276ed032011-12-15 21:54:55 +00003081 int Spacing = 0;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003082 unsigned FirstReg = Reg;
3083 // The list is of D registers, but we also allow Q regs and just interpret
3084 // them as the two D sub-registers.
3085 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3086 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003087 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3088 // it's ambiguous with four-register single spaced.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003089 ++Reg;
3090 ++Count;
3091 }
Jim Grosbach7636bf62011-12-02 00:35:16 +00003092 if (parseVectorLane(LaneKind, LaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003093 return MatchOperand_ParseFail;
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003094
Jim Grosbache43862b2011-11-15 23:19:15 +00003095 while (Parser.getTok().is(AsmToken::Comma) ||
3096 Parser.getTok().is(AsmToken::Minus)) {
3097 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003098 if (!Spacing)
3099 Spacing = 1; // Register range implies a single spaced list.
3100 else if (Spacing == 2) {
3101 Error(Parser.getTok().getLoc(),
3102 "sequential registers in double spaced list");
3103 return MatchOperand_ParseFail;
3104 }
Jim Grosbache43862b2011-11-15 23:19:15 +00003105 Parser.Lex(); // Eat the minus.
3106 SMLoc EndLoc = Parser.getTok().getLoc();
3107 int EndReg = tryParseRegister();
3108 if (EndReg == -1) {
3109 Error(EndLoc, "register expected");
3110 return MatchOperand_ParseFail;
3111 }
3112 // Allow Q regs and just interpret them as the two D sub-registers.
3113 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3114 EndReg = getDRegFromQReg(EndReg) + 1;
3115 // If the register is the same as the start reg, there's nothing
3116 // more to do.
3117 if (Reg == EndReg)
3118 continue;
3119 // The register must be in the same register class as the first.
3120 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
3121 Error(EndLoc, "invalid register in register list");
3122 return MatchOperand_ParseFail;
3123 }
3124 // Ranges must go from low to high.
3125 if (Reg > EndReg) {
3126 Error(EndLoc, "bad range in register list");
3127 return MatchOperand_ParseFail;
3128 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003129 // Parse the lane specifier if present.
3130 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003131 unsigned NextLaneIndex;
3132 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003133 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003134 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003135 Error(EndLoc, "mismatched lane index in register list");
3136 return MatchOperand_ParseFail;
3137 }
3138 EndLoc = Parser.getTok().getLoc();
Jim Grosbache43862b2011-11-15 23:19:15 +00003139
3140 // Add all the registers in the range to the register list.
3141 Count += EndReg - Reg;
3142 Reg = EndReg;
3143 continue;
3144 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003145 Parser.Lex(); // Eat the comma.
3146 RegLoc = Parser.getTok().getLoc();
3147 int OldReg = Reg;
3148 Reg = tryParseRegister();
3149 if (Reg == -1) {
3150 Error(RegLoc, "register expected");
3151 return MatchOperand_ParseFail;
3152 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003153 // vector register lists must be contiguous.
Jim Grosbach862019c2011-10-18 23:02:30 +00003154 // It's OK to use the enumeration values directly here rather, as the
3155 // VFP register classes have the enum sorted properly.
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003156 //
3157 // The list is of D registers, but we also allow Q regs and just interpret
3158 // them as the two D sub-registers.
3159 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003160 if (!Spacing)
3161 Spacing = 1; // Register range implies a single spaced list.
3162 else if (Spacing == 2) {
3163 Error(RegLoc,
3164 "invalid register in double-spaced list (must be 'D' register')");
3165 return MatchOperand_ParseFail;
3166 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003167 Reg = getDRegFromQReg(Reg);
3168 if (Reg != OldReg + 1) {
3169 Error(RegLoc, "non-contiguous register range");
3170 return MatchOperand_ParseFail;
3171 }
3172 ++Reg;
3173 Count += 2;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003174 // Parse the lane specifier if present.
3175 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003176 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003177 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003178 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003179 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003180 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003181 Error(EndLoc, "mismatched lane index in register list");
3182 return MatchOperand_ParseFail;
3183 }
Jim Grosbachc73d73e2011-10-28 00:06:50 +00003184 continue;
3185 }
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003186 // Normal D register.
3187 // Figure out the register spacing (single or double) of the list if
3188 // we don't know it already.
3189 if (!Spacing)
3190 Spacing = 1 + (Reg == OldReg + 2);
3191
3192 // Just check that it's contiguous and keep going.
3193 if (Reg != OldReg + Spacing) {
Jim Grosbach862019c2011-10-18 23:02:30 +00003194 Error(RegLoc, "non-contiguous register range");
3195 return MatchOperand_ParseFail;
3196 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003197 ++Count;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003198 // Parse the lane specifier if present.
3199 VectorLaneTy NextLaneKind;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003200 unsigned NextLaneIndex;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003201 SMLoc EndLoc = Parser.getTok().getLoc();
Jim Grosbach7636bf62011-12-02 00:35:16 +00003202 if (parseVectorLane(NextLaneKind, NextLaneIndex) != MatchOperand_Success)
Jim Grosbach98b05a52011-11-30 01:09:44 +00003203 return MatchOperand_ParseFail;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003204 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003205 Error(EndLoc, "mismatched lane index in register list");
3206 return MatchOperand_ParseFail;
3207 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003208 }
3209
3210 SMLoc E = Parser.getTok().getLoc();
3211 if (Parser.getTok().isNot(AsmToken::RCurly)) {
3212 Error(E, "'}' expected");
3213 return MatchOperand_ParseFail;
3214 }
3215 Parser.Lex(); // Eat '}' token.
3216
Jim Grosbach98b05a52011-11-30 01:09:44 +00003217 switch (LaneKind) {
Jim Grosbach98b05a52011-11-30 01:09:44 +00003218 case NoLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003219 // Two-register operands have been converted to the
Jim Grosbachc3384c92012-03-05 21:43:40 +00003220 // composite register classes.
3221 if (Count == 2) {
3222 const MCRegisterClass *RC = (Spacing == 1) ?
3223 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3224 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3225 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3226 }
Jim Grosbach28f08c92012-03-05 19:33:30 +00003227
Jim Grosbach0aaf4cd2011-12-15 21:44:33 +00003228 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3229 (Spacing == 2), S, E));
Jim Grosbach98b05a52011-11-30 01:09:44 +00003230 break;
3231 case AllLanes:
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003232 // Two-register operands have been converted to the
3233 // composite register classes.
Jim Grosbach4d0983a2012-03-06 23:10:38 +00003234 if (Count == 2) {
3235 const MCRegisterClass *RC = (Spacing == 1) ?
3236 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3237 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbachc0fc4502012-03-06 22:01:44 +00003238 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3239 }
Jim Grosbach98b05a52011-11-30 01:09:44 +00003240 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbach3471d4f2011-12-21 00:38:54 +00003241 (Spacing == 2),
Jim Grosbach98b05a52011-11-30 01:09:44 +00003242 S, E));
3243 break;
Jim Grosbach7636bf62011-12-02 00:35:16 +00003244 case IndexedLane:
3245 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach95fad1c2011-12-20 19:21:26 +00003246 LaneIndex,
3247 (Spacing == 2),
3248 S, E));
Jim Grosbach7636bf62011-12-02 00:35:16 +00003249 break;
Jim Grosbach98b05a52011-11-30 01:09:44 +00003250 }
Jim Grosbach862019c2011-10-18 23:02:30 +00003251 return MatchOperand_Success;
3252}
3253
Jim Grosbach43904292011-07-25 20:14:50 +00003254/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
Jim Grosbachf922c472011-02-12 01:34:40 +00003255ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003256parseMemBarrierOptOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003257 SMLoc S = Parser.getTok().getLoc();
3258 const AsmToken &Tok = Parser.getTok();
3259 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3260 StringRef OptStr = Tok.getString();
3261
3262 unsigned Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()))
3263 .Case("sy", ARM_MB::SY)
3264 .Case("st", ARM_MB::ST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003265 .Case("sh", ARM_MB::ISH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003266 .Case("ish", ARM_MB::ISH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003267 .Case("shst", ARM_MB::ISHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003268 .Case("ishst", ARM_MB::ISHST)
3269 .Case("nsh", ARM_MB::NSH)
Jim Grosbach032434d2011-07-13 23:40:38 +00003270 .Case("un", ARM_MB::NSH)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003271 .Case("nshst", ARM_MB::NSHST)
Jim Grosbach032434d2011-07-13 23:40:38 +00003272 .Case("unst", ARM_MB::NSHST)
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003273 .Case("osh", ARM_MB::OSH)
3274 .Case("oshst", ARM_MB::OSHST)
3275 .Default(~0U);
3276
3277 if (Opt == ~0U)
Jim Grosbachf922c472011-02-12 01:34:40 +00003278 return MatchOperand_NoMatch;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003279
3280 Parser.Lex(); // Eat identifier token.
3281 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbachf922c472011-02-12 01:34:40 +00003282 return MatchOperand_Success;
Bruno Cardoso Lopes706d9462011-02-07 22:09:15 +00003283}
3284
Jim Grosbach43904292011-07-25 20:14:50 +00003285/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003286ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003287parseProcIFlagsOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003288 SMLoc S = Parser.getTok().getLoc();
3289 const AsmToken &Tok = Parser.getTok();
Richard Bartona1c73672012-06-14 10:48:04 +00003290 if (!Tok.is(AsmToken::Identifier))
3291 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003292 StringRef IFlagsStr = Tok.getString();
3293
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003294 // An iflags string of "none" is interpreted to mean that none of the AIF
3295 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003296 unsigned IFlags = 0;
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003297 if (IFlagsStr != "none") {
3298 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3299 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3300 .Case("a", ARM_PROC::A)
3301 .Case("i", ARM_PROC::I)
3302 .Case("f", ARM_PROC::F)
3303 .Default(~0U);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003304
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003305 // If some specific iflag is already set, it means that some letter is
3306 // present more than once, this is not acceptable.
3307 if (Flag == ~0U || (IFlags & Flag))
3308 return MatchOperand_NoMatch;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003309
Owen Anderson2dbb46a2011-10-05 17:16:40 +00003310 IFlags |= Flag;
3311 }
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00003312 }
3313
3314 Parser.Lex(); // Eat identifier token.
3315 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3316 return MatchOperand_Success;
3317}
3318
Jim Grosbach43904292011-07-25 20:14:50 +00003319/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003320ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jim Grosbach43904292011-07-25 20:14:50 +00003321parseMSRMaskOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003322 SMLoc S = Parser.getTok().getLoc();
3323 const AsmToken &Tok = Parser.getTok();
3324 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
3325 StringRef Mask = Tok.getString();
3326
James Molloyacad68d2011-09-28 14:21:38 +00003327 if (isMClass()) {
3328 // See ARMv6-M 10.1.1
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00003329 std::string Name = Mask.lower();
3330 unsigned FlagsVal = StringSwitch<unsigned>(Name)
Kevin Enderby0fd4f3c2012-05-17 22:18:01 +00003331 // Note: in the documentation:
3332 // ARM deprecates using MSR APSR without a _<bits> qualifier as an alias
3333 // for MSR APSR_nzcvq.
3334 // but we do make it an alias here. This is so to get the "mask encoding"
3335 // bits correct on MSR APSR writes.
3336 //
3337 // FIXME: Note the 0xc00 "mask encoding" bits version of the registers
3338 // should really only be allowed when writing a special register. Note
3339 // they get dropped in the MRS instruction reading a special register as
3340 // the SYSm field is only 8 bits.
3341 //
3342 // FIXME: the _g and _nzcvqg versions are only allowed if the processor
3343 // includes the DSP extension but that is not checked.
3344 .Case("apsr", 0x800)
3345 .Case("apsr_nzcvq", 0x800)
3346 .Case("apsr_g", 0x400)
3347 .Case("apsr_nzcvqg", 0xc00)
3348 .Case("iapsr", 0x801)
3349 .Case("iapsr_nzcvq", 0x801)
3350 .Case("iapsr_g", 0x401)
3351 .Case("iapsr_nzcvqg", 0xc01)
3352 .Case("eapsr", 0x802)
3353 .Case("eapsr_nzcvq", 0x802)
3354 .Case("eapsr_g", 0x402)
3355 .Case("eapsr_nzcvqg", 0xc02)
3356 .Case("xpsr", 0x803)
3357 .Case("xpsr_nzcvq", 0x803)
3358 .Case("xpsr_g", 0x403)
3359 .Case("xpsr_nzcvqg", 0xc03)
Kevin Enderbyf49a4092012-06-15 22:14:44 +00003360 .Case("ipsr", 0x805)
3361 .Case("epsr", 0x806)
3362 .Case("iepsr", 0x807)
3363 .Case("msp", 0x808)
3364 .Case("psp", 0x809)
3365 .Case("primask", 0x810)
3366 .Case("basepri", 0x811)
3367 .Case("basepri_max", 0x812)
3368 .Case("faultmask", 0x813)
3369 .Case("control", 0x814)
James Molloyacad68d2011-09-28 14:21:38 +00003370 .Default(~0U);
Jim Grosbach18c8d122011-12-22 17:17:10 +00003371
James Molloyacad68d2011-09-28 14:21:38 +00003372 if (FlagsVal == ~0U)
3373 return MatchOperand_NoMatch;
3374
Kevin Enderbyf49a4092012-06-15 22:14:44 +00003375 if (!hasV7Ops() && FlagsVal >= 0x811 && FlagsVal <= 0x813)
James Molloyacad68d2011-09-28 14:21:38 +00003376 // basepri, basepri_max and faultmask only valid for V7m.
3377 return MatchOperand_NoMatch;
Jim Grosbach18c8d122011-12-22 17:17:10 +00003378
James Molloyacad68d2011-09-28 14:21:38 +00003379 Parser.Lex(); // Eat identifier token.
3380 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3381 return MatchOperand_Success;
3382 }
3383
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003384 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
3385 size_t Start = 0, Next = Mask.find('_');
3386 StringRef Flags = "";
Benjamin Kramer59085362011-11-06 20:37:06 +00003387 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003388 if (Next != StringRef::npos)
3389 Flags = Mask.slice(Next+1, Mask.size());
3390
3391 // FlagsVal contains the complete mask:
3392 // 3-0: Mask
3393 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3394 unsigned FlagsVal = 0;
3395
3396 if (SpecReg == "apsr") {
3397 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachb29b4dd2011-07-19 22:45:10 +00003398 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003399 .Case("g", 0x4) // same as CPSR_s
3400 .Case("nzcvqg", 0xc) // same as CPSR_fs
3401 .Default(~0U);
3402
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003403 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003404 if (!Flags.empty())
3405 return MatchOperand_NoMatch;
3406 else
Jim Grosbachbf841cf2011-09-14 20:03:46 +00003407 FlagsVal = 8; // No flag
Joerg Sonnenberger4b19c982011-02-19 00:43:45 +00003408 }
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003409 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Jim Grosbachb657a902012-04-05 03:17:53 +00003410 // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
3411 if (Flags == "all" || Flags == "")
Bruno Cardoso Lopes56926a32011-05-25 00:35:03 +00003412 Flags = "fc";
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003413 for (int i = 0, e = Flags.size(); i != e; ++i) {
3414 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
3415 .Case("c", 1)
3416 .Case("x", 2)
3417 .Case("s", 4)
3418 .Case("f", 8)
3419 .Default(~0U);
3420
3421 // If some specific flag is already set, it means that some letter is
3422 // present more than once, this is not acceptable.
3423 if (FlagsVal == ~0U || (FlagsVal & Flag))
3424 return MatchOperand_NoMatch;
3425 FlagsVal |= Flag;
3426 }
3427 } else // No match for special register.
3428 return MatchOperand_NoMatch;
3429
Owen Anderson7784f1d2011-10-21 18:43:28 +00003430 // Special register without flags is NOT equivalent to "fc" flags.
3431 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
3432 // two lines would enable gas compatibility at the expense of breaking
3433 // round-tripping.
3434 //
3435 // if (!FlagsVal)
3436 // FlagsVal = 0x9;
Bruno Cardoso Lopes584bf7b2011-02-18 19:45:59 +00003437
3438 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
3439 if (SpecReg == "spsr")
3440 FlagsVal |= 16;
3441
3442 Parser.Lex(); // Eat identifier token.
3443 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
3444 return MatchOperand_Success;
3445}
3446
Jim Grosbachf6c05252011-07-21 17:23:04 +00003447ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3448parsePKHImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands, StringRef Op,
3449 int Low, int High) {
3450 const AsmToken &Tok = Parser.getTok();
3451 if (Tok.isNot(AsmToken::Identifier)) {
3452 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3453 return MatchOperand_ParseFail;
3454 }
3455 StringRef ShiftName = Tok.getString();
Benjamin Kramer59085362011-11-06 20:37:06 +00003456 std::string LowerOp = Op.lower();
3457 std::string UpperOp = Op.upper();
Jim Grosbachf6c05252011-07-21 17:23:04 +00003458 if (ShiftName != LowerOp && ShiftName != UpperOp) {
3459 Error(Parser.getTok().getLoc(), Op + " operand expected.");
3460 return MatchOperand_ParseFail;
3461 }
3462 Parser.Lex(); // Eat shift type token.
3463
3464 // There must be a '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003465 if (Parser.getTok().isNot(AsmToken::Hash) &&
3466 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbachf6c05252011-07-21 17:23:04 +00003467 Error(Parser.getTok().getLoc(), "'#' expected");
3468 return MatchOperand_ParseFail;
3469 }
3470 Parser.Lex(); // Eat hash token.
3471
3472 const MCExpr *ShiftAmount;
3473 SMLoc Loc = Parser.getTok().getLoc();
3474 if (getParser().ParseExpression(ShiftAmount)) {
3475 Error(Loc, "illegal expression");
3476 return MatchOperand_ParseFail;
3477 }
3478 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3479 if (!CE) {
3480 Error(Loc, "constant expression expected");
3481 return MatchOperand_ParseFail;
3482 }
3483 int Val = CE->getValue();
3484 if (Val < Low || Val > High) {
3485 Error(Loc, "immediate value out of range");
3486 return MatchOperand_ParseFail;
3487 }
3488
3489 Operands.push_back(ARMOperand::CreateImm(CE, Loc, Parser.getTok().getLoc()));
3490
3491 return MatchOperand_Success;
3492}
3493
Jim Grosbachc27d4f92011-07-22 17:44:50 +00003494ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3495parseSetEndImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3496 const AsmToken &Tok = Parser.getTok();
3497 SMLoc S = Tok.getLoc();
3498 if (Tok.isNot(AsmToken::Identifier)) {
3499 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3500 return MatchOperand_ParseFail;
3501 }
3502 int Val = StringSwitch<int>(Tok.getString())
3503 .Case("be", 1)
3504 .Case("le", 0)
3505 .Default(-1);
3506 Parser.Lex(); // Eat the token.
3507
3508 if (Val == -1) {
3509 Error(Tok.getLoc(), "'be' or 'le' operand expected");
3510 return MatchOperand_ParseFail;
3511 }
3512 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
3513 getContext()),
3514 S, Parser.getTok().getLoc()));
3515 return MatchOperand_Success;
3516}
3517
Jim Grosbach580f4a92011-07-25 22:20:28 +00003518/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
3519/// instructions. Legal values are:
3520/// lsl #n 'n' in [0,31]
3521/// asr #n 'n' in [1,32]
3522/// n == 32 encoded as n == 0.
3523ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3524parseShifterImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3525 const AsmToken &Tok = Parser.getTok();
3526 SMLoc S = Tok.getLoc();
3527 if (Tok.isNot(AsmToken::Identifier)) {
3528 Error(S, "shift operator 'asr' or 'lsl' expected");
3529 return MatchOperand_ParseFail;
3530 }
3531 StringRef ShiftName = Tok.getString();
3532 bool isASR;
3533 if (ShiftName == "lsl" || ShiftName == "LSL")
3534 isASR = false;
3535 else if (ShiftName == "asr" || ShiftName == "ASR")
3536 isASR = true;
3537 else {
3538 Error(S, "shift operator 'asr' or 'lsl' expected");
3539 return MatchOperand_ParseFail;
3540 }
3541 Parser.Lex(); // Eat the operator.
3542
3543 // A '#' and a shift amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003544 if (Parser.getTok().isNot(AsmToken::Hash) &&
3545 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach580f4a92011-07-25 22:20:28 +00003546 Error(Parser.getTok().getLoc(), "'#' expected");
3547 return MatchOperand_ParseFail;
3548 }
3549 Parser.Lex(); // Eat hash token.
3550
3551 const MCExpr *ShiftAmount;
3552 SMLoc E = Parser.getTok().getLoc();
3553 if (getParser().ParseExpression(ShiftAmount)) {
3554 Error(E, "malformed shift expression");
3555 return MatchOperand_ParseFail;
3556 }
3557 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3558 if (!CE) {
3559 Error(E, "shift amount must be an immediate");
3560 return MatchOperand_ParseFail;
3561 }
3562
3563 int64_t Val = CE->getValue();
3564 if (isASR) {
3565 // Shift amount must be in [1,32]
3566 if (Val < 1 || Val > 32) {
3567 Error(E, "'asr' shift amount must be in range [1,32]");
3568 return MatchOperand_ParseFail;
3569 }
Owen Anderson0afa0092011-09-26 21:06:22 +00003570 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
3571 if (isThumb() && Val == 32) {
3572 Error(E, "'asr #32' shift amount not allowed in Thumb mode");
3573 return MatchOperand_ParseFail;
3574 }
Jim Grosbach580f4a92011-07-25 22:20:28 +00003575 if (Val == 32) Val = 0;
3576 } else {
3577 // Shift amount must be in [1,32]
3578 if (Val < 0 || Val > 31) {
3579 Error(E, "'lsr' shift amount must be in range [0,31]");
3580 return MatchOperand_ParseFail;
3581 }
3582 }
3583
3584 E = Parser.getTok().getLoc();
3585 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, E));
3586
3587 return MatchOperand_Success;
3588}
3589
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003590/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
3591/// of instructions. Legal values are:
3592/// ror #n 'n' in {0, 8, 16, 24}
3593ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3594parseRotImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3595 const AsmToken &Tok = Parser.getTok();
3596 SMLoc S = Tok.getLoc();
Jim Grosbach326efe52011-09-19 20:29:33 +00003597 if (Tok.isNot(AsmToken::Identifier))
3598 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003599 StringRef ShiftName = Tok.getString();
Jim Grosbach326efe52011-09-19 20:29:33 +00003600 if (ShiftName != "ror" && ShiftName != "ROR")
3601 return MatchOperand_NoMatch;
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003602 Parser.Lex(); // Eat the operator.
3603
3604 // A '#' and a rotate amount.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003605 if (Parser.getTok().isNot(AsmToken::Hash) &&
3606 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach7e1547e2011-07-27 20:15:40 +00003607 Error(Parser.getTok().getLoc(), "'#' expected");
3608 return MatchOperand_ParseFail;
3609 }
3610 Parser.Lex(); // Eat hash token.
3611
3612 const MCExpr *ShiftAmount;
3613 SMLoc E = Parser.getTok().getLoc();
3614 if (getParser().ParseExpression(ShiftAmount)) {
3615 Error(E, "malformed rotate expression");
3616 return MatchOperand_ParseFail;
3617 }
3618 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
3619 if (!CE) {
3620 Error(E, "rotate amount must be an immediate");
3621 return MatchOperand_ParseFail;
3622 }
3623
3624 int64_t Val = CE->getValue();
3625 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
3626 // normally, zero is represented in asm by omitting the rotate operand
3627 // entirely.
3628 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
3629 Error(E, "'ror' rotate amount must be 8, 16, or 24");
3630 return MatchOperand_ParseFail;
3631 }
3632
3633 E = Parser.getTok().getLoc();
3634 Operands.push_back(ARMOperand::CreateRotImm(Val, S, E));
3635
3636 return MatchOperand_Success;
3637}
3638
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003639ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3640parseBitfield(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3641 SMLoc S = Parser.getTok().getLoc();
3642 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003643 if (Parser.getTok().isNot(AsmToken::Hash) &&
3644 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003645 Error(Parser.getTok().getLoc(), "'#' expected");
3646 return MatchOperand_ParseFail;
3647 }
3648 Parser.Lex(); // Eat hash token.
3649
3650 const MCExpr *LSBExpr;
3651 SMLoc E = Parser.getTok().getLoc();
3652 if (getParser().ParseExpression(LSBExpr)) {
3653 Error(E, "malformed immediate expression");
3654 return MatchOperand_ParseFail;
3655 }
3656 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
3657 if (!CE) {
3658 Error(E, "'lsb' operand must be an immediate");
3659 return MatchOperand_ParseFail;
3660 }
3661
3662 int64_t LSB = CE->getValue();
3663 // The LSB must be in the range [0,31]
3664 if (LSB < 0 || LSB > 31) {
3665 Error(E, "'lsb' operand must be in the range [0,31]");
3666 return MatchOperand_ParseFail;
3667 }
3668 E = Parser.getTok().getLoc();
3669
3670 // Expect another immediate operand.
3671 if (Parser.getTok().isNot(AsmToken::Comma)) {
3672 Error(Parser.getTok().getLoc(), "too few operands");
3673 return MatchOperand_ParseFail;
3674 }
3675 Parser.Lex(); // Eat hash token.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003676 if (Parser.getTok().isNot(AsmToken::Hash) &&
3677 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach293a2ee2011-07-28 21:34:26 +00003678 Error(Parser.getTok().getLoc(), "'#' expected");
3679 return MatchOperand_ParseFail;
3680 }
3681 Parser.Lex(); // Eat hash token.
3682
3683 const MCExpr *WidthExpr;
3684 if (getParser().ParseExpression(WidthExpr)) {
3685 Error(E, "malformed immediate expression");
3686 return MatchOperand_ParseFail;
3687 }
3688 CE = dyn_cast<MCConstantExpr>(WidthExpr);
3689 if (!CE) {
3690 Error(E, "'width' operand must be an immediate");
3691 return MatchOperand_ParseFail;
3692 }
3693
3694 int64_t Width = CE->getValue();
3695 // The LSB must be in the range [1,32-lsb]
3696 if (Width < 1 || Width > 32 - LSB) {
3697 Error(E, "'width' operand must be in the range [1,32-lsb]");
3698 return MatchOperand_ParseFail;
3699 }
3700 E = Parser.getTok().getLoc();
3701
3702 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, E));
3703
3704 return MatchOperand_Success;
3705}
3706
Jim Grosbach7ce05792011-08-03 23:50:40 +00003707ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3708parsePostIdxReg(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3709 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003710 // postidx_reg := '+' register {, shift}
3711 // | '-' register {, shift}
3712 // | register {, shift}
Jim Grosbach7ce05792011-08-03 23:50:40 +00003713
3714 // This method must return MatchOperand_NoMatch without consuming any tokens
3715 // in the case where there is no match, as other alternatives take other
3716 // parse methods.
3717 AsmToken Tok = Parser.getTok();
3718 SMLoc S = Tok.getLoc();
3719 bool haveEaten = false;
Jim Grosbach16578b52011-08-05 16:11:38 +00003720 bool isAdd = true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003721 int Reg = -1;
3722 if (Tok.is(AsmToken::Plus)) {
3723 Parser.Lex(); // Eat the '+' token.
3724 haveEaten = true;
3725 } else if (Tok.is(AsmToken::Minus)) {
3726 Parser.Lex(); // Eat the '-' token.
Jim Grosbach16578b52011-08-05 16:11:38 +00003727 isAdd = false;
Jim Grosbach7ce05792011-08-03 23:50:40 +00003728 haveEaten = true;
3729 }
3730 if (Parser.getTok().is(AsmToken::Identifier))
3731 Reg = tryParseRegister();
3732 if (Reg == -1) {
3733 if (!haveEaten)
3734 return MatchOperand_NoMatch;
3735 Error(Parser.getTok().getLoc(), "register expected");
3736 return MatchOperand_ParseFail;
3737 }
3738 SMLoc E = Parser.getTok().getLoc();
3739
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003740 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
3741 unsigned ShiftImm = 0;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00003742 if (Parser.getTok().is(AsmToken::Comma)) {
3743 Parser.Lex(); // Eat the ','.
3744 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
3745 return MatchOperand_ParseFail;
3746 }
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00003747
3748 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
3749 ShiftImm, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003750
3751 return MatchOperand_Success;
3752}
3753
Jim Grosbach251bf252011-08-10 21:56:18 +00003754ARMAsmParser::OperandMatchResultTy ARMAsmParser::
3755parseAM3Offset(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3756 // Check for a post-index addressing register operand. Specifically:
3757 // am3offset := '+' register
3758 // | '-' register
3759 // | register
3760 // | # imm
3761 // | # + imm
3762 // | # - imm
3763
3764 // This method must return MatchOperand_NoMatch without consuming any tokens
3765 // in the case where there is no match, as other alternatives take other
3766 // parse methods.
3767 AsmToken Tok = Parser.getTok();
3768 SMLoc S = Tok.getLoc();
3769
3770 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00003771 if (Parser.getTok().is(AsmToken::Hash) ||
3772 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach251bf252011-08-10 21:56:18 +00003773 Parser.Lex(); // Eat the '#'.
3774 // Explicitly look for a '-', as we need to encode negative zero
3775 // differently.
3776 bool isNegative = Parser.getTok().is(AsmToken::Minus);
3777 const MCExpr *Offset;
3778 if (getParser().ParseExpression(Offset))
3779 return MatchOperand_ParseFail;
3780 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
3781 if (!CE) {
3782 Error(S, "constant expression expected");
3783 return MatchOperand_ParseFail;
3784 }
3785 SMLoc E = Tok.getLoc();
3786 // Negative zero is encoded as the flag value INT32_MIN.
3787 int32_t Val = CE->getValue();
3788 if (isNegative && Val == 0)
3789 Val = INT32_MIN;
3790
3791 Operands.push_back(
3792 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
3793
3794 return MatchOperand_Success;
3795 }
3796
3797
3798 bool haveEaten = false;
3799 bool isAdd = true;
3800 int Reg = -1;
3801 if (Tok.is(AsmToken::Plus)) {
3802 Parser.Lex(); // Eat the '+' token.
3803 haveEaten = true;
3804 } else if (Tok.is(AsmToken::Minus)) {
3805 Parser.Lex(); // Eat the '-' token.
3806 isAdd = false;
3807 haveEaten = true;
3808 }
3809 if (Parser.getTok().is(AsmToken::Identifier))
3810 Reg = tryParseRegister();
3811 if (Reg == -1) {
3812 if (!haveEaten)
3813 return MatchOperand_NoMatch;
3814 Error(Parser.getTok().getLoc(), "register expected");
3815 return MatchOperand_ParseFail;
3816 }
3817 SMLoc E = Parser.getTok().getLoc();
3818
3819 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
3820 0, S, E));
3821
3822 return MatchOperand_Success;
3823}
3824
Jim Grosbacha77295d2011-09-08 22:07:06 +00003825/// cvtT2LdrdPre - Convert parsed operands to MCInst.
3826/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3827/// when they refer multiple MIOperands inside a single one.
3828bool ARMAsmParser::
3829cvtT2LdrdPre(MCInst &Inst, unsigned Opcode,
3830 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3831 // Rt, Rt2
3832 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3833 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3834 // Create a writeback register dummy placeholder.
3835 Inst.addOperand(MCOperand::CreateReg(0));
3836 // addr
3837 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3838 // pred
3839 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3840 return true;
3841}
3842
3843/// cvtT2StrdPre - Convert parsed operands to MCInst.
3844/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3845/// when they refer multiple MIOperands inside a single one.
3846bool ARMAsmParser::
3847cvtT2StrdPre(MCInst &Inst, unsigned Opcode,
3848 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3849 // Create a writeback register dummy placeholder.
3850 Inst.addOperand(MCOperand::CreateReg(0));
3851 // Rt, Rt2
3852 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3853 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
3854 // addr
3855 ((ARMOperand*)Operands[4])->addMemImm8s4OffsetOperands(Inst, 2);
3856 // pred
3857 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3858 return true;
3859}
3860
Jim Grosbacheeec0252011-09-08 00:39:19 +00003861/// cvtLdWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3862/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3863/// when they refer multiple MIOperands inside a single one.
3864bool ARMAsmParser::
3865cvtLdWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3866 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3867 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3868
3869 // Create a writeback register dummy placeholder.
3870 Inst.addOperand(MCOperand::CreateImm(0));
3871
3872 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3873 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3874 return true;
3875}
3876
Jim Grosbachee2c2a42011-09-16 21:55:56 +00003877/// cvtStWriteBackRegT2AddrModeImm8 - Convert parsed operands to MCInst.
3878/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3879/// when they refer multiple MIOperands inside a single one.
3880bool ARMAsmParser::
3881cvtStWriteBackRegT2AddrModeImm8(MCInst &Inst, unsigned Opcode,
3882 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3883 // Create a writeback register dummy placeholder.
3884 Inst.addOperand(MCOperand::CreateImm(0));
3885 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3886 ((ARMOperand*)Operands[3])->addMemImm8OffsetOperands(Inst, 2);
3887 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3888 return true;
3889}
3890
Jim Grosbach1355cf12011-07-26 17:10:22 +00003891/// cvtLdWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003892/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3893/// when they refer multiple MIOperands inside a single one.
3894bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003895cvtLdWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003896 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3897 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3898
3899 // Create a writeback register dummy placeholder.
3900 Inst.addOperand(MCOperand::CreateImm(0));
3901
Jim Grosbach7ce05792011-08-03 23:50:40 +00003902 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003903 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3904 return true;
3905}
3906
Owen Anderson9ab0f252011-08-26 20:43:14 +00003907/// cvtLdWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3908/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3909/// when they refer multiple MIOperands inside a single one.
3910bool ARMAsmParser::
3911cvtLdWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3912 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3913 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3914
3915 // Create a writeback register dummy placeholder.
3916 Inst.addOperand(MCOperand::CreateImm(0));
3917
3918 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3919 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3920 return true;
3921}
3922
3923
Jim Grosbach548340c2011-08-11 19:22:40 +00003924/// cvtStWriteBackRegAddrModeImm12 - Convert parsed operands to MCInst.
3925/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3926/// when they refer multiple MIOperands inside a single one.
3927bool ARMAsmParser::
3928cvtStWriteBackRegAddrModeImm12(MCInst &Inst, unsigned Opcode,
3929 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3930 // Create a writeback register dummy placeholder.
3931 Inst.addOperand(MCOperand::CreateImm(0));
3932 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3933 ((ARMOperand*)Operands[3])->addMemImm12OffsetOperands(Inst, 2);
3934 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3935 return true;
3936}
3937
Jim Grosbach1355cf12011-07-26 17:10:22 +00003938/// cvtStWriteBackRegAddrMode2 - Convert parsed operands to MCInst.
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003939/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3940/// when they refer multiple MIOperands inside a single one.
3941bool ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00003942cvtStWriteBackRegAddrMode2(MCInst &Inst, unsigned Opcode,
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003943 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3944 // Create a writeback register dummy placeholder.
3945 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach548340c2011-08-11 19:22:40 +00003946 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3947 ((ARMOperand*)Operands[3])->addAddrMode2Operands(Inst, 3);
3948 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003949 return true;
3950}
3951
Jim Grosbach7b8f46c2011-08-11 21:17:22 +00003952/// cvtStWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
3953/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3954/// when they refer multiple MIOperands inside a single one.
3955bool ARMAsmParser::
3956cvtStWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
3957 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3958 // Create a writeback register dummy placeholder.
3959 Inst.addOperand(MCOperand::CreateImm(0));
3960 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
3961 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
3962 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3963 return true;
3964}
3965
Jim Grosbach7ce05792011-08-03 23:50:40 +00003966/// cvtLdExtTWriteBackImm - Convert parsed operands to MCInst.
3967/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3968/// when they refer multiple MIOperands inside a single one.
3969bool ARMAsmParser::
3970cvtLdExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
3971 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3972 // Rt
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003973 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00003974 // Create a writeback register dummy placeholder.
3975 Inst.addOperand(MCOperand::CreateImm(0));
3976 // addr
3977 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3978 // offset
3979 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
3980 // pred
Bruno Cardoso Lopesae085542011-03-31 23:26:08 +00003981 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
3982 return true;
3983}
3984
Jim Grosbach7ce05792011-08-03 23:50:40 +00003985/// cvtLdExtTWriteBackReg - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003986/// Needed here because the Asm Gen Matcher can't handle properly tied operands
3987/// when they refer multiple MIOperands inside a single one.
3988bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00003989cvtLdExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
3990 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
3991 // Rt
Owen Andersonaa3402e2011-07-28 17:18:57 +00003992 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00003993 // Create a writeback register dummy placeholder.
3994 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00003995 // addr
3996 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
3997 // offset
3998 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
3999 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004000 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4001 return true;
4002}
4003
Jim Grosbach7ce05792011-08-03 23:50:40 +00004004/// cvtStExtTWriteBackImm - Convert parsed operands to MCInst.
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004005/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4006/// when they refer multiple MIOperands inside a single one.
4007bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004008cvtStExtTWriteBackImm(MCInst &Inst, unsigned Opcode,
4009 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004010 // Create a writeback register dummy placeholder.
4011 Inst.addOperand(MCOperand::CreateImm(0));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004012 // Rt
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004013 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004014 // addr
4015 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4016 // offset
4017 ((ARMOperand*)Operands[4])->addPostIdxImm8Operands(Inst, 1);
4018 // pred
4019 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4020 return true;
4021}
4022
4023/// cvtStExtTWriteBackReg - Convert parsed operands to MCInst.
4024/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4025/// when they refer multiple MIOperands inside a single one.
4026bool ARMAsmParser::
4027cvtStExtTWriteBackReg(MCInst &Inst, unsigned Opcode,
4028 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4029 // Create a writeback register dummy placeholder.
4030 Inst.addOperand(MCOperand::CreateImm(0));
4031 // Rt
4032 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4033 // addr
4034 ((ARMOperand*)Operands[3])->addMemNoOffsetOperands(Inst, 1);
4035 // offset
4036 ((ARMOperand*)Operands[4])->addPostIdxRegOperands(Inst, 2);
4037 // pred
Bruno Cardoso Lopesac79e4c2011-04-04 17:18:19 +00004038 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4039 return true;
4040}
4041
Jim Grosbach2fd2b872011-08-10 20:29:19 +00004042/// cvtLdrdPre - Convert parsed operands to MCInst.
4043/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4044/// when they refer multiple MIOperands inside a single one.
4045bool ARMAsmParser::
4046cvtLdrdPre(MCInst &Inst, unsigned Opcode,
4047 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4048 // Rt, Rt2
4049 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4050 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4051 // Create a writeback register dummy placeholder.
4052 Inst.addOperand(MCOperand::CreateImm(0));
4053 // addr
4054 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4055 // pred
4056 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4057 return true;
4058}
4059
Jim Grosbach14605d12011-08-11 20:28:23 +00004060/// cvtStrdPre - Convert parsed operands to MCInst.
4061/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4062/// when they refer multiple MIOperands inside a single one.
4063bool ARMAsmParser::
4064cvtStrdPre(MCInst &Inst, unsigned Opcode,
4065 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4066 // Create a writeback register dummy placeholder.
4067 Inst.addOperand(MCOperand::CreateImm(0));
4068 // Rt, Rt2
4069 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4070 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4071 // addr
4072 ((ARMOperand*)Operands[4])->addAddrMode3Operands(Inst, 3);
4073 // pred
4074 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4075 return true;
4076}
4077
Jim Grosbach623a4542011-08-10 22:42:16 +00004078/// cvtLdWriteBackRegAddrMode3 - Convert parsed operands to MCInst.
4079/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4080/// when they refer multiple MIOperands inside a single one.
4081bool ARMAsmParser::
4082cvtLdWriteBackRegAddrMode3(MCInst &Inst, unsigned Opcode,
4083 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4084 ((ARMOperand*)Operands[2])->addRegOperands(Inst, 1);
4085 // Create a writeback register dummy placeholder.
4086 Inst.addOperand(MCOperand::CreateImm(0));
4087 ((ARMOperand*)Operands[3])->addAddrMode3Operands(Inst, 3);
4088 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4089 return true;
4090}
4091
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004092/// cvtThumbMultiple- Convert parsed operands to MCInst.
4093/// Needed here because the Asm Gen Matcher can't handle properly tied operands
4094/// when they refer multiple MIOperands inside a single one.
4095bool ARMAsmParser::
4096cvtThumbMultiply(MCInst &Inst, unsigned Opcode,
4097 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4098 // The second source operand must be the same register as the destination
4099 // operand.
4100 if (Operands.size() == 6 &&
Jim Grosbach7a010692011-08-19 22:30:46 +00004101 (((ARMOperand*)Operands[3])->getReg() !=
4102 ((ARMOperand*)Operands[5])->getReg()) &&
4103 (((ARMOperand*)Operands[3])->getReg() !=
4104 ((ARMOperand*)Operands[4])->getReg())) {
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004105 Error(Operands[3]->getStartLoc(),
Jim Grosbach7a010692011-08-19 22:30:46 +00004106 "destination register must match source register");
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004107 return false;
4108 }
4109 ((ARMOperand*)Operands[3])->addRegOperands(Inst, 1);
4110 ((ARMOperand*)Operands[1])->addCCOutOperands(Inst, 1);
Jim Grosbach1b332862011-11-10 22:10:12 +00004111 // If we have a three-operand form, make sure to set Rn to be the operand
4112 // that isn't the same as Rd.
4113 unsigned RegOp = 4;
4114 if (Operands.size() == 6 &&
4115 ((ARMOperand*)Operands[4])->getReg() ==
4116 ((ARMOperand*)Operands[3])->getReg())
4117 RegOp = 5;
4118 ((ARMOperand*)Operands[RegOp])->addRegOperands(Inst, 1);
4119 Inst.addOperand(Inst.getOperand(0));
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00004120 ((ARMOperand*)Operands[2])->addCondCodeOperands(Inst, 2);
4121
4122 return true;
4123}
Jim Grosbach623a4542011-08-10 22:42:16 +00004124
Jim Grosbach12431322011-10-24 22:16:58 +00004125bool ARMAsmParser::
4126cvtVLDwbFixed(MCInst &Inst, unsigned Opcode,
4127 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4128 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004129 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004130 // Create a writeback register dummy placeholder.
4131 Inst.addOperand(MCOperand::CreateImm(0));
4132 // Vn
4133 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4134 // pred
4135 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4136 return true;
4137}
4138
4139bool ARMAsmParser::
4140cvtVLDwbRegister(MCInst &Inst, unsigned Opcode,
4141 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4142 // Vd
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004143 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach12431322011-10-24 22:16:58 +00004144 // Create a writeback register dummy placeholder.
4145 Inst.addOperand(MCOperand::CreateImm(0));
4146 // Vn
4147 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4148 // Vm
4149 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4150 // pred
4151 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4152 return true;
4153}
4154
Jim Grosbach4334e032011-10-31 21:50:31 +00004155bool ARMAsmParser::
4156cvtVSTwbFixed(MCInst &Inst, unsigned Opcode,
4157 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4158 // Create a writeback register dummy placeholder.
4159 Inst.addOperand(MCOperand::CreateImm(0));
4160 // Vn
4161 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4162 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004163 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004164 // pred
4165 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4166 return true;
4167}
4168
4169bool ARMAsmParser::
4170cvtVSTwbRegister(MCInst &Inst, unsigned Opcode,
4171 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
4172 // Create a writeback register dummy placeholder.
4173 Inst.addOperand(MCOperand::CreateImm(0));
4174 // Vn
4175 ((ARMOperand*)Operands[4])->addAlignedMemoryOperands(Inst, 2);
4176 // Vm
4177 ((ARMOperand*)Operands[5])->addRegOperands(Inst, 1);
4178 // Vt
Jim Grosbach6029b6d2011-11-29 23:51:09 +00004179 ((ARMOperand*)Operands[3])->addVecListOperands(Inst, 1);
Jim Grosbach4334e032011-10-31 21:50:31 +00004180 // pred
4181 ((ARMOperand*)Operands[1])->addCondCodeOperands(Inst, 2);
4182 return true;
4183}
4184
Bill Wendlinge7176102010-11-06 22:36:58 +00004185/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004186/// or an error. The first token must be a '[' when called.
Bill Wendling50d0f582010-11-18 23:43:05 +00004187bool ARMAsmParser::
Jim Grosbach7ce05792011-08-03 23:50:40 +00004188parseMemory(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Sean Callanan76264762010-04-02 22:27:05 +00004189 SMLoc S, E;
Sean Callanan18b83232010-01-19 21:44:56 +00004190 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendlinga60f1572010-11-06 10:48:18 +00004191 "Token is not a Left Bracket");
Sean Callanan76264762010-04-02 22:27:05 +00004192 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004193 Parser.Lex(); // Eat left bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004194
Sean Callanan18b83232010-01-19 21:44:56 +00004195 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbach1355cf12011-07-26 17:10:22 +00004196 int BaseRegNum = tryParseRegister();
Jim Grosbach7ce05792011-08-03 23:50:40 +00004197 if (BaseRegNum == -1)
4198 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004199
Daniel Dunbar05710932011-01-18 05:34:17 +00004200 // The next token must either be a comma or a closing bracket.
4201 const AsmToken &Tok = Parser.getTok();
4202 if (!Tok.is(AsmToken::Comma) && !Tok.is(AsmToken::RBrac))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004203 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar05710932011-01-18 05:34:17 +00004204
Jim Grosbach7ce05792011-08-03 23:50:40 +00004205 if (Tok.is(AsmToken::RBrac)) {
Sean Callanan76264762010-04-02 22:27:05 +00004206 E = Tok.getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004207 Parser.Lex(); // Eat right bracket token.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004208
Jim Grosbach7ce05792011-08-03 23:50:40 +00004209 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0, ARM_AM::no_shift,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004210 0, 0, false, S, E));
Jim Grosbach03f44a02010-11-29 23:18:01 +00004211
Jim Grosbachfb12f352011-09-19 18:42:21 +00004212 // If there's a pre-indexing writeback marker, '!', just add it as a token
4213 // operand. It's rather odd, but syntactically valid.
4214 if (Parser.getTok().is(AsmToken::Exclaim)) {
4215 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4216 Parser.Lex(); // Eat the '!'.
4217 }
4218
Jim Grosbach7ce05792011-08-03 23:50:40 +00004219 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004220 }
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004221
Jim Grosbach7ce05792011-08-03 23:50:40 +00004222 assert(Tok.is(AsmToken::Comma) && "Lost comma in memory operand?!");
4223 Parser.Lex(); // Eat the comma.
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004224
Jim Grosbach57dcb852011-10-11 17:29:55 +00004225 // If we have a ':', it's an alignment specifier.
4226 if (Parser.getTok().is(AsmToken::Colon)) {
4227 Parser.Lex(); // Eat the ':'.
4228 E = Parser.getTok().getLoc();
4229
4230 const MCExpr *Expr;
4231 if (getParser().ParseExpression(Expr))
4232 return true;
4233
4234 // The expression has to be a constant. Memory references with relocations
4235 // don't come through here, as they use the <label> forms of the relevant
4236 // instructions.
4237 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4238 if (!CE)
4239 return Error (E, "constant expression expected");
4240
4241 unsigned Align = 0;
4242 switch (CE->getValue()) {
4243 default:
Jim Grosbacheeaf1c12011-12-19 18:31:43 +00004244 return Error(E,
4245 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4246 case 16: Align = 2; break;
4247 case 32: Align = 4; break;
Jim Grosbach57dcb852011-10-11 17:29:55 +00004248 case 64: Align = 8; break;
4249 case 128: Align = 16; break;
4250 case 256: Align = 32; break;
4251 }
4252
4253 // Now we should have the closing ']'
4254 E = Parser.getTok().getLoc();
4255 if (Parser.getTok().isNot(AsmToken::RBrac))
4256 return Error(E, "']' expected");
4257 Parser.Lex(); // Eat right bracket token.
4258
4259 // Don't worry about range checking the value here. That's handled by
4260 // the is*() predicates.
4261 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, 0,
4262 ARM_AM::no_shift, 0, Align,
4263 false, S, E));
4264
4265 // If there's a pre-indexing writeback marker, '!', just add it as a token
4266 // operand.
4267 if (Parser.getTok().is(AsmToken::Exclaim)) {
4268 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4269 Parser.Lex(); // Eat the '!'.
4270 }
4271
4272 return false;
4273 }
4274
4275 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004276 // offset. Be friendly and also accept a plain integer (without a leading
4277 // hash) for gas compatibility.
4278 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004279 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004280 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004281 if (Parser.getTok().isNot(AsmToken::Integer))
Jim Grosbach6cb4b082011-11-15 22:14:41 +00004282 Parser.Lex(); // Eat the '#'.
Jim Grosbach7ce05792011-08-03 23:50:40 +00004283 E = Parser.getTok().getLoc();
Daniel Dunbar05d8b712011-01-18 05:34:24 +00004284
Owen Anderson0da10cf2011-08-29 19:36:44 +00004285 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbach7ce05792011-08-03 23:50:40 +00004286 const MCExpr *Offset;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004287 if (getParser().ParseExpression(Offset))
4288 return true;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004289
4290 // The expression has to be a constant. Memory references with relocations
4291 // don't come through here, as they use the <label> forms of the relevant
4292 // instructions.
4293 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4294 if (!CE)
4295 return Error (E, "constant expression expected");
4296
Owen Anderson0da10cf2011-08-29 19:36:44 +00004297 // If the constant was #-0, represent it as INT32_MIN.
4298 int32_t Val = CE->getValue();
4299 if (isNegative && Val == 0)
4300 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4301
Jim Grosbach7ce05792011-08-03 23:50:40 +00004302 // Now we should have the closing ']'
4303 E = Parser.getTok().getLoc();
4304 if (Parser.getTok().isNot(AsmToken::RBrac))
4305 return Error(E, "']' expected");
4306 Parser.Lex(); // Eat right bracket token.
4307
4308 // Don't worry about range checking the value here. That's handled by
4309 // the is*() predicates.
4310 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004311 ARM_AM::no_shift, 0, 0,
4312 false, S, E));
Jim Grosbach7ce05792011-08-03 23:50:40 +00004313
4314 // If there's a pre-indexing writeback marker, '!', just add it as a token
4315 // operand.
4316 if (Parser.getTok().is(AsmToken::Exclaim)) {
4317 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4318 Parser.Lex(); // Eat the '!'.
4319 }
4320
4321 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004322 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004323
4324 // The register offset is optionally preceded by a '+' or '-'
4325 bool isNegative = false;
4326 if (Parser.getTok().is(AsmToken::Minus)) {
4327 isNegative = true;
4328 Parser.Lex(); // Eat the '-'.
4329 } else if (Parser.getTok().is(AsmToken::Plus)) {
4330 // Nothing to do.
4331 Parser.Lex(); // Eat the '+'.
4332 }
4333
4334 E = Parser.getTok().getLoc();
4335 int OffsetRegNum = tryParseRegister();
4336 if (OffsetRegNum == -1)
4337 return Error(E, "register expected");
4338
4339 // If there's a shift operator, handle it.
4340 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004341 unsigned ShiftImm = 0;
Jim Grosbach7ce05792011-08-03 23:50:40 +00004342 if (Parser.getTok().is(AsmToken::Comma)) {
4343 Parser.Lex(); // Eat the ','.
Jim Grosbach0d6fac32011-08-05 22:03:36 +00004344 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004345 return true;
4346 }
4347
4348 // Now we should have the closing ']'
4349 E = Parser.getTok().getLoc();
4350 if (Parser.getTok().isNot(AsmToken::RBrac))
4351 return Error(E, "']' expected");
4352 Parser.Lex(); // Eat right bracket token.
4353
4354 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, 0, OffsetRegNum,
Jim Grosbach57dcb852011-10-11 17:29:55 +00004355 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbach7ce05792011-08-03 23:50:40 +00004356 S, E));
4357
Jim Grosbachf4fa3d62011-08-05 21:28:30 +00004358 // If there's a pre-indexing writeback marker, '!', just add it as a token
4359 // operand.
4360 if (Parser.getTok().is(AsmToken::Exclaim)) {
4361 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4362 Parser.Lex(); // Eat the '!'.
4363 }
Jim Grosbach7ce05792011-08-03 23:50:40 +00004364
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004365 return false;
4366}
4367
Jim Grosbach7ce05792011-08-03 23:50:40 +00004368/// parseMemRegOffsetShift - one of these two:
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004369/// ( lsl | lsr | asr | ror ) , # shift_amount
4370/// rrx
Jim Grosbach7ce05792011-08-03 23:50:40 +00004371/// return true if it parses a shift otherwise it returns false.
4372bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4373 unsigned &Amount) {
4374 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan18b83232010-01-19 21:44:56 +00004375 const AsmToken &Tok = Parser.getTok();
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004376 if (Tok.isNot(AsmToken::Identifier))
4377 return true;
Benjamin Kramer38e59892010-07-14 22:38:02 +00004378 StringRef ShiftName = Tok.getString();
Jim Grosbachaf4edea2011-12-07 23:40:58 +00004379 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4380 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson00828302011-03-18 22:50:18 +00004381 St = ARM_AM::lsl;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004382 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson00828302011-03-18 22:50:18 +00004383 St = ARM_AM::lsr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004384 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson00828302011-03-18 22:50:18 +00004385 St = ARM_AM::asr;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004386 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson00828302011-03-18 22:50:18 +00004387 St = ARM_AM::ror;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004388 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson00828302011-03-18 22:50:18 +00004389 St = ARM_AM::rrx;
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004390 else
Jim Grosbach7ce05792011-08-03 23:50:40 +00004391 return Error(Loc, "illegal shift operator");
Sean Callananb9a25b72010-01-19 20:27:46 +00004392 Parser.Lex(); // Eat shift type token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004393
Jim Grosbach7ce05792011-08-03 23:50:40 +00004394 // rrx stands alone.
4395 Amount = 0;
4396 if (St != ARM_AM::rrx) {
4397 Loc = Parser.getTok().getLoc();
4398 // A '#' and a shift amount.
4399 const AsmToken &HashTok = Parser.getTok();
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004400 if (HashTok.isNot(AsmToken::Hash) &&
4401 HashTok.isNot(AsmToken::Dollar))
Jim Grosbach7ce05792011-08-03 23:50:40 +00004402 return Error(HashTok.getLoc(), "'#' expected");
4403 Parser.Lex(); // Eat hash token.
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004404
Jim Grosbach7ce05792011-08-03 23:50:40 +00004405 const MCExpr *Expr;
4406 if (getParser().ParseExpression(Expr))
4407 return true;
4408 // Range check the immediate.
4409 // lsl, ror: 0 <= imm <= 31
4410 // lsr, asr: 0 <= imm <= 32
4411 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4412 if (!CE)
4413 return Error(Loc, "shift amount must be an immediate");
4414 int64_t Imm = CE->getValue();
4415 if (Imm < 0 ||
4416 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4417 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4418 return Error(Loc, "immediate shift value out of range");
4419 Amount = Imm;
4420 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004421
4422 return false;
4423}
4424
Jim Grosbach9d390362011-10-03 23:38:36 +00004425/// parseFPImm - A floating point immediate expression operand.
4426ARMAsmParser::OperandMatchResultTy ARMAsmParser::
4427parseFPImm(SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004428 // Anything that can accept a floating point constant as an operand
4429 // needs to go through here, as the regular ParseExpression is
4430 // integer only.
4431 //
4432 // This routine still creates a generic Immediate operand, containing
4433 // a bitcast of the 64-bit floating point value. The various operands
4434 // that accept floats can check whether the value is valid for them
4435 // via the standard is*() predicates.
4436
Jim Grosbach9d390362011-10-03 23:38:36 +00004437 SMLoc S = Parser.getTok().getLoc();
4438
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004439 if (Parser.getTok().isNot(AsmToken::Hash) &&
4440 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbach9d390362011-10-03 23:38:36 +00004441 return MatchOperand_NoMatch;
Jim Grosbach0e387b22011-10-17 22:26:03 +00004442
4443 // Disambiguate the VMOV forms that can accept an FP immediate.
4444 // vmov.f32 <sreg>, #imm
4445 // vmov.f64 <dreg>, #imm
4446 // vmov.f32 <dreg>, #imm @ vector f32x2
4447 // vmov.f32 <qreg>, #imm @ vector f32x4
4448 //
4449 // There are also the NEON VMOV instructions which expect an
4450 // integer constant. Make sure we don't try to parse an FPImm
4451 // for these:
4452 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
4453 ARMOperand *TyOp = static_cast<ARMOperand*>(Operands[2]);
4454 if (!TyOp->isToken() || (TyOp->getToken() != ".f32" &&
4455 TyOp->getToken() != ".f64"))
4456 return MatchOperand_NoMatch;
4457
Jim Grosbach9d390362011-10-03 23:38:36 +00004458 Parser.Lex(); // Eat the '#'.
4459
4460 // Handle negation, as that still comes through as a separate token.
4461 bool isNegative = false;
4462 if (Parser.getTok().is(AsmToken::Minus)) {
4463 isNegative = true;
4464 Parser.Lex();
4465 }
4466 const AsmToken &Tok = Parser.getTok();
Jim Grosbachae69f702012-01-19 02:47:30 +00004467 SMLoc Loc = Tok.getLoc();
Jim Grosbach9d390362011-10-03 23:38:36 +00004468 if (Tok.is(AsmToken::Real)) {
Jim Grosbach51222d12012-01-20 18:09:51 +00004469 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbach9d390362011-10-03 23:38:36 +00004470 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4471 // If we had a '-' in front, toggle the sign bit.
Jim Grosbach51222d12012-01-20 18:09:51 +00004472 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbach9d390362011-10-03 23:38:36 +00004473 Parser.Lex(); // Eat the token.
Jim Grosbach51222d12012-01-20 18:09:51 +00004474 Operands.push_back(ARMOperand::CreateImm(
4475 MCConstantExpr::Create(IntVal, getContext()),
4476 S, Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004477 return MatchOperand_Success;
4478 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004479 // Also handle plain integers. Instructions which allow floating point
4480 // immediates also allow a raw encoded 8-bit value.
Jim Grosbach9d390362011-10-03 23:38:36 +00004481 if (Tok.is(AsmToken::Integer)) {
4482 int64_t Val = Tok.getIntVal();
4483 Parser.Lex(); // Eat the token.
4484 if (Val > 255 || Val < 0) {
Jim Grosbachae69f702012-01-19 02:47:30 +00004485 Error(Loc, "encoded floating point value out of range");
Jim Grosbach9d390362011-10-03 23:38:36 +00004486 return MatchOperand_ParseFail;
4487 }
Jim Grosbach51222d12012-01-20 18:09:51 +00004488 double RealVal = ARM_AM::getFPImmFloat(Val);
4489 Val = APFloat(APFloat::IEEEdouble, RealVal).bitcastToAPInt().getZExtValue();
4490 Operands.push_back(ARMOperand::CreateImm(
4491 MCConstantExpr::Create(Val, getContext()), S,
4492 Parser.getTok().getLoc()));
Jim Grosbach9d390362011-10-03 23:38:36 +00004493 return MatchOperand_Success;
4494 }
4495
Jim Grosbachae69f702012-01-19 02:47:30 +00004496 Error(Loc, "invalid floating point immediate");
Jim Grosbach9d390362011-10-03 23:38:36 +00004497 return MatchOperand_ParseFail;
4498}
Jim Grosbach51222d12012-01-20 18:09:51 +00004499
Kevin Enderby9c41fa82009-10-30 22:55:57 +00004500/// Parse a arm instruction operand. For now this parses the operand regardless
4501/// of the mnemonic.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004502bool ARMAsmParser::parseOperand(SmallVectorImpl<MCParsedAsmOperand*> &Operands,
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004503 StringRef Mnemonic) {
Sean Callanan76264762010-04-02 22:27:05 +00004504 SMLoc S, E;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004505
4506 // Check if the current operand has a custom associated parser, if so, try to
4507 // custom parse the operand, or fallback to the general approach.
Jim Grosbachf922c472011-02-12 01:34:40 +00004508 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4509 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004510 return false;
Jim Grosbachf922c472011-02-12 01:34:40 +00004511 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4512 // there was a match, but an error occurred, in which case, just return that
4513 // the operand parsing failed.
4514 if (ResTy == MatchOperand_ParseFail)
4515 return true;
Bruno Cardoso Lopesfafde7f2011-02-07 21:41:25 +00004516
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004517 switch (getLexer().getKind()) {
Bill Wendling146018f2010-11-06 21:42:12 +00004518 default:
4519 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling50d0f582010-11-18 23:43:05 +00004520 return true;
Jim Grosbach19906722011-07-13 18:49:30 +00004521 case AsmToken::Identifier: {
Jim Grosbach1355cf12011-07-26 17:10:22 +00004522 if (!tryParseRegisterWithWriteBack(Operands))
Bill Wendling50d0f582010-11-18 23:43:05 +00004523 return false;
Jim Grosbach0d87ec22011-07-26 20:41:24 +00004524 int Res = tryParseShiftRegister(Operands);
Jim Grosbach19906722011-07-13 18:49:30 +00004525 if (Res == 0) // success
Owen Anderson00828302011-03-18 22:50:18 +00004526 return false;
Jim Grosbach19906722011-07-13 18:49:30 +00004527 else if (Res == -1) // irrecoverable error
4528 return true;
Jim Grosbach3cbe43f2011-12-20 22:26:38 +00004529 // If this is VMRS, check for the apsr_nzcv operand.
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004530 if (Mnemonic == "vmrs" &&
4531 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004532 S = Parser.getTok().getLoc();
4533 Parser.Lex();
Jim Grosbachb84ad4a2012-03-15 21:34:14 +00004534 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
Jim Grosbach5cd5ac62011-10-03 21:12:43 +00004535 return false;
4536 }
Owen Andersone4e5e2a2011-01-13 21:46:02 +00004537
4538 // Fall though for the Identifier case that is not a register or a
4539 // special name.
Jim Grosbach19906722011-07-13 18:49:30 +00004540 }
Jim Grosbach758a5192011-10-26 21:14:08 +00004541 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderby67b212e2011-01-13 20:32:36 +00004542 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach6284afc2011-11-01 22:38:31 +00004543 case AsmToken::String: // quoted label names.
Kevin Enderby67b212e2011-01-13 20:32:36 +00004544 case AsmToken::Dot: { // . as a branch target
Kevin Enderby515d5092009-10-15 20:48:48 +00004545 // This was not a register so parse other operands that start with an
4546 // identifier (like labels) as expressions and create them as immediates.
4547 const MCExpr *IdVal;
Sean Callanan76264762010-04-02 22:27:05 +00004548 S = Parser.getTok().getLoc();
Kevin Enderby515d5092009-10-15 20:48:48 +00004549 if (getParser().ParseExpression(IdVal))
Bill Wendling50d0f582010-11-18 23:43:05 +00004550 return true;
Sean Callanan76264762010-04-02 22:27:05 +00004551 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling50d0f582010-11-18 23:43:05 +00004552 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4553 return false;
4554 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004555 case AsmToken::LBrac:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004556 return parseMemory(Operands);
Kevin Enderbyd7894f12009-10-09 21:12:28 +00004557 case AsmToken::LCurly:
Jim Grosbach1355cf12011-07-26 17:10:22 +00004558 return parseRegisterList(Operands);
Jim Grosbach8a12e3b2011-12-09 22:25:03 +00004559 case AsmToken::Dollar:
Owen Anderson63553c72011-08-29 17:17:09 +00004560 case AsmToken::Hash: {
Kevin Enderby079469f2009-10-13 23:33:38 +00004561 // #42 -> immediate.
Sean Callanan76264762010-04-02 22:27:05 +00004562 S = Parser.getTok().getLoc();
Sean Callananb9a25b72010-01-19 20:27:46 +00004563 Parser.Lex();
Jim Grosbachb8768dc2012-04-16 21:18:46 +00004564
4565 if (Parser.getTok().isNot(AsmToken::Colon)) {
4566 bool isNegative = Parser.getTok().is(AsmToken::Minus);
4567 const MCExpr *ImmVal;
4568 if (getParser().ParseExpression(ImmVal))
4569 return true;
4570 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
4571 if (CE) {
4572 int32_t Val = CE->getValue();
4573 if (isNegative && Val == 0)
4574 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
4575 }
4576 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
4577 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
4578 return false;
Owen Anderson63553c72011-08-29 17:17:09 +00004579 }
Jim Grosbachb8768dc2012-04-16 21:18:46 +00004580 // w/ a ':' after the '#', it's just like a plain ':'.
4581 // FALLTHROUGH
Owen Anderson63553c72011-08-29 17:17:09 +00004582 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004583 case AsmToken::Colon: {
4584 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng75972122011-01-13 07:58:56 +00004585 // FIXME: Check it's an expression prefix,
4586 // e.g. (FOO - :lower16:BAR) isn't legal.
4587 ARMMCExpr::VariantKind RefKind;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004588 if (parsePrefix(RefKind))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004589 return true;
4590
Evan Cheng75972122011-01-13 07:58:56 +00004591 const MCExpr *SubExprVal;
4592 if (getParser().ParseExpression(SubExprVal))
Jason W Kim9081b4b2011-01-11 23:53:41 +00004593 return true;
4594
Evan Cheng75972122011-01-13 07:58:56 +00004595 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
4596 getContext());
Jason W Kim9081b4b2011-01-11 23:53:41 +00004597 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng75972122011-01-13 07:58:56 +00004598 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim9081b4b2011-01-11 23:53:41 +00004599 return false;
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00004600 }
Jason W Kim9081b4b2011-01-11 23:53:41 +00004601 }
4602}
4603
Jim Grosbach1355cf12011-07-26 17:10:22 +00004604// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng75972122011-01-13 07:58:56 +00004605// :lower16: and :upper16:.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004606bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng75972122011-01-13 07:58:56 +00004607 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004608
4609 // :lower16: and :upper16: modifiers
Jason W Kim8a8696d2011-01-13 00:27:00 +00004610 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim9081b4b2011-01-11 23:53:41 +00004611 Parser.Lex(); // Eat ':'
4612
4613 if (getLexer().isNot(AsmToken::Identifier)) {
4614 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
4615 return true;
4616 }
4617
4618 StringRef IDVal = Parser.getTok().getIdentifier();
4619 if (IDVal == "lower16") {
Evan Cheng75972122011-01-13 07:58:56 +00004620 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004621 } else if (IDVal == "upper16") {
Evan Cheng75972122011-01-13 07:58:56 +00004622 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim9081b4b2011-01-11 23:53:41 +00004623 } else {
4624 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
4625 return true;
4626 }
4627 Parser.Lex();
4628
4629 if (getLexer().isNot(AsmToken::Colon)) {
4630 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
4631 return true;
4632 }
4633 Parser.Lex(); // Eat the last ':'
4634 return false;
4635}
4636
Daniel Dunbar352e1482011-01-11 15:59:50 +00004637/// \brief Given a mnemonic, split out possible predication code and carry
4638/// setting letters to form a canonical mnemonic and flags.
4639//
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004640// FIXME: Would be nice to autogen this.
Jim Grosbach89df9962011-08-26 21:43:41 +00004641// FIXME: This is a bit of a maze of special cases.
Jim Grosbach1355cf12011-07-26 17:10:22 +00004642StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5f160572011-07-19 20:10:31 +00004643 unsigned &PredicationCode,
4644 bool &CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004645 unsigned &ProcessorIMod,
4646 StringRef &ITMask) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004647 PredicationCode = ARMCC::AL;
4648 CarrySetting = false;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004649 ProcessorIMod = 0;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004650
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004651 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar352e1482011-01-11 15:59:50 +00004652 //
4653 // FIXME: Would be nice to autogen this.
Jim Grosbach5f160572011-07-19 20:10:31 +00004654 if ((Mnemonic == "movs" && isThumb()) ||
4655 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
4656 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
4657 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
4658 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
4659 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
4660 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbach68490192011-12-19 19:43:50 +00004661 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
4662 Mnemonic == "fmuls")
Daniel Dunbar352e1482011-01-11 15:59:50 +00004663 return Mnemonic;
Daniel Dunbar5747b132010-08-11 06:37:16 +00004664
Jim Grosbach3f00e312011-07-11 17:09:57 +00004665 // First, split out any predication code. Ignore mnemonics we know aren't
4666 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbachab40f4b2011-07-20 18:20:31 +00004667 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach71725a02011-07-27 21:58:11 +00004668 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach04d55f12011-08-22 23:55:58 +00004669 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbach2f25d9b2011-09-01 18:22:13 +00004670 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbach3f00e312011-07-11 17:09:57 +00004671 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
4672 .Case("eq", ARMCC::EQ)
4673 .Case("ne", ARMCC::NE)
4674 .Case("hs", ARMCC::HS)
4675 .Case("cs", ARMCC::HS)
4676 .Case("lo", ARMCC::LO)
4677 .Case("cc", ARMCC::LO)
4678 .Case("mi", ARMCC::MI)
4679 .Case("pl", ARMCC::PL)
4680 .Case("vs", ARMCC::VS)
4681 .Case("vc", ARMCC::VC)
4682 .Case("hi", ARMCC::HI)
4683 .Case("ls", ARMCC::LS)
4684 .Case("ge", ARMCC::GE)
4685 .Case("lt", ARMCC::LT)
4686 .Case("gt", ARMCC::GT)
4687 .Case("le", ARMCC::LE)
4688 .Case("al", ARMCC::AL)
4689 .Default(~0U);
4690 if (CC != ~0U) {
4691 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
4692 PredicationCode = CC;
4693 }
Bill Wendling52925b62010-10-29 23:50:21 +00004694 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00004695
Daniel Dunbar352e1482011-01-11 15:59:50 +00004696 // Next, determine if we have a carry setting bit. We explicitly ignore all
4697 // the instructions we know end in 's'.
4698 if (Mnemonic.endswith("s") &&
Jim Grosbach00f5d982011-08-17 22:49:09 +00004699 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5f160572011-07-19 20:10:31 +00004700 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
4701 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
4702 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach67ca1ad2011-12-08 00:49:29 +00004703 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach48171e72011-12-10 00:01:02 +00004704 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach9c397892011-12-19 19:02:41 +00004705 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbach6357cae2012-03-15 20:48:18 +00004706 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004707 Mnemonic == "vfms" || Mnemonic == "vfnms" ||
Jim Grosbache1cf5902011-07-29 20:26:09 +00004708 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar352e1482011-01-11 15:59:50 +00004709 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
4710 CarrySetting = true;
4711 }
4712
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004713 // The "cps" instruction can have a interrupt mode operand which is glued into
4714 // the mnemonic. Check if this is the case, split it and parse the imod op
4715 if (Mnemonic.startswith("cps")) {
4716 // Split out any imod code.
4717 unsigned IMod =
4718 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
4719 .Case("ie", ARM_PROC::IE)
4720 .Case("id", ARM_PROC::ID)
4721 .Default(~0U);
4722 if (IMod != ~0U) {
4723 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
4724 ProcessorIMod = IMod;
4725 }
4726 }
4727
Jim Grosbach89df9962011-08-26 21:43:41 +00004728 // The "it" instruction has the condition mask on the end of the mnemonic.
4729 if (Mnemonic.startswith("it")) {
4730 ITMask = Mnemonic.slice(2, Mnemonic.size());
4731 Mnemonic = Mnemonic.slice(0, 2);
4732 }
4733
Daniel Dunbar352e1482011-01-11 15:59:50 +00004734 return Mnemonic;
4735}
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004736
4737/// \brief Given a canonical mnemonic, determine if the instruction ever allows
4738/// inclusion of carry set or predication code operands.
4739//
4740// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004741void ARMAsmParser::
Jim Grosbach1355cf12011-07-26 17:10:22 +00004742getMnemonicAcceptInfo(StringRef Mnemonic, bool &CanAcceptCarrySet,
Bruno Cardoso Lopesfdcee772011-01-18 20:55:11 +00004743 bool &CanAcceptPredicationCode) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004744 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
4745 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004746 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004747 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004748 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004749 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004750 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Evan Cheng82509e52012-04-11 00:13:00 +00004751 Mnemonic == "vfm" || Mnemonic == "vfnm" ||
Jim Grosbach3443ed52011-09-16 18:05:48 +00004752 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachd5d0e812011-09-19 23:31:02 +00004753 Mnemonic == "mla" || Mnemonic == "smlal" ||
4754 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004755 CanAcceptCarrySet = true;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004756 } else
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004757 CanAcceptCarrySet = false;
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004758
Daniel Dunbareb9f3f92011-01-11 19:06:29 +00004759 if (Mnemonic == "cbnz" || Mnemonic == "setend" || Mnemonic == "dmb" ||
4760 Mnemonic == "cps" || Mnemonic == "mcr2" || Mnemonic == "it" ||
4761 Mnemonic == "mcrr2" || Mnemonic == "cbz" || Mnemonic == "cdp2" ||
4762 Mnemonic == "trap" || Mnemonic == "mrc2" || Mnemonic == "mrrc2" ||
Jim Grosbachad2dad92011-09-06 20:27:04 +00004763 Mnemonic == "dsb" || Mnemonic == "isb" || Mnemonic == "setend" ||
4764 (Mnemonic == "clrex" && !isThumb()) ||
Jim Grosbach0780b632011-08-19 23:24:36 +00004765 (Mnemonic == "nop" && isThumbOne()) ||
Jim Grosbach2bd01182011-10-11 21:55:36 +00004766 ((Mnemonic == "pld" || Mnemonic == "pli" || Mnemonic == "pldw" ||
4767 Mnemonic == "ldc2" || Mnemonic == "ldc2l" ||
4768 Mnemonic == "stc2" || Mnemonic == "stc2l") && !isThumb()) ||
Jim Grosbach4af54a42011-08-26 22:21:51 +00004769 ((Mnemonic.startswith("rfe") || Mnemonic.startswith("srs")) &&
4770 !isThumb()) ||
Jim Grosbach1ad60c22011-09-10 00:15:36 +00004771 Mnemonic.startswith("cps") || (Mnemonic == "movs" && isThumbOne())) {
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004772 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004773 } else
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004774 CanAcceptPredicationCode = true;
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004775
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004776 if (isThumb()) {
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004777 if (Mnemonic == "bkpt" || Mnemonic == "mcr" || Mnemonic == "mcrr" ||
Jim Grosbach63b46fa2011-06-30 22:10:46 +00004778 Mnemonic == "mrc" || Mnemonic == "mrrc" || Mnemonic == "cdp")
Bruno Cardoso Lopesfa5bd272011-01-20 16:35:57 +00004779 CanAcceptPredicationCode = false;
Jim Grosbachfb9cffe2011-09-16 16:39:25 +00004780 }
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004781}
4782
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004783bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
4784 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004785 // FIXME: This is all horribly hacky. We really need a better way to deal
4786 // with optional operands like this in the matcher table.
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004787
4788 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
4789 // another does not. Specifically, the MOVW instruction does not. So we
4790 // special case it here and remove the defaulted (non-setting) cc_out
4791 // operand if that's the instruction we're trying to match.
4792 //
4793 // We do this as post-processing of the explicit operands rather than just
4794 // conditionally adding the cc_out in the first place because we need
4795 // to check the type of the parsed immediate operand.
Owen Anderson8adf6202011-09-14 22:46:14 +00004796 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004797 !static_cast<ARMOperand*>(Operands[4])->isARMSOImm() &&
4798 static_cast<ARMOperand*>(Operands[4])->isImm0_65535Expr() &&
4799 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4800 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004801
4802 // Register-register 'add' for thumb does not have a cc_out operand
4803 // when there are only two register operands.
4804 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
4805 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4806 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4807 static_cast<ARMOperand*>(Operands[1])->getReg() == 0)
4808 return true;
Jim Grosbach72f39f82011-08-24 21:22:15 +00004809 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004810 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
4811 // have to check the immediate range here since Thumb2 has a variant
4812 // that can handle a different range and has a cc_out operand.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004813 if (((isThumb() && Mnemonic == "add") ||
4814 (isThumbTwo() && Mnemonic == "sub")) &&
4815 Operands.size() == 6 &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004816 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4817 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4818 static_cast<ARMOperand*>(Operands[4])->getReg() == ARM::SP &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004819 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004820 ((Mnemonic == "add" &&static_cast<ARMOperand*>(Operands[5])->isReg()) ||
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004821 static_cast<ARMOperand*>(Operands[5])->isImm0_1020s4()))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004822 return true;
Jim Grosbachf67e8552011-09-16 22:58:42 +00004823 // For Thumb2, add/sub immediate does not have a cc_out operand for the
4824 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004825 // selecting via the generic "add" mnemonic, so to know that we
4826 // should remove the cc_out operand, we have to explicitly check that
4827 // it's not one of the other variants. Ugh.
Jim Grosbachf67e8552011-09-16 22:58:42 +00004828 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
4829 Operands.size() == 6 &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004830 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4831 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4832 static_cast<ARMOperand*>(Operands[5])->isImm()) {
4833 // Nest conditions rather than one big 'if' statement for readability.
4834 //
4835 // If either register is a high reg, it's either one of the SP
4836 // variants (handled above) or a 32-bit encoding, so we just
Jim Grosbach12a88632012-01-21 00:07:56 +00004837 // check against T3. If the second register is the PC, this is an
4838 // alternate form of ADR, which uses encoding T4, so check for that too.
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004839 if ((!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4840 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg())) &&
Jim Grosbach12a88632012-01-21 00:07:56 +00004841 static_cast<ARMOperand*>(Operands[4])->getReg() != ARM::PC &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004842 static_cast<ARMOperand*>(Operands[5])->isT2SOImm())
4843 return false;
4844 // If both registers are low, we're in an IT block, and the immediate is
4845 // in range, we should use encoding T1 instead, which has a cc_out.
4846 if (inITBlock() &&
Jim Grosbach64944f42011-09-14 21:00:40 +00004847 isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004848 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) &&
4849 static_cast<ARMOperand*>(Operands[5])->isImm0_7())
4850 return false;
4851
4852 // Otherwise, we use encoding T4, which does not have a cc_out
4853 // operand.
4854 return true;
4855 }
4856
Jim Grosbach64944f42011-09-14 21:00:40 +00004857 // The thumb2 multiply instruction doesn't have a CCOut register, so
4858 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
4859 // use the 16-bit encoding or not.
4860 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
4861 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4862 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4863 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4864 static_cast<ARMOperand*>(Operands[5])->isReg() &&
4865 // If the registers aren't low regs, the destination reg isn't the
4866 // same as one of the source regs, or the cc_out operand is zero
4867 // outside of an IT block, we have to use the 32-bit encoding, so
4868 // remove the cc_out operand.
4869 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4870 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
Jim Grosbach1de0bd12011-11-15 19:29:45 +00004871 !isARMLowRegister(static_cast<ARMOperand*>(Operands[5])->getReg()) ||
Jim Grosbach64944f42011-09-14 21:00:40 +00004872 !inITBlock() ||
4873 (static_cast<ARMOperand*>(Operands[3])->getReg() !=
4874 static_cast<ARMOperand*>(Operands[5])->getReg() &&
4875 static_cast<ARMOperand*>(Operands[3])->getReg() !=
4876 static_cast<ARMOperand*>(Operands[4])->getReg())))
4877 return true;
4878
Jim Grosbach7f1ec952011-11-15 19:55:16 +00004879 // Also check the 'mul' syntax variant that doesn't specify an explicit
4880 // destination register.
4881 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
4882 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4883 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4884 static_cast<ARMOperand*>(Operands[4])->isReg() &&
4885 // If the registers aren't low regs or the cc_out operand is zero
4886 // outside of an IT block, we have to use the 32-bit encoding, so
4887 // remove the cc_out operand.
4888 (!isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) ||
4889 !isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()) ||
4890 !inITBlock()))
4891 return true;
4892
Jim Grosbach64944f42011-09-14 21:00:40 +00004893
Jim Grosbach20ed2e72011-09-01 00:28:52 +00004894
Jim Grosbachf69c8042011-08-24 21:42:27 +00004895 // Register-register 'add/sub' for thumb does not have a cc_out operand
4896 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
4897 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
4898 // right, this will result in better diagnostics (which operand is off)
4899 // anyway.
4900 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
4901 (Operands.size() == 5 || Operands.size() == 6) &&
Jim Grosbach72f39f82011-08-24 21:22:15 +00004902 static_cast<ARMOperand*>(Operands[3])->isReg() &&
4903 static_cast<ARMOperand*>(Operands[3])->getReg() == ARM::SP &&
Jim Grosbacha23ecc22012-04-10 17:31:55 +00004904 static_cast<ARMOperand*>(Operands[1])->getReg() == 0 &&
4905 (static_cast<ARMOperand*>(Operands[4])->isImm() ||
4906 (Operands.size() == 6 &&
4907 static_cast<ARMOperand*>(Operands[5])->isImm())))
Jim Grosbach72f39f82011-08-24 21:22:15 +00004908 return true;
Jim Grosbach3912b732011-08-16 21:34:08 +00004909
Jim Grosbachd54b4e62011-08-16 21:12:37 +00004910 return false;
4911}
4912
Jim Grosbach7aef99b2011-11-11 23:08:10 +00004913static bool isDataTypeToken(StringRef Tok) {
4914 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
4915 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
4916 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
4917 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
4918 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
4919 Tok == ".f" || Tok == ".d";
4920}
4921
4922// FIXME: This bit should probably be handled via an explicit match class
4923// in the .td files that matches the suffix instead of having it be
4924// a literal string token the way it is now.
4925static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
4926 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
4927}
4928
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004929static void applyMnemonicAliases(StringRef &Mnemonic, unsigned Features);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004930/// Parse an arm instruction mnemonic followed by its operands.
4931bool ARMAsmParser::ParseInstruction(StringRef Name, SMLoc NameLoc,
4932 SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Jim Grosbach21d7fb82011-12-09 23:34:09 +00004933 // Apply mnemonic aliases before doing anything else, as the destination
4934 // mnemnonic may include suffices and we want to handle them normally.
4935 // The generic tblgen'erated code does this later, at the start of
4936 // MatchInstructionImpl(), but that's too late for aliases that include
4937 // any sort of suffix.
4938 unsigned AvailableFeatures = getAvailableFeatures();
4939 applyMnemonicAliases(Name, AvailableFeatures);
4940
Jim Grosbacha39cda72011-12-14 02:16:11 +00004941 // First check for the ARM-specific .req directive.
4942 if (Parser.getTok().is(AsmToken::Identifier) &&
4943 Parser.getTok().getIdentifier() == ".req") {
4944 parseDirectiveReq(Name, NameLoc);
4945 // We always return 'error' for this, as we're done with this
4946 // statement and don't need to match the 'instruction."
4947 return true;
4948 }
4949
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004950 // Create the leading tokens for the mnemonic, split by '.' characters.
4951 size_t Start = 0, Next = Name.find('.');
Jim Grosbachffa32252011-07-19 19:13:28 +00004952 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004953
Daniel Dunbar352e1482011-01-11 15:59:50 +00004954 // Split out the predication code and carry setting flag from the mnemonic.
4955 unsigned PredicationCode;
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00004956 unsigned ProcessorIMod;
Daniel Dunbar352e1482011-01-11 15:59:50 +00004957 bool CarrySetting;
Jim Grosbach89df9962011-08-26 21:43:41 +00004958 StringRef ITMask;
Jim Grosbach1355cf12011-07-26 17:10:22 +00004959 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach89df9962011-08-26 21:43:41 +00004960 ProcessorIMod, ITMask);
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00004961
Jim Grosbach0c49ac02011-08-25 17:23:55 +00004962 // In Thumb1, only the branch (B) instruction can be predicated.
4963 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
4964 Parser.EatToEndOfStatement();
4965 return Error(NameLoc, "conditional execution not supported in Thumb1");
4966 }
4967
Jim Grosbachffa32252011-07-19 19:13:28 +00004968 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
4969
Jim Grosbach89df9962011-08-26 21:43:41 +00004970 // Handle the IT instruction ITMask. Convert it to a bitmask. This
4971 // is the mask as it will be for the IT encoding if the conditional
4972 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
4973 // where the conditional bit0 is zero, the instruction post-processing
4974 // will adjust the mask accordingly.
4975 if (Mnemonic == "it") {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004976 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
4977 if (ITMask.size() > 3) {
4978 Parser.EatToEndOfStatement();
4979 return Error(Loc, "too many conditions on IT instruction");
4980 }
Jim Grosbach89df9962011-08-26 21:43:41 +00004981 unsigned Mask = 8;
4982 for (unsigned i = ITMask.size(); i != 0; --i) {
4983 char pos = ITMask[i - 1];
4984 if (pos != 't' && pos != 'e') {
4985 Parser.EatToEndOfStatement();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004986 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach89df9962011-08-26 21:43:41 +00004987 }
4988 Mask >>= 1;
4989 if (ITMask[i - 1] == 't')
4990 Mask |= 8;
4991 }
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00004992 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach89df9962011-08-26 21:43:41 +00004993 }
4994
Jim Grosbachffa32252011-07-19 19:13:28 +00004995 // FIXME: This is all a pretty gross hack. We should automatically handle
4996 // optional operands like this via tblgen.
Bill Wendling9717fa92010-11-21 10:56:05 +00004997
Daniel Dunbar3771dd02011-01-11 15:59:53 +00004998 // Next, add the CCOut and ConditionCode operands, if needed.
4999 //
5000 // For mnemonics which can ever incorporate a carry setting bit or predication
5001 // code, our matching model involves us always generating CCOut and
5002 // ConditionCode operands to match the mnemonic "as written" and then we let
5003 // the matcher deal with finding the right instruction or generating an
5004 // appropriate error.
5005 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Jim Grosbach1355cf12011-07-26 17:10:22 +00005006 getMnemonicAcceptInfo(Mnemonic, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005007
Jim Grosbach33c16a22011-07-14 22:04:21 +00005008 // If we had a carry-set on an instruction that can't do that, issue an
5009 // error.
5010 if (!CanAcceptCarrySet && CarrySetting) {
5011 Parser.EatToEndOfStatement();
Jim Grosbachffa32252011-07-19 19:13:28 +00005012 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach33c16a22011-07-14 22:04:21 +00005013 "' can not set flags, but 's' suffix specified");
5014 }
Jim Grosbachc27d4f92011-07-22 17:44:50 +00005015 // If we had a predication code on an instruction that can't do that, issue an
5016 // error.
5017 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
5018 Parser.EatToEndOfStatement();
5019 return Error(NameLoc, "instruction '" + Mnemonic +
5020 "' is not predicable, but condition code specified");
5021 }
Jim Grosbach33c16a22011-07-14 22:04:21 +00005022
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005023 // Add the carry setting operand, if necessary.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005024 if (CanAcceptCarrySet) {
5025 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005026 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005027 Loc));
5028 }
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005029
5030 // Add the predication code operand, if necessary.
5031 if (CanAcceptPredicationCode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005032 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
5033 CarrySetting);
Daniel Dunbar3771dd02011-01-11 15:59:53 +00005034 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005035 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbarbadbd2f2011-01-10 12:24:52 +00005036 }
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005037
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005038 // Add the processor imod operand, if necessary.
5039 if (ProcessorIMod) {
5040 Operands.push_back(ARMOperand::CreateImm(
5041 MCConstantExpr::Create(ProcessorIMod, getContext()),
5042 NameLoc, NameLoc));
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005043 }
5044
Daniel Dunbar345a9a62010-08-11 06:37:20 +00005045 // Add the remaining tokens in the mnemonic.
Daniel Dunbar5747b132010-08-11 06:37:16 +00005046 while (Next != StringRef::npos) {
5047 Start = Next;
5048 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopesa2b6e412011-02-14 13:09:44 +00005049 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005050
Jim Grosbach7aef99b2011-11-11 23:08:10 +00005051 // Some NEON instructions have an optional datatype suffix that is
5052 // completely ignored. Check for that.
5053 if (isDataTypeToken(ExtraToken) &&
5054 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
5055 continue;
5056
Jim Grosbach81d2e392011-09-07 16:06:04 +00005057 if (ExtraToken != ".n") {
5058 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5059 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
5060 }
Daniel Dunbar5747b132010-08-11 06:37:16 +00005061 }
5062
5063 // Read the remaining operands.
5064 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005065 // Read the first operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005066 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005067 Parser.EatToEndOfStatement();
5068 return true;
5069 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005070
5071 while (getLexer().is(AsmToken::Comma)) {
Sean Callananb9a25b72010-01-19 20:27:46 +00005072 Parser.Lex(); // Eat the comma.
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005073
5074 // Parse and remember the operand.
Jim Grosbach1355cf12011-07-26 17:10:22 +00005075 if (parseOperand(Operands, Mnemonic)) {
Chris Lattnercbf8a982010-09-11 16:18:25 +00005076 Parser.EatToEndOfStatement();
5077 return true;
5078 }
Kevin Enderbya7ba3a82009-10-06 22:26:42 +00005079 }
5080 }
Jim Grosbach16c74252010-10-29 14:46:02 +00005081
Chris Lattnercbf8a982010-09-11 16:18:25 +00005082 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbach186ffac2011-10-07 18:27:04 +00005083 SMLoc Loc = getLexer().getLoc();
Chris Lattnercbf8a982010-09-11 16:18:25 +00005084 Parser.EatToEndOfStatement();
Jim Grosbach186ffac2011-10-07 18:27:04 +00005085 return Error(Loc, "unexpected token in argument list");
Chris Lattnercbf8a982010-09-11 16:18:25 +00005086 }
Bill Wendling146018f2010-11-06 21:42:12 +00005087
Chris Lattner34e53142010-09-08 05:10:46 +00005088 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbachffa32252011-07-19 19:13:28 +00005089
Jim Grosbachd54b4e62011-08-16 21:12:37 +00005090 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5091 // do and don't have a cc_out optional-def operand. With some spot-checks
5092 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach20ed2e72011-09-01 00:28:52 +00005093 // parse and adjust accordingly before actually matching. We shouldn't ever
5094 // try to remove a cc_out operand that was explicitly set on the the
5095 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5096 // table driven matcher doesn't fit well with the ARM instruction set.
5097 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands)) {
Jim Grosbachffa32252011-07-19 19:13:28 +00005098 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5099 Operands.erase(Operands.begin() + 1);
5100 delete Op;
5101 }
5102
Jim Grosbachcf121c32011-07-28 21:57:55 +00005103 // ARM mode 'blx' need special handling, as the register operand version
5104 // is predicable, but the label operand version is not. So, we can't rely
5105 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach21ff17c2011-10-07 23:24:09 +00005106 // a k_CondCode operand in the list. If we're trying to match the label
5107 // version, remove the k_CondCode operand here.
Jim Grosbachcf121c32011-07-28 21:57:55 +00005108 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
5109 static_cast<ARMOperand*>(Operands[2])->isImm()) {
5110 ARMOperand *Op = static_cast<ARMOperand*>(Operands[1]);
5111 Operands.erase(Operands.begin() + 1);
5112 delete Op;
5113 }
Jim Grosbach857e1a72011-08-11 23:51:13 +00005114
5115 // The vector-compare-to-zero instructions have a literal token "#0" at
5116 // the end that comes to here as an immediate operand. Convert it to a
5117 // token to play nicely with the matcher.
5118 if ((Mnemonic == "vceq" || Mnemonic == "vcge" || Mnemonic == "vcgt" ||
5119 Mnemonic == "vcle" || Mnemonic == "vclt") && Operands.size() == 6 &&
5120 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5121 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5122 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5123 if (CE && CE->getValue() == 0) {
5124 Operands.erase(Operands.begin() + 5);
5125 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5126 delete Op;
5127 }
5128 }
Jim Grosbach68259142011-10-03 22:30:24 +00005129 // VCMP{E} does the same thing, but with a different operand count.
5130 if ((Mnemonic == "vcmp" || Mnemonic == "vcmpe") && Operands.size() == 5 &&
5131 static_cast<ARMOperand*>(Operands[4])->isImm()) {
5132 ARMOperand *Op = static_cast<ARMOperand*>(Operands[4]);
5133 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
5134 if (CE && CE->getValue() == 0) {
5135 Operands.erase(Operands.begin() + 4);
5136 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5137 delete Op;
5138 }
5139 }
Jim Grosbach934755a2011-08-22 23:47:13 +00005140 // Similarly, the Thumb1 "RSB" instruction has a literal "#0" on the
Jim Grosbach55b02f22011-12-13 20:50:38 +00005141 // end. Convert it to a token here. Take care not to convert those
5142 // that should hit the Thumb2 encoding.
Jim Grosbach934755a2011-08-22 23:47:13 +00005143 if (Mnemonic == "rsb" && isThumb() && Operands.size() == 6 &&
Jim Grosbach55b02f22011-12-13 20:50:38 +00005144 static_cast<ARMOperand*>(Operands[3])->isReg() &&
5145 static_cast<ARMOperand*>(Operands[4])->isReg() &&
Jim Grosbach934755a2011-08-22 23:47:13 +00005146 static_cast<ARMOperand*>(Operands[5])->isImm()) {
5147 ARMOperand *Op = static_cast<ARMOperand*>(Operands[5]);
5148 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op->getImm());
Jim Grosbach55b02f22011-12-13 20:50:38 +00005149 if (CE && CE->getValue() == 0 &&
5150 (isThumbOne() ||
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005151 // The cc_out operand matches the IT block.
5152 ((inITBlock() != CarrySetting) &&
5153 // Neither register operand is a high register.
Jim Grosbach55b02f22011-12-13 20:50:38 +00005154 (isARMLowRegister(static_cast<ARMOperand*>(Operands[3])->getReg()) &&
Jim Grosbachd7ea73a2011-12-13 21:06:41 +00005155 isARMLowRegister(static_cast<ARMOperand*>(Operands[4])->getReg()))))){
Jim Grosbach934755a2011-08-22 23:47:13 +00005156 Operands.erase(Operands.begin() + 5);
5157 Operands.push_back(ARMOperand::CreateToken("#0", Op->getStartLoc()));
5158 delete Op;
5159 }
5160 }
5161
Chris Lattner98986712010-01-14 22:21:20 +00005162 return false;
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00005163}
5164
Jim Grosbach189610f2011-07-26 18:25:39 +00005165// Validate context-sensitive operand constraints.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005166
5167// return 'true' if register list contains non-low GPR registers,
5168// 'false' otherwise. If Reg is in the register list or is HiReg, set
5169// 'containsReg' to true.
5170static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5171 unsigned HiReg, bool &containsReg) {
5172 containsReg = false;
5173 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5174 unsigned OpReg = Inst.getOperand(i).getReg();
5175 if (OpReg == Reg)
5176 containsReg = true;
5177 // Anything other than a low register isn't legal here.
5178 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5179 return true;
5180 }
5181 return false;
5182}
5183
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005184// Check if the specified regisgter is in the register list of the inst,
5185// starting at the indicated operand number.
5186static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5187 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5188 unsigned OpReg = Inst.getOperand(i).getReg();
5189 if (OpReg == Reg)
5190 return true;
5191 }
5192 return false;
5193}
5194
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005195// FIXME: We would really prefer to have MCInstrInfo (the wrapper around
5196// the ARMInsts array) instead. Getting that here requires awkward
5197// API changes, though. Better way?
5198namespace llvm {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005199extern const MCInstrDesc ARMInsts[];
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005200}
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005201static const MCInstrDesc &getInstDesc(unsigned Opcode) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005202 return ARMInsts[Opcode];
5203}
5204
Jim Grosbach189610f2011-07-26 18:25:39 +00005205// FIXME: We would really like to be able to tablegen'erate this.
5206bool ARMAsmParser::
5207validateInstruction(MCInst &Inst,
5208 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00005209 const MCInstrDesc &MCID = getInstDesc(Inst.getOpcode());
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005210 SMLoc Loc = Operands[0]->getStartLoc();
5211 // Check the IT block state first.
Jim Grosbach74423e32012-01-25 19:52:01 +00005212 // NOTE: BKPT instruction has the interesting property of being
5213 // allowed in IT blocks, but not being predicable. It just always
Owen Andersonb6b7f512011-09-13 17:59:19 +00005214 // executes.
Jim Grosbach74423e32012-01-25 19:52:01 +00005215 if (inITBlock() && Inst.getOpcode() != ARM::tBKPT &&
5216 Inst.getOpcode() != ARM::BKPT) {
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005217 unsigned bit = 1;
5218 if (ITState.FirstCond)
5219 ITState.FirstCond = false;
5220 else
Jim Grosbacha1109882011-09-02 23:22:08 +00005221 bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005222 // The instruction must be predicable.
5223 if (!MCID.isPredicable())
5224 return Error(Loc, "instructions in IT block must be predicable");
5225 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
5226 unsigned ITCond = bit ? ITState.Cond :
5227 ARMCC::getOppositeCondition(ITState.Cond);
5228 if (Cond != ITCond) {
5229 // Find the condition code Operand to get its SMLoc information.
5230 SMLoc CondLoc;
5231 for (unsigned i = 1; i < Operands.size(); ++i)
5232 if (static_cast<ARMOperand*>(Operands[i])->isCondCode())
5233 CondLoc = Operands[i]->getStartLoc();
5234 return Error(CondLoc, "incorrect condition in IT block; got '" +
5235 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5236 "', but expected '" +
5237 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5238 }
Jim Grosbachc9a9b442011-08-31 18:29:05 +00005239 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005240 } else if (isThumbTwo() && MCID.isPredicable() &&
5241 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Owen Anderson51f6a7a2011-09-09 21:48:23 +00005242 ARMCC::AL && Inst.getOpcode() != ARM::tB &&
5243 Inst.getOpcode() != ARM::t2B)
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00005244 return Error(Loc, "predicated instructions must be in IT block");
5245
Jim Grosbach189610f2011-07-26 18:25:39 +00005246 switch (Inst.getOpcode()) {
Jim Grosbach2fd2b872011-08-10 20:29:19 +00005247 case ARM::LDRD:
5248 case ARM::LDRD_PRE:
5249 case ARM::LDRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005250 case ARM::LDREXD: {
5251 // Rt2 must be Rt + 1.
5252 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5253 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5254 if (Rt2 != Rt + 1)
5255 return Error(Operands[3]->getStartLoc(),
5256 "destination operands must be sequential");
5257 return false;
5258 }
Jim Grosbach14605d12011-08-11 20:28:23 +00005259 case ARM::STRD: {
5260 // Rt2 must be Rt + 1.
5261 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(0).getReg());
5262 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5263 if (Rt2 != Rt + 1)
5264 return Error(Operands[3]->getStartLoc(),
5265 "source operands must be sequential");
5266 return false;
5267 }
Jim Grosbach53642c52011-08-10 20:49:18 +00005268 case ARM::STRD_PRE:
5269 case ARM::STRD_POST:
Jim Grosbach189610f2011-07-26 18:25:39 +00005270 case ARM::STREXD: {
5271 // Rt2 must be Rt + 1.
5272 unsigned Rt = getARMRegisterNumbering(Inst.getOperand(1).getReg());
5273 unsigned Rt2 = getARMRegisterNumbering(Inst.getOperand(2).getReg());
5274 if (Rt2 != Rt + 1)
Jim Grosbach14605d12011-08-11 20:28:23 +00005275 return Error(Operands[3]->getStartLoc(),
Jim Grosbach189610f2011-07-26 18:25:39 +00005276 "source operands must be sequential");
5277 return false;
5278 }
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005279 case ARM::SBFX:
5280 case ARM::UBFX: {
5281 // width must be in range [1, 32-lsb]
5282 unsigned lsb = Inst.getOperand(2).getImm();
5283 unsigned widthm1 = Inst.getOperand(3).getImm();
5284 if (widthm1 >= 32 - lsb)
5285 return Error(Operands[5]->getStartLoc(),
5286 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach00c9a512011-08-16 21:42:31 +00005287 return false;
Jim Grosbachfb8989e2011-07-27 21:09:25 +00005288 }
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005289 case ARM::tLDMIA: {
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005290 // If we're parsing Thumb2, the .w variant is available and handles
5291 // most cases that are normally illegal for a Thumb1 LDM
5292 // instruction. We'll make the transformation in processInstruction()
5293 // if necessary.
5294 //
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005295 // Thumb LDM instructions are writeback iff the base register is not
5296 // in the register list.
5297 unsigned Rn = Inst.getOperand(0).getReg();
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005298 bool hasWritebackToken =
5299 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
5300 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
Jim Grosbachaa875f82011-08-23 18:13:04 +00005301 bool listContainsBase;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005302 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) && !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005303 return Error(Operands[3 + hasWritebackToken]->getStartLoc(),
5304 "registers must be in range r0-r7");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005305 // If we should have writeback, then there should be a '!' token.
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005306 if (!listContainsBase && !hasWritebackToken && !isThumbTwo())
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005307 return Error(Operands[2]->getStartLoc(),
5308 "writeback operator '!' expected");
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005309 // If we should not have writeback, there must not be a '!'. This is
5310 // true even for the 32-bit wide encodings.
Jim Grosbachaa875f82011-08-23 18:13:04 +00005311 if (listContainsBase && hasWritebackToken)
Jim Grosbach7260c6a2011-08-22 23:01:07 +00005312 return Error(Operands[3]->getStartLoc(),
5313 "writeback operator '!' not allowed when base register "
5314 "in register list");
Jim Grosbach93b3eff2011-08-18 21:50:53 +00005315
5316 break;
5317 }
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00005318 case ARM::t2LDMIA_UPD: {
5319 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
5320 return Error(Operands[4]->getStartLoc(),
5321 "writeback operator '!' not allowed when base register "
5322 "in register list");
5323 break;
5324 }
Jim Grosbach54026372011-11-10 23:17:11 +00005325 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
5326 // so only issue a diagnostic for thumb1. The instructions will be
5327 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005328 case ARM::tPOP: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005329 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005330 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase) &&
5331 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005332 return Error(Operands[2]->getStartLoc(),
5333 "registers must be in range r0-r7 or pc");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005334 break;
5335 }
5336 case ARM::tPUSH: {
Jim Grosbachaa875f82011-08-23 18:13:04 +00005337 bool listContainsBase;
Jim Grosbach54026372011-11-10 23:17:11 +00005338 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase) &&
5339 !isThumbTwo())
Jim Grosbachaa875f82011-08-23 18:13:04 +00005340 return Error(Operands[2]->getStartLoc(),
5341 "registers must be in range r0-r7 or lr");
Jim Grosbach6dcafc02011-08-22 23:17:34 +00005342 break;
5343 }
Jim Grosbach1e84f192011-08-23 18:15:37 +00005344 case ARM::tSTMIA_UPD: {
5345 bool listContainsBase;
Jim Grosbach8213c962011-09-16 20:50:13 +00005346 if (checkLowRegisterList(Inst, 4, 0, 0, listContainsBase) && !isThumbTwo())
Jim Grosbach1e84f192011-08-23 18:15:37 +00005347 return Error(Operands[4]->getStartLoc(),
5348 "registers must be in range r0-r7");
5349 break;
5350 }
Jim Grosbacha9cc08f2012-04-27 23:51:36 +00005351 case ARM::tADDrSP: {
5352 // If the non-SP source operand and the destination operand are not the
5353 // same, we need thumb2 (for the wide encoding), or we have an error.
5354 if (!isThumbTwo() &&
5355 Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
5356 return Error(Operands[4]->getStartLoc(),
5357 "source register must be the same as destination");
5358 }
5359 break;
5360 }
Jim Grosbach189610f2011-07-26 18:25:39 +00005361 }
5362
5363 return false;
5364}
5365
Jim Grosbachd7433e22012-01-23 23:45:44 +00005366static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach84defb52011-12-02 22:34:51 +00005367 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005368 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005369 // VST1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005370 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5371 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5372 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5373 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
5374 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
5375 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
5376 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
5377 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
5378 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005379
5380 // VST2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005381 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5382 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5383 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5384 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5385 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005386
Jim Grosbach7945ead2012-01-24 00:43:12 +00005387 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
5388 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
5389 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
5390 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
5391 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach5b484312011-12-20 20:46:29 +00005392
Jim Grosbach7945ead2012-01-24 00:43:12 +00005393 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
5394 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
5395 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
5396 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
5397 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005398
Jim Grosbach4adb1822012-01-24 00:07:41 +00005399 // VST3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005400 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5401 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5402 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5403 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
5404 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5405 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
5406 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
5407 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
5408 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
5409 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
5410 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
5411 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
5412 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
5413 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
5414 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbach4adb1822012-01-24 00:07:41 +00005415
Jim Grosbachd7433e22012-01-23 23:45:44 +00005416 // VST3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005417 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5418 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5419 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5420 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5421 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5422 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5423 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
5424 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
5425 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
5426 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
5427 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
5428 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
5429 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
5430 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
5431 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
5432 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
5433 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
5434 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbach539aab72012-01-24 00:58:13 +00005435
Jim Grosbach88a54de2012-01-24 18:53:13 +00005436 // VST4LN
5437 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5438 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5439 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5440 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
5441 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5442 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
5443 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
5444 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
5445 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
5446 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
5447 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
5448 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
5449 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
5450 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
5451 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
5452
Jim Grosbach539aab72012-01-24 00:58:13 +00005453 // VST4
5454 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5455 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5456 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5457 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5458 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5459 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5460 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
5461 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
5462 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
5463 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
5464 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
5465 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
5466 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
5467 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
5468 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
5469 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
5470 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
5471 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbach84defb52011-12-02 22:34:51 +00005472 }
5473}
5474
Jim Grosbachd7433e22012-01-23 23:45:44 +00005475static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach7636bf62011-12-02 00:35:16 +00005476 switch(Opc) {
Craig Topperbc219812012-02-07 02:50:20 +00005477 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005478 // VLD1LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005479 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5480 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5481 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5482 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
5483 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
5484 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
5485 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
5486 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
5487 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005488
5489 // VLD2LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005490 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5491 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5492 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5493 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
5494 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5495 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
5496 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
5497 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
5498 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
5499 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
5500 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
5501 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
5502 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
5503 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
5504 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbach3a678af2012-01-23 21:53:26 +00005505
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00005506 // VLD3DUP
5507 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5508 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5509 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5510 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
5511 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPq16_UPD;
5512 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5513 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
5514 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
5515 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
5516 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
5517 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
5518 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
5519 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
5520 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
5521 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
5522 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
5523 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
5524 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
5525
Jim Grosbach3a678af2012-01-23 21:53:26 +00005526 // VLD3LN
Jim Grosbach7945ead2012-01-24 00:43:12 +00005527 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5528 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5529 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5530 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
5531 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5532 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
5533 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
5534 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
5535 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
5536 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
5537 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
5538 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
5539 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
5540 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
5541 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachc387fc62012-01-23 23:20:46 +00005542
5543 // VLD3
Jim Grosbach7945ead2012-01-24 00:43:12 +00005544 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5545 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5546 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5547 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5548 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5549 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5550 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
5551 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
5552 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
5553 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
5554 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
5555 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
5556 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
5557 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
5558 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
5559 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
5560 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
5561 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005562
Jim Grosbache983a132012-01-24 18:37:25 +00005563 // VLD4LN
5564 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5565 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5566 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5567 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNq16_UPD;
5568 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5569 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
5570 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
5571 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
5572 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
5573 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
5574 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
5575 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
5576 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
5577 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
5578 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
5579
Jim Grosbacha57a36a2012-01-25 00:01:08 +00005580 // VLD4DUP
5581 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5582 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5583 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5584 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
5585 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
5586 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5587 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
5588 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
5589 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
5590 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
5591 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
5592 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
5593 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
5594 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
5595 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
5596 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
5597 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
5598 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
5599
Jim Grosbach8abe7e32012-01-24 00:43:17 +00005600 // VLD4
5601 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5602 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5603 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5604 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5605 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5606 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5607 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
5608 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
5609 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
5610 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
5611 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
5612 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
5613 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
5614 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
5615 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
5616 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
5617 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
5618 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach7636bf62011-12-02 00:35:16 +00005619 }
5620}
5621
Jim Grosbach83ec8772011-11-10 23:42:14 +00005622bool ARMAsmParser::
Jim Grosbachf8fce712011-08-11 17:35:48 +00005623processInstruction(MCInst &Inst,
5624 const SmallVectorImpl<MCParsedAsmOperand*> &Operands) {
5625 switch (Inst.getOpcode()) {
Jim Grosbach0b4c6732012-01-18 22:46:46 +00005626 // Aliases for alternate PC+imm syntax of LDR instructions.
5627 case ARM::t2LDRpcrel:
5628 Inst.setOpcode(ARM::t2LDRpci);
5629 return true;
5630 case ARM::t2LDRBpcrel:
5631 Inst.setOpcode(ARM::t2LDRBpci);
5632 return true;
5633 case ARM::t2LDRHpcrel:
5634 Inst.setOpcode(ARM::t2LDRHpci);
5635 return true;
5636 case ARM::t2LDRSBpcrel:
5637 Inst.setOpcode(ARM::t2LDRSBpci);
5638 return true;
5639 case ARM::t2LDRSHpcrel:
5640 Inst.setOpcode(ARM::t2LDRSHpci);
5641 return true;
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005642 // Handle NEON VST complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005643 case ARM::VST1LNdWB_register_Asm_8:
5644 case ARM::VST1LNdWB_register_Asm_16:
5645 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005646 MCInst TmpInst;
5647 // Shuffle the operands around so the lane index operand is in the
5648 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005649 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005650 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005651 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5652 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5653 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5654 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5655 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5656 TmpInst.addOperand(Inst.getOperand(1)); // lane
5657 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5658 TmpInst.addOperand(Inst.getOperand(6));
5659 Inst = TmpInst;
5660 return true;
5661 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005662
Jim Grosbach8b31f952012-01-23 19:39:08 +00005663 case ARM::VST2LNdWB_register_Asm_8:
5664 case ARM::VST2LNdWB_register_Asm_16:
5665 case ARM::VST2LNdWB_register_Asm_32:
5666 case ARM::VST2LNqWB_register_Asm_16:
5667 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005668 MCInst TmpInst;
5669 // Shuffle the operands around so the lane index operand is in the
5670 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005671 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005672 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005673 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5674 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5675 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5676 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5677 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005678 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5679 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005680 TmpInst.addOperand(Inst.getOperand(1)); // lane
5681 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5682 TmpInst.addOperand(Inst.getOperand(6));
5683 Inst = TmpInst;
5684 return true;
5685 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005686
5687 case ARM::VST3LNdWB_register_Asm_8:
5688 case ARM::VST3LNdWB_register_Asm_16:
5689 case ARM::VST3LNdWB_register_Asm_32:
5690 case ARM::VST3LNqWB_register_Asm_16:
5691 case ARM::VST3LNqWB_register_Asm_32: {
5692 MCInst TmpInst;
5693 // Shuffle the operands around so the lane index operand is in the
5694 // right place.
5695 unsigned Spacing;
5696 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5697 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5698 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5699 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5700 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5701 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5702 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5703 Spacing));
5704 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5705 Spacing * 2));
5706 TmpInst.addOperand(Inst.getOperand(1)); // lane
5707 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5708 TmpInst.addOperand(Inst.getOperand(6));
5709 Inst = TmpInst;
5710 return true;
5711 }
5712
Jim Grosbach88a54de2012-01-24 18:53:13 +00005713 case ARM::VST4LNdWB_register_Asm_8:
5714 case ARM::VST4LNdWB_register_Asm_16:
5715 case ARM::VST4LNdWB_register_Asm_32:
5716 case ARM::VST4LNqWB_register_Asm_16:
5717 case ARM::VST4LNqWB_register_Asm_32: {
5718 MCInst TmpInst;
5719 // Shuffle the operands around so the lane index operand is in the
5720 // right place.
5721 unsigned Spacing;
5722 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5723 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5724 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5725 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5726 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5727 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5728 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5729 Spacing));
5730 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5731 Spacing * 2));
5732 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5733 Spacing * 3));
5734 TmpInst.addOperand(Inst.getOperand(1)); // lane
5735 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5736 TmpInst.addOperand(Inst.getOperand(6));
5737 Inst = TmpInst;
5738 return true;
5739 }
5740
Jim Grosbach8b31f952012-01-23 19:39:08 +00005741 case ARM::VST1LNdWB_fixed_Asm_8:
5742 case ARM::VST1LNdWB_fixed_Asm_16:
5743 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005744 MCInst TmpInst;
5745 // Shuffle the operands around so the lane index operand is in the
5746 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005747 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005748 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005749 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5750 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5751 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5752 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5753 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5754 TmpInst.addOperand(Inst.getOperand(1)); // lane
5755 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5756 TmpInst.addOperand(Inst.getOperand(5));
5757 Inst = TmpInst;
5758 return true;
5759 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005760
Jim Grosbach8b31f952012-01-23 19:39:08 +00005761 case ARM::VST2LNdWB_fixed_Asm_8:
5762 case ARM::VST2LNdWB_fixed_Asm_16:
5763 case ARM::VST2LNdWB_fixed_Asm_32:
5764 case ARM::VST2LNqWB_fixed_Asm_16:
5765 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005766 MCInst TmpInst;
5767 // Shuffle the operands around so the lane index operand is in the
5768 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005769 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005770 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005771 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5772 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5773 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5774 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5775 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005776 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5777 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005778 TmpInst.addOperand(Inst.getOperand(1)); // lane
5779 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5780 TmpInst.addOperand(Inst.getOperand(5));
5781 Inst = TmpInst;
5782 return true;
5783 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005784
5785 case ARM::VST3LNdWB_fixed_Asm_8:
5786 case ARM::VST3LNdWB_fixed_Asm_16:
5787 case ARM::VST3LNdWB_fixed_Asm_32:
5788 case ARM::VST3LNqWB_fixed_Asm_16:
5789 case ARM::VST3LNqWB_fixed_Asm_32: {
5790 MCInst TmpInst;
5791 // Shuffle the operands around so the lane index operand is in the
5792 // right place.
5793 unsigned Spacing;
5794 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5795 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5796 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5797 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5798 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5799 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5800 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5801 Spacing));
5802 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5803 Spacing * 2));
5804 TmpInst.addOperand(Inst.getOperand(1)); // lane
5805 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5806 TmpInst.addOperand(Inst.getOperand(5));
5807 Inst = TmpInst;
5808 return true;
5809 }
5810
Jim Grosbach88a54de2012-01-24 18:53:13 +00005811 case ARM::VST4LNdWB_fixed_Asm_8:
5812 case ARM::VST4LNdWB_fixed_Asm_16:
5813 case ARM::VST4LNdWB_fixed_Asm_32:
5814 case ARM::VST4LNqWB_fixed_Asm_16:
5815 case ARM::VST4LNqWB_fixed_Asm_32: {
5816 MCInst TmpInst;
5817 // Shuffle the operands around so the lane index operand is in the
5818 // right place.
5819 unsigned Spacing;
5820 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5821 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5822 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5823 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5824 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
5825 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5826 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5827 Spacing));
5828 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5829 Spacing * 2));
5830 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5831 Spacing * 3));
5832 TmpInst.addOperand(Inst.getOperand(1)); // lane
5833 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5834 TmpInst.addOperand(Inst.getOperand(5));
5835 Inst = TmpInst;
5836 return true;
5837 }
5838
Jim Grosbach8b31f952012-01-23 19:39:08 +00005839 case ARM::VST1LNdAsm_8:
5840 case ARM::VST1LNdAsm_16:
5841 case ARM::VST1LNdAsm_32: {
Jim Grosbach84defb52011-12-02 22:34:51 +00005842 MCInst TmpInst;
5843 // Shuffle the operands around so the lane index operand is in the
5844 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005845 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005846 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach84defb52011-12-02 22:34:51 +00005847 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5848 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5849 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5850 TmpInst.addOperand(Inst.getOperand(1)); // lane
5851 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5852 TmpInst.addOperand(Inst.getOperand(5));
5853 Inst = TmpInst;
5854 return true;
5855 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005856
Jim Grosbach8b31f952012-01-23 19:39:08 +00005857 case ARM::VST2LNdAsm_8:
5858 case ARM::VST2LNdAsm_16:
5859 case ARM::VST2LNdAsm_32:
5860 case ARM::VST2LNqAsm_16:
5861 case ARM::VST2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005862 MCInst TmpInst;
5863 // Shuffle the operands around so the lane index operand is in the
5864 // right place.
Jim Grosbach5b484312011-12-20 20:46:29 +00005865 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005866 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005867 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5868 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5869 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach5b484312011-12-20 20:46:29 +00005870 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5871 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005872 TmpInst.addOperand(Inst.getOperand(1)); // lane
5873 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5874 TmpInst.addOperand(Inst.getOperand(5));
5875 Inst = TmpInst;
5876 return true;
5877 }
Jim Grosbach4adb1822012-01-24 00:07:41 +00005878
5879 case ARM::VST3LNdAsm_8:
5880 case ARM::VST3LNdAsm_16:
5881 case ARM::VST3LNdAsm_32:
5882 case ARM::VST3LNqAsm_16:
5883 case ARM::VST3LNqAsm_32: {
5884 MCInst TmpInst;
5885 // Shuffle the operands around so the lane index operand is in the
5886 // right place.
5887 unsigned Spacing;
5888 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5889 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5890 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5891 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5892 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5893 Spacing));
5894 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5895 Spacing * 2));
5896 TmpInst.addOperand(Inst.getOperand(1)); // lane
5897 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5898 TmpInst.addOperand(Inst.getOperand(5));
5899 Inst = TmpInst;
5900 return true;
5901 }
5902
Jim Grosbach88a54de2012-01-24 18:53:13 +00005903 case ARM::VST4LNdAsm_8:
5904 case ARM::VST4LNdAsm_16:
5905 case ARM::VST4LNdAsm_32:
5906 case ARM::VST4LNqAsm_16:
5907 case ARM::VST4LNqAsm_32: {
5908 MCInst TmpInst;
5909 // Shuffle the operands around so the lane index operand is in the
5910 // right place.
5911 unsigned Spacing;
5912 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
5913 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5914 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5915 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5916 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5917 Spacing));
5918 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5919 Spacing * 2));
5920 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5921 Spacing * 3));
5922 TmpInst.addOperand(Inst.getOperand(1)); // lane
5923 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
5924 TmpInst.addOperand(Inst.getOperand(5));
5925 Inst = TmpInst;
5926 return true;
5927 }
5928
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005929 // Handle NEON VLD complex aliases.
Jim Grosbach8b31f952012-01-23 19:39:08 +00005930 case ARM::VLD1LNdWB_register_Asm_8:
5931 case ARM::VLD1LNdWB_register_Asm_16:
5932 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00005933 MCInst TmpInst;
5934 // Shuffle the operands around so the lane index operand is in the
5935 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005936 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005937 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00005938 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5939 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5940 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5941 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5942 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5943 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5944 TmpInst.addOperand(Inst.getOperand(1)); // lane
5945 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5946 TmpInst.addOperand(Inst.getOperand(6));
5947 Inst = TmpInst;
5948 return true;
5949 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005950
Jim Grosbach8b31f952012-01-23 19:39:08 +00005951 case ARM::VLD2LNdWB_register_Asm_8:
5952 case ARM::VLD2LNdWB_register_Asm_16:
5953 case ARM::VLD2LNdWB_register_Asm_32:
5954 case ARM::VLD2LNqWB_register_Asm_16:
5955 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005956 MCInst TmpInst;
5957 // Shuffle the operands around so the lane index operand is in the
5958 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005959 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005960 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005961 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005962 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5963 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005964 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5965 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5966 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5967 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5968 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00005969 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5970 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00005971 TmpInst.addOperand(Inst.getOperand(1)); // lane
5972 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
5973 TmpInst.addOperand(Inst.getOperand(6));
5974 Inst = TmpInst;
5975 return true;
5976 }
5977
Jim Grosbach3a678af2012-01-23 21:53:26 +00005978 case ARM::VLD3LNdWB_register_Asm_8:
5979 case ARM::VLD3LNdWB_register_Asm_16:
5980 case ARM::VLD3LNdWB_register_Asm_32:
5981 case ARM::VLD3LNqWB_register_Asm_16:
5982 case ARM::VLD3LNqWB_register_Asm_32: {
5983 MCInst TmpInst;
5984 // Shuffle the operands around so the lane index operand is in the
5985 // right place.
5986 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00005987 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005988 TmpInst.addOperand(Inst.getOperand(0)); // Vd
5989 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5990 Spacing));
5991 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00005992 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00005993 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
5994 TmpInst.addOperand(Inst.getOperand(2)); // Rn
5995 TmpInst.addOperand(Inst.getOperand(3)); // alignment
5996 TmpInst.addOperand(Inst.getOperand(4)); // Rm
5997 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
5998 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
5999 Spacing));
6000 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006001 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006002 TmpInst.addOperand(Inst.getOperand(1)); // lane
6003 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6004 TmpInst.addOperand(Inst.getOperand(6));
6005 Inst = TmpInst;
6006 return true;
6007 }
6008
Jim Grosbache983a132012-01-24 18:37:25 +00006009 case ARM::VLD4LNdWB_register_Asm_8:
6010 case ARM::VLD4LNdWB_register_Asm_16:
6011 case ARM::VLD4LNdWB_register_Asm_32:
6012 case ARM::VLD4LNqWB_register_Asm_16:
6013 case ARM::VLD4LNqWB_register_Asm_32: {
6014 MCInst TmpInst;
6015 // Shuffle the operands around so the lane index operand is in the
6016 // right place.
6017 unsigned Spacing;
6018 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6019 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6020 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6021 Spacing));
6022 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6023 Spacing * 2));
6024 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6025 Spacing * 3));
6026 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6027 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6028 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6029 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6030 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6031 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6032 Spacing));
6033 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6034 Spacing * 2));
6035 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6036 Spacing * 3));
6037 TmpInst.addOperand(Inst.getOperand(1)); // lane
6038 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6039 TmpInst.addOperand(Inst.getOperand(6));
6040 Inst = TmpInst;
6041 return true;
6042 }
6043
Jim Grosbach8b31f952012-01-23 19:39:08 +00006044 case ARM::VLD1LNdWB_fixed_Asm_8:
6045 case ARM::VLD1LNdWB_fixed_Asm_16:
6046 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbach872eedb2011-12-02 22:01:52 +00006047 MCInst TmpInst;
6048 // Shuffle the operands around so the lane index operand is in the
6049 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006050 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006051 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach872eedb2011-12-02 22:01:52 +00006052 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6053 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6054 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6055 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6056 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6057 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6058 TmpInst.addOperand(Inst.getOperand(1)); // lane
6059 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6060 TmpInst.addOperand(Inst.getOperand(5));
6061 Inst = TmpInst;
6062 return true;
6063 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006064
Jim Grosbach8b31f952012-01-23 19:39:08 +00006065 case ARM::VLD2LNdWB_fixed_Asm_8:
6066 case ARM::VLD2LNdWB_fixed_Asm_16:
6067 case ARM::VLD2LNdWB_fixed_Asm_32:
6068 case ARM::VLD2LNqWB_fixed_Asm_16:
6069 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006070 MCInst TmpInst;
6071 // Shuffle the operands around so the lane index operand is in the
6072 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006073 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006074 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006075 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006076 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6077 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006078 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6079 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6080 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6081 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6082 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006083 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6084 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006085 TmpInst.addOperand(Inst.getOperand(1)); // lane
6086 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6087 TmpInst.addOperand(Inst.getOperand(5));
6088 Inst = TmpInst;
6089 return true;
6090 }
6091
Jim Grosbach3a678af2012-01-23 21:53:26 +00006092 case ARM::VLD3LNdWB_fixed_Asm_8:
6093 case ARM::VLD3LNdWB_fixed_Asm_16:
6094 case ARM::VLD3LNdWB_fixed_Asm_32:
6095 case ARM::VLD3LNqWB_fixed_Asm_16:
6096 case ARM::VLD3LNqWB_fixed_Asm_32: {
6097 MCInst TmpInst;
6098 // Shuffle the operands around so the lane index operand is in the
6099 // right place.
6100 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006101 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006102 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6103 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6104 Spacing));
6105 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006106 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006107 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6108 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6109 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6110 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6111 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6112 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6113 Spacing));
6114 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006115 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006116 TmpInst.addOperand(Inst.getOperand(1)); // lane
6117 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6118 TmpInst.addOperand(Inst.getOperand(5));
6119 Inst = TmpInst;
6120 return true;
6121 }
6122
Jim Grosbache983a132012-01-24 18:37:25 +00006123 case ARM::VLD4LNdWB_fixed_Asm_8:
6124 case ARM::VLD4LNdWB_fixed_Asm_16:
6125 case ARM::VLD4LNdWB_fixed_Asm_32:
6126 case ARM::VLD4LNqWB_fixed_Asm_16:
6127 case ARM::VLD4LNqWB_fixed_Asm_32: {
6128 MCInst TmpInst;
6129 // Shuffle the operands around so the lane index operand is in the
6130 // right place.
6131 unsigned Spacing;
6132 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6133 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6134 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6135 Spacing));
6136 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6137 Spacing * 2));
6138 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6139 Spacing * 3));
6140 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6141 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6142 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6143 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6144 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6145 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6146 Spacing));
6147 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6148 Spacing * 2));
6149 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6150 Spacing * 3));
6151 TmpInst.addOperand(Inst.getOperand(1)); // lane
6152 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6153 TmpInst.addOperand(Inst.getOperand(5));
6154 Inst = TmpInst;
6155 return true;
6156 }
6157
Jim Grosbach8b31f952012-01-23 19:39:08 +00006158 case ARM::VLD1LNdAsm_8:
6159 case ARM::VLD1LNdAsm_16:
6160 case ARM::VLD1LNdAsm_32: {
Jim Grosbach7636bf62011-12-02 00:35:16 +00006161 MCInst TmpInst;
6162 // Shuffle the operands around so the lane index operand is in the
6163 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006164 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006165 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach7636bf62011-12-02 00:35:16 +00006166 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6167 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6168 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6169 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6170 TmpInst.addOperand(Inst.getOperand(1)); // lane
6171 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6172 TmpInst.addOperand(Inst.getOperand(5));
6173 Inst = TmpInst;
6174 return true;
6175 }
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006176
Jim Grosbach8b31f952012-01-23 19:39:08 +00006177 case ARM::VLD2LNdAsm_8:
6178 case ARM::VLD2LNdAsm_16:
6179 case ARM::VLD2LNdAsm_32:
6180 case ARM::VLD2LNqAsm_16:
6181 case ARM::VLD2LNqAsm_32: {
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006182 MCInst TmpInst;
6183 // Shuffle the operands around so the lane index operand is in the
6184 // right place.
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006185 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006186 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006187 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006188 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6189 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006190 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6191 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6192 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach95fad1c2011-12-20 19:21:26 +00006193 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6194 Spacing));
Jim Grosbach9b1b3902011-12-14 23:25:46 +00006195 TmpInst.addOperand(Inst.getOperand(1)); // lane
6196 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6197 TmpInst.addOperand(Inst.getOperand(5));
6198 Inst = TmpInst;
6199 return true;
6200 }
Jim Grosbach3a678af2012-01-23 21:53:26 +00006201
6202 case ARM::VLD3LNdAsm_8:
6203 case ARM::VLD3LNdAsm_16:
6204 case ARM::VLD3LNdAsm_32:
6205 case ARM::VLD3LNqAsm_16:
6206 case ARM::VLD3LNqAsm_32: {
6207 MCInst TmpInst;
6208 // Shuffle the operands around so the lane index operand is in the
6209 // right place.
6210 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006211 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006212 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6213 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6214 Spacing));
6215 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006216 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006217 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6218 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6219 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6220 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6221 Spacing));
6222 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachc387fc62012-01-23 23:20:46 +00006223 Spacing * 2));
Jim Grosbach3a678af2012-01-23 21:53:26 +00006224 TmpInst.addOperand(Inst.getOperand(1)); // lane
6225 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6226 TmpInst.addOperand(Inst.getOperand(5));
6227 Inst = TmpInst;
6228 return true;
6229 }
6230
Jim Grosbache983a132012-01-24 18:37:25 +00006231 case ARM::VLD4LNdAsm_8:
6232 case ARM::VLD4LNdAsm_16:
6233 case ARM::VLD4LNdAsm_32:
6234 case ARM::VLD4LNqAsm_16:
6235 case ARM::VLD4LNqAsm_32: {
6236 MCInst TmpInst;
6237 // Shuffle the operands around so the lane index operand is in the
6238 // right place.
6239 unsigned Spacing;
6240 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6241 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6242 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6243 Spacing));
6244 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6245 Spacing * 2));
6246 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6247 Spacing * 3));
6248 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6249 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6250 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6251 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6252 Spacing));
6253 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6254 Spacing * 2));
6255 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6256 Spacing * 3));
6257 TmpInst.addOperand(Inst.getOperand(1)); // lane
6258 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6259 TmpInst.addOperand(Inst.getOperand(5));
6260 Inst = TmpInst;
6261 return true;
6262 }
6263
Jim Grosbach5e59f7e2012-01-24 23:47:04 +00006264 // VLD3DUP single 3-element structure to all lanes instructions.
6265 case ARM::VLD3DUPdAsm_8:
6266 case ARM::VLD3DUPdAsm_16:
6267 case ARM::VLD3DUPdAsm_32:
6268 case ARM::VLD3DUPqAsm_8:
6269 case ARM::VLD3DUPqAsm_16:
6270 case ARM::VLD3DUPqAsm_32: {
6271 MCInst TmpInst;
6272 unsigned Spacing;
6273 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6274 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6275 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6276 Spacing));
6277 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6278 Spacing * 2));
6279 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6280 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6281 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6282 TmpInst.addOperand(Inst.getOperand(4));
6283 Inst = TmpInst;
6284 return true;
6285 }
6286
6287 case ARM::VLD3DUPdWB_fixed_Asm_8:
6288 case ARM::VLD3DUPdWB_fixed_Asm_16:
6289 case ARM::VLD3DUPdWB_fixed_Asm_32:
6290 case ARM::VLD3DUPqWB_fixed_Asm_8:
6291 case ARM::VLD3DUPqWB_fixed_Asm_16:
6292 case ARM::VLD3DUPqWB_fixed_Asm_32: {
6293 MCInst TmpInst;
6294 unsigned Spacing;
6295 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6296 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6297 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6298 Spacing));
6299 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6300 Spacing * 2));
6301 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6302 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6303 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6304 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6305 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6306 TmpInst.addOperand(Inst.getOperand(4));
6307 Inst = TmpInst;
6308 return true;
6309 }
6310
6311 case ARM::VLD3DUPdWB_register_Asm_8:
6312 case ARM::VLD3DUPdWB_register_Asm_16:
6313 case ARM::VLD3DUPdWB_register_Asm_32:
6314 case ARM::VLD3DUPqWB_register_Asm_8:
6315 case ARM::VLD3DUPqWB_register_Asm_16:
6316 case ARM::VLD3DUPqWB_register_Asm_32: {
6317 MCInst TmpInst;
6318 unsigned Spacing;
6319 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6320 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6321 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6322 Spacing));
6323 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6324 Spacing * 2));
6325 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6326 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6327 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6328 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6329 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6330 TmpInst.addOperand(Inst.getOperand(5));
6331 Inst = TmpInst;
6332 return true;
6333 }
6334
Jim Grosbachc387fc62012-01-23 23:20:46 +00006335 // VLD3 multiple 3-element structure instructions.
6336 case ARM::VLD3dAsm_8:
6337 case ARM::VLD3dAsm_16:
6338 case ARM::VLD3dAsm_32:
6339 case ARM::VLD3qAsm_8:
6340 case ARM::VLD3qAsm_16:
6341 case ARM::VLD3qAsm_32: {
6342 MCInst TmpInst;
6343 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006344 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006345 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6346 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6347 Spacing));
6348 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6349 Spacing * 2));
6350 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6351 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6352 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6353 TmpInst.addOperand(Inst.getOperand(4));
6354 Inst = TmpInst;
6355 return true;
6356 }
6357
6358 case ARM::VLD3dWB_fixed_Asm_8:
6359 case ARM::VLD3dWB_fixed_Asm_16:
6360 case ARM::VLD3dWB_fixed_Asm_32:
6361 case ARM::VLD3qWB_fixed_Asm_8:
6362 case ARM::VLD3qWB_fixed_Asm_16:
6363 case ARM::VLD3qWB_fixed_Asm_32: {
6364 MCInst TmpInst;
6365 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006366 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006367 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6368 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6369 Spacing));
6370 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6371 Spacing * 2));
6372 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6373 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6374 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6375 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6376 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6377 TmpInst.addOperand(Inst.getOperand(4));
6378 Inst = TmpInst;
6379 return true;
6380 }
6381
6382 case ARM::VLD3dWB_register_Asm_8:
6383 case ARM::VLD3dWB_register_Asm_16:
6384 case ARM::VLD3dWB_register_Asm_32:
6385 case ARM::VLD3qWB_register_Asm_8:
6386 case ARM::VLD3qWB_register_Asm_16:
6387 case ARM::VLD3qWB_register_Asm_32: {
6388 MCInst TmpInst;
6389 unsigned Spacing;
Jim Grosbachd7433e22012-01-23 23:45:44 +00006390 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachc387fc62012-01-23 23:20:46 +00006391 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6392 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6393 Spacing));
6394 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6395 Spacing * 2));
6396 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6397 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6398 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6399 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6400 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6401 TmpInst.addOperand(Inst.getOperand(5));
6402 Inst = TmpInst;
6403 return true;
6404 }
6405
Jim Grosbacha57a36a2012-01-25 00:01:08 +00006406 // VLD4DUP single 3-element structure to all lanes instructions.
6407 case ARM::VLD4DUPdAsm_8:
6408 case ARM::VLD4DUPdAsm_16:
6409 case ARM::VLD4DUPdAsm_32:
6410 case ARM::VLD4DUPqAsm_8:
6411 case ARM::VLD4DUPqAsm_16:
6412 case ARM::VLD4DUPqAsm_32: {
6413 MCInst TmpInst;
6414 unsigned Spacing;
6415 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6416 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6417 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6418 Spacing));
6419 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6420 Spacing * 2));
6421 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6422 Spacing * 3));
6423 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6424 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6425 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6426 TmpInst.addOperand(Inst.getOperand(4));
6427 Inst = TmpInst;
6428 return true;
6429 }
6430
6431 case ARM::VLD4DUPdWB_fixed_Asm_8:
6432 case ARM::VLD4DUPdWB_fixed_Asm_16:
6433 case ARM::VLD4DUPdWB_fixed_Asm_32:
6434 case ARM::VLD4DUPqWB_fixed_Asm_8:
6435 case ARM::VLD4DUPqWB_fixed_Asm_16:
6436 case ARM::VLD4DUPqWB_fixed_Asm_32: {
6437 MCInst TmpInst;
6438 unsigned Spacing;
6439 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6440 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6441 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6442 Spacing));
6443 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6444 Spacing * 2));
6445 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6446 Spacing * 3));
6447 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6448 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6449 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6450 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6451 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6452 TmpInst.addOperand(Inst.getOperand(4));
6453 Inst = TmpInst;
6454 return true;
6455 }
6456
6457 case ARM::VLD4DUPdWB_register_Asm_8:
6458 case ARM::VLD4DUPdWB_register_Asm_16:
6459 case ARM::VLD4DUPdWB_register_Asm_32:
6460 case ARM::VLD4DUPqWB_register_Asm_8:
6461 case ARM::VLD4DUPqWB_register_Asm_16:
6462 case ARM::VLD4DUPqWB_register_Asm_32: {
6463 MCInst TmpInst;
6464 unsigned Spacing;
6465 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6466 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6467 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6468 Spacing));
6469 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6470 Spacing * 2));
6471 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6472 Spacing * 3));
6473 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6474 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6475 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6476 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6477 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6478 TmpInst.addOperand(Inst.getOperand(5));
6479 Inst = TmpInst;
6480 return true;
6481 }
6482
6483 // VLD4 multiple 4-element structure instructions.
Jim Grosbach8abe7e32012-01-24 00:43:17 +00006484 case ARM::VLD4dAsm_8:
6485 case ARM::VLD4dAsm_16:
6486 case ARM::VLD4dAsm_32:
6487 case ARM::VLD4qAsm_8:
6488 case ARM::VLD4qAsm_16:
6489 case ARM::VLD4qAsm_32: {
6490 MCInst TmpInst;
6491 unsigned Spacing;
6492 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6493 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6494 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6495 Spacing));
6496 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6497 Spacing * 2));
6498 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6499 Spacing * 3));
6500 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6501 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6502 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6503 TmpInst.addOperand(Inst.getOperand(4));
6504 Inst = TmpInst;
6505 return true;
6506 }
6507
6508 case ARM::VLD4dWB_fixed_Asm_8:
6509 case ARM::VLD4dWB_fixed_Asm_16:
6510 case ARM::VLD4dWB_fixed_Asm_32:
6511 case ARM::VLD4qWB_fixed_Asm_8:
6512 case ARM::VLD4qWB_fixed_Asm_16:
6513 case ARM::VLD4qWB_fixed_Asm_32: {
6514 MCInst TmpInst;
6515 unsigned Spacing;
6516 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6517 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6518 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6519 Spacing));
6520 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6521 Spacing * 2));
6522 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6523 Spacing * 3));
6524 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6525 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6526 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6527 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6528 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6529 TmpInst.addOperand(Inst.getOperand(4));
6530 Inst = TmpInst;
6531 return true;
6532 }
6533
6534 case ARM::VLD4dWB_register_Asm_8:
6535 case ARM::VLD4dWB_register_Asm_16:
6536 case ARM::VLD4dWB_register_Asm_32:
6537 case ARM::VLD4qWB_register_Asm_8:
6538 case ARM::VLD4qWB_register_Asm_16:
6539 case ARM::VLD4qWB_register_Asm_32: {
6540 MCInst TmpInst;
6541 unsigned Spacing;
6542 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6543 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6544 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6545 Spacing));
6546 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6547 Spacing * 2));
6548 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6549 Spacing * 3));
6550 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6551 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6552 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6553 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6554 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6555 TmpInst.addOperand(Inst.getOperand(5));
6556 Inst = TmpInst;
6557 return true;
6558 }
6559
Jim Grosbachd7433e22012-01-23 23:45:44 +00006560 // VST3 multiple 3-element structure instructions.
6561 case ARM::VST3dAsm_8:
6562 case ARM::VST3dAsm_16:
6563 case ARM::VST3dAsm_32:
6564 case ARM::VST3qAsm_8:
6565 case ARM::VST3qAsm_16:
6566 case ARM::VST3qAsm_32: {
6567 MCInst TmpInst;
6568 unsigned Spacing;
6569 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6570 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6571 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6572 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6573 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6574 Spacing));
6575 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6576 Spacing * 2));
6577 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6578 TmpInst.addOperand(Inst.getOperand(4));
6579 Inst = TmpInst;
6580 return true;
6581 }
6582
6583 case ARM::VST3dWB_fixed_Asm_8:
6584 case ARM::VST3dWB_fixed_Asm_16:
6585 case ARM::VST3dWB_fixed_Asm_32:
6586 case ARM::VST3qWB_fixed_Asm_8:
6587 case ARM::VST3qWB_fixed_Asm_16:
6588 case ARM::VST3qWB_fixed_Asm_32: {
6589 MCInst TmpInst;
6590 unsigned Spacing;
6591 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6592 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6593 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6594 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6595 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6596 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6597 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6598 Spacing));
6599 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6600 Spacing * 2));
6601 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6602 TmpInst.addOperand(Inst.getOperand(4));
6603 Inst = TmpInst;
6604 return true;
6605 }
6606
6607 case ARM::VST3dWB_register_Asm_8:
6608 case ARM::VST3dWB_register_Asm_16:
6609 case ARM::VST3dWB_register_Asm_32:
6610 case ARM::VST3qWB_register_Asm_8:
6611 case ARM::VST3qWB_register_Asm_16:
6612 case ARM::VST3qWB_register_Asm_32: {
6613 MCInst TmpInst;
6614 unsigned Spacing;
6615 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6616 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6617 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6618 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6619 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6620 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6621 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6622 Spacing));
6623 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6624 Spacing * 2));
6625 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6626 TmpInst.addOperand(Inst.getOperand(5));
6627 Inst = TmpInst;
6628 return true;
6629 }
6630
Jim Grosbach539aab72012-01-24 00:58:13 +00006631 // VST4 multiple 3-element structure instructions.
6632 case ARM::VST4dAsm_8:
6633 case ARM::VST4dAsm_16:
6634 case ARM::VST4dAsm_32:
6635 case ARM::VST4qAsm_8:
6636 case ARM::VST4qAsm_16:
6637 case ARM::VST4qAsm_32: {
6638 MCInst TmpInst;
6639 unsigned Spacing;
6640 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6641 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6642 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6643 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6644 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6645 Spacing));
6646 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6647 Spacing * 2));
6648 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6649 Spacing * 3));
6650 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6651 TmpInst.addOperand(Inst.getOperand(4));
6652 Inst = TmpInst;
6653 return true;
6654 }
6655
6656 case ARM::VST4dWB_fixed_Asm_8:
6657 case ARM::VST4dWB_fixed_Asm_16:
6658 case ARM::VST4dWB_fixed_Asm_32:
6659 case ARM::VST4qWB_fixed_Asm_8:
6660 case ARM::VST4qWB_fixed_Asm_16:
6661 case ARM::VST4qWB_fixed_Asm_32: {
6662 MCInst TmpInst;
6663 unsigned Spacing;
6664 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6665 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6666 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6667 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6668 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6669 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6670 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6671 Spacing));
6672 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6673 Spacing * 2));
6674 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6675 Spacing * 3));
6676 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6677 TmpInst.addOperand(Inst.getOperand(4));
6678 Inst = TmpInst;
6679 return true;
6680 }
6681
6682 case ARM::VST4dWB_register_Asm_8:
6683 case ARM::VST4dWB_register_Asm_16:
6684 case ARM::VST4dWB_register_Asm_32:
6685 case ARM::VST4qWB_register_Asm_8:
6686 case ARM::VST4qWB_register_Asm_16:
6687 case ARM::VST4qWB_register_Asm_32: {
6688 MCInst TmpInst;
6689 unsigned Spacing;
6690 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6691 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6692 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
6693 TmpInst.addOperand(Inst.getOperand(2)); // alignment
6694 TmpInst.addOperand(Inst.getOperand(3)); // Rm
6695 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6696 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6697 Spacing));
6698 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6699 Spacing * 2));
6700 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6701 Spacing * 3));
6702 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6703 TmpInst.addOperand(Inst.getOperand(5));
6704 Inst = TmpInst;
6705 return true;
6706 }
6707
Jim Grosbacha5378eb2012-04-11 00:15:16 +00006708 // Handle encoding choice for the shift-immediate instructions.
6709 case ARM::t2LSLri:
6710 case ARM::t2LSRri:
6711 case ARM::t2ASRri: {
6712 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6713 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6714 Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
6715 !(static_cast<ARMOperand*>(Operands[3])->isToken() &&
6716 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w")) {
6717 unsigned NewOpc;
6718 switch (Inst.getOpcode()) {
6719 default: llvm_unreachable("unexpected opcode");
6720 case ARM::t2LSLri: NewOpc = ARM::tLSLri; break;
6721 case ARM::t2LSRri: NewOpc = ARM::tLSRri; break;
6722 case ARM::t2ASRri: NewOpc = ARM::tASRri; break;
6723 }
6724 // The Thumb1 operands aren't in the same order. Awesome, eh?
6725 MCInst TmpInst;
6726 TmpInst.setOpcode(NewOpc);
6727 TmpInst.addOperand(Inst.getOperand(0));
6728 TmpInst.addOperand(Inst.getOperand(5));
6729 TmpInst.addOperand(Inst.getOperand(1));
6730 TmpInst.addOperand(Inst.getOperand(2));
6731 TmpInst.addOperand(Inst.getOperand(3));
6732 TmpInst.addOperand(Inst.getOperand(4));
6733 Inst = TmpInst;
6734 return true;
6735 }
6736 return false;
6737 }
6738
Jim Grosbach863d2af2011-12-13 22:45:11 +00006739 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbach2cc5cda2011-12-21 20:54:00 +00006740 case ARM::t2MOVsr:
6741 case ARM::t2MOVSsr: {
6742 // Which instruction to expand to depends on the CCOut operand and
6743 // whether we're in an IT block if the register operands are low
6744 // registers.
6745 bool isNarrow = false;
6746 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6747 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6748 isARMLowRegister(Inst.getOperand(2).getReg()) &&
6749 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
6750 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
6751 isNarrow = true;
6752 MCInst TmpInst;
6753 unsigned newOpc;
6754 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
6755 default: llvm_unreachable("unexpected opcode!");
6756 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
6757 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
6758 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
6759 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
6760 }
6761 TmpInst.setOpcode(newOpc);
6762 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6763 if (isNarrow)
6764 TmpInst.addOperand(MCOperand::CreateReg(
6765 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6766 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6767 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6768 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6769 TmpInst.addOperand(Inst.getOperand(5));
6770 if (!isNarrow)
6771 TmpInst.addOperand(MCOperand::CreateReg(
6772 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
6773 Inst = TmpInst;
6774 return true;
6775 }
Jim Grosbach863d2af2011-12-13 22:45:11 +00006776 case ARM::t2MOVsi:
6777 case ARM::t2MOVSsi: {
6778 // Which instruction to expand to depends on the CCOut operand and
6779 // whether we're in an IT block if the register operands are low
6780 // registers.
6781 bool isNarrow = false;
6782 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
6783 isARMLowRegister(Inst.getOperand(1).getReg()) &&
6784 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
6785 isNarrow = true;
6786 MCInst TmpInst;
6787 unsigned newOpc;
6788 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
6789 default: llvm_unreachable("unexpected opcode!");
6790 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
6791 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
6792 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
6793 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach520dc782011-12-21 21:04:19 +00006794 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006795 }
Benjamin Kramerd9b0b022012-06-02 10:20:22 +00006796 unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
6797 if (Amount == 32) Amount = 0;
Jim Grosbach863d2af2011-12-13 22:45:11 +00006798 TmpInst.setOpcode(newOpc);
6799 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6800 if (isNarrow)
6801 TmpInst.addOperand(MCOperand::CreateReg(
6802 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6803 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach520dc782011-12-21 21:04:19 +00006804 if (newOpc != ARM::t2RRX)
Benjamin Kramerd9b0b022012-06-02 10:20:22 +00006805 TmpInst.addOperand(MCOperand::CreateImm(Amount));
Jim Grosbach863d2af2011-12-13 22:45:11 +00006806 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6807 TmpInst.addOperand(Inst.getOperand(4));
6808 if (!isNarrow)
6809 TmpInst.addOperand(MCOperand::CreateReg(
6810 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
6811 Inst = TmpInst;
6812 return true;
6813 }
6814 // Handle the ARM mode MOV complex aliases.
Jim Grosbach23f22072011-11-16 18:31:45 +00006815 case ARM::ASRr:
6816 case ARM::LSRr:
6817 case ARM::LSLr:
6818 case ARM::RORr: {
6819 ARM_AM::ShiftOpc ShiftTy;
6820 switch(Inst.getOpcode()) {
6821 default: llvm_unreachable("unexpected opcode!");
6822 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
6823 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
6824 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
6825 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
6826 }
Jim Grosbach23f22072011-11-16 18:31:45 +00006827 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
6828 MCInst TmpInst;
6829 TmpInst.setOpcode(ARM::MOVsr);
6830 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6831 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6832 TmpInst.addOperand(Inst.getOperand(2)); // Rm
6833 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6834 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6835 TmpInst.addOperand(Inst.getOperand(4));
6836 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6837 Inst = TmpInst;
6838 return true;
6839 }
Jim Grosbachee10ff82011-11-10 19:18:01 +00006840 case ARM::ASRi:
6841 case ARM::LSRi:
6842 case ARM::LSLi:
6843 case ARM::RORi: {
6844 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006845 switch(Inst.getOpcode()) {
6846 default: llvm_unreachable("unexpected opcode!");
6847 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
6848 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
6849 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
6850 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
6851 }
6852 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach48b368b2011-11-16 19:05:59 +00006853 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachee10ff82011-11-10 19:18:01 +00006854 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
Richard Bartonb56e4112012-04-25 18:00:18 +00006855 // A shift by 32 should be encoded as 0 when permitted
6856 if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr))
6857 Amt = 0;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006858 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006859 MCInst TmpInst;
Jim Grosbachee10ff82011-11-10 19:18:01 +00006860 TmpInst.setOpcode(Opc);
Jim Grosbach71810ab2011-11-10 16:44:55 +00006861 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6862 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachee10ff82011-11-10 19:18:01 +00006863 if (Opc == ARM::MOVsi)
6864 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach71810ab2011-11-10 16:44:55 +00006865 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
6866 TmpInst.addOperand(Inst.getOperand(4));
6867 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
6868 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006869 return true;
Jim Grosbach71810ab2011-11-10 16:44:55 +00006870 }
Jim Grosbach48b368b2011-11-16 19:05:59 +00006871 case ARM::RRXi: {
6872 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
6873 MCInst TmpInst;
6874 TmpInst.setOpcode(ARM::MOVsi);
6875 TmpInst.addOperand(Inst.getOperand(0)); // Rd
6876 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6877 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
6878 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6879 TmpInst.addOperand(Inst.getOperand(3));
6880 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
6881 Inst = TmpInst;
6882 return true;
6883 }
Jim Grosbach0352b462011-11-10 23:58:34 +00006884 case ARM::t2LDMIA_UPD: {
6885 // If this is a load of a single register, then we should use
6886 // a post-indexed LDR instruction instead, per the ARM ARM.
6887 if (Inst.getNumOperands() != 5)
6888 return false;
6889 MCInst TmpInst;
6890 TmpInst.setOpcode(ARM::t2LDR_POST);
6891 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6892 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6893 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6894 TmpInst.addOperand(MCOperand::CreateImm(4));
6895 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6896 TmpInst.addOperand(Inst.getOperand(3));
6897 Inst = TmpInst;
6898 return true;
6899 }
6900 case ARM::t2STMDB_UPD: {
6901 // If this is a store of a single register, then we should use
6902 // a pre-indexed STR instruction instead, per the ARM ARM.
6903 if (Inst.getNumOperands() != 5)
6904 return false;
6905 MCInst TmpInst;
6906 TmpInst.setOpcode(ARM::t2STR_PRE);
6907 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6908 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6909 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6910 TmpInst.addOperand(MCOperand::CreateImm(-4));
6911 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6912 TmpInst.addOperand(Inst.getOperand(3));
6913 Inst = TmpInst;
6914 return true;
6915 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00006916 case ARM::LDMIA_UPD:
6917 // If this is a load of a single register via a 'pop', then we should use
6918 // a post-indexed LDR instruction instead, per the ARM ARM.
6919 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "pop" &&
6920 Inst.getNumOperands() == 5) {
6921 MCInst TmpInst;
6922 TmpInst.setOpcode(ARM::LDR_POST_IMM);
6923 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6924 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6925 TmpInst.addOperand(Inst.getOperand(1)); // Rn
6926 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
6927 TmpInst.addOperand(MCOperand::CreateImm(4));
6928 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6929 TmpInst.addOperand(Inst.getOperand(3));
6930 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00006931 return true;
Jim Grosbachf8fce712011-08-11 17:35:48 +00006932 }
6933 break;
Jim Grosbachf6713912011-08-11 18:07:11 +00006934 case ARM::STMDB_UPD:
6935 // If this is a store of a single register via a 'push', then we should use
6936 // a pre-indexed STR instruction instead, per the ARM ARM.
6937 if (static_cast<ARMOperand*>(Operands[0])->getToken() == "push" &&
6938 Inst.getNumOperands() == 5) {
6939 MCInst TmpInst;
6940 TmpInst.setOpcode(ARM::STR_PRE_IMM);
6941 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
6942 TmpInst.addOperand(Inst.getOperand(4)); // Rt
6943 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
6944 TmpInst.addOperand(MCOperand::CreateImm(-4));
6945 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
6946 TmpInst.addOperand(Inst.getOperand(3));
6947 Inst = TmpInst;
6948 }
6949 break;
Jim Grosbachda847862011-12-05 21:06:26 +00006950 case ARM::t2ADDri12:
6951 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
6952 // mnemonic was used (not "addw"), encoding T3 is preferred.
6953 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "add" ||
6954 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6955 break;
6956 Inst.setOpcode(ARM::t2ADDri);
6957 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6958 break;
6959 case ARM::t2SUBri12:
6960 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
6961 // mnemonic was used (not "subw"), encoding T3 is preferred.
6962 if (static_cast<ARMOperand*>(Operands[0])->getToken() != "sub" ||
6963 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
6964 break;
6965 Inst.setOpcode(ARM::t2SUBri);
6966 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
6967 break;
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006968 case ARM::tADDi8:
Jim Grosbach0f3abd82011-08-31 17:07:33 +00006969 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6970 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6971 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6972 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006973 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006974 Inst.setOpcode(ARM::tADDi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006975 return true;
6976 }
Jim Grosbach89e2aa62011-08-16 23:57:34 +00006977 break;
Jim Grosbachf67e8552011-09-16 22:58:42 +00006978 case ARM::tSUBi8:
6979 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
6980 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
6981 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
6982 // to encoding T1 if <Rd> is omitted."
Jim Grosbachc0164f82012-03-30 16:31:31 +00006983 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachf67e8552011-09-16 22:58:42 +00006984 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbach83ec8772011-11-10 23:42:14 +00006985 return true;
6986 }
Jim Grosbachf67e8552011-09-16 22:58:42 +00006987 break;
Jim Grosbach2d30d942012-03-30 17:20:40 +00006988 case ARM::t2ADDri:
6989 case ARM::t2SUBri: {
6990 // If the destination and first source operand are the same, and
6991 // the flags are compatible with the current IT status, use encoding T2
6992 // instead of T3. For compatibility with the system 'as'. Make sure the
6993 // wide encoding wasn't explicit.
6994 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
Jim Grosbach8f1148b2012-03-30 18:39:43 +00006995 !isARMLowRegister(Inst.getOperand(0).getReg()) ||
Jim Grosbach2d30d942012-03-30 17:20:40 +00006996 (unsigned)Inst.getOperand(2).getImm() > 255 ||
6997 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
6998 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
6999 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7000 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
7001 break;
7002 MCInst TmpInst;
7003 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
7004 ARM::tADDi8 : ARM::tSUBi8);
7005 TmpInst.addOperand(Inst.getOperand(0));
7006 TmpInst.addOperand(Inst.getOperand(5));
7007 TmpInst.addOperand(Inst.getOperand(0));
7008 TmpInst.addOperand(Inst.getOperand(2));
7009 TmpInst.addOperand(Inst.getOperand(3));
7010 TmpInst.addOperand(Inst.getOperand(4));
7011 Inst = TmpInst;
7012 return true;
7013 }
Jim Grosbach927b9df2011-12-05 22:16:39 +00007014 case ARM::t2ADDrr: {
7015 // If the destination and first source operand are the same, and
7016 // there's no setting of the flags, use encoding T2 instead of T3.
7017 // Note that this is only for ADD, not SUB. This mirrors the system
7018 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
7019 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
7020 Inst.getOperand(5).getReg() != 0 ||
Jim Grosbach713c7022011-12-05 22:27:04 +00007021 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7022 static_cast<ARMOperand*>(Operands[3])->getToken() == ".w"))
Jim Grosbach927b9df2011-12-05 22:16:39 +00007023 break;
7024 MCInst TmpInst;
7025 TmpInst.setOpcode(ARM::tADDhirr);
7026 TmpInst.addOperand(Inst.getOperand(0));
7027 TmpInst.addOperand(Inst.getOperand(0));
7028 TmpInst.addOperand(Inst.getOperand(2));
7029 TmpInst.addOperand(Inst.getOperand(3));
7030 TmpInst.addOperand(Inst.getOperand(4));
7031 Inst = TmpInst;
7032 return true;
7033 }
Jim Grosbacha9cc08f2012-04-27 23:51:36 +00007034 case ARM::tADDrSP: {
7035 // If the non-SP source operand and the destination operand are not the
7036 // same, we need to use the 32-bit encoding if it's available.
7037 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
7038 Inst.setOpcode(ARM::t2ADDrr);
7039 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7040 return true;
7041 }
7042 break;
7043 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007044 case ARM::tB:
7045 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007046 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007047 Inst.setOpcode(ARM::tBcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007048 return true;
7049 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007050 break;
7051 case ARM::t2B:
7052 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007053 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007054 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007055 return true;
7056 }
Owen Anderson51f6a7a2011-09-09 21:48:23 +00007057 break;
Jim Grosbachc0755102011-08-31 21:17:31 +00007058 case ARM::t2Bcc:
Jim Grosbacha1109882011-09-02 23:22:08 +00007059 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007060 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbachc0755102011-08-31 21:17:31 +00007061 Inst.setOpcode(ARM::t2B);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007062 return true;
7063 }
Jim Grosbachc0755102011-08-31 21:17:31 +00007064 break;
Jim Grosbach395b4532011-08-17 22:57:40 +00007065 case ARM::tBcc:
7066 // If the conditional is AL, we really want tB.
Jim Grosbach83ec8772011-11-10 23:42:14 +00007067 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbach395b4532011-08-17 22:57:40 +00007068 Inst.setOpcode(ARM::tB);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007069 return true;
7070 }
Jim Grosbach3ce23d32011-08-18 16:08:39 +00007071 break;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007072 case ARM::tLDMIA: {
7073 // If the register list contains any high registers, or if the writeback
7074 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
7075 // instead if we're in Thumb2. Otherwise, this should have generated
7076 // an error in validateInstruction().
7077 unsigned Rn = Inst.getOperand(0).getReg();
7078 bool hasWritebackToken =
7079 (static_cast<ARMOperand*>(Operands[3])->isToken() &&
7080 static_cast<ARMOperand*>(Operands[3])->getToken() == "!");
7081 bool listContainsBase;
7082 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
7083 (!listContainsBase && !hasWritebackToken) ||
7084 (listContainsBase && hasWritebackToken)) {
7085 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7086 assert (isThumbTwo());
7087 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
7088 // If we're switching to the updating version, we need to insert
7089 // the writeback tied operand.
7090 if (hasWritebackToken)
7091 Inst.insert(Inst.begin(),
7092 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007093 return true;
Jim Grosbach76ecc3d2011-09-07 18:05:34 +00007094 }
7095 break;
7096 }
Jim Grosbach8213c962011-09-16 20:50:13 +00007097 case ARM::tSTMIA_UPD: {
7098 // If the register list contains any high registers, we need to use
7099 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7100 // should have generated an error in validateInstruction().
7101 unsigned Rn = Inst.getOperand(0).getReg();
7102 bool listContainsBase;
7103 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
7104 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7105 assert (isThumbTwo());
7106 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbach83ec8772011-11-10 23:42:14 +00007107 return true;
Jim Grosbach8213c962011-09-16 20:50:13 +00007108 }
7109 break;
7110 }
Jim Grosbach54026372011-11-10 23:17:11 +00007111 case ARM::tPOP: {
7112 bool listContainsBase;
7113 // If the register list contains any high registers, we need to use
7114 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7115 // should have generated an error in validateInstruction().
7116 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007117 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007118 assert (isThumbTwo());
7119 Inst.setOpcode(ARM::t2LDMIA_UPD);
7120 // Add the base register and writeback operands.
7121 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7122 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007123 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007124 }
7125 case ARM::tPUSH: {
7126 bool listContainsBase;
7127 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbach83ec8772011-11-10 23:42:14 +00007128 return false;
Jim Grosbach54026372011-11-10 23:17:11 +00007129 assert (isThumbTwo());
7130 Inst.setOpcode(ARM::t2STMDB_UPD);
7131 // Add the base register and writeback operands.
7132 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7133 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbach83ec8772011-11-10 23:42:14 +00007134 return true;
Jim Grosbach54026372011-11-10 23:17:11 +00007135 }
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007136 case ARM::t2MOVi: {
7137 // If we can use the 16-bit encoding and the user didn't explicitly
7138 // request the 32-bit variant, transform it here.
7139 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbachc0164f82012-03-30 16:31:31 +00007140 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbachc2d31642011-09-14 19:12:11 +00007141 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
7142 Inst.getOperand(4).getReg() == ARM::CPSR) ||
7143 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007144 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7145 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7146 // The operands aren't in the same order for tMOVi8...
7147 MCInst TmpInst;
7148 TmpInst.setOpcode(ARM::tMOVi8);
7149 TmpInst.addOperand(Inst.getOperand(0));
7150 TmpInst.addOperand(Inst.getOperand(4));
7151 TmpInst.addOperand(Inst.getOperand(1));
7152 TmpInst.addOperand(Inst.getOperand(2));
7153 TmpInst.addOperand(Inst.getOperand(3));
7154 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007155 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007156 }
7157 break;
7158 }
7159 case ARM::t2MOVr: {
7160 // If we can use the 16-bit encoding and the user didn't explicitly
7161 // request the 32-bit variant, transform it here.
7162 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7163 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7164 Inst.getOperand(2).getImm() == ARMCC::AL &&
7165 Inst.getOperand(4).getReg() == ARM::CPSR &&
7166 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7167 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
7168 // The operands aren't the same for tMOV[S]r... (no cc_out)
7169 MCInst TmpInst;
7170 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
7171 TmpInst.addOperand(Inst.getOperand(0));
7172 TmpInst.addOperand(Inst.getOperand(1));
7173 TmpInst.addOperand(Inst.getOperand(2));
7174 TmpInst.addOperand(Inst.getOperand(3));
7175 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007176 return true;
Jim Grosbach1ad60c22011-09-10 00:15:36 +00007177 }
7178 break;
7179 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007180 case ARM::t2SXTH:
Jim Grosbach50f1c372011-09-20 00:46:54 +00007181 case ARM::t2SXTB:
7182 case ARM::t2UXTH:
7183 case ARM::t2UXTB: {
Jim Grosbach326efe52011-09-19 20:29:33 +00007184 // If we can use the 16-bit encoding and the user didn't explicitly
7185 // request the 32-bit variant, transform it here.
7186 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7187 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7188 Inst.getOperand(2).getImm() == 0 &&
7189 (!static_cast<ARMOperand*>(Operands[2])->isToken() ||
7190 static_cast<ARMOperand*>(Operands[2])->getToken() != ".w")) {
Jim Grosbach50f1c372011-09-20 00:46:54 +00007191 unsigned NewOpc;
7192 switch (Inst.getOpcode()) {
7193 default: llvm_unreachable("Illegal opcode!");
7194 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
7195 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
7196 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
7197 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
7198 }
Jim Grosbach326efe52011-09-19 20:29:33 +00007199 // The operands aren't the same for thumb1 (no rotate operand).
7200 MCInst TmpInst;
7201 TmpInst.setOpcode(NewOpc);
7202 TmpInst.addOperand(Inst.getOperand(0));
7203 TmpInst.addOperand(Inst.getOperand(1));
7204 TmpInst.addOperand(Inst.getOperand(3));
7205 TmpInst.addOperand(Inst.getOperand(4));
7206 Inst = TmpInst;
Jim Grosbach83ec8772011-11-10 23:42:14 +00007207 return true;
Jim Grosbach326efe52011-09-19 20:29:33 +00007208 }
7209 break;
7210 }
Jim Grosbach04b5d932011-12-20 00:59:38 +00007211 case ARM::MOVsi: {
7212 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
Richard Bartonb56e4112012-04-25 18:00:18 +00007213 // rrx shifts and asr/lsr of #32 is encoded as 0
7214 if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr)
7215 return false;
Jim Grosbach04b5d932011-12-20 00:59:38 +00007216 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
7217 // Shifting by zero is accepted as a vanilla 'MOVr'
7218 MCInst TmpInst;
7219 TmpInst.setOpcode(ARM::MOVr);
7220 TmpInst.addOperand(Inst.getOperand(0));
7221 TmpInst.addOperand(Inst.getOperand(1));
7222 TmpInst.addOperand(Inst.getOperand(3));
7223 TmpInst.addOperand(Inst.getOperand(4));
7224 TmpInst.addOperand(Inst.getOperand(5));
7225 Inst = TmpInst;
7226 return true;
7227 }
7228 return false;
7229 }
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007230 case ARM::ANDrsi:
7231 case ARM::ORRrsi:
7232 case ARM::EORrsi:
7233 case ARM::BICrsi:
7234 case ARM::SUBrsi:
7235 case ARM::ADDrsi: {
7236 unsigned newOpc;
7237 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
7238 if (SOpc == ARM_AM::rrx) return false;
7239 switch (Inst.getOpcode()) {
Craig Topperbc219812012-02-07 02:50:20 +00007240 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach8d9550b2011-12-22 18:04:04 +00007241 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
7242 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
7243 case ARM::EORrsi: newOpc = ARM::EORrr; break;
7244 case ARM::BICrsi: newOpc = ARM::BICrr; break;
7245 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
7246 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
7247 }
7248 // If the shift is by zero, use the non-shifted instruction definition.
7249 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0) {
7250 MCInst TmpInst;
7251 TmpInst.setOpcode(newOpc);
7252 TmpInst.addOperand(Inst.getOperand(0));
7253 TmpInst.addOperand(Inst.getOperand(1));
7254 TmpInst.addOperand(Inst.getOperand(2));
7255 TmpInst.addOperand(Inst.getOperand(4));
7256 TmpInst.addOperand(Inst.getOperand(5));
7257 TmpInst.addOperand(Inst.getOperand(6));
7258 Inst = TmpInst;
7259 return true;
7260 }
7261 return false;
7262 }
Jim Grosbach74423e32012-01-25 19:52:01 +00007263 case ARM::ITasm:
Jim Grosbach89df9962011-08-26 21:43:41 +00007264 case ARM::t2IT: {
7265 // The mask bits for all but the first condition are represented as
7266 // the low bit of the condition code value implies 't'. We currently
7267 // always have 1 implies 't', so XOR toggle the bits if the low bit
Richard Barton4d2f0772012-04-27 08:42:59 +00007268 // of the condition code is zero.
Jim Grosbach89df9962011-08-26 21:43:41 +00007269 MCOperand &MO = Inst.getOperand(1);
7270 unsigned Mask = MO.getImm();
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007271 unsigned OrigMask = Mask;
7272 unsigned TZ = CountTrailingZeros_32(Mask);
Jim Grosbach89df9962011-08-26 21:43:41 +00007273 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach89df9962011-08-26 21:43:41 +00007274 assert(Mask && TZ <= 3 && "illegal IT mask value!");
7275 for (unsigned i = 3; i != TZ; --i)
7276 Mask ^= 1 << i;
Richard Barton4d2f0772012-04-27 08:42:59 +00007277 }
Jim Grosbach89df9962011-08-26 21:43:41 +00007278 MO.setImm(Mask);
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007279
7280 // Set up the IT block state according to the IT instruction we just
7281 // matched.
7282 assert(!inITBlock() && "nested IT blocks?!");
7283 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
7284 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
7285 ITState.CurPosition = 0;
7286 ITState.FirstCond = true;
Jim Grosbach89df9962011-08-26 21:43:41 +00007287 break;
7288 }
Jim Grosbachf8fce712011-08-11 17:35:48 +00007289 }
Jim Grosbach83ec8772011-11-10 23:42:14 +00007290 return false;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007291}
7292
Jim Grosbach47a0d522011-08-16 20:45:50 +00007293unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
7294 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
7295 // suffix depending on whether they're in an IT block or not.
Jim Grosbach194bd892011-08-16 22:20:01 +00007296 unsigned Opc = Inst.getOpcode();
Benjamin Kramer1a2f9882011-10-22 16:50:00 +00007297 const MCInstrDesc &MCID = getInstDesc(Opc);
Jim Grosbach47a0d522011-08-16 20:45:50 +00007298 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
7299 assert(MCID.hasOptionalDef() &&
7300 "optionally flag setting instruction missing optional def operand");
7301 assert(MCID.NumOperands == Inst.getNumOperands() &&
7302 "operand count mismatch!");
7303 // Find the optional-def operand (cc_out).
7304 unsigned OpNo;
7305 for (OpNo = 0;
7306 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
7307 ++OpNo)
7308 ;
7309 // If we're parsing Thumb1, reject it completely.
7310 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
7311 return Match_MnemonicFail;
7312 // If we're parsing Thumb2, which form is legal depends on whether we're
7313 // in an IT block.
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007314 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
7315 !inITBlock())
Jim Grosbach47a0d522011-08-16 20:45:50 +00007316 return Match_RequiresITBlock;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007317 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
7318 inITBlock())
7319 return Match_RequiresNotITBlock;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007320 }
Jim Grosbach194bd892011-08-16 22:20:01 +00007321 // Some high-register supporting Thumb1 encodings only allow both registers
7322 // to be from r0-r7 when in Thumb2.
7323 else if (Opc == ARM::tADDhirr && isThumbOne() &&
7324 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7325 isARMLowRegister(Inst.getOperand(2).getReg()))
7326 return Match_RequiresThumb2;
7327 // Others only require ARMv6 or later.
Jim Grosbach4ec6e882011-08-19 20:46:54 +00007328 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbach194bd892011-08-16 22:20:01 +00007329 isARMLowRegister(Inst.getOperand(0).getReg()) &&
7330 isARMLowRegister(Inst.getOperand(1).getReg()))
7331 return Match_RequiresV6;
Jim Grosbach47a0d522011-08-16 20:45:50 +00007332 return Match_Success;
7333}
7334
Jim Grosbach14ce6fa2012-04-24 22:40:08 +00007335static const char *getSubtargetFeatureName(unsigned Val);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007336bool ARMAsmParser::
7337MatchAndEmitInstruction(SMLoc IDLoc,
7338 SmallVectorImpl<MCParsedAsmOperand*> &Operands,
7339 MCStreamer &Out) {
7340 MCInst Inst;
7341 unsigned ErrorInfo;
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007342 unsigned MatchResult;
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007343 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo);
Kevin Enderby193c3ac2010-12-09 19:19:43 +00007344 switch (MatchResult) {
Jim Grosbach19cb7f42011-08-15 23:03:29 +00007345 default: break;
Chris Lattnere73d4f82010-10-28 21:41:58 +00007346 case Match_Success:
Jim Grosbach189610f2011-07-26 18:25:39 +00007347 // Context sensitive operand constraints aren't handled by the matcher,
7348 // so check them here.
Jim Grosbacha1109882011-09-02 23:22:08 +00007349 if (validateInstruction(Inst, Operands)) {
7350 // Still progress the IT block, otherwise one wrong condition causes
7351 // nasty cascading errors.
7352 forwardITPosition();
Jim Grosbach189610f2011-07-26 18:25:39 +00007353 return true;
Jim Grosbacha1109882011-09-02 23:22:08 +00007354 }
Jim Grosbach189610f2011-07-26 18:25:39 +00007355
Jim Grosbachf8fce712011-08-11 17:35:48 +00007356 // Some instructions need post-processing to, for example, tweak which
Jim Grosbach83ec8772011-11-10 23:42:14 +00007357 // encoding is selected. Loop on it while changes happen so the
7358 // individual transformations can chain off each other. E.g.,
7359 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
7360 while (processInstruction(Inst, Operands))
7361 ;
Jim Grosbachf8fce712011-08-11 17:35:48 +00007362
Jim Grosbacha1109882011-09-02 23:22:08 +00007363 // Only move forward at the very end so that everything in validate
7364 // and process gets a consistent answer about whether we're in an IT
7365 // block.
7366 forwardITPosition();
7367
Jim Grosbach74423e32012-01-25 19:52:01 +00007368 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
7369 // doesn't actually encode.
7370 if (Inst.getOpcode() == ARM::ITasm)
7371 return false;
7372
Jim Grosbach42e6bd32012-01-26 23:20:15 +00007373 Inst.setLoc(IDLoc);
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007374 Out.EmitInstruction(Inst);
7375 return false;
Jim Grosbach14ce6fa2012-04-24 22:40:08 +00007376 case Match_MissingFeature: {
7377 assert(ErrorInfo && "Unknown missing feature!");
7378 // Special case the error message for the very common case where only
7379 // a single subtarget feature is missing (Thumb vs. ARM, e.g.).
7380 std::string Msg = "instruction requires:";
7381 unsigned Mask = 1;
7382 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
7383 if (ErrorInfo & Mask) {
7384 Msg += " ";
7385 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
7386 }
7387 Mask <<= 1;
7388 }
7389 return Error(IDLoc, Msg);
7390 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007391 case Match_InvalidOperand: {
7392 SMLoc ErrorLoc = IDLoc;
7393 if (ErrorInfo != ~0U) {
7394 if (ErrorInfo >= Operands.size())
7395 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach16c74252010-10-29 14:46:02 +00007396
Chris Lattnere73d4f82010-10-28 21:41:58 +00007397 ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7398 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7399 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007400
Chris Lattnere73d4f82010-10-28 21:41:58 +00007401 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007402 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007403 case Match_MnemonicFail:
Benjamin Kramer362a05a2012-04-15 17:04:27 +00007404 return Error(IDLoc, "invalid instruction",
7405 ((ARMOperand*)Operands[0])->getLocRange());
Daniel Dunbarb4129152011-02-04 17:12:23 +00007406 case Match_ConversionFail:
Benjamin Kramerd9b0b022012-06-02 10:20:22 +00007407 // The converter function will have already emitted a diagnostic.
Jim Grosbach88ae2bc2011-08-19 22:07:46 +00007408 return true;
Jim Grosbachf8e1e3e2011-08-29 22:24:09 +00007409 case Match_RequiresNotITBlock:
7410 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach47a0d522011-08-16 20:45:50 +00007411 case Match_RequiresITBlock:
7412 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbach194bd892011-08-16 22:20:01 +00007413 case Match_RequiresV6:
7414 return Error(IDLoc, "instruction variant requires ARMv6 or later");
7415 case Match_RequiresThumb2:
7416 return Error(IDLoc, "instruction variant requires Thumb2");
Jim Grosbach70c9bf32012-06-22 23:56:48 +00007417 case Match_ImmRange0_15: {
7418 SMLoc ErrorLoc = ((ARMOperand*)Operands[ErrorInfo])->getStartLoc();
7419 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
7420 return Error(ErrorLoc, "immediate operand must be in the range [0,15]");
7421 }
Chris Lattnere73d4f82010-10-28 21:41:58 +00007422 }
Jim Grosbach16c74252010-10-29 14:46:02 +00007423
Eric Christopherc223e2b2010-10-29 09:26:59 +00007424 llvm_unreachable("Implement any new match types added!");
Chris Lattnerfa42fad2010-10-28 21:28:01 +00007425}
7426
Jim Grosbach1355cf12011-07-26 17:10:22 +00007427/// parseDirective parses the arm specific directives
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007428bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
7429 StringRef IDVal = DirectiveID.getIdentifier();
7430 if (IDVal == ".word")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007431 return parseDirectiveWord(4, DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007432 else if (IDVal == ".thumb")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007433 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach9a70df92011-12-07 18:04:19 +00007434 else if (IDVal == ".arm")
7435 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007436 else if (IDVal == ".thumb_func")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007437 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007438 else if (IDVal == ".code")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007439 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby515d5092009-10-15 20:48:48 +00007440 else if (IDVal == ".syntax")
Jim Grosbach1355cf12011-07-26 17:10:22 +00007441 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbacha39cda72011-12-14 02:16:11 +00007442 else if (IDVal == ".unreq")
7443 return parseDirectiveUnreq(DirectiveID.getLoc());
Jason W Kimd7c9e082011-12-20 17:38:12 +00007444 else if (IDVal == ".arch")
7445 return parseDirectiveArch(DirectiveID.getLoc());
7446 else if (IDVal == ".eabi_attribute")
7447 return parseDirectiveEabiAttr(DirectiveID.getLoc());
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007448 return true;
7449}
7450
Jim Grosbach1355cf12011-07-26 17:10:22 +00007451/// parseDirectiveWord
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007452/// ::= .word [ expression (, expression)* ]
Jim Grosbach1355cf12011-07-26 17:10:22 +00007453bool ARMAsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007454 if (getLexer().isNot(AsmToken::EndOfStatement)) {
7455 for (;;) {
7456 const MCExpr *Value;
7457 if (getParser().ParseExpression(Value))
7458 return true;
7459
Chris Lattneraaec2052010-01-19 19:46:13 +00007460 getParser().getStreamer().EmitValue(Value, Size, 0/*addrspace*/);
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007461
7462 if (getLexer().is(AsmToken::EndOfStatement))
7463 break;
Jim Grosbach16c74252010-10-29 14:46:02 +00007464
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007465 // FIXME: Improve diagnostic.
7466 if (getLexer().isNot(AsmToken::Comma))
7467 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007468 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007469 }
7470 }
7471
Sean Callananb9a25b72010-01-19 20:27:46 +00007472 Parser.Lex();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007473 return false;
7474}
7475
Jim Grosbach1355cf12011-07-26 17:10:22 +00007476/// parseDirectiveThumb
Kevin Enderby515d5092009-10-15 20:48:48 +00007477/// ::= .thumb
Jim Grosbach1355cf12011-07-26 17:10:22 +00007478bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Kevin Enderby515d5092009-10-15 20:48:48 +00007479 if (getLexer().isNot(AsmToken::EndOfStatement))
7480 return Error(L, "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007481 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007482
Jim Grosbach9a70df92011-12-07 18:04:19 +00007483 if (!isThumb())
7484 SwitchMode();
7485 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
7486 return false;
7487}
7488
7489/// parseDirectiveARM
7490/// ::= .arm
7491bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
7492 if (getLexer().isNot(AsmToken::EndOfStatement))
7493 return Error(L, "unexpected token in directive");
7494 Parser.Lex();
7495
7496 if (isThumb())
7497 SwitchMode();
7498 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby515d5092009-10-15 20:48:48 +00007499 return false;
7500}
7501
Jim Grosbach1355cf12011-07-26 17:10:22 +00007502/// parseDirectiveThumbFunc
Kevin Enderby515d5092009-10-15 20:48:48 +00007503/// ::= .thumbfunc symbol_name
Jim Grosbach1355cf12011-07-26 17:10:22 +00007504bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Rafael Espindola64695402011-05-16 16:17:21 +00007505 const MCAsmInfo &MAI = getParser().getStreamer().getContext().getAsmInfo();
7506 bool isMachO = MAI.hasSubsectionsViaSymbols();
7507 StringRef Name;
Jim Grosbachde4d8392011-12-21 22:30:16 +00007508 bool needFuncName = true;
Rafael Espindola64695402011-05-16 16:17:21 +00007509
Jim Grosbachde4d8392011-12-21 22:30:16 +00007510 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindola64695402011-05-16 16:17:21 +00007511 // ELF doesn't
7512 if (isMachO) {
7513 const AsmToken &Tok = Parser.getTok();
Jim Grosbachde4d8392011-12-21 22:30:16 +00007514 if (Tok.isNot(AsmToken::EndOfStatement)) {
7515 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String))
7516 return Error(L, "unexpected token in .thumb_func directive");
7517 Name = Tok.getIdentifier();
7518 Parser.Lex(); // Consume the identifier token.
7519 needFuncName = false;
7520 }
Rafael Espindola64695402011-05-16 16:17:21 +00007521 }
7522
Jim Grosbachde4d8392011-12-21 22:30:16 +00007523 if (getLexer().isNot(AsmToken::EndOfStatement))
Kevin Enderby515d5092009-10-15 20:48:48 +00007524 return Error(L, "unexpected token in directive");
Jim Grosbachde4d8392011-12-21 22:30:16 +00007525
7526 // Eat the end of statement and any blank lines that follow.
7527 while (getLexer().is(AsmToken::EndOfStatement))
7528 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007529
Rafael Espindola64695402011-05-16 16:17:21 +00007530 // FIXME: assuming function name will be the line following .thumb_func
Jim Grosbachde4d8392011-12-21 22:30:16 +00007531 // We really should be checking the next symbol definition even if there's
7532 // stuff in between.
7533 if (needFuncName) {
Jim Grosbachd475f862011-11-10 20:48:53 +00007534 Name = Parser.getTok().getIdentifier();
Rafael Espindola64695402011-05-16 16:17:21 +00007535 }
7536
Jim Grosbach642fc9c2010-11-05 22:33:53 +00007537 // Mark symbol as a thumb symbol.
7538 MCSymbol *Func = getParser().getContext().GetOrCreateSymbol(Name);
7539 getParser().getStreamer().EmitThumbFunc(Func);
Kevin Enderby515d5092009-10-15 20:48:48 +00007540 return false;
7541}
7542
Jim Grosbach1355cf12011-07-26 17:10:22 +00007543/// parseDirectiveSyntax
Kevin Enderby515d5092009-10-15 20:48:48 +00007544/// ::= .syntax unified | divided
Jim Grosbach1355cf12011-07-26 17:10:22 +00007545bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007546 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007547 if (Tok.isNot(AsmToken::Identifier))
7548 return Error(L, "unexpected token in .syntax directive");
Benjamin Kramer38e59892010-07-14 22:38:02 +00007549 StringRef Mode = Tok.getString();
Duncan Sands58c86912010-06-29 13:04:35 +00007550 if (Mode == "unified" || Mode == "UNIFIED")
Sean Callananb9a25b72010-01-19 20:27:46 +00007551 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007552 else if (Mode == "divided" || Mode == "DIVIDED")
Kevin Enderby9e56fb12011-01-27 23:22:36 +00007553 return Error(L, "'.syntax divided' arm asssembly not supported");
Kevin Enderby515d5092009-10-15 20:48:48 +00007554 else
7555 return Error(L, "unrecognized syntax mode in .syntax directive");
7556
7557 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007558 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007559 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007560
7561 // TODO tell the MC streamer the mode
7562 // getParser().getStreamer().Emit???();
7563 return false;
7564}
7565
Jim Grosbach1355cf12011-07-26 17:10:22 +00007566/// parseDirectiveCode
Kevin Enderby515d5092009-10-15 20:48:48 +00007567/// ::= .code 16 | 32
Jim Grosbach1355cf12011-07-26 17:10:22 +00007568bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan18b83232010-01-19 21:44:56 +00007569 const AsmToken &Tok = Parser.getTok();
Kevin Enderby515d5092009-10-15 20:48:48 +00007570 if (Tok.isNot(AsmToken::Integer))
7571 return Error(L, "unexpected token in .code directive");
Sean Callanan18b83232010-01-19 21:44:56 +00007572 int64_t Val = Parser.getTok().getIntVal();
Duncan Sands58c86912010-06-29 13:04:35 +00007573 if (Val == 16)
Sean Callananb9a25b72010-01-19 20:27:46 +00007574 Parser.Lex();
Duncan Sands58c86912010-06-29 13:04:35 +00007575 else if (Val == 32)
Sean Callananb9a25b72010-01-19 20:27:46 +00007576 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007577 else
7578 return Error(L, "invalid operand to .code directive");
7579
7580 if (getLexer().isNot(AsmToken::EndOfStatement))
Sean Callanan18b83232010-01-19 21:44:56 +00007581 return Error(Parser.getTok().getLoc(), "unexpected token in directive");
Sean Callananb9a25b72010-01-19 20:27:46 +00007582 Parser.Lex();
Kevin Enderby515d5092009-10-15 20:48:48 +00007583
Evan Cheng32869202011-07-08 22:36:29 +00007584 if (Val == 16) {
Jim Grosbach98447da2011-09-06 18:46:23 +00007585 if (!isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007586 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007587 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng32869202011-07-08 22:36:29 +00007588 } else {
Jim Grosbach98447da2011-09-06 18:46:23 +00007589 if (isThumb())
Evan Chengffc0e732011-07-09 05:47:46 +00007590 SwitchMode();
Jim Grosbach98447da2011-09-06 18:46:23 +00007591 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Chengeb0caa12011-07-08 22:49:55 +00007592 }
Jim Grosbach2a301702010-11-05 22:40:53 +00007593
Kevin Enderby515d5092009-10-15 20:48:48 +00007594 return false;
7595}
7596
Jim Grosbacha39cda72011-12-14 02:16:11 +00007597/// parseDirectiveReq
7598/// ::= name .req registername
7599bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
7600 Parser.Lex(); // Eat the '.req' token.
7601 unsigned Reg;
7602 SMLoc SRegLoc, ERegLoc;
7603 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
7604 Parser.EatToEndOfStatement();
7605 return Error(SRegLoc, "register name expected");
7606 }
7607
7608 // Shouldn't be anything else.
7609 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
7610 Parser.EatToEndOfStatement();
7611 return Error(Parser.getTok().getLoc(),
7612 "unexpected input in .req directive.");
7613 }
7614
7615 Parser.Lex(); // Consume the EndOfStatement
7616
7617 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg)
7618 return Error(SRegLoc, "redefinition of '" + Name +
7619 "' does not match original.");
7620
7621 return false;
7622}
7623
7624/// parseDirectiveUneq
7625/// ::= .unreq registername
7626bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
7627 if (Parser.getTok().isNot(AsmToken::Identifier)) {
7628 Parser.EatToEndOfStatement();
7629 return Error(L, "unexpected input in .unreq directive.");
7630 }
7631 RegisterReqs.erase(Parser.getTok().getIdentifier());
7632 Parser.Lex(); // Eat the identifier.
7633 return false;
7634}
7635
Jason W Kimd7c9e082011-12-20 17:38:12 +00007636/// parseDirectiveArch
7637/// ::= .arch token
7638bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
7639 return true;
7640}
7641
7642/// parseDirectiveEabiAttr
7643/// ::= .eabi_attribute int, int
7644bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
7645 return true;
7646}
7647
Sean Callanan90b70972010-04-07 20:29:34 +00007648extern "C" void LLVMInitializeARMAsmLexer();
7649
Kevin Enderby9c41fa82009-10-30 22:55:57 +00007650/// Force static initialization.
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007651extern "C" void LLVMInitializeARMAsmParser() {
Evan Cheng94b95502011-07-26 00:24:13 +00007652 RegisterMCAsmParser<ARMAsmParser> X(TheARMTarget);
7653 RegisterMCAsmParser<ARMAsmParser> Y(TheThumbTarget);
Sean Callanan90b70972010-04-07 20:29:34 +00007654 LLVMInitializeARMAsmLexer();
Kevin Enderbyca9c42c2009-09-15 00:27:25 +00007655}
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007656
Chris Lattner0692ee62010-09-06 19:11:01 +00007657#define GET_REGISTER_MATCHER
Craig Topper8030e1a2012-04-25 06:56:34 +00007658#define GET_SUBTARGET_FEATURE_NAME
Chris Lattner0692ee62010-09-06 19:11:01 +00007659#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar3483aca2010-08-11 05:24:50 +00007660#include "ARMGenAsmMatcher.inc"