blob: 682ab9374f5f0e3a30839ac7c3b055592e3e0f90 [file] [log] [blame]
Kevin Enderbyccab3172009-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
Logan Chien8cbb80d2013-10-28 17:51:12 +000010#include "ARMFPUName.h"
Amara Emerson52cfb6a2013-10-03 09:31:51 +000011#include "ARMFeatures.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000012#include "MCTargetDesc/ARMAddressingModes.h"
Logan Chien439e8f92013-12-11 17:16:25 +000013#include "MCTargetDesc/ARMArchName.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000014#include "MCTargetDesc/ARMBaseInfo.h"
15#include "MCTargetDesc/ARMMCExpr.h"
Evan Cheng11424442011-07-26 00:24:13 +000016#include "llvm/ADT/STLExtras.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000017#include "llvm/ADT/SmallVector.h"
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +000018#include "llvm/ADT/StringExtras.h"
Daniel Dunbar188b47b2010-08-11 06:37:20 +000019#include "llvm/ADT/StringSwitch.h"
Chris Lattner00646cf2010-01-22 01:44:57 +000020#include "llvm/ADT/Twine.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000021#include "llvm/MC/MCAsmInfo.h"
Jack Carter718da0b2013-01-30 02:24:33 +000022#include "llvm/MC/MCAssembler.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000023#include "llvm/MC/MCContext.h"
Tim Northoverd6a729b2014-01-06 14:28:05 +000024#include "llvm/MC/MCDisassembler.h"
Jack Carter718da0b2013-01-30 02:24:33 +000025#include "llvm/MC/MCELFStreamer.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000026#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
28#include "llvm/MC/MCInstrDesc.h"
Joey Gouly0e76fa72013-09-12 10:28:05 +000029#include "llvm/MC/MCInstrInfo.h"
Saleem Abdulrasool39f773f2014-03-20 06:05:33 +000030#include "llvm/MC/MCObjectFileInfo.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000031#include "llvm/MC/MCParser/MCAsmLexer.h"
32#include "llvm/MC/MCParser/MCAsmParser.h"
33#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
34#include "llvm/MC/MCRegisterInfo.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000035#include "llvm/MC/MCSection.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000036#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
David Peixottoe407d092013-12-19 18:12:36 +000038#include "llvm/MC/MCSymbol.h"
Chandler Carruth8a8cd2b2014-01-07 11:48:04 +000039#include "llvm/MC/MCTargetAsmParser.h"
Saleem Abdulrasool278a9f42014-01-19 08:25:27 +000040#include "llvm/Support/ARMBuildAttributes.h"
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +000041#include "llvm/Support/ARMEHABI.h"
Saleem Abdulrasool39f773f2014-03-20 06:05:33 +000042#include "llvm/Support/COFF.h"
Tim Northoverd6a729b2014-01-06 14:28:05 +000043#include "llvm/Support/Debug.h"
Jack Carter718da0b2013-01-30 02:24:33 +000044#include "llvm/Support/ELF.h"
Chandler Carruthed0881b2012-12-03 16:50:05 +000045#include "llvm/Support/MathExtras.h"
46#include "llvm/Support/SourceMgr.h"
47#include "llvm/Support/TargetRegistry.h"
48#include "llvm/Support/raw_ostream.h"
Evan Cheng4d1ca962011-07-08 01:53:10 +000049
Kevin Enderbyccab3172009-09-15 00:27:25 +000050using namespace llvm;
51
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +000052namespace {
Bill Wendlingee7f1f92010-11-06 21:42:12 +000053
54class ARMOperand;
Jim Grosbach624bcc72010-10-29 14:46:02 +000055
Jim Grosbach04945c42011-12-02 00:35:16 +000056enum VectorLaneTy { NoLanes, AllLanes, IndexedLane };
Jim Grosbachcd6f5e72011-11-30 01:09:44 +000057
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +000058class UnwindContext {
59 MCAsmParser &Parser;
60
Saleem Abdulrasool4cb063c2014-01-07 02:29:00 +000061 typedef SmallVector<SMLoc, 4> Locs;
62
63 Locs FnStartLocs;
64 Locs CantUnwindLocs;
65 Locs PersonalityLocs;
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +000066 Locs PersonalityIndexLocs;
Saleem Abdulrasool4cb063c2014-01-07 02:29:00 +000067 Locs HandlerDataLocs;
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +000068 int FPReg;
69
70public:
Saleem Abdulrasool5d962d32014-01-30 04:46:24 +000071 UnwindContext(MCAsmParser &P) : Parser(P), FPReg(ARM::SP) {}
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +000072
Saleem Abdulrasool4cb063c2014-01-07 02:29:00 +000073 bool hasFnStart() const { return !FnStartLocs.empty(); }
74 bool cantUnwind() const { return !CantUnwindLocs.empty(); }
75 bool hasHandlerData() const { return !HandlerDataLocs.empty(); }
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +000076 bool hasPersonality() const {
77 return !(PersonalityLocs.empty() && PersonalityIndexLocs.empty());
78 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +000079
Saleem Abdulrasool4cb063c2014-01-07 02:29:00 +000080 void recordFnStart(SMLoc L) { FnStartLocs.push_back(L); }
81 void recordCantUnwind(SMLoc L) { CantUnwindLocs.push_back(L); }
82 void recordPersonality(SMLoc L) { PersonalityLocs.push_back(L); }
83 void recordHandlerData(SMLoc L) { HandlerDataLocs.push_back(L); }
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +000084 void recordPersonalityIndex(SMLoc L) { PersonalityIndexLocs.push_back(L); }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +000085
86 void saveFPReg(int Reg) { FPReg = Reg; }
87 int getFPReg() const { return FPReg; }
88
89 void emitFnStartLocNotes() const {
Saleem Abdulrasool4cb063c2014-01-07 02:29:00 +000090 for (Locs::const_iterator FI = FnStartLocs.begin(), FE = FnStartLocs.end();
91 FI != FE; ++FI)
92 Parser.Note(*FI, ".fnstart was specified here");
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +000093 }
94 void emitCantUnwindLocNotes() const {
Saleem Abdulrasool4cb063c2014-01-07 02:29:00 +000095 for (Locs::const_iterator UI = CantUnwindLocs.begin(),
96 UE = CantUnwindLocs.end(); UI != UE; ++UI)
97 Parser.Note(*UI, ".cantunwind was specified here");
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +000098 }
99 void emitHandlerDataLocNotes() const {
Saleem Abdulrasool4cb063c2014-01-07 02:29:00 +0000100 for (Locs::const_iterator HI = HandlerDataLocs.begin(),
101 HE = HandlerDataLocs.end(); HI != HE; ++HI)
102 Parser.Note(*HI, ".handlerdata was specified here");
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +0000103 }
104 void emitPersonalityLocNotes() const {
Saleem Abdulrasool4cb063c2014-01-07 02:29:00 +0000105 for (Locs::const_iterator PI = PersonalityLocs.begin(),
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +0000106 PE = PersonalityLocs.end(),
107 PII = PersonalityIndexLocs.begin(),
108 PIE = PersonalityIndexLocs.end();
109 PI != PE || PII != PIE;) {
110 if (PI != PE && (PII == PIE || PI->getPointer() < PII->getPointer()))
111 Parser.Note(*PI++, ".personality was specified here");
112 else if (PII != PIE && (PI == PE || PII->getPointer() < PI->getPointer()))
113 Parser.Note(*PII++, ".personalityindex was specified here");
114 else
115 llvm_unreachable(".personality and .personalityindex cannot be "
116 "at the same location");
117 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +0000118 }
119
120 void reset() {
Saleem Abdulrasool4cb063c2014-01-07 02:29:00 +0000121 FnStartLocs = Locs();
122 CantUnwindLocs = Locs();
123 PersonalityLocs = Locs();
124 HandlerDataLocs = Locs();
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +0000125 PersonalityIndexLocs = Locs();
Saleem Abdulrasool5d962d32014-01-30 04:46:24 +0000126 FPReg = ARM::SP;
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +0000127 }
128};
129
Evan Cheng11424442011-07-26 00:24:13 +0000130class ARMAsmParser : public MCTargetAsmParser {
Evan Cheng91111d22011-07-09 05:47:46 +0000131 MCSubtargetInfo &STI;
Kevin Enderbyccab3172009-09-15 00:27:25 +0000132 MCAsmParser &Parser;
Joey Gouly0e76fa72013-09-12 10:28:05 +0000133 const MCInstrInfo &MII;
Jim Grosbachc988e0c2012-03-05 19:33:30 +0000134 const MCRegisterInfo *MRI;
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +0000135 UnwindContext UC;
David Peixottoe407d092013-12-19 18:12:36 +0000136
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000137 ARMTargetStreamer &getTargetStreamer() {
Saleem Abdulrasoolbfdfb142014-09-18 04:28:29 +0000138 assert(getParser().getStreamer().getTargetStreamer() &&
139 "do not have a target streamer");
Rafael Espindola4a1a3602014-01-14 01:21:46 +0000140 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
Rafael Espindolaa17151a2013-10-08 13:08:17 +0000141 return static_cast<ARMTargetStreamer &>(TS);
142 }
143
Jim Grosbachab5830e2011-12-14 02:16:11 +0000144 // Map of register aliases registers via the .req directive.
145 StringMap<unsigned> RegisterReqs;
146
Tim Northover1744d0a2013-10-25 12:49:50 +0000147 bool NextSymbolIsThumb;
148
Jim Grosbached16ec42011-08-29 22:24:09 +0000149 struct {
150 ARMCC::CondCodes Cond; // Condition for IT block.
151 unsigned Mask:4; // Condition mask for instructions.
152 // Starting at first 1 (from lsb).
153 // '1' condition as indicated in IT.
154 // '0' inverse of condition (else).
155 // Count of instructions in IT block is
156 // 4 - trailingzeroes(mask)
157
158 bool FirstCond; // Explicit flag for when we're parsing the
159 // First instruction in the IT block. It's
160 // implied in the mask, so needs special
161 // handling.
162
163 unsigned CurPosition; // Current position in parsing of IT
164 // block. In range [0,3]. Initialized
165 // according to count of instructions in block.
166 // ~0U if no active IT block.
167 } ITState;
168 bool inITBlock() { return ITState.CurPosition != ~0U;}
Jim Grosbacha0d34d32011-09-02 23:22:08 +0000169 void forwardITPosition() {
170 if (!inITBlock()) return;
171 // Move to the next instruction in the IT block, if there is one. If not,
172 // mark the block as done.
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +0000173 unsigned TZ = countTrailingZeros(ITState.Mask);
Jim Grosbacha0d34d32011-09-02 23:22:08 +0000174 if (++ITState.CurPosition == 5 - TZ)
175 ITState.CurPosition = ~0U; // Done with the IT block after this.
176 }
Jim Grosbached16ec42011-08-29 22:24:09 +0000177
178
Kevin Enderbyccab3172009-09-15 00:27:25 +0000179 MCAsmParser &getParser() const { return Parser; }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000180 MCAsmLexer &getLexer() const { return Parser.getLexer(); }
181
Saleem Abdulrasool69c7caf2014-01-07 02:28:31 +0000182 void Note(SMLoc L, const Twine &Msg, ArrayRef<SMRange> Ranges = None) {
183 return Parser.Note(L, Msg, Ranges);
184 }
Benjamin Kramer673824b2012-04-15 17:04:27 +0000185 bool Warning(SMLoc L, const Twine &Msg,
Dmitri Gribenko3238fb72013-05-05 00:40:33 +0000186 ArrayRef<SMRange> Ranges = None) {
Benjamin Kramer673824b2012-04-15 17:04:27 +0000187 return Parser.Warning(L, Msg, Ranges);
188 }
189 bool Error(SMLoc L, const Twine &Msg,
Dmitri Gribenko3238fb72013-05-05 00:40:33 +0000190 ArrayRef<SMRange> Ranges = None) {
Benjamin Kramer673824b2012-04-15 17:04:27 +0000191 return Parser.Error(L, Msg, Ranges);
192 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000193
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000194 int tryParseRegister();
David Blaikie960ea3f2014-06-08 16:18:35 +0000195 bool tryParseRegisterWithWriteBack(OperandVector &);
196 int tryParseShiftRegister(OperandVector &);
197 bool parseRegisterList(OperandVector &);
198 bool parseMemory(OperandVector &);
199 bool parseOperand(OperandVector &, StringRef Mnemonic);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000200 bool parsePrefix(ARMMCExpr::VariantKind &RefKind);
Jim Grosbachd3595712011-08-03 23:50:40 +0000201 bool parseMemRegOffsetShift(ARM_AM::ShiftOpc &ShiftType,
202 unsigned &ShiftAmount);
Saleem Abdulrasool38976512014-02-23 06:22:09 +0000203 bool parseLiteralValues(unsigned Size, SMLoc L);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000204 bool parseDirectiveThumb(SMLoc L);
Jim Grosbach7f882392011-12-07 18:04:19 +0000205 bool parseDirectiveARM(SMLoc L);
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000206 bool parseDirectiveThumbFunc(SMLoc L);
207 bool parseDirectiveCode(SMLoc L);
208 bool parseDirectiveSyntax(SMLoc L);
Jim Grosbachab5830e2011-12-14 02:16:11 +0000209 bool parseDirectiveReq(StringRef Name, SMLoc L);
210 bool parseDirectiveUnreq(SMLoc L);
Jason W Kim135d2442011-12-20 17:38:12 +0000211 bool parseDirectiveArch(SMLoc L);
212 bool parseDirectiveEabiAttr(SMLoc L);
Logan Chien8cbb80d2013-10-28 17:51:12 +0000213 bool parseDirectiveCPU(SMLoc L);
214 bool parseDirectiveFPU(SMLoc L);
Logan Chien4ea23b52013-05-10 16:17:24 +0000215 bool parseDirectiveFnStart(SMLoc L);
216 bool parseDirectiveFnEnd(SMLoc L);
217 bool parseDirectiveCantUnwind(SMLoc L);
218 bool parseDirectivePersonality(SMLoc L);
219 bool parseDirectiveHandlerData(SMLoc L);
220 bool parseDirectiveSetFP(SMLoc L);
221 bool parseDirectivePad(SMLoc L);
222 bool parseDirectiveRegSave(SMLoc L, bool IsVector);
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +0000223 bool parseDirectiveInst(SMLoc L, char Suffix = '\0');
David Peixotto80c083a2013-12-19 18:26:07 +0000224 bool parseDirectiveLtorg(SMLoc L);
Saleem Abdulrasoola5549682013-12-26 01:52:28 +0000225 bool parseDirectiveEven(SMLoc L);
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +0000226 bool parseDirectivePersonalityIndex(SMLoc L);
Saleem Abdulrasoold9f08602014-01-21 02:33:10 +0000227 bool parseDirectiveUnwindRaw(SMLoc L);
Saleem Abdulrasool56e06e82014-01-30 04:02:47 +0000228 bool parseDirectiveTLSDescSeq(SMLoc L);
Saleem Abdulrasool5d962d32014-01-30 04:46:24 +0000229 bool parseDirectiveMovSP(SMLoc L);
Saleem Abdulrasool4c4789b2014-01-30 04:46:41 +0000230 bool parseDirectiveObjectArch(SMLoc L);
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +0000231 bool parseDirectiveArchExtension(SMLoc L);
Saleem Abdulrasoolfd6ed1e2014-02-23 17:45:32 +0000232 bool parseDirectiveAlign(SMLoc L);
Saleem Abdulrasool39f773f2014-03-20 06:05:33 +0000233 bool parseDirectiveThumbSet(SMLoc L);
Kevin Enderby146dcf22009-10-15 20:48:48 +0000234
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000235 StringRef splitMnemonic(StringRef Mnemonic, unsigned &PredicationCode,
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000236 bool &CarrySetting, unsigned &ProcessorIMod,
237 StringRef &ITMask);
Amara Emerson33089092013-09-19 11:59:01 +0000238 void getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst,
239 bool &CanAcceptCarrySet,
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +0000240 bool &CanAcceptPredicationCode);
Jim Grosbach624bcc72010-10-29 14:46:02 +0000241
Evan Cheng4d1ca962011-07-08 01:53:10 +0000242 bool isThumb() const {
243 // FIXME: Can tablegen auto-generate this?
Evan Cheng91111d22011-07-09 05:47:46 +0000244 return (STI.getFeatureBits() & ARM::ModeThumb) != 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000245 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000246 bool isThumbOne() const {
Evan Cheng91111d22011-07-09 05:47:46 +0000247 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2) == 0;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000248 }
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000249 bool isThumbTwo() const {
250 return isThumb() && (STI.getFeatureBits() & ARM::FeatureThumb2);
251 }
Tim Northovera2292d02013-06-10 23:20:58 +0000252 bool hasThumb() const {
253 return STI.getFeatureBits() & ARM::HasV4TOps;
254 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000255 bool hasV6Ops() const {
256 return STI.getFeatureBits() & ARM::HasV6Ops;
257 }
Tim Northoverf86d1f02013-10-07 11:10:47 +0000258 bool hasV6MOps() const {
259 return STI.getFeatureBits() & ARM::HasV6MOps;
260 }
James Molloy21efa7d2011-09-28 14:21:38 +0000261 bool hasV7Ops() const {
262 return STI.getFeatureBits() & ARM::HasV7Ops;
263 }
Joey Goulyb3f550e2013-06-26 16:58:26 +0000264 bool hasV8Ops() const {
265 return STI.getFeatureBits() & ARM::HasV8Ops;
266 }
Tim Northovera2292d02013-06-10 23:20:58 +0000267 bool hasARM() const {
268 return !(STI.getFeatureBits() & ARM::FeatureNoARM);
269 }
Renato Golin92c816c2014-09-01 11:25:07 +0000270 bool hasThumb2DSP() const {
271 return STI.getFeatureBits() & ARM::FeatureDSPThumb2;
272 }
Oliver Stannard9e89d8c2014-11-05 12:06:39 +0000273 bool hasD16() const {
274 return STI.getFeatureBits() & ARM::FeatureD16;
275 }
Tim Northovera2292d02013-06-10 23:20:58 +0000276
Evan Cheng284b4672011-07-08 22:36:29 +0000277 void SwitchMode() {
Tim Northover26bb14e2014-08-18 11:49:42 +0000278 uint64_t FB = ComputeAvailableFeatures(STI.ToggleFeature(ARM::ModeThumb));
Evan Cheng91111d22011-07-09 05:47:46 +0000279 setAvailableFeatures(FB);
Evan Cheng284b4672011-07-08 22:36:29 +0000280 }
James Molloy21efa7d2011-09-28 14:21:38 +0000281 bool isMClass() const {
282 return STI.getFeatureBits() & ARM::FeatureMClass;
283 }
Evan Cheng4d1ca962011-07-08 01:53:10 +0000284
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000285 /// @name Auto-generated Match Functions
286 /// {
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +0000287
Chris Lattner3e4582a2010-09-06 19:11:01 +0000288#define GET_ASSEMBLER_HEADER
289#include "ARMGenAsmMatcher.inc"
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000290
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000291 /// }
292
David Blaikie960ea3f2014-06-08 16:18:35 +0000293 OperandMatchResultTy parseITCondCode(OperandVector &);
294 OperandMatchResultTy parseCoprocNumOperand(OperandVector &);
295 OperandMatchResultTy parseCoprocRegOperand(OperandVector &);
296 OperandMatchResultTy parseCoprocOptionOperand(OperandVector &);
297 OperandMatchResultTy parseMemBarrierOptOperand(OperandVector &);
298 OperandMatchResultTy parseInstSyncBarrierOptOperand(OperandVector &);
299 OperandMatchResultTy parseProcIFlagsOperand(OperandVector &);
300 OperandMatchResultTy parseMSRMaskOperand(OperandVector &);
Tim Northoveree843ef2014-08-15 10:47:12 +0000301 OperandMatchResultTy parseBankedRegOperand(OperandVector &);
David Blaikie960ea3f2014-06-08 16:18:35 +0000302 OperandMatchResultTy parsePKHImm(OperandVector &O, StringRef Op, int Low,
303 int High);
304 OperandMatchResultTy parsePKHLSLImm(OperandVector &O) {
Jim Grosbach27c1e252011-07-21 17:23:04 +0000305 return parsePKHImm(O, "lsl", 0, 31);
306 }
David Blaikie960ea3f2014-06-08 16:18:35 +0000307 OperandMatchResultTy parsePKHASRImm(OperandVector &O) {
Jim Grosbach27c1e252011-07-21 17:23:04 +0000308 return parsePKHImm(O, "asr", 1, 32);
309 }
David Blaikie960ea3f2014-06-08 16:18:35 +0000310 OperandMatchResultTy parseSetEndImm(OperandVector &);
311 OperandMatchResultTy parseShifterImm(OperandVector &);
312 OperandMatchResultTy parseRotImm(OperandVector &);
313 OperandMatchResultTy parseBitfield(OperandVector &);
314 OperandMatchResultTy parsePostIdxReg(OperandVector &);
315 OperandMatchResultTy parseAM3Offset(OperandVector &);
316 OperandMatchResultTy parseFPImm(OperandVector &);
317 OperandMatchResultTy parseVectorList(OperandVector &);
Jordan Rosee8f1eae2013-01-07 19:00:49 +0000318 OperandMatchResultTy parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index,
319 SMLoc &EndLoc);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +0000320
321 // Asm Match Converter Methods
David Blaikie960ea3f2014-06-08 16:18:35 +0000322 void cvtThumbMultiply(MCInst &Inst, const OperandVector &);
323 void cvtThumbBranches(MCInst &Inst, const OperandVector &);
Saleem Abdulrasool4ab6e732014-02-23 17:45:36 +0000324
David Blaikie960ea3f2014-06-08 16:18:35 +0000325 bool validateInstruction(MCInst &Inst, const OperandVector &Ops);
326 bool processInstruction(MCInst &Inst, const OperandVector &Ops);
327 bool shouldOmitCCOutOperand(StringRef Mnemonic, OperandVector &Operands);
328 bool shouldOmitPredicateOperand(StringRef Mnemonic, OperandVector &Operands);
329
Kevin Enderbyccab3172009-09-15 00:27:25 +0000330public:
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000331 enum ARMMatchResultTy {
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000332 Match_RequiresITBlock = FIRST_TARGET_MATCH_RESULT_TY,
Jim Grosbached16ec42011-08-29 22:24:09 +0000333 Match_RequiresNotITBlock,
Jim Grosbachb7fa2c02011-08-16 22:20:01 +0000334 Match_RequiresV6,
Jim Grosbach087affe2012-06-22 23:56:48 +0000335 Match_RequiresThumb2,
336#define GET_OPERAND_DIAGNOSTIC_TYPES
337#include "ARMGenAsmMatcher.inc"
338
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000339 };
340
Joey Gouly0e76fa72013-09-12 10:28:05 +0000341 ARMAsmParser(MCSubtargetInfo &_STI, MCAsmParser &_Parser,
Evgeniy Stepanov0a951b72014-04-23 11:16:03 +0000342 const MCInstrInfo &MII,
343 const MCTargetOptions &Options)
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +0000344 : MCTargetAsmParser(), STI(_STI), Parser(_Parser), MII(MII), UC(_Parser) {
Evan Cheng4d1ca962011-07-08 01:53:10 +0000345 MCAsmParserExtension::Initialize(_Parser);
Evan Cheng284b4672011-07-08 22:36:29 +0000346
Jim Grosbachc988e0c2012-03-05 19:33:30 +0000347 // Cache the MCRegisterInfo.
Bill Wendlingbc07a892013-06-18 07:20:20 +0000348 MRI = getContext().getRegisterInfo();
Jim Grosbachc988e0c2012-03-05 19:33:30 +0000349
Evan Cheng4d1ca962011-07-08 01:53:10 +0000350 // Initialize the set of available features.
Evan Cheng91111d22011-07-09 05:47:46 +0000351 setAvailableFeatures(ComputeAvailableFeatures(STI.getFeatureBits()));
Jim Grosbached16ec42011-08-29 22:24:09 +0000352
353 // Not in an ITBlock to start with.
354 ITState.CurPosition = ~0U;
Tim Northover1744d0a2013-10-25 12:49:50 +0000355
356 NextSymbolIsThumb = false;
Evan Cheng4d1ca962011-07-08 01:53:10 +0000357 }
Kevin Enderbyccab3172009-09-15 00:27:25 +0000358
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000359 // Implementation of the MCTargetAsmParser interface:
Craig Topperca7e3e52014-03-10 03:19:03 +0000360 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000361 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
362 SMLoc NameLoc, OperandVector &Operands) override;
Craig Topperca7e3e52014-03-10 03:19:03 +0000363 bool ParseDirective(AsmToken DirectiveID) override;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +0000364
David Blaikie960ea3f2014-06-08 16:18:35 +0000365 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Craig Topperca7e3e52014-03-10 03:19:03 +0000366 unsigned Kind) override;
367 unsigned checkTargetMatchPredicate(MCInst &Inst) override;
Jim Grosbach3e941ae2011-08-16 20:45:50 +0000368
Chad Rosier49963552012-10-13 00:26:04 +0000369 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
David Blaikie960ea3f2014-06-08 16:18:35 +0000370 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000371 uint64_t &ErrorInfo,
Craig Topperca7e3e52014-03-10 03:19:03 +0000372 bool MatchingInlineAsm) override;
373 void onLabelParsed(MCSymbol *Symbol) override;
Kevin Enderbyccab3172009-09-15 00:27:25 +0000374};
Jim Grosbach624bcc72010-10-29 14:46:02 +0000375} // end anonymous namespace
376
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +0000377namespace {
378
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000379/// ARMOperand - Instances of this class represent a parsed ARM machine
Joel Jones54597542013-01-09 22:34:16 +0000380/// operand.
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000381class ARMOperand : public MCParsedAsmOperand {
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000382 enum KindTy {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000383 k_CondCode,
384 k_CCOut,
385 k_ITCondMask,
386 k_CoprocNum,
387 k_CoprocReg,
Jim Grosbach48399582011-10-12 17:34:41 +0000388 k_CoprocOption,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000389 k_Immediate,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000390 k_MemBarrierOpt,
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +0000391 k_InstSyncBarrierOpt,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000392 k_Memory,
393 k_PostIndexRegister,
394 k_MSRMask,
Tim Northoveree843ef2014-08-15 10:47:12 +0000395 k_BankedReg,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000396 k_ProcIFlags,
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000397 k_VectorIndex,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000398 k_Register,
399 k_RegisterList,
400 k_DPRRegisterList,
401 k_SPRRegisterList,
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000402 k_VectorList,
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000403 k_VectorListAllLanes,
Jim Grosbach04945c42011-12-02 00:35:16 +0000404 k_VectorListIndexed,
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000405 k_ShiftedRegister,
406 k_ShiftedImmediate,
407 k_ShifterImmediate,
408 k_RotateImmediate,
409 k_BitfieldDescriptor,
410 k_Token
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000411 } Kind;
412
Kevin Enderby488f20b2014-04-10 20:18:58 +0000413 SMLoc StartLoc, EndLoc, AlignmentLoc;
Bill Wendling0ab0f672010-11-18 21:50:54 +0000414 SmallVector<unsigned, 8> Registers;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000415
Eric Christopher8996c5d2013-03-15 00:42:55 +0000416 struct CCOp {
417 ARMCC::CondCodes Val;
418 };
419
420 struct CopOp {
421 unsigned Val;
422 };
423
424 struct CoprocOptionOp {
425 unsigned Val;
426 };
427
428 struct ITMaskOp {
429 unsigned Mask:4;
430 };
431
432 struct MBOptOp {
433 ARM_MB::MemBOpt Val;
434 };
435
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +0000436 struct ISBOptOp {
437 ARM_ISB::InstSyncBOpt Val;
438 };
439
Eric Christopher8996c5d2013-03-15 00:42:55 +0000440 struct IFlagsOp {
441 ARM_PROC::IFlags Val;
442 };
443
444 struct MMaskOp {
445 unsigned Val;
446 };
447
Tim Northoveree843ef2014-08-15 10:47:12 +0000448 struct BankedRegOp {
449 unsigned Val;
450 };
451
Eric Christopher8996c5d2013-03-15 00:42:55 +0000452 struct TokOp {
453 const char *Data;
454 unsigned Length;
455 };
456
457 struct RegOp {
458 unsigned RegNum;
459 };
460
461 // A vector register list is a sequential list of 1 to 4 registers.
462 struct VectorListOp {
463 unsigned RegNum;
464 unsigned Count;
465 unsigned LaneIndex;
466 bool isDoubleSpaced;
467 };
468
469 struct VectorIndexOp {
470 unsigned Val;
471 };
472
473 struct ImmOp {
474 const MCExpr *Val;
475 };
476
477 /// Combined record for all forms of ARM address expressions.
478 struct MemoryOp {
479 unsigned BaseRegNum;
480 // Offset is in OffsetReg or OffsetImm. If both are zero, no offset
481 // was specified.
482 const MCConstantExpr *OffsetImm; // Offset immediate value
483 unsigned OffsetRegNum; // Offset register num, when OffsetImm == NULL
484 ARM_AM::ShiftOpc ShiftType; // Shift type for OffsetReg
485 unsigned ShiftImm; // shift for OffsetReg.
486 unsigned Alignment; // 0 = no alignment specified
487 // n = alignment in bytes (2, 4, 8, 16, or 32)
488 unsigned isNegative : 1; // Negated OffsetReg? (~'U' bit)
489 };
490
491 struct PostIdxRegOp {
492 unsigned RegNum;
493 bool isAdd;
494 ARM_AM::ShiftOpc ShiftTy;
495 unsigned ShiftImm;
496 };
497
498 struct ShifterImmOp {
499 bool isASR;
500 unsigned Imm;
501 };
502
503 struct RegShiftedRegOp {
504 ARM_AM::ShiftOpc ShiftTy;
505 unsigned SrcReg;
506 unsigned ShiftReg;
507 unsigned ShiftImm;
508 };
509
510 struct RegShiftedImmOp {
511 ARM_AM::ShiftOpc ShiftTy;
512 unsigned SrcReg;
513 unsigned ShiftImm;
514 };
515
516 struct RotImmOp {
517 unsigned Imm;
518 };
519
520 struct BitfieldOp {
521 unsigned LSB;
522 unsigned Width;
523 };
524
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000525 union {
Eric Christopher8996c5d2013-03-15 00:42:55 +0000526 struct CCOp CC;
527 struct CopOp Cop;
528 struct CoprocOptionOp CoprocOption;
529 struct MBOptOp MBOpt;
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +0000530 struct ISBOptOp ISBOpt;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000531 struct ITMaskOp ITMask;
532 struct IFlagsOp IFlags;
533 struct MMaskOp MMask;
Tim Northoveree843ef2014-08-15 10:47:12 +0000534 struct BankedRegOp BankedReg;
Eric Christopher8996c5d2013-03-15 00:42:55 +0000535 struct TokOp Tok;
536 struct RegOp Reg;
537 struct VectorListOp VectorList;
538 struct VectorIndexOp VectorIndex;
539 struct ImmOp Imm;
540 struct MemoryOp Memory;
541 struct PostIdxRegOp PostIdxReg;
542 struct ShifterImmOp ShifterImm;
543 struct RegShiftedRegOp RegShiftedReg;
544 struct RegShiftedImmOp RegShiftedImm;
545 struct RotImmOp RotImm;
546 struct BitfieldOp Bitfield;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000547 };
Jim Grosbach624bcc72010-10-29 14:46:02 +0000548
Bill Wendlingee7f1f92010-11-06 21:42:12 +0000549public:
David Blaikie960ea3f2014-06-08 16:18:35 +0000550 ARMOperand(KindTy K) : MCParsedAsmOperand(), Kind(K) {}
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000551 ARMOperand(const ARMOperand &o) : MCParsedAsmOperand() {
552 Kind = o.Kind;
553 StartLoc = o.StartLoc;
554 EndLoc = o.EndLoc;
555 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000556 case k_CondCode:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000557 CC = o.CC;
558 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000559 case k_ITCondMask:
Jim Grosbach3d1eac82011-08-26 21:43:41 +0000560 ITMask = o.ITMask;
561 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000562 case k_Token:
Daniel Dunbard8042b72010-08-11 06:36:53 +0000563 Tok = o.Tok;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000564 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000565 case k_CCOut:
566 case k_Register:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000567 Reg = o.Reg;
568 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000569 case k_RegisterList:
570 case k_DPRRegisterList:
571 case k_SPRRegisterList:
Bill Wendling0ab0f672010-11-18 21:50:54 +0000572 Registers = o.Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000573 break;
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000574 case k_VectorList:
Jim Grosbachcd6f5e72011-11-30 01:09:44 +0000575 case k_VectorListAllLanes:
Jim Grosbach04945c42011-12-02 00:35:16 +0000576 case k_VectorListIndexed:
Jim Grosbachad47cfc2011-10-18 23:02:30 +0000577 VectorList = o.VectorList;
578 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000579 case k_CoprocNum:
580 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000581 Cop = o.Cop;
582 break;
Jim Grosbach48399582011-10-12 17:34:41 +0000583 case k_CoprocOption:
584 CoprocOption = o.CoprocOption;
585 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000586 case k_Immediate:
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000587 Imm = o.Imm;
588 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000589 case k_MemBarrierOpt:
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000590 MBOpt = o.MBOpt;
591 break;
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +0000592 case k_InstSyncBarrierOpt:
593 ISBOpt = o.ISBOpt;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000594 case k_Memory:
Jim Grosbach871dff72011-10-11 15:59:20 +0000595 Memory = o.Memory;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000596 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000597 case k_PostIndexRegister:
Jim Grosbachd3595712011-08-03 23:50:40 +0000598 PostIdxReg = o.PostIdxReg;
599 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000600 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000601 MMask = o.MMask;
602 break;
Tim Northoveree843ef2014-08-15 10:47:12 +0000603 case k_BankedReg:
604 BankedReg = o.BankedReg;
605 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000606 case k_ProcIFlags:
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000607 IFlags = o.IFlags;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000608 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000609 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +0000610 ShifterImm = o.ShifterImm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +0000611 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000612 case k_ShiftedRegister:
Jim Grosbachac798e12011-07-25 20:49:51 +0000613 RegShiftedReg = o.RegShiftedReg;
Jim Grosbach7dcd1352011-07-13 17:50:29 +0000614 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000615 case k_ShiftedImmediate:
Jim Grosbachac798e12011-07-25 20:49:51 +0000616 RegShiftedImm = o.RegShiftedImm;
Owen Andersonb595ed02011-07-21 18:54:16 +0000617 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000618 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +0000619 RotImm = o.RotImm;
620 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000621 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +0000622 Bitfield = o.Bitfield;
623 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000624 case k_VectorIndex:
625 VectorIndex = o.VectorIndex;
626 break;
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000627 }
628 }
Jim Grosbach624bcc72010-10-29 14:46:02 +0000629
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000630 /// getStartLoc - Get the location of the first token of this operand.
Craig Topperca7e3e52014-03-10 03:19:03 +0000631 SMLoc getStartLoc() const override { return StartLoc; }
Sean Callanan7ad0ad02010-04-02 22:27:05 +0000632 /// getEndLoc - Get the location of the last token of this operand.
Craig Topperca7e3e52014-03-10 03:19:03 +0000633 SMLoc getEndLoc() const override { return EndLoc; }
Chad Rosier143d0f72012-09-21 20:51:43 +0000634 /// getLocRange - Get the range between the first and last token of this
635 /// operand.
Benjamin Kramer673824b2012-04-15 17:04:27 +0000636 SMRange getLocRange() const { return SMRange(StartLoc, EndLoc); }
637
Kevin Enderby488f20b2014-04-10 20:18:58 +0000638 /// getAlignmentLoc - Get the location of the Alignment token of this operand.
639 SMLoc getAlignmentLoc() const {
640 assert(Kind == k_Memory && "Invalid access!");
641 return AlignmentLoc;
642 }
643
Daniel Dunbard8042b72010-08-11 06:36:53 +0000644 ARMCC::CondCodes getCondCode() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000645 assert(Kind == k_CondCode && "Invalid access!");
Daniel Dunbard8042b72010-08-11 06:36:53 +0000646 return CC.Val;
647 }
648
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000649 unsigned getCoproc() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000650 assert((Kind == k_CoprocNum || Kind == k_CoprocReg) && "Invalid access!");
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +0000651 return Cop.Val;
652 }
653
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000654 StringRef getToken() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000655 assert(Kind == k_Token && "Invalid access!");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000656 return StringRef(Tok.Data, Tok.Length);
657 }
658
Craig Topperca7e3e52014-03-10 03:19:03 +0000659 unsigned getReg() const override {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000660 assert((Kind == k_Register || Kind == k_CCOut) && "Invalid access!");
Bill Wendling2cae3272010-11-09 22:44:22 +0000661 return Reg.RegNum;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +0000662 }
663
Bill Wendlingbed94652010-11-09 23:28:44 +0000664 const SmallVectorImpl<unsigned> &getRegList() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000665 assert((Kind == k_RegisterList || Kind == k_DPRRegisterList ||
666 Kind == k_SPRRegisterList) && "Invalid access!");
Bill Wendling0ab0f672010-11-18 21:50:54 +0000667 return Registers;
Bill Wendling7cef4472010-11-06 19:56:04 +0000668 }
669
Kevin Enderbyf5079942009-10-13 22:19:02 +0000670 const MCExpr *getImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000671 assert(isImm() && "Invalid access!");
Kevin Enderbyf5079942009-10-13 22:19:02 +0000672 return Imm.Val;
673 }
674
Jim Grosbachd0637bf2011-10-07 23:56:00 +0000675 unsigned getVectorIndex() const {
676 assert(Kind == k_VectorIndex && "Invalid access!");
677 return VectorIndex.Val;
678 }
679
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000680 ARM_MB::MemBOpt getMemBarrierOpt() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000681 assert(Kind == k_MemBarrierOpt && "Invalid access!");
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +0000682 return MBOpt.Val;
683 }
684
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +0000685 ARM_ISB::InstSyncBOpt getInstSyncBarrierOpt() const {
686 assert(Kind == k_InstSyncBarrierOpt && "Invalid access!");
687 return ISBOpt.Val;
688 }
689
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000690 ARM_PROC::IFlags getProcIFlags() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000691 assert(Kind == k_ProcIFlags && "Invalid access!");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +0000692 return IFlags.Val;
693 }
694
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000695 unsigned getMSRMask() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000696 assert(Kind == k_MSRMask && "Invalid access!");
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +0000697 return MMask.Val;
698 }
699
Tim Northoveree843ef2014-08-15 10:47:12 +0000700 unsigned getBankedReg() const {
701 assert(Kind == k_BankedReg && "Invalid access!");
702 return BankedReg.Val;
703 }
704
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000705 bool isCoprocNum() const { return Kind == k_CoprocNum; }
706 bool isCoprocReg() const { return Kind == k_CoprocReg; }
Jim Grosbach48399582011-10-12 17:34:41 +0000707 bool isCoprocOption() const { return Kind == k_CoprocOption; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +0000708 bool isCondCode() const { return Kind == k_CondCode; }
709 bool isCCOut() const { return Kind == k_CCOut; }
710 bool isITMask() const { return Kind == k_ITCondMask; }
711 bool isITCondCode() const { return Kind == k_CondCode; }
Craig Topperca7e3e52014-03-10 03:19:03 +0000712 bool isImm() const override { return Kind == k_Immediate; }
Mihai Popad36cbaa2013-07-03 09:21:44 +0000713 // checks whether this operand is an unsigned offset which fits is a field
714 // of specified width and scaled by a specific number of bits
715 template<unsigned width, unsigned scale>
716 bool isUnsignedOffset() const {
717 if (!isImm()) return false;
Mihai Popaad18d3c2013-08-09 10:38:32 +0000718 if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
Mihai Popad36cbaa2013-07-03 09:21:44 +0000719 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
720 int64_t Val = CE->getValue();
721 int64_t Align = 1LL << scale;
722 int64_t Max = Align * ((1LL << width) - 1);
723 return ((Val % Align) == 0) && (Val >= 0) && (Val <= Max);
724 }
725 return false;
726 }
Mihai Popaad18d3c2013-08-09 10:38:32 +0000727 // checks whether this operand is an signed offset which fits is a field
728 // of specified width and scaled by a specific number of bits
729 template<unsigned width, unsigned scale>
730 bool isSignedOffset() const {
731 if (!isImm()) return false;
732 if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
733 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
734 int64_t Val = CE->getValue();
735 int64_t Align = 1LL << scale;
736 int64_t Max = Align * ((1LL << (width-1)) - 1);
737 int64_t Min = -Align * (1LL << (width-1));
738 return ((Val % Align) == 0) && (Val >= Min) && (Val <= Max);
739 }
740 return false;
741 }
742
Mihai Popa8a9da5b2013-07-22 15:49:36 +0000743 // checks whether this operand is a memory operand computed as an offset
744 // applied to PC. the offset may have 8 bits of magnitude and is represented
745 // with two bits of shift. textually it may be either [pc, #imm], #imm or
746 // relocable expression...
747 bool isThumbMemPC() const {
748 int64_t Val = 0;
749 if (isImm()) {
750 if (isa<MCSymbolRefExpr>(Imm.Val)) return true;
751 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val);
752 if (!CE) return false;
753 Val = CE->getValue();
754 }
755 else if (isMem()) {
756 if(!Memory.OffsetImm || Memory.OffsetRegNum) return false;
757 if(Memory.BaseRegNum != ARM::PC) return false;
758 Val = Memory.OffsetImm->getValue();
759 }
760 else return false;
Mihai Popad79f00b2013-08-15 15:43:06 +0000761 return ((Val % 4) == 0) && (Val >= 0) && (Val <= 1020);
Mihai Popa8a9da5b2013-07-22 15:49:36 +0000762 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +0000763 bool isFPImm() const {
764 if (!isImm()) return false;
765 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
766 if (!CE) return false;
767 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
768 return Val != -1;
769 }
Jim Grosbachea231912011-12-22 22:19:05 +0000770 bool isFBits16() const {
771 if (!isImm()) return false;
772 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
773 if (!CE) return false;
774 int64_t Value = CE->getValue();
775 return Value >= 0 && Value <= 16;
776 }
777 bool isFBits32() const {
778 if (!isImm()) return false;
779 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
780 if (!CE) return false;
781 int64_t Value = CE->getValue();
782 return Value >= 1 && Value <= 32;
783 }
Jim Grosbach7db8d692011-09-08 22:07:06 +0000784 bool isImm8s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000785 if (!isImm()) return false;
Jim Grosbach7db8d692011-09-08 22:07:06 +0000786 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
787 if (!CE) return false;
788 int64_t Value = CE->getValue();
789 return ((Value & 3) == 0) && Value >= -1020 && Value <= 1020;
790 }
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000791 bool isImm0_1020s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000792 if (!isImm()) return false;
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000793 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
794 if (!CE) return false;
795 int64_t Value = CE->getValue();
796 return ((Value & 3) == 0) && Value >= 0 && Value <= 1020;
797 }
798 bool isImm0_508s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000799 if (!isImm()) return false;
Jim Grosbach0a0b3072011-08-24 21:22:15 +0000800 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
801 if (!CE) return false;
802 int64_t Value = CE->getValue();
803 return ((Value & 3) == 0) && Value >= 0 && Value <= 508;
804 }
Jim Grosbach930f2f62012-04-05 20:57:13 +0000805 bool isImm0_508s4Neg() const {
806 if (!isImm()) return false;
807 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
808 if (!CE) return false;
809 int64_t Value = -CE->getValue();
810 // explicitly exclude zero. we want that to use the normal 0_508 version.
811 return ((Value & 3) == 0) && Value > 0 && Value <= 508;
812 }
Artyom Skrobovfc12e702013-10-23 10:14:40 +0000813 bool isImm0_239() const {
814 if (!isImm()) return false;
815 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
816 if (!CE) return false;
817 int64_t Value = CE->getValue();
818 return Value >= 0 && Value < 240;
819 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000820 bool isImm0_255() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000821 if (!isImm()) return false;
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +0000822 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
823 if (!CE) return false;
824 int64_t Value = CE->getValue();
825 return Value >= 0 && Value < 256;
826 }
Jim Grosbach930f2f62012-04-05 20:57:13 +0000827 bool isImm0_4095() const {
828 if (!isImm()) return false;
829 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
830 if (!CE) return false;
831 int64_t Value = CE->getValue();
832 return Value >= 0 && Value < 4096;
833 }
834 bool isImm0_4095Neg() const {
835 if (!isImm()) return false;
836 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
837 if (!CE) return false;
838 int64_t Value = -CE->getValue();
839 return Value > 0 && Value < 4096;
840 }
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000841 bool isImm0_1() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000842 if (!isImm()) return false;
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000843 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
844 if (!CE) return false;
845 int64_t Value = CE->getValue();
846 return Value >= 0 && Value < 2;
847 }
848 bool isImm0_3() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000849 if (!isImm()) return false;
Jim Grosbach9dff9f42011-12-02 23:34:39 +0000850 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
851 if (!CE) return false;
852 int64_t Value = CE->getValue();
853 return Value >= 0 && Value < 4;
854 }
Jim Grosbach31756c22011-07-13 22:01:08 +0000855 bool isImm0_7() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000856 if (!isImm()) return false;
Jim Grosbach31756c22011-07-13 22:01:08 +0000857 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
858 if (!CE) return false;
859 int64_t Value = CE->getValue();
860 return Value >= 0 && Value < 8;
861 }
862 bool isImm0_15() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000863 if (!isImm()) return false;
Jim Grosbach31756c22011-07-13 22:01:08 +0000864 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
865 if (!CE) return false;
866 int64_t Value = CE->getValue();
867 return Value >= 0 && Value < 16;
868 }
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000869 bool isImm0_31() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000870 if (!isImm()) return false;
Jim Grosbach72e7c4f2011-07-21 23:26:25 +0000871 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
872 if (!CE) return false;
873 int64_t Value = CE->getValue();
874 return Value >= 0 && Value < 32;
875 }
Jim Grosbach00326402011-12-08 01:30:04 +0000876 bool isImm0_63() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000877 if (!isImm()) return false;
Jim Grosbach00326402011-12-08 01:30:04 +0000878 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
879 if (!CE) return false;
880 int64_t Value = CE->getValue();
881 return Value >= 0 && Value < 64;
882 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000883 bool isImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000884 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000885 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
886 if (!CE) return false;
887 int64_t Value = CE->getValue();
888 return Value == 8;
889 }
890 bool isImm16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000891 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000892 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
893 if (!CE) return false;
894 int64_t Value = CE->getValue();
895 return Value == 16;
896 }
897 bool isImm32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000898 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000899 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
900 if (!CE) return false;
901 int64_t Value = CE->getValue();
902 return Value == 32;
903 }
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000904 bool isShrImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000905 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000906 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
907 if (!CE) return false;
908 int64_t Value = CE->getValue();
909 return Value > 0 && Value <= 8;
910 }
911 bool isShrImm16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000912 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000913 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
914 if (!CE) return false;
915 int64_t Value = CE->getValue();
916 return Value > 0 && Value <= 16;
917 }
918 bool isShrImm32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000919 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000920 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
921 if (!CE) return false;
922 int64_t Value = CE->getValue();
923 return Value > 0 && Value <= 32;
924 }
925 bool isShrImm64() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000926 if (!isImm()) return false;
Jim Grosbachba7d6ed2011-12-08 22:06:06 +0000927 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
928 if (!CE) return false;
929 int64_t Value = CE->getValue();
930 return Value > 0 && Value <= 64;
931 }
Jim Grosbachd4b82492011-12-07 01:07:24 +0000932 bool isImm1_7() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000933 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000934 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
935 if (!CE) return false;
936 int64_t Value = CE->getValue();
937 return Value > 0 && Value < 8;
938 }
939 bool isImm1_15() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000940 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000941 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
942 if (!CE) return false;
943 int64_t Value = CE->getValue();
944 return Value > 0 && Value < 16;
945 }
946 bool isImm1_31() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000947 if (!isImm()) return false;
Jim Grosbachd4b82492011-12-07 01:07:24 +0000948 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
949 if (!CE) return false;
950 int64_t Value = CE->getValue();
951 return Value > 0 && Value < 32;
952 }
Jim Grosbach475c6db2011-07-25 23:09:14 +0000953 bool isImm1_16() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000954 if (!isImm()) return false;
Jim Grosbach475c6db2011-07-25 23:09:14 +0000955 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
956 if (!CE) return false;
957 int64_t Value = CE->getValue();
958 return Value > 0 && Value < 17;
959 }
Jim Grosbach801e0a32011-07-22 23:16:18 +0000960 bool isImm1_32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000961 if (!isImm()) return false;
Jim Grosbach801e0a32011-07-22 23:16:18 +0000962 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
963 if (!CE) return false;
964 int64_t Value = CE->getValue();
965 return Value > 0 && Value < 33;
966 }
Jim Grosbachc14871c2011-11-10 19:18:01 +0000967 bool isImm0_32() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000968 if (!isImm()) return false;
Jim Grosbachc14871c2011-11-10 19:18:01 +0000969 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
970 if (!CE) return false;
971 int64_t Value = CE->getValue();
972 return Value >= 0 && Value < 33;
973 }
Jim Grosbach975b6412011-07-13 20:10:10 +0000974 bool isImm0_65535() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000975 if (!isImm()) return false;
Jim Grosbach975b6412011-07-13 20:10:10 +0000976 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
977 if (!CE) return false;
978 int64_t Value = CE->getValue();
979 return Value >= 0 && Value < 65536;
980 }
Mihai Popaae1112b2013-08-21 13:14:58 +0000981 bool isImm256_65535Expr() const {
982 if (!isImm()) return false;
983 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
984 // If it's not a constant expression, it'll generate a fixup and be
985 // handled later.
986 if (!CE) return true;
987 int64_t Value = CE->getValue();
988 return Value >= 256 && Value < 65536;
989 }
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000990 bool isImm0_65535Expr() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +0000991 if (!isImm()) return false;
Jim Grosbach7c09e3c2011-07-19 19:13:28 +0000992 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
993 // If it's not a constant expression, it'll generate a fixup and be
994 // handled later.
995 if (!CE) return true;
996 int64_t Value = CE->getValue();
997 return Value >= 0 && Value < 65536;
998 }
Jim Grosbachf1637842011-07-26 16:24:27 +0000999 bool isImm24bit() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001000 if (!isImm()) return false;
Jim Grosbachf1637842011-07-26 16:24:27 +00001001 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1002 if (!CE) return false;
1003 int64_t Value = CE->getValue();
1004 return Value >= 0 && Value <= 0xffffff;
1005 }
Jim Grosbach46dd4132011-08-17 21:51:27 +00001006 bool isImmThumbSR() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001007 if (!isImm()) return false;
Jim Grosbach46dd4132011-08-17 21:51:27 +00001008 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1009 if (!CE) return false;
1010 int64_t Value = CE->getValue();
1011 return Value > 0 && Value < 33;
1012 }
Jim Grosbach27c1e252011-07-21 17:23:04 +00001013 bool isPKHLSLImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001014 if (!isImm()) return false;
Jim Grosbach27c1e252011-07-21 17:23:04 +00001015 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1016 if (!CE) return false;
1017 int64_t Value = CE->getValue();
1018 return Value >= 0 && Value < 32;
1019 }
1020 bool isPKHASRImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001021 if (!isImm()) return false;
Jim Grosbach27c1e252011-07-21 17:23:04 +00001022 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1023 if (!CE) return false;
1024 int64_t Value = CE->getValue();
1025 return Value > 0 && Value <= 32;
1026 }
Jiangning Liu10dd40e2012-08-02 08:13:13 +00001027 bool isAdrLabel() const {
1028 // If we have an immediate that's not a constant, treat it as a label
1029 // reference needing a fixup. If it is a constant, but it can't fit
1030 // into shift immediate encoding, we reject it.
1031 if (isImm() && !isa<MCConstantExpr>(getImm())) return true;
1032 else return (isARMSOImm() || isARMSOImmNeg());
1033 }
Jim Grosbach9720dcf2011-07-19 16:50:30 +00001034 bool isARMSOImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001035 if (!isImm()) return false;
Jim Grosbach9720dcf2011-07-19 16:50:30 +00001036 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1037 if (!CE) return false;
1038 int64_t Value = CE->getValue();
1039 return ARM_AM::getSOImmVal(Value) != -1;
1040 }
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001041 bool isARMSOImmNot() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001042 if (!isImm()) return false;
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001043 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1044 if (!CE) return false;
1045 int64_t Value = CE->getValue();
1046 return ARM_AM::getSOImmVal(~Value) != -1;
1047 }
Jim Grosbach30506252011-12-08 00:31:07 +00001048 bool isARMSOImmNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001049 if (!isImm()) return false;
Jim Grosbach30506252011-12-08 00:31:07 +00001050 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1051 if (!CE) return false;
1052 int64_t Value = CE->getValue();
Jim Grosbachfdaab532012-03-30 19:59:02 +00001053 // Only use this when not representable as a plain so_imm.
1054 return ARM_AM::getSOImmVal(Value) == -1 &&
1055 ARM_AM::getSOImmVal(-Value) != -1;
Jim Grosbach30506252011-12-08 00:31:07 +00001056 }
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001057 bool isT2SOImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001058 if (!isImm()) return false;
Jim Grosbacha6f7a1e2011-06-27 23:54:06 +00001059 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1060 if (!CE) return false;
1061 int64_t Value = CE->getValue();
1062 return ARM_AM::getT2SOImmVal(Value) != -1;
1063 }
Jim Grosbachb009a872011-10-28 22:36:30 +00001064 bool isT2SOImmNot() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001065 if (!isImm()) return false;
Jim Grosbachb009a872011-10-28 22:36:30 +00001066 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1067 if (!CE) return false;
1068 int64_t Value = CE->getValue();
Mihai Popacf276b22013-08-16 11:55:44 +00001069 return ARM_AM::getT2SOImmVal(Value) == -1 &&
1070 ARM_AM::getT2SOImmVal(~Value) != -1;
Jim Grosbachb009a872011-10-28 22:36:30 +00001071 }
Jim Grosbach30506252011-12-08 00:31:07 +00001072 bool isT2SOImmNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001073 if (!isImm()) return false;
Jim Grosbach30506252011-12-08 00:31:07 +00001074 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1075 if (!CE) return false;
1076 int64_t Value = CE->getValue();
Jim Grosbachfdaab532012-03-30 19:59:02 +00001077 // Only use this when not representable as a plain so_imm.
1078 return ARM_AM::getT2SOImmVal(Value) == -1 &&
1079 ARM_AM::getT2SOImmVal(-Value) != -1;
Jim Grosbach30506252011-12-08 00:31:07 +00001080 }
Jim Grosbach0a547702011-07-22 17:44:50 +00001081 bool isSetEndImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001082 if (!isImm()) return false;
Jim Grosbach0a547702011-07-22 17:44:50 +00001083 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1084 if (!CE) return false;
1085 int64_t Value = CE->getValue();
1086 return Value == 1 || Value == 0;
1087 }
Craig Topperca7e3e52014-03-10 03:19:03 +00001088 bool isReg() const override { return Kind == k_Register; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001089 bool isRegList() const { return Kind == k_RegisterList; }
1090 bool isDPRRegList() const { return Kind == k_DPRRegisterList; }
1091 bool isSPRRegList() const { return Kind == k_SPRRegisterList; }
Craig Topperca7e3e52014-03-10 03:19:03 +00001092 bool isToken() const override { return Kind == k_Token; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001093 bool isMemBarrierOpt() const { return Kind == k_MemBarrierOpt; }
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +00001094 bool isInstSyncBarrierOpt() const { return Kind == k_InstSyncBarrierOpt; }
Craig Topperca7e3e52014-03-10 03:19:03 +00001095 bool isMem() const override { return Kind == k_Memory; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001096 bool isShifterImm() const { return Kind == k_ShifterImmediate; }
1097 bool isRegShiftedReg() const { return Kind == k_ShiftedRegister; }
1098 bool isRegShiftedImm() const { return Kind == k_ShiftedImmediate; }
1099 bool isRotImm() const { return Kind == k_RotateImmediate; }
1100 bool isBitfield() const { return Kind == k_BitfieldDescriptor; }
1101 bool isPostIdxRegShifted() const { return Kind == k_PostIndexRegister; }
Jim Grosbachc320c852011-08-05 21:28:30 +00001102 bool isPostIdxReg() const {
Jim Grosbachee201fa2011-11-14 17:52:47 +00001103 return Kind == k_PostIndexRegister && PostIdxReg.ShiftTy ==ARM_AM::no_shift;
Jim Grosbachc320c852011-08-05 21:28:30 +00001104 }
Kevin Enderby488f20b2014-04-10 20:18:58 +00001105 bool isMemNoOffset(bool alignOK = false, unsigned Alignment = 0) const {
Chad Rosier41099832012-09-11 23:02:35 +00001106 if (!isMem())
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001107 return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001108 // No offset of any kind.
Craig Topper062a2ba2014-04-25 05:30:21 +00001109 return Memory.OffsetRegNum == 0 && Memory.OffsetImm == nullptr &&
Kevin Enderby488f20b2014-04-10 20:18:58 +00001110 (alignOK || Memory.Alignment == Alignment);
Jim Grosbacha95ec992011-10-11 17:29:55 +00001111 }
Jim Grosbach94298a92012-01-18 22:46:46 +00001112 bool isMemPCRelImm12() const {
Chad Rosier41099832012-09-11 23:02:35 +00001113 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach94298a92012-01-18 22:46:46 +00001114 return false;
1115 // Base register must be PC.
1116 if (Memory.BaseRegNum != ARM::PC)
1117 return false;
1118 // Immediate offset in range [-4095, 4095].
1119 if (!Memory.OffsetImm) return true;
1120 int64_t Val = Memory.OffsetImm->getValue();
1121 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
1122 }
Jim Grosbacha95ec992011-10-11 17:29:55 +00001123 bool isAlignedMemory() const {
1124 return isMemNoOffset(true);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00001125 }
Kevin Enderby488f20b2014-04-10 20:18:58 +00001126 bool isAlignedMemoryNone() const {
1127 return isMemNoOffset(false, 0);
1128 }
1129 bool isDupAlignedMemoryNone() const {
1130 return isMemNoOffset(false, 0);
1131 }
1132 bool isAlignedMemory16() const {
1133 if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2.
1134 return true;
1135 return isMemNoOffset(false, 0);
1136 }
1137 bool isDupAlignedMemory16() const {
1138 if (isMemNoOffset(false, 2)) // alignment in bytes for 16-bits is 2.
1139 return true;
1140 return isMemNoOffset(false, 0);
1141 }
1142 bool isAlignedMemory32() const {
1143 if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4.
1144 return true;
1145 return isMemNoOffset(false, 0);
1146 }
1147 bool isDupAlignedMemory32() const {
1148 if (isMemNoOffset(false, 4)) // alignment in bytes for 32-bits is 4.
1149 return true;
1150 return isMemNoOffset(false, 0);
1151 }
1152 bool isAlignedMemory64() const {
1153 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1154 return true;
1155 return isMemNoOffset(false, 0);
1156 }
1157 bool isDupAlignedMemory64() const {
1158 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1159 return true;
1160 return isMemNoOffset(false, 0);
1161 }
1162 bool isAlignedMemory64or128() const {
1163 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1164 return true;
1165 if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16.
1166 return true;
1167 return isMemNoOffset(false, 0);
1168 }
1169 bool isDupAlignedMemory64or128() const {
1170 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1171 return true;
1172 if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16.
1173 return true;
1174 return isMemNoOffset(false, 0);
1175 }
1176 bool isAlignedMemory64or128or256() const {
1177 if (isMemNoOffset(false, 8)) // alignment in bytes for 64-bits is 8.
1178 return true;
1179 if (isMemNoOffset(false, 16)) // alignment in bytes for 128-bits is 16.
1180 return true;
1181 if (isMemNoOffset(false, 32)) // alignment in bytes for 256-bits is 32.
1182 return true;
1183 return isMemNoOffset(false, 0);
1184 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001185 bool isAddrMode2() const {
Chad Rosier41099832012-09-11 23:02:35 +00001186 if (!isMem() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001187 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001188 if (Memory.OffsetRegNum) return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00001189 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001190 if (!Memory.OffsetImm) return true;
1191 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbachd3595712011-08-03 23:50:40 +00001192 return Val > -4096 && Val < 4096;
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00001193 }
Jim Grosbachcd17c122011-08-04 23:01:30 +00001194 bool isAM2OffsetImm() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001195 if (!isImm()) return false;
Jim Grosbachcd17c122011-08-04 23:01:30 +00001196 // Immediate offset in range [-4095, 4095].
1197 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1198 if (!CE) return false;
1199 int64_t Val = CE->getValue();
Mihai Popac1d119e2013-06-11 09:48:35 +00001200 return (Val == INT32_MIN) || (Val > -4096 && Val < 4096);
Jim Grosbachcd17c122011-08-04 23:01:30 +00001201 }
Jim Grosbach5b96b802011-08-10 20:29:19 +00001202 bool isAddrMode3() const {
Jim Grosbach8648c102011-12-19 23:06:24 +00001203 // If we have an immediate that's not a constant, treat it as a label
1204 // reference needing a fixup. If it is a constant, it's something else
1205 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001206 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +00001207 return true;
Chad Rosier41099832012-09-11 23:02:35 +00001208 if (!isMem() || Memory.Alignment != 0) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001209 // No shifts are legal for AM3.
Jim Grosbach871dff72011-10-11 15:59:20 +00001210 if (Memory.ShiftType != ARM_AM::no_shift) return false;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001211 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001212 if (Memory.OffsetRegNum) return true;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001213 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001214 if (!Memory.OffsetImm) return true;
1215 int64_t Val = Memory.OffsetImm->getValue();
Silviu Baranga5a719f92012-05-11 09:10:54 +00001216 // The #-0 offset is encoded as INT32_MIN, and we have to check
1217 // for this too.
1218 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001219 }
1220 bool isAM3Offset() const {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001221 if (Kind != k_Immediate && Kind != k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +00001222 return false;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001223 if (Kind == k_PostIndexRegister)
Jim Grosbach5b96b802011-08-10 20:29:19 +00001224 return PostIdxReg.ShiftTy == ARM_AM::no_shift;
1225 // Immediate offset in range [-255, 255].
1226 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1227 if (!CE) return false;
1228 int64_t Val = CE->getValue();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00001229 // Special case, #-0 is INT32_MIN.
1230 return (Val > -256 && Val < 256) || Val == INT32_MIN;
Jim Grosbach5b96b802011-08-10 20:29:19 +00001231 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001232 bool isAddrMode5() const {
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001233 // If we have an immediate that's not a constant, treat it as a label
1234 // reference needing a fixup. If it is a constant, it's something else
1235 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001236 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001237 return true;
Chad Rosier41099832012-09-11 23:02:35 +00001238 if (!isMem() || Memory.Alignment != 0) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001239 // Check for register offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00001240 if (Memory.OffsetRegNum) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001241 // Immediate offset in range [-1020, 1020] and a multiple of 4.
Jim Grosbach871dff72011-10-11 15:59:20 +00001242 if (!Memory.OffsetImm) return true;
1243 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001244 return (Val >= -1020 && Val <= 1020 && ((Val & 3) == 0)) ||
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00001245 Val == INT32_MIN;
Bill Wendling8d2aa032010-11-08 23:49:57 +00001246 }
Jim Grosbach05541f42011-09-19 22:21:13 +00001247 bool isMemTBB() const {
Chad Rosier41099832012-09-11 23:02:35 +00001248 if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +00001249 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Jim Grosbach05541f42011-09-19 22:21:13 +00001250 return false;
1251 return true;
1252 }
1253 bool isMemTBH() const {
Chad Rosier41099832012-09-11 23:02:35 +00001254 if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +00001255 Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm != 1 ||
1256 Memory.Alignment != 0 )
Jim Grosbach05541f42011-09-19 22:21:13 +00001257 return false;
1258 return true;
1259 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001260 bool isMemRegOffset() const {
Chad Rosier41099832012-09-11 23:02:35 +00001261 if (!isMem() || !Memory.OffsetRegNum || Memory.Alignment != 0)
Bill Wendling092a7bd2010-12-14 03:36:38 +00001262 return false;
Daniel Dunbar7ed45592011-01-18 05:34:11 +00001263 return true;
Bill Wendling092a7bd2010-12-14 03:36:38 +00001264 }
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001265 bool isT2MemRegOffset() const {
Chad Rosier41099832012-09-11 23:02:35 +00001266 if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +00001267 Memory.Alignment != 0)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001268 return false;
1269 // Only lsl #{0, 1, 2, 3} allowed.
Jim Grosbach871dff72011-10-11 15:59:20 +00001270 if (Memory.ShiftType == ARM_AM::no_shift)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001271 return true;
Jim Grosbach871dff72011-10-11 15:59:20 +00001272 if (Memory.ShiftType != ARM_AM::lsl || Memory.ShiftImm > 3)
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00001273 return false;
1274 return true;
1275 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001276 bool isMemThumbRR() const {
1277 // Thumb reg+reg addressing is simple. Just two registers, a base and
1278 // an offset. No shifts, negations or any other complicating factors.
Chad Rosier41099832012-09-11 23:02:35 +00001279 if (!isMem() || !Memory.OffsetRegNum || Memory.isNegative ||
Jim Grosbacha95ec992011-10-11 17:29:55 +00001280 Memory.ShiftType != ARM_AM::no_shift || Memory.Alignment != 0)
Bill Wendling811c9362010-11-30 07:44:32 +00001281 return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001282 return isARMLowRegister(Memory.BaseRegNum) &&
1283 (!Memory.OffsetRegNum || isARMLowRegister(Memory.OffsetRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001284 }
1285 bool isMemThumbRIs4() const {
Chad Rosier41099832012-09-11 23:02:35 +00001286 if (!isMem() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +00001287 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach3fe94e32011-08-19 17:55:24 +00001288 return false;
1289 // Immediate offset, multiple of 4 in range [0, 124].
Jim Grosbach871dff72011-10-11 15:59:20 +00001290 if (!Memory.OffsetImm) return true;
1291 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +00001292 return Val >= 0 && Val <= 124 && (Val % 4) == 0;
1293 }
Jim Grosbach26d35872011-08-19 18:55:51 +00001294 bool isMemThumbRIs2() const {
Chad Rosier41099832012-09-11 23:02:35 +00001295 if (!isMem() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +00001296 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbach26d35872011-08-19 18:55:51 +00001297 return false;
1298 // Immediate offset, multiple of 4 in range [0, 62].
Jim Grosbach871dff72011-10-11 15:59:20 +00001299 if (!Memory.OffsetImm) return true;
1300 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach26d35872011-08-19 18:55:51 +00001301 return Val >= 0 && Val <= 62 && (Val % 2) == 0;
1302 }
Jim Grosbacha32c7532011-08-19 18:49:59 +00001303 bool isMemThumbRIs1() const {
Chad Rosier41099832012-09-11 23:02:35 +00001304 if (!isMem() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +00001305 !isARMLowRegister(Memory.BaseRegNum) || Memory.Alignment != 0)
Jim Grosbacha32c7532011-08-19 18:49:59 +00001306 return false;
1307 // Immediate offset in range [0, 31].
Jim Grosbach871dff72011-10-11 15:59:20 +00001308 if (!Memory.OffsetImm) return true;
1309 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha32c7532011-08-19 18:49:59 +00001310 return Val >= 0 && Val <= 31;
1311 }
Jim Grosbach23983d62011-08-19 18:13:48 +00001312 bool isMemThumbSPI() const {
Chad Rosier41099832012-09-11 23:02:35 +00001313 if (!isMem() || Memory.OffsetRegNum != 0 ||
Jim Grosbacha95ec992011-10-11 17:29:55 +00001314 Memory.BaseRegNum != ARM::SP || Memory.Alignment != 0)
Jim Grosbach23983d62011-08-19 18:13:48 +00001315 return false;
1316 // Immediate offset, multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001317 if (!Memory.OffsetImm) return true;
1318 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach23983d62011-08-19 18:13:48 +00001319 return Val >= 0 && Val <= 1020 && (Val % 4) == 0;
Bill Wendling811c9362010-11-30 07:44:32 +00001320 }
Jim Grosbach7db8d692011-09-08 22:07:06 +00001321 bool isMemImm8s4Offset() const {
Jim Grosbach8648c102011-12-19 23:06:24 +00001322 // If we have an immediate that's not a constant, treat it as a label
1323 // reference needing a fixup. If it is a constant, it's something else
1324 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001325 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach8648c102011-12-19 23:06:24 +00001326 return true;
Chad Rosier41099832012-09-11 23:02:35 +00001327 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach7db8d692011-09-08 22:07:06 +00001328 return false;
1329 // Immediate offset a multiple of 4 in range [-1020, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001330 if (!Memory.OffsetImm) return true;
1331 int64_t Val = Memory.OffsetImm->getValue();
Jiangning Liu6a43bf72012-08-02 08:29:50 +00001332 // Special case, #-0 is INT32_MIN.
1333 return (Val >= -1020 && Val <= 1020 && (Val & 3) == 0) || Val == INT32_MIN;
Jim Grosbach7db8d692011-09-08 22:07:06 +00001334 }
Jim Grosbacha05627e2011-09-09 18:37:27 +00001335 bool isMemImm0_1020s4Offset() const {
Chad Rosier41099832012-09-11 23:02:35 +00001336 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbacha05627e2011-09-09 18:37:27 +00001337 return false;
1338 // Immediate offset a multiple of 4 in range [0, 1020].
Jim Grosbach871dff72011-10-11 15:59:20 +00001339 if (!Memory.OffsetImm) return true;
1340 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbacha05627e2011-09-09 18:37:27 +00001341 return Val >= 0 && Val <= 1020 && (Val & 3) == 0;
1342 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001343 bool isMemImm8Offset() const {
Chad Rosier41099832012-09-11 23:02:35 +00001344 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001345 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001346 // Base reg of PC isn't allowed for these encodings.
1347 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001348 // Immediate offset in range [-255, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001349 if (!Memory.OffsetImm) return true;
1350 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson49168402011-09-23 22:25:02 +00001351 return (Val == INT32_MIN) || (Val > -256 && Val < 256);
Jim Grosbachd3595712011-08-03 23:50:40 +00001352 }
Jim Grosbach2392c532011-09-07 23:39:14 +00001353 bool isMemPosImm8Offset() const {
Chad Rosier41099832012-09-11 23:02:35 +00001354 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach2392c532011-09-07 23:39:14 +00001355 return false;
1356 // Immediate offset in range [0, 255].
Jim Grosbach871dff72011-10-11 15:59:20 +00001357 if (!Memory.OffsetImm) return true;
1358 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach2392c532011-09-07 23:39:14 +00001359 return Val >= 0 && Val < 256;
1360 }
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001361 bool isMemNegImm8Offset() const {
Chad Rosier41099832012-09-11 23:02:35 +00001362 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001363 return false;
Jim Grosbach94298a92012-01-18 22:46:46 +00001364 // Base reg of PC isn't allowed for these encodings.
1365 if (Memory.BaseRegNum == ARM::PC) return false;
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001366 // Immediate offset in range [-255, -1].
Jim Grosbach175c7d02011-12-06 04:49:29 +00001367 if (!Memory.OffsetImm) return false;
Jim Grosbach871dff72011-10-11 15:59:20 +00001368 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach175c7d02011-12-06 04:49:29 +00001369 return (Val == INT32_MIN) || (Val > -256 && Val < 0);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001370 }
1371 bool isMemUImm12Offset() const {
Chad Rosier41099832012-09-11 23:02:35 +00001372 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001373 return false;
1374 // Immediate offset in range [0, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001375 if (!Memory.OffsetImm) return true;
1376 int64_t Val = Memory.OffsetImm->getValue();
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00001377 return (Val >= 0 && Val < 4096);
1378 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001379 bool isMemImm12Offset() const {
Jim Grosbach95466ce2011-08-08 20:59:31 +00001380 // If we have an immediate that's not a constant, treat it as a label
1381 // reference needing a fixup. If it is a constant, it's something else
1382 // and we reject it.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001383 if (isImm() && !isa<MCConstantExpr>(getImm()))
Jim Grosbach95466ce2011-08-08 20:59:31 +00001384 return true;
1385
Chad Rosier41099832012-09-11 23:02:35 +00001386 if (!isMem() || Memory.OffsetRegNum != 0 || Memory.Alignment != 0)
Jim Grosbachd3595712011-08-03 23:50:40 +00001387 return false;
1388 // Immediate offset in range [-4095, 4095].
Jim Grosbach871dff72011-10-11 15:59:20 +00001389 if (!Memory.OffsetImm) return true;
1390 int64_t Val = Memory.OffsetImm->getValue();
Owen Anderson967674d2011-08-29 19:36:44 +00001391 return (Val > -4096 && Val < 4096) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001392 }
1393 bool isPostIdxImm8() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001394 if (!isImm()) return false;
Jim Grosbachd3595712011-08-03 23:50:40 +00001395 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1396 if (!CE) return false;
1397 int64_t Val = CE->getValue();
Owen Andersonf02d98d2011-08-29 17:17:09 +00001398 return (Val > -256 && Val < 256) || (Val == INT32_MIN);
Jim Grosbachd3595712011-08-03 23:50:40 +00001399 }
Jim Grosbach93981412011-10-11 21:55:36 +00001400 bool isPostIdxImm8s4() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001401 if (!isImm()) return false;
Jim Grosbach93981412011-10-11 21:55:36 +00001402 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1403 if (!CE) return false;
1404 int64_t Val = CE->getValue();
1405 return ((Val & 3) == 0 && Val >= -1020 && Val <= 1020) ||
1406 (Val == INT32_MIN);
1407 }
Jim Grosbachd3595712011-08-03 23:50:40 +00001408
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001409 bool isMSRMask() const { return Kind == k_MSRMask; }
Tim Northoveree843ef2014-08-15 10:47:12 +00001410 bool isBankedReg() const { return Kind == k_BankedReg; }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00001411 bool isProcIFlags() const { return Kind == k_ProcIFlags; }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001412
Jim Grosbach741cd732011-10-17 22:26:03 +00001413 // NEON operands.
Jim Grosbach2f50e922011-12-15 21:44:33 +00001414 bool isSingleSpacedVectorList() const {
1415 return Kind == k_VectorList && !VectorList.isDoubleSpaced;
1416 }
1417 bool isDoubleSpacedVectorList() const {
1418 return Kind == k_VectorList && VectorList.isDoubleSpaced;
1419 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001420 bool isVecListOneD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001421 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00001422 return VectorList.Count == 1;
1423 }
1424
Jim Grosbachc988e0c2012-03-05 19:33:30 +00001425 bool isVecListDPair() const {
1426 if (!isSingleSpacedVectorList()) return false;
1427 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1428 .contains(VectorList.RegNum));
1429 }
1430
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001431 bool isVecListThreeD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001432 if (!isSingleSpacedVectorList()) return false;
Jim Grosbachc4360fe2011-10-21 20:02:19 +00001433 return VectorList.Count == 3;
1434 }
1435
Jim Grosbach846bcff2011-10-21 20:35:01 +00001436 bool isVecListFourD() const {
Jim Grosbach2f50e922011-12-15 21:44:33 +00001437 if (!isSingleSpacedVectorList()) return false;
Jim Grosbach846bcff2011-10-21 20:35:01 +00001438 return VectorList.Count == 4;
1439 }
1440
Jim Grosbache5307f92012-03-05 21:43:40 +00001441 bool isVecListDPairSpaced() const {
Kevin Enderby56113982014-03-26 21:54:11 +00001442 if (Kind != k_VectorList) return false;
Kevin Enderby816ca272012-03-20 17:41:51 +00001443 if (isSingleSpacedVectorList()) return false;
Jim Grosbache5307f92012-03-05 21:43:40 +00001444 return (ARMMCRegisterClasses[ARM::DPairSpcRegClassID]
1445 .contains(VectorList.RegNum));
1446 }
1447
Jim Grosbachac2af3f2012-01-23 23:20:46 +00001448 bool isVecListThreeQ() const {
1449 if (!isDoubleSpacedVectorList()) return false;
1450 return VectorList.Count == 3;
1451 }
1452
Jim Grosbach1e946a42012-01-24 00:43:12 +00001453 bool isVecListFourQ() const {
1454 if (!isDoubleSpacedVectorList()) return false;
1455 return VectorList.Count == 4;
1456 }
1457
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001458 bool isSingleSpacedVectorAllLanes() const {
1459 return Kind == k_VectorListAllLanes && !VectorList.isDoubleSpaced;
1460 }
1461 bool isDoubleSpacedVectorAllLanes() const {
1462 return Kind == k_VectorListAllLanes && VectorList.isDoubleSpaced;
1463 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001464 bool isVecListOneDAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001465 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00001466 return VectorList.Count == 1;
1467 }
1468
Jim Grosbach13a292c2012-03-06 22:01:44 +00001469 bool isVecListDPairAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001470 if (!isSingleSpacedVectorAllLanes()) return false;
Jim Grosbach13a292c2012-03-06 22:01:44 +00001471 return (ARMMCRegisterClasses[ARM::DPairRegClassID]
1472 .contains(VectorList.RegNum));
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001473 }
1474
Jim Grosbached428bc2012-03-06 23:10:38 +00001475 bool isVecListDPairSpacedAllLanes() const {
Jim Grosbachc5af54e2011-12-21 00:38:54 +00001476 if (!isDoubleSpacedVectorAllLanes()) return false;
Jim Grosbach3ecf9762011-11-30 18:21:25 +00001477 return VectorList.Count == 2;
1478 }
1479
Jim Grosbachb78403c2012-01-24 23:47:04 +00001480 bool isVecListThreeDAllLanes() const {
1481 if (!isSingleSpacedVectorAllLanes()) return false;
1482 return VectorList.Count == 3;
1483 }
1484
1485 bool isVecListThreeQAllLanes() const {
1486 if (!isDoubleSpacedVectorAllLanes()) return false;
1487 return VectorList.Count == 3;
1488 }
1489
Jim Grosbach086cbfa2012-01-25 00:01:08 +00001490 bool isVecListFourDAllLanes() const {
1491 if (!isSingleSpacedVectorAllLanes()) return false;
1492 return VectorList.Count == 4;
1493 }
1494
1495 bool isVecListFourQAllLanes() const {
1496 if (!isDoubleSpacedVectorAllLanes()) return false;
1497 return VectorList.Count == 4;
1498 }
1499
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001500 bool isSingleSpacedVectorIndexed() const {
1501 return Kind == k_VectorListIndexed && !VectorList.isDoubleSpaced;
1502 }
1503 bool isDoubleSpacedVectorIndexed() const {
1504 return Kind == k_VectorListIndexed && VectorList.isDoubleSpaced;
1505 }
Jim Grosbach04945c42011-12-02 00:35:16 +00001506 bool isVecListOneDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001507 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbach04945c42011-12-02 00:35:16 +00001508 return VectorList.Count == 1 && VectorList.LaneIndex <= 7;
1509 }
1510
Jim Grosbachda511042011-12-14 23:35:06 +00001511 bool isVecListOneDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001512 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001513 return VectorList.Count == 1 && VectorList.LaneIndex <= 3;
1514 }
1515
1516 bool isVecListOneDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001517 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001518 return VectorList.Count == 1 && VectorList.LaneIndex <= 1;
1519 }
1520
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001521 bool isVecListTwoDByteIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001522 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00001523 return VectorList.Count == 2 && VectorList.LaneIndex <= 7;
1524 }
1525
Jim Grosbachda511042011-12-14 23:35:06 +00001526 bool isVecListTwoDHWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001527 if (!isSingleSpacedVectorIndexed()) return false;
1528 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1529 }
1530
1531 bool isVecListTwoQWordIndexed() const {
1532 if (!isDoubleSpacedVectorIndexed()) return false;
1533 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1534 }
1535
1536 bool isVecListTwoQHWordIndexed() const {
1537 if (!isDoubleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001538 return VectorList.Count == 2 && VectorList.LaneIndex <= 3;
1539 }
1540
1541 bool isVecListTwoDWordIndexed() const {
Jim Grosbach75e2ab52011-12-20 19:21:26 +00001542 if (!isSingleSpacedVectorIndexed()) return false;
Jim Grosbachda511042011-12-14 23:35:06 +00001543 return VectorList.Count == 2 && VectorList.LaneIndex <= 1;
1544 }
1545
Jim Grosbacha8b444b2012-01-23 21:53:26 +00001546 bool isVecListThreeDByteIndexed() const {
1547 if (!isSingleSpacedVectorIndexed()) return false;
1548 return VectorList.Count == 3 && VectorList.LaneIndex <= 7;
1549 }
1550
1551 bool isVecListThreeDHWordIndexed() const {
1552 if (!isSingleSpacedVectorIndexed()) return false;
1553 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1554 }
1555
1556 bool isVecListThreeQWordIndexed() const {
1557 if (!isDoubleSpacedVectorIndexed()) return false;
1558 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1559 }
1560
1561 bool isVecListThreeQHWordIndexed() const {
1562 if (!isDoubleSpacedVectorIndexed()) return false;
1563 return VectorList.Count == 3 && VectorList.LaneIndex <= 3;
1564 }
1565
1566 bool isVecListThreeDWordIndexed() const {
1567 if (!isSingleSpacedVectorIndexed()) return false;
1568 return VectorList.Count == 3 && VectorList.LaneIndex <= 1;
1569 }
1570
Jim Grosbach14952a02012-01-24 18:37:25 +00001571 bool isVecListFourDByteIndexed() const {
1572 if (!isSingleSpacedVectorIndexed()) return false;
1573 return VectorList.Count == 4 && VectorList.LaneIndex <= 7;
1574 }
1575
1576 bool isVecListFourDHWordIndexed() const {
1577 if (!isSingleSpacedVectorIndexed()) return false;
1578 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1579 }
1580
1581 bool isVecListFourQWordIndexed() const {
1582 if (!isDoubleSpacedVectorIndexed()) return false;
1583 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1584 }
1585
1586 bool isVecListFourQHWordIndexed() const {
1587 if (!isDoubleSpacedVectorIndexed()) return false;
1588 return VectorList.Count == 4 && VectorList.LaneIndex <= 3;
1589 }
1590
1591 bool isVecListFourDWordIndexed() const {
1592 if (!isSingleSpacedVectorIndexed()) return false;
1593 return VectorList.Count == 4 && VectorList.LaneIndex <= 1;
1594 }
1595
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001596 bool isVectorIndex8() const {
1597 if (Kind != k_VectorIndex) return false;
1598 return VectorIndex.Val < 8;
1599 }
1600 bool isVectorIndex16() const {
1601 if (Kind != k_VectorIndex) return false;
1602 return VectorIndex.Val < 4;
1603 }
1604 bool isVectorIndex32() const {
1605 if (Kind != k_VectorIndex) return false;
1606 return VectorIndex.Val < 2;
1607 }
1608
Jim Grosbach741cd732011-10-17 22:26:03 +00001609 bool isNEONi8splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001610 if (!isImm()) return false;
Jim Grosbach741cd732011-10-17 22:26:03 +00001611 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1612 // Must be a constant.
1613 if (!CE) return false;
1614 int64_t Value = CE->getValue();
1615 // i8 value splatted across 8 bytes. The immediate is just the 8 byte
1616 // value.
Jim Grosbach741cd732011-10-17 22:26:03 +00001617 return Value >= 0 && Value < 256;
1618 }
Jim Grosbachd0637bf2011-10-07 23:56:00 +00001619
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001620 bool isNEONi16splat() const {
Stepan Dyatkovskiy00dcc0f2014-04-24 06:03:01 +00001621 if (isNEONByteReplicate(2))
1622 return false; // Leave that for bytes replication and forbid by default.
1623 if (!isImm())
1624 return false;
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001625 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1626 // Must be a constant.
1627 if (!CE) return false;
Renato Golinf5dd1da2014-09-25 11:31:24 +00001628 unsigned Value = CE->getValue();
1629 return ARM_AM::isNEONi16splat(Value);
1630 }
1631
1632 bool isNEONi16splatNot() const {
1633 if (!isImm())
1634 return false;
1635 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1636 // Must be a constant.
1637 if (!CE) return false;
1638 unsigned Value = CE->getValue();
1639 return ARM_AM::isNEONi16splat(~Value & 0xffff);
Jim Grosbachcda32ae2011-10-17 23:09:09 +00001640 }
1641
Jim Grosbach8211c052011-10-18 00:22:00 +00001642 bool isNEONi32splat() const {
Stepan Dyatkovskiy00dcc0f2014-04-24 06:03:01 +00001643 if (isNEONByteReplicate(4))
1644 return false; // Leave that for bytes replication and forbid by default.
1645 if (!isImm())
1646 return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1648 // Must be a constant.
1649 if (!CE) return false;
Renato Golinf5dd1da2014-09-25 11:31:24 +00001650 unsigned Value = CE->getValue();
1651 return ARM_AM::isNEONi32splat(Value);
1652 }
1653
1654 bool isNEONi32splatNot() const {
1655 if (!isImm())
1656 return false;
1657 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1658 // Must be a constant.
1659 if (!CE) return false;
1660 unsigned Value = CE->getValue();
1661 return ARM_AM::isNEONi32splat(~Value);
Jim Grosbach8211c052011-10-18 00:22:00 +00001662 }
1663
Stepan Dyatkovskiy00dcc0f2014-04-24 06:03:01 +00001664 bool isNEONByteReplicate(unsigned NumBytes) const {
1665 if (!isImm())
1666 return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001667 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1668 // Must be a constant.
Stepan Dyatkovskiy00dcc0f2014-04-24 06:03:01 +00001669 if (!CE)
1670 return false;
1671 int64_t Value = CE->getValue();
1672 if (!Value)
1673 return false; // Don't bother with zero.
1674
1675 unsigned char B = Value & 0xff;
1676 for (unsigned i = 1; i < NumBytes; ++i) {
1677 Value >>= 8;
1678 if ((Value & 0xff) != B)
1679 return false;
1680 }
1681 return true;
1682 }
1683 bool isNEONi16ByteReplicate() const { return isNEONByteReplicate(2); }
1684 bool isNEONi32ByteReplicate() const { return isNEONByteReplicate(4); }
1685 bool isNEONi32vmov() const {
1686 if (isNEONByteReplicate(4))
1687 return false; // Let it to be classified as byte-replicate case.
1688 if (!isImm())
1689 return false;
1690 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1691 // Must be a constant.
1692 if (!CE)
1693 return false;
Jim Grosbach8211c052011-10-18 00:22:00 +00001694 int64_t Value = CE->getValue();
1695 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1696 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
Renato Golinf5dd1da2014-09-25 11:31:24 +00001697 // FIXME: This is probably wrong and a copy and paste from previous example
Jim Grosbach8211c052011-10-18 00:22:00 +00001698 return (Value >= 0 && Value < 256) ||
1699 (Value >= 0x0100 && Value <= 0xff00) ||
1700 (Value >= 0x010000 && Value <= 0xff0000) ||
1701 (Value >= 0x01000000 && Value <= 0xff000000) ||
1702 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1703 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1704 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00001705 bool isNEONi32vmovNeg() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001706 if (!isImm()) return false;
Jim Grosbach045b6c72011-12-19 23:51:07 +00001707 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1708 // Must be a constant.
1709 if (!CE) return false;
1710 int64_t Value = ~CE->getValue();
1711 // i32 value with set bits only in one byte X000, 0X00, 00X0, or 000X,
1712 // for VMOV/VMVN only, 00Xf or 0Xff are also accepted.
Renato Golinf5dd1da2014-09-25 11:31:24 +00001713 // FIXME: This is probably wrong and a copy and paste from previous example
Jim Grosbach045b6c72011-12-19 23:51:07 +00001714 return (Value >= 0 && Value < 256) ||
1715 (Value >= 0x0100 && Value <= 0xff00) ||
1716 (Value >= 0x010000 && Value <= 0xff0000) ||
1717 (Value >= 0x01000000 && Value <= 0xff000000) ||
1718 (Value >= 0x01ff && Value <= 0xffff && (Value & 0xff) == 0xff) ||
1719 (Value >= 0x01ffff && Value <= 0xffffff && (Value & 0xffff) == 0xffff);
1720 }
Jim Grosbach8211c052011-10-18 00:22:00 +00001721
Jim Grosbache4454e02011-10-18 16:18:11 +00001722 bool isNEONi64splat() const {
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00001723 if (!isImm()) return false;
Jim Grosbache4454e02011-10-18 16:18:11 +00001724 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1725 // Must be a constant.
1726 if (!CE) return false;
1727 uint64_t Value = CE->getValue();
1728 // i64 value with each byte being either 0 or 0xff.
1729 for (unsigned i = 0; i < 8; ++i)
1730 if ((Value & 0xff) != 0 && (Value & 0xff) != 0xff) return false;
1731 return true;
1732 }
1733
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001734 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001735 // Add as immediates when possible. Null MCExpr = 0.
Craig Topper062a2ba2014-04-25 05:30:21 +00001736 if (!Expr)
Chris Lattner5d6f6a02010-10-29 00:27:31 +00001737 Inst.addOperand(MCOperand::CreateImm(0));
1738 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001739 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1740 else
1741 Inst.addOperand(MCOperand::CreateExpr(Expr));
1742 }
1743
Daniel Dunbard8042b72010-08-11 06:36:53 +00001744 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
Daniel Dunbar188b47b2010-08-11 06:37:20 +00001745 assert(N == 2 && "Invalid number of operands!");
Daniel Dunbard8042b72010-08-11 06:36:53 +00001746 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
Jim Grosbach968c9272010-12-06 18:30:57 +00001747 unsigned RegNum = getCondCode() == ARMCC::AL ? 0: ARM::CPSR;
1748 Inst.addOperand(MCOperand::CreateReg(RegNum));
Daniel Dunbard8042b72010-08-11 06:36:53 +00001749 }
1750
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00001751 void addCoprocNumOperands(MCInst &Inst, unsigned N) const {
1752 assert(N == 1 && "Invalid number of operands!");
1753 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1754 }
1755
Jim Grosbach48399582011-10-12 17:34:41 +00001756 void addCoprocRegOperands(MCInst &Inst, unsigned N) const {
1757 assert(N == 1 && "Invalid number of operands!");
1758 Inst.addOperand(MCOperand::CreateImm(getCoproc()));
1759 }
1760
1761 void addCoprocOptionOperands(MCInst &Inst, unsigned N) const {
1762 assert(N == 1 && "Invalid number of operands!");
1763 Inst.addOperand(MCOperand::CreateImm(CoprocOption.Val));
1764 }
1765
Jim Grosbach3d1eac82011-08-26 21:43:41 +00001766 void addITMaskOperands(MCInst &Inst, unsigned N) const {
1767 assert(N == 1 && "Invalid number of operands!");
1768 Inst.addOperand(MCOperand::CreateImm(ITMask.Mask));
1769 }
1770
1771 void addITCondCodeOperands(MCInst &Inst, unsigned N) const {
1772 assert(N == 1 && "Invalid number of operands!");
1773 Inst.addOperand(MCOperand::CreateImm(unsigned(getCondCode())));
1774 }
1775
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00001776 void addCCOutOperands(MCInst &Inst, unsigned N) const {
1777 assert(N == 1 && "Invalid number of operands!");
1778 Inst.addOperand(MCOperand::CreateReg(getReg()));
1779 }
1780
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00001781 void addRegOperands(MCInst &Inst, unsigned N) const {
1782 assert(N == 1 && "Invalid number of operands!");
1783 Inst.addOperand(MCOperand::CreateReg(getReg()));
1784 }
1785
Jim Grosbachac798e12011-07-25 20:49:51 +00001786 void addRegShiftedRegOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001787 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001788 assert(isRegShiftedReg() &&
Alp Tokerf907b892013-12-05 05:44:44 +00001789 "addRegShiftedRegOperands() on non-RegShiftedReg!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001790 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.SrcReg));
1791 Inst.addOperand(MCOperand::CreateReg(RegShiftedReg.ShiftReg));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001792 Inst.addOperand(MCOperand::CreateImm(
Jim Grosbachac798e12011-07-25 20:49:51 +00001793 ARM_AM::getSORegOpc(RegShiftedReg.ShiftTy, RegShiftedReg.ShiftImm)));
Jim Grosbach7dcd1352011-07-13 17:50:29 +00001794 }
1795
Jim Grosbachac798e12011-07-25 20:49:51 +00001796 void addRegShiftedImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson04912702011-07-21 23:38:37 +00001797 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00001798 assert(isRegShiftedImm() &&
Alp Tokerf907b892013-12-05 05:44:44 +00001799 "addRegShiftedImmOperands() on non-RegShiftedImm!");
Jim Grosbachac798e12011-07-25 20:49:51 +00001800 Inst.addOperand(MCOperand::CreateReg(RegShiftedImm.SrcReg));
Richard Bartonba5b0cc2012-04-25 18:00:18 +00001801 // Shift of #32 is encoded as 0 where permitted
1802 unsigned Imm = (RegShiftedImm.ShiftImm == 32 ? 0 : RegShiftedImm.ShiftImm);
Owen Andersonb595ed02011-07-21 18:54:16 +00001803 Inst.addOperand(MCOperand::CreateImm(
Richard Bartonba5b0cc2012-04-25 18:00:18 +00001804 ARM_AM::getSORegOpc(RegShiftedImm.ShiftTy, Imm)));
Owen Andersonb595ed02011-07-21 18:54:16 +00001805 }
1806
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001807 void addShifterImmOperands(MCInst &Inst, unsigned N) const {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001808 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00001809 Inst.addOperand(MCOperand::CreateImm((ShifterImm.isASR << 5) |
1810 ShifterImm.Imm));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00001811 }
1812
Bill Wendling8d2aa032010-11-08 23:49:57 +00001813 void addRegListOperands(MCInst &Inst, unsigned N) const {
Bill Wendling2cae3272010-11-09 22:44:22 +00001814 assert(N == 1 && "Invalid number of operands!");
Bill Wendlingbed94652010-11-09 23:28:44 +00001815 const SmallVectorImpl<unsigned> &RegList = getRegList();
1816 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00001817 I = RegList.begin(), E = RegList.end(); I != E; ++I)
1818 Inst.addOperand(MCOperand::CreateReg(*I));
Bill Wendling8d2aa032010-11-08 23:49:57 +00001819 }
1820
Bill Wendling9898ac92010-11-17 04:32:08 +00001821 void addDPRRegListOperands(MCInst &Inst, unsigned N) const {
1822 addRegListOperands(Inst, N);
1823 }
1824
1825 void addSPRRegListOperands(MCInst &Inst, unsigned N) const {
1826 addRegListOperands(Inst, N);
1827 }
1828
Jim Grosbach833b9d32011-07-27 20:15:40 +00001829 void addRotImmOperands(MCInst &Inst, unsigned N) const {
1830 assert(N == 1 && "Invalid number of operands!");
1831 // Encoded as val>>3. The printer handles display as 8, 16, 24.
1832 Inst.addOperand(MCOperand::CreateImm(RotImm.Imm >> 3));
1833 }
1834
Jim Grosbach864b6092011-07-28 21:34:26 +00001835 void addBitfieldOperands(MCInst &Inst, unsigned N) const {
1836 assert(N == 1 && "Invalid number of operands!");
1837 // Munge the lsb/width into a bitfield mask.
1838 unsigned lsb = Bitfield.LSB;
1839 unsigned width = Bitfield.Width;
1840 // Make a 32-bit mask w/ the referenced bits clear and all other bits set.
1841 uint32_t Mask = ~(((uint32_t)0xffffffff >> lsb) << (32 - width) >>
1842 (32 - (lsb + width)));
1843 Inst.addOperand(MCOperand::CreateImm(Mask));
1844 }
1845
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00001846 void addImmOperands(MCInst &Inst, unsigned N) const {
1847 assert(N == 1 && "Invalid number of operands!");
1848 addExpr(Inst, getImm());
1849 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00001850
Jim Grosbachea231912011-12-22 22:19:05 +00001851 void addFBits16Operands(MCInst &Inst, unsigned N) const {
1852 assert(N == 1 && "Invalid number of operands!");
1853 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1854 Inst.addOperand(MCOperand::CreateImm(16 - CE->getValue()));
1855 }
1856
1857 void addFBits32Operands(MCInst &Inst, unsigned N) const {
1858 assert(N == 1 && "Invalid number of operands!");
1859 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1860 Inst.addOperand(MCOperand::CreateImm(32 - CE->getValue()));
1861 }
1862
Jim Grosbache7fbce72011-10-03 23:38:36 +00001863 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1864 assert(N == 1 && "Invalid number of operands!");
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00001865 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1866 int Val = ARM_AM::getFP32Imm(APInt(32, CE->getValue()));
1867 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbache7fbce72011-10-03 23:38:36 +00001868 }
1869
Jim Grosbach7db8d692011-09-08 22:07:06 +00001870 void addImm8s4Operands(MCInst &Inst, unsigned N) const {
1871 assert(N == 1 && "Invalid number of operands!");
1872 // FIXME: We really want to scale the value here, but the LDRD/STRD
1873 // instruction don't encode operands that way yet.
1874 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1875 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1876 }
1877
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001878 void addImm0_1020s4Operands(MCInst &Inst, unsigned N) const {
1879 assert(N == 1 && "Invalid number of operands!");
1880 // The immediate is scaled by four in the encoding and is stored
1881 // in the MCInst as such. Lop off the low two bits here.
1882 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1883 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1884 }
1885
Jim Grosbach930f2f62012-04-05 20:57:13 +00001886 void addImm0_508s4NegOperands(MCInst &Inst, unsigned N) const {
1887 assert(N == 1 && "Invalid number of operands!");
1888 // The immediate is scaled by four in the encoding and is stored
1889 // in the MCInst as such. Lop off the low two bits here.
1890 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1891 Inst.addOperand(MCOperand::CreateImm(-(CE->getValue() / 4)));
1892 }
1893
Jim Grosbach0a0b3072011-08-24 21:22:15 +00001894 void addImm0_508s4Operands(MCInst &Inst, unsigned N) const {
1895 assert(N == 1 && "Invalid number of operands!");
1896 // The immediate is scaled by four in the encoding and is stored
1897 // in the MCInst as such. Lop off the low two bits here.
1898 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1899 Inst.addOperand(MCOperand::CreateImm(CE->getValue() / 4));
1900 }
1901
Jim Grosbach475c6db2011-07-25 23:09:14 +00001902 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1903 assert(N == 1 && "Invalid number of operands!");
1904 // The constant encodes as the immediate-1, and we store in the instruction
1905 // the bits as encoded, so subtract off one here.
1906 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1907 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1908 }
1909
Jim Grosbach801e0a32011-07-22 23:16:18 +00001910 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1911 assert(N == 1 && "Invalid number of operands!");
1912 // The constant encodes as the immediate-1, and we store in the instruction
1913 // the bits as encoded, so subtract off one here.
1914 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1915 Inst.addOperand(MCOperand::CreateImm(CE->getValue() - 1));
1916 }
1917
Jim Grosbach46dd4132011-08-17 21:51:27 +00001918 void addImmThumbSROperands(MCInst &Inst, unsigned N) const {
1919 assert(N == 1 && "Invalid number of operands!");
1920 // The constant encodes as the immediate, except for 32, which encodes as
1921 // zero.
1922 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1923 unsigned Imm = CE->getValue();
1924 Inst.addOperand(MCOperand::CreateImm((Imm == 32 ? 0 : Imm)));
1925 }
1926
Jim Grosbach27c1e252011-07-21 17:23:04 +00001927 void addPKHASRImmOperands(MCInst &Inst, unsigned N) const {
1928 assert(N == 1 && "Invalid number of operands!");
1929 // An ASR value of 32 encodes as 0, so that's how we want to add it to
1930 // the instruction as well.
1931 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1932 int Val = CE->getValue();
1933 Inst.addOperand(MCOperand::CreateImm(Val == 32 ? 0 : Val));
1934 }
1935
Jim Grosbachb009a872011-10-28 22:36:30 +00001936 void addT2SOImmNotOperands(MCInst &Inst, unsigned N) const {
1937 assert(N == 1 && "Invalid number of operands!");
1938 // The operand is actually a t2_so_imm, but we have its bitwise
1939 // negation in the assembly source, so twiddle it here.
1940 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1941 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1942 }
1943
Jim Grosbach30506252011-12-08 00:31:07 +00001944 void addT2SOImmNegOperands(MCInst &Inst, unsigned N) const {
1945 assert(N == 1 && "Invalid number of operands!");
1946 // The operand is actually a t2_so_imm, but we have its
1947 // negation in the assembly source, so twiddle it here.
1948 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1949 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1950 }
1951
Jim Grosbach930f2f62012-04-05 20:57:13 +00001952 void addImm0_4095NegOperands(MCInst &Inst, unsigned N) const {
1953 assert(N == 1 && "Invalid number of operands!");
1954 // The operand is actually an imm0_4095, but we have its
1955 // negation in the assembly source, so twiddle it here.
1956 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1957 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
1958 }
1959
Mihai Popad36cbaa2013-07-03 09:21:44 +00001960 void addUnsignedOffset_b8s2Operands(MCInst &Inst, unsigned N) const {
1961 if(const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm())) {
1962 Inst.addOperand(MCOperand::CreateImm(CE->getValue() >> 2));
1963 return;
1964 }
1965
1966 const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
1967 assert(SR && "Unknown value type!");
1968 Inst.addOperand(MCOperand::CreateExpr(SR));
1969 }
1970
Mihai Popa8a9da5b2013-07-22 15:49:36 +00001971 void addThumbMemPCOperands(MCInst &Inst, unsigned N) const {
1972 assert(N == 1 && "Invalid number of operands!");
1973 if (isImm()) {
1974 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1975 if (CE) {
1976 Inst.addOperand(MCOperand::CreateImm(CE->getValue()));
1977 return;
1978 }
1979
1980 const MCSymbolRefExpr *SR = dyn_cast<MCSymbolRefExpr>(Imm.Val);
1981 assert(SR && "Unknown value type!");
1982 Inst.addOperand(MCOperand::CreateExpr(SR));
1983 return;
1984 }
1985
1986 assert(isMem() && "Unknown value type!");
1987 assert(isa<MCConstantExpr>(Memory.OffsetImm) && "Unknown value type!");
1988 Inst.addOperand(MCOperand::CreateImm(Memory.OffsetImm->getValue()));
1989 }
1990
Jim Grosbach3d785ed2011-10-28 22:50:54 +00001991 void addARMSOImmNotOperands(MCInst &Inst, unsigned N) const {
1992 assert(N == 1 && "Invalid number of operands!");
1993 // The operand is actually a so_imm, but we have its bitwise
1994 // negation in the assembly source, so twiddle it here.
1995 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
1996 Inst.addOperand(MCOperand::CreateImm(~CE->getValue()));
1997 }
1998
Jim Grosbach30506252011-12-08 00:31:07 +00001999 void addARMSOImmNegOperands(MCInst &Inst, unsigned N) const {
2000 assert(N == 1 && "Invalid number of operands!");
2001 // The operand is actually a so_imm, but we have its
2002 // negation in the assembly source, so twiddle it here.
2003 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2004 Inst.addOperand(MCOperand::CreateImm(-CE->getValue()));
2005 }
2006
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002007 void addMemBarrierOptOperands(MCInst &Inst, unsigned N) const {
2008 assert(N == 1 && "Invalid number of operands!");
2009 Inst.addOperand(MCOperand::CreateImm(unsigned(getMemBarrierOpt())));
2010 }
2011
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +00002012 void addInstSyncBarrierOptOperands(MCInst &Inst, unsigned N) const {
2013 assert(N == 1 && "Invalid number of operands!");
2014 Inst.addOperand(MCOperand::CreateImm(unsigned(getInstSyncBarrierOpt())));
2015 }
2016
Jim Grosbachd3595712011-08-03 23:50:40 +00002017 void addMemNoOffsetOperands(MCInst &Inst, unsigned N) const {
2018 assert(N == 1 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002019 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Bruno Cardoso Lopesf170f8b2011-03-24 21:04:58 +00002020 }
2021
Jim Grosbach94298a92012-01-18 22:46:46 +00002022 void addMemPCRelImm12Operands(MCInst &Inst, unsigned N) const {
2023 assert(N == 1 && "Invalid number of operands!");
2024 int32_t Imm = Memory.OffsetImm->getValue();
Jim Grosbach94298a92012-01-18 22:46:46 +00002025 Inst.addOperand(MCOperand::CreateImm(Imm));
2026 }
2027
Jiangning Liu10dd40e2012-08-02 08:13:13 +00002028 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
2029 assert(N == 1 && "Invalid number of operands!");
2030 assert(isImm() && "Not an immediate!");
2031
2032 // If we have an immediate that's not a constant, treat it as a label
2033 // reference needing a fixup.
2034 if (!isa<MCConstantExpr>(getImm())) {
2035 Inst.addOperand(MCOperand::CreateExpr(getImm()));
2036 return;
2037 }
2038
2039 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2040 int Val = CE->getValue();
2041 Inst.addOperand(MCOperand::CreateImm(Val));
2042 }
2043
Jim Grosbacha95ec992011-10-11 17:29:55 +00002044 void addAlignedMemoryOperands(MCInst &Inst, unsigned N) const {
2045 assert(N == 2 && "Invalid number of operands!");
2046 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
2047 Inst.addOperand(MCOperand::CreateImm(Memory.Alignment));
2048 }
2049
Kevin Enderby488f20b2014-04-10 20:18:58 +00002050 void addDupAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const {
2051 addAlignedMemoryOperands(Inst, N);
2052 }
2053
2054 void addAlignedMemoryNoneOperands(MCInst &Inst, unsigned N) const {
2055 addAlignedMemoryOperands(Inst, N);
2056 }
2057
2058 void addAlignedMemory16Operands(MCInst &Inst, unsigned N) const {
2059 addAlignedMemoryOperands(Inst, N);
2060 }
2061
2062 void addDupAlignedMemory16Operands(MCInst &Inst, unsigned N) const {
2063 addAlignedMemoryOperands(Inst, N);
2064 }
2065
2066 void addAlignedMemory32Operands(MCInst &Inst, unsigned N) const {
2067 addAlignedMemoryOperands(Inst, N);
2068 }
2069
2070 void addDupAlignedMemory32Operands(MCInst &Inst, unsigned N) const {
2071 addAlignedMemoryOperands(Inst, N);
2072 }
2073
2074 void addAlignedMemory64Operands(MCInst &Inst, unsigned N) const {
2075 addAlignedMemoryOperands(Inst, N);
2076 }
2077
2078 void addDupAlignedMemory64Operands(MCInst &Inst, unsigned N) const {
2079 addAlignedMemoryOperands(Inst, N);
2080 }
2081
2082 void addAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const {
2083 addAlignedMemoryOperands(Inst, N);
2084 }
2085
2086 void addDupAlignedMemory64or128Operands(MCInst &Inst, unsigned N) const {
2087 addAlignedMemoryOperands(Inst, N);
2088 }
2089
2090 void addAlignedMemory64or128or256Operands(MCInst &Inst, unsigned N) const {
2091 addAlignedMemoryOperands(Inst, N);
2092 }
2093
Jim Grosbachd3595712011-08-03 23:50:40 +00002094 void addAddrMode2Operands(MCInst &Inst, unsigned N) const {
2095 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002096 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2097 if (!Memory.OffsetRegNum) {
Jim Grosbachd3595712011-08-03 23:50:40 +00002098 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2099 // Special case for #-0
2100 if (Val == INT32_MIN) Val = 0;
2101 if (Val < 0) Val = -Val;
2102 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
2103 } else {
2104 // For register offset, we encode the shift type and negation flag
2105 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00002106 Val = ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
2107 Memory.ShiftImm, Memory.ShiftType);
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002108 }
Jim Grosbach871dff72011-10-11 15:59:20 +00002109 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
2110 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00002111 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesab830502011-03-31 23:26:08 +00002112 }
2113
Jim Grosbachcd17c122011-08-04 23:01:30 +00002114 void addAM2OffsetImmOperands(MCInst &Inst, unsigned N) const {
2115 assert(N == 2 && "Invalid number of operands!");
2116 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2117 assert(CE && "non-constant AM2OffsetImm operand!");
2118 int32_t Val = CE->getValue();
2119 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2120 // Special case for #-0
2121 if (Val == INT32_MIN) Val = 0;
2122 if (Val < 0) Val = -Val;
2123 Val = ARM_AM::getAM2Opc(AddSub, Val, ARM_AM::no_shift);
2124 Inst.addOperand(MCOperand::CreateReg(0));
2125 Inst.addOperand(MCOperand::CreateImm(Val));
2126 }
2127
Jim Grosbach5b96b802011-08-10 20:29:19 +00002128 void addAddrMode3Operands(MCInst &Inst, unsigned N) const {
2129 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00002130 // If we have an immediate that's not a constant, treat it as a label
2131 // reference needing a fixup. If it is a constant, it's something else
2132 // and we reject it.
2133 if (isImm()) {
2134 Inst.addOperand(MCOperand::CreateExpr(getImm()));
2135 Inst.addOperand(MCOperand::CreateReg(0));
2136 Inst.addOperand(MCOperand::CreateImm(0));
2137 return;
2138 }
2139
Jim Grosbach871dff72011-10-11 15:59:20 +00002140 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2141 if (!Memory.OffsetRegNum) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00002142 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2143 // Special case for #-0
2144 if (Val == INT32_MIN) Val = 0;
2145 if (Val < 0) Val = -Val;
2146 Val = ARM_AM::getAM3Opc(AddSub, Val);
2147 } else {
2148 // For register offset, we encode the shift type and negation flag
2149 // here.
Jim Grosbach871dff72011-10-11 15:59:20 +00002150 Val = ARM_AM::getAM3Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add, 0);
Jim Grosbach5b96b802011-08-10 20:29:19 +00002151 }
Jim Grosbach871dff72011-10-11 15:59:20 +00002152 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
2153 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach5b96b802011-08-10 20:29:19 +00002154 Inst.addOperand(MCOperand::CreateImm(Val));
2155 }
2156
2157 void addAM3OffsetOperands(MCInst &Inst, unsigned N) const {
2158 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002159 if (Kind == k_PostIndexRegister) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00002160 int32_t Val =
2161 ARM_AM::getAM3Opc(PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub, 0);
2162 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
2163 Inst.addOperand(MCOperand::CreateImm(Val));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00002164 return;
Jim Grosbach5b96b802011-08-10 20:29:19 +00002165 }
2166
2167 // Constant offset.
2168 const MCConstantExpr *CE = static_cast<const MCConstantExpr*>(getImm());
2169 int32_t Val = CE->getValue();
2170 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2171 // Special case for #-0
2172 if (Val == INT32_MIN) Val = 0;
2173 if (Val < 0) Val = -Val;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00002174 Val = ARM_AM::getAM3Opc(AddSub, Val);
Jim Grosbach5b96b802011-08-10 20:29:19 +00002175 Inst.addOperand(MCOperand::CreateReg(0));
2176 Inst.addOperand(MCOperand::CreateImm(Val));
2177 }
2178
Jim Grosbachd3595712011-08-03 23:50:40 +00002179 void addAddrMode5Operands(MCInst &Inst, unsigned N) const {
2180 assert(N == 2 && "Invalid number of operands!");
Jim Grosbachfb2f1d62011-11-01 01:24:45 +00002181 // If we have an immediate that's not a constant, treat it as a label
2182 // reference needing a fixup. If it is a constant, it's something else
2183 // and we reject it.
2184 if (isImm()) {
2185 Inst.addOperand(MCOperand::CreateExpr(getImm()));
2186 Inst.addOperand(MCOperand::CreateImm(0));
2187 return;
2188 }
2189
Jim Grosbachd3595712011-08-03 23:50:40 +00002190 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00002191 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00002192 ARM_AM::AddrOpc AddSub = Val < 0 ? ARM_AM::sub : ARM_AM::add;
2193 // Special case for #-0
2194 if (Val == INT32_MIN) Val = 0;
2195 if (Val < 0) Val = -Val;
2196 Val = ARM_AM::getAM5Opc(AddSub, Val);
Jim Grosbach871dff72011-10-11 15:59:20 +00002197 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00002198 Inst.addOperand(MCOperand::CreateImm(Val));
Bruno Cardoso Lopesbda36322011-04-04 17:18:19 +00002199 }
2200
Jim Grosbach7db8d692011-09-08 22:07:06 +00002201 void addMemImm8s4OffsetOperands(MCInst &Inst, unsigned N) const {
2202 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach8648c102011-12-19 23:06:24 +00002203 // If we have an immediate that's not a constant, treat it as a label
2204 // reference needing a fixup. If it is a constant, it's something else
2205 // and we reject it.
2206 if (isImm()) {
2207 Inst.addOperand(MCOperand::CreateExpr(getImm()));
2208 Inst.addOperand(MCOperand::CreateImm(0));
2209 return;
2210 }
2211
Jim Grosbach871dff72011-10-11 15:59:20 +00002212 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2213 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach7db8d692011-09-08 22:07:06 +00002214 Inst.addOperand(MCOperand::CreateImm(Val));
2215 }
2216
Jim Grosbacha05627e2011-09-09 18:37:27 +00002217 void addMemImm0_1020s4OffsetOperands(MCInst &Inst, unsigned N) const {
2218 assert(N == 2 && "Invalid number of operands!");
2219 // The lower two bits are always zero and as such are not encoded.
Jim Grosbach871dff72011-10-11 15:59:20 +00002220 int32_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() / 4 : 0;
2221 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha05627e2011-09-09 18:37:27 +00002222 Inst.addOperand(MCOperand::CreateImm(Val));
2223 }
2224
Jim Grosbachd3595712011-08-03 23:50:40 +00002225 void addMemImm8OffsetOperands(MCInst &Inst, unsigned N) const {
2226 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002227 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2228 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00002229 Inst.addOperand(MCOperand::CreateImm(Val));
Chris Lattner5d6f6a02010-10-29 00:27:31 +00002230 }
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002231
Jim Grosbach2392c532011-09-07 23:39:14 +00002232 void addMemPosImm8OffsetOperands(MCInst &Inst, unsigned N) const {
2233 addMemImm8OffsetOperands(Inst, N);
2234 }
2235
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00002236 void addMemNegImm8OffsetOperands(MCInst &Inst, unsigned N) const {
Jim Grosbach2392c532011-09-07 23:39:14 +00002237 addMemImm8OffsetOperands(Inst, N);
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00002238 }
2239
2240 void addMemUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
2241 assert(N == 2 && "Invalid number of operands!");
2242 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00002243 if (isImm()) {
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00002244 addExpr(Inst, getImm());
2245 Inst.addOperand(MCOperand::CreateImm(0));
2246 return;
2247 }
2248
2249 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00002250 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2251 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach5bfa8ba2011-09-07 20:58:57 +00002252 Inst.addOperand(MCOperand::CreateImm(Val));
2253 }
2254
Jim Grosbachd3595712011-08-03 23:50:40 +00002255 void addMemImm12OffsetOperands(MCInst &Inst, unsigned N) const {
2256 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach95466ce2011-08-08 20:59:31 +00002257 // If this is an immediate, it's a label reference.
Jim Grosbachc4d8d2f2011-12-22 22:02:35 +00002258 if (isImm()) {
Jim Grosbach95466ce2011-08-08 20:59:31 +00002259 addExpr(Inst, getImm());
2260 Inst.addOperand(MCOperand::CreateImm(0));
2261 return;
2262 }
2263
2264 // Otherwise, it's a normal memory reg+offset.
Jim Grosbach871dff72011-10-11 15:59:20 +00002265 int64_t Val = Memory.OffsetImm ? Memory.OffsetImm->getValue() : 0;
2266 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00002267 Inst.addOperand(MCOperand::CreateImm(Val));
Bill Wendling092a7bd2010-12-14 03:36:38 +00002268 }
Bill Wendling811c9362010-11-30 07:44:32 +00002269
Jim Grosbach05541f42011-09-19 22:21:13 +00002270 void addMemTBBOperands(MCInst &Inst, unsigned N) const {
2271 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002272 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
2273 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00002274 }
2275
2276 void addMemTBHOperands(MCInst &Inst, unsigned N) const {
2277 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002278 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
2279 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbach05541f42011-09-19 22:21:13 +00002280 }
2281
Jim Grosbachd3595712011-08-03 23:50:40 +00002282 void addMemRegOffsetOperands(MCInst &Inst, unsigned N) const {
2283 assert(N == 3 && "Invalid number of operands!");
Jim Grosbachee201fa2011-11-14 17:52:47 +00002284 unsigned Val =
2285 ARM_AM::getAM2Opc(Memory.isNegative ? ARM_AM::sub : ARM_AM::add,
2286 Memory.ShiftImm, Memory.ShiftType);
Jim Grosbach871dff72011-10-11 15:59:20 +00002287 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
2288 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00002289 Inst.addOperand(MCOperand::CreateImm(Val));
2290 }
2291
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00002292 void addT2MemRegOffsetOperands(MCInst &Inst, unsigned N) const {
2293 assert(N == 3 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002294 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
2295 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
2296 Inst.addOperand(MCOperand::CreateImm(Memory.ShiftImm));
Jim Grosbache0ebc1c2011-09-07 23:10:15 +00002297 }
2298
Jim Grosbachd3595712011-08-03 23:50:40 +00002299 void addMemThumbRROperands(MCInst &Inst, unsigned N) const {
2300 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002301 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
2302 Inst.addOperand(MCOperand::CreateReg(Memory.OffsetRegNum));
Jim Grosbachd3595712011-08-03 23:50:40 +00002303 }
2304
Jim Grosbach3fe94e32011-08-19 17:55:24 +00002305 void addMemThumbRIs4Operands(MCInst &Inst, unsigned N) const {
2306 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002307 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
2308 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach3fe94e32011-08-19 17:55:24 +00002309 Inst.addOperand(MCOperand::CreateImm(Val));
2310 }
2311
Jim Grosbach26d35872011-08-19 18:55:51 +00002312 void addMemThumbRIs2Operands(MCInst &Inst, unsigned N) const {
2313 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002314 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 2) : 0;
2315 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach26d35872011-08-19 18:55:51 +00002316 Inst.addOperand(MCOperand::CreateImm(Val));
2317 }
2318
Jim Grosbacha32c7532011-08-19 18:49:59 +00002319 void addMemThumbRIs1Operands(MCInst &Inst, unsigned N) const {
2320 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002321 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue()) : 0;
2322 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbacha32c7532011-08-19 18:49:59 +00002323 Inst.addOperand(MCOperand::CreateImm(Val));
2324 }
2325
Jim Grosbach23983d62011-08-19 18:13:48 +00002326 void addMemThumbSPIOperands(MCInst &Inst, unsigned N) const {
2327 assert(N == 2 && "Invalid number of operands!");
Jim Grosbach871dff72011-10-11 15:59:20 +00002328 int64_t Val = Memory.OffsetImm ? (Memory.OffsetImm->getValue() / 4) : 0;
2329 Inst.addOperand(MCOperand::CreateReg(Memory.BaseRegNum));
Jim Grosbach23983d62011-08-19 18:13:48 +00002330 Inst.addOperand(MCOperand::CreateImm(Val));
2331 }
2332
Jim Grosbachd3595712011-08-03 23:50:40 +00002333 void addPostIdxImm8Operands(MCInst &Inst, unsigned N) const {
2334 assert(N == 1 && "Invalid number of operands!");
2335 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2336 assert(CE && "non-constant post-idx-imm8 operand!");
2337 int Imm = CE->getValue();
2338 bool isAdd = Imm >= 0;
Owen Andersonf02d98d2011-08-29 17:17:09 +00002339 if (Imm == INT32_MIN) Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00002340 Imm = (Imm < 0 ? -Imm : Imm) | (int)isAdd << 8;
2341 Inst.addOperand(MCOperand::CreateImm(Imm));
2342 }
2343
Jim Grosbach93981412011-10-11 21:55:36 +00002344 void addPostIdxImm8s4Operands(MCInst &Inst, unsigned N) const {
2345 assert(N == 1 && "Invalid number of operands!");
2346 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2347 assert(CE && "non-constant post-idx-imm8s4 operand!");
2348 int Imm = CE->getValue();
2349 bool isAdd = Imm >= 0;
2350 if (Imm == INT32_MIN) Imm = 0;
2351 // Immediate is scaled by 4.
2352 Imm = ((Imm < 0 ? -Imm : Imm) / 4) | (int)isAdd << 8;
2353 Inst.addOperand(MCOperand::CreateImm(Imm));
2354 }
2355
Jim Grosbachd3595712011-08-03 23:50:40 +00002356 void addPostIdxRegOperands(MCInst &Inst, unsigned N) const {
2357 assert(N == 2 && "Invalid number of operands!");
2358 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
Jim Grosbachc320c852011-08-05 21:28:30 +00002359 Inst.addOperand(MCOperand::CreateImm(PostIdxReg.isAdd));
2360 }
2361
2362 void addPostIdxRegShiftedOperands(MCInst &Inst, unsigned N) const {
2363 assert(N == 2 && "Invalid number of operands!");
2364 Inst.addOperand(MCOperand::CreateReg(PostIdxReg.RegNum));
2365 // The sign, shift type, and shift amount are encoded in a single operand
2366 // using the AM2 encoding helpers.
2367 ARM_AM::AddrOpc opc = PostIdxReg.isAdd ? ARM_AM::add : ARM_AM::sub;
2368 unsigned Imm = ARM_AM::getAM2Opc(opc, PostIdxReg.ShiftImm,
2369 PostIdxReg.ShiftTy);
2370 Inst.addOperand(MCOperand::CreateImm(Imm));
Bill Wendling811c9362010-11-30 07:44:32 +00002371 }
2372
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002373 void addMSRMaskOperands(MCInst &Inst, unsigned N) const {
2374 assert(N == 1 && "Invalid number of operands!");
2375 Inst.addOperand(MCOperand::CreateImm(unsigned(getMSRMask())));
2376 }
2377
Tim Northoveree843ef2014-08-15 10:47:12 +00002378 void addBankedRegOperands(MCInst &Inst, unsigned N) const {
2379 assert(N == 1 && "Invalid number of operands!");
2380 Inst.addOperand(MCOperand::CreateImm(unsigned(getBankedReg())));
2381 }
2382
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002383 void addProcIFlagsOperands(MCInst &Inst, unsigned N) const {
2384 assert(N == 1 && "Invalid number of operands!");
2385 Inst.addOperand(MCOperand::CreateImm(unsigned(getProcIFlags())));
2386 }
2387
Jim Grosbach182b6a02011-11-29 23:51:09 +00002388 void addVecListOperands(MCInst &Inst, unsigned N) const {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002389 assert(N == 1 && "Invalid number of operands!");
2390 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
2391 }
2392
Jim Grosbach04945c42011-12-02 00:35:16 +00002393 void addVecListIndexedOperands(MCInst &Inst, unsigned N) const {
2394 assert(N == 2 && "Invalid number of operands!");
2395 Inst.addOperand(MCOperand::CreateReg(VectorList.RegNum));
2396 Inst.addOperand(MCOperand::CreateImm(VectorList.LaneIndex));
2397 }
2398
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002399 void addVectorIndex8Operands(MCInst &Inst, unsigned N) const {
2400 assert(N == 1 && "Invalid number of operands!");
2401 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
2402 }
2403
2404 void addVectorIndex16Operands(MCInst &Inst, unsigned N) const {
2405 assert(N == 1 && "Invalid number of operands!");
2406 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
2407 }
2408
2409 void addVectorIndex32Operands(MCInst &Inst, unsigned N) const {
2410 assert(N == 1 && "Invalid number of operands!");
2411 Inst.addOperand(MCOperand::CreateImm(getVectorIndex()));
2412 }
2413
Jim Grosbach741cd732011-10-17 22:26:03 +00002414 void addNEONi8splatOperands(MCInst &Inst, unsigned N) const {
2415 assert(N == 1 && "Invalid number of operands!");
2416 // The immediate encodes the type of constant as well as the value.
2417 // Mask in that this is an i8 splat.
2418 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2419 Inst.addOperand(MCOperand::CreateImm(CE->getValue() | 0xe00));
2420 }
2421
Jim Grosbachcda32ae2011-10-17 23:09:09 +00002422 void addNEONi16splatOperands(MCInst &Inst, unsigned N) const {
2423 assert(N == 1 && "Invalid number of operands!");
2424 // The immediate encodes the type of constant as well as the value.
2425 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2426 unsigned Value = CE->getValue();
Renato Golinf5dd1da2014-09-25 11:31:24 +00002427 Value = ARM_AM::encodeNEONi16splat(Value);
2428 Inst.addOperand(MCOperand::CreateImm(Value));
2429 }
2430
2431 void addNEONi16splatNotOperands(MCInst &Inst, unsigned N) const {
2432 assert(N == 1 && "Invalid number of operands!");
2433 // The immediate encodes the type of constant as well as the value.
2434 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2435 unsigned Value = CE->getValue();
2436 Value = ARM_AM::encodeNEONi16splat(~Value & 0xffff);
Jim Grosbachcda32ae2011-10-17 23:09:09 +00002437 Inst.addOperand(MCOperand::CreateImm(Value));
2438 }
2439
Jim Grosbach8211c052011-10-18 00:22:00 +00002440 void addNEONi32splatOperands(MCInst &Inst, unsigned N) const {
2441 assert(N == 1 && "Invalid number of operands!");
2442 // The immediate encodes the type of constant as well as the value.
2443 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2444 unsigned Value = CE->getValue();
Renato Golinf5dd1da2014-09-25 11:31:24 +00002445 Value = ARM_AM::encodeNEONi32splat(Value);
2446 Inst.addOperand(MCOperand::CreateImm(Value));
2447 }
2448
2449 void addNEONi32splatNotOperands(MCInst &Inst, unsigned N) const {
2450 assert(N == 1 && "Invalid number of operands!");
2451 // The immediate encodes the type of constant as well as the value.
2452 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2453 unsigned Value = CE->getValue();
2454 Value = ARM_AM::encodeNEONi32splat(~Value);
Jim Grosbach8211c052011-10-18 00:22:00 +00002455 Inst.addOperand(MCOperand::CreateImm(Value));
2456 }
2457
Stepan Dyatkovskiy00dcc0f2014-04-24 06:03:01 +00002458 void addNEONinvByteReplicateOperands(MCInst &Inst, unsigned N) const {
2459 assert(N == 1 && "Invalid number of operands!");
2460 // The immediate encodes the type of constant as well as the value.
2461 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2462 unsigned Value = CE->getValue();
2463 assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
2464 Inst.getOpcode() == ARM::VMOVv16i8) &&
2465 "All vmvn instructions that wants to replicate non-zero byte "
2466 "always must be replaced with VMOVv8i8 or VMOVv16i8.");
2467 unsigned B = ((~Value) & 0xff);
2468 B |= 0xe00; // cmode = 0b1110
2469 Inst.addOperand(MCOperand::CreateImm(B));
2470 }
Jim Grosbach8211c052011-10-18 00:22:00 +00002471 void addNEONi32vmovOperands(MCInst &Inst, unsigned N) const {
2472 assert(N == 1 && "Invalid number of operands!");
2473 // The immediate encodes the type of constant as well as the value.
2474 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2475 unsigned Value = CE->getValue();
2476 if (Value >= 256 && Value <= 0xffff)
2477 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2478 else if (Value > 0xffff && Value <= 0xffffff)
2479 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2480 else if (Value > 0xffffff)
2481 Value = (Value >> 24) | 0x600;
2482 Inst.addOperand(MCOperand::CreateImm(Value));
2483 }
2484
Stepan Dyatkovskiy00dcc0f2014-04-24 06:03:01 +00002485 void addNEONvmovByteReplicateOperands(MCInst &Inst, unsigned N) const {
2486 assert(N == 1 && "Invalid number of operands!");
2487 // The immediate encodes the type of constant as well as the value.
2488 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2489 unsigned Value = CE->getValue();
2490 assert((Inst.getOpcode() == ARM::VMOVv8i8 ||
2491 Inst.getOpcode() == ARM::VMOVv16i8) &&
2492 "All instructions that wants to replicate non-zero byte "
2493 "always must be replaced with VMOVv8i8 or VMOVv16i8.");
2494 unsigned B = Value & 0xff;
2495 B |= 0xe00; // cmode = 0b1110
2496 Inst.addOperand(MCOperand::CreateImm(B));
2497 }
Jim Grosbach045b6c72011-12-19 23:51:07 +00002498 void addNEONi32vmovNegOperands(MCInst &Inst, unsigned N) const {
2499 assert(N == 1 && "Invalid number of operands!");
2500 // The immediate encodes the type of constant as well as the value.
2501 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2502 unsigned Value = ~CE->getValue();
2503 if (Value >= 256 && Value <= 0xffff)
2504 Value = (Value >> 8) | ((Value & 0xff) ? 0xc00 : 0x200);
2505 else if (Value > 0xffff && Value <= 0xffffff)
2506 Value = (Value >> 16) | ((Value & 0xff) ? 0xd00 : 0x400);
2507 else if (Value > 0xffffff)
2508 Value = (Value >> 24) | 0x600;
2509 Inst.addOperand(MCOperand::CreateImm(Value));
2510 }
2511
Jim Grosbache4454e02011-10-18 16:18:11 +00002512 void addNEONi64splatOperands(MCInst &Inst, unsigned N) const {
2513 assert(N == 1 && "Invalid number of operands!");
2514 // The immediate encodes the type of constant as well as the value.
2515 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
2516 uint64_t Value = CE->getValue();
2517 unsigned Imm = 0;
2518 for (unsigned i = 0; i < 8; ++i, Value >>= 8) {
2519 Imm |= (Value & 1) << i;
2520 }
2521 Inst.addOperand(MCOperand::CreateImm(Imm | 0x1e00));
2522 }
2523
Craig Topperca7e3e52014-03-10 03:19:03 +00002524 void print(raw_ostream &OS) const override;
Daniel Dunbarebace222010-08-11 06:37:04 +00002525
David Blaikie960ea3f2014-06-08 16:18:35 +00002526 static std::unique_ptr<ARMOperand> CreateITMask(unsigned Mask, SMLoc S) {
2527 auto Op = make_unique<ARMOperand>(k_ITCondMask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002528 Op->ITMask.Mask = Mask;
2529 Op->StartLoc = S;
2530 Op->EndLoc = S;
2531 return Op;
2532 }
2533
David Blaikie960ea3f2014-06-08 16:18:35 +00002534 static std::unique_ptr<ARMOperand> CreateCondCode(ARMCC::CondCodes CC,
2535 SMLoc S) {
2536 auto Op = make_unique<ARMOperand>(k_CondCode);
Daniel Dunbar188b47b2010-08-11 06:37:20 +00002537 Op->CC.Val = CC;
2538 Op->StartLoc = S;
2539 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002540 return Op;
Daniel Dunbar188b47b2010-08-11 06:37:20 +00002541 }
2542
David Blaikie960ea3f2014-06-08 16:18:35 +00002543 static std::unique_ptr<ARMOperand> CreateCoprocNum(unsigned CopVal, SMLoc S) {
2544 auto Op = make_unique<ARMOperand>(k_CoprocNum);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002545 Op->Cop.Val = CopVal;
2546 Op->StartLoc = S;
2547 Op->EndLoc = S;
2548 return Op;
2549 }
2550
David Blaikie960ea3f2014-06-08 16:18:35 +00002551 static std::unique_ptr<ARMOperand> CreateCoprocReg(unsigned CopVal, SMLoc S) {
2552 auto Op = make_unique<ARMOperand>(k_CoprocReg);
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002553 Op->Cop.Val = CopVal;
2554 Op->StartLoc = S;
2555 Op->EndLoc = S;
2556 return Op;
2557 }
2558
David Blaikie960ea3f2014-06-08 16:18:35 +00002559 static std::unique_ptr<ARMOperand> CreateCoprocOption(unsigned Val, SMLoc S,
2560 SMLoc E) {
2561 auto Op = make_unique<ARMOperand>(k_CoprocOption);
Jim Grosbach48399582011-10-12 17:34:41 +00002562 Op->Cop.Val = Val;
2563 Op->StartLoc = S;
2564 Op->EndLoc = E;
2565 return Op;
2566 }
2567
David Blaikie960ea3f2014-06-08 16:18:35 +00002568 static std::unique_ptr<ARMOperand> CreateCCOut(unsigned RegNum, SMLoc S) {
2569 auto Op = make_unique<ARMOperand>(k_CCOut);
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002570 Op->Reg.RegNum = RegNum;
2571 Op->StartLoc = S;
2572 Op->EndLoc = S;
2573 return Op;
2574 }
2575
David Blaikie960ea3f2014-06-08 16:18:35 +00002576 static std::unique_ptr<ARMOperand> CreateToken(StringRef Str, SMLoc S) {
2577 auto Op = make_unique<ARMOperand>(k_Token);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002578 Op->Tok.Data = Str.data();
2579 Op->Tok.Length = Str.size();
2580 Op->StartLoc = S;
2581 Op->EndLoc = S;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002582 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002583 }
2584
David Blaikie960ea3f2014-06-08 16:18:35 +00002585 static std::unique_ptr<ARMOperand> CreateReg(unsigned RegNum, SMLoc S,
2586 SMLoc E) {
2587 auto Op = make_unique<ARMOperand>(k_Register);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002588 Op->Reg.RegNum = RegNum;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002589 Op->StartLoc = S;
2590 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002591 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002592 }
2593
David Blaikie960ea3f2014-06-08 16:18:35 +00002594 static std::unique_ptr<ARMOperand>
2595 CreateShiftedRegister(ARM_AM::ShiftOpc ShTy, unsigned SrcReg,
2596 unsigned ShiftReg, unsigned ShiftImm, SMLoc S,
2597 SMLoc E) {
2598 auto Op = make_unique<ARMOperand>(k_ShiftedRegister);
Jim Grosbachac798e12011-07-25 20:49:51 +00002599 Op->RegShiftedReg.ShiftTy = ShTy;
2600 Op->RegShiftedReg.SrcReg = SrcReg;
2601 Op->RegShiftedReg.ShiftReg = ShiftReg;
2602 Op->RegShiftedReg.ShiftImm = ShiftImm;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002603 Op->StartLoc = S;
2604 Op->EndLoc = E;
2605 return Op;
2606 }
2607
David Blaikie960ea3f2014-06-08 16:18:35 +00002608 static std::unique_ptr<ARMOperand>
2609 CreateShiftedImmediate(ARM_AM::ShiftOpc ShTy, unsigned SrcReg,
2610 unsigned ShiftImm, SMLoc S, SMLoc E) {
2611 auto Op = make_unique<ARMOperand>(k_ShiftedImmediate);
Jim Grosbachac798e12011-07-25 20:49:51 +00002612 Op->RegShiftedImm.ShiftTy = ShTy;
2613 Op->RegShiftedImm.SrcReg = SrcReg;
2614 Op->RegShiftedImm.ShiftImm = ShiftImm;
Owen Andersonb595ed02011-07-21 18:54:16 +00002615 Op->StartLoc = S;
2616 Op->EndLoc = E;
2617 return Op;
2618 }
2619
David Blaikie960ea3f2014-06-08 16:18:35 +00002620 static std::unique_ptr<ARMOperand> CreateShifterImm(bool isASR, unsigned Imm,
2621 SMLoc S, SMLoc E) {
2622 auto Op = make_unique<ARMOperand>(k_ShifterImmediate);
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002623 Op->ShifterImm.isASR = isASR;
2624 Op->ShifterImm.Imm = Imm;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002625 Op->StartLoc = S;
2626 Op->EndLoc = E;
2627 return Op;
2628 }
2629
David Blaikie960ea3f2014-06-08 16:18:35 +00002630 static std::unique_ptr<ARMOperand> CreateRotImm(unsigned Imm, SMLoc S,
2631 SMLoc E) {
2632 auto Op = make_unique<ARMOperand>(k_RotateImmediate);
Jim Grosbach833b9d32011-07-27 20:15:40 +00002633 Op->RotImm.Imm = Imm;
2634 Op->StartLoc = S;
2635 Op->EndLoc = E;
2636 return Op;
2637 }
2638
David Blaikie960ea3f2014-06-08 16:18:35 +00002639 static std::unique_ptr<ARMOperand>
2640 CreateBitfield(unsigned LSB, unsigned Width, SMLoc S, SMLoc E) {
2641 auto Op = make_unique<ARMOperand>(k_BitfieldDescriptor);
Jim Grosbach864b6092011-07-28 21:34:26 +00002642 Op->Bitfield.LSB = LSB;
2643 Op->Bitfield.Width = Width;
2644 Op->StartLoc = S;
2645 Op->EndLoc = E;
2646 return Op;
2647 }
2648
David Blaikie960ea3f2014-06-08 16:18:35 +00002649 static std::unique_ptr<ARMOperand>
2650 CreateRegList(SmallVectorImpl<std::pair<unsigned, unsigned>> &Regs,
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002651 SMLoc StartLoc, SMLoc EndLoc) {
Chad Rosierfa705ee2013-07-01 20:49:23 +00002652 assert (Regs.size() > 0 && "RegList contains no registers?");
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002653 KindTy Kind = k_RegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002654
Chad Rosierfa705ee2013-07-01 20:49:23 +00002655 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Regs.front().second))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002656 Kind = k_DPRRegisterList;
Jim Grosbach75461af2011-09-13 22:56:44 +00002657 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].
Chad Rosierfa705ee2013-07-01 20:49:23 +00002658 contains(Regs.front().second))
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002659 Kind = k_SPRRegisterList;
Bill Wendling9898ac92010-11-17 04:32:08 +00002660
Chad Rosierfa705ee2013-07-01 20:49:23 +00002661 // Sort based on the register encoding values.
2662 array_pod_sort(Regs.begin(), Regs.end());
2663
David Blaikie960ea3f2014-06-08 16:18:35 +00002664 auto Op = make_unique<ARMOperand>(Kind);
Chad Rosierfa705ee2013-07-01 20:49:23 +00002665 for (SmallVectorImpl<std::pair<unsigned, unsigned> >::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002666 I = Regs.begin(), E = Regs.end(); I != E; ++I)
Chad Rosierfa705ee2013-07-01 20:49:23 +00002667 Op->Registers.push_back(I->second);
Matt Beaumont-Gay55c4cc72010-11-10 00:08:58 +00002668 Op->StartLoc = StartLoc;
2669 Op->EndLoc = EndLoc;
Bill Wendling7cef4472010-11-06 19:56:04 +00002670 return Op;
2671 }
2672
David Blaikie960ea3f2014-06-08 16:18:35 +00002673 static std::unique_ptr<ARMOperand> CreateVectorList(unsigned RegNum,
2674 unsigned Count,
2675 bool isDoubleSpaced,
2676 SMLoc S, SMLoc E) {
2677 auto Op = make_unique<ARMOperand>(k_VectorList);
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002678 Op->VectorList.RegNum = RegNum;
2679 Op->VectorList.Count = Count;
Jim Grosbach2f50e922011-12-15 21:44:33 +00002680 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002681 Op->StartLoc = S;
2682 Op->EndLoc = E;
2683 return Op;
2684 }
2685
David Blaikie960ea3f2014-06-08 16:18:35 +00002686 static std::unique_ptr<ARMOperand>
2687 CreateVectorListAllLanes(unsigned RegNum, unsigned Count, bool isDoubleSpaced,
2688 SMLoc S, SMLoc E) {
2689 auto Op = make_unique<ARMOperand>(k_VectorListAllLanes);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002690 Op->VectorList.RegNum = RegNum;
2691 Op->VectorList.Count = Count;
Jim Grosbachc5af54e2011-12-21 00:38:54 +00002692 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002693 Op->StartLoc = S;
2694 Op->EndLoc = E;
2695 return Op;
2696 }
2697
David Blaikie960ea3f2014-06-08 16:18:35 +00002698 static std::unique_ptr<ARMOperand>
2699 CreateVectorListIndexed(unsigned RegNum, unsigned Count, unsigned Index,
2700 bool isDoubleSpaced, SMLoc S, SMLoc E) {
2701 auto Op = make_unique<ARMOperand>(k_VectorListIndexed);
Jim Grosbach04945c42011-12-02 00:35:16 +00002702 Op->VectorList.RegNum = RegNum;
2703 Op->VectorList.Count = Count;
2704 Op->VectorList.LaneIndex = Index;
Jim Grosbach75e2ab52011-12-20 19:21:26 +00002705 Op->VectorList.isDoubleSpaced = isDoubleSpaced;
Jim Grosbach04945c42011-12-02 00:35:16 +00002706 Op->StartLoc = S;
2707 Op->EndLoc = E;
2708 return Op;
2709 }
2710
David Blaikie960ea3f2014-06-08 16:18:35 +00002711 static std::unique_ptr<ARMOperand>
2712 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
2713 auto Op = make_unique<ARMOperand>(k_VectorIndex);
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002714 Op->VectorIndex.Val = Idx;
2715 Op->StartLoc = S;
2716 Op->EndLoc = E;
2717 return Op;
2718 }
2719
David Blaikie960ea3f2014-06-08 16:18:35 +00002720 static std::unique_ptr<ARMOperand> CreateImm(const MCExpr *Val, SMLoc S,
2721 SMLoc E) {
2722 auto Op = make_unique<ARMOperand>(k_Immediate);
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002723 Op->Imm.Val = Val;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002724 Op->StartLoc = S;
2725 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002726 return Op;
Kevin Enderbyf5079942009-10-13 22:19:02 +00002727 }
2728
David Blaikie960ea3f2014-06-08 16:18:35 +00002729 static std::unique_ptr<ARMOperand>
2730 CreateMem(unsigned BaseRegNum, const MCConstantExpr *OffsetImm,
2731 unsigned OffsetRegNum, ARM_AM::ShiftOpc ShiftType,
2732 unsigned ShiftImm, unsigned Alignment, bool isNegative, SMLoc S,
2733 SMLoc E, SMLoc AlignmentLoc = SMLoc()) {
2734 auto Op = make_unique<ARMOperand>(k_Memory);
Jim Grosbach871dff72011-10-11 15:59:20 +00002735 Op->Memory.BaseRegNum = BaseRegNum;
2736 Op->Memory.OffsetImm = OffsetImm;
2737 Op->Memory.OffsetRegNum = OffsetRegNum;
2738 Op->Memory.ShiftType = ShiftType;
2739 Op->Memory.ShiftImm = ShiftImm;
Jim Grosbacha95ec992011-10-11 17:29:55 +00002740 Op->Memory.Alignment = Alignment;
Jim Grosbach871dff72011-10-11 15:59:20 +00002741 Op->Memory.isNegative = isNegative;
Jim Grosbachd3595712011-08-03 23:50:40 +00002742 Op->StartLoc = S;
2743 Op->EndLoc = E;
Kevin Enderby488f20b2014-04-10 20:18:58 +00002744 Op->AlignmentLoc = AlignmentLoc;
Jim Grosbachd3595712011-08-03 23:50:40 +00002745 return Op;
2746 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00002747
David Blaikie960ea3f2014-06-08 16:18:35 +00002748 static std::unique_ptr<ARMOperand>
2749 CreatePostIdxReg(unsigned RegNum, bool isAdd, ARM_AM::ShiftOpc ShiftTy,
2750 unsigned ShiftImm, SMLoc S, SMLoc E) {
2751 auto Op = make_unique<ARMOperand>(k_PostIndexRegister);
Jim Grosbachd3595712011-08-03 23:50:40 +00002752 Op->PostIdxReg.RegNum = RegNum;
Jim Grosbachc320c852011-08-05 21:28:30 +00002753 Op->PostIdxReg.isAdd = isAdd;
2754 Op->PostIdxReg.ShiftTy = ShiftTy;
2755 Op->PostIdxReg.ShiftImm = ShiftImm;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00002756 Op->StartLoc = S;
2757 Op->EndLoc = E;
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00002758 return Op;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002759 }
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002760
David Blaikie960ea3f2014-06-08 16:18:35 +00002761 static std::unique_ptr<ARMOperand> CreateMemBarrierOpt(ARM_MB::MemBOpt Opt,
2762 SMLoc S) {
2763 auto Op = make_unique<ARMOperand>(k_MemBarrierOpt);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002764 Op->MBOpt.Val = Opt;
2765 Op->StartLoc = S;
2766 Op->EndLoc = S;
2767 return Op;
2768 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002769
David Blaikie960ea3f2014-06-08 16:18:35 +00002770 static std::unique_ptr<ARMOperand>
2771 CreateInstSyncBarrierOpt(ARM_ISB::InstSyncBOpt Opt, SMLoc S) {
2772 auto Op = make_unique<ARMOperand>(k_InstSyncBarrierOpt);
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +00002773 Op->ISBOpt.Val = Opt;
2774 Op->StartLoc = S;
2775 Op->EndLoc = S;
2776 return Op;
2777 }
2778
David Blaikie960ea3f2014-06-08 16:18:35 +00002779 static std::unique_ptr<ARMOperand> CreateProcIFlags(ARM_PROC::IFlags IFlags,
2780 SMLoc S) {
2781 auto Op = make_unique<ARMOperand>(k_ProcIFlags);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002782 Op->IFlags.Val = IFlags;
2783 Op->StartLoc = S;
2784 Op->EndLoc = S;
2785 return Op;
2786 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002787
David Blaikie960ea3f2014-06-08 16:18:35 +00002788 static std::unique_ptr<ARMOperand> CreateMSRMask(unsigned MMask, SMLoc S) {
2789 auto Op = make_unique<ARMOperand>(k_MSRMask);
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002790 Op->MMask.Val = MMask;
2791 Op->StartLoc = S;
2792 Op->EndLoc = S;
2793 return Op;
2794 }
Tim Northoveree843ef2014-08-15 10:47:12 +00002795
2796 static std::unique_ptr<ARMOperand> CreateBankedReg(unsigned Reg, SMLoc S) {
2797 auto Op = make_unique<ARMOperand>(k_BankedReg);
2798 Op->BankedReg.Val = Reg;
2799 Op->StartLoc = S;
2800 Op->EndLoc = S;
2801 return Op;
2802 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00002803};
2804
2805} // end anonymous namespace.
2806
Jim Grosbach602aa902011-07-13 15:34:57 +00002807void ARMOperand::print(raw_ostream &OS) const {
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002808 switch (Kind) {
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002809 case k_CondCode:
Daniel Dunbar2be732a2011-01-10 15:26:21 +00002810 OS << "<ARMCC::" << ARMCondCodeToString(getCondCode()) << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002811 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002812 case k_CCOut:
Jim Grosbach0bfb4d52010-12-06 18:21:12 +00002813 OS << "<ccout " << getReg() << ">";
2814 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002815 case k_ITCondMask: {
Craig Topper42b96d12012-05-24 04:11:15 +00002816 static const char *const MaskStr[] = {
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00002817 "()", "(t)", "(e)", "(tt)", "(et)", "(te)", "(ee)", "(ttt)", "(ett)",
2818 "(tet)", "(eet)", "(tte)", "(ete)", "(tee)", "(eee)"
2819 };
Jim Grosbach3d1eac82011-08-26 21:43:41 +00002820 assert((ITMask.Mask & 0xf) == ITMask.Mask);
2821 OS << "<it-mask " << MaskStr[ITMask.Mask] << ">";
2822 break;
2823 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002824 case k_CoprocNum:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002825 OS << "<coprocessor number: " << getCoproc() << ">";
2826 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002827 case k_CoprocReg:
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00002828 OS << "<coprocessor register: " << getCoproc() << ">";
2829 break;
Jim Grosbach48399582011-10-12 17:34:41 +00002830 case k_CoprocOption:
2831 OS << "<coprocessor option: " << CoprocOption.Val << ">";
2832 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002833 case k_MSRMask:
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00002834 OS << "<mask: " << getMSRMask() << ">";
2835 break;
Tim Northoveree843ef2014-08-15 10:47:12 +00002836 case k_BankedReg:
2837 OS << "<banked reg: " << getBankedReg() << ">";
2838 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002839 case k_Immediate:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002840 getImm()->print(OS);
2841 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002842 case k_MemBarrierOpt:
Joey Gouly926d3f52013-09-05 15:35:24 +00002843 OS << "<ARM_MB::" << MemBOptToString(getMemBarrierOpt(), false) << ">";
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00002844 break;
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +00002845 case k_InstSyncBarrierOpt:
2846 OS << "<ARM_ISB::" << InstSyncBOptToString(getInstSyncBarrierOpt()) << ">";
2847 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002848 case k_Memory:
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002849 OS << "<memory "
Jim Grosbach871dff72011-10-11 15:59:20 +00002850 << " base:" << Memory.BaseRegNum;
Daniel Dunbarbcd8eb02011-01-18 05:55:21 +00002851 OS << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002852 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002853 case k_PostIndexRegister:
Jim Grosbachc320c852011-08-05 21:28:30 +00002854 OS << "post-idx register " << (PostIdxReg.isAdd ? "" : "-")
2855 << PostIdxReg.RegNum;
2856 if (PostIdxReg.ShiftTy != ARM_AM::no_shift)
2857 OS << ARM_AM::getShiftOpcStr(PostIdxReg.ShiftTy) << " "
2858 << PostIdxReg.ShiftImm;
2859 OS << ">";
Jim Grosbachd3595712011-08-03 23:50:40 +00002860 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002861 case k_ProcIFlags: {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00002862 OS << "<ARM_PROC::";
2863 unsigned IFlags = getProcIFlags();
2864 for (int i=2; i >= 0; --i)
2865 if (IFlags & (1 << i))
2866 OS << ARM_PROC::IFlagsToString(1 << i);
2867 OS << ">";
2868 break;
2869 }
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002870 case k_Register:
Bill Wendling2063b842010-11-18 23:43:05 +00002871 OS << "<register " << getReg() << ">";
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002872 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002873 case k_ShifterImmediate:
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00002874 OS << "<shift " << (ShifterImm.isASR ? "asr" : "lsl")
2875 << " #" << ShifterImm.Imm << ">";
Jim Grosbach7dcd1352011-07-13 17:50:29 +00002876 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002877 case k_ShiftedRegister:
Owen Andersonb595ed02011-07-21 18:54:16 +00002878 OS << "<so_reg_reg "
Jim Grosbach01e04392011-11-16 21:46:50 +00002879 << RegShiftedReg.SrcReg << " "
2880 << ARM_AM::getShiftOpcStr(RegShiftedReg.ShiftTy)
2881 << " " << RegShiftedReg.ShiftReg << ">";
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00002882 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002883 case k_ShiftedImmediate:
Owen Andersonb595ed02011-07-21 18:54:16 +00002884 OS << "<so_reg_imm "
Jim Grosbach01e04392011-11-16 21:46:50 +00002885 << RegShiftedImm.SrcReg << " "
2886 << ARM_AM::getShiftOpcStr(RegShiftedImm.ShiftTy)
2887 << " #" << RegShiftedImm.ShiftImm << ">";
Owen Andersonb595ed02011-07-21 18:54:16 +00002888 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002889 case k_RotateImmediate:
Jim Grosbach833b9d32011-07-27 20:15:40 +00002890 OS << "<ror " << " #" << (RotImm.Imm * 8) << ">";
2891 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002892 case k_BitfieldDescriptor:
Jim Grosbach864b6092011-07-28 21:34:26 +00002893 OS << "<bitfield " << "lsb: " << Bitfield.LSB
2894 << ", width: " << Bitfield.Width << ">";
2895 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002896 case k_RegisterList:
2897 case k_DPRRegisterList:
2898 case k_SPRRegisterList: {
Bill Wendling7cef4472010-11-06 19:56:04 +00002899 OS << "<register_list ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002900
Bill Wendlingbed94652010-11-09 23:28:44 +00002901 const SmallVectorImpl<unsigned> &RegList = getRegList();
2902 for (SmallVectorImpl<unsigned>::const_iterator
Bill Wendling2cae3272010-11-09 22:44:22 +00002903 I = RegList.begin(), E = RegList.end(); I != E; ) {
2904 OS << *I;
2905 if (++I < E) OS << ", ";
Bill Wendling7cef4472010-11-06 19:56:04 +00002906 }
2907
2908 OS << ">";
2909 break;
2910 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00002911 case k_VectorList:
2912 OS << "<vector_list " << VectorList.Count << " * "
2913 << VectorList.RegNum << ">";
2914 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00002915 case k_VectorListAllLanes:
2916 OS << "<vector_list(all lanes) " << VectorList.Count << " * "
2917 << VectorList.RegNum << ">";
2918 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00002919 case k_VectorListIndexed:
2920 OS << "<vector_list(lane " << VectorList.LaneIndex << ") "
2921 << VectorList.Count << " * " << VectorList.RegNum << ">";
2922 break;
Jim Grosbach6e5778f2011-10-07 23:24:09 +00002923 case k_Token:
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002924 OS << "'" << getToken() << "'";
2925 break;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002926 case k_VectorIndex:
2927 OS << "<vectorindex " << getVectorIndex() << ">";
2928 break;
Daniel Dunbar4a863e62010-08-11 06:37:12 +00002929 }
2930}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00002931
2932/// @name Auto-generated Match Functions
2933/// {
2934
2935static unsigned MatchRegisterName(StringRef Name);
2936
2937/// }
2938
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002939bool ARMAsmParser::ParseRegister(unsigned &RegNo,
2940 SMLoc &StartLoc, SMLoc &EndLoc) {
Jim Grosbachab5830e2011-12-14 02:16:11 +00002941 StartLoc = Parser.getTok().getLoc();
Jordan Rosee8f1eae2013-01-07 19:00:49 +00002942 EndLoc = Parser.getTok().getEndLoc();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002943 RegNo = tryParseRegister();
Roman Divacky36b1b472011-01-27 17:14:22 +00002944
2945 return (RegNo == (unsigned)-1);
2946}
2947
Kevin Enderby8be42bd2009-10-30 22:55:57 +00002948/// Try to parse a register name. The token must be an Identifier when called,
Chris Lattner44e5981c2010-10-30 04:09:10 +00002949/// and if it is a register name the token is eaten and the register number is
2950/// returned. Otherwise return -1.
2951///
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00002952int ARMAsmParser::tryParseRegister() {
Chris Lattner44e5981c2010-10-30 04:09:10 +00002953 const AsmToken &Tok = Parser.getTok();
Jim Grosbachd3595712011-08-03 23:50:40 +00002954 if (Tok.isNot(AsmToken::Identifier)) return -1;
Jim Grosbach99710a82010-11-01 16:44:21 +00002955
Benjamin Kramer20baffb2011-11-06 20:37:06 +00002956 std::string lowerCase = Tok.getString().lower();
Owen Andersona098d152011-01-13 22:50:36 +00002957 unsigned RegNum = MatchRegisterName(lowerCase);
2958 if (!RegNum) {
2959 RegNum = StringSwitch<unsigned>(lowerCase)
2960 .Case("r13", ARM::SP)
2961 .Case("r14", ARM::LR)
2962 .Case("r15", ARM::PC)
2963 .Case("ip", ARM::R12)
Jim Grosbach4edc7362011-12-08 19:27:38 +00002964 // Additional register name aliases for 'gas' compatibility.
2965 .Case("a1", ARM::R0)
2966 .Case("a2", ARM::R1)
2967 .Case("a3", ARM::R2)
2968 .Case("a4", ARM::R3)
2969 .Case("v1", ARM::R4)
2970 .Case("v2", ARM::R5)
2971 .Case("v3", ARM::R6)
2972 .Case("v4", ARM::R7)
2973 .Case("v5", ARM::R8)
2974 .Case("v6", ARM::R9)
2975 .Case("v7", ARM::R10)
2976 .Case("v8", ARM::R11)
2977 .Case("sb", ARM::R9)
2978 .Case("sl", ARM::R10)
2979 .Case("fp", ARM::R11)
Owen Andersona098d152011-01-13 22:50:36 +00002980 .Default(0);
2981 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00002982 if (!RegNum) {
Jim Grosbachcd22e4a2011-12-20 23:11:00 +00002983 // Check for aliases registered via .req. Canonicalize to lower case.
2984 // That's more consistent since register names are case insensitive, and
2985 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2986 StringMap<unsigned>::const_iterator Entry = RegisterReqs.find(lowerCase);
Jim Grosbachab5830e2011-12-14 02:16:11 +00002987 // If no match, return failure.
2988 if (Entry == RegisterReqs.end())
2989 return -1;
2990 Parser.Lex(); // Eat identifier token.
2991 return Entry->getValue();
2992 }
Bob Wilsonfb0bd042011-02-03 21:46:10 +00002993
Oliver Stannard9e89d8c2014-11-05 12:06:39 +00002994 // Some FPUs only have 16 D registers, so D16-D31 are invalid
2995 if (hasD16() && RegNum >= ARM::D16 && RegNum <= ARM::D31)
2996 return -1;
2997
Chris Lattner44e5981c2010-10-30 04:09:10 +00002998 Parser.Lex(); // Eat identifier token.
Jim Grosbachd0637bf2011-10-07 23:56:00 +00002999
Chris Lattner44e5981c2010-10-30 04:09:10 +00003000 return RegNum;
3001}
Jim Grosbach99710a82010-11-01 16:44:21 +00003002
Jim Grosbachbb24c592011-07-13 18:49:30 +00003003// Try to parse a shifter (e.g., "lsl <amt>"). On success, return 0.
3004// If a recoverable error occurs, return 1. If an irrecoverable error
3005// occurs, return -1. An irrecoverable error is one where tokens have been
3006// consumed in the process of trying to parse the shifter (i.e., when it is
3007// indeed a shifter operand, but malformed).
David Blaikie960ea3f2014-06-08 16:18:35 +00003008int ARMAsmParser::tryParseShiftRegister(OperandVector &Operands) {
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003009 SMLoc S = Parser.getTok().getLoc();
3010 const AsmToken &Tok = Parser.getTok();
Kevin Enderby62873712014-02-17 21:45:27 +00003011 if (Tok.isNot(AsmToken::Identifier))
3012 return -1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003013
Benjamin Kramer20baffb2011-11-06 20:37:06 +00003014 std::string lowerCase = Tok.getString().lower();
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003015 ARM_AM::ShiftOpc ShiftTy = StringSwitch<ARM_AM::ShiftOpc>(lowerCase)
Jim Grosbach3b559ff2011-12-07 23:40:58 +00003016 .Case("asl", ARM_AM::lsl)
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003017 .Case("lsl", ARM_AM::lsl)
3018 .Case("lsr", ARM_AM::lsr)
3019 .Case("asr", ARM_AM::asr)
3020 .Case("ror", ARM_AM::ror)
3021 .Case("rrx", ARM_AM::rrx)
3022 .Default(ARM_AM::no_shift);
3023
3024 if (ShiftTy == ARM_AM::no_shift)
Jim Grosbachbb24c592011-07-13 18:49:30 +00003025 return 1;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003026
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003027 Parser.Lex(); // Eat the operator.
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003028
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003029 // The source register for the shift has already been added to the
3030 // operand list, so we need to pop it off and combine it into the shifted
3031 // register operand instead.
David Blaikie960ea3f2014-06-08 16:18:35 +00003032 std::unique_ptr<ARMOperand> PrevOp(
3033 (ARMOperand *)Operands.pop_back_val().release());
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003034 if (!PrevOp->isReg())
3035 return Error(PrevOp->getStartLoc(), "shift must be of a register");
3036 int SrcReg = PrevOp->getReg();
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003037
3038 SMLoc EndLoc;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003039 int64_t Imm = 0;
3040 int ShiftReg = 0;
3041 if (ShiftTy == ARM_AM::rrx) {
3042 // RRX Doesn't have an explicit shift amount. The encoder expects
3043 // the shift register to be the same as the source register. Seems odd,
3044 // but OK.
3045 ShiftReg = SrcReg;
3046 } else {
3047 // Figure out if this is shifted by a constant or a register (for non-RRX).
Jim Grosbachef70e9b2011-12-09 22:25:03 +00003048 if (Parser.getTok().is(AsmToken::Hash) ||
3049 Parser.getTok().is(AsmToken::Dollar)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003050 Parser.Lex(); // Eat hash.
3051 SMLoc ImmLoc = Parser.getTok().getLoc();
Craig Topper062a2ba2014-04-25 05:30:21 +00003052 const MCExpr *ShiftExpr = nullptr;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003053 if (getParser().parseExpression(ShiftExpr, EndLoc)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00003054 Error(ImmLoc, "invalid immediate shift value");
3055 return -1;
3056 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003057 // The expression must be evaluatable as an immediate.
3058 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftExpr);
Jim Grosbachbb24c592011-07-13 18:49:30 +00003059 if (!CE) {
3060 Error(ImmLoc, "invalid immediate shift value");
3061 return -1;
3062 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003063 // Range check the immediate.
3064 // lsl, ror: 0 <= imm <= 31
3065 // lsr, asr: 0 <= imm <= 32
3066 Imm = CE->getValue();
3067 if (Imm < 0 ||
3068 ((ShiftTy == ARM_AM::lsl || ShiftTy == ARM_AM::ror) && Imm > 31) ||
3069 ((ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr) && Imm > 32)) {
Jim Grosbachbb24c592011-07-13 18:49:30 +00003070 Error(ImmLoc, "immediate shift value out of range");
3071 return -1;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003072 }
Jim Grosbach21488b82011-12-22 17:37:00 +00003073 // shift by zero is a nop. Always send it through as lsl.
3074 // ('as' compatibility)
3075 if (Imm == 0)
3076 ShiftTy = ARM_AM::lsl;
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003077 } else if (Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003078 SMLoc L = Parser.getTok().getLoc();
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003079 EndLoc = Parser.getTok().getEndLoc();
3080 ShiftReg = tryParseRegister();
Jim Grosbachbb24c592011-07-13 18:49:30 +00003081 if (ShiftReg == -1) {
Saleem Abdulrasool6d11b7c2014-05-17 21:49:54 +00003082 Error(L, "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00003083 return -1;
3084 }
3085 } else {
Saleem Abdulrasool6d11b7c2014-05-17 21:49:54 +00003086 Error(Parser.getTok().getLoc(),
3087 "expected immediate or register in shift operand");
Jim Grosbachbb24c592011-07-13 18:49:30 +00003088 return -1;
3089 }
Jim Grosbach7dcd1352011-07-13 17:50:29 +00003090 }
3091
Owen Andersonb595ed02011-07-21 18:54:16 +00003092 if (ShiftReg && ShiftTy != ARM_AM::rrx)
3093 Operands.push_back(ARMOperand::CreateShiftedRegister(ShiftTy, SrcReg,
Jim Grosbachac798e12011-07-25 20:49:51 +00003094 ShiftReg, Imm,
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003095 S, EndLoc));
Owen Andersonb595ed02011-07-21 18:54:16 +00003096 else
3097 Operands.push_back(ARMOperand::CreateShiftedImmediate(ShiftTy, SrcReg, Imm,
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003098 S, EndLoc));
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003099
Jim Grosbachbb24c592011-07-13 18:49:30 +00003100 return 0;
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00003101}
3102
3103
Bill Wendling2063b842010-11-18 23:43:05 +00003104/// Try to parse a register name. The token must be an Identifier when called.
3105/// If it's a register, an AsmOperand is created. Another AsmOperand is created
3106/// if there is a "writeback". 'true' if it's not a register.
Chris Lattnerbd7c9fa2010-10-28 17:20:03 +00003107///
Kevin Enderby8be42bd2009-10-30 22:55:57 +00003108/// TODO this is likely to change to allow different register types and or to
3109/// parse for a specific register type.
David Blaikie960ea3f2014-06-08 16:18:35 +00003110bool ARMAsmParser::tryParseRegisterWithWriteBack(OperandVector &Operands) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003111 const AsmToken &RegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00003112 int RegNo = tryParseRegister();
Bill Wendlinge18980a2010-11-06 22:36:58 +00003113 if (RegNo == -1)
Bill Wendling2063b842010-11-18 23:43:05 +00003114 return true;
Jim Grosbach99710a82010-11-01 16:44:21 +00003115
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003116 Operands.push_back(ARMOperand::CreateReg(RegNo, RegTok.getLoc(),
3117 RegTok.getEndLoc()));
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003118
Chris Lattner44e5981c2010-10-30 04:09:10 +00003119 const AsmToken &ExclaimTok = Parser.getTok();
3120 if (ExclaimTok.is(AsmToken::Exclaim)) {
Bill Wendling2063b842010-11-18 23:43:05 +00003121 Operands.push_back(ARMOperand::CreateToken(ExclaimTok.getString(),
3122 ExclaimTok.getLoc()));
Chris Lattner44e5981c2010-10-30 04:09:10 +00003123 Parser.Lex(); // Eat exclaim token
Jim Grosbachd0637bf2011-10-07 23:56:00 +00003124 return false;
3125 }
3126
3127 // Also check for an index operand. This is only legal for vector registers,
3128 // but that'll get caught OK in operand matching, so we don't need to
3129 // explicitly filter everything else out here.
3130 if (Parser.getTok().is(AsmToken::LBrac)) {
3131 SMLoc SIdx = Parser.getTok().getLoc();
3132 Parser.Lex(); // Eat left bracket token.
3133
3134 const MCExpr *ImmVal;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003135 if (getParser().parseExpression(ImmVal))
Jim Grosbacha2147ce2012-01-31 23:51:09 +00003136 return true;
Jim Grosbachd0637bf2011-10-07 23:56:00 +00003137 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
Jim Grosbachc8f2b782012-01-26 15:56:45 +00003138 if (!MCE)
3139 return TokError("immediate value expected for vector index");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00003140
Jim Grosbachc8f2b782012-01-26 15:56:45 +00003141 if (Parser.getTok().isNot(AsmToken::RBrac))
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003142 return Error(Parser.getTok().getLoc(), "']' expected");
Jim Grosbachd0637bf2011-10-07 23:56:00 +00003143
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003144 SMLoc E = Parser.getTok().getEndLoc();
Jim Grosbachd0637bf2011-10-07 23:56:00 +00003145 Parser.Lex(); // Eat right bracket token.
3146
3147 Operands.push_back(ARMOperand::CreateVectorIndex(MCE->getValue(),
3148 SIdx, E,
3149 getContext()));
Kevin Enderby2207e5f2009-10-07 18:01:35 +00003150 }
3151
Bill Wendling2063b842010-11-18 23:43:05 +00003152 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00003153}
3154
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003155/// MatchCoprocessorOperandName - Try to parse an coprocessor related
Renato Golinac561c32014-06-26 13:10:53 +00003156/// instruction with a symbolic operand name.
3157/// We accept "crN" syntax for GAS compatibility.
3158/// <operand-name> ::= <prefix><number>
3159/// If CoprocOp is 'c', then:
3160/// <prefix> ::= c | cr
3161/// If CoprocOp is 'p', then :
3162/// <prefix> ::= p
3163/// <number> ::= integer in range [0, 15]
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003164static int MatchCoprocessorOperandName(StringRef Name, char CoprocOp) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003165 // Use the same layout as the tablegen'erated register name matcher. Ugly,
3166 // but efficient.
Renato Golinac561c32014-06-26 13:10:53 +00003167 if (Name.size() < 2 || Name[0] != CoprocOp)
3168 return -1;
3169 Name = (Name[1] == 'r') ? Name.drop_front(2) : Name.drop_front();
3170
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003171 switch (Name.size()) {
David Blaikie46a9f012012-01-20 21:51:11 +00003172 default: return -1;
Renato Golinac561c32014-06-26 13:10:53 +00003173 case 1:
3174 switch (Name[0]) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003175 default: return -1;
3176 case '0': return 0;
3177 case '1': return 1;
3178 case '2': return 2;
3179 case '3': return 3;
3180 case '4': return 4;
3181 case '5': return 5;
3182 case '6': return 6;
3183 case '7': return 7;
3184 case '8': return 8;
3185 case '9': return 9;
3186 }
Renato Golinac561c32014-06-26 13:10:53 +00003187 case 2:
3188 if (Name[0] != '1')
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003189 return -1;
Renato Golinac561c32014-06-26 13:10:53 +00003190 switch (Name[1]) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003191 default: return -1;
Renato Golinbc0b0372014-08-04 23:21:56 +00003192 // CP10 and CP11 are VFP/NEON and so vector instructions should be used.
3193 // However, old cores (v5/v6) did use them in that way.
3194 case '0': return 10;
3195 case '1': return 11;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003196 case '2': return 12;
3197 case '3': return 13;
3198 case '4': return 14;
3199 case '5': return 15;
3200 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003201 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003202}
3203
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003204/// parseITCondCode - Try to parse a condition code for an IT instruction.
David Blaikie960ea3f2014-06-08 16:18:35 +00003205ARMAsmParser::OperandMatchResultTy
3206ARMAsmParser::parseITCondCode(OperandVector &Operands) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003207 SMLoc S = Parser.getTok().getLoc();
3208 const AsmToken &Tok = Parser.getTok();
3209 if (!Tok.is(AsmToken::Identifier))
3210 return MatchOperand_NoMatch;
Richard Barton82f95ea2012-04-27 17:34:01 +00003211 unsigned CC = StringSwitch<unsigned>(Tok.getString().lower())
Jim Grosbach3d1eac82011-08-26 21:43:41 +00003212 .Case("eq", ARMCC::EQ)
3213 .Case("ne", ARMCC::NE)
3214 .Case("hs", ARMCC::HS)
3215 .Case("cs", ARMCC::HS)
3216 .Case("lo", ARMCC::LO)
3217 .Case("cc", ARMCC::LO)
3218 .Case("mi", ARMCC::MI)
3219 .Case("pl", ARMCC::PL)
3220 .Case("vs", ARMCC::VS)
3221 .Case("vc", ARMCC::VC)
3222 .Case("hi", ARMCC::HI)
3223 .Case("ls", ARMCC::LS)
3224 .Case("ge", ARMCC::GE)
3225 .Case("lt", ARMCC::LT)
3226 .Case("gt", ARMCC::GT)
3227 .Case("le", ARMCC::LE)
3228 .Case("al", ARMCC::AL)
3229 .Default(~0U);
3230 if (CC == ~0U)
3231 return MatchOperand_NoMatch;
3232 Parser.Lex(); // Eat the token.
3233
3234 Operands.push_back(ARMOperand::CreateCondCode(ARMCC::CondCodes(CC), S));
3235
3236 return MatchOperand_Success;
3237}
3238
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003239/// parseCoprocNumOperand - Try to parse an coprocessor number operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003240/// token must be an Identifier when called, and if it is a coprocessor
3241/// number, the token is eaten and the operand is added to the operand list.
David Blaikie960ea3f2014-06-08 16:18:35 +00003242ARMAsmParser::OperandMatchResultTy
3243ARMAsmParser::parseCoprocNumOperand(OperandVector &Operands) {
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003244 SMLoc S = Parser.getTok().getLoc();
3245 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00003246 if (Tok.isNot(AsmToken::Identifier))
3247 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003248
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003249 int Num = MatchCoprocessorOperandName(Tok.getString(), 'p');
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003250 if (Num == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003251 return MatchOperand_NoMatch;
Renato Golinbc0b0372014-08-04 23:21:56 +00003252 // ARMv7 and v8 don't allow cp10/cp11 due to VFP/NEON specific instructions
3253 if ((hasV7Ops() || hasV8Ops()) && (Num == 10 || Num == 11))
3254 return MatchOperand_NoMatch;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003255
3256 Parser.Lex(); // Eat identifier token.
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003257 Operands.push_back(ARMOperand::CreateCoprocNum(Num, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003258 return MatchOperand_Success;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003259}
3260
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003261/// parseCoprocRegOperand - Try to parse an coprocessor register operand. The
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003262/// token must be an Identifier when called, and if it is a coprocessor
3263/// number, the token is eaten and the operand is added to the operand list.
David Blaikie960ea3f2014-06-08 16:18:35 +00003264ARMAsmParser::OperandMatchResultTy
3265ARMAsmParser::parseCoprocRegOperand(OperandVector &Operands) {
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003266 SMLoc S = Parser.getTok().getLoc();
3267 const AsmToken &Tok = Parser.getTok();
Jim Grosbach54a20ed2011-10-12 20:54:17 +00003268 if (Tok.isNot(AsmToken::Identifier))
3269 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003270
3271 int Reg = MatchCoprocessorOperandName(Tok.getString(), 'c');
3272 if (Reg == -1)
Jim Grosbach861e49c2011-02-12 01:34:40 +00003273 return MatchOperand_NoMatch;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00003274
3275 Parser.Lex(); // Eat identifier token.
3276 Operands.push_back(ARMOperand::CreateCoprocReg(Reg, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003277 return MatchOperand_Success;
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00003278}
3279
Jim Grosbach48399582011-10-12 17:34:41 +00003280/// parseCoprocOptionOperand - Try to parse an coprocessor option operand.
3281/// coproc_option : '{' imm0_255 '}'
David Blaikie960ea3f2014-06-08 16:18:35 +00003282ARMAsmParser::OperandMatchResultTy
3283ARMAsmParser::parseCoprocOptionOperand(OperandVector &Operands) {
Jim Grosbach48399582011-10-12 17:34:41 +00003284 SMLoc S = Parser.getTok().getLoc();
3285
3286 // If this isn't a '{', this isn't a coprocessor immediate operand.
3287 if (Parser.getTok().isNot(AsmToken::LCurly))
3288 return MatchOperand_NoMatch;
3289 Parser.Lex(); // Eat the '{'
3290
3291 const MCExpr *Expr;
3292 SMLoc Loc = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003293 if (getParser().parseExpression(Expr)) {
Jim Grosbach48399582011-10-12 17:34:41 +00003294 Error(Loc, "illegal expression");
3295 return MatchOperand_ParseFail;
3296 }
3297 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
3298 if (!CE || CE->getValue() < 0 || CE->getValue() > 255) {
3299 Error(Loc, "coprocessor option must be an immediate in range [0, 255]");
3300 return MatchOperand_ParseFail;
3301 }
3302 int Val = CE->getValue();
3303
3304 // Check for and consume the closing '}'
3305 if (Parser.getTok().isNot(AsmToken::RCurly))
3306 return MatchOperand_ParseFail;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003307 SMLoc E = Parser.getTok().getEndLoc();
Jim Grosbach48399582011-10-12 17:34:41 +00003308 Parser.Lex(); // Eat the '}'
3309
3310 Operands.push_back(ARMOperand::CreateCoprocOption(Val, S, E));
3311 return MatchOperand_Success;
3312}
3313
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003314// For register list parsing, we need to map from raw GPR register numbering
3315// to the enumeration values. The enumeration values aren't sorted by
3316// register number due to our using "sp", "lr" and "pc" as canonical names.
3317static unsigned getNextRegister(unsigned Reg) {
3318 // If this is a GPR, we need to do it manually, otherwise we can rely
3319 // on the sort ordering of the enumeration since the other reg-classes
3320 // are sane.
3321 if (!ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
3322 return Reg + 1;
3323 switch(Reg) {
Craig Toppere55c5562012-02-07 02:50:20 +00003324 default: llvm_unreachable("Invalid GPR number!");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003325 case ARM::R0: return ARM::R1; case ARM::R1: return ARM::R2;
3326 case ARM::R2: return ARM::R3; case ARM::R3: return ARM::R4;
3327 case ARM::R4: return ARM::R5; case ARM::R5: return ARM::R6;
3328 case ARM::R6: return ARM::R7; case ARM::R7: return ARM::R8;
3329 case ARM::R8: return ARM::R9; case ARM::R9: return ARM::R10;
3330 case ARM::R10: return ARM::R11; case ARM::R11: return ARM::R12;
3331 case ARM::R12: return ARM::SP; case ARM::SP: return ARM::LR;
3332 case ARM::LR: return ARM::PC; case ARM::PC: return ARM::R0;
3333 }
3334}
3335
Jim Grosbach85a23432011-11-11 21:27:40 +00003336// Return the low-subreg of a given Q register.
3337static unsigned getDRegFromQReg(unsigned QReg) {
3338 switch (QReg) {
3339 default: llvm_unreachable("expected a Q register!");
3340 case ARM::Q0: return ARM::D0;
3341 case ARM::Q1: return ARM::D2;
3342 case ARM::Q2: return ARM::D4;
3343 case ARM::Q3: return ARM::D6;
3344 case ARM::Q4: return ARM::D8;
3345 case ARM::Q5: return ARM::D10;
3346 case ARM::Q6: return ARM::D12;
3347 case ARM::Q7: return ARM::D14;
3348 case ARM::Q8: return ARM::D16;
Jim Grosbacha92a5d82011-11-15 21:01:30 +00003349 case ARM::Q9: return ARM::D18;
Jim Grosbach85a23432011-11-11 21:27:40 +00003350 case ARM::Q10: return ARM::D20;
3351 case ARM::Q11: return ARM::D22;
3352 case ARM::Q12: return ARM::D24;
3353 case ARM::Q13: return ARM::D26;
3354 case ARM::Q14: return ARM::D28;
3355 case ARM::Q15: return ARM::D30;
3356 }
3357}
3358
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003359/// Parse a register list.
David Blaikie960ea3f2014-06-08 16:18:35 +00003360bool ARMAsmParser::parseRegisterList(OperandVector &Operands) {
Sean Callanan936b0d32010-01-19 21:44:56 +00003361 assert(Parser.getTok().is(AsmToken::LCurly) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00003362 "Token is not a Left Curly Brace");
Bill Wendlinge18980a2010-11-06 22:36:58 +00003363 SMLoc S = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003364 Parser.Lex(); // Eat '{' token.
3365 SMLoc RegLoc = Parser.getTok().getLoc();
Kevin Enderbya2b99102009-10-09 21:12:28 +00003366
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003367 // Check the first register in the list to see what register class
3368 // this is a list of.
3369 int Reg = tryParseRegister();
3370 if (Reg == -1)
3371 return Error(RegLoc, "register expected");
3372
Jim Grosbach85a23432011-11-11 21:27:40 +00003373 // The reglist instructions have at most 16 registers, so reserve
3374 // space for that many.
Chad Rosierfa705ee2013-07-01 20:49:23 +00003375 int EReg = 0;
3376 SmallVector<std::pair<unsigned, unsigned>, 16> Registers;
Jim Grosbach85a23432011-11-11 21:27:40 +00003377
3378 // Allow Q regs and just interpret them as the two D sub-registers.
3379 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3380 Reg = getDRegFromQReg(Reg);
Chad Rosierfa705ee2013-07-01 20:49:23 +00003381 EReg = MRI->getEncodingValue(Reg);
3382 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
Jim Grosbach85a23432011-11-11 21:27:40 +00003383 ++Reg;
3384 }
Benjamin Kramer0d6d0982011-10-22 16:50:00 +00003385 const MCRegisterClass *RC;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003386 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
3387 RC = &ARMMCRegisterClasses[ARM::GPRRegClassID];
3388 else if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg))
3389 RC = &ARMMCRegisterClasses[ARM::DPRRegClassID];
3390 else if (ARMMCRegisterClasses[ARM::SPRRegClassID].contains(Reg))
3391 RC = &ARMMCRegisterClasses[ARM::SPRRegClassID];
3392 else
3393 return Error(RegLoc, "invalid register in register list");
3394
Jim Grosbach85a23432011-11-11 21:27:40 +00003395 // Store the register.
Chad Rosierfa705ee2013-07-01 20:49:23 +00003396 EReg = MRI->getEncodingValue(Reg);
3397 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
Kevin Enderbya2b99102009-10-09 21:12:28 +00003398
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003399 // This starts immediately after the first register token in the list,
3400 // so we can see either a comma or a minus (range separator) as a legal
3401 // next token.
3402 while (Parser.getTok().is(AsmToken::Comma) ||
3403 Parser.getTok().is(AsmToken::Minus)) {
3404 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbache891fe82011-11-15 23:19:15 +00003405 Parser.Lex(); // Eat the minus.
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003406 SMLoc AfterMinusLoc = Parser.getTok().getLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003407 int EndReg = tryParseRegister();
3408 if (EndReg == -1)
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003409 return Error(AfterMinusLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00003410 // Allow Q regs and just interpret them as the two D sub-registers.
3411 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3412 EndReg = getDRegFromQReg(EndReg) + 1;
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003413 // If the register is the same as the start reg, there's nothing
3414 // more to do.
3415 if (Reg == EndReg)
3416 continue;
3417 // The register must be in the same register class as the first.
3418 if (!RC->contains(EndReg))
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003419 return Error(AfterMinusLoc, "invalid register in register list");
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003420 // Ranges must go from low to high.
Eric Christopher6ac277c2012-08-09 22:10:21 +00003421 if (MRI->getEncodingValue(Reg) > MRI->getEncodingValue(EndReg))
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003422 return Error(AfterMinusLoc, "bad range in register list");
Kevin Enderbya2b99102009-10-09 21:12:28 +00003423
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003424 // Add all the registers in the range to the register list.
3425 while (Reg != EndReg) {
3426 Reg = getNextRegister(Reg);
Chad Rosierfa705ee2013-07-01 20:49:23 +00003427 EReg = MRI->getEncodingValue(Reg);
3428 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003429 }
3430 continue;
3431 }
3432 Parser.Lex(); // Eat the comma.
3433 RegLoc = Parser.getTok().getLoc();
3434 int OldReg = Reg;
Jim Grosbach98bc7972011-12-08 21:34:20 +00003435 const AsmToken RegTok = Parser.getTok();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003436 Reg = tryParseRegister();
3437 if (Reg == -1)
Jim Grosbach3337e392011-09-12 23:36:42 +00003438 return Error(RegLoc, "register expected");
Jim Grosbach85a23432011-11-11 21:27:40 +00003439 // Allow Q regs and just interpret them as the two D sub-registers.
3440 bool isQReg = false;
3441 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3442 Reg = getDRegFromQReg(Reg);
3443 isQReg = true;
3444 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003445 // The register must be in the same register class as the first.
3446 if (!RC->contains(Reg))
3447 return Error(RegLoc, "invalid register in register list");
3448 // List must be monotonically increasing.
Eric Christopher6ac277c2012-08-09 22:10:21 +00003449 if (MRI->getEncodingValue(Reg) < MRI->getEncodingValue(OldReg)) {
Jim Grosbach905686a2012-03-16 20:48:38 +00003450 if (ARMMCRegisterClasses[ARM::GPRRegClassID].contains(Reg))
3451 Warning(RegLoc, "register list not in ascending order");
3452 else
3453 return Error(RegLoc, "register list not in ascending order");
3454 }
Eric Christopher6ac277c2012-08-09 22:10:21 +00003455 if (MRI->getEncodingValue(Reg) == MRI->getEncodingValue(OldReg)) {
Jim Grosbach98bc7972011-12-08 21:34:20 +00003456 Warning(RegLoc, "duplicated register (" + RegTok.getString() +
3457 ") in register list");
3458 continue;
3459 }
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003460 // VFP register lists must also be contiguous.
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003461 if (RC != &ARMMCRegisterClasses[ARM::GPRRegClassID] &&
3462 Reg != OldReg + 1)
3463 return Error(RegLoc, "non-contiguous register range");
Chad Rosierfa705ee2013-07-01 20:49:23 +00003464 EReg = MRI->getEncodingValue(Reg);
3465 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3466 if (isQReg) {
3467 EReg = MRI->getEncodingValue(++Reg);
3468 Registers.push_back(std::pair<unsigned, unsigned>(EReg, Reg));
3469 }
Bill Wendlinge18980a2010-11-06 22:36:58 +00003470 }
3471
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003472 if (Parser.getTok().isNot(AsmToken::RCurly))
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003473 return Error(Parser.getTok().getLoc(), "'}' expected");
3474 SMLoc E = Parser.getTok().getEndLoc();
Jim Grosbach3ac26b12011-09-14 18:08:35 +00003475 Parser.Lex(); // Eat '}' token.
3476
Jim Grosbach18bf3632011-12-13 21:48:29 +00003477 // Push the register list operand.
Bill Wendling2063b842010-11-18 23:43:05 +00003478 Operands.push_back(ARMOperand::CreateRegList(Registers, S, E));
Jim Grosbach18bf3632011-12-13 21:48:29 +00003479
3480 // The ARM system instruction variants for LDM/STM have a '^' token here.
3481 if (Parser.getTok().is(AsmToken::Caret)) {
3482 Operands.push_back(ARMOperand::CreateToken("^",Parser.getTok().getLoc()));
3483 Parser.Lex(); // Eat '^' token.
3484 }
3485
Bill Wendling2063b842010-11-18 23:43:05 +00003486 return false;
Kevin Enderbya2b99102009-10-09 21:12:28 +00003487}
3488
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003489// Helper function to parse the lane index for vector lists.
3490ARMAsmParser::OperandMatchResultTy ARMAsmParser::
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003491parseVectorLane(VectorLaneTy &LaneKind, unsigned &Index, SMLoc &EndLoc) {
Jim Grosbach04945c42011-12-02 00:35:16 +00003492 Index = 0; // Always return a defined index value.
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003493 if (Parser.getTok().is(AsmToken::LBrac)) {
3494 Parser.Lex(); // Eat the '['.
3495 if (Parser.getTok().is(AsmToken::RBrac)) {
3496 // "Dn[]" is the 'all lanes' syntax.
3497 LaneKind = AllLanes;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003498 EndLoc = Parser.getTok().getEndLoc();
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003499 Parser.Lex(); // Eat the ']'.
3500 return MatchOperand_Success;
3501 }
Jim Grosbach67e76ba2012-03-19 20:39:53 +00003502
3503 // There's an optional '#' token here. Normally there wouldn't be, but
3504 // inline assemble puts one in, and it's friendly to accept that.
3505 if (Parser.getTok().is(AsmToken::Hash))
Amaury de la Vieuvillebac917f2013-06-10 14:17:15 +00003506 Parser.Lex(); // Eat '#' or '$'.
Jim Grosbach67e76ba2012-03-19 20:39:53 +00003507
Jim Grosbach7de7ab82011-12-21 01:19:23 +00003508 const MCExpr *LaneIndex;
3509 SMLoc Loc = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003510 if (getParser().parseExpression(LaneIndex)) {
Jim Grosbach7de7ab82011-12-21 01:19:23 +00003511 Error(Loc, "illegal expression");
3512 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003513 }
Jim Grosbach7de7ab82011-12-21 01:19:23 +00003514 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LaneIndex);
3515 if (!CE) {
3516 Error(Loc, "lane index must be empty or an integer");
3517 return MatchOperand_ParseFail;
3518 }
3519 if (Parser.getTok().isNot(AsmToken::RBrac)) {
3520 Error(Parser.getTok().getLoc(), "']' expected");
3521 return MatchOperand_ParseFail;
3522 }
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003523 EndLoc = Parser.getTok().getEndLoc();
Jim Grosbach7de7ab82011-12-21 01:19:23 +00003524 Parser.Lex(); // Eat the ']'.
3525 int64_t Val = CE->getValue();
3526
3527 // FIXME: Make this range check context sensitive for .8, .16, .32.
3528 if (Val < 0 || Val > 7) {
3529 Error(Parser.getTok().getLoc(), "lane index out of range");
3530 return MatchOperand_ParseFail;
3531 }
3532 Index = Val;
3533 LaneKind = IndexedLane;
3534 return MatchOperand_Success;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003535 }
3536 LaneKind = NoLanes;
3537 return MatchOperand_Success;
3538}
3539
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003540// parse a vector register list
David Blaikie960ea3f2014-06-08 16:18:35 +00003541ARMAsmParser::OperandMatchResultTy
3542ARMAsmParser::parseVectorList(OperandVector &Operands) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003543 VectorLaneTy LaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003544 unsigned LaneIndex;
Jim Grosbach8d579232011-11-15 21:45:55 +00003545 SMLoc S = Parser.getTok().getLoc();
3546 // As an extension (to match gas), support a plain D register or Q register
3547 // (without encosing curly braces) as a single or double entry list,
3548 // respectively.
3549 if (Parser.getTok().is(AsmToken::Identifier)) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003550 SMLoc E = Parser.getTok().getEndLoc();
Jim Grosbach8d579232011-11-15 21:45:55 +00003551 int Reg = tryParseRegister();
3552 if (Reg == -1)
3553 return MatchOperand_NoMatch;
Jim Grosbach8d579232011-11-15 21:45:55 +00003554 if (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(Reg)) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003555 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003556 if (Res != MatchOperand_Success)
3557 return Res;
3558 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003559 case NoLanes:
Jim Grosbach2f50e922011-12-15 21:44:33 +00003560 Operands.push_back(ARMOperand::CreateVectorList(Reg, 1, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003561 break;
3562 case AllLanes:
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003563 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 1, false,
3564 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003565 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003566 case IndexedLane:
3567 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 1,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003568 LaneIndex,
3569 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003570 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003571 }
Jim Grosbach8d579232011-11-15 21:45:55 +00003572 return MatchOperand_Success;
3573 }
3574 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3575 Reg = getDRegFromQReg(Reg);
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003576 OperandMatchResultTy Res = parseVectorLane(LaneKind, LaneIndex, E);
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003577 if (Res != MatchOperand_Success)
3578 return Res;
3579 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003580 case NoLanes:
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003581 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
Jim Grosbach13a292c2012-03-06 22:01:44 +00003582 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbach2f50e922011-12-15 21:44:33 +00003583 Operands.push_back(ARMOperand::CreateVectorList(Reg, 2, false, S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003584 break;
3585 case AllLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003586 Reg = MRI->getMatchingSuperReg(Reg, ARM::dsub_0,
3587 &ARMMCRegisterClasses[ARM::DPairRegClassID]);
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003588 Operands.push_back(ARMOperand::CreateVectorListAllLanes(Reg, 2, false,
3589 S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003590 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003591 case IndexedLane:
3592 Operands.push_back(ARMOperand::CreateVectorListIndexed(Reg, 2,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003593 LaneIndex,
3594 false, S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003595 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003596 }
Jim Grosbach8d579232011-11-15 21:45:55 +00003597 return MatchOperand_Success;
3598 }
3599 Error(S, "vector register expected");
3600 return MatchOperand_ParseFail;
3601 }
3602
3603 if (Parser.getTok().isNot(AsmToken::LCurly))
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003604 return MatchOperand_NoMatch;
3605
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003606 Parser.Lex(); // Eat '{' token.
3607 SMLoc RegLoc = Parser.getTok().getLoc();
3608
3609 int Reg = tryParseRegister();
3610 if (Reg == -1) {
3611 Error(RegLoc, "register expected");
3612 return MatchOperand_ParseFail;
3613 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003614 unsigned Count = 1;
Jim Grosbachc2f16a32011-12-15 21:54:55 +00003615 int Spacing = 0;
Jim Grosbach080a4992011-10-28 00:06:50 +00003616 unsigned FirstReg = Reg;
3617 // The list is of D registers, but we also allow Q regs and just interpret
3618 // them as the two D sub-registers.
3619 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
3620 FirstReg = Reg = getDRegFromQReg(Reg);
Jim Grosbach2f50e922011-12-15 21:44:33 +00003621 Spacing = 1; // double-spacing requires explicit D registers, otherwise
3622 // it's ambiguous with four-register single spaced.
Jim Grosbach080a4992011-10-28 00:06:50 +00003623 ++Reg;
3624 ++Count;
3625 }
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003626
3627 SMLoc E;
3628 if (parseVectorLane(LaneKind, LaneIndex, E) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003629 return MatchOperand_ParseFail;
Jim Grosbach080a4992011-10-28 00:06:50 +00003630
Jim Grosbache891fe82011-11-15 23:19:15 +00003631 while (Parser.getTok().is(AsmToken::Comma) ||
3632 Parser.getTok().is(AsmToken::Minus)) {
3633 if (Parser.getTok().is(AsmToken::Minus)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003634 if (!Spacing)
3635 Spacing = 1; // Register range implies a single spaced list.
3636 else if (Spacing == 2) {
3637 Error(Parser.getTok().getLoc(),
3638 "sequential registers in double spaced list");
3639 return MatchOperand_ParseFail;
3640 }
Jim Grosbache891fe82011-11-15 23:19:15 +00003641 Parser.Lex(); // Eat the minus.
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003642 SMLoc AfterMinusLoc = Parser.getTok().getLoc();
Jim Grosbache891fe82011-11-15 23:19:15 +00003643 int EndReg = tryParseRegister();
3644 if (EndReg == -1) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003645 Error(AfterMinusLoc, "register expected");
Jim Grosbache891fe82011-11-15 23:19:15 +00003646 return MatchOperand_ParseFail;
3647 }
3648 // Allow Q regs and just interpret them as the two D sub-registers.
3649 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(EndReg))
3650 EndReg = getDRegFromQReg(EndReg) + 1;
3651 // If the register is the same as the start reg, there's nothing
3652 // more to do.
3653 if (Reg == EndReg)
3654 continue;
3655 // The register must be in the same register class as the first.
3656 if (!ARMMCRegisterClasses[ARM::DPRRegClassID].contains(EndReg)) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003657 Error(AfterMinusLoc, "invalid register in register list");
Jim Grosbache891fe82011-11-15 23:19:15 +00003658 return MatchOperand_ParseFail;
3659 }
3660 // Ranges must go from low to high.
3661 if (Reg > EndReg) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003662 Error(AfterMinusLoc, "bad range in register list");
Jim Grosbache891fe82011-11-15 23:19:15 +00003663 return MatchOperand_ParseFail;
3664 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003665 // Parse the lane specifier if present.
3666 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003667 unsigned NextLaneIndex;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003668 if (parseVectorLane(NextLaneKind, NextLaneIndex, E) !=
3669 MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003670 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003671 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003672 Error(AfterMinusLoc, "mismatched lane index in register list");
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003673 return MatchOperand_ParseFail;
3674 }
Jim Grosbache891fe82011-11-15 23:19:15 +00003675
3676 // Add all the registers in the range to the register list.
3677 Count += EndReg - Reg;
3678 Reg = EndReg;
3679 continue;
3680 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003681 Parser.Lex(); // Eat the comma.
3682 RegLoc = Parser.getTok().getLoc();
3683 int OldReg = Reg;
3684 Reg = tryParseRegister();
3685 if (Reg == -1) {
3686 Error(RegLoc, "register expected");
3687 return MatchOperand_ParseFail;
3688 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003689 // vector register lists must be contiguous.
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003690 // It's OK to use the enumeration values directly here rather, as the
3691 // VFP register classes have the enum sorted properly.
Jim Grosbach080a4992011-10-28 00:06:50 +00003692 //
3693 // The list is of D registers, but we also allow Q regs and just interpret
3694 // them as the two D sub-registers.
3695 if (ARMMCRegisterClasses[ARM::QPRRegClassID].contains(Reg)) {
Jim Grosbach2f50e922011-12-15 21:44:33 +00003696 if (!Spacing)
3697 Spacing = 1; // Register range implies a single spaced list.
3698 else if (Spacing == 2) {
3699 Error(RegLoc,
3700 "invalid register in double-spaced list (must be 'D' register')");
3701 return MatchOperand_ParseFail;
3702 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003703 Reg = getDRegFromQReg(Reg);
3704 if (Reg != OldReg + 1) {
3705 Error(RegLoc, "non-contiguous register range");
3706 return MatchOperand_ParseFail;
3707 }
3708 ++Reg;
3709 Count += 2;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003710 // Parse the lane specifier if present.
3711 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003712 unsigned NextLaneIndex;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003713 SMLoc LaneLoc = Parser.getTok().getLoc();
3714 if (parseVectorLane(NextLaneKind, NextLaneIndex, E) !=
3715 MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003716 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003717 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003718 Error(LaneLoc, "mismatched lane index in register list");
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003719 return MatchOperand_ParseFail;
3720 }
Jim Grosbach080a4992011-10-28 00:06:50 +00003721 continue;
3722 }
Jim Grosbach2f50e922011-12-15 21:44:33 +00003723 // Normal D register.
3724 // Figure out the register spacing (single or double) of the list if
3725 // we don't know it already.
3726 if (!Spacing)
3727 Spacing = 1 + (Reg == OldReg + 2);
3728
3729 // Just check that it's contiguous and keep going.
3730 if (Reg != OldReg + Spacing) {
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003731 Error(RegLoc, "non-contiguous register range");
3732 return MatchOperand_ParseFail;
3733 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003734 ++Count;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003735 // Parse the lane specifier if present.
3736 VectorLaneTy NextLaneKind;
Jim Grosbach04945c42011-12-02 00:35:16 +00003737 unsigned NextLaneIndex;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003738 SMLoc EndLoc = Parser.getTok().getLoc();
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003739 if (parseVectorLane(NextLaneKind, NextLaneIndex, E) != MatchOperand_Success)
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003740 return MatchOperand_ParseFail;
Jim Grosbach04945c42011-12-02 00:35:16 +00003741 if (NextLaneKind != LaneKind || LaneIndex != NextLaneIndex) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003742 Error(EndLoc, "mismatched lane index in register list");
3743 return MatchOperand_ParseFail;
3744 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003745 }
3746
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003747 if (Parser.getTok().isNot(AsmToken::RCurly)) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003748 Error(Parser.getTok().getLoc(), "'}' expected");
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003749 return MatchOperand_ParseFail;
3750 }
Jordan Rosee8f1eae2013-01-07 19:00:49 +00003751 E = Parser.getTok().getEndLoc();
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003752 Parser.Lex(); // Eat '}' token.
3753
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003754 switch (LaneKind) {
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003755 case NoLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003756 // Two-register operands have been converted to the
Jim Grosbache5307f92012-03-05 21:43:40 +00003757 // composite register classes.
3758 if (Count == 2) {
3759 const MCRegisterClass *RC = (Spacing == 1) ?
3760 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3761 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
3762 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3763 }
Jim Grosbachc988e0c2012-03-05 19:33:30 +00003764
Jim Grosbach2f50e922011-12-15 21:44:33 +00003765 Operands.push_back(ARMOperand::CreateVectorList(FirstReg, Count,
3766 (Spacing == 2), S, E));
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003767 break;
3768 case AllLanes:
Jim Grosbach13a292c2012-03-06 22:01:44 +00003769 // Two-register operands have been converted to the
3770 // composite register classes.
Jim Grosbached428bc2012-03-06 23:10:38 +00003771 if (Count == 2) {
3772 const MCRegisterClass *RC = (Spacing == 1) ?
3773 &ARMMCRegisterClasses[ARM::DPairRegClassID] :
3774 &ARMMCRegisterClasses[ARM::DPairSpcRegClassID];
Jim Grosbach13a292c2012-03-06 22:01:44 +00003775 FirstReg = MRI->getMatchingSuperReg(FirstReg, ARM::dsub_0, RC);
3776 }
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003777 Operands.push_back(ARMOperand::CreateVectorListAllLanes(FirstReg, Count,
Jim Grosbachc5af54e2011-12-21 00:38:54 +00003778 (Spacing == 2),
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003779 S, E));
3780 break;
Jim Grosbach04945c42011-12-02 00:35:16 +00003781 case IndexedLane:
3782 Operands.push_back(ARMOperand::CreateVectorListIndexed(FirstReg, Count,
Jim Grosbach75e2ab52011-12-20 19:21:26 +00003783 LaneIndex,
3784 (Spacing == 2),
3785 S, E));
Jim Grosbach04945c42011-12-02 00:35:16 +00003786 break;
Jim Grosbachcd6f5e72011-11-30 01:09:44 +00003787 }
Jim Grosbachad47cfc2011-10-18 23:02:30 +00003788 return MatchOperand_Success;
3789}
3790
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003791/// parseMemBarrierOptOperand - Try to parse DSB/DMB data barrier options.
David Blaikie960ea3f2014-06-08 16:18:35 +00003792ARMAsmParser::OperandMatchResultTy
3793ARMAsmParser::parseMemBarrierOptOperand(OperandVector &Operands) {
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003794 SMLoc S = Parser.getTok().getLoc();
3795 const AsmToken &Tok = Parser.getTok();
Jiangning Liu288e1af2012-08-02 08:21:27 +00003796 unsigned Opt;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003797
Jiangning Liu288e1af2012-08-02 08:21:27 +00003798 if (Tok.is(AsmToken::Identifier)) {
3799 StringRef OptStr = Tok.getString();
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003800
Jiangning Liu288e1af2012-08-02 08:21:27 +00003801 Opt = StringSwitch<unsigned>(OptStr.slice(0, OptStr.size()).lower())
3802 .Case("sy", ARM_MB::SY)
3803 .Case("st", ARM_MB::ST)
Joey Gouly926d3f52013-09-05 15:35:24 +00003804 .Case("ld", ARM_MB::LD)
Jiangning Liu288e1af2012-08-02 08:21:27 +00003805 .Case("sh", ARM_MB::ISH)
3806 .Case("ish", ARM_MB::ISH)
3807 .Case("shst", ARM_MB::ISHST)
3808 .Case("ishst", ARM_MB::ISHST)
Joey Gouly926d3f52013-09-05 15:35:24 +00003809 .Case("ishld", ARM_MB::ISHLD)
Jiangning Liu288e1af2012-08-02 08:21:27 +00003810 .Case("nsh", ARM_MB::NSH)
3811 .Case("un", ARM_MB::NSH)
3812 .Case("nshst", ARM_MB::NSHST)
Joey Gouly926d3f52013-09-05 15:35:24 +00003813 .Case("nshld", ARM_MB::NSHLD)
Jiangning Liu288e1af2012-08-02 08:21:27 +00003814 .Case("unst", ARM_MB::NSHST)
3815 .Case("osh", ARM_MB::OSH)
3816 .Case("oshst", ARM_MB::OSHST)
Joey Gouly926d3f52013-09-05 15:35:24 +00003817 .Case("oshld", ARM_MB::OSHLD)
Jiangning Liu288e1af2012-08-02 08:21:27 +00003818 .Default(~0U);
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003819
Joey Gouly926d3f52013-09-05 15:35:24 +00003820 // ishld, oshld, nshld and ld are only available from ARMv8.
3821 if (!hasV8Ops() && (Opt == ARM_MB::ISHLD || Opt == ARM_MB::OSHLD ||
3822 Opt == ARM_MB::NSHLD || Opt == ARM_MB::LD))
3823 Opt = ~0U;
3824
Jiangning Liu288e1af2012-08-02 08:21:27 +00003825 if (Opt == ~0U)
3826 return MatchOperand_NoMatch;
3827
3828 Parser.Lex(); // Eat identifier token.
3829 } else if (Tok.is(AsmToken::Hash) ||
3830 Tok.is(AsmToken::Dollar) ||
3831 Tok.is(AsmToken::Integer)) {
3832 if (Parser.getTok().isNot(AsmToken::Integer))
Amaury de la Vieuvillebac917f2013-06-10 14:17:15 +00003833 Parser.Lex(); // Eat '#' or '$'.
Jiangning Liu288e1af2012-08-02 08:21:27 +00003834 SMLoc Loc = Parser.getTok().getLoc();
3835
3836 const MCExpr *MemBarrierID;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00003837 if (getParser().parseExpression(MemBarrierID)) {
Jiangning Liu288e1af2012-08-02 08:21:27 +00003838 Error(Loc, "illegal expression");
3839 return MatchOperand_ParseFail;
3840 }
Saleem Abdulrasool4ab6e732014-02-23 17:45:36 +00003841
Jiangning Liu288e1af2012-08-02 08:21:27 +00003842 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(MemBarrierID);
3843 if (!CE) {
3844 Error(Loc, "constant expression expected");
3845 return MatchOperand_ParseFail;
3846 }
3847
3848 int Val = CE->getValue();
3849 if (Val & ~0xf) {
3850 Error(Loc, "immediate value out of range");
3851 return MatchOperand_ParseFail;
3852 }
3853
3854 Opt = ARM_MB::RESERVED_0 + Val;
3855 } else
3856 return MatchOperand_ParseFail;
3857
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003858 Operands.push_back(ARMOperand::CreateMemBarrierOpt((ARM_MB::MemBOpt)Opt, S));
Jim Grosbach861e49c2011-02-12 01:34:40 +00003859 return MatchOperand_Success;
Bruno Cardoso Lopes36dd43f2011-02-07 22:09:15 +00003860}
3861
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +00003862/// parseInstSyncBarrierOptOperand - Try to parse ISB inst sync barrier options.
David Blaikie960ea3f2014-06-08 16:18:35 +00003863ARMAsmParser::OperandMatchResultTy
3864ARMAsmParser::parseInstSyncBarrierOptOperand(OperandVector &Operands) {
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +00003865 SMLoc S = Parser.getTok().getLoc();
3866 const AsmToken &Tok = Parser.getTok();
3867 unsigned Opt;
3868
3869 if (Tok.is(AsmToken::Identifier)) {
3870 StringRef OptStr = Tok.getString();
3871
Benjamin Kramer3e9237a2013-11-09 22:48:13 +00003872 if (OptStr.equals_lower("sy"))
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +00003873 Opt = ARM_ISB::SY;
3874 else
3875 return MatchOperand_NoMatch;
3876
3877 Parser.Lex(); // Eat identifier token.
3878 } else if (Tok.is(AsmToken::Hash) ||
3879 Tok.is(AsmToken::Dollar) ||
3880 Tok.is(AsmToken::Integer)) {
3881 if (Parser.getTok().isNot(AsmToken::Integer))
Amaury de la Vieuvillebac917f2013-06-10 14:17:15 +00003882 Parser.Lex(); // Eat '#' or '$'.
Amaury de la Vieuville43cb13a2013-06-10 14:17:08 +00003883 SMLoc Loc = Parser.getTok().getLoc();
3884
3885 const MCExpr *ISBarrierID;
3886 if (getParser().parseExpression(ISBarrierID)) {
3887 Error(Loc, "illegal expression");
3888 return MatchOperand_ParseFail;
3889 }
3890
3891 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ISBarrierID);
3892 if (!CE) {
3893 Error(Loc, "constant expression expected");
3894 return MatchOperand_ParseFail;
3895 }
3896
3897 int Val = CE->getValue();
3898 if (Val & ~0xf) {
3899 Error(Loc, "immediate value out of range");
3900 return MatchOperand_ParseFail;
3901 }
3902
3903 Opt = ARM_ISB::RESERVED_0 + Val;
3904 } else
3905 return MatchOperand_ParseFail;
3906
3907 Operands.push_back(ARMOperand::CreateInstSyncBarrierOpt(
3908 (ARM_ISB::InstSyncBOpt)Opt, S));
3909 return MatchOperand_Success;
3910}
3911
3912
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003913/// parseProcIFlagsOperand - Try to parse iflags from CPS instruction.
David Blaikie960ea3f2014-06-08 16:18:35 +00003914ARMAsmParser::OperandMatchResultTy
3915ARMAsmParser::parseProcIFlagsOperand(OperandVector &Operands) {
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003916 SMLoc S = Parser.getTok().getLoc();
3917 const AsmToken &Tok = Parser.getTok();
Richard Bartonb0ec3752012-06-14 10:48:04 +00003918 if (!Tok.is(AsmToken::Identifier))
3919 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003920 StringRef IFlagsStr = Tok.getString();
3921
Owen Anderson10c5b122011-10-05 17:16:40 +00003922 // An iflags string of "none" is interpreted to mean that none of the AIF
3923 // bits are set. Not a terribly useful instruction, but a valid encoding.
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003924 unsigned IFlags = 0;
Owen Anderson10c5b122011-10-05 17:16:40 +00003925 if (IFlagsStr != "none") {
3926 for (int i = 0, e = IFlagsStr.size(); i != e; ++i) {
3927 unsigned Flag = StringSwitch<unsigned>(IFlagsStr.substr(i, 1))
3928 .Case("a", ARM_PROC::A)
3929 .Case("i", ARM_PROC::I)
3930 .Case("f", ARM_PROC::F)
3931 .Default(~0U);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003932
Owen Anderson10c5b122011-10-05 17:16:40 +00003933 // If some specific iflag is already set, it means that some letter is
3934 // present more than once, this is not acceptable.
3935 if (Flag == ~0U || (IFlags & Flag))
3936 return MatchOperand_NoMatch;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003937
Owen Anderson10c5b122011-10-05 17:16:40 +00003938 IFlags |= Flag;
3939 }
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00003940 }
3941
3942 Parser.Lex(); // Eat identifier token.
3943 Operands.push_back(ARMOperand::CreateProcIFlags((ARM_PROC::IFlags)IFlags, S));
3944 return MatchOperand_Success;
3945}
3946
Jim Grosbach2d6ef442011-07-25 20:14:50 +00003947/// parseMSRMaskOperand - Try to parse mask flags from MSR instruction.
David Blaikie960ea3f2014-06-08 16:18:35 +00003948ARMAsmParser::OperandMatchResultTy
3949ARMAsmParser::parseMSRMaskOperand(OperandVector &Operands) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003950 SMLoc S = Parser.getTok().getLoc();
3951 const AsmToken &Tok = Parser.getTok();
Craig Toppera004b0d2012-10-09 04:55:28 +00003952 if (!Tok.is(AsmToken::Identifier))
3953 return MatchOperand_NoMatch;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00003954 StringRef Mask = Tok.getString();
3955
James Molloy21efa7d2011-09-28 14:21:38 +00003956 if (isMClass()) {
3957 // See ARMv6-M 10.1.1
Jim Grosbachd28888d2012-03-15 21:34:14 +00003958 std::string Name = Mask.lower();
3959 unsigned FlagsVal = StringSwitch<unsigned>(Name)
Kevin Enderbyf1b225d2012-05-17 22:18:01 +00003960 // Note: in the documentation:
3961 // ARM deprecates using MSR APSR without a _<bits> qualifier as an alias
3962 // for MSR APSR_nzcvq.
3963 // but we do make it an alias here. This is so to get the "mask encoding"
3964 // bits correct on MSR APSR writes.
3965 //
3966 // FIXME: Note the 0xc00 "mask encoding" bits version of the registers
3967 // should really only be allowed when writing a special register. Note
3968 // they get dropped in the MRS instruction reading a special register as
3969 // the SYSm field is only 8 bits.
Kevin Enderbyf1b225d2012-05-17 22:18:01 +00003970 .Case("apsr", 0x800)
3971 .Case("apsr_nzcvq", 0x800)
3972 .Case("apsr_g", 0x400)
3973 .Case("apsr_nzcvqg", 0xc00)
3974 .Case("iapsr", 0x801)
3975 .Case("iapsr_nzcvq", 0x801)
3976 .Case("iapsr_g", 0x401)
3977 .Case("iapsr_nzcvqg", 0xc01)
3978 .Case("eapsr", 0x802)
3979 .Case("eapsr_nzcvq", 0x802)
3980 .Case("eapsr_g", 0x402)
3981 .Case("eapsr_nzcvqg", 0xc02)
3982 .Case("xpsr", 0x803)
3983 .Case("xpsr_nzcvq", 0x803)
3984 .Case("xpsr_g", 0x403)
3985 .Case("xpsr_nzcvqg", 0xc03)
Kevin Enderby6c7279e2012-06-15 22:14:44 +00003986 .Case("ipsr", 0x805)
3987 .Case("epsr", 0x806)
3988 .Case("iepsr", 0x807)
3989 .Case("msp", 0x808)
3990 .Case("psp", 0x809)
3991 .Case("primask", 0x810)
3992 .Case("basepri", 0x811)
3993 .Case("basepri_max", 0x812)
3994 .Case("faultmask", 0x813)
3995 .Case("control", 0x814)
James Molloy21efa7d2011-09-28 14:21:38 +00003996 .Default(~0U);
Jim Grosbach3794d822011-12-22 17:17:10 +00003997
James Molloy21efa7d2011-09-28 14:21:38 +00003998 if (FlagsVal == ~0U)
3999 return MatchOperand_NoMatch;
4000
Renato Golin92c816c2014-09-01 11:25:07 +00004001 if (!hasThumb2DSP() && (FlagsVal & 0x400))
4002 // The _g and _nzcvqg versions are only valid if the DSP extension is
4003 // available.
4004 return MatchOperand_NoMatch;
4005
Kevin Enderby6c7279e2012-06-15 22:14:44 +00004006 if (!hasV7Ops() && FlagsVal >= 0x811 && FlagsVal <= 0x813)
James Molloy21efa7d2011-09-28 14:21:38 +00004007 // basepri, basepri_max and faultmask only valid for V7m.
4008 return MatchOperand_NoMatch;
Jim Grosbach3794d822011-12-22 17:17:10 +00004009
James Molloy21efa7d2011-09-28 14:21:38 +00004010 Parser.Lex(); // Eat identifier token.
4011 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
4012 return MatchOperand_Success;
4013 }
4014
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00004015 // Split spec_reg from flag, example: CPSR_sxf => "CPSR" and "sxf"
4016 size_t Start = 0, Next = Mask.find('_');
4017 StringRef Flags = "";
Benjamin Kramer20baffb2011-11-06 20:37:06 +00004018 std::string SpecReg = Mask.slice(Start, Next).lower();
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00004019 if (Next != StringRef::npos)
4020 Flags = Mask.slice(Next+1, Mask.size());
4021
4022 // FlagsVal contains the complete mask:
4023 // 3-0: Mask
4024 // 4: Special Reg (cpsr, apsr => 0; spsr => 1)
4025 unsigned FlagsVal = 0;
4026
4027 if (SpecReg == "apsr") {
4028 FlagsVal = StringSwitch<unsigned>(Flags)
Jim Grosbachd25c2cd2011-07-19 22:45:10 +00004029 .Case("nzcvq", 0x8) // same as CPSR_f
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00004030 .Case("g", 0x4) // same as CPSR_s
4031 .Case("nzcvqg", 0xc) // same as CPSR_fs
4032 .Default(~0U);
4033
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00004034 if (FlagsVal == ~0U) {
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00004035 if (!Flags.empty())
4036 return MatchOperand_NoMatch;
4037 else
Jim Grosbach0ecd3952011-09-14 20:03:46 +00004038 FlagsVal = 8; // No flag
Joerg Sonnenberger740467a2011-02-19 00:43:45 +00004039 }
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00004040 } else if (SpecReg == "cpsr" || SpecReg == "spsr") {
Jim Grosbach3d00eec2012-04-05 03:17:53 +00004041 // cpsr_all is an alias for cpsr_fc, as is plain cpsr.
4042 if (Flags == "all" || Flags == "")
Bruno Cardoso Lopes54452132011-05-25 00:35:03 +00004043 Flags = "fc";
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00004044 for (int i = 0, e = Flags.size(); i != e; ++i) {
4045 unsigned Flag = StringSwitch<unsigned>(Flags.substr(i, 1))
4046 .Case("c", 1)
4047 .Case("x", 2)
4048 .Case("s", 4)
4049 .Case("f", 8)
4050 .Default(~0U);
4051
4052 // If some specific flag is already set, it means that some letter is
4053 // present more than once, this is not acceptable.
4054 if (FlagsVal == ~0U || (FlagsVal & Flag))
4055 return MatchOperand_NoMatch;
4056 FlagsVal |= Flag;
4057 }
4058 } else // No match for special register.
4059 return MatchOperand_NoMatch;
4060
Owen Anderson03a173e2011-10-21 18:43:28 +00004061 // Special register without flags is NOT equivalent to "fc" flags.
4062 // NOTE: This is a divergence from gas' behavior. Uncommenting the following
4063 // two lines would enable gas compatibility at the expense of breaking
4064 // round-tripping.
4065 //
4066 // if (!FlagsVal)
4067 // FlagsVal = 0x9;
Bruno Cardoso Lopes9cd43972011-02-18 19:45:59 +00004068
4069 // Bit 4: Special Reg (cpsr, apsr => 0; spsr => 1)
4070 if (SpecReg == "spsr")
4071 FlagsVal |= 16;
4072
4073 Parser.Lex(); // Eat identifier token.
4074 Operands.push_back(ARMOperand::CreateMSRMask(FlagsVal, S));
4075 return MatchOperand_Success;
4076}
4077
Tim Northoveree843ef2014-08-15 10:47:12 +00004078/// parseBankedRegOperand - Try to parse a banked register (e.g. "lr_irq") for
4079/// use in the MRS/MSR instructions added to support virtualization.
4080ARMAsmParser::OperandMatchResultTy
4081ARMAsmParser::parseBankedRegOperand(OperandVector &Operands) {
4082 SMLoc S = Parser.getTok().getLoc();
4083 const AsmToken &Tok = Parser.getTok();
4084 if (!Tok.is(AsmToken::Identifier))
4085 return MatchOperand_NoMatch;
4086 StringRef RegName = Tok.getString();
4087
4088 // The values here come from B9.2.3 of the ARM ARM, where bits 4-0 are SysM
4089 // and bit 5 is R.
4090 unsigned Encoding = StringSwitch<unsigned>(RegName.lower())
4091 .Case("r8_usr", 0x00)
4092 .Case("r9_usr", 0x01)
4093 .Case("r10_usr", 0x02)
4094 .Case("r11_usr", 0x03)
4095 .Case("r12_usr", 0x04)
4096 .Case("sp_usr", 0x05)
4097 .Case("lr_usr", 0x06)
4098 .Case("r8_fiq", 0x08)
4099 .Case("r9_fiq", 0x09)
4100 .Case("r10_fiq", 0x0a)
4101 .Case("r11_fiq", 0x0b)
4102 .Case("r12_fiq", 0x0c)
4103 .Case("sp_fiq", 0x0d)
4104 .Case("lr_fiq", 0x0e)
4105 .Case("lr_irq", 0x10)
4106 .Case("sp_irq", 0x11)
4107 .Case("lr_svc", 0x12)
4108 .Case("sp_svc", 0x13)
4109 .Case("lr_abt", 0x14)
4110 .Case("sp_abt", 0x15)
4111 .Case("lr_und", 0x16)
4112 .Case("sp_und", 0x17)
4113 .Case("lr_mon", 0x1c)
4114 .Case("sp_mon", 0x1d)
4115 .Case("elr_hyp", 0x1e)
4116 .Case("sp_hyp", 0x1f)
4117 .Case("spsr_fiq", 0x2e)
4118 .Case("spsr_irq", 0x30)
4119 .Case("spsr_svc", 0x32)
4120 .Case("spsr_abt", 0x34)
4121 .Case("spsr_und", 0x36)
4122 .Case("spsr_mon", 0x3c)
4123 .Case("spsr_hyp", 0x3e)
4124 .Default(~0U);
4125
4126 if (Encoding == ~0U)
4127 return MatchOperand_NoMatch;
4128
4129 Parser.Lex(); // Eat identifier token.
4130 Operands.push_back(ARMOperand::CreateBankedReg(Encoding, S));
4131 return MatchOperand_Success;
4132}
4133
David Blaikie960ea3f2014-06-08 16:18:35 +00004134ARMAsmParser::OperandMatchResultTy
4135ARMAsmParser::parsePKHImm(OperandVector &Operands, StringRef Op, int Low,
4136 int High) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00004137 const AsmToken &Tok = Parser.getTok();
4138 if (Tok.isNot(AsmToken::Identifier)) {
4139 Error(Parser.getTok().getLoc(), Op + " operand expected.");
4140 return MatchOperand_ParseFail;
4141 }
4142 StringRef ShiftName = Tok.getString();
Benjamin Kramer20baffb2011-11-06 20:37:06 +00004143 std::string LowerOp = Op.lower();
4144 std::string UpperOp = Op.upper();
Jim Grosbach27c1e252011-07-21 17:23:04 +00004145 if (ShiftName != LowerOp && ShiftName != UpperOp) {
4146 Error(Parser.getTok().getLoc(), Op + " operand expected.");
4147 return MatchOperand_ParseFail;
4148 }
4149 Parser.Lex(); // Eat shift type token.
4150
4151 // There must be a '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004152 if (Parser.getTok().isNot(AsmToken::Hash) &&
4153 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00004154 Error(Parser.getTok().getLoc(), "'#' expected");
4155 return MatchOperand_ParseFail;
4156 }
4157 Parser.Lex(); // Eat hash token.
4158
4159 const MCExpr *ShiftAmount;
4160 SMLoc Loc = Parser.getTok().getLoc();
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004161 SMLoc EndLoc;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004162 if (getParser().parseExpression(ShiftAmount, EndLoc)) {
Jim Grosbach27c1e252011-07-21 17:23:04 +00004163 Error(Loc, "illegal expression");
4164 return MatchOperand_ParseFail;
4165 }
4166 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
4167 if (!CE) {
4168 Error(Loc, "constant expression expected");
4169 return MatchOperand_ParseFail;
4170 }
4171 int Val = CE->getValue();
4172 if (Val < Low || Val > High) {
4173 Error(Loc, "immediate value out of range");
4174 return MatchOperand_ParseFail;
4175 }
4176
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004177 Operands.push_back(ARMOperand::CreateImm(CE, Loc, EndLoc));
Jim Grosbach27c1e252011-07-21 17:23:04 +00004178
4179 return MatchOperand_Success;
4180}
4181
David Blaikie960ea3f2014-06-08 16:18:35 +00004182ARMAsmParser::OperandMatchResultTy
4183ARMAsmParser::parseSetEndImm(OperandVector &Operands) {
Jim Grosbach0a547702011-07-22 17:44:50 +00004184 const AsmToken &Tok = Parser.getTok();
4185 SMLoc S = Tok.getLoc();
4186 if (Tok.isNot(AsmToken::Identifier)) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004187 Error(S, "'be' or 'le' operand expected");
Jim Grosbach0a547702011-07-22 17:44:50 +00004188 return MatchOperand_ParseFail;
4189 }
Tim Northover4d141442013-05-31 15:58:45 +00004190 int Val = StringSwitch<int>(Tok.getString().lower())
Jim Grosbach0a547702011-07-22 17:44:50 +00004191 .Case("be", 1)
4192 .Case("le", 0)
4193 .Default(-1);
4194 Parser.Lex(); // Eat the token.
4195
4196 if (Val == -1) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004197 Error(S, "'be' or 'le' operand expected");
Jim Grosbach0a547702011-07-22 17:44:50 +00004198 return MatchOperand_ParseFail;
4199 }
4200 Operands.push_back(ARMOperand::CreateImm(MCConstantExpr::Create(Val,
4201 getContext()),
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004202 S, Tok.getEndLoc()));
Jim Grosbach0a547702011-07-22 17:44:50 +00004203 return MatchOperand_Success;
4204}
4205
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004206/// parseShifterImm - Parse the shifter immediate operand for SSAT/USAT
4207/// instructions. Legal values are:
4208/// lsl #n 'n' in [0,31]
4209/// asr #n 'n' in [1,32]
4210/// n == 32 encoded as n == 0.
David Blaikie960ea3f2014-06-08 16:18:35 +00004211ARMAsmParser::OperandMatchResultTy
4212ARMAsmParser::parseShifterImm(OperandVector &Operands) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004213 const AsmToken &Tok = Parser.getTok();
4214 SMLoc S = Tok.getLoc();
4215 if (Tok.isNot(AsmToken::Identifier)) {
4216 Error(S, "shift operator 'asr' or 'lsl' expected");
4217 return MatchOperand_ParseFail;
4218 }
4219 StringRef ShiftName = Tok.getString();
4220 bool isASR;
4221 if (ShiftName == "lsl" || ShiftName == "LSL")
4222 isASR = false;
4223 else if (ShiftName == "asr" || ShiftName == "ASR")
4224 isASR = true;
4225 else {
4226 Error(S, "shift operator 'asr' or 'lsl' expected");
4227 return MatchOperand_ParseFail;
4228 }
4229 Parser.Lex(); // Eat the operator.
4230
4231 // A '#' and a shift amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004232 if (Parser.getTok().isNot(AsmToken::Hash) &&
4233 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004234 Error(Parser.getTok().getLoc(), "'#' expected");
4235 return MatchOperand_ParseFail;
4236 }
4237 Parser.Lex(); // Eat hash token.
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004238 SMLoc ExLoc = Parser.getTok().getLoc();
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004239
4240 const MCExpr *ShiftAmount;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004241 SMLoc EndLoc;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004242 if (getParser().parseExpression(ShiftAmount, EndLoc)) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004243 Error(ExLoc, "malformed shift expression");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004244 return MatchOperand_ParseFail;
4245 }
4246 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
4247 if (!CE) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004248 Error(ExLoc, "shift amount must be an immediate");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004249 return MatchOperand_ParseFail;
4250 }
4251
4252 int64_t Val = CE->getValue();
4253 if (isASR) {
4254 // Shift amount must be in [1,32]
4255 if (Val < 1 || Val > 32) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004256 Error(ExLoc, "'asr' shift amount must be in range [1,32]");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004257 return MatchOperand_ParseFail;
4258 }
Owen Andersonf01e2de2011-09-26 21:06:22 +00004259 // asr #32 encoded as asr #0, but is not allowed in Thumb2 mode.
4260 if (isThumb() && Val == 32) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004261 Error(ExLoc, "'asr #32' shift amount not allowed in Thumb mode");
Owen Andersonf01e2de2011-09-26 21:06:22 +00004262 return MatchOperand_ParseFail;
4263 }
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004264 if (Val == 32) Val = 0;
4265 } else {
4266 // Shift amount must be in [1,32]
4267 if (Val < 0 || Val > 31) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004268 Error(ExLoc, "'lsr' shift amount must be in range [0,31]");
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004269 return MatchOperand_ParseFail;
4270 }
4271 }
4272
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004273 Operands.push_back(ARMOperand::CreateShifterImm(isASR, Val, S, EndLoc));
Jim Grosbach3a9cbee2011-07-25 22:20:28 +00004274
4275 return MatchOperand_Success;
4276}
4277
Jim Grosbach833b9d32011-07-27 20:15:40 +00004278/// parseRotImm - Parse the shifter immediate operand for SXTB/UXTB family
4279/// of instructions. Legal values are:
4280/// ror #n 'n' in {0, 8, 16, 24}
David Blaikie960ea3f2014-06-08 16:18:35 +00004281ARMAsmParser::OperandMatchResultTy
4282ARMAsmParser::parseRotImm(OperandVector &Operands) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00004283 const AsmToken &Tok = Parser.getTok();
4284 SMLoc S = Tok.getLoc();
Jim Grosbach82213192011-09-19 20:29:33 +00004285 if (Tok.isNot(AsmToken::Identifier))
4286 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00004287 StringRef ShiftName = Tok.getString();
Jim Grosbach82213192011-09-19 20:29:33 +00004288 if (ShiftName != "ror" && ShiftName != "ROR")
4289 return MatchOperand_NoMatch;
Jim Grosbach833b9d32011-07-27 20:15:40 +00004290 Parser.Lex(); // Eat the operator.
4291
4292 // A '#' and a rotate amount.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004293 if (Parser.getTok().isNot(AsmToken::Hash) &&
4294 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach833b9d32011-07-27 20:15:40 +00004295 Error(Parser.getTok().getLoc(), "'#' expected");
4296 return MatchOperand_ParseFail;
4297 }
4298 Parser.Lex(); // Eat hash token.
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004299 SMLoc ExLoc = Parser.getTok().getLoc();
Jim Grosbach833b9d32011-07-27 20:15:40 +00004300
4301 const MCExpr *ShiftAmount;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004302 SMLoc EndLoc;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004303 if (getParser().parseExpression(ShiftAmount, EndLoc)) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004304 Error(ExLoc, "malformed rotate expression");
Jim Grosbach833b9d32011-07-27 20:15:40 +00004305 return MatchOperand_ParseFail;
4306 }
4307 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ShiftAmount);
4308 if (!CE) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004309 Error(ExLoc, "rotate amount must be an immediate");
Jim Grosbach833b9d32011-07-27 20:15:40 +00004310 return MatchOperand_ParseFail;
4311 }
4312
4313 int64_t Val = CE->getValue();
4314 // Shift amount must be in {0, 8, 16, 24} (0 is undocumented extension)
4315 // normally, zero is represented in asm by omitting the rotate operand
4316 // entirely.
4317 if (Val != 8 && Val != 16 && Val != 24 && Val != 0) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004318 Error(ExLoc, "'ror' rotate amount must be 8, 16, or 24");
Jim Grosbach833b9d32011-07-27 20:15:40 +00004319 return MatchOperand_ParseFail;
4320 }
4321
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004322 Operands.push_back(ARMOperand::CreateRotImm(Val, S, EndLoc));
Jim Grosbach833b9d32011-07-27 20:15:40 +00004323
4324 return MatchOperand_Success;
4325}
4326
David Blaikie960ea3f2014-06-08 16:18:35 +00004327ARMAsmParser::OperandMatchResultTy
4328ARMAsmParser::parseBitfield(OperandVector &Operands) {
Jim Grosbach864b6092011-07-28 21:34:26 +00004329 SMLoc S = Parser.getTok().getLoc();
4330 // The bitfield descriptor is really two operands, the LSB and the width.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004331 if (Parser.getTok().isNot(AsmToken::Hash) &&
4332 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00004333 Error(Parser.getTok().getLoc(), "'#' expected");
4334 return MatchOperand_ParseFail;
4335 }
4336 Parser.Lex(); // Eat hash token.
4337
4338 const MCExpr *LSBExpr;
4339 SMLoc E = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004340 if (getParser().parseExpression(LSBExpr)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00004341 Error(E, "malformed immediate expression");
4342 return MatchOperand_ParseFail;
4343 }
4344 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(LSBExpr);
4345 if (!CE) {
4346 Error(E, "'lsb' operand must be an immediate");
4347 return MatchOperand_ParseFail;
4348 }
4349
4350 int64_t LSB = CE->getValue();
4351 // The LSB must be in the range [0,31]
4352 if (LSB < 0 || LSB > 31) {
4353 Error(E, "'lsb' operand must be in the range [0,31]");
4354 return MatchOperand_ParseFail;
4355 }
4356 E = Parser.getTok().getLoc();
4357
4358 // Expect another immediate operand.
4359 if (Parser.getTok().isNot(AsmToken::Comma)) {
4360 Error(Parser.getTok().getLoc(), "too few operands");
4361 return MatchOperand_ParseFail;
4362 }
4363 Parser.Lex(); // Eat hash token.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004364 if (Parser.getTok().isNot(AsmToken::Hash) &&
4365 Parser.getTok().isNot(AsmToken::Dollar)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00004366 Error(Parser.getTok().getLoc(), "'#' expected");
4367 return MatchOperand_ParseFail;
4368 }
4369 Parser.Lex(); // Eat hash token.
4370
4371 const MCExpr *WidthExpr;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004372 SMLoc EndLoc;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004373 if (getParser().parseExpression(WidthExpr, EndLoc)) {
Jim Grosbach864b6092011-07-28 21:34:26 +00004374 Error(E, "malformed immediate expression");
4375 return MatchOperand_ParseFail;
4376 }
4377 CE = dyn_cast<MCConstantExpr>(WidthExpr);
4378 if (!CE) {
4379 Error(E, "'width' operand must be an immediate");
4380 return MatchOperand_ParseFail;
4381 }
4382
4383 int64_t Width = CE->getValue();
4384 // The LSB must be in the range [1,32-lsb]
4385 if (Width < 1 || Width > 32 - LSB) {
4386 Error(E, "'width' operand must be in the range [1,32-lsb]");
4387 return MatchOperand_ParseFail;
4388 }
Jim Grosbach864b6092011-07-28 21:34:26 +00004389
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004390 Operands.push_back(ARMOperand::CreateBitfield(LSB, Width, S, EndLoc));
Jim Grosbach864b6092011-07-28 21:34:26 +00004391
4392 return MatchOperand_Success;
4393}
4394
David Blaikie960ea3f2014-06-08 16:18:35 +00004395ARMAsmParser::OperandMatchResultTy
4396ARMAsmParser::parsePostIdxReg(OperandVector &Operands) {
Jim Grosbachd3595712011-08-03 23:50:40 +00004397 // Check for a post-index addressing register operand. Specifically:
Jim Grosbachc320c852011-08-05 21:28:30 +00004398 // postidx_reg := '+' register {, shift}
4399 // | '-' register {, shift}
4400 // | register {, shift}
Jim Grosbachd3595712011-08-03 23:50:40 +00004401
4402 // This method must return MatchOperand_NoMatch without consuming any tokens
4403 // in the case where there is no match, as other alternatives take other
4404 // parse methods.
4405 AsmToken Tok = Parser.getTok();
4406 SMLoc S = Tok.getLoc();
4407 bool haveEaten = false;
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00004408 bool isAdd = true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004409 if (Tok.is(AsmToken::Plus)) {
4410 Parser.Lex(); // Eat the '+' token.
4411 haveEaten = true;
4412 } else if (Tok.is(AsmToken::Minus)) {
4413 Parser.Lex(); // Eat the '-' token.
Jim Grosbacha70fbfd52011-08-05 16:11:38 +00004414 isAdd = false;
Jim Grosbachd3595712011-08-03 23:50:40 +00004415 haveEaten = true;
4416 }
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004417
4418 SMLoc E = Parser.getTok().getEndLoc();
4419 int Reg = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00004420 if (Reg == -1) {
4421 if (!haveEaten)
4422 return MatchOperand_NoMatch;
4423 Error(Parser.getTok().getLoc(), "register expected");
4424 return MatchOperand_ParseFail;
4425 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004426
Jim Grosbachc320c852011-08-05 21:28:30 +00004427 ARM_AM::ShiftOpc ShiftTy = ARM_AM::no_shift;
4428 unsigned ShiftImm = 0;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004429 if (Parser.getTok().is(AsmToken::Comma)) {
4430 Parser.Lex(); // Eat the ','.
4431 if (parseMemRegOffsetShift(ShiftTy, ShiftImm))
4432 return MatchOperand_ParseFail;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004433
4434 // FIXME: Only approximates end...may include intervening whitespace.
4435 E = Parser.getTok().getLoc();
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004436 }
Jim Grosbachc320c852011-08-05 21:28:30 +00004437
4438 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ShiftTy,
4439 ShiftImm, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004440
4441 return MatchOperand_Success;
4442}
4443
David Blaikie960ea3f2014-06-08 16:18:35 +00004444ARMAsmParser::OperandMatchResultTy
4445ARMAsmParser::parseAM3Offset(OperandVector &Operands) {
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00004446 // Check for a post-index addressing register operand. Specifically:
4447 // am3offset := '+' register
4448 // | '-' register
4449 // | register
4450 // | # imm
4451 // | # + imm
4452 // | # - imm
4453
4454 // This method must return MatchOperand_NoMatch without consuming any tokens
4455 // in the case where there is no match, as other alternatives take other
4456 // parse methods.
4457 AsmToken Tok = Parser.getTok();
4458 SMLoc S = Tok.getLoc();
4459
4460 // Do immediates first, as we always parse those if we have a '#'.
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004461 if (Parser.getTok().is(AsmToken::Hash) ||
4462 Parser.getTok().is(AsmToken::Dollar)) {
Amaury de la Vieuvillebac917f2013-06-10 14:17:15 +00004463 Parser.Lex(); // Eat '#' or '$'.
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00004464 // Explicitly look for a '-', as we need to encode negative zero
4465 // differently.
4466 bool isNegative = Parser.getTok().is(AsmToken::Minus);
4467 const MCExpr *Offset;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004468 SMLoc E;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004469 if (getParser().parseExpression(Offset, E))
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00004470 return MatchOperand_ParseFail;
4471 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4472 if (!CE) {
4473 Error(S, "constant expression expected");
4474 return MatchOperand_ParseFail;
4475 }
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00004476 // Negative zero is encoded as the flag value INT32_MIN.
4477 int32_t Val = CE->getValue();
4478 if (isNegative && Val == 0)
4479 Val = INT32_MIN;
4480
4481 Operands.push_back(
4482 ARMOperand::CreateImm(MCConstantExpr::Create(Val, getContext()), S, E));
4483
4484 return MatchOperand_Success;
4485 }
4486
4487
4488 bool haveEaten = false;
4489 bool isAdd = true;
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00004490 if (Tok.is(AsmToken::Plus)) {
4491 Parser.Lex(); // Eat the '+' token.
4492 haveEaten = true;
4493 } else if (Tok.is(AsmToken::Minus)) {
4494 Parser.Lex(); // Eat the '-' token.
4495 isAdd = false;
4496 haveEaten = true;
4497 }
Saleem Abdulrasool4ab6e732014-02-23 17:45:36 +00004498
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004499 Tok = Parser.getTok();
4500 int Reg = tryParseRegister();
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00004501 if (Reg == -1) {
4502 if (!haveEaten)
4503 return MatchOperand_NoMatch;
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004504 Error(Tok.getLoc(), "register expected");
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00004505 return MatchOperand_ParseFail;
4506 }
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00004507
4508 Operands.push_back(ARMOperand::CreatePostIdxReg(Reg, isAdd, ARM_AM::no_shift,
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004509 0, S, Tok.getEndLoc()));
Jim Grosbach1d9d5e92011-08-10 21:56:18 +00004510
4511 return MatchOperand_Success;
4512}
4513
Tim Northovereb5e4d52013-07-22 09:06:12 +00004514/// Convert parsed operands to MCInst. Needed here because this instruction
4515/// only has two register operands, but multiplication is commutative so
4516/// assemblers should accept both "mul rD, rN, rD" and "mul rD, rD, rN".
David Blaikie960ea3f2014-06-08 16:18:35 +00004517void ARMAsmParser::cvtThumbMultiply(MCInst &Inst,
4518 const OperandVector &Operands) {
4519 ((ARMOperand &)*Operands[3]).addRegOperands(Inst, 1);
4520 ((ARMOperand &)*Operands[1]).addCCOutOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00004521 // If we have a three-operand form, make sure to set Rn to be the operand
4522 // that isn't the same as Rd.
4523 unsigned RegOp = 4;
4524 if (Operands.size() == 6 &&
David Blaikie960ea3f2014-06-08 16:18:35 +00004525 ((ARMOperand &)*Operands[4]).getReg() ==
4526 ((ARMOperand &)*Operands[3]).getReg())
Jim Grosbach5a5ce632011-11-10 22:10:12 +00004527 RegOp = 5;
David Blaikie960ea3f2014-06-08 16:18:35 +00004528 ((ARMOperand &)*Operands[RegOp]).addRegOperands(Inst, 1);
Jim Grosbach5a5ce632011-11-10 22:10:12 +00004529 Inst.addOperand(Inst.getOperand(0));
David Blaikie960ea3f2014-06-08 16:18:35 +00004530 ((ARMOperand &)*Operands[2]).addCondCodeOperands(Inst, 2);
Jim Grosbach8e048492011-08-19 22:07:46 +00004531}
Jim Grosbachcd4dd252011-08-10 22:42:16 +00004532
David Blaikie960ea3f2014-06-08 16:18:35 +00004533void ARMAsmParser::cvtThumbBranches(MCInst &Inst,
4534 const OperandVector &Operands) {
Mihai Popaad18d3c2013-08-09 10:38:32 +00004535 int CondOp = -1, ImmOp = -1;
4536 switch(Inst.getOpcode()) {
4537 case ARM::tB:
4538 case ARM::tBcc: CondOp = 1; ImmOp = 2; break;
4539
4540 case ARM::t2B:
4541 case ARM::t2Bcc: CondOp = 1; ImmOp = 3; break;
4542
4543 default: llvm_unreachable("Unexpected instruction in cvtThumbBranches");
4544 }
4545 // first decide whether or not the branch should be conditional
4546 // by looking at it's location relative to an IT block
4547 if(inITBlock()) {
4548 // inside an IT block we cannot have any conditional branches. any
4549 // such instructions needs to be converted to unconditional form
4550 switch(Inst.getOpcode()) {
4551 case ARM::tBcc: Inst.setOpcode(ARM::tB); break;
4552 case ARM::t2Bcc: Inst.setOpcode(ARM::t2B); break;
4553 }
4554 } else {
4555 // outside IT blocks we can only have unconditional branches with AL
4556 // condition code or conditional branches with non-AL condition code
David Blaikie960ea3f2014-06-08 16:18:35 +00004557 unsigned Cond = static_cast<ARMOperand &>(*Operands[CondOp]).getCondCode();
Mihai Popaad18d3c2013-08-09 10:38:32 +00004558 switch(Inst.getOpcode()) {
4559 case ARM::tB:
4560 case ARM::tBcc:
4561 Inst.setOpcode(Cond == ARMCC::AL ? ARM::tB : ARM::tBcc);
4562 break;
4563 case ARM::t2B:
4564 case ARM::t2Bcc:
4565 Inst.setOpcode(Cond == ARMCC::AL ? ARM::t2B : ARM::t2Bcc);
4566 break;
4567 }
4568 }
Saleem Abdulrasool4ab6e732014-02-23 17:45:36 +00004569
Mihai Popaad18d3c2013-08-09 10:38:32 +00004570 // now decide on encoding size based on branch target range
4571 switch(Inst.getOpcode()) {
4572 // classify tB as either t2B or t1B based on range of immediate operand
4573 case ARM::tB: {
David Blaikie960ea3f2014-06-08 16:18:35 +00004574 ARMOperand &op = static_cast<ARMOperand &>(*Operands[ImmOp]);
4575 if (!op.isSignedOffset<11, 1>() && isThumbTwo())
Mihai Popaad18d3c2013-08-09 10:38:32 +00004576 Inst.setOpcode(ARM::t2B);
4577 break;
4578 }
4579 // classify tBcc as either t2Bcc or t1Bcc based on range of immediate operand
4580 case ARM::tBcc: {
David Blaikie960ea3f2014-06-08 16:18:35 +00004581 ARMOperand &op = static_cast<ARMOperand &>(*Operands[ImmOp]);
4582 if (!op.isSignedOffset<8, 1>() && isThumbTwo())
Mihai Popaad18d3c2013-08-09 10:38:32 +00004583 Inst.setOpcode(ARM::t2Bcc);
4584 break;
4585 }
4586 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004587 ((ARMOperand &)*Operands[ImmOp]).addImmOperands(Inst, 1);
4588 ((ARMOperand &)*Operands[CondOp]).addCondCodeOperands(Inst, 2);
Mihai Popaad18d3c2013-08-09 10:38:32 +00004589}
4590
Bill Wendlinge18980a2010-11-06 22:36:58 +00004591/// Parse an ARM memory expression, return false if successful else return true
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004592/// or an error. The first token must be a '[' when called.
David Blaikie960ea3f2014-06-08 16:18:35 +00004593bool ARMAsmParser::parseMemory(OperandVector &Operands) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004594 SMLoc S, E;
Sean Callanan936b0d32010-01-19 21:44:56 +00004595 assert(Parser.getTok().is(AsmToken::LBrac) &&
Bill Wendling4f4bce02010-11-06 10:48:18 +00004596 "Token is not a Left Bracket");
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004597 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004598 Parser.Lex(); // Eat left bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004599
Sean Callanan936b0d32010-01-19 21:44:56 +00004600 const AsmToken &BaseRegTok = Parser.getTok();
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004601 int BaseRegNum = tryParseRegister();
Jim Grosbachd3595712011-08-03 23:50:40 +00004602 if (BaseRegNum == -1)
4603 return Error(BaseRegTok.getLoc(), "register expected");
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004604
Kristof Beyls2efb59a2013-02-14 14:46:12 +00004605 // The next token must either be a comma, a colon or a closing bracket.
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004606 const AsmToken &Tok = Parser.getTok();
Kristof Beyls2efb59a2013-02-14 14:46:12 +00004607 if (!Tok.is(AsmToken::Colon) && !Tok.is(AsmToken::Comma) &&
4608 !Tok.is(AsmToken::RBrac))
Jim Grosbachd3595712011-08-03 23:50:40 +00004609 return Error(Tok.getLoc(), "malformed memory operand");
Daniel Dunbar1d5e9542011-01-18 05:34:17 +00004610
Jim Grosbachd3595712011-08-03 23:50:40 +00004611 if (Tok.is(AsmToken::RBrac)) {
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004612 E = Tok.getEndLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004613 Parser.Lex(); // Eat right bracket token.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004614
Craig Topper062a2ba2014-04-25 05:30:21 +00004615 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0,
4616 ARM_AM::no_shift, 0, 0, false,
4617 S, E));
Jim Grosbach32ff5582010-11-29 23:18:01 +00004618
Jim Grosbach40700e02011-09-19 18:42:21 +00004619 // If there's a pre-indexing writeback marker, '!', just add it as a token
4620 // operand. It's rather odd, but syntactically valid.
4621 if (Parser.getTok().is(AsmToken::Exclaim)) {
4622 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4623 Parser.Lex(); // Eat the '!'.
4624 }
4625
Jim Grosbachd3595712011-08-03 23:50:40 +00004626 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004627 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004628
Kristof Beyls2efb59a2013-02-14 14:46:12 +00004629 assert((Tok.is(AsmToken::Colon) || Tok.is(AsmToken::Comma)) &&
4630 "Lost colon or comma in memory operand?!");
4631 if (Tok.is(AsmToken::Comma)) {
4632 Parser.Lex(); // Eat the comma.
4633 }
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004634
Jim Grosbacha95ec992011-10-11 17:29:55 +00004635 // If we have a ':', it's an alignment specifier.
4636 if (Parser.getTok().is(AsmToken::Colon)) {
4637 Parser.Lex(); // Eat the ':'.
4638 E = Parser.getTok().getLoc();
Kevin Enderby488f20b2014-04-10 20:18:58 +00004639 SMLoc AlignmentLoc = Tok.getLoc();
Jim Grosbacha95ec992011-10-11 17:29:55 +00004640
4641 const MCExpr *Expr;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004642 if (getParser().parseExpression(Expr))
Jim Grosbacha95ec992011-10-11 17:29:55 +00004643 return true;
4644
4645 // The expression has to be a constant. Memory references with relocations
4646 // don't come through here, as they use the <label> forms of the relevant
4647 // instructions.
4648 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4649 if (!CE)
4650 return Error (E, "constant expression expected");
4651
4652 unsigned Align = 0;
4653 switch (CE->getValue()) {
4654 default:
Jim Grosbachcef98cd2011-12-19 18:31:43 +00004655 return Error(E,
4656 "alignment specifier must be 16, 32, 64, 128, or 256 bits");
4657 case 16: Align = 2; break;
4658 case 32: Align = 4; break;
Jim Grosbacha95ec992011-10-11 17:29:55 +00004659 case 64: Align = 8; break;
4660 case 128: Align = 16; break;
4661 case 256: Align = 32; break;
4662 }
4663
4664 // Now we should have the closing ']'
Jim Grosbacha95ec992011-10-11 17:29:55 +00004665 if (Parser.getTok().isNot(AsmToken::RBrac))
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004666 return Error(Parser.getTok().getLoc(), "']' expected");
4667 E = Parser.getTok().getEndLoc();
Jim Grosbacha95ec992011-10-11 17:29:55 +00004668 Parser.Lex(); // Eat right bracket token.
4669
4670 // Don't worry about range checking the value here. That's handled by
4671 // the is*() predicates.
Craig Topper062a2ba2014-04-25 05:30:21 +00004672 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004673 ARM_AM::no_shift, 0, Align,
Kevin Enderby488f20b2014-04-10 20:18:58 +00004674 false, S, E, AlignmentLoc));
Jim Grosbacha95ec992011-10-11 17:29:55 +00004675
4676 // If there's a pre-indexing writeback marker, '!', just add it as a token
4677 // operand.
4678 if (Parser.getTok().is(AsmToken::Exclaim)) {
4679 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4680 Parser.Lex(); // Eat the '!'.
4681 }
4682
4683 return false;
4684 }
4685
4686 // If we have a '#', it's an immediate offset, else assume it's a register
Jim Grosbach8279c182011-11-15 22:14:41 +00004687 // offset. Be friendly and also accept a plain integer (without a leading
4688 // hash) for gas compatibility.
4689 if (Parser.getTok().is(AsmToken::Hash) ||
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004690 Parser.getTok().is(AsmToken::Dollar) ||
Jim Grosbach8279c182011-11-15 22:14:41 +00004691 Parser.getTok().is(AsmToken::Integer)) {
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004692 if (Parser.getTok().isNot(AsmToken::Integer))
Amaury de la Vieuvillebac917f2013-06-10 14:17:15 +00004693 Parser.Lex(); // Eat '#' or '$'.
Jim Grosbachd3595712011-08-03 23:50:40 +00004694 E = Parser.getTok().getLoc();
Daniel Dunbarf5164f42011-01-18 05:34:24 +00004695
Owen Anderson967674d2011-08-29 19:36:44 +00004696 bool isNegative = getParser().getTok().is(AsmToken::Minus);
Jim Grosbachd3595712011-08-03 23:50:40 +00004697 const MCExpr *Offset;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004698 if (getParser().parseExpression(Offset))
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004699 return true;
Jim Grosbachd3595712011-08-03 23:50:40 +00004700
4701 // The expression has to be a constant. Memory references with relocations
4702 // don't come through here, as they use the <label> forms of the relevant
4703 // instructions.
4704 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Offset);
4705 if (!CE)
4706 return Error (E, "constant expression expected");
4707
Owen Anderson967674d2011-08-29 19:36:44 +00004708 // If the constant was #-0, represent it as INT32_MIN.
4709 int32_t Val = CE->getValue();
4710 if (isNegative && Val == 0)
4711 CE = MCConstantExpr::Create(INT32_MIN, getContext());
4712
Jim Grosbachd3595712011-08-03 23:50:40 +00004713 // Now we should have the closing ']'
Jim Grosbachd3595712011-08-03 23:50:40 +00004714 if (Parser.getTok().isNot(AsmToken::RBrac))
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004715 return Error(Parser.getTok().getLoc(), "']' expected");
4716 E = Parser.getTok().getEndLoc();
Jim Grosbachd3595712011-08-03 23:50:40 +00004717 Parser.Lex(); // Eat right bracket token.
4718
4719 // Don't worry about range checking the value here. That's handled by
4720 // the is*() predicates.
4721 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, CE, 0,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004722 ARM_AM::no_shift, 0, 0,
4723 false, S, E));
Jim Grosbachd3595712011-08-03 23:50:40 +00004724
4725 // If there's a pre-indexing writeback marker, '!', just add it as a token
4726 // operand.
4727 if (Parser.getTok().is(AsmToken::Exclaim)) {
4728 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4729 Parser.Lex(); // Eat the '!'.
4730 }
4731
4732 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004733 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004734
4735 // The register offset is optionally preceded by a '+' or '-'
4736 bool isNegative = false;
4737 if (Parser.getTok().is(AsmToken::Minus)) {
4738 isNegative = true;
4739 Parser.Lex(); // Eat the '-'.
4740 } else if (Parser.getTok().is(AsmToken::Plus)) {
4741 // Nothing to do.
4742 Parser.Lex(); // Eat the '+'.
4743 }
4744
4745 E = Parser.getTok().getLoc();
4746 int OffsetRegNum = tryParseRegister();
4747 if (OffsetRegNum == -1)
4748 return Error(E, "register expected");
4749
4750 // If there's a shift operator, handle it.
4751 ARM_AM::ShiftOpc ShiftType = ARM_AM::no_shift;
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004752 unsigned ShiftImm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004753 if (Parser.getTok().is(AsmToken::Comma)) {
4754 Parser.Lex(); // Eat the ','.
Jim Grosbach3d0b3a32011-08-05 22:03:36 +00004755 if (parseMemRegOffsetShift(ShiftType, ShiftImm))
Jim Grosbachd3595712011-08-03 23:50:40 +00004756 return true;
4757 }
4758
4759 // Now we should have the closing ']'
Jim Grosbachd3595712011-08-03 23:50:40 +00004760 if (Parser.getTok().isNot(AsmToken::RBrac))
Jordan Rosee8f1eae2013-01-07 19:00:49 +00004761 return Error(Parser.getTok().getLoc(), "']' expected");
4762 E = Parser.getTok().getEndLoc();
Jim Grosbachd3595712011-08-03 23:50:40 +00004763 Parser.Lex(); // Eat right bracket token.
4764
Craig Topper062a2ba2014-04-25 05:30:21 +00004765 Operands.push_back(ARMOperand::CreateMem(BaseRegNum, nullptr, OffsetRegNum,
Jim Grosbacha95ec992011-10-11 17:29:55 +00004766 ShiftType, ShiftImm, 0, isNegative,
Jim Grosbachd3595712011-08-03 23:50:40 +00004767 S, E));
4768
Jim Grosbachc320c852011-08-05 21:28:30 +00004769 // If there's a pre-indexing writeback marker, '!', just add it as a token
4770 // operand.
4771 if (Parser.getTok().is(AsmToken::Exclaim)) {
4772 Operands.push_back(ARMOperand::CreateToken("!",Parser.getTok().getLoc()));
4773 Parser.Lex(); // Eat the '!'.
4774 }
Jim Grosbachd3595712011-08-03 23:50:40 +00004775
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004776 return false;
4777}
4778
Jim Grosbachd3595712011-08-03 23:50:40 +00004779/// parseMemRegOffsetShift - one of these two:
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004780/// ( lsl | lsr | asr | ror ) , # shift_amount
4781/// rrx
Jim Grosbachd3595712011-08-03 23:50:40 +00004782/// return true if it parses a shift otherwise it returns false.
4783bool ARMAsmParser::parseMemRegOffsetShift(ARM_AM::ShiftOpc &St,
4784 unsigned &Amount) {
4785 SMLoc Loc = Parser.getTok().getLoc();
Sean Callanan936b0d32010-01-19 21:44:56 +00004786 const AsmToken &Tok = Parser.getTok();
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004787 if (Tok.isNot(AsmToken::Identifier))
4788 return true;
Benjamin Kramer92d89982010-07-14 22:38:02 +00004789 StringRef ShiftName = Tok.getString();
Jim Grosbach3b559ff2011-12-07 23:40:58 +00004790 if (ShiftName == "lsl" || ShiftName == "LSL" ||
4791 ShiftName == "asl" || ShiftName == "ASL")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004792 St = ARM_AM::lsl;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004793 else if (ShiftName == "lsr" || ShiftName == "LSR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004794 St = ARM_AM::lsr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004795 else if (ShiftName == "asr" || ShiftName == "ASR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004796 St = ARM_AM::asr;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004797 else if (ShiftName == "ror" || ShiftName == "ROR")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004798 St = ARM_AM::ror;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004799 else if (ShiftName == "rrx" || ShiftName == "RRX")
Owen Anderson1d2f5ce2011-03-18 22:50:18 +00004800 St = ARM_AM::rrx;
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004801 else
Jim Grosbachd3595712011-08-03 23:50:40 +00004802 return Error(Loc, "illegal shift operator");
Sean Callanana83fd7d2010-01-19 20:27:46 +00004803 Parser.Lex(); // Eat shift type token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004804
Jim Grosbachd3595712011-08-03 23:50:40 +00004805 // rrx stands alone.
4806 Amount = 0;
4807 if (St != ARM_AM::rrx) {
4808 Loc = Parser.getTok().getLoc();
4809 // A '#' and a shift amount.
4810 const AsmToken &HashTok = Parser.getTok();
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004811 if (HashTok.isNot(AsmToken::Hash) &&
4812 HashTok.isNot(AsmToken::Dollar))
Jim Grosbachd3595712011-08-03 23:50:40 +00004813 return Error(HashTok.getLoc(), "'#' expected");
4814 Parser.Lex(); // Eat hash token.
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004815
Jim Grosbachd3595712011-08-03 23:50:40 +00004816 const MCExpr *Expr;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004817 if (getParser().parseExpression(Expr))
Jim Grosbachd3595712011-08-03 23:50:40 +00004818 return true;
4819 // Range check the immediate.
4820 // lsl, ror: 0 <= imm <= 31
4821 // lsr, asr: 0 <= imm <= 32
4822 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
4823 if (!CE)
4824 return Error(Loc, "shift amount must be an immediate");
4825 int64_t Imm = CE->getValue();
4826 if (Imm < 0 ||
4827 ((St == ARM_AM::lsl || St == ARM_AM::ror) && Imm > 31) ||
4828 ((St == ARM_AM::lsr || St == ARM_AM::asr) && Imm > 32))
4829 return Error(Loc, "immediate shift value out of range");
Tim Northover0c97e762012-09-22 11:18:12 +00004830 // If <ShiftTy> #0, turn it into a no_shift.
4831 if (Imm == 0)
4832 St = ARM_AM::lsl;
4833 // For consistency, treat lsr #32 and asr #32 as having immediate value 0.
4834 if (Imm == 32)
4835 Imm = 0;
Jim Grosbachd3595712011-08-03 23:50:40 +00004836 Amount = Imm;
4837 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004838
4839 return false;
4840}
4841
Jim Grosbache7fbce72011-10-03 23:38:36 +00004842/// parseFPImm - A floating point immediate expression operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00004843ARMAsmParser::OperandMatchResultTy
4844ARMAsmParser::parseFPImm(OperandVector &Operands) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004845 // Anything that can accept a floating point constant as an operand
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004846 // needs to go through here, as the regular parseExpression is
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004847 // integer only.
4848 //
4849 // This routine still creates a generic Immediate operand, containing
4850 // a bitcast of the 64-bit floating point value. The various operands
4851 // that accept floats can check whether the value is valid for them
4852 // via the standard is*() predicates.
4853
Jim Grosbache7fbce72011-10-03 23:38:36 +00004854 SMLoc S = Parser.getTok().getLoc();
4855
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004856 if (Parser.getTok().isNot(AsmToken::Hash) &&
4857 Parser.getTok().isNot(AsmToken::Dollar))
Jim Grosbache7fbce72011-10-03 23:38:36 +00004858 return MatchOperand_NoMatch;
Jim Grosbach741cd732011-10-17 22:26:03 +00004859
4860 // Disambiguate the VMOV forms that can accept an FP immediate.
4861 // vmov.f32 <sreg>, #imm
4862 // vmov.f64 <dreg>, #imm
4863 // vmov.f32 <dreg>, #imm @ vector f32x2
4864 // vmov.f32 <qreg>, #imm @ vector f32x4
4865 //
4866 // There are also the NEON VMOV instructions which expect an
4867 // integer constant. Make sure we don't try to parse an FPImm
4868 // for these:
4869 // vmov.i{8|16|32|64} <dreg|qreg>, #imm
David Blaikie960ea3f2014-06-08 16:18:35 +00004870 ARMOperand &TyOp = static_cast<ARMOperand &>(*Operands[2]);
4871 bool isVmovf = TyOp.isToken() &&
4872 (TyOp.getToken() == ".f32" || TyOp.getToken() == ".f64");
4873 ARMOperand &Mnemonic = static_cast<ARMOperand &>(*Operands[0]);
4874 bool isFconst = Mnemonic.isToken() && (Mnemonic.getToken() == "fconstd" ||
4875 Mnemonic.getToken() == "fconsts");
David Peixottoa872e0e2014-01-07 18:19:23 +00004876 if (!(isVmovf || isFconst))
Jim Grosbach741cd732011-10-17 22:26:03 +00004877 return MatchOperand_NoMatch;
4878
Amaury de la Vieuvillebac917f2013-06-10 14:17:15 +00004879 Parser.Lex(); // Eat '#' or '$'.
Jim Grosbache7fbce72011-10-03 23:38:36 +00004880
4881 // Handle negation, as that still comes through as a separate token.
4882 bool isNegative = false;
4883 if (Parser.getTok().is(AsmToken::Minus)) {
4884 isNegative = true;
4885 Parser.Lex();
4886 }
4887 const AsmToken &Tok = Parser.getTok();
Jim Grosbach235c8d22012-01-19 02:47:30 +00004888 SMLoc Loc = Tok.getLoc();
David Peixottoa872e0e2014-01-07 18:19:23 +00004889 if (Tok.is(AsmToken::Real) && isVmovf) {
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004890 APFloat RealVal(APFloat::IEEEsingle, Tok.getString());
Jim Grosbache7fbce72011-10-03 23:38:36 +00004891 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
4892 // If we had a '-' in front, toggle the sign bit.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004893 IntVal ^= (uint64_t)isNegative << 31;
Jim Grosbache7fbce72011-10-03 23:38:36 +00004894 Parser.Lex(); // Eat the token.
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004895 Operands.push_back(ARMOperand::CreateImm(
4896 MCConstantExpr::Create(IntVal, getContext()),
4897 S, Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004898 return MatchOperand_Success;
4899 }
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004900 // Also handle plain integers. Instructions which allow floating point
4901 // immediates also allow a raw encoded 8-bit value.
David Peixottoa872e0e2014-01-07 18:19:23 +00004902 if (Tok.is(AsmToken::Integer) && isFconst) {
Jim Grosbache7fbce72011-10-03 23:38:36 +00004903 int64_t Val = Tok.getIntVal();
4904 Parser.Lex(); // Eat the token.
4905 if (Val > 255 || Val < 0) {
Jim Grosbach235c8d22012-01-19 02:47:30 +00004906 Error(Loc, "encoded floating point value out of range");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004907 return MatchOperand_ParseFail;
4908 }
David Peixottoa872e0e2014-01-07 18:19:23 +00004909 float RealVal = ARM_AM::getFPImmFloat(Val);
4910 Val = APFloat(RealVal).bitcastToAPInt().getZExtValue();
4911
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004912 Operands.push_back(ARMOperand::CreateImm(
4913 MCConstantExpr::Create(Val, getContext()), S,
4914 Parser.getTok().getLoc()));
Jim Grosbache7fbce72011-10-03 23:38:36 +00004915 return MatchOperand_Success;
4916 }
4917
Jim Grosbach235c8d22012-01-19 02:47:30 +00004918 Error(Loc, "invalid floating point immediate");
Jim Grosbache7fbce72011-10-03 23:38:36 +00004919 return MatchOperand_ParseFail;
4920}
Jim Grosbacha9d36fb2012-01-20 18:09:51 +00004921
Kevin Enderby8be42bd2009-10-30 22:55:57 +00004922/// Parse a arm instruction operand. For now this parses the operand regardless
4923/// of the mnemonic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004924bool ARMAsmParser::parseOperand(OperandVector &Operands, StringRef Mnemonic) {
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004925 SMLoc S, E;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004926
4927 // Check if the current operand has a custom associated parser, if so, try to
4928 // custom parse the operand, or fallback to the general approach.
Jim Grosbach861e49c2011-02-12 01:34:40 +00004929 OperandMatchResultTy ResTy = MatchOperandParserImpl(Operands, Mnemonic);
4930 if (ResTy == MatchOperand_Success)
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004931 return false;
Jim Grosbach861e49c2011-02-12 01:34:40 +00004932 // If there wasn't a custom match, try the generic matcher below. Otherwise,
4933 // there was a match, but an error occurred, in which case, just return that
4934 // the operand parsing failed.
4935 if (ResTy == MatchOperand_ParseFail)
4936 return true;
Bruno Cardoso Lopesc9253b42011-02-07 21:41:25 +00004937
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004938 switch (getLexer().getKind()) {
Bill Wendlingee7f1f92010-11-06 21:42:12 +00004939 default:
4940 Error(Parser.getTok().getLoc(), "unexpected token in operand");
Bill Wendling2063b842010-11-18 23:43:05 +00004941 return true;
Jim Grosbachbb24c592011-07-13 18:49:30 +00004942 case AsmToken::Identifier: {
Chad Rosierb162a5c2013-03-19 23:44:03 +00004943 // If we've seen a branch mnemonic, the next operand must be a label. This
4944 // is true even if the label is a register name. So "br r1" means branch to
4945 // label "r1".
4946 bool ExpectLabel = Mnemonic == "b" || Mnemonic == "bl";
4947 if (!ExpectLabel) {
4948 if (!tryParseRegisterWithWriteBack(Operands))
4949 return false;
4950 int Res = tryParseShiftRegister(Operands);
4951 if (Res == 0) // success
4952 return false;
4953 else if (Res == -1) // irrecoverable error
4954 return true;
4955 // If this is VMRS, check for the apsr_nzcv operand.
4956 if (Mnemonic == "vmrs" &&
4957 Parser.getTok().getString().equals_lower("apsr_nzcv")) {
4958 S = Parser.getTok().getLoc();
4959 Parser.Lex();
4960 Operands.push_back(ARMOperand::CreateToken("APSR_nzcv", S));
4961 return false;
4962 }
Jim Grosbach4ab23b52011-10-03 21:12:43 +00004963 }
Owen Andersonc3c7f5d2011-01-13 21:46:02 +00004964
4965 // Fall though for the Identifier case that is not a register or a
4966 // special name.
Jim Grosbachbb24c592011-07-13 18:49:30 +00004967 }
Jim Grosbach4e380352011-10-26 21:14:08 +00004968 case AsmToken::LParen: // parenthesized expressions like (_strcmp-4)
Kevin Enderbyb084be92011-01-13 20:32:36 +00004969 case AsmToken::Integer: // things like 1f and 2b as a branch targets
Jim Grosbach5c6b6342011-11-01 22:38:31 +00004970 case AsmToken::String: // quoted label names.
Kevin Enderbyb084be92011-01-13 20:32:36 +00004971 case AsmToken::Dot: { // . as a branch target
Kevin Enderby146dcf22009-10-15 20:48:48 +00004972 // This was not a register so parse other operands that start with an
4973 // identifier (like labels) as expressions and create them as immediates.
4974 const MCExpr *IdVal;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004975 S = Parser.getTok().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004976 if (getParser().parseExpression(IdVal))
Bill Wendling2063b842010-11-18 23:43:05 +00004977 return true;
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004978 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Bill Wendling2063b842010-11-18 23:43:05 +00004979 Operands.push_back(ARMOperand::CreateImm(IdVal, S, E));
4980 return false;
4981 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00004982 case AsmToken::LBrac:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004983 return parseMemory(Operands);
Kevin Enderbya2b99102009-10-09 21:12:28 +00004984 case AsmToken::LCurly:
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00004985 return parseRegisterList(Operands);
Jim Grosbachef70e9b2011-12-09 22:25:03 +00004986 case AsmToken::Dollar:
Owen Andersonf02d98d2011-08-29 17:17:09 +00004987 case AsmToken::Hash: {
Kevin Enderby3a80dac2009-10-13 23:33:38 +00004988 // #42 -> immediate.
Sean Callanan7ad0ad02010-04-02 22:27:05 +00004989 S = Parser.getTok().getLoc();
Sean Callanana83fd7d2010-01-19 20:27:46 +00004990 Parser.Lex();
Jim Grosbach003607f2012-04-16 21:18:46 +00004991
4992 if (Parser.getTok().isNot(AsmToken::Colon)) {
4993 bool isNegative = Parser.getTok().is(AsmToken::Minus);
4994 const MCExpr *ImmVal;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00004995 if (getParser().parseExpression(ImmVal))
Jim Grosbach003607f2012-04-16 21:18:46 +00004996 return true;
4997 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ImmVal);
4998 if (CE) {
4999 int32_t Val = CE->getValue();
5000 if (isNegative && Val == 0)
5001 ImmVal = MCConstantExpr::Create(INT32_MIN, getContext());
5002 }
5003 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5004 Operands.push_back(ARMOperand::CreateImm(ImmVal, S, E));
Jim Grosbach9be2d712013-02-23 00:52:09 +00005005
5006 // There can be a trailing '!' on operands that we want as a separate
Saleem Abdulrasool83e37702013-12-28 03:07:12 +00005007 // '!' Token operand. Handle that here. For example, the compatibility
Jim Grosbach9be2d712013-02-23 00:52:09 +00005008 // alias for 'srsdb sp!, #imm' is 'srsdb #imm!'.
5009 if (Parser.getTok().is(AsmToken::Exclaim)) {
5010 Operands.push_back(ARMOperand::CreateToken(Parser.getTok().getString(),
5011 Parser.getTok().getLoc()));
5012 Parser.Lex(); // Eat exclaim token
5013 }
Jim Grosbach003607f2012-04-16 21:18:46 +00005014 return false;
Owen Andersonf02d98d2011-08-29 17:17:09 +00005015 }
Jim Grosbach003607f2012-04-16 21:18:46 +00005016 // w/ a ':' after the '#', it's just like a plain ':'.
5017 // FALLTHROUGH
Owen Andersonf02d98d2011-08-29 17:17:09 +00005018 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00005019 case AsmToken::Colon: {
5020 // ":lower16:" and ":upper16:" expression prefixes
Evan Cheng965b3c72011-01-13 07:58:56 +00005021 // FIXME: Check it's an expression prefix,
5022 // e.g. (FOO - :lower16:BAR) isn't legal.
5023 ARMMCExpr::VariantKind RefKind;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005024 if (parsePrefix(RefKind))
Jason W Kim1f7bc072011-01-11 23:53:41 +00005025 return true;
5026
Evan Cheng965b3c72011-01-13 07:58:56 +00005027 const MCExpr *SubExprVal;
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005028 if (getParser().parseExpression(SubExprVal))
Jason W Kim1f7bc072011-01-11 23:53:41 +00005029 return true;
5030
Evan Cheng965b3c72011-01-13 07:58:56 +00005031 const MCExpr *ExprVal = ARMMCExpr::Create(RefKind, SubExprVal,
Jim Grosbach9659ed92012-09-21 00:26:53 +00005032 getContext());
Jason W Kim1f7bc072011-01-11 23:53:41 +00005033 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
Evan Cheng965b3c72011-01-13 07:58:56 +00005034 Operands.push_back(ARMOperand::CreateImm(ExprVal, S, E));
Jason W Kim1f7bc072011-01-11 23:53:41 +00005035 return false;
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005036 }
David Peixottoe407d092013-12-19 18:12:36 +00005037 case AsmToken::Equal: {
5038 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
5039 return Error(Parser.getTok().getLoc(), "unexpected token in operand");
5040
David Peixottoe407d092013-12-19 18:12:36 +00005041 Parser.Lex(); // Eat '='
5042 const MCExpr *SubExprVal;
5043 if (getParser().parseExpression(SubExprVal))
5044 return true;
5045 E = SMLoc::getFromPointer(Parser.getTok().getLoc().getPointer() - 1);
5046
David Peixottob9b73622014-02-04 17:22:40 +00005047 const MCExpr *CPLoc = getTargetStreamer().addConstantPoolEntry(SubExprVal);
David Peixottoe407d092013-12-19 18:12:36 +00005048 Operands.push_back(ARMOperand::CreateImm(CPLoc, S, E));
5049 return false;
5050 }
Jason W Kim1f7bc072011-01-11 23:53:41 +00005051 }
5052}
5053
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005054// parsePrefix - Parse ARM 16-bit relocations expression prefix, i.e.
Evan Cheng965b3c72011-01-13 07:58:56 +00005055// :lower16: and :upper16:.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005056bool ARMAsmParser::parsePrefix(ARMMCExpr::VariantKind &RefKind) {
Evan Cheng965b3c72011-01-13 07:58:56 +00005057 RefKind = ARMMCExpr::VK_ARM_None;
Jason W Kim1f7bc072011-01-11 23:53:41 +00005058
Saleem Abdulrasool435f4562014-01-10 04:38:40 +00005059 // consume an optional '#' (GNU compatibility)
5060 if (getLexer().is(AsmToken::Hash))
5061 Parser.Lex();
5062
Jason W Kim1f7bc072011-01-11 23:53:41 +00005063 // :lower16: and :upper16: modifiers
Jason W Kim93229972011-01-13 00:27:00 +00005064 assert(getLexer().is(AsmToken::Colon) && "expected a :");
Jason W Kim1f7bc072011-01-11 23:53:41 +00005065 Parser.Lex(); // Eat ':'
5066
5067 if (getLexer().isNot(AsmToken::Identifier)) {
5068 Error(Parser.getTok().getLoc(), "expected prefix identifier in operand");
5069 return true;
5070 }
5071
5072 StringRef IDVal = Parser.getTok().getIdentifier();
5073 if (IDVal == "lower16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00005074 RefKind = ARMMCExpr::VK_ARM_LO16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00005075 } else if (IDVal == "upper16") {
Evan Cheng965b3c72011-01-13 07:58:56 +00005076 RefKind = ARMMCExpr::VK_ARM_HI16;
Jason W Kim1f7bc072011-01-11 23:53:41 +00005077 } else {
5078 Error(Parser.getTok().getLoc(), "unexpected prefix in operand");
5079 return true;
5080 }
5081 Parser.Lex();
5082
5083 if (getLexer().isNot(AsmToken::Colon)) {
5084 Error(Parser.getTok().getLoc(), "unexpected token after prefix");
5085 return true;
5086 }
5087 Parser.Lex(); // Eat the last ':'
5088 return false;
5089}
5090
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005091/// \brief Given a mnemonic, split out possible predication code and carry
5092/// setting letters to form a canonical mnemonic and flags.
5093//
Daniel Dunbar876bb0182011-01-10 12:24:52 +00005094// FIXME: Would be nice to autogen this.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005095// FIXME: This is a bit of a maze of special cases.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005096StringRef ARMAsmParser::splitMnemonic(StringRef Mnemonic,
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00005097 unsigned &PredicationCode,
5098 bool &CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005099 unsigned &ProcessorIMod,
5100 StringRef &ITMask) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005101 PredicationCode = ARMCC::AL;
5102 CarrySetting = false;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00005103 ProcessorIMod = 0;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005104
Daniel Dunbar876bb0182011-01-10 12:24:52 +00005105 // Ignore some mnemonics we know aren't predicated forms.
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005106 //
5107 // FIXME: Would be nice to autogen this.
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00005108 if ((Mnemonic == "movs" && isThumb()) ||
5109 Mnemonic == "teq" || Mnemonic == "vceq" || Mnemonic == "svc" ||
5110 Mnemonic == "mls" || Mnemonic == "smmls" || Mnemonic == "vcls" ||
5111 Mnemonic == "vmls" || Mnemonic == "vnmls" || Mnemonic == "vacge" ||
5112 Mnemonic == "vcge" || Mnemonic == "vclt" || Mnemonic == "vacgt" ||
Richard Barton8d519fe2013-09-05 14:14:19 +00005113 Mnemonic == "vaclt" || Mnemonic == "vacle" || Mnemonic == "hlt" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00005114 Mnemonic == "vcgt" || Mnemonic == "vcle" || Mnemonic == "smlal" ||
5115 Mnemonic == "umaal" || Mnemonic == "umlal" || Mnemonic == "vabal" ||
Jim Grosbache16acac2011-12-19 19:43:50 +00005116 Mnemonic == "vmlal" || Mnemonic == "vpadal" || Mnemonic == "vqdmlal" ||
Joey Gouly2efaa732013-07-06 20:50:18 +00005117 Mnemonic == "fmuls" || Mnemonic == "vmaxnm" || Mnemonic == "vminnm" ||
Joey Gouly0f12aa22013-07-09 11:26:18 +00005118 Mnemonic == "vcvta" || Mnemonic == "vcvtn" || Mnemonic == "vcvtp" ||
5119 Mnemonic == "vcvtm" || Mnemonic == "vrinta" || Mnemonic == "vrintn" ||
5120 Mnemonic == "vrintp" || Mnemonic == "vrintm" || Mnemonic.startswith("vsel"))
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005121 return Mnemonic;
Daniel Dunbar75d26be2010-08-11 06:37:16 +00005122
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00005123 // First, split out any predication code. Ignore mnemonics we know aren't
5124 // predicated but do have a carry-set and so weren't caught above.
Jim Grosbach8d114902011-07-20 18:20:31 +00005125 if (Mnemonic != "adcs" && Mnemonic != "bics" && Mnemonic != "movs" &&
Jim Grosbach0c398b92011-07-27 21:58:11 +00005126 Mnemonic != "muls" && Mnemonic != "smlals" && Mnemonic != "smulls" &&
Jim Grosbach3636be32011-08-22 23:55:58 +00005127 Mnemonic != "umlals" && Mnemonic != "umulls" && Mnemonic != "lsls" &&
Jim Grosbachf6d5d602011-09-01 18:22:13 +00005128 Mnemonic != "sbcs" && Mnemonic != "rscs") {
Jim Grosbacha9a3f0a2011-07-11 17:09:57 +00005129 unsigned CC = StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2))
5130 .Case("eq", ARMCC::EQ)
5131 .Case("ne", ARMCC::NE)
5132 .Case("hs", ARMCC::HS)
5133 .Case("cs", ARMCC::HS)
5134 .Case("lo", ARMCC::LO)
5135 .Case("cc", ARMCC::LO)
5136 .Case("mi", ARMCC::MI)
5137 .Case("pl", ARMCC::PL)
5138 .Case("vs", ARMCC::VS)
5139 .Case("vc", ARMCC::VC)
5140 .Case("hi", ARMCC::HI)
5141 .Case("ls", ARMCC::LS)
5142 .Case("ge", ARMCC::GE)
5143 .Case("lt", ARMCC::LT)
5144 .Case("gt", ARMCC::GT)
5145 .Case("le", ARMCC::LE)
5146 .Case("al", ARMCC::AL)
5147 .Default(~0U);
5148 if (CC != ~0U) {
5149 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 2);
5150 PredicationCode = CC;
5151 }
Bill Wendling193961b2010-10-29 23:50:21 +00005152 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00005153
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005154 // Next, determine if we have a carry setting bit. We explicitly ignore all
5155 // the instructions we know end in 's'.
5156 if (Mnemonic.endswith("s") &&
Jim Grosbachd3e8e292011-08-17 22:49:09 +00005157 !(Mnemonic == "cps" || Mnemonic == "mls" ||
Jim Grosbach5cc3b4c2011-07-19 20:10:31 +00005158 Mnemonic == "mrs" || Mnemonic == "smmls" || Mnemonic == "vabs" ||
5159 Mnemonic == "vcls" || Mnemonic == "vmls" || Mnemonic == "vmrs" ||
5160 Mnemonic == "vnmls" || Mnemonic == "vqabs" || Mnemonic == "vrecps" ||
Jim Grosbach086d0132011-12-08 00:49:29 +00005161 Mnemonic == "vrsqrts" || Mnemonic == "srs" || Mnemonic == "flds" ||
Jim Grosbach54337b82011-12-10 00:01:02 +00005162 Mnemonic == "fmrs" || Mnemonic == "fsqrts" || Mnemonic == "fsubs" ||
Jim Grosbach92a939a2011-12-19 19:02:41 +00005163 Mnemonic == "fsts" || Mnemonic == "fcpys" || Mnemonic == "fdivs" ||
Jim Grosbachd74560b2012-03-15 20:48:18 +00005164 Mnemonic == "fmuls" || Mnemonic == "fcmps" || Mnemonic == "fcmpzs" ||
David Peixottoa872e0e2014-01-07 18:19:23 +00005165 Mnemonic == "vfms" || Mnemonic == "vfnms" || Mnemonic == "fconsts" ||
Jim Grosbach51726e22011-07-29 20:26:09 +00005166 (Mnemonic == "movs" && isThumb()))) {
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005167 Mnemonic = Mnemonic.slice(0, Mnemonic.size() - 1);
5168 CarrySetting = true;
5169 }
5170
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00005171 // The "cps" instruction can have a interrupt mode operand which is glued into
5172 // the mnemonic. Check if this is the case, split it and parse the imod op
5173 if (Mnemonic.startswith("cps")) {
5174 // Split out any imod code.
5175 unsigned IMod =
5176 StringSwitch<unsigned>(Mnemonic.substr(Mnemonic.size()-2, 2))
5177 .Case("ie", ARM_PROC::IE)
5178 .Case("id", ARM_PROC::ID)
5179 .Default(~0U);
5180 if (IMod != ~0U) {
5181 Mnemonic = Mnemonic.slice(0, Mnemonic.size()-2);
5182 ProcessorIMod = IMod;
5183 }
5184 }
5185
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005186 // The "it" instruction has the condition mask on the end of the mnemonic.
5187 if (Mnemonic.startswith("it")) {
5188 ITMask = Mnemonic.slice(2, Mnemonic.size());
5189 Mnemonic = Mnemonic.slice(0, 2);
5190 }
5191
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005192 return Mnemonic;
5193}
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005194
5195/// \brief Given a canonical mnemonic, determine if the instruction ever allows
5196/// inclusion of carry set or predication code operands.
5197//
5198// FIXME: It would be nice to autogen this.
Bruno Cardoso Lopese6290cc2011-01-18 20:55:11 +00005199void ARMAsmParser::
Amara Emerson33089092013-09-19 11:59:01 +00005200getMnemonicAcceptInfo(StringRef Mnemonic, StringRef FullInst,
5201 bool &CanAcceptCarrySet, bool &CanAcceptPredicationCode) {
Daniel Dunbar09264122011-01-11 19:06:29 +00005202 if (Mnemonic == "and" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
5203 Mnemonic == "rrx" || Mnemonic == "ror" || Mnemonic == "sub" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00005204 Mnemonic == "add" || Mnemonic == "adc" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00005205 Mnemonic == "mul" || Mnemonic == "bic" || Mnemonic == "asr" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00005206 Mnemonic == "orr" || Mnemonic == "mvn" ||
Daniel Dunbar09264122011-01-11 19:06:29 +00005207 Mnemonic == "rsb" || Mnemonic == "rsc" || Mnemonic == "orn" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00005208 Mnemonic == "sbc" || Mnemonic == "eor" || Mnemonic == "neg" ||
Evan Chengaca6c822012-04-11 00:13:00 +00005209 Mnemonic == "vfm" || Mnemonic == "vfnm" ||
Jim Grosbachd73c6452011-09-16 18:05:48 +00005210 (!isThumb() && (Mnemonic == "smull" || Mnemonic == "mov" ||
Jim Grosbachfc545182011-09-19 23:31:02 +00005211 Mnemonic == "mla" || Mnemonic == "smlal" ||
5212 Mnemonic == "umlal" || Mnemonic == "umull"))) {
Daniel Dunbar09264122011-01-11 19:06:29 +00005213 CanAcceptCarrySet = true;
Jim Grosbach6c45b752011-09-16 16:39:25 +00005214 } else
Daniel Dunbar09264122011-01-11 19:06:29 +00005215 CanAcceptCarrySet = false;
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005216
Tim Northover2c45a382013-06-26 16:52:40 +00005217 if (Mnemonic == "bkpt" || Mnemonic == "cbnz" || Mnemonic == "setend" ||
5218 Mnemonic == "cps" || Mnemonic == "it" || Mnemonic == "cbz" ||
Saleem Abdulrasool27351f22014-05-14 03:47:39 +00005219 Mnemonic == "trap" || Mnemonic == "hlt" || Mnemonic == "udf" ||
5220 Mnemonic.startswith("crc32") || Mnemonic.startswith("cps") ||
5221 Mnemonic.startswith("vsel") ||
Joey Gouly2d0175e2013-07-09 09:59:04 +00005222 Mnemonic == "vmaxnm" || Mnemonic == "vminnm" || Mnemonic == "vcvta" ||
Joey Gouly0f12aa22013-07-09 11:26:18 +00005223 Mnemonic == "vcvtn" || Mnemonic == "vcvtp" || Mnemonic == "vcvtm" ||
5224 Mnemonic == "vrinta" || Mnemonic == "vrintn" || Mnemonic == "vrintp" ||
Amara Emerson33089092013-09-19 11:59:01 +00005225 Mnemonic == "vrintm" || Mnemonic.startswith("aes") ||
5226 Mnemonic.startswith("sha1") || Mnemonic.startswith("sha256") ||
5227 (FullInst.startswith("vmull") && FullInst.endswith(".p64"))) {
Tim Northover2c45a382013-06-26 16:52:40 +00005228 // These mnemonics are never predicable
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005229 CanAcceptPredicationCode = false;
Tim Northover2c45a382013-06-26 16:52:40 +00005230 } else if (!isThumb()) {
5231 // Some instructions are only predicable in Thumb mode
5232 CanAcceptPredicationCode
5233 = Mnemonic != "cdp2" && Mnemonic != "clrex" && Mnemonic != "mcr2" &&
5234 Mnemonic != "mcrr2" && Mnemonic != "mrc2" && Mnemonic != "mrrc2" &&
5235 Mnemonic != "dmb" && Mnemonic != "dsb" && Mnemonic != "isb" &&
5236 Mnemonic != "pld" && Mnemonic != "pli" && Mnemonic != "pldw" &&
5237 Mnemonic != "ldc2" && Mnemonic != "ldc2l" &&
5238 Mnemonic != "stc2" && Mnemonic != "stc2l" &&
5239 !Mnemonic.startswith("rfe") && !Mnemonic.startswith("srs");
5240 } else if (isThumbOne()) {
Tim Northoverf86d1f02013-10-07 11:10:47 +00005241 if (hasV6MOps())
5242 CanAcceptPredicationCode = Mnemonic != "movs";
5243 else
5244 CanAcceptPredicationCode = Mnemonic != "nop" && Mnemonic != "movs";
Jim Grosbach6c45b752011-09-16 16:39:25 +00005245 } else
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005246 CanAcceptPredicationCode = true;
Daniel Dunbar876bb0182011-01-10 12:24:52 +00005247}
5248
Jim Grosbach7283da92011-08-16 21:12:37 +00005249bool ARMAsmParser::shouldOmitCCOutOperand(StringRef Mnemonic,
David Blaikie960ea3f2014-06-08 16:18:35 +00005250 OperandVector &Operands) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005251 // FIXME: This is all horribly hacky. We really need a better way to deal
5252 // with optional operands like this in the matcher table.
Jim Grosbach7283da92011-08-16 21:12:37 +00005253
5254 // The 'mov' mnemonic is special. One variant has a cc_out operand, while
5255 // another does not. Specifically, the MOVW instruction does not. So we
5256 // special case it here and remove the defaulted (non-setting) cc_out
5257 // operand if that's the instruction we're trying to match.
5258 //
5259 // We do this as post-processing of the explicit operands rather than just
5260 // conditionally adding the cc_out in the first place because we need
5261 // to check the type of the parsed immediate operand.
Owen Andersond7791b92011-09-14 22:46:14 +00005262 if (Mnemonic == "mov" && Operands.size() > 4 && !isThumb() &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005263 !static_cast<ARMOperand &>(*Operands[4]).isARMSOImm() &&
5264 static_cast<ARMOperand &>(*Operands[4]).isImm0_65535Expr() &&
5265 static_cast<ARMOperand &>(*Operands[1]).getReg() == 0)
Jim Grosbach7283da92011-08-16 21:12:37 +00005266 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00005267
5268 // Register-register 'add' for thumb does not have a cc_out operand
5269 // when there are only two register operands.
5270 if (isThumb() && Mnemonic == "add" && Operands.size() == 5 &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005271 static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5272 static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5273 static_cast<ARMOperand &>(*Operands[1]).getReg() == 0)
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00005274 return true;
Jim Grosbach0a0b3072011-08-24 21:22:15 +00005275 // Register-register 'add' for thumb does not have a cc_out operand
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005276 // when it's an ADD Rdm, SP, {Rdm|#imm0_255} instruction. We do
5277 // have to check the immediate range here since Thumb2 has a variant
5278 // that can handle a different range and has a cc_out operand.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005279 if (((isThumb() && Mnemonic == "add") ||
5280 (isThumbTwo() && Mnemonic == "sub")) &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005281 Operands.size() == 6 && static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5282 static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5283 static_cast<ARMOperand &>(*Operands[4]).getReg() == ARM::SP &&
5284 static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 &&
5285 ((Mnemonic == "add" && static_cast<ARMOperand &>(*Operands[5]).isReg()) ||
5286 static_cast<ARMOperand &>(*Operands[5]).isImm0_1020s4()))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00005287 return true;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005288 // For Thumb2, add/sub immediate does not have a cc_out operand for the
5289 // imm0_4095 variant. That's the least-preferred variant when
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005290 // selecting via the generic "add" mnemonic, so to know that we
5291 // should remove the cc_out operand, we have to explicitly check that
5292 // it's not one of the other variants. Ugh.
Jim Grosbachd0c435c2011-09-16 22:58:42 +00005293 if (isThumbTwo() && (Mnemonic == "add" || Mnemonic == "sub") &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005294 Operands.size() == 6 && static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5295 static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5296 static_cast<ARMOperand &>(*Operands[5]).isImm()) {
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005297 // Nest conditions rather than one big 'if' statement for readability.
5298 //
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005299 // If both registers are low, we're in an IT block, and the immediate is
5300 // in range, we should use encoding T1 instead, which has a cc_out.
5301 if (inITBlock() &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005302 isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg()) &&
5303 isARMLowRegister(static_cast<ARMOperand &>(*Operands[4]).getReg()) &&
5304 static_cast<ARMOperand &>(*Operands[5]).isImm0_7())
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005305 return false;
Tilmann Schelleref5666f2013-07-03 20:38:01 +00005306 // Check against T3. If the second register is the PC, this is an
5307 // alternate form of ADR, which uses encoding T4, so check for that too.
David Blaikie960ea3f2014-06-08 16:18:35 +00005308 if (static_cast<ARMOperand &>(*Operands[4]).getReg() != ARM::PC &&
5309 static_cast<ARMOperand &>(*Operands[5]).isT2SOImm())
Tilmann Schelleref5666f2013-07-03 20:38:01 +00005310 return false;
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005311
5312 // Otherwise, we use encoding T4, which does not have a cc_out
5313 // operand.
5314 return true;
5315 }
5316
Jim Grosbach9c8b9932011-09-14 21:00:40 +00005317 // The thumb2 multiply instruction doesn't have a CCOut register, so
5318 // if we have a "mul" mnemonic in Thumb mode, check if we'll be able to
5319 // use the 16-bit encoding or not.
5320 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 6 &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005321 static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 &&
5322 static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5323 static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5324 static_cast<ARMOperand &>(*Operands[5]).isReg() &&
Jim Grosbach9c8b9932011-09-14 21:00:40 +00005325 // If the registers aren't low regs, the destination reg isn't the
5326 // same as one of the source regs, or the cc_out operand is zero
5327 // outside of an IT block, we have to use the 32-bit encoding, so
5328 // remove the cc_out operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005329 (!isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg()) ||
5330 !isARMLowRegister(static_cast<ARMOperand &>(*Operands[4]).getReg()) ||
5331 !isARMLowRegister(static_cast<ARMOperand &>(*Operands[5]).getReg()) ||
5332 !inITBlock() || (static_cast<ARMOperand &>(*Operands[3]).getReg() !=
5333 static_cast<ARMOperand &>(*Operands[5]).getReg() &&
5334 static_cast<ARMOperand &>(*Operands[3]).getReg() !=
5335 static_cast<ARMOperand &>(*Operands[4]).getReg())))
Jim Grosbach9c8b9932011-09-14 21:00:40 +00005336 return true;
5337
Jim Grosbachefa7e952011-11-15 19:55:16 +00005338 // Also check the 'mul' syntax variant that doesn't specify an explicit
5339 // destination register.
5340 if (isThumbTwo() && Mnemonic == "mul" && Operands.size() == 5 &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005341 static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 &&
5342 static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5343 static_cast<ARMOperand &>(*Operands[4]).isReg() &&
Jim Grosbachefa7e952011-11-15 19:55:16 +00005344 // If the registers aren't low regs or the cc_out operand is zero
5345 // outside of an IT block, we have to use the 32-bit encoding, so
5346 // remove the cc_out operand.
David Blaikie960ea3f2014-06-08 16:18:35 +00005347 (!isARMLowRegister(static_cast<ARMOperand &>(*Operands[3]).getReg()) ||
5348 !isARMLowRegister(static_cast<ARMOperand &>(*Operands[4]).getReg()) ||
Jim Grosbachefa7e952011-11-15 19:55:16 +00005349 !inITBlock()))
5350 return true;
5351
Jim Grosbach9c8b9932011-09-14 21:00:40 +00005352
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005353
Jim Grosbach4b701af2011-08-24 21:42:27 +00005354 // Register-register 'add/sub' for thumb does not have a cc_out operand
5355 // when it's an ADD/SUB SP, #imm. Be lenient on count since there's also
5356 // the "add/sub SP, SP, #imm" version. If the follow-up operands aren't
5357 // right, this will result in better diagnostics (which operand is off)
5358 // anyway.
5359 if (isThumb() && (Mnemonic == "add" || Mnemonic == "sub") &&
5360 (Operands.size() == 5 || Operands.size() == 6) &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005361 static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5362 static_cast<ARMOperand &>(*Operands[3]).getReg() == ARM::SP &&
5363 static_cast<ARMOperand &>(*Operands[1]).getReg() == 0 &&
5364 (static_cast<ARMOperand &>(*Operands[4]).isImm() ||
Jim Grosbachdf5a2442012-04-10 17:31:55 +00005365 (Operands.size() == 6 &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005366 static_cast<ARMOperand &>(*Operands[5]).isImm())))
Jim Grosbach0a0b3072011-08-24 21:22:15 +00005367 return true;
Jim Grosbach58ffdcc2011-08-16 21:34:08 +00005368
Jim Grosbach7283da92011-08-16 21:12:37 +00005369 return false;
5370}
5371
David Blaikie960ea3f2014-06-08 16:18:35 +00005372bool ARMAsmParser::shouldOmitPredicateOperand(StringRef Mnemonic,
5373 OperandVector &Operands) {
Joey Goulye8602552013-07-19 16:34:16 +00005374 // VRINT{Z, R, X} have a predicate operand in VFP, but not in NEON
5375 unsigned RegIdx = 3;
5376 if ((Mnemonic == "vrintz" || Mnemonic == "vrintx" || Mnemonic == "vrintr") &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005377 static_cast<ARMOperand &>(*Operands[2]).getToken() == ".f32") {
5378 if (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
5379 static_cast<ARMOperand &>(*Operands[3]).getToken() == ".f32")
Joey Goulye8602552013-07-19 16:34:16 +00005380 RegIdx = 4;
5381
David Blaikie960ea3f2014-06-08 16:18:35 +00005382 if (static_cast<ARMOperand &>(*Operands[RegIdx]).isReg() &&
5383 (ARMMCRegisterClasses[ARM::DPRRegClassID].contains(
5384 static_cast<ARMOperand &>(*Operands[RegIdx]).getReg()) ||
5385 ARMMCRegisterClasses[ARM::QPRRegClassID].contains(
5386 static_cast<ARMOperand &>(*Operands[RegIdx]).getReg())))
Joey Goulye8602552013-07-19 16:34:16 +00005387 return true;
5388 }
Joey Goulyf520d5e2013-07-19 16:45:16 +00005389 return false;
Joey Goulye8602552013-07-19 16:34:16 +00005390}
5391
Jim Grosbach12952fe2011-11-11 23:08:10 +00005392static bool isDataTypeToken(StringRef Tok) {
5393 return Tok == ".8" || Tok == ".16" || Tok == ".32" || Tok == ".64" ||
5394 Tok == ".i8" || Tok == ".i16" || Tok == ".i32" || Tok == ".i64" ||
5395 Tok == ".u8" || Tok == ".u16" || Tok == ".u32" || Tok == ".u64" ||
5396 Tok == ".s8" || Tok == ".s16" || Tok == ".s32" || Tok == ".s64" ||
5397 Tok == ".p8" || Tok == ".p16" || Tok == ".f32" || Tok == ".f64" ||
5398 Tok == ".f" || Tok == ".d";
5399}
5400
5401// FIXME: This bit should probably be handled via an explicit match class
5402// in the .td files that matches the suffix instead of having it be
5403// a literal string token the way it is now.
5404static bool doesIgnoreDataTypeSuffix(StringRef Mnemonic, StringRef DT) {
5405 return Mnemonic.startswith("vldm") || Mnemonic.startswith("vstm");
5406}
Tim Northover26bb14e2014-08-18 11:49:42 +00005407static void applyMnemonicAliases(StringRef &Mnemonic, uint64_t Features,
Chad Rosier9f7a2212013-04-18 22:35:36 +00005408 unsigned VariantID);
Saleem Abdulrasoole3a9dc12013-12-30 18:38:01 +00005409
5410static bool RequiresVFPRegListValidation(StringRef Inst,
5411 bool &AcceptSinglePrecisionOnly,
5412 bool &AcceptDoublePrecisionOnly) {
5413 if (Inst.size() < 7)
5414 return false;
5415
5416 if (Inst.startswith("fldm") || Inst.startswith("fstm")) {
5417 StringRef AddressingMode = Inst.substr(4, 2);
5418 if (AddressingMode == "ia" || AddressingMode == "db" ||
5419 AddressingMode == "ea" || AddressingMode == "fd") {
5420 AcceptSinglePrecisionOnly = Inst[6] == 's';
5421 AcceptDoublePrecisionOnly = Inst[6] == 'd' || Inst[6] == 'x';
5422 return true;
5423 }
5424 }
5425
5426 return false;
5427}
5428
Daniel Dunbar876bb0182011-01-10 12:24:52 +00005429/// Parse an arm instruction mnemonic followed by its operands.
Chad Rosierf0e87202012-10-25 20:41:34 +00005430bool ARMAsmParser::ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
David Blaikie960ea3f2014-06-08 16:18:35 +00005431 SMLoc NameLoc, OperandVector &Operands) {
Saleem Abdulrasool4da9c6e2013-12-29 17:58:35 +00005432 // FIXME: Can this be done via tablegen in some fashion?
Saleem Abdulrasoole3a9dc12013-12-30 18:38:01 +00005433 bool RequireVFPRegisterListCheck;
Saleem Abdulrasool4da9c6e2013-12-29 17:58:35 +00005434 bool AcceptSinglePrecisionOnly;
Saleem Abdulrasoole3a9dc12013-12-30 18:38:01 +00005435 bool AcceptDoublePrecisionOnly;
5436 RequireVFPRegisterListCheck =
5437 RequiresVFPRegListValidation(Name, AcceptSinglePrecisionOnly,
5438 AcceptDoublePrecisionOnly);
Saleem Abdulrasool4da9c6e2013-12-29 17:58:35 +00005439
Jim Grosbach8be2f652011-12-09 23:34:09 +00005440 // Apply mnemonic aliases before doing anything else, as the destination
Saleem Abdulrasoola1937cb2013-12-29 17:58:31 +00005441 // mnemonic may include suffices and we want to handle them normally.
Jim Grosbach8be2f652011-12-09 23:34:09 +00005442 // The generic tblgen'erated code does this later, at the start of
5443 // MatchInstructionImpl(), but that's too late for aliases that include
5444 // any sort of suffix.
Tim Northover26bb14e2014-08-18 11:49:42 +00005445 uint64_t AvailableFeatures = getAvailableFeatures();
Chad Rosier9f7a2212013-04-18 22:35:36 +00005446 unsigned AssemblerDialect = getParser().getAssemblerDialect();
5447 applyMnemonicAliases(Name, AvailableFeatures, AssemblerDialect);
Jim Grosbach8be2f652011-12-09 23:34:09 +00005448
Jim Grosbachab5830e2011-12-14 02:16:11 +00005449 // First check for the ARM-specific .req directive.
5450 if (Parser.getTok().is(AsmToken::Identifier) &&
5451 Parser.getTok().getIdentifier() == ".req") {
5452 parseDirectiveReq(Name, NameLoc);
5453 // We always return 'error' for this, as we're done with this
5454 // statement and don't need to match the 'instruction."
5455 return true;
5456 }
5457
Daniel Dunbar876bb0182011-01-10 12:24:52 +00005458 // Create the leading tokens for the mnemonic, split by '.' characters.
5459 size_t Start = 0, Next = Name.find('.');
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005460 StringRef Mnemonic = Name.slice(Start, Next);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00005461
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005462 // Split out the predication code and carry setting flag from the mnemonic.
5463 unsigned PredicationCode;
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00005464 unsigned ProcessorIMod;
Daniel Dunbar9d944b32011-01-11 15:59:50 +00005465 bool CarrySetting;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005466 StringRef ITMask;
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005467 Mnemonic = splitMnemonic(Mnemonic, PredicationCode, CarrySetting,
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005468 ProcessorIMod, ITMask);
Daniel Dunbar876bb0182011-01-10 12:24:52 +00005469
Jim Grosbach1c171b12011-08-25 17:23:55 +00005470 // In Thumb1, only the branch (B) instruction can be predicated.
5471 if (isThumbOne() && PredicationCode != ARMCC::AL && Mnemonic != "b") {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005472 Parser.eatToEndOfStatement();
Jim Grosbach1c171b12011-08-25 17:23:55 +00005473 return Error(NameLoc, "conditional execution not supported in Thumb1");
5474 }
5475
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005476 Operands.push_back(ARMOperand::CreateToken(Mnemonic, NameLoc));
5477
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005478 // Handle the IT instruction ITMask. Convert it to a bitmask. This
5479 // is the mask as it will be for the IT encoding if the conditional
5480 // encoding has a '1' as it's bit0 (i.e. 't' ==> '1'). In the case
5481 // where the conditional bit0 is zero, the instruction post-processing
5482 // will adjust the mask accordingly.
5483 if (Mnemonic == "it") {
Jim Grosbached16ec42011-08-29 22:24:09 +00005484 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + 2);
5485 if (ITMask.size() > 3) {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005486 Parser.eatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00005487 return Error(Loc, "too many conditions on IT instruction");
5488 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005489 unsigned Mask = 8;
5490 for (unsigned i = ITMask.size(); i != 0; --i) {
5491 char pos = ITMask[i - 1];
5492 if (pos != 't' && pos != 'e') {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005493 Parser.eatToEndOfStatement();
Jim Grosbached16ec42011-08-29 22:24:09 +00005494 return Error(Loc, "illegal IT block condition mask '" + ITMask + "'");
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005495 }
5496 Mask >>= 1;
5497 if (ITMask[i - 1] == 't')
5498 Mask |= 8;
5499 }
Jim Grosbached16ec42011-08-29 22:24:09 +00005500 Operands.push_back(ARMOperand::CreateITMask(Mask, Loc));
Jim Grosbach3d1eac82011-08-26 21:43:41 +00005501 }
5502
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005503 // FIXME: This is all a pretty gross hack. We should automatically handle
5504 // optional operands like this via tblgen.
Bill Wendling219dabd2010-11-21 10:56:05 +00005505
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005506 // Next, add the CCOut and ConditionCode operands, if needed.
5507 //
5508 // For mnemonics which can ever incorporate a carry setting bit or predication
5509 // code, our matching model involves us always generating CCOut and
5510 // ConditionCode operands to match the mnemonic "as written" and then we let
5511 // the matcher deal with finding the right instruction or generating an
5512 // appropriate error.
5513 bool CanAcceptCarrySet, CanAcceptPredicationCode;
Amara Emerson33089092013-09-19 11:59:01 +00005514 getMnemonicAcceptInfo(Mnemonic, Name, CanAcceptCarrySet, CanAcceptPredicationCode);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005515
Jim Grosbach03a8a162011-07-14 22:04:21 +00005516 // If we had a carry-set on an instruction that can't do that, issue an
5517 // error.
5518 if (!CanAcceptCarrySet && CarrySetting) {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005519 Parser.eatToEndOfStatement();
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005520 return Error(NameLoc, "instruction '" + Mnemonic +
Jim Grosbach03a8a162011-07-14 22:04:21 +00005521 "' can not set flags, but 's' suffix specified");
5522 }
Jim Grosbach0a547702011-07-22 17:44:50 +00005523 // If we had a predication code on an instruction that can't do that, issue an
5524 // error.
5525 if (!CanAcceptPredicationCode && PredicationCode != ARMCC::AL) {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005526 Parser.eatToEndOfStatement();
Jim Grosbach0a547702011-07-22 17:44:50 +00005527 return Error(NameLoc, "instruction '" + Mnemonic +
5528 "' is not predicable, but condition code specified");
5529 }
Jim Grosbach03a8a162011-07-14 22:04:21 +00005530
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005531 // Add the carry setting operand, if necessary.
Jim Grosbached16ec42011-08-29 22:24:09 +00005532 if (CanAcceptCarrySet) {
5533 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size());
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005534 Operands.push_back(ARMOperand::CreateCCOut(CarrySetting ? ARM::CPSR : 0,
Jim Grosbached16ec42011-08-29 22:24:09 +00005535 Loc));
5536 }
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005537
5538 // Add the predication code operand, if necessary.
5539 if (CanAcceptPredicationCode) {
Jim Grosbached16ec42011-08-29 22:24:09 +00005540 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Mnemonic.size() +
5541 CarrySetting);
Daniel Dunbar5a384c82011-01-11 15:59:53 +00005542 Operands.push_back(ARMOperand::CreateCondCode(
Jim Grosbached16ec42011-08-29 22:24:09 +00005543 ARMCC::CondCodes(PredicationCode), Loc));
Daniel Dunbar876bb0182011-01-10 12:24:52 +00005544 }
Daniel Dunbar188b47b2010-08-11 06:37:20 +00005545
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00005546 // Add the processor imod operand, if necessary.
5547 if (ProcessorIMod) {
5548 Operands.push_back(ARMOperand::CreateImm(
5549 MCConstantExpr::Create(ProcessorIMod, getContext()),
5550 NameLoc, NameLoc));
Oliver Stannard1ae8b472014-09-24 14:20:01 +00005551 } else if (Mnemonic == "cps" && isMClass()) {
5552 return Error(NameLoc, "instruction 'cps' requires effect for M-class");
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00005553 }
5554
Daniel Dunbar188b47b2010-08-11 06:37:20 +00005555 // Add the remaining tokens in the mnemonic.
Daniel Dunbar75d26be2010-08-11 06:37:16 +00005556 while (Next != StringRef::npos) {
5557 Start = Next;
5558 Next = Name.find('.', Start + 1);
Bruno Cardoso Lopes90d1dfe2011-02-14 13:09:44 +00005559 StringRef ExtraToken = Name.slice(Start, Next);
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005560
Jim Grosbach12952fe2011-11-11 23:08:10 +00005561 // Some NEON instructions have an optional datatype suffix that is
5562 // completely ignored. Check for that.
5563 if (isDataTypeToken(ExtraToken) &&
5564 doesIgnoreDataTypeSuffix(Mnemonic, ExtraToken))
5565 continue;
5566
Kevin Enderbyc5d09352013-06-18 20:19:24 +00005567 // For for ARM mode generate an error if the .n qualifier is used.
5568 if (ExtraToken == ".n" && !isThumb()) {
5569 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
Saleem Abdulrasoolbdae4b82014-01-12 05:25:44 +00005570 Parser.eatToEndOfStatement();
Kevin Enderbyc5d09352013-06-18 20:19:24 +00005571 return Error(Loc, "instruction with .n (narrow) qualifier not allowed in "
5572 "arm mode");
5573 }
5574
5575 // The .n qualifier is always discarded as that is what the tables
5576 // and matcher expect. In ARM mode the .w qualifier has no effect,
5577 // so discard it to avoid errors that can be caused by the matcher.
5578 if (ExtraToken != ".n" && (isThumb() || ExtraToken != ".w")) {
Jim Grosbach39c6e1d2011-09-07 16:06:04 +00005579 SMLoc Loc = SMLoc::getFromPointer(NameLoc.getPointer() + Start);
5580 Operands.push_back(ARMOperand::CreateToken(ExtraToken, Loc));
5581 }
Daniel Dunbar75d26be2010-08-11 06:37:16 +00005582 }
5583
5584 // Read the remaining operands.
5585 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005586 // Read the first operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005587 if (parseOperand(Operands, Mnemonic)) {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005588 Parser.eatToEndOfStatement();
Chris Lattnera2a9d162010-09-11 16:18:25 +00005589 return true;
5590 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005591
5592 while (getLexer().is(AsmToken::Comma)) {
Sean Callanana83fd7d2010-01-19 20:27:46 +00005593 Parser.Lex(); // Eat the comma.
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005594
5595 // Parse and remember the operand.
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00005596 if (parseOperand(Operands, Mnemonic)) {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005597 Parser.eatToEndOfStatement();
Chris Lattnera2a9d162010-09-11 16:18:25 +00005598 return true;
5599 }
Kevin Enderbyfebe39b2009-10-06 22:26:42 +00005600 }
5601 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00005602
Chris Lattnera2a9d162010-09-11 16:18:25 +00005603 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachb8d9f512011-10-07 18:27:04 +00005604 SMLoc Loc = getLexer().getLoc();
Jim Grosbachd2037eb2013-02-20 22:21:35 +00005605 Parser.eatToEndOfStatement();
Jim Grosbachb8d9f512011-10-07 18:27:04 +00005606 return Error(Loc, "unexpected token in argument list");
Chris Lattnera2a9d162010-09-11 16:18:25 +00005607 }
Bill Wendlingee7f1f92010-11-06 21:42:12 +00005608
Chris Lattner91689c12010-09-08 05:10:46 +00005609 Parser.Lex(); // Consume the EndOfStatement
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005610
Saleem Abdulrasoole3a9dc12013-12-30 18:38:01 +00005611 if (RequireVFPRegisterListCheck) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005612 ARMOperand &Op = static_cast<ARMOperand &>(*Operands.back());
5613 if (AcceptSinglePrecisionOnly && !Op.isSPRRegList())
5614 return Error(Op.getStartLoc(),
Saleem Abdulrasoolaca443c2013-12-29 18:53:16 +00005615 "VFP/Neon single precision register expected");
David Blaikie960ea3f2014-06-08 16:18:35 +00005616 if (AcceptDoublePrecisionOnly && !Op.isDPRRegList())
5617 return Error(Op.getStartLoc(),
Saleem Abdulrasoolaca443c2013-12-29 18:53:16 +00005618 "VFP/Neon double precision register expected");
Saleem Abdulrasool4da9c6e2013-12-29 17:58:35 +00005619 }
5620
Jim Grosbach7283da92011-08-16 21:12:37 +00005621 // Some instructions, mostly Thumb, have forms for the same mnemonic that
5622 // do and don't have a cc_out optional-def operand. With some spot-checks
5623 // of the operand list, we can figure out which variant we're trying to
Jim Grosbach1d3c1372011-09-01 00:28:52 +00005624 // parse and adjust accordingly before actually matching. We shouldn't ever
5625 // try to remove a cc_out operand that was explicitly set on the the
5626 // mnemonic, of course (CarrySetting == true). Reason number #317 the
5627 // table driven matcher doesn't fit well with the ARM instruction set.
David Blaikie960ea3f2014-06-08 16:18:35 +00005628 if (!CarrySetting && shouldOmitCCOutOperand(Mnemonic, Operands))
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005629 Operands.erase(Operands.begin() + 1);
Jim Grosbach7c09e3c2011-07-19 19:13:28 +00005630
Joey Goulye8602552013-07-19 16:34:16 +00005631 // Some instructions have the same mnemonic, but don't always
5632 // have a predicate. Distinguish them here and delete the
5633 // predicate if needed.
David Blaikie960ea3f2014-06-08 16:18:35 +00005634 if (shouldOmitPredicateOperand(Mnemonic, Operands))
Joey Goulye8602552013-07-19 16:34:16 +00005635 Operands.erase(Operands.begin() + 1);
Joey Goulye8602552013-07-19 16:34:16 +00005636
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005637 // ARM mode 'blx' need special handling, as the register operand version
5638 // is predicable, but the label operand version is not. So, we can't rely
5639 // on the Mnemonic based checking to correctly figure out when to put
Jim Grosbach6e5778f2011-10-07 23:24:09 +00005640 // a k_CondCode operand in the list. If we're trying to match the label
5641 // version, remove the k_CondCode operand here.
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005642 if (!isThumb() && Mnemonic == "blx" && Operands.size() == 3 &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005643 static_cast<ARMOperand &>(*Operands[2]).isImm())
Jim Grosbacha03ab0e2011-07-28 21:57:55 +00005644 Operands.erase(Operands.begin() + 1);
Jim Grosbach8cffa282011-08-11 23:51:13 +00005645
Weiming Zhao8f56f882012-11-16 21:55:34 +00005646 // Adjust operands of ldrexd/strexd to MCK_GPRPair.
5647 // ldrexd/strexd require even/odd GPR pair. To enforce this constraint,
5648 // a single GPRPair reg operand is used in the .td file to replace the two
5649 // GPRs. However, when parsing from asm, the two GRPs cannot be automatically
5650 // expressed as a GPRPair, so we have to manually merge them.
5651 // FIXME: We would really like to be able to tablegen'erate this.
5652 if (!isThumb() && Operands.size() > 4 &&
Joey Goulye6d165c2013-08-27 17:38:16 +00005653 (Mnemonic == "ldrexd" || Mnemonic == "strexd" || Mnemonic == "ldaexd" ||
5654 Mnemonic == "stlexd")) {
5655 bool isLoad = (Mnemonic == "ldrexd" || Mnemonic == "ldaexd");
Weiming Zhao8f56f882012-11-16 21:55:34 +00005656 unsigned Idx = isLoad ? 2 : 3;
David Blaikie960ea3f2014-06-08 16:18:35 +00005657 ARMOperand &Op1 = static_cast<ARMOperand &>(*Operands[Idx]);
5658 ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[Idx + 1]);
Weiming Zhao8f56f882012-11-16 21:55:34 +00005659
5660 const MCRegisterClass& MRC = MRI->getRegClass(ARM::GPRRegClassID);
5661 // Adjust only if Op1 and Op2 are GPRs.
David Blaikie960ea3f2014-06-08 16:18:35 +00005662 if (Op1.isReg() && Op2.isReg() && MRC.contains(Op1.getReg()) &&
5663 MRC.contains(Op2.getReg())) {
5664 unsigned Reg1 = Op1.getReg();
5665 unsigned Reg2 = Op2.getReg();
Weiming Zhao8f56f882012-11-16 21:55:34 +00005666 unsigned Rt = MRI->getEncodingValue(Reg1);
5667 unsigned Rt2 = MRI->getEncodingValue(Reg2);
5668
5669 // Rt2 must be Rt + 1 and Rt must be even.
5670 if (Rt + 1 != Rt2 || (Rt & 1)) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005671 Error(Op2.getStartLoc(), isLoad
5672 ? "destination operands must be sequential"
5673 : "source operands must be sequential");
Weiming Zhao8f56f882012-11-16 21:55:34 +00005674 return true;
5675 }
5676 unsigned NewReg = MRI->getMatchingSuperReg(Reg1, ARM::gsub_0,
5677 &(MRI->getRegClass(ARM::GPRPairRegClassID)));
David Blaikie960ea3f2014-06-08 16:18:35 +00005678 Operands[Idx] =
5679 ARMOperand::CreateReg(NewReg, Op1.getStartLoc(), Op2.getEndLoc());
5680 Operands.erase(Operands.begin() + Idx + 1);
Weiming Zhao8f56f882012-11-16 21:55:34 +00005681 }
5682 }
5683
Renato Golin36c626e2014-09-26 16:14:29 +00005684 // If first 2 operands of a 3 operand instruction are the same
5685 // then transform to 2 operand version of the same instruction
5686 // e.g. 'adds r0, r0, #1' transforms to 'adds r0, #1'
5687 // FIXME: We would really like to be able to tablegen'erate this.
5688 if (isThumbOne() && Operands.size() == 6 &&
5689 (Mnemonic == "add" || Mnemonic == "sub" || Mnemonic == "and" ||
5690 Mnemonic == "eor" || Mnemonic == "lsl" || Mnemonic == "lsr" ||
5691 Mnemonic == "asr" || Mnemonic == "adc" || Mnemonic == "sbc" ||
5692 Mnemonic == "ror" || Mnemonic == "orr" || Mnemonic == "bic")) {
5693 ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
5694 ARMOperand &Op4 = static_cast<ARMOperand &>(*Operands[4]);
5695 ARMOperand &Op5 = static_cast<ARMOperand &>(*Operands[5]);
5696
5697 // If both registers are the same then remove one of them from
5698 // the operand list.
5699 if (Op3.isReg() && Op4.isReg() && Op3.getReg() == Op4.getReg()) {
5700 // If 3rd operand (variable Op5) is a register and the instruction is adds/sub
5701 // then do not transform as the backend already handles this instruction
5702 // correctly.
5703 if (!Op5.isReg() || !((Mnemonic == "add" && CarrySetting) || Mnemonic == "sub")) {
5704 Operands.erase(Operands.begin() + 3);
5705 if (Mnemonic == "add" && !CarrySetting) {
5706 // Special case for 'add' (not 'adds') instruction must
5707 // remove the CCOut operand as well.
5708 Operands.erase(Operands.begin() + 1);
5709 }
5710 }
5711 }
5712 }
5713
5714 // If instruction is 'add' and first two register operands
5715 // use SP register, then remove one of the SP registers from
5716 // the instruction.
5717 // FIXME: We would really like to be able to tablegen'erate this.
5718 if (isThumbOne() && Operands.size() == 5 && Mnemonic == "add" && !CarrySetting) {
5719 ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]);
5720 ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
5721 if (Op2.isReg() && Op3.isReg() && Op2.getReg() == ARM::SP && Op3.getReg() == ARM::SP) {
5722 Operands.erase(Operands.begin() + 2);
5723 }
5724 }
5725
Saleem Abdulrasoole6e6d712014-01-10 04:38:35 +00005726 // GNU Assembler extension (compatibility)
Stepan Dyatkovskiy3f1fa3d2014-04-04 10:17:56 +00005727 if ((Mnemonic == "ldrd" || Mnemonic == "strd")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005728 ARMOperand &Op2 = static_cast<ARMOperand &>(*Operands[2]);
5729 ARMOperand &Op3 = static_cast<ARMOperand &>(*Operands[3]);
5730 if (Op3.isMem()) {
5731 assert(Op2.isReg() && "expected register argument");
Stepan Dyatkovskiy6207a4d2014-04-03 11:29:15 +00005732
Stepan Dyatkovskiy3f1fa3d2014-04-04 10:17:56 +00005733 unsigned SuperReg = MRI->getMatchingSuperReg(
David Blaikie960ea3f2014-06-08 16:18:35 +00005734 Op2.getReg(), ARM::gsub_0, &MRI->getRegClass(ARM::GPRPairRegClassID));
Stepan Dyatkovskiy6207a4d2014-04-03 11:29:15 +00005735
Stepan Dyatkovskiy3f1fa3d2014-04-04 10:17:56 +00005736 assert(SuperReg && "expected register pair");
Stepan Dyatkovskiy6207a4d2014-04-03 11:29:15 +00005737
Stepan Dyatkovskiy3f1fa3d2014-04-04 10:17:56 +00005738 unsigned PairedReg = MRI->getSubReg(SuperReg, ARM::gsub_1);
Stepan Dyatkovskiy6207a4d2014-04-03 11:29:15 +00005739
David Blaikie960ea3f2014-06-08 16:18:35 +00005740 Operands.insert(
5741 Operands.begin() + 3,
5742 ARMOperand::CreateReg(PairedReg, Op2.getStartLoc(), Op2.getEndLoc()));
Stepan Dyatkovskiy3f1fa3d2014-04-04 10:17:56 +00005743 }
Saleem Abdulrasoole6e6d712014-01-10 04:38:35 +00005744 }
5745
Kevin Enderby78f95722013-07-31 21:05:30 +00005746 // FIXME: As said above, this is all a pretty gross hack. This instruction
5747 // does not fit with other "subs" and tblgen.
5748 // Adjust operands of B9.3.19 SUBS PC, LR, #imm (Thumb2) system instruction
5749 // so the Mnemonic is the original name "subs" and delete the predicate
5750 // operand so it will match the table entry.
5751 if (isThumbTwo() && Mnemonic == "sub" && Operands.size() == 6 &&
David Blaikie960ea3f2014-06-08 16:18:35 +00005752 static_cast<ARMOperand &>(*Operands[3]).isReg() &&
5753 static_cast<ARMOperand &>(*Operands[3]).getReg() == ARM::PC &&
5754 static_cast<ARMOperand &>(*Operands[4]).isReg() &&
5755 static_cast<ARMOperand &>(*Operands[4]).getReg() == ARM::LR &&
5756 static_cast<ARMOperand &>(*Operands[5]).isImm()) {
5757 Operands.front() = ARMOperand::CreateToken(Name, NameLoc);
Kevin Enderby78f95722013-07-31 21:05:30 +00005758 Operands.erase(Operands.begin() + 1);
Kevin Enderby78f95722013-07-31 21:05:30 +00005759 }
Chris Lattnerf29c0b62010-01-14 22:21:20 +00005760 return false;
Kevin Enderbyccab3172009-09-15 00:27:25 +00005761}
5762
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005763// Validate context-sensitive operand constraints.
Jim Grosbach169b2be2011-08-23 18:13:04 +00005764
5765// return 'true' if register list contains non-low GPR registers,
5766// 'false' otherwise. If Reg is in the register list or is HiReg, set
5767// 'containsReg' to true.
5768static bool checkLowRegisterList(MCInst Inst, unsigned OpNo, unsigned Reg,
5769 unsigned HiReg, bool &containsReg) {
5770 containsReg = false;
5771 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5772 unsigned OpReg = Inst.getOperand(i).getReg();
5773 if (OpReg == Reg)
5774 containsReg = true;
5775 // Anything other than a low register isn't legal here.
5776 if (!isARMLowRegister(OpReg) && (!HiReg || OpReg != HiReg))
5777 return true;
5778 }
5779 return false;
5780}
5781
Jim Grosbacha31f2232011-09-07 18:05:34 +00005782// Check if the specified regisgter is in the register list of the inst,
5783// starting at the indicated operand number.
5784static bool listContainsReg(MCInst &Inst, unsigned OpNo, unsigned Reg) {
5785 for (unsigned i = OpNo; i < Inst.getNumOperands(); ++i) {
5786 unsigned OpReg = Inst.getOperand(i).getReg();
5787 if (OpReg == Reg)
5788 return true;
5789 }
5790 return false;
5791}
5792
Richard Barton8d519fe2013-09-05 14:14:19 +00005793// Return true if instruction has the interesting property of being
5794// allowed in IT blocks, but not being predicable.
5795static bool instIsBreakpoint(const MCInst &Inst) {
5796 return Inst.getOpcode() == ARM::tBKPT ||
5797 Inst.getOpcode() == ARM::BKPT ||
5798 Inst.getOpcode() == ARM::tHLT ||
5799 Inst.getOpcode() == ARM::HLT;
5800
5801}
5802
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005803// FIXME: We would really like to be able to tablegen'erate this.
David Blaikie960ea3f2014-06-08 16:18:35 +00005804bool ARMAsmParser::validateInstruction(MCInst &Inst,
5805 const OperandVector &Operands) {
Joey Gouly0e76fa72013-09-12 10:28:05 +00005806 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
Jim Grosbached16ec42011-08-29 22:24:09 +00005807 SMLoc Loc = Operands[0]->getStartLoc();
Mihai Popaad18d3c2013-08-09 10:38:32 +00005808
Jim Grosbached16ec42011-08-29 22:24:09 +00005809 // Check the IT block state first.
Richard Barton8d519fe2013-09-05 14:14:19 +00005810 // NOTE: BKPT and HLT instructions have the interesting property of being
Tilmann Schellerbe904772013-09-30 17:57:30 +00005811 // allowed in IT blocks, but not being predicable. They just always execute.
Richard Barton8d519fe2013-09-05 14:14:19 +00005812 if (inITBlock() && !instIsBreakpoint(Inst)) {
Tilmann Schellerbe904772013-09-30 17:57:30 +00005813 unsigned Bit = 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00005814 if (ITState.FirstCond)
5815 ITState.FirstCond = false;
5816 else
Tilmann Schellerbe904772013-09-30 17:57:30 +00005817 Bit = (ITState.Mask >> (5 - ITState.CurPosition)) & 1;
Jim Grosbached16ec42011-08-29 22:24:09 +00005818 // The instruction must be predicable.
5819 if (!MCID.isPredicable())
5820 return Error(Loc, "instructions in IT block must be predicable");
5821 unsigned Cond = Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm();
Tilmann Schellerbe904772013-09-30 17:57:30 +00005822 unsigned ITCond = Bit ? ITState.Cond :
Jim Grosbached16ec42011-08-29 22:24:09 +00005823 ARMCC::getOppositeCondition(ITState.Cond);
5824 if (Cond != ITCond) {
5825 // Find the condition code Operand to get its SMLoc information.
5826 SMLoc CondLoc;
Tilmann Schellerbe904772013-09-30 17:57:30 +00005827 for (unsigned I = 1; I < Operands.size(); ++I)
David Blaikie960ea3f2014-06-08 16:18:35 +00005828 if (static_cast<ARMOperand &>(*Operands[I]).isCondCode())
Tilmann Schellerbe904772013-09-30 17:57:30 +00005829 CondLoc = Operands[I]->getStartLoc();
Jim Grosbached16ec42011-08-29 22:24:09 +00005830 return Error(CondLoc, "incorrect condition in IT block; got '" +
5831 StringRef(ARMCondCodeToString(ARMCC::CondCodes(Cond))) +
5832 "', but expected '" +
5833 ARMCondCodeToString(ARMCC::CondCodes(ITCond)) + "'");
5834 }
Jim Grosbachc61fc8f2011-08-31 18:29:05 +00005835 // Check for non-'al' condition codes outside of the IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00005836 } else if (isThumbTwo() && MCID.isPredicable() &&
5837 Inst.getOperand(MCID.findFirstPredOperandIdx()).getImm() !=
Mihai Popaad18d3c2013-08-09 10:38:32 +00005838 ARMCC::AL && Inst.getOpcode() != ARM::tBcc &&
5839 Inst.getOpcode() != ARM::t2Bcc)
Jim Grosbached16ec42011-08-29 22:24:09 +00005840 return Error(Loc, "predicated instructions must be in IT block");
5841
Tilmann Scheller255722b2013-09-30 16:11:48 +00005842 const unsigned Opcode = Inst.getOpcode();
5843 switch (Opcode) {
Jim Grosbach5b96b802011-08-10 20:29:19 +00005844 case ARM::LDRD:
5845 case ARM::LDRD_PRE:
Weiming Zhao8f56f882012-11-16 21:55:34 +00005846 case ARM::LDRD_POST: {
Tilmann Scheller255722b2013-09-30 16:11:48 +00005847 const unsigned RtReg = Inst.getOperand(0).getReg();
5848
Tilmann Scheller1aebfa02013-09-27 13:28:17 +00005849 // Rt can't be R14.
5850 if (RtReg == ARM::LR)
5851 return Error(Operands[3]->getStartLoc(),
5852 "Rt can't be R14");
Tilmann Scheller255722b2013-09-30 16:11:48 +00005853
5854 const unsigned Rt = MRI->getEncodingValue(RtReg);
Tilmann Scheller1aebfa02013-09-27 13:28:17 +00005855 // Rt must be even-numbered.
5856 if ((Rt & 1) == 1)
5857 return Error(Operands[3]->getStartLoc(),
5858 "Rt must be even-numbered");
Tilmann Scheller255722b2013-09-30 16:11:48 +00005859
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005860 // Rt2 must be Rt + 1.
Tilmann Scheller255722b2013-09-30 16:11:48 +00005861 const unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005862 if (Rt2 != Rt + 1)
5863 return Error(Operands[3]->getStartLoc(),
5864 "destination operands must be sequential");
Tilmann Scheller255722b2013-09-30 16:11:48 +00005865
5866 if (Opcode == ARM::LDRD_PRE || Opcode == ARM::LDRD_POST) {
5867 const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(3).getReg());
5868 // For addressing modes with writeback, the base register needs to be
5869 // different from the destination registers.
5870 if (Rn == Rt || Rn == Rt2)
5871 return Error(Operands[3]->getStartLoc(),
5872 "base register needs to be different from destination "
5873 "registers");
5874 }
5875
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005876 return false;
5877 }
Tilmann Scheller88c8f162013-09-27 10:30:18 +00005878 case ARM::t2LDRDi8:
5879 case ARM::t2LDRD_PRE:
5880 case ARM::t2LDRD_POST: {
Tilmann Scheller041f7172013-09-27 10:38:11 +00005881 // Rt2 must be different from Rt.
Tilmann Scheller88c8f162013-09-27 10:30:18 +00005882 unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
5883 unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
5884 if (Rt2 == Rt)
5885 return Error(Operands[3]->getStartLoc(),
5886 "destination operands can't be identical");
5887 return false;
5888 }
Jim Grosbacheb09f492011-08-11 20:28:23 +00005889 case ARM::STRD: {
5890 // Rt2 must be Rt + 1.
Eric Christopher6ac277c2012-08-09 22:10:21 +00005891 unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
5892 unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(1).getReg());
Jim Grosbacheb09f492011-08-11 20:28:23 +00005893 if (Rt2 != Rt + 1)
5894 return Error(Operands[3]->getStartLoc(),
5895 "source operands must be sequential");
5896 return false;
5897 }
Jim Grosbachf7164b22011-08-10 20:49:18 +00005898 case ARM::STRD_PRE:
Weiming Zhao8f56f882012-11-16 21:55:34 +00005899 case ARM::STRD_POST: {
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005900 // Rt2 must be Rt + 1.
Eric Christopher6ac277c2012-08-09 22:10:21 +00005901 unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg());
5902 unsigned Rt2 = MRI->getEncodingValue(Inst.getOperand(2).getReg());
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005903 if (Rt2 != Rt + 1)
Jim Grosbacheb09f492011-08-11 20:28:23 +00005904 return Error(Operands[3]->getStartLoc(),
Jim Grosbachedaa35a2011-07-26 18:25:39 +00005905 "source operands must be sequential");
5906 return false;
5907 }
Tilmann Scheller3352a582014-07-23 12:38:17 +00005908 case ARM::STR_PRE_IMM:
5909 case ARM::STR_PRE_REG:
5910 case ARM::STR_POST_IMM:
Tilmann Scheller27272792014-07-23 13:03:47 +00005911 case ARM::STR_POST_REG:
Tilmann Scheller96ef72e2014-07-24 09:55:46 +00005912 case ARM::STRH_PRE:
5913 case ARM::STRH_POST:
Tilmann Scheller27272792014-07-23 13:03:47 +00005914 case ARM::STRB_PRE_IMM:
5915 case ARM::STRB_PRE_REG:
5916 case ARM::STRB_POST_IMM:
5917 case ARM::STRB_POST_REG: {
Tilmann Scheller3352a582014-07-23 12:38:17 +00005918 // Rt must be different from Rn.
5919 const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(1).getReg());
5920 const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg());
5921
5922 if (Rt == Rn)
5923 return Error(Operands[3]->getStartLoc(),
5924 "source register and base register can't be identical");
5925 return false;
5926 }
Tilmann Scheller8ba74302014-08-01 11:08:51 +00005927 case ARM::LDR_PRE_IMM:
5928 case ARM::LDR_PRE_REG:
5929 case ARM::LDR_POST_IMM:
Tilmann Scheller8ff079c2014-08-01 11:33:47 +00005930 case ARM::LDR_POST_REG:
5931 case ARM::LDRH_PRE:
5932 case ARM::LDRH_POST:
5933 case ARM::LDRSH_PRE:
Tilmann Scheller7cc0ed42014-08-01 12:08:04 +00005934 case ARM::LDRSH_POST:
5935 case ARM::LDRB_PRE_IMM:
5936 case ARM::LDRB_PRE_REG:
5937 case ARM::LDRB_POST_IMM:
5938 case ARM::LDRB_POST_REG:
5939 case ARM::LDRSB_PRE:
5940 case ARM::LDRSB_POST: {
Tilmann Scheller8ba74302014-08-01 11:08:51 +00005941 // Rt must be different from Rn.
5942 const unsigned Rt = MRI->getEncodingValue(Inst.getOperand(0).getReg());
5943 const unsigned Rn = MRI->getEncodingValue(Inst.getOperand(2).getReg());
5944
5945 if (Rt == Rn)
5946 return Error(Operands[3]->getStartLoc(),
5947 "destination register and base register can't be identical");
5948 return false;
5949 }
Jim Grosbach03f56d92011-07-27 21:09:25 +00005950 case ARM::SBFX:
5951 case ARM::UBFX: {
Tilmann Schellerbe904772013-09-30 17:57:30 +00005952 // Width must be in range [1, 32-lsb].
5953 unsigned LSB = Inst.getOperand(2).getImm();
5954 unsigned Widthm1 = Inst.getOperand(3).getImm();
5955 if (Widthm1 >= 32 - LSB)
Jim Grosbach03f56d92011-07-27 21:09:25 +00005956 return Error(Operands[5]->getStartLoc(),
5957 "bitfield width must be in range [1,32-lsb]");
Jim Grosbach64610e52011-08-16 21:42:31 +00005958 return false;
Jim Grosbach03f56d92011-07-27 21:09:25 +00005959 }
Tim Northover08a86602013-10-22 19:00:39 +00005960 // Notionally handles ARM::tLDMIA_UPD too.
Jim Grosbach90103cc2011-08-18 21:50:53 +00005961 case ARM::tLDMIA: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00005962 // If we're parsing Thumb2, the .w variant is available and handles
Tilmann Schellerbe904772013-09-30 17:57:30 +00005963 // most cases that are normally illegal for a Thumb1 LDM instruction.
5964 // We'll make the transformation in processInstruction() if necessary.
Jim Grosbacha31f2232011-09-07 18:05:34 +00005965 //
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00005966 // Thumb LDM instructions are writeback iff the base register is not
Jim Grosbach90103cc2011-08-18 21:50:53 +00005967 // in the register list.
5968 unsigned Rn = Inst.getOperand(0).getReg();
Tilmann Schellerbe904772013-09-30 17:57:30 +00005969 bool HasWritebackToken =
David Blaikie960ea3f2014-06-08 16:18:35 +00005970 (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
5971 static_cast<ARMOperand &>(*Operands[3]).getToken() == "!");
Tilmann Schellerbe904772013-09-30 17:57:30 +00005972 bool ListContainsBase;
5973 if (checkLowRegisterList(Inst, 3, Rn, 0, ListContainsBase) && !isThumbTwo())
5974 return Error(Operands[3 + HasWritebackToken]->getStartLoc(),
Jim Grosbach169b2be2011-08-23 18:13:04 +00005975 "registers must be in range r0-r7");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005976 // If we should have writeback, then there should be a '!' token.
Tilmann Schellerbe904772013-09-30 17:57:30 +00005977 if (!ListContainsBase && !HasWritebackToken && !isThumbTwo())
Jim Grosbach90103cc2011-08-18 21:50:53 +00005978 return Error(Operands[2]->getStartLoc(),
5979 "writeback operator '!' expected");
Jim Grosbacha31f2232011-09-07 18:05:34 +00005980 // If we should not have writeback, there must not be a '!'. This is
5981 // true even for the 32-bit wide encodings.
Tilmann Schellerbe904772013-09-30 17:57:30 +00005982 if (ListContainsBase && HasWritebackToken)
Jim Grosbach139acd22011-08-22 23:01:07 +00005983 return Error(Operands[3]->getStartLoc(),
5984 "writeback operator '!' not allowed when base register "
5985 "in register list");
Jyoti Allur3b686072014-10-22 10:41:14 +00005986 if (listContainsReg(Inst, 3 + HasWritebackToken, ARM::SP))
5987 return Error(Operands[3 + HasWritebackToken]->getStartLoc(),
5988 "SP not allowed in register list");
Jim Grosbach90103cc2011-08-18 21:50:53 +00005989 break;
5990 }
Tim Northover08a86602013-10-22 19:00:39 +00005991 case ARM::LDMIA_UPD:
5992 case ARM::LDMDB_UPD:
5993 case ARM::LDMIB_UPD:
5994 case ARM::LDMDA_UPD:
5995 // ARM variants loading and updating the same register are only officially
5996 // UNPREDICTABLE on v7 upwards. Goodness knows what they did before.
5997 if (!hasV7Ops())
5998 break;
Jyoti Allur3b686072014-10-22 10:41:14 +00005999 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
6000 return Error(Operands.back()->getStartLoc(),
6001 "writeback register not allowed in register list");
6002 break;
6003 case ARM::t2LDMIA:
6004 case ARM::t2LDMDB:
6005 case ARM::t2STMIA:
6006 case ARM::t2STMDB: {
6007 if (listContainsReg(Inst, 3, ARM::SP))
6008 return Error(Operands.back()->getStartLoc(),
6009 "SP not allowed in register list");
6010 break;
6011 }
Tim Northover08a86602013-10-22 19:00:39 +00006012 case ARM::t2LDMIA_UPD:
6013 case ARM::t2LDMDB_UPD:
6014 case ARM::t2STMIA_UPD:
6015 case ARM::t2STMDB_UPD: {
Jim Grosbacha31f2232011-09-07 18:05:34 +00006016 if (listContainsReg(Inst, 3, Inst.getOperand(0).getReg()))
Tim Northover741e6ef2013-10-24 09:37:18 +00006017 return Error(Operands.back()->getStartLoc(),
6018 "writeback register not allowed in register list");
Jyoti Allur3b686072014-10-22 10:41:14 +00006019
6020 if (listContainsReg(Inst, 4, ARM::SP))
6021 return Error(Operands.back()->getStartLoc(),
6022 "SP not allowed in register list");
Jim Grosbacha31f2232011-09-07 18:05:34 +00006023 break;
6024 }
Tim Northover8eaf1542013-11-12 21:32:41 +00006025 case ARM::sysLDMIA_UPD:
6026 case ARM::sysLDMDA_UPD:
6027 case ARM::sysLDMDB_UPD:
6028 case ARM::sysLDMIB_UPD:
6029 if (!listContainsReg(Inst, 3, ARM::PC))
6030 return Error(Operands[4]->getStartLoc(),
6031 "writeback register only allowed on system LDM "
6032 "if PC in register-list");
6033 break;
6034 case ARM::sysSTMIA_UPD:
6035 case ARM::sysSTMDA_UPD:
6036 case ARM::sysSTMDB_UPD:
6037 case ARM::sysSTMIB_UPD:
6038 return Error(Operands[2]->getStartLoc(),
6039 "system STM cannot have writeback register");
Chad Rosier8513ffb2012-08-30 23:20:38 +00006040 case ARM::tMUL: {
6041 // The second source operand must be the same register as the destination
6042 // operand.
Chad Rosier9d1fc362012-08-31 17:24:10 +00006043 //
6044 // In this case, we must directly check the parsed operands because the
6045 // cvtThumbMultiply() function is written in such a way that it guarantees
6046 // this first statement is always true for the new Inst. Essentially, the
6047 // destination is unconditionally copied into the second source operand
6048 // without checking to see if it matches what we actually parsed.
David Blaikie960ea3f2014-06-08 16:18:35 +00006049 if (Operands.size() == 6 && (((ARMOperand &)*Operands[3]).getReg() !=
6050 ((ARMOperand &)*Operands[5]).getReg()) &&
6051 (((ARMOperand &)*Operands[3]).getReg() !=
6052 ((ARMOperand &)*Operands[4]).getReg())) {
Chad Rosierdb482ef2012-08-30 23:22:05 +00006053 return Error(Operands[3]->getStartLoc(),
6054 "destination register must match source register");
Chad Rosier8513ffb2012-08-30 23:20:38 +00006055 }
6056 break;
6057 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006058 // Like for ldm/stm, push and pop have hi-reg handling version in Thumb2,
6059 // so only issue a diagnostic for thumb1. The instructions will be
6060 // switched to the t2 encodings in processInstruction() if necessary.
Jim Grosbach38c59fc2011-08-22 23:17:34 +00006061 case ARM::tPOP: {
Tilmann Schellerbe904772013-09-30 17:57:30 +00006062 bool ListContainsBase;
6063 if (checkLowRegisterList(Inst, 2, 0, ARM::PC, ListContainsBase) &&
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006064 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00006065 return Error(Operands[2]->getStartLoc(),
6066 "registers must be in range r0-r7 or pc");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00006067 break;
6068 }
6069 case ARM::tPUSH: {
Tilmann Schellerbe904772013-09-30 17:57:30 +00006070 bool ListContainsBase;
6071 if (checkLowRegisterList(Inst, 2, 0, ARM::LR, ListContainsBase) &&
Jim Grosbach9bded9d2011-11-10 23:17:11 +00006072 !isThumbTwo())
Jim Grosbach169b2be2011-08-23 18:13:04 +00006073 return Error(Operands[2]->getStartLoc(),
6074 "registers must be in range r0-r7 or lr");
Jim Grosbach38c59fc2011-08-22 23:17:34 +00006075 break;
6076 }
Jim Grosbachd80d1692011-08-23 18:15:37 +00006077 case ARM::tSTMIA_UPD: {
Tim Northover08a86602013-10-22 19:00:39 +00006078 bool ListContainsBase, InvalidLowList;
6079 InvalidLowList = checkLowRegisterList(Inst, 4, Inst.getOperand(0).getReg(),
6080 0, ListContainsBase);
6081 if (InvalidLowList && !isThumbTwo())
Jim Grosbachd80d1692011-08-23 18:15:37 +00006082 return Error(Operands[4]->getStartLoc(),
6083 "registers must be in range r0-r7");
Tim Northover08a86602013-10-22 19:00:39 +00006084
6085 // This would be converted to a 32-bit stm, but that's not valid if the
6086 // writeback register is in the list.
6087 if (InvalidLowList && ListContainsBase)
6088 return Error(Operands[4]->getStartLoc(),
6089 "writeback operator '!' not allowed when base register "
6090 "in register list");
Jyoti Allur3b686072014-10-22 10:41:14 +00006091 if (listContainsReg(Inst, 4, ARM::SP) && !inITBlock())
6092 return Error(Operands.back()->getStartLoc(),
6093 "SP not allowed in register list");
Jim Grosbachd80d1692011-08-23 18:15:37 +00006094 break;
6095 }
Jim Grosbachc6f32b32012-04-27 23:51:36 +00006096 case ARM::tADDrSP: {
6097 // If the non-SP source operand and the destination operand are not the
6098 // same, we need thumb2 (for the wide encoding), or we have an error.
6099 if (!isThumbTwo() &&
6100 Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
6101 return Error(Operands[4]->getStartLoc(),
6102 "source register must be the same as destination");
6103 }
6104 break;
6105 }
Tilmann Schellerbe904772013-09-30 17:57:30 +00006106 // Final range checking for Thumb unconditional branch instructions.
Mihai Popaad18d3c2013-08-09 10:38:32 +00006107 case ARM::tB:
David Blaikie960ea3f2014-06-08 16:18:35 +00006108 if (!(static_cast<ARMOperand &>(*Operands[2])).isSignedOffset<11, 1>())
Tilmann Schellerbe904772013-09-30 17:57:30 +00006109 return Error(Operands[2]->getStartLoc(), "branch target out of range");
Mihai Popaad18d3c2013-08-09 10:38:32 +00006110 break;
6111 case ARM::t2B: {
6112 int op = (Operands[2]->isImm()) ? 2 : 3;
David Blaikie960ea3f2014-06-08 16:18:35 +00006113 if (!static_cast<ARMOperand &>(*Operands[op]).isSignedOffset<24, 1>())
Tilmann Schellerbe904772013-09-30 17:57:30 +00006114 return Error(Operands[op]->getStartLoc(), "branch target out of range");
Mihai Popaad18d3c2013-08-09 10:38:32 +00006115 break;
6116 }
Tilmann Schellerbe904772013-09-30 17:57:30 +00006117 // Final range checking for Thumb conditional branch instructions.
Mihai Popaad18d3c2013-08-09 10:38:32 +00006118 case ARM::tBcc:
David Blaikie960ea3f2014-06-08 16:18:35 +00006119 if (!static_cast<ARMOperand &>(*Operands[2]).isSignedOffset<8, 1>())
Tilmann Schellerbe904772013-09-30 17:57:30 +00006120 return Error(Operands[2]->getStartLoc(), "branch target out of range");
Mihai Popaad18d3c2013-08-09 10:38:32 +00006121 break;
6122 case ARM::t2Bcc: {
Tilmann Schellerbe904772013-09-30 17:57:30 +00006123 int Op = (Operands[2]->isImm()) ? 2 : 3;
David Blaikie960ea3f2014-06-08 16:18:35 +00006124 if (!static_cast<ARMOperand &>(*Operands[Op]).isSignedOffset<20, 1>())
Tilmann Schellerbe904772013-09-30 17:57:30 +00006125 return Error(Operands[Op]->getStartLoc(), "branch target out of range");
Mihai Popaad18d3c2013-08-09 10:38:32 +00006126 break;
6127 }
Kevin Enderbyb7e51f62014-04-18 23:06:39 +00006128 case ARM::MOVi16:
6129 case ARM::t2MOVi16:
6130 case ARM::t2MOVTi16:
6131 {
6132 // We want to avoid misleadingly allowing something like "mov r0, <symbol>"
6133 // especially when we turn it into a movw and the expression <symbol> does
6134 // not have a :lower16: or :upper16 as part of the expression. We don't
6135 // want the behavior of silently truncating, which can be unexpected and
6136 // lead to bugs that are difficult to find since this is an easy mistake
6137 // to make.
6138 int i = (Operands[3]->isImm()) ? 3 : 4;
David Blaikie960ea3f2014-06-08 16:18:35 +00006139 ARMOperand &Op = static_cast<ARMOperand &>(*Operands[i]);
6140 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Kevin Enderbyb7e51f62014-04-18 23:06:39 +00006141 if (CE) break;
David Blaikie960ea3f2014-06-08 16:18:35 +00006142 const MCExpr *E = dyn_cast<MCExpr>(Op.getImm());
Kevin Enderbyb7e51f62014-04-18 23:06:39 +00006143 if (!E) break;
6144 const ARMMCExpr *ARM16Expr = dyn_cast<ARMMCExpr>(E);
6145 if (!ARM16Expr || (ARM16Expr->getKind() != ARMMCExpr::VK_ARM_HI16 &&
David Blaikie960ea3f2014-06-08 16:18:35 +00006146 ARM16Expr->getKind() != ARMMCExpr::VK_ARM_LO16))
6147 return Error(
6148 Op.getStartLoc(),
6149 "immediate expression for mov requires :lower16: or :upper16");
6150 break;
6151 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00006152 }
6153
6154 return false;
6155}
6156
Jim Grosbach1a747242012-01-23 23:45:44 +00006157static unsigned getRealVSTOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbacheb538222011-12-02 22:34:51 +00006158 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00006159 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006160 // VST1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00006161 case ARM::VST1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
6162 case ARM::VST1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
6163 case ARM::VST1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
6164 case ARM::VST1LNdWB_register_Asm_8: Spacing = 1; return ARM::VST1LNd8_UPD;
6165 case ARM::VST1LNdWB_register_Asm_16: Spacing = 1; return ARM::VST1LNd16_UPD;
6166 case ARM::VST1LNdWB_register_Asm_32: Spacing = 1; return ARM::VST1LNd32_UPD;
6167 case ARM::VST1LNdAsm_8: Spacing = 1; return ARM::VST1LNd8;
6168 case ARM::VST1LNdAsm_16: Spacing = 1; return ARM::VST1LNd16;
6169 case ARM::VST1LNdAsm_32: Spacing = 1; return ARM::VST1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006170
6171 // VST2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00006172 case ARM::VST2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
6173 case ARM::VST2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
6174 case ARM::VST2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
6175 case ARM::VST2LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
6176 case ARM::VST2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00006177
Jim Grosbach1e946a42012-01-24 00:43:12 +00006178 case ARM::VST2LNdWB_register_Asm_8: Spacing = 1; return ARM::VST2LNd8_UPD;
6179 case ARM::VST2LNdWB_register_Asm_16: Spacing = 1; return ARM::VST2LNd16_UPD;
6180 case ARM::VST2LNdWB_register_Asm_32: Spacing = 1; return ARM::VST2LNd32_UPD;
6181 case ARM::VST2LNqWB_register_Asm_16: Spacing = 2; return ARM::VST2LNq16_UPD;
6182 case ARM::VST2LNqWB_register_Asm_32: Spacing = 2; return ARM::VST2LNq32_UPD;
Jim Grosbach2c590522011-12-20 20:46:29 +00006183
Jim Grosbach1e946a42012-01-24 00:43:12 +00006184 case ARM::VST2LNdAsm_8: Spacing = 1; return ARM::VST2LNd8;
6185 case ARM::VST2LNdAsm_16: Spacing = 1; return ARM::VST2LNd16;
6186 case ARM::VST2LNdAsm_32: Spacing = 1; return ARM::VST2LNd32;
6187 case ARM::VST2LNqAsm_16: Spacing = 2; return ARM::VST2LNq16;
6188 case ARM::VST2LNqAsm_32: Spacing = 2; return ARM::VST2LNq32;
Jim Grosbach1a747242012-01-23 23:45:44 +00006189
Jim Grosbachd3d36d92012-01-24 00:07:41 +00006190 // VST3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00006191 case ARM::VST3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
6192 case ARM::VST3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
6193 case ARM::VST3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
6194 case ARM::VST3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST3LNq16_UPD;
6195 case ARM::VST3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
6196 case ARM::VST3LNdWB_register_Asm_8: Spacing = 1; return ARM::VST3LNd8_UPD;
6197 case ARM::VST3LNdWB_register_Asm_16: Spacing = 1; return ARM::VST3LNd16_UPD;
6198 case ARM::VST3LNdWB_register_Asm_32: Spacing = 1; return ARM::VST3LNd32_UPD;
6199 case ARM::VST3LNqWB_register_Asm_16: Spacing = 2; return ARM::VST3LNq16_UPD;
6200 case ARM::VST3LNqWB_register_Asm_32: Spacing = 2; return ARM::VST3LNq32_UPD;
6201 case ARM::VST3LNdAsm_8: Spacing = 1; return ARM::VST3LNd8;
6202 case ARM::VST3LNdAsm_16: Spacing = 1; return ARM::VST3LNd16;
6203 case ARM::VST3LNdAsm_32: Spacing = 1; return ARM::VST3LNd32;
6204 case ARM::VST3LNqAsm_16: Spacing = 2; return ARM::VST3LNq16;
6205 case ARM::VST3LNqAsm_32: Spacing = 2; return ARM::VST3LNq32;
Jim Grosbachd3d36d92012-01-24 00:07:41 +00006206
Jim Grosbach1a747242012-01-23 23:45:44 +00006207 // VST3
Jim Grosbach1e946a42012-01-24 00:43:12 +00006208 case ARM::VST3dWB_fixed_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
6209 case ARM::VST3dWB_fixed_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
6210 case ARM::VST3dWB_fixed_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
6211 case ARM::VST3qWB_fixed_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
6212 case ARM::VST3qWB_fixed_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
6213 case ARM::VST3qWB_fixed_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
6214 case ARM::VST3dWB_register_Asm_8: Spacing = 1; return ARM::VST3d8_UPD;
6215 case ARM::VST3dWB_register_Asm_16: Spacing = 1; return ARM::VST3d16_UPD;
6216 case ARM::VST3dWB_register_Asm_32: Spacing = 1; return ARM::VST3d32_UPD;
6217 case ARM::VST3qWB_register_Asm_8: Spacing = 2; return ARM::VST3q8_UPD;
6218 case ARM::VST3qWB_register_Asm_16: Spacing = 2; return ARM::VST3q16_UPD;
6219 case ARM::VST3qWB_register_Asm_32: Spacing = 2; return ARM::VST3q32_UPD;
6220 case ARM::VST3dAsm_8: Spacing = 1; return ARM::VST3d8;
6221 case ARM::VST3dAsm_16: Spacing = 1; return ARM::VST3d16;
6222 case ARM::VST3dAsm_32: Spacing = 1; return ARM::VST3d32;
6223 case ARM::VST3qAsm_8: Spacing = 2; return ARM::VST3q8;
6224 case ARM::VST3qAsm_16: Spacing = 2; return ARM::VST3q16;
6225 case ARM::VST3qAsm_32: Spacing = 2; return ARM::VST3q32;
Jim Grosbachda70eac2012-01-24 00:58:13 +00006226
Jim Grosbach8e2722c2012-01-24 18:53:13 +00006227 // VST4LN
6228 case ARM::VST4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
6229 case ARM::VST4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
6230 case ARM::VST4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
6231 case ARM::VST4LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VST4LNq16_UPD;
6232 case ARM::VST4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
6233 case ARM::VST4LNdWB_register_Asm_8: Spacing = 1; return ARM::VST4LNd8_UPD;
6234 case ARM::VST4LNdWB_register_Asm_16: Spacing = 1; return ARM::VST4LNd16_UPD;
6235 case ARM::VST4LNdWB_register_Asm_32: Spacing = 1; return ARM::VST4LNd32_UPD;
6236 case ARM::VST4LNqWB_register_Asm_16: Spacing = 2; return ARM::VST4LNq16_UPD;
6237 case ARM::VST4LNqWB_register_Asm_32: Spacing = 2; return ARM::VST4LNq32_UPD;
6238 case ARM::VST4LNdAsm_8: Spacing = 1; return ARM::VST4LNd8;
6239 case ARM::VST4LNdAsm_16: Spacing = 1; return ARM::VST4LNd16;
6240 case ARM::VST4LNdAsm_32: Spacing = 1; return ARM::VST4LNd32;
6241 case ARM::VST4LNqAsm_16: Spacing = 2; return ARM::VST4LNq16;
6242 case ARM::VST4LNqAsm_32: Spacing = 2; return ARM::VST4LNq32;
6243
Jim Grosbachda70eac2012-01-24 00:58:13 +00006244 // VST4
6245 case ARM::VST4dWB_fixed_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
6246 case ARM::VST4dWB_fixed_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
6247 case ARM::VST4dWB_fixed_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
6248 case ARM::VST4qWB_fixed_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
6249 case ARM::VST4qWB_fixed_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
6250 case ARM::VST4qWB_fixed_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
6251 case ARM::VST4dWB_register_Asm_8: Spacing = 1; return ARM::VST4d8_UPD;
6252 case ARM::VST4dWB_register_Asm_16: Spacing = 1; return ARM::VST4d16_UPD;
6253 case ARM::VST4dWB_register_Asm_32: Spacing = 1; return ARM::VST4d32_UPD;
6254 case ARM::VST4qWB_register_Asm_8: Spacing = 2; return ARM::VST4q8_UPD;
6255 case ARM::VST4qWB_register_Asm_16: Spacing = 2; return ARM::VST4q16_UPD;
6256 case ARM::VST4qWB_register_Asm_32: Spacing = 2; return ARM::VST4q32_UPD;
6257 case ARM::VST4dAsm_8: Spacing = 1; return ARM::VST4d8;
6258 case ARM::VST4dAsm_16: Spacing = 1; return ARM::VST4d16;
6259 case ARM::VST4dAsm_32: Spacing = 1; return ARM::VST4d32;
6260 case ARM::VST4qAsm_8: Spacing = 2; return ARM::VST4q8;
6261 case ARM::VST4qAsm_16: Spacing = 2; return ARM::VST4q16;
6262 case ARM::VST4qAsm_32: Spacing = 2; return ARM::VST4q32;
Jim Grosbacheb538222011-12-02 22:34:51 +00006263 }
6264}
6265
Jim Grosbach1a747242012-01-23 23:45:44 +00006266static unsigned getRealVLDOpcode(unsigned Opc, unsigned &Spacing) {
Jim Grosbach04945c42011-12-02 00:35:16 +00006267 switch(Opc) {
Craig Toppere55c5562012-02-07 02:50:20 +00006268 default: llvm_unreachable("unexpected opcode!");
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006269 // VLD1LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00006270 case ARM::VLD1LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
6271 case ARM::VLD1LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
6272 case ARM::VLD1LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
6273 case ARM::VLD1LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD1LNd8_UPD;
6274 case ARM::VLD1LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD1LNd16_UPD;
6275 case ARM::VLD1LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD1LNd32_UPD;
6276 case ARM::VLD1LNdAsm_8: Spacing = 1; return ARM::VLD1LNd8;
6277 case ARM::VLD1LNdAsm_16: Spacing = 1; return ARM::VLD1LNd16;
6278 case ARM::VLD1LNdAsm_32: Spacing = 1; return ARM::VLD1LNd32;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006279
6280 // VLD2LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00006281 case ARM::VLD2LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
6282 case ARM::VLD2LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
6283 case ARM::VLD2LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
6284 case ARM::VLD2LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD2LNq16_UPD;
6285 case ARM::VLD2LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
6286 case ARM::VLD2LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD2LNd8_UPD;
6287 case ARM::VLD2LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD2LNd16_UPD;
6288 case ARM::VLD2LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD2LNd32_UPD;
6289 case ARM::VLD2LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD2LNq16_UPD;
6290 case ARM::VLD2LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD2LNq32_UPD;
6291 case ARM::VLD2LNdAsm_8: Spacing = 1; return ARM::VLD2LNd8;
6292 case ARM::VLD2LNdAsm_16: Spacing = 1; return ARM::VLD2LNd16;
6293 case ARM::VLD2LNdAsm_32: Spacing = 1; return ARM::VLD2LNd32;
6294 case ARM::VLD2LNqAsm_16: Spacing = 2; return ARM::VLD2LNq16;
6295 case ARM::VLD2LNqAsm_32: Spacing = 2; return ARM::VLD2LNq32;
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006296
Jim Grosbachb78403c2012-01-24 23:47:04 +00006297 // VLD3DUP
6298 case ARM::VLD3DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
6299 case ARM::VLD3DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
6300 case ARM::VLD3DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
6301 case ARM::VLD3DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3DUPq8_UPD;
Kevin Enderbyd88fec32014-04-08 18:00:52 +00006302 case ARM::VLD3DUPqWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
Jim Grosbachb78403c2012-01-24 23:47:04 +00006303 case ARM::VLD3DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
6304 case ARM::VLD3DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD3DUPd8_UPD;
6305 case ARM::VLD3DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD3DUPd16_UPD;
6306 case ARM::VLD3DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD3DUPd32_UPD;
6307 case ARM::VLD3DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD3DUPq8_UPD;
6308 case ARM::VLD3DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD3DUPq16_UPD;
6309 case ARM::VLD3DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD3DUPq32_UPD;
6310 case ARM::VLD3DUPdAsm_8: Spacing = 1; return ARM::VLD3DUPd8;
6311 case ARM::VLD3DUPdAsm_16: Spacing = 1; return ARM::VLD3DUPd16;
6312 case ARM::VLD3DUPdAsm_32: Spacing = 1; return ARM::VLD3DUPd32;
6313 case ARM::VLD3DUPqAsm_8: Spacing = 2; return ARM::VLD3DUPq8;
6314 case ARM::VLD3DUPqAsm_16: Spacing = 2; return ARM::VLD3DUPq16;
6315 case ARM::VLD3DUPqAsm_32: Spacing = 2; return ARM::VLD3DUPq32;
6316
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006317 // VLD3LN
Jim Grosbach1e946a42012-01-24 00:43:12 +00006318 case ARM::VLD3LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
6319 case ARM::VLD3LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
6320 case ARM::VLD3LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
6321 case ARM::VLD3LNqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3LNq16_UPD;
6322 case ARM::VLD3LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
6323 case ARM::VLD3LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD3LNd8_UPD;
6324 case ARM::VLD3LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD3LNd16_UPD;
6325 case ARM::VLD3LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD3LNd32_UPD;
6326 case ARM::VLD3LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD3LNq16_UPD;
6327 case ARM::VLD3LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD3LNq32_UPD;
6328 case ARM::VLD3LNdAsm_8: Spacing = 1; return ARM::VLD3LNd8;
6329 case ARM::VLD3LNdAsm_16: Spacing = 1; return ARM::VLD3LNd16;
6330 case ARM::VLD3LNdAsm_32: Spacing = 1; return ARM::VLD3LNd32;
6331 case ARM::VLD3LNqAsm_16: Spacing = 2; return ARM::VLD3LNq16;
6332 case ARM::VLD3LNqAsm_32: Spacing = 2; return ARM::VLD3LNq32;
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006333
6334 // VLD3
Jim Grosbach1e946a42012-01-24 00:43:12 +00006335 case ARM::VLD3dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
6336 case ARM::VLD3dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
6337 case ARM::VLD3dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
6338 case ARM::VLD3qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
6339 case ARM::VLD3qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
6340 case ARM::VLD3qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
6341 case ARM::VLD3dWB_register_Asm_8: Spacing = 1; return ARM::VLD3d8_UPD;
6342 case ARM::VLD3dWB_register_Asm_16: Spacing = 1; return ARM::VLD3d16_UPD;
6343 case ARM::VLD3dWB_register_Asm_32: Spacing = 1; return ARM::VLD3d32_UPD;
6344 case ARM::VLD3qWB_register_Asm_8: Spacing = 2; return ARM::VLD3q8_UPD;
6345 case ARM::VLD3qWB_register_Asm_16: Spacing = 2; return ARM::VLD3q16_UPD;
6346 case ARM::VLD3qWB_register_Asm_32: Spacing = 2; return ARM::VLD3q32_UPD;
6347 case ARM::VLD3dAsm_8: Spacing = 1; return ARM::VLD3d8;
6348 case ARM::VLD3dAsm_16: Spacing = 1; return ARM::VLD3d16;
6349 case ARM::VLD3dAsm_32: Spacing = 1; return ARM::VLD3d32;
6350 case ARM::VLD3qAsm_8: Spacing = 2; return ARM::VLD3q8;
6351 case ARM::VLD3qAsm_16: Spacing = 2; return ARM::VLD3q16;
6352 case ARM::VLD3qAsm_32: Spacing = 2; return ARM::VLD3q32;
Jim Grosbached561fc2012-01-24 00:43:17 +00006353
Jim Grosbach14952a02012-01-24 18:37:25 +00006354 // VLD4LN
6355 case ARM::VLD4LNdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
6356 case ARM::VLD4LNdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
6357 case ARM::VLD4LNdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
Kevin Enderby8108f382014-03-26 19:35:40 +00006358 case ARM::VLD4LNqWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
Jim Grosbach14952a02012-01-24 18:37:25 +00006359 case ARM::VLD4LNqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
6360 case ARM::VLD4LNdWB_register_Asm_8: Spacing = 1; return ARM::VLD4LNd8_UPD;
6361 case ARM::VLD4LNdWB_register_Asm_16: Spacing = 1; return ARM::VLD4LNd16_UPD;
6362 case ARM::VLD4LNdWB_register_Asm_32: Spacing = 1; return ARM::VLD4LNd32_UPD;
6363 case ARM::VLD4LNqWB_register_Asm_16: Spacing = 2; return ARM::VLD4LNq16_UPD;
6364 case ARM::VLD4LNqWB_register_Asm_32: Spacing = 2; return ARM::VLD4LNq32_UPD;
6365 case ARM::VLD4LNdAsm_8: Spacing = 1; return ARM::VLD4LNd8;
6366 case ARM::VLD4LNdAsm_16: Spacing = 1; return ARM::VLD4LNd16;
6367 case ARM::VLD4LNdAsm_32: Spacing = 1; return ARM::VLD4LNd32;
6368 case ARM::VLD4LNqAsm_16: Spacing = 2; return ARM::VLD4LNq16;
6369 case ARM::VLD4LNqAsm_32: Spacing = 2; return ARM::VLD4LNq32;
6370
Jim Grosbach086cbfa2012-01-25 00:01:08 +00006371 // VLD4DUP
6372 case ARM::VLD4DUPdWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
6373 case ARM::VLD4DUPdWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
6374 case ARM::VLD4DUPdWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
6375 case ARM::VLD4DUPqWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4DUPq8_UPD;
6376 case ARM::VLD4DUPqWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4DUPq16_UPD;
6377 case ARM::VLD4DUPqWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
6378 case ARM::VLD4DUPdWB_register_Asm_8: Spacing = 1; return ARM::VLD4DUPd8_UPD;
6379 case ARM::VLD4DUPdWB_register_Asm_16: Spacing = 1; return ARM::VLD4DUPd16_UPD;
6380 case ARM::VLD4DUPdWB_register_Asm_32: Spacing = 1; return ARM::VLD4DUPd32_UPD;
6381 case ARM::VLD4DUPqWB_register_Asm_8: Spacing = 2; return ARM::VLD4DUPq8_UPD;
6382 case ARM::VLD4DUPqWB_register_Asm_16: Spacing = 2; return ARM::VLD4DUPq16_UPD;
6383 case ARM::VLD4DUPqWB_register_Asm_32: Spacing = 2; return ARM::VLD4DUPq32_UPD;
6384 case ARM::VLD4DUPdAsm_8: Spacing = 1; return ARM::VLD4DUPd8;
6385 case ARM::VLD4DUPdAsm_16: Spacing = 1; return ARM::VLD4DUPd16;
6386 case ARM::VLD4DUPdAsm_32: Spacing = 1; return ARM::VLD4DUPd32;
6387 case ARM::VLD4DUPqAsm_8: Spacing = 2; return ARM::VLD4DUPq8;
6388 case ARM::VLD4DUPqAsm_16: Spacing = 2; return ARM::VLD4DUPq16;
6389 case ARM::VLD4DUPqAsm_32: Spacing = 2; return ARM::VLD4DUPq32;
6390
Jim Grosbached561fc2012-01-24 00:43:17 +00006391 // VLD4
6392 case ARM::VLD4dWB_fixed_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
6393 case ARM::VLD4dWB_fixed_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
6394 case ARM::VLD4dWB_fixed_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
6395 case ARM::VLD4qWB_fixed_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
6396 case ARM::VLD4qWB_fixed_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
6397 case ARM::VLD4qWB_fixed_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
6398 case ARM::VLD4dWB_register_Asm_8: Spacing = 1; return ARM::VLD4d8_UPD;
6399 case ARM::VLD4dWB_register_Asm_16: Spacing = 1; return ARM::VLD4d16_UPD;
6400 case ARM::VLD4dWB_register_Asm_32: Spacing = 1; return ARM::VLD4d32_UPD;
6401 case ARM::VLD4qWB_register_Asm_8: Spacing = 2; return ARM::VLD4q8_UPD;
6402 case ARM::VLD4qWB_register_Asm_16: Spacing = 2; return ARM::VLD4q16_UPD;
6403 case ARM::VLD4qWB_register_Asm_32: Spacing = 2; return ARM::VLD4q32_UPD;
6404 case ARM::VLD4dAsm_8: Spacing = 1; return ARM::VLD4d8;
6405 case ARM::VLD4dAsm_16: Spacing = 1; return ARM::VLD4d16;
6406 case ARM::VLD4dAsm_32: Spacing = 1; return ARM::VLD4d32;
6407 case ARM::VLD4qAsm_8: Spacing = 2; return ARM::VLD4q8;
6408 case ARM::VLD4qAsm_16: Spacing = 2; return ARM::VLD4q16;
6409 case ARM::VLD4qAsm_32: Spacing = 2; return ARM::VLD4q32;
Jim Grosbach04945c42011-12-02 00:35:16 +00006410 }
6411}
6412
David Blaikie960ea3f2014-06-08 16:18:35 +00006413bool ARMAsmParser::processInstruction(MCInst &Inst,
6414 const OperandVector &Operands) {
Jim Grosbach8ba76c62011-08-11 17:35:48 +00006415 switch (Inst.getOpcode()) {
Saleem Abdulrasoolfb3950e2014-01-12 04:36:01 +00006416 // Alias for alternate form of 'ldr{,b}t Rt, [Rn], #imm' instruction.
6417 case ARM::LDRT_POST:
6418 case ARM::LDRBT_POST: {
6419 const unsigned Opcode =
6420 (Inst.getOpcode() == ARM::LDRT_POST) ? ARM::LDRT_POST_IMM
6421 : ARM::LDRBT_POST_IMM;
6422 MCInst TmpInst;
6423 TmpInst.setOpcode(Opcode);
6424 TmpInst.addOperand(Inst.getOperand(0));
6425 TmpInst.addOperand(Inst.getOperand(1));
6426 TmpInst.addOperand(Inst.getOperand(1));
6427 TmpInst.addOperand(MCOperand::CreateReg(0));
6428 TmpInst.addOperand(MCOperand::CreateImm(0));
6429 TmpInst.addOperand(Inst.getOperand(2));
6430 TmpInst.addOperand(Inst.getOperand(3));
6431 Inst = TmpInst;
6432 return true;
6433 }
6434 // Alias for alternate form of 'str{,b}t Rt, [Rn], #imm' instruction.
6435 case ARM::STRT_POST:
6436 case ARM::STRBT_POST: {
6437 const unsigned Opcode =
6438 (Inst.getOpcode() == ARM::STRT_POST) ? ARM::STRT_POST_IMM
6439 : ARM::STRBT_POST_IMM;
6440 MCInst TmpInst;
6441 TmpInst.setOpcode(Opcode);
6442 TmpInst.addOperand(Inst.getOperand(1));
6443 TmpInst.addOperand(Inst.getOperand(0));
6444 TmpInst.addOperand(Inst.getOperand(1));
6445 TmpInst.addOperand(MCOperand::CreateReg(0));
6446 TmpInst.addOperand(MCOperand::CreateImm(0));
6447 TmpInst.addOperand(Inst.getOperand(2));
6448 TmpInst.addOperand(Inst.getOperand(3));
6449 Inst = TmpInst;
6450 return true;
6451 }
Jim Grosbache974a6a2012-09-25 00:08:13 +00006452 // Alias for alternate form of 'ADR Rd, #imm' instruction.
6453 case ARM::ADDri: {
6454 if (Inst.getOperand(1).getReg() != ARM::PC ||
6455 Inst.getOperand(5).getReg() != 0)
6456 return false;
6457 MCInst TmpInst;
6458 TmpInst.setOpcode(ARM::ADR);
6459 TmpInst.addOperand(Inst.getOperand(0));
6460 TmpInst.addOperand(Inst.getOperand(2));
6461 TmpInst.addOperand(Inst.getOperand(3));
6462 TmpInst.addOperand(Inst.getOperand(4));
6463 Inst = TmpInst;
6464 return true;
6465 }
Jim Grosbach94298a92012-01-18 22:46:46 +00006466 // Aliases for alternate PC+imm syntax of LDR instructions.
6467 case ARM::t2LDRpcrel:
Kevin Enderby06aa3eb82012-12-14 23:04:25 +00006468 // Select the narrow version if the immediate will fit.
6469 if (Inst.getOperand(1).getImm() > 0 &&
Amaury de la Vieuvilleeac0bad2013-06-18 08:13:05 +00006470 Inst.getOperand(1).getImm() <= 0xff &&
David Blaikie960ea3f2014-06-08 16:18:35 +00006471 !(static_cast<ARMOperand &>(*Operands[2]).isToken() &&
6472 static_cast<ARMOperand &>(*Operands[2]).getToken() == ".w"))
Kevin Enderby06aa3eb82012-12-14 23:04:25 +00006473 Inst.setOpcode(ARM::tLDRpci);
6474 else
6475 Inst.setOpcode(ARM::t2LDRpci);
Jim Grosbach94298a92012-01-18 22:46:46 +00006476 return true;
6477 case ARM::t2LDRBpcrel:
6478 Inst.setOpcode(ARM::t2LDRBpci);
6479 return true;
6480 case ARM::t2LDRHpcrel:
6481 Inst.setOpcode(ARM::t2LDRHpci);
6482 return true;
6483 case ARM::t2LDRSBpcrel:
6484 Inst.setOpcode(ARM::t2LDRSBpci);
6485 return true;
6486 case ARM::t2LDRSHpcrel:
6487 Inst.setOpcode(ARM::t2LDRSHpci);
6488 return true;
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006489 // Handle NEON VST complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006490 case ARM::VST1LNdWB_register_Asm_8:
6491 case ARM::VST1LNdWB_register_Asm_16:
6492 case ARM::VST1LNdWB_register_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00006493 MCInst TmpInst;
6494 // Shuffle the operands around so the lane index operand is in the
6495 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00006496 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006497 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00006498 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6499 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6500 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6501 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6502 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6503 TmpInst.addOperand(Inst.getOperand(1)); // lane
6504 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6505 TmpInst.addOperand(Inst.getOperand(6));
6506 Inst = TmpInst;
6507 return true;
6508 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006509
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006510 case ARM::VST2LNdWB_register_Asm_8:
6511 case ARM::VST2LNdWB_register_Asm_16:
6512 case ARM::VST2LNdWB_register_Asm_32:
6513 case ARM::VST2LNqWB_register_Asm_16:
6514 case ARM::VST2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006515 MCInst TmpInst;
6516 // Shuffle the operands around so the lane index operand is in the
6517 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00006518 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006519 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006520 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6521 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6522 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6523 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6524 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00006525 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6526 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006527 TmpInst.addOperand(Inst.getOperand(1)); // lane
6528 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6529 TmpInst.addOperand(Inst.getOperand(6));
6530 Inst = TmpInst;
6531 return true;
6532 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00006533
6534 case ARM::VST3LNdWB_register_Asm_8:
6535 case ARM::VST3LNdWB_register_Asm_16:
6536 case ARM::VST3LNdWB_register_Asm_32:
6537 case ARM::VST3LNqWB_register_Asm_16:
6538 case ARM::VST3LNqWB_register_Asm_32: {
6539 MCInst TmpInst;
6540 // Shuffle the operands around so the lane index operand is in the
6541 // right place.
6542 unsigned Spacing;
6543 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6544 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6545 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6546 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6547 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6548 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6549 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6550 Spacing));
6551 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6552 Spacing * 2));
6553 TmpInst.addOperand(Inst.getOperand(1)); // lane
6554 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6555 TmpInst.addOperand(Inst.getOperand(6));
6556 Inst = TmpInst;
6557 return true;
6558 }
6559
Jim Grosbach8e2722c2012-01-24 18:53:13 +00006560 case ARM::VST4LNdWB_register_Asm_8:
6561 case ARM::VST4LNdWB_register_Asm_16:
6562 case ARM::VST4LNdWB_register_Asm_32:
6563 case ARM::VST4LNqWB_register_Asm_16:
6564 case ARM::VST4LNqWB_register_Asm_32: {
6565 MCInst TmpInst;
6566 // Shuffle the operands around so the lane index operand is in the
6567 // right place.
6568 unsigned Spacing;
6569 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6570 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6571 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6572 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6573 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6574 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6575 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6576 Spacing));
6577 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6578 Spacing * 2));
6579 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6580 Spacing * 3));
6581 TmpInst.addOperand(Inst.getOperand(1)); // lane
6582 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6583 TmpInst.addOperand(Inst.getOperand(6));
6584 Inst = TmpInst;
6585 return true;
6586 }
6587
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006588 case ARM::VST1LNdWB_fixed_Asm_8:
6589 case ARM::VST1LNdWB_fixed_Asm_16:
6590 case ARM::VST1LNdWB_fixed_Asm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00006591 MCInst TmpInst;
6592 // Shuffle the operands around so the lane index operand is in the
6593 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00006594 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006595 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00006596 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6597 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6598 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6599 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6600 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6601 TmpInst.addOperand(Inst.getOperand(1)); // lane
6602 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6603 TmpInst.addOperand(Inst.getOperand(5));
6604 Inst = TmpInst;
6605 return true;
6606 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006607
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006608 case ARM::VST2LNdWB_fixed_Asm_8:
6609 case ARM::VST2LNdWB_fixed_Asm_16:
6610 case ARM::VST2LNdWB_fixed_Asm_32:
6611 case ARM::VST2LNqWB_fixed_Asm_16:
6612 case ARM::VST2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006613 MCInst TmpInst;
6614 // Shuffle the operands around so the lane index operand is in the
6615 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00006616 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006617 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006618 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6619 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6620 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6621 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6622 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00006623 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6624 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006625 TmpInst.addOperand(Inst.getOperand(1)); // lane
6626 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6627 TmpInst.addOperand(Inst.getOperand(5));
6628 Inst = TmpInst;
6629 return true;
6630 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00006631
6632 case ARM::VST3LNdWB_fixed_Asm_8:
6633 case ARM::VST3LNdWB_fixed_Asm_16:
6634 case ARM::VST3LNdWB_fixed_Asm_32:
6635 case ARM::VST3LNqWB_fixed_Asm_16:
6636 case ARM::VST3LNqWB_fixed_Asm_32: {
6637 MCInst TmpInst;
6638 // Shuffle the operands around so the lane index operand is in the
6639 // right place.
6640 unsigned Spacing;
6641 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6642 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6643 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6644 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6645 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6646 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6647 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6648 Spacing));
6649 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6650 Spacing * 2));
6651 TmpInst.addOperand(Inst.getOperand(1)); // lane
6652 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6653 TmpInst.addOperand(Inst.getOperand(5));
6654 Inst = TmpInst;
6655 return true;
6656 }
6657
Jim Grosbach8e2722c2012-01-24 18:53:13 +00006658 case ARM::VST4LNdWB_fixed_Asm_8:
6659 case ARM::VST4LNdWB_fixed_Asm_16:
6660 case ARM::VST4LNdWB_fixed_Asm_32:
6661 case ARM::VST4LNqWB_fixed_Asm_16:
6662 case ARM::VST4LNqWB_fixed_Asm_32: {
6663 MCInst TmpInst;
6664 // Shuffle the operands around so the lane index operand is in the
6665 // right place.
6666 unsigned Spacing;
6667 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6668 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6669 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6670 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6671 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6672 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6673 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6674 Spacing));
6675 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6676 Spacing * 2));
6677 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6678 Spacing * 3));
6679 TmpInst.addOperand(Inst.getOperand(1)); // lane
6680 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6681 TmpInst.addOperand(Inst.getOperand(5));
6682 Inst = TmpInst;
6683 return true;
6684 }
6685
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006686 case ARM::VST1LNdAsm_8:
6687 case ARM::VST1LNdAsm_16:
6688 case ARM::VST1LNdAsm_32: {
Jim Grosbacheb538222011-12-02 22:34:51 +00006689 MCInst TmpInst;
6690 // Shuffle the operands around so the lane index operand is in the
6691 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00006692 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006693 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacheb538222011-12-02 22:34:51 +00006694 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6695 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6696 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6697 TmpInst.addOperand(Inst.getOperand(1)); // lane
6698 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6699 TmpInst.addOperand(Inst.getOperand(5));
6700 Inst = TmpInst;
6701 return true;
6702 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006703
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006704 case ARM::VST2LNdAsm_8:
6705 case ARM::VST2LNdAsm_16:
6706 case ARM::VST2LNdAsm_32:
6707 case ARM::VST2LNqAsm_16:
6708 case ARM::VST2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006709 MCInst TmpInst;
6710 // Shuffle the operands around so the lane index operand is in the
6711 // right place.
Jim Grosbach2c590522011-12-20 20:46:29 +00006712 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006713 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006714 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6715 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6716 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach2c590522011-12-20 20:46:29 +00006717 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6718 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006719 TmpInst.addOperand(Inst.getOperand(1)); // lane
6720 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6721 TmpInst.addOperand(Inst.getOperand(5));
6722 Inst = TmpInst;
6723 return true;
6724 }
Jim Grosbachd3d36d92012-01-24 00:07:41 +00006725
6726 case ARM::VST3LNdAsm_8:
6727 case ARM::VST3LNdAsm_16:
6728 case ARM::VST3LNdAsm_32:
6729 case ARM::VST3LNqAsm_16:
6730 case ARM::VST3LNqAsm_32: {
6731 MCInst TmpInst;
6732 // Shuffle the operands around so the lane index operand is in the
6733 // right place.
6734 unsigned Spacing;
6735 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6736 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6737 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6738 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6739 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6740 Spacing));
6741 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6742 Spacing * 2));
6743 TmpInst.addOperand(Inst.getOperand(1)); // lane
6744 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6745 TmpInst.addOperand(Inst.getOperand(5));
6746 Inst = TmpInst;
6747 return true;
6748 }
6749
Jim Grosbach8e2722c2012-01-24 18:53:13 +00006750 case ARM::VST4LNdAsm_8:
6751 case ARM::VST4LNdAsm_16:
6752 case ARM::VST4LNdAsm_32:
6753 case ARM::VST4LNqAsm_16:
6754 case ARM::VST4LNqAsm_32: {
6755 MCInst TmpInst;
6756 // Shuffle the operands around so the lane index operand is in the
6757 // right place.
6758 unsigned Spacing;
6759 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
6760 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6761 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6762 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6763 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6764 Spacing));
6765 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6766 Spacing * 2));
6767 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6768 Spacing * 3));
6769 TmpInst.addOperand(Inst.getOperand(1)); // lane
6770 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6771 TmpInst.addOperand(Inst.getOperand(5));
6772 Inst = TmpInst;
6773 return true;
6774 }
6775
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006776 // Handle NEON VLD complex aliases.
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006777 case ARM::VLD1LNdWB_register_Asm_8:
6778 case ARM::VLD1LNdWB_register_Asm_16:
6779 case ARM::VLD1LNdWB_register_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00006780 MCInst TmpInst;
6781 // Shuffle the operands around so the lane index operand is in the
6782 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006783 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006784 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00006785 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6786 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6787 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6788 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6789 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6790 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6791 TmpInst.addOperand(Inst.getOperand(1)); // lane
6792 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6793 TmpInst.addOperand(Inst.getOperand(6));
6794 Inst = TmpInst;
6795 return true;
6796 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006797
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006798 case ARM::VLD2LNdWB_register_Asm_8:
6799 case ARM::VLD2LNdWB_register_Asm_16:
6800 case ARM::VLD2LNdWB_register_Asm_32:
6801 case ARM::VLD2LNqWB_register_Asm_16:
6802 case ARM::VLD2LNqWB_register_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006803 MCInst TmpInst;
6804 // Shuffle the operands around so the lane index operand is in the
6805 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006806 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006807 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006808 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006809 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6810 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006811 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6812 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6813 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6814 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6815 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006816 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6817 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006818 TmpInst.addOperand(Inst.getOperand(1)); // lane
6819 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6820 TmpInst.addOperand(Inst.getOperand(6));
6821 Inst = TmpInst;
6822 return true;
6823 }
6824
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006825 case ARM::VLD3LNdWB_register_Asm_8:
6826 case ARM::VLD3LNdWB_register_Asm_16:
6827 case ARM::VLD3LNdWB_register_Asm_32:
6828 case ARM::VLD3LNqWB_register_Asm_16:
6829 case ARM::VLD3LNqWB_register_Asm_32: {
6830 MCInst TmpInst;
6831 // Shuffle the operands around so the lane index operand is in the
6832 // right place.
6833 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006834 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006835 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6836 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6837 Spacing));
6838 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006839 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006840 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6841 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6842 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6843 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6844 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6845 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6846 Spacing));
6847 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006848 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006849 TmpInst.addOperand(Inst.getOperand(1)); // lane
6850 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6851 TmpInst.addOperand(Inst.getOperand(6));
6852 Inst = TmpInst;
6853 return true;
6854 }
6855
Jim Grosbach14952a02012-01-24 18:37:25 +00006856 case ARM::VLD4LNdWB_register_Asm_8:
6857 case ARM::VLD4LNdWB_register_Asm_16:
6858 case ARM::VLD4LNdWB_register_Asm_32:
6859 case ARM::VLD4LNqWB_register_Asm_16:
6860 case ARM::VLD4LNqWB_register_Asm_32: {
6861 MCInst TmpInst;
6862 // Shuffle the operands around so the lane index operand is in the
6863 // right place.
6864 unsigned Spacing;
6865 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6866 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6867 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6868 Spacing));
6869 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6870 Spacing * 2));
6871 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6872 Spacing * 3));
6873 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6874 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6875 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6876 TmpInst.addOperand(Inst.getOperand(4)); // Rm
6877 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6878 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6879 Spacing));
6880 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6881 Spacing * 2));
6882 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6883 Spacing * 3));
6884 TmpInst.addOperand(Inst.getOperand(1)); // lane
6885 TmpInst.addOperand(Inst.getOperand(5)); // CondCode
6886 TmpInst.addOperand(Inst.getOperand(6));
6887 Inst = TmpInst;
6888 return true;
6889 }
6890
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006891 case ARM::VLD1LNdWB_fixed_Asm_8:
6892 case ARM::VLD1LNdWB_fixed_Asm_16:
6893 case ARM::VLD1LNdWB_fixed_Asm_32: {
Jim Grosbachdda976b2011-12-02 22:01:52 +00006894 MCInst TmpInst;
6895 // Shuffle the operands around so the lane index operand is in the
6896 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006897 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006898 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachdda976b2011-12-02 22:01:52 +00006899 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6900 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6901 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6902 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6903 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6904 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6905 TmpInst.addOperand(Inst.getOperand(1)); // lane
6906 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6907 TmpInst.addOperand(Inst.getOperand(5));
6908 Inst = TmpInst;
6909 return true;
6910 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006911
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00006912 case ARM::VLD2LNdWB_fixed_Asm_8:
6913 case ARM::VLD2LNdWB_fixed_Asm_16:
6914 case ARM::VLD2LNdWB_fixed_Asm_32:
6915 case ARM::VLD2LNqWB_fixed_Asm_16:
6916 case ARM::VLD2LNqWB_fixed_Asm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006917 MCInst TmpInst;
6918 // Shuffle the operands around so the lane index operand is in the
6919 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006920 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006921 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006922 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006923 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6924 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006925 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6926 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6927 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6928 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6929 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00006930 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6931 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00006932 TmpInst.addOperand(Inst.getOperand(1)); // lane
6933 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6934 TmpInst.addOperand(Inst.getOperand(5));
6935 Inst = TmpInst;
6936 return true;
6937 }
6938
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006939 case ARM::VLD3LNdWB_fixed_Asm_8:
6940 case ARM::VLD3LNdWB_fixed_Asm_16:
6941 case ARM::VLD3LNdWB_fixed_Asm_32:
6942 case ARM::VLD3LNqWB_fixed_Asm_16:
6943 case ARM::VLD3LNqWB_fixed_Asm_32: {
6944 MCInst TmpInst;
6945 // Shuffle the operands around so the lane index operand is in the
6946 // right place.
6947 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00006948 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006949 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6950 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6951 Spacing));
6952 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006953 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006954 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6955 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6956 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6957 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6958 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6959 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6960 Spacing));
6961 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00006962 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00006963 TmpInst.addOperand(Inst.getOperand(1)); // lane
6964 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
6965 TmpInst.addOperand(Inst.getOperand(5));
6966 Inst = TmpInst;
6967 return true;
6968 }
6969
Jim Grosbach14952a02012-01-24 18:37:25 +00006970 case ARM::VLD4LNdWB_fixed_Asm_8:
6971 case ARM::VLD4LNdWB_fixed_Asm_16:
6972 case ARM::VLD4LNdWB_fixed_Asm_32:
6973 case ARM::VLD4LNqWB_fixed_Asm_16:
6974 case ARM::VLD4LNqWB_fixed_Asm_32: {
6975 MCInst TmpInst;
6976 // Shuffle the operands around so the lane index operand is in the
6977 // right place.
6978 unsigned Spacing;
6979 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
6980 TmpInst.addOperand(Inst.getOperand(0)); // Vd
6981 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6982 Spacing));
6983 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6984 Spacing * 2));
6985 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6986 Spacing * 3));
6987 TmpInst.addOperand(Inst.getOperand(2)); // Rn_wb
6988 TmpInst.addOperand(Inst.getOperand(2)); // Rn
6989 TmpInst.addOperand(Inst.getOperand(3)); // alignment
6990 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
6991 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
6992 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6993 Spacing));
6994 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6995 Spacing * 2));
6996 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
6997 Spacing * 3));
6998 TmpInst.addOperand(Inst.getOperand(1)); // lane
6999 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7000 TmpInst.addOperand(Inst.getOperand(5));
7001 Inst = TmpInst;
7002 return true;
7003 }
7004
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00007005 case ARM::VLD1LNdAsm_8:
7006 case ARM::VLD1LNdAsm_16:
7007 case ARM::VLD1LNdAsm_32: {
Jim Grosbach04945c42011-12-02 00:35:16 +00007008 MCInst TmpInst;
7009 // Shuffle the operands around so the lane index operand is in the
7010 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00007011 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00007012 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbach04945c42011-12-02 00:35:16 +00007013 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7014 TmpInst.addOperand(Inst.getOperand(2)); // Rn
7015 TmpInst.addOperand(Inst.getOperand(3)); // alignment
7016 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7017 TmpInst.addOperand(Inst.getOperand(1)); // lane
7018 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7019 TmpInst.addOperand(Inst.getOperand(5));
7020 Inst = TmpInst;
7021 return true;
7022 }
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00007023
Jim Grosbachd28ef9a2012-01-23 19:39:08 +00007024 case ARM::VLD2LNdAsm_8:
7025 case ARM::VLD2LNdAsm_16:
7026 case ARM::VLD2LNdAsm_32:
7027 case ARM::VLD2LNqAsm_16:
7028 case ARM::VLD2LNqAsm_32: {
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00007029 MCInst TmpInst;
7030 // Shuffle the operands around so the lane index operand is in the
7031 // right place.
Jim Grosbach75e2ab52011-12-20 19:21:26 +00007032 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00007033 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00007034 TmpInst.addOperand(Inst.getOperand(0)); // Vd
Jim Grosbach75e2ab52011-12-20 19:21:26 +00007035 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7036 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00007037 TmpInst.addOperand(Inst.getOperand(2)); // Rn
7038 TmpInst.addOperand(Inst.getOperand(3)); // alignment
7039 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
Jim Grosbach75e2ab52011-12-20 19:21:26 +00007040 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7041 Spacing));
Jim Grosbacha8aa30b2011-12-14 23:25:46 +00007042 TmpInst.addOperand(Inst.getOperand(1)); // lane
7043 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7044 TmpInst.addOperand(Inst.getOperand(5));
7045 Inst = TmpInst;
7046 return true;
7047 }
Jim Grosbacha8b444b2012-01-23 21:53:26 +00007048
7049 case ARM::VLD3LNdAsm_8:
7050 case ARM::VLD3LNdAsm_16:
7051 case ARM::VLD3LNdAsm_32:
7052 case ARM::VLD3LNqAsm_16:
7053 case ARM::VLD3LNqAsm_32: {
7054 MCInst TmpInst;
7055 // Shuffle the operands around so the lane index operand is in the
7056 // right place.
7057 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00007058 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00007059 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7060 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7061 Spacing));
7062 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00007063 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00007064 TmpInst.addOperand(Inst.getOperand(2)); // Rn
7065 TmpInst.addOperand(Inst.getOperand(3)); // alignment
7066 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7067 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7068 Spacing));
7069 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
Jim Grosbachac2af3f2012-01-23 23:20:46 +00007070 Spacing * 2));
Jim Grosbacha8b444b2012-01-23 21:53:26 +00007071 TmpInst.addOperand(Inst.getOperand(1)); // lane
7072 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7073 TmpInst.addOperand(Inst.getOperand(5));
7074 Inst = TmpInst;
7075 return true;
7076 }
7077
Jim Grosbach14952a02012-01-24 18:37:25 +00007078 case ARM::VLD4LNdAsm_8:
7079 case ARM::VLD4LNdAsm_16:
7080 case ARM::VLD4LNdAsm_32:
7081 case ARM::VLD4LNqAsm_16:
7082 case ARM::VLD4LNqAsm_32: {
7083 MCInst TmpInst;
7084 // Shuffle the operands around so the lane index operand is in the
7085 // right place.
7086 unsigned Spacing;
7087 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7088 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7089 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7090 Spacing));
7091 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7092 Spacing * 2));
7093 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7094 Spacing * 3));
7095 TmpInst.addOperand(Inst.getOperand(2)); // Rn
7096 TmpInst.addOperand(Inst.getOperand(3)); // alignment
7097 TmpInst.addOperand(Inst.getOperand(0)); // Tied operand src (== Vd)
7098 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7099 Spacing));
7100 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7101 Spacing * 2));
7102 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7103 Spacing * 3));
7104 TmpInst.addOperand(Inst.getOperand(1)); // lane
7105 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7106 TmpInst.addOperand(Inst.getOperand(5));
7107 Inst = TmpInst;
7108 return true;
7109 }
7110
Jim Grosbachb78403c2012-01-24 23:47:04 +00007111 // VLD3DUP single 3-element structure to all lanes instructions.
7112 case ARM::VLD3DUPdAsm_8:
7113 case ARM::VLD3DUPdAsm_16:
7114 case ARM::VLD3DUPdAsm_32:
7115 case ARM::VLD3DUPqAsm_8:
7116 case ARM::VLD3DUPqAsm_16:
7117 case ARM::VLD3DUPqAsm_32: {
7118 MCInst TmpInst;
7119 unsigned Spacing;
7120 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7121 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7122 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7123 Spacing));
7124 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7125 Spacing * 2));
7126 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7127 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7128 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7129 TmpInst.addOperand(Inst.getOperand(4));
7130 Inst = TmpInst;
7131 return true;
7132 }
7133
7134 case ARM::VLD3DUPdWB_fixed_Asm_8:
7135 case ARM::VLD3DUPdWB_fixed_Asm_16:
7136 case ARM::VLD3DUPdWB_fixed_Asm_32:
7137 case ARM::VLD3DUPqWB_fixed_Asm_8:
7138 case ARM::VLD3DUPqWB_fixed_Asm_16:
7139 case ARM::VLD3DUPqWB_fixed_Asm_32: {
7140 MCInst TmpInst;
7141 unsigned Spacing;
7142 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7143 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7144 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7145 Spacing));
7146 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7147 Spacing * 2));
7148 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7149 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7150 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7151 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
7152 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7153 TmpInst.addOperand(Inst.getOperand(4));
7154 Inst = TmpInst;
7155 return true;
7156 }
7157
7158 case ARM::VLD3DUPdWB_register_Asm_8:
7159 case ARM::VLD3DUPdWB_register_Asm_16:
7160 case ARM::VLD3DUPdWB_register_Asm_32:
7161 case ARM::VLD3DUPqWB_register_Asm_8:
7162 case ARM::VLD3DUPqWB_register_Asm_16:
7163 case ARM::VLD3DUPqWB_register_Asm_32: {
7164 MCInst TmpInst;
7165 unsigned Spacing;
7166 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7167 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7168 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7169 Spacing));
7170 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7171 Spacing * 2));
7172 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7173 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7174 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7175 TmpInst.addOperand(Inst.getOperand(3)); // Rm
7176 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7177 TmpInst.addOperand(Inst.getOperand(5));
7178 Inst = TmpInst;
7179 return true;
7180 }
7181
Jim Grosbachac2af3f2012-01-23 23:20:46 +00007182 // VLD3 multiple 3-element structure instructions.
7183 case ARM::VLD3dAsm_8:
7184 case ARM::VLD3dAsm_16:
7185 case ARM::VLD3dAsm_32:
7186 case ARM::VLD3qAsm_8:
7187 case ARM::VLD3qAsm_16:
7188 case ARM::VLD3qAsm_32: {
7189 MCInst TmpInst;
7190 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00007191 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00007192 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7193 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7194 Spacing));
7195 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7196 Spacing * 2));
7197 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7198 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7199 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7200 TmpInst.addOperand(Inst.getOperand(4));
7201 Inst = TmpInst;
7202 return true;
7203 }
7204
7205 case ARM::VLD3dWB_fixed_Asm_8:
7206 case ARM::VLD3dWB_fixed_Asm_16:
7207 case ARM::VLD3dWB_fixed_Asm_32:
7208 case ARM::VLD3qWB_fixed_Asm_8:
7209 case ARM::VLD3qWB_fixed_Asm_16:
7210 case ARM::VLD3qWB_fixed_Asm_32: {
7211 MCInst TmpInst;
7212 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00007213 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00007214 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7215 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7216 Spacing));
7217 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7218 Spacing * 2));
7219 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7220 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7221 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7222 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
7223 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7224 TmpInst.addOperand(Inst.getOperand(4));
7225 Inst = TmpInst;
7226 return true;
7227 }
7228
7229 case ARM::VLD3dWB_register_Asm_8:
7230 case ARM::VLD3dWB_register_Asm_16:
7231 case ARM::VLD3dWB_register_Asm_32:
7232 case ARM::VLD3qWB_register_Asm_8:
7233 case ARM::VLD3qWB_register_Asm_16:
7234 case ARM::VLD3qWB_register_Asm_32: {
7235 MCInst TmpInst;
7236 unsigned Spacing;
Jim Grosbach1a747242012-01-23 23:45:44 +00007237 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
Jim Grosbachac2af3f2012-01-23 23:20:46 +00007238 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7239 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7240 Spacing));
7241 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7242 Spacing * 2));
7243 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7244 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7245 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7246 TmpInst.addOperand(Inst.getOperand(3)); // Rm
7247 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7248 TmpInst.addOperand(Inst.getOperand(5));
7249 Inst = TmpInst;
7250 return true;
7251 }
7252
Jim Grosbach086cbfa2012-01-25 00:01:08 +00007253 // VLD4DUP single 3-element structure to all lanes instructions.
7254 case ARM::VLD4DUPdAsm_8:
7255 case ARM::VLD4DUPdAsm_16:
7256 case ARM::VLD4DUPdAsm_32:
7257 case ARM::VLD4DUPqAsm_8:
7258 case ARM::VLD4DUPqAsm_16:
7259 case ARM::VLD4DUPqAsm_32: {
7260 MCInst TmpInst;
7261 unsigned Spacing;
7262 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7263 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7264 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7265 Spacing));
7266 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7267 Spacing * 2));
7268 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7269 Spacing * 3));
7270 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7271 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7272 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7273 TmpInst.addOperand(Inst.getOperand(4));
7274 Inst = TmpInst;
7275 return true;
7276 }
7277
7278 case ARM::VLD4DUPdWB_fixed_Asm_8:
7279 case ARM::VLD4DUPdWB_fixed_Asm_16:
7280 case ARM::VLD4DUPdWB_fixed_Asm_32:
7281 case ARM::VLD4DUPqWB_fixed_Asm_8:
7282 case ARM::VLD4DUPqWB_fixed_Asm_16:
7283 case ARM::VLD4DUPqWB_fixed_Asm_32: {
7284 MCInst TmpInst;
7285 unsigned Spacing;
7286 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7287 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7288 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7289 Spacing));
7290 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7291 Spacing * 2));
7292 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7293 Spacing * 3));
7294 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7295 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7296 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7297 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
7298 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7299 TmpInst.addOperand(Inst.getOperand(4));
7300 Inst = TmpInst;
7301 return true;
7302 }
7303
7304 case ARM::VLD4DUPdWB_register_Asm_8:
7305 case ARM::VLD4DUPdWB_register_Asm_16:
7306 case ARM::VLD4DUPdWB_register_Asm_32:
7307 case ARM::VLD4DUPqWB_register_Asm_8:
7308 case ARM::VLD4DUPqWB_register_Asm_16:
7309 case ARM::VLD4DUPqWB_register_Asm_32: {
7310 MCInst TmpInst;
7311 unsigned Spacing;
7312 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7313 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7314 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7315 Spacing));
7316 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7317 Spacing * 2));
7318 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7319 Spacing * 3));
7320 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7321 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7322 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7323 TmpInst.addOperand(Inst.getOperand(3)); // Rm
7324 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7325 TmpInst.addOperand(Inst.getOperand(5));
7326 Inst = TmpInst;
7327 return true;
7328 }
7329
7330 // VLD4 multiple 4-element structure instructions.
Jim Grosbached561fc2012-01-24 00:43:17 +00007331 case ARM::VLD4dAsm_8:
7332 case ARM::VLD4dAsm_16:
7333 case ARM::VLD4dAsm_32:
7334 case ARM::VLD4qAsm_8:
7335 case ARM::VLD4qAsm_16:
7336 case ARM::VLD4qAsm_32: {
7337 MCInst TmpInst;
7338 unsigned Spacing;
7339 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7340 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7341 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7342 Spacing));
7343 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7344 Spacing * 2));
7345 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7346 Spacing * 3));
7347 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7348 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7349 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7350 TmpInst.addOperand(Inst.getOperand(4));
7351 Inst = TmpInst;
7352 return true;
7353 }
7354
7355 case ARM::VLD4dWB_fixed_Asm_8:
7356 case ARM::VLD4dWB_fixed_Asm_16:
7357 case ARM::VLD4dWB_fixed_Asm_32:
7358 case ARM::VLD4qWB_fixed_Asm_8:
7359 case ARM::VLD4qWB_fixed_Asm_16:
7360 case ARM::VLD4qWB_fixed_Asm_32: {
7361 MCInst TmpInst;
7362 unsigned Spacing;
7363 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7364 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7365 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7366 Spacing));
7367 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7368 Spacing * 2));
7369 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7370 Spacing * 3));
7371 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7372 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7373 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7374 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
7375 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7376 TmpInst.addOperand(Inst.getOperand(4));
7377 Inst = TmpInst;
7378 return true;
7379 }
7380
7381 case ARM::VLD4dWB_register_Asm_8:
7382 case ARM::VLD4dWB_register_Asm_16:
7383 case ARM::VLD4dWB_register_Asm_32:
7384 case ARM::VLD4qWB_register_Asm_8:
7385 case ARM::VLD4qWB_register_Asm_16:
7386 case ARM::VLD4qWB_register_Asm_32: {
7387 MCInst TmpInst;
7388 unsigned Spacing;
7389 TmpInst.setOpcode(getRealVLDOpcode(Inst.getOpcode(), Spacing));
7390 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7391 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7392 Spacing));
7393 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7394 Spacing * 2));
7395 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7396 Spacing * 3));
7397 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7398 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7399 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7400 TmpInst.addOperand(Inst.getOperand(3)); // Rm
7401 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7402 TmpInst.addOperand(Inst.getOperand(5));
7403 Inst = TmpInst;
7404 return true;
7405 }
7406
Jim Grosbach1a747242012-01-23 23:45:44 +00007407 // VST3 multiple 3-element structure instructions.
7408 case ARM::VST3dAsm_8:
7409 case ARM::VST3dAsm_16:
7410 case ARM::VST3dAsm_32:
7411 case ARM::VST3qAsm_8:
7412 case ARM::VST3qAsm_16:
7413 case ARM::VST3qAsm_32: {
7414 MCInst TmpInst;
7415 unsigned Spacing;
7416 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7417 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7418 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7419 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7420 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7421 Spacing));
7422 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7423 Spacing * 2));
7424 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7425 TmpInst.addOperand(Inst.getOperand(4));
7426 Inst = TmpInst;
7427 return true;
7428 }
7429
7430 case ARM::VST3dWB_fixed_Asm_8:
7431 case ARM::VST3dWB_fixed_Asm_16:
7432 case ARM::VST3dWB_fixed_Asm_32:
7433 case ARM::VST3qWB_fixed_Asm_8:
7434 case ARM::VST3qWB_fixed_Asm_16:
7435 case ARM::VST3qWB_fixed_Asm_32: {
7436 MCInst TmpInst;
7437 unsigned Spacing;
7438 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7439 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7440 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7441 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7442 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
7443 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7444 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7445 Spacing));
7446 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7447 Spacing * 2));
7448 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7449 TmpInst.addOperand(Inst.getOperand(4));
7450 Inst = TmpInst;
7451 return true;
7452 }
7453
7454 case ARM::VST3dWB_register_Asm_8:
7455 case ARM::VST3dWB_register_Asm_16:
7456 case ARM::VST3dWB_register_Asm_32:
7457 case ARM::VST3qWB_register_Asm_8:
7458 case ARM::VST3qWB_register_Asm_16:
7459 case ARM::VST3qWB_register_Asm_32: {
7460 MCInst TmpInst;
7461 unsigned Spacing;
7462 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7463 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7464 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7465 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7466 TmpInst.addOperand(Inst.getOperand(3)); // Rm
7467 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7468 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7469 Spacing));
7470 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7471 Spacing * 2));
7472 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7473 TmpInst.addOperand(Inst.getOperand(5));
7474 Inst = TmpInst;
7475 return true;
7476 }
7477
Jim Grosbachda70eac2012-01-24 00:58:13 +00007478 // VST4 multiple 3-element structure instructions.
7479 case ARM::VST4dAsm_8:
7480 case ARM::VST4dAsm_16:
7481 case ARM::VST4dAsm_32:
7482 case ARM::VST4qAsm_8:
7483 case ARM::VST4qAsm_16:
7484 case ARM::VST4qAsm_32: {
7485 MCInst TmpInst;
7486 unsigned Spacing;
7487 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7488 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7489 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7490 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7491 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7492 Spacing));
7493 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7494 Spacing * 2));
7495 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7496 Spacing * 3));
7497 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7498 TmpInst.addOperand(Inst.getOperand(4));
7499 Inst = TmpInst;
7500 return true;
7501 }
7502
7503 case ARM::VST4dWB_fixed_Asm_8:
7504 case ARM::VST4dWB_fixed_Asm_16:
7505 case ARM::VST4dWB_fixed_Asm_32:
7506 case ARM::VST4qWB_fixed_Asm_8:
7507 case ARM::VST4qWB_fixed_Asm_16:
7508 case ARM::VST4qWB_fixed_Asm_32: {
7509 MCInst TmpInst;
7510 unsigned Spacing;
7511 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7512 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7513 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7514 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7515 TmpInst.addOperand(MCOperand::CreateReg(0)); // Rm
7516 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7517 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7518 Spacing));
7519 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7520 Spacing * 2));
7521 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7522 Spacing * 3));
7523 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7524 TmpInst.addOperand(Inst.getOperand(4));
7525 Inst = TmpInst;
7526 return true;
7527 }
7528
7529 case ARM::VST4dWB_register_Asm_8:
7530 case ARM::VST4dWB_register_Asm_16:
7531 case ARM::VST4dWB_register_Asm_32:
7532 case ARM::VST4qWB_register_Asm_8:
7533 case ARM::VST4qWB_register_Asm_16:
7534 case ARM::VST4qWB_register_Asm_32: {
7535 MCInst TmpInst;
7536 unsigned Spacing;
7537 TmpInst.setOpcode(getRealVSTOpcode(Inst.getOpcode(), Spacing));
7538 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7539 TmpInst.addOperand(Inst.getOperand(1)); // Rn_wb == tied Rn
7540 TmpInst.addOperand(Inst.getOperand(2)); // alignment
7541 TmpInst.addOperand(Inst.getOperand(3)); // Rm
7542 TmpInst.addOperand(Inst.getOperand(0)); // Vd
7543 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7544 Spacing));
7545 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7546 Spacing * 2));
7547 TmpInst.addOperand(MCOperand::CreateReg(Inst.getOperand(0).getReg() +
7548 Spacing * 3));
7549 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7550 TmpInst.addOperand(Inst.getOperand(5));
7551 Inst = TmpInst;
7552 return true;
7553 }
7554
Jim Grosbachad66de12012-04-11 00:15:16 +00007555 // Handle encoding choice for the shift-immediate instructions.
7556 case ARM::t2LSLri:
7557 case ARM::t2LSRri:
7558 case ARM::t2ASRri: {
7559 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7560 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
7561 Inst.getOperand(5).getReg() == (inITBlock() ? 0 : ARM::CPSR) &&
David Blaikie960ea3f2014-06-08 16:18:35 +00007562 !(static_cast<ARMOperand &>(*Operands[3]).isToken() &&
7563 static_cast<ARMOperand &>(*Operands[3]).getToken() == ".w")) {
Jim Grosbachad66de12012-04-11 00:15:16 +00007564 unsigned NewOpc;
7565 switch (Inst.getOpcode()) {
7566 default: llvm_unreachable("unexpected opcode");
7567 case ARM::t2LSLri: NewOpc = ARM::tLSLri; break;
7568 case ARM::t2LSRri: NewOpc = ARM::tLSRri; break;
7569 case ARM::t2ASRri: NewOpc = ARM::tASRri; break;
7570 }
7571 // The Thumb1 operands aren't in the same order. Awesome, eh?
7572 MCInst TmpInst;
7573 TmpInst.setOpcode(NewOpc);
7574 TmpInst.addOperand(Inst.getOperand(0));
7575 TmpInst.addOperand(Inst.getOperand(5));
7576 TmpInst.addOperand(Inst.getOperand(1));
7577 TmpInst.addOperand(Inst.getOperand(2));
7578 TmpInst.addOperand(Inst.getOperand(3));
7579 TmpInst.addOperand(Inst.getOperand(4));
7580 Inst = TmpInst;
7581 return true;
7582 }
7583 return false;
7584 }
7585
Jim Grosbach485e5622011-12-13 22:45:11 +00007586 // Handle the Thumb2 mode MOV complex aliases.
Jim Grosbachb3ef7132011-12-21 20:54:00 +00007587 case ARM::t2MOVsr:
7588 case ARM::t2MOVSsr: {
7589 // Which instruction to expand to depends on the CCOut operand and
7590 // whether we're in an IT block if the register operands are low
7591 // registers.
7592 bool isNarrow = false;
7593 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7594 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7595 isARMLowRegister(Inst.getOperand(2).getReg()) &&
7596 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
7597 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsr))
7598 isNarrow = true;
7599 MCInst TmpInst;
7600 unsigned newOpc;
7601 switch(ARM_AM::getSORegShOp(Inst.getOperand(3).getImm())) {
7602 default: llvm_unreachable("unexpected opcode!");
7603 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRrr : ARM::t2ASRrr; break;
7604 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRrr : ARM::t2LSRrr; break;
7605 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLrr : ARM::t2LSLrr; break;
7606 case ARM_AM::ror: newOpc = isNarrow ? ARM::tROR : ARM::t2RORrr; break;
7607 }
7608 TmpInst.setOpcode(newOpc);
7609 TmpInst.addOperand(Inst.getOperand(0)); // Rd
7610 if (isNarrow)
7611 TmpInst.addOperand(MCOperand::CreateReg(
7612 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
7613 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7614 TmpInst.addOperand(Inst.getOperand(2)); // Rm
7615 TmpInst.addOperand(Inst.getOperand(4)); // CondCode
7616 TmpInst.addOperand(Inst.getOperand(5));
7617 if (!isNarrow)
7618 TmpInst.addOperand(MCOperand::CreateReg(
7619 Inst.getOpcode() == ARM::t2MOVSsr ? ARM::CPSR : 0));
7620 Inst = TmpInst;
7621 return true;
7622 }
Jim Grosbach485e5622011-12-13 22:45:11 +00007623 case ARM::t2MOVsi:
7624 case ARM::t2MOVSsi: {
7625 // Which instruction to expand to depends on the CCOut operand and
7626 // whether we're in an IT block if the register operands are low
7627 // registers.
7628 bool isNarrow = false;
7629 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
7630 isARMLowRegister(Inst.getOperand(1).getReg()) &&
7631 inITBlock() == (Inst.getOpcode() == ARM::t2MOVsi))
7632 isNarrow = true;
7633 MCInst TmpInst;
7634 unsigned newOpc;
7635 switch(ARM_AM::getSORegShOp(Inst.getOperand(2).getImm())) {
7636 default: llvm_unreachable("unexpected opcode!");
7637 case ARM_AM::asr: newOpc = isNarrow ? ARM::tASRri : ARM::t2ASRri; break;
7638 case ARM_AM::lsr: newOpc = isNarrow ? ARM::tLSRri : ARM::t2LSRri; break;
7639 case ARM_AM::lsl: newOpc = isNarrow ? ARM::tLSLri : ARM::t2LSLri; break;
7640 case ARM_AM::ror: newOpc = ARM::t2RORri; isNarrow = false; break;
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00007641 case ARM_AM::rrx: isNarrow = false; newOpc = ARM::t2RRX; break;
Jim Grosbach485e5622011-12-13 22:45:11 +00007642 }
Benjamin Kramerbde91762012-06-02 10:20:22 +00007643 unsigned Amount = ARM_AM::getSORegOffset(Inst.getOperand(2).getImm());
7644 if (Amount == 32) Amount = 0;
Jim Grosbach485e5622011-12-13 22:45:11 +00007645 TmpInst.setOpcode(newOpc);
7646 TmpInst.addOperand(Inst.getOperand(0)); // Rd
7647 if (isNarrow)
7648 TmpInst.addOperand(MCOperand::CreateReg(
7649 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
7650 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbach8c59bbc2011-12-21 21:04:19 +00007651 if (newOpc != ARM::t2RRX)
Benjamin Kramerbde91762012-06-02 10:20:22 +00007652 TmpInst.addOperand(MCOperand::CreateImm(Amount));
Jim Grosbach485e5622011-12-13 22:45:11 +00007653 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7654 TmpInst.addOperand(Inst.getOperand(4));
7655 if (!isNarrow)
7656 TmpInst.addOperand(MCOperand::CreateReg(
7657 Inst.getOpcode() == ARM::t2MOVSsi ? ARM::CPSR : 0));
7658 Inst = TmpInst;
7659 return true;
7660 }
7661 // Handle the ARM mode MOV complex aliases.
Jim Grosbachabcac562011-11-16 18:31:45 +00007662 case ARM::ASRr:
7663 case ARM::LSRr:
7664 case ARM::LSLr:
7665 case ARM::RORr: {
7666 ARM_AM::ShiftOpc ShiftTy;
7667 switch(Inst.getOpcode()) {
7668 default: llvm_unreachable("unexpected opcode!");
7669 case ARM::ASRr: ShiftTy = ARM_AM::asr; break;
7670 case ARM::LSRr: ShiftTy = ARM_AM::lsr; break;
7671 case ARM::LSLr: ShiftTy = ARM_AM::lsl; break;
7672 case ARM::RORr: ShiftTy = ARM_AM::ror; break;
7673 }
Jim Grosbachabcac562011-11-16 18:31:45 +00007674 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, 0);
7675 MCInst TmpInst;
7676 TmpInst.setOpcode(ARM::MOVsr);
7677 TmpInst.addOperand(Inst.getOperand(0)); // Rd
7678 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7679 TmpInst.addOperand(Inst.getOperand(2)); // Rm
7680 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
7681 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7682 TmpInst.addOperand(Inst.getOperand(4));
7683 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
7684 Inst = TmpInst;
7685 return true;
7686 }
Jim Grosbachc14871c2011-11-10 19:18:01 +00007687 case ARM::ASRi:
7688 case ARM::LSRi:
7689 case ARM::LSLi:
7690 case ARM::RORi: {
7691 ARM_AM::ShiftOpc ShiftTy;
Jim Grosbachc14871c2011-11-10 19:18:01 +00007692 switch(Inst.getOpcode()) {
7693 default: llvm_unreachable("unexpected opcode!");
7694 case ARM::ASRi: ShiftTy = ARM_AM::asr; break;
7695 case ARM::LSRi: ShiftTy = ARM_AM::lsr; break;
7696 case ARM::LSLi: ShiftTy = ARM_AM::lsl; break;
7697 case ARM::RORi: ShiftTy = ARM_AM::ror; break;
7698 }
7699 // A shift by zero is a plain MOVr, not a MOVsi.
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00007700 unsigned Amt = Inst.getOperand(2).getImm();
Jim Grosbachc14871c2011-11-10 19:18:01 +00007701 unsigned Opc = Amt == 0 ? ARM::MOVr : ARM::MOVsi;
Richard Bartonba5b0cc2012-04-25 18:00:18 +00007702 // A shift by 32 should be encoded as 0 when permitted
7703 if (Amt == 32 && (ShiftTy == ARM_AM::lsr || ShiftTy == ARM_AM::asr))
7704 Amt = 0;
Jim Grosbachc14871c2011-11-10 19:18:01 +00007705 unsigned Shifter = ARM_AM::getSORegOpc(ShiftTy, Amt);
Jim Grosbach61db5a52011-11-10 16:44:55 +00007706 MCInst TmpInst;
Jim Grosbachc14871c2011-11-10 19:18:01 +00007707 TmpInst.setOpcode(Opc);
Jim Grosbach61db5a52011-11-10 16:44:55 +00007708 TmpInst.addOperand(Inst.getOperand(0)); // Rd
7709 TmpInst.addOperand(Inst.getOperand(1)); // Rn
Jim Grosbachc14871c2011-11-10 19:18:01 +00007710 if (Opc == ARM::MOVsi)
7711 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
Jim Grosbach61db5a52011-11-10 16:44:55 +00007712 TmpInst.addOperand(Inst.getOperand(3)); // CondCode
7713 TmpInst.addOperand(Inst.getOperand(4));
7714 TmpInst.addOperand(Inst.getOperand(5)); // cc_out
7715 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007716 return true;
Jim Grosbach61db5a52011-11-10 16:44:55 +00007717 }
Jim Grosbach1a2f9ee2011-11-16 19:05:59 +00007718 case ARM::RRXi: {
7719 unsigned Shifter = ARM_AM::getSORegOpc(ARM_AM::rrx, 0);
7720 MCInst TmpInst;
7721 TmpInst.setOpcode(ARM::MOVsi);
7722 TmpInst.addOperand(Inst.getOperand(0)); // Rd
7723 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7724 TmpInst.addOperand(MCOperand::CreateImm(Shifter)); // Shift value and ty
7725 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
7726 TmpInst.addOperand(Inst.getOperand(3));
7727 TmpInst.addOperand(Inst.getOperand(4)); // cc_out
7728 Inst = TmpInst;
7729 return true;
7730 }
Jim Grosbachd9a9be22011-11-10 23:58:34 +00007731 case ARM::t2LDMIA_UPD: {
7732 // If this is a load of a single register, then we should use
7733 // a post-indexed LDR instruction instead, per the ARM ARM.
7734 if (Inst.getNumOperands() != 5)
7735 return false;
7736 MCInst TmpInst;
7737 TmpInst.setOpcode(ARM::t2LDR_POST);
7738 TmpInst.addOperand(Inst.getOperand(4)); // Rt
7739 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
7740 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7741 TmpInst.addOperand(MCOperand::CreateImm(4));
7742 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
7743 TmpInst.addOperand(Inst.getOperand(3));
7744 Inst = TmpInst;
7745 return true;
7746 }
7747 case ARM::t2STMDB_UPD: {
7748 // If this is a store of a single register, then we should use
7749 // a pre-indexed STR instruction instead, per the ARM ARM.
7750 if (Inst.getNumOperands() != 5)
7751 return false;
7752 MCInst TmpInst;
7753 TmpInst.setOpcode(ARM::t2STR_PRE);
7754 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
7755 TmpInst.addOperand(Inst.getOperand(4)); // Rt
7756 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7757 TmpInst.addOperand(MCOperand::CreateImm(-4));
7758 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
7759 TmpInst.addOperand(Inst.getOperand(3));
7760 Inst = TmpInst;
7761 return true;
7762 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007763 case ARM::LDMIA_UPD:
7764 // If this is a load of a single register via a 'pop', then we should use
7765 // a post-indexed LDR instruction instead, per the ARM ARM.
David Blaikie960ea3f2014-06-08 16:18:35 +00007766 if (static_cast<ARMOperand &>(*Operands[0]).getToken() == "pop" &&
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007767 Inst.getNumOperands() == 5) {
7768 MCInst TmpInst;
7769 TmpInst.setOpcode(ARM::LDR_POST_IMM);
7770 TmpInst.addOperand(Inst.getOperand(4)); // Rt
7771 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
7772 TmpInst.addOperand(Inst.getOperand(1)); // Rn
7773 TmpInst.addOperand(MCOperand::CreateReg(0)); // am2offset
7774 TmpInst.addOperand(MCOperand::CreateImm(4));
7775 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
7776 TmpInst.addOperand(Inst.getOperand(3));
7777 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00007778 return true;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00007779 }
7780 break;
Jim Grosbach27ad83d2011-08-11 18:07:11 +00007781 case ARM::STMDB_UPD:
7782 // If this is a store of a single register via a 'push', then we should use
7783 // a pre-indexed STR instruction instead, per the ARM ARM.
David Blaikie960ea3f2014-06-08 16:18:35 +00007784 if (static_cast<ARMOperand &>(*Operands[0]).getToken() == "push" &&
Jim Grosbach27ad83d2011-08-11 18:07:11 +00007785 Inst.getNumOperands() == 5) {
7786 MCInst TmpInst;
7787 TmpInst.setOpcode(ARM::STR_PRE_IMM);
7788 TmpInst.addOperand(Inst.getOperand(0)); // Rn_wb
7789 TmpInst.addOperand(Inst.getOperand(4)); // Rt
7790 TmpInst.addOperand(Inst.getOperand(1)); // addrmode_imm12
7791 TmpInst.addOperand(MCOperand::CreateImm(-4));
7792 TmpInst.addOperand(Inst.getOperand(2)); // CondCode
7793 TmpInst.addOperand(Inst.getOperand(3));
7794 Inst = TmpInst;
7795 }
7796 break;
Jim Grosbachec9ba982011-12-05 21:06:26 +00007797 case ARM::t2ADDri12:
7798 // If the immediate fits for encoding T3 (t2ADDri) and the generic "add"
7799 // mnemonic was used (not "addw"), encoding T3 is preferred.
David Blaikie960ea3f2014-06-08 16:18:35 +00007800 if (static_cast<ARMOperand &>(*Operands[0]).getToken() != "add" ||
Jim Grosbachec9ba982011-12-05 21:06:26 +00007801 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
7802 break;
7803 Inst.setOpcode(ARM::t2ADDri);
7804 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7805 break;
7806 case ARM::t2SUBri12:
7807 // If the immediate fits for encoding T3 (t2SUBri) and the generic "sub"
7808 // mnemonic was used (not "subw"), encoding T3 is preferred.
David Blaikie960ea3f2014-06-08 16:18:35 +00007809 if (static_cast<ARMOperand &>(*Operands[0]).getToken() != "sub" ||
Jim Grosbachec9ba982011-12-05 21:06:26 +00007810 ARM_AM::getT2SOImmVal(Inst.getOperand(2).getImm()) == -1)
7811 break;
7812 Inst.setOpcode(ARM::t2SUBri);
7813 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7814 break;
Jim Grosbache9ab47a2011-08-16 23:57:34 +00007815 case ARM::tADDi8:
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00007816 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
Jim Grosbach6d606fb2011-08-31 17:07:33 +00007817 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
7818 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
7819 // to encoding T1 if <Rd> is omitted."
Jim Grosbach199ab902012-03-30 16:31:31 +00007820 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbache9ab47a2011-08-16 23:57:34 +00007821 Inst.setOpcode(ARM::tADDi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00007822 return true;
7823 }
Jim Grosbache9ab47a2011-08-16 23:57:34 +00007824 break;
Jim Grosbachd0c435c2011-09-16 22:58:42 +00007825 case ARM::tSUBi8:
Sylvestre Ledru91ce36c2012-09-27 10:14:43 +00007826 // If the immediate is in the range 0-7, we want tADDi3 iff Rd was
Jim Grosbachd0c435c2011-09-16 22:58:42 +00007827 // explicitly specified. From the ARM ARM: "Encoding T1 is preferred
7828 // to encoding T2 if <Rd> is specified and encoding T2 is preferred
7829 // to encoding T1 if <Rd> is omitted."
Jim Grosbach199ab902012-03-30 16:31:31 +00007830 if ((unsigned)Inst.getOperand(3).getImm() < 8 && Operands.size() == 6) {
Jim Grosbachd0c435c2011-09-16 22:58:42 +00007831 Inst.setOpcode(ARM::tSUBi3);
Jim Grosbachafad0532011-11-10 23:42:14 +00007832 return true;
7833 }
Jim Grosbachd0c435c2011-09-16 22:58:42 +00007834 break;
Jim Grosbachdef5e342012-03-30 17:20:40 +00007835 case ARM::t2ADDri:
7836 case ARM::t2SUBri: {
7837 // If the destination and first source operand are the same, and
7838 // the flags are compatible with the current IT status, use encoding T2
7839 // instead of T3. For compatibility with the system 'as'. Make sure the
7840 // wide encoding wasn't explicit.
7841 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
Jim Grosbach74005ae2012-03-30 18:39:43 +00007842 !isARMLowRegister(Inst.getOperand(0).getReg()) ||
Jim Grosbachdef5e342012-03-30 17:20:40 +00007843 (unsigned)Inst.getOperand(2).getImm() > 255 ||
7844 ((!inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR) ||
David Blaikie960ea3f2014-06-08 16:18:35 +00007845 (inITBlock() && Inst.getOperand(5).getReg() != 0)) ||
7846 (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
7847 static_cast<ARMOperand &>(*Operands[3]).getToken() == ".w"))
Jim Grosbachdef5e342012-03-30 17:20:40 +00007848 break;
7849 MCInst TmpInst;
7850 TmpInst.setOpcode(Inst.getOpcode() == ARM::t2ADDri ?
7851 ARM::tADDi8 : ARM::tSUBi8);
7852 TmpInst.addOperand(Inst.getOperand(0));
7853 TmpInst.addOperand(Inst.getOperand(5));
7854 TmpInst.addOperand(Inst.getOperand(0));
7855 TmpInst.addOperand(Inst.getOperand(2));
7856 TmpInst.addOperand(Inst.getOperand(3));
7857 TmpInst.addOperand(Inst.getOperand(4));
7858 Inst = TmpInst;
7859 return true;
7860 }
Jim Grosbache489bab2011-12-05 22:16:39 +00007861 case ARM::t2ADDrr: {
7862 // If the destination and first source operand are the same, and
7863 // there's no setting of the flags, use encoding T2 instead of T3.
7864 // Note that this is only for ADD, not SUB. This mirrors the system
7865 // 'as' behaviour. Make sure the wide encoding wasn't explicit.
7866 if (Inst.getOperand(0).getReg() != Inst.getOperand(1).getReg() ||
7867 Inst.getOperand(5).getReg() != 0 ||
David Blaikie960ea3f2014-06-08 16:18:35 +00007868 (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
7869 static_cast<ARMOperand &>(*Operands[3]).getToken() == ".w"))
Jim Grosbache489bab2011-12-05 22:16:39 +00007870 break;
7871 MCInst TmpInst;
7872 TmpInst.setOpcode(ARM::tADDhirr);
7873 TmpInst.addOperand(Inst.getOperand(0));
7874 TmpInst.addOperand(Inst.getOperand(0));
7875 TmpInst.addOperand(Inst.getOperand(2));
7876 TmpInst.addOperand(Inst.getOperand(3));
7877 TmpInst.addOperand(Inst.getOperand(4));
7878 Inst = TmpInst;
7879 return true;
7880 }
Jim Grosbachc6f32b32012-04-27 23:51:36 +00007881 case ARM::tADDrSP: {
7882 // If the non-SP source operand and the destination operand are not the
7883 // same, we need to use the 32-bit encoding if it's available.
7884 if (Inst.getOperand(0).getReg() != Inst.getOperand(2).getReg()) {
7885 Inst.setOpcode(ARM::t2ADDrr);
7886 Inst.addOperand(MCOperand::CreateReg(0)); // cc_out
7887 return true;
7888 }
7889 break;
7890 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007891 case ARM::tB:
7892 // A Thumb conditional branch outside of an IT block is a tBcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00007893 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()) {
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007894 Inst.setOpcode(ARM::tBcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00007895 return true;
7896 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007897 break;
7898 case ARM::t2B:
7899 // A Thumb2 conditional branch outside of an IT block is a t2Bcc.
Jim Grosbachafad0532011-11-10 23:42:14 +00007900 if (Inst.getOperand(1).getImm() != ARMCC::AL && !inITBlock()){
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007901 Inst.setOpcode(ARM::t2Bcc);
Jim Grosbachafad0532011-11-10 23:42:14 +00007902 return true;
7903 }
Owen Anderson29cfe6c2011-09-09 21:48:23 +00007904 break;
Jim Grosbach99bc8462011-08-31 21:17:31 +00007905 case ARM::t2Bcc:
Jim Grosbacha0d34d32011-09-02 23:22:08 +00007906 // If the conditional is AL or we're in an IT block, we really want t2B.
Jim Grosbachafad0532011-11-10 23:42:14 +00007907 if (Inst.getOperand(1).getImm() == ARMCC::AL || inITBlock()) {
Jim Grosbach99bc8462011-08-31 21:17:31 +00007908 Inst.setOpcode(ARM::t2B);
Jim Grosbachafad0532011-11-10 23:42:14 +00007909 return true;
7910 }
Jim Grosbach99bc8462011-08-31 21:17:31 +00007911 break;
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00007912 case ARM::tBcc:
7913 // If the conditional is AL, we really want tB.
Jim Grosbachafad0532011-11-10 23:42:14 +00007914 if (Inst.getOperand(1).getImm() == ARMCC::AL) {
Jim Grosbachcbd4ab12011-08-17 22:57:40 +00007915 Inst.setOpcode(ARM::tB);
Jim Grosbachafad0532011-11-10 23:42:14 +00007916 return true;
7917 }
Jim Grosbach6ddb5682011-08-18 16:08:39 +00007918 break;
Jim Grosbacha31f2232011-09-07 18:05:34 +00007919 case ARM::tLDMIA: {
7920 // If the register list contains any high registers, or if the writeback
7921 // doesn't match what tLDMIA can do, we need to use the 32-bit encoding
7922 // instead if we're in Thumb2. Otherwise, this should have generated
7923 // an error in validateInstruction().
7924 unsigned Rn = Inst.getOperand(0).getReg();
7925 bool hasWritebackToken =
David Blaikie960ea3f2014-06-08 16:18:35 +00007926 (static_cast<ARMOperand &>(*Operands[3]).isToken() &&
7927 static_cast<ARMOperand &>(*Operands[3]).getToken() == "!");
Jim Grosbacha31f2232011-09-07 18:05:34 +00007928 bool listContainsBase;
7929 if (checkLowRegisterList(Inst, 3, Rn, 0, listContainsBase) ||
7930 (!listContainsBase && !hasWritebackToken) ||
7931 (listContainsBase && hasWritebackToken)) {
7932 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7933 assert (isThumbTwo());
7934 Inst.setOpcode(hasWritebackToken ? ARM::t2LDMIA_UPD : ARM::t2LDMIA);
7935 // If we're switching to the updating version, we need to insert
7936 // the writeback tied operand.
7937 if (hasWritebackToken)
7938 Inst.insert(Inst.begin(),
7939 MCOperand::CreateReg(Inst.getOperand(0).getReg()));
Jim Grosbachafad0532011-11-10 23:42:14 +00007940 return true;
Jim Grosbacha31f2232011-09-07 18:05:34 +00007941 }
7942 break;
7943 }
Jim Grosbach099c9762011-09-16 20:50:13 +00007944 case ARM::tSTMIA_UPD: {
7945 // If the register list contains any high registers, we need to use
7946 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7947 // should have generated an error in validateInstruction().
7948 unsigned Rn = Inst.getOperand(0).getReg();
7949 bool listContainsBase;
7950 if (checkLowRegisterList(Inst, 4, Rn, 0, listContainsBase)) {
7951 // 16-bit encoding isn't sufficient. Switch to the 32-bit version.
7952 assert (isThumbTwo());
7953 Inst.setOpcode(ARM::t2STMIA_UPD);
Jim Grosbachafad0532011-11-10 23:42:14 +00007954 return true;
Jim Grosbach099c9762011-09-16 20:50:13 +00007955 }
7956 break;
7957 }
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007958 case ARM::tPOP: {
7959 bool listContainsBase;
7960 // If the register list contains any high registers, we need to use
7961 // the 32-bit encoding instead if we're in Thumb2. Otherwise, this
7962 // should have generated an error in validateInstruction().
7963 if (!checkLowRegisterList(Inst, 2, 0, ARM::PC, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00007964 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007965 assert (isThumbTwo());
7966 Inst.setOpcode(ARM::t2LDMIA_UPD);
7967 // Add the base register and writeback operands.
7968 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7969 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00007970 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007971 }
7972 case ARM::tPUSH: {
7973 bool listContainsBase;
7974 if (!checkLowRegisterList(Inst, 2, 0, ARM::LR, listContainsBase))
Jim Grosbachafad0532011-11-10 23:42:14 +00007975 return false;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007976 assert (isThumbTwo());
7977 Inst.setOpcode(ARM::t2STMDB_UPD);
7978 // Add the base register and writeback operands.
7979 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
7980 Inst.insert(Inst.begin(), MCOperand::CreateReg(ARM::SP));
Jim Grosbachafad0532011-11-10 23:42:14 +00007981 return true;
Jim Grosbach9bded9d2011-11-10 23:17:11 +00007982 }
Jim Grosbachb908b7a2011-09-10 00:15:36 +00007983 case ARM::t2MOVi: {
7984 // If we can use the 16-bit encoding and the user didn't explicitly
7985 // request the 32-bit variant, transform it here.
7986 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
Jim Grosbach199ab902012-03-30 16:31:31 +00007987 (unsigned)Inst.getOperand(1).getImm() <= 255 &&
Jim Grosbach18b8b172011-09-14 19:12:11 +00007988 ((!inITBlock() && Inst.getOperand(2).getImm() == ARMCC::AL &&
David Blaikie960ea3f2014-06-08 16:18:35 +00007989 Inst.getOperand(4).getReg() == ARM::CPSR) ||
7990 (inITBlock() && Inst.getOperand(4).getReg() == 0)) &&
7991 (!static_cast<ARMOperand &>(*Operands[2]).isToken() ||
7992 static_cast<ARMOperand &>(*Operands[2]).getToken() != ".w")) {
Jim Grosbachb908b7a2011-09-10 00:15:36 +00007993 // The operands aren't in the same order for tMOVi8...
7994 MCInst TmpInst;
7995 TmpInst.setOpcode(ARM::tMOVi8);
7996 TmpInst.addOperand(Inst.getOperand(0));
7997 TmpInst.addOperand(Inst.getOperand(4));
7998 TmpInst.addOperand(Inst.getOperand(1));
7999 TmpInst.addOperand(Inst.getOperand(2));
8000 TmpInst.addOperand(Inst.getOperand(3));
8001 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00008002 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00008003 }
8004 break;
8005 }
8006 case ARM::t2MOVr: {
8007 // If we can use the 16-bit encoding and the user didn't explicitly
8008 // request the 32-bit variant, transform it here.
8009 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
8010 isARMLowRegister(Inst.getOperand(1).getReg()) &&
8011 Inst.getOperand(2).getImm() == ARMCC::AL &&
8012 Inst.getOperand(4).getReg() == ARM::CPSR &&
David Blaikie960ea3f2014-06-08 16:18:35 +00008013 (!static_cast<ARMOperand &>(*Operands[2]).isToken() ||
8014 static_cast<ARMOperand &>(*Operands[2]).getToken() != ".w")) {
Jim Grosbachb908b7a2011-09-10 00:15:36 +00008015 // The operands aren't the same for tMOV[S]r... (no cc_out)
8016 MCInst TmpInst;
8017 TmpInst.setOpcode(Inst.getOperand(4).getReg() ? ARM::tMOVSr : ARM::tMOVr);
8018 TmpInst.addOperand(Inst.getOperand(0));
8019 TmpInst.addOperand(Inst.getOperand(1));
8020 TmpInst.addOperand(Inst.getOperand(2));
8021 TmpInst.addOperand(Inst.getOperand(3));
8022 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00008023 return true;
Jim Grosbachb908b7a2011-09-10 00:15:36 +00008024 }
8025 break;
8026 }
Jim Grosbach82213192011-09-19 20:29:33 +00008027 case ARM::t2SXTH:
Jim Grosbachb3519802011-09-20 00:46:54 +00008028 case ARM::t2SXTB:
8029 case ARM::t2UXTH:
8030 case ARM::t2UXTB: {
Jim Grosbach82213192011-09-19 20:29:33 +00008031 // If we can use the 16-bit encoding and the user didn't explicitly
8032 // request the 32-bit variant, transform it here.
8033 if (isARMLowRegister(Inst.getOperand(0).getReg()) &&
8034 isARMLowRegister(Inst.getOperand(1).getReg()) &&
8035 Inst.getOperand(2).getImm() == 0 &&
David Blaikie960ea3f2014-06-08 16:18:35 +00008036 (!static_cast<ARMOperand &>(*Operands[2]).isToken() ||
8037 static_cast<ARMOperand &>(*Operands[2]).getToken() != ".w")) {
Jim Grosbachb3519802011-09-20 00:46:54 +00008038 unsigned NewOpc;
8039 switch (Inst.getOpcode()) {
8040 default: llvm_unreachable("Illegal opcode!");
8041 case ARM::t2SXTH: NewOpc = ARM::tSXTH; break;
8042 case ARM::t2SXTB: NewOpc = ARM::tSXTB; break;
8043 case ARM::t2UXTH: NewOpc = ARM::tUXTH; break;
8044 case ARM::t2UXTB: NewOpc = ARM::tUXTB; break;
8045 }
Jim Grosbach82213192011-09-19 20:29:33 +00008046 // The operands aren't the same for thumb1 (no rotate operand).
8047 MCInst TmpInst;
8048 TmpInst.setOpcode(NewOpc);
8049 TmpInst.addOperand(Inst.getOperand(0));
8050 TmpInst.addOperand(Inst.getOperand(1));
8051 TmpInst.addOperand(Inst.getOperand(3));
8052 TmpInst.addOperand(Inst.getOperand(4));
8053 Inst = TmpInst;
Jim Grosbachafad0532011-11-10 23:42:14 +00008054 return true;
Jim Grosbach82213192011-09-19 20:29:33 +00008055 }
8056 break;
8057 }
Jim Grosbache2ca9e52011-12-20 00:59:38 +00008058 case ARM::MOVsi: {
8059 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(2).getImm());
Richard Bartonba5b0cc2012-04-25 18:00:18 +00008060 // rrx shifts and asr/lsr of #32 is encoded as 0
8061 if (SOpc == ARM_AM::rrx || SOpc == ARM_AM::asr || SOpc == ARM_AM::lsr)
8062 return false;
Jim Grosbache2ca9e52011-12-20 00:59:38 +00008063 if (ARM_AM::getSORegOffset(Inst.getOperand(2).getImm()) == 0) {
8064 // Shifting by zero is accepted as a vanilla 'MOVr'
8065 MCInst TmpInst;
8066 TmpInst.setOpcode(ARM::MOVr);
8067 TmpInst.addOperand(Inst.getOperand(0));
8068 TmpInst.addOperand(Inst.getOperand(1));
8069 TmpInst.addOperand(Inst.getOperand(3));
8070 TmpInst.addOperand(Inst.getOperand(4));
8071 TmpInst.addOperand(Inst.getOperand(5));
8072 Inst = TmpInst;
8073 return true;
8074 }
8075 return false;
8076 }
Jim Grosbach12ccf452011-12-22 18:04:04 +00008077 case ARM::ANDrsi:
8078 case ARM::ORRrsi:
8079 case ARM::EORrsi:
8080 case ARM::BICrsi:
8081 case ARM::SUBrsi:
8082 case ARM::ADDrsi: {
8083 unsigned newOpc;
8084 ARM_AM::ShiftOpc SOpc = ARM_AM::getSORegShOp(Inst.getOperand(3).getImm());
8085 if (SOpc == ARM_AM::rrx) return false;
8086 switch (Inst.getOpcode()) {
Craig Toppere55c5562012-02-07 02:50:20 +00008087 default: llvm_unreachable("unexpected opcode!");
Jim Grosbach12ccf452011-12-22 18:04:04 +00008088 case ARM::ANDrsi: newOpc = ARM::ANDrr; break;
8089 case ARM::ORRrsi: newOpc = ARM::ORRrr; break;
8090 case ARM::EORrsi: newOpc = ARM::EORrr; break;
8091 case ARM::BICrsi: newOpc = ARM::BICrr; break;
8092 case ARM::SUBrsi: newOpc = ARM::SUBrr; break;
8093 case ARM::ADDrsi: newOpc = ARM::ADDrr; break;
8094 }
8095 // If the shift is by zero, use the non-shifted instruction definition.
Richard Barton35aceb82012-07-09 16:31:14 +00008096 // The exception is for right shifts, where 0 == 32
8097 if (ARM_AM::getSORegOffset(Inst.getOperand(3).getImm()) == 0 &&
8098 !(SOpc == ARM_AM::lsr || SOpc == ARM_AM::asr)) {
Jim Grosbach12ccf452011-12-22 18:04:04 +00008099 MCInst TmpInst;
8100 TmpInst.setOpcode(newOpc);
8101 TmpInst.addOperand(Inst.getOperand(0));
8102 TmpInst.addOperand(Inst.getOperand(1));
8103 TmpInst.addOperand(Inst.getOperand(2));
8104 TmpInst.addOperand(Inst.getOperand(4));
8105 TmpInst.addOperand(Inst.getOperand(5));
8106 TmpInst.addOperand(Inst.getOperand(6));
8107 Inst = TmpInst;
8108 return true;
8109 }
8110 return false;
8111 }
Jim Grosbach82f76d12012-01-25 19:52:01 +00008112 case ARM::ITasm:
Jim Grosbach3d1eac82011-08-26 21:43:41 +00008113 case ARM::t2IT: {
8114 // The mask bits for all but the first condition are represented as
8115 // the low bit of the condition code value implies 't'. We currently
8116 // always have 1 implies 't', so XOR toggle the bits if the low bit
Richard Bartonf435b092012-04-27 08:42:59 +00008117 // of the condition code is zero.
Jim Grosbach3d1eac82011-08-26 21:43:41 +00008118 MCOperand &MO = Inst.getOperand(1);
8119 unsigned Mask = MO.getImm();
Jim Grosbached16ec42011-08-29 22:24:09 +00008120 unsigned OrigMask = Mask;
Michael J. Spencerdf1ecbd72013-05-24 22:23:49 +00008121 unsigned TZ = countTrailingZeros(Mask);
Jim Grosbach3d1eac82011-08-26 21:43:41 +00008122 if ((Inst.getOperand(0).getImm() & 1) == 0) {
Jim Grosbach3d1eac82011-08-26 21:43:41 +00008123 assert(Mask && TZ <= 3 && "illegal IT mask value!");
Benjamin Kramer8bad66e2013-05-19 22:01:57 +00008124 Mask ^= (0xE << TZ) & 0xF;
Richard Bartonf435b092012-04-27 08:42:59 +00008125 }
Jim Grosbach3d1eac82011-08-26 21:43:41 +00008126 MO.setImm(Mask);
Jim Grosbached16ec42011-08-29 22:24:09 +00008127
8128 // Set up the IT block state according to the IT instruction we just
8129 // matched.
8130 assert(!inITBlock() && "nested IT blocks?!");
8131 ITState.Cond = ARMCC::CondCodes(Inst.getOperand(0).getImm());
8132 ITState.Mask = OrigMask; // Use the original mask, not the updated one.
8133 ITState.CurPosition = 0;
8134 ITState.FirstCond = true;
Jim Grosbach3d1eac82011-08-26 21:43:41 +00008135 break;
8136 }
Richard Bartona39625e2012-07-09 16:12:24 +00008137 case ARM::t2LSLrr:
8138 case ARM::t2LSRrr:
8139 case ARM::t2ASRrr:
8140 case ARM::t2SBCrr:
8141 case ARM::t2RORrr:
8142 case ARM::t2BICrr:
8143 {
Richard Bartond5660372012-07-09 16:14:28 +00008144 // Assemblers should use the narrow encodings of these instructions when permissible.
Richard Bartona39625e2012-07-09 16:12:24 +00008145 if ((isARMLowRegister(Inst.getOperand(1).getReg()) &&
8146 isARMLowRegister(Inst.getOperand(2).getReg())) &&
8147 Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() &&
Richard Barton984d0ba2012-07-09 18:30:56 +00008148 ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) ||
David Blaikie960ea3f2014-06-08 16:18:35 +00008149 (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) &&
8150 (!static_cast<ARMOperand &>(*Operands[3]).isToken() ||
8151 !static_cast<ARMOperand &>(*Operands[3]).getToken().equals_lower(
8152 ".w"))) {
Richard Bartona39625e2012-07-09 16:12:24 +00008153 unsigned NewOpc;
8154 switch (Inst.getOpcode()) {
8155 default: llvm_unreachable("unexpected opcode");
8156 case ARM::t2LSLrr: NewOpc = ARM::tLSLrr; break;
8157 case ARM::t2LSRrr: NewOpc = ARM::tLSRrr; break;
8158 case ARM::t2ASRrr: NewOpc = ARM::tASRrr; break;
8159 case ARM::t2SBCrr: NewOpc = ARM::tSBC; break;
8160 case ARM::t2RORrr: NewOpc = ARM::tROR; break;
8161 case ARM::t2BICrr: NewOpc = ARM::tBIC; break;
8162 }
8163 MCInst TmpInst;
8164 TmpInst.setOpcode(NewOpc);
8165 TmpInst.addOperand(Inst.getOperand(0));
8166 TmpInst.addOperand(Inst.getOperand(5));
8167 TmpInst.addOperand(Inst.getOperand(1));
8168 TmpInst.addOperand(Inst.getOperand(2));
8169 TmpInst.addOperand(Inst.getOperand(3));
8170 TmpInst.addOperand(Inst.getOperand(4));
8171 Inst = TmpInst;
8172 return true;
8173 }
8174 return false;
8175 }
8176 case ARM::t2ANDrr:
8177 case ARM::t2EORrr:
8178 case ARM::t2ADCrr:
8179 case ARM::t2ORRrr:
8180 {
Richard Bartond5660372012-07-09 16:14:28 +00008181 // Assemblers should use the narrow encodings of these instructions when permissible.
Richard Bartona39625e2012-07-09 16:12:24 +00008182 // These instructions are special in that they are commutable, so shorter encodings
8183 // are available more often.
8184 if ((isARMLowRegister(Inst.getOperand(1).getReg()) &&
8185 isARMLowRegister(Inst.getOperand(2).getReg())) &&
8186 (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg() ||
8187 Inst.getOperand(0).getReg() == Inst.getOperand(2).getReg()) &&
Richard Barton984d0ba2012-07-09 18:30:56 +00008188 ((!inITBlock() && Inst.getOperand(5).getReg() == ARM::CPSR) ||
David Blaikie960ea3f2014-06-08 16:18:35 +00008189 (inITBlock() && Inst.getOperand(5).getReg() != ARM::CPSR)) &&
8190 (!static_cast<ARMOperand &>(*Operands[3]).isToken() ||
8191 !static_cast<ARMOperand &>(*Operands[3]).getToken().equals_lower(
8192 ".w"))) {
Richard Bartona39625e2012-07-09 16:12:24 +00008193 unsigned NewOpc;
8194 switch (Inst.getOpcode()) {
8195 default: llvm_unreachable("unexpected opcode");
8196 case ARM::t2ADCrr: NewOpc = ARM::tADC; break;
8197 case ARM::t2ANDrr: NewOpc = ARM::tAND; break;
8198 case ARM::t2EORrr: NewOpc = ARM::tEOR; break;
8199 case ARM::t2ORRrr: NewOpc = ARM::tORR; break;
8200 }
8201 MCInst TmpInst;
8202 TmpInst.setOpcode(NewOpc);
8203 TmpInst.addOperand(Inst.getOperand(0));
8204 TmpInst.addOperand(Inst.getOperand(5));
8205 if (Inst.getOperand(0).getReg() == Inst.getOperand(1).getReg()) {
8206 TmpInst.addOperand(Inst.getOperand(1));
8207 TmpInst.addOperand(Inst.getOperand(2));
8208 } else {
8209 TmpInst.addOperand(Inst.getOperand(2));
8210 TmpInst.addOperand(Inst.getOperand(1));
8211 }
8212 TmpInst.addOperand(Inst.getOperand(3));
8213 TmpInst.addOperand(Inst.getOperand(4));
8214 Inst = TmpInst;
8215 return true;
8216 }
8217 return false;
8218 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00008219 }
Jim Grosbachafad0532011-11-10 23:42:14 +00008220 return false;
Jim Grosbach8ba76c62011-08-11 17:35:48 +00008221}
8222
Jim Grosbach3e941ae2011-08-16 20:45:50 +00008223unsigned ARMAsmParser::checkTargetMatchPredicate(MCInst &Inst) {
8224 // 16-bit thumb arithmetic instructions either require or preclude the 'S'
8225 // suffix depending on whether they're in an IT block or not.
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00008226 unsigned Opc = Inst.getOpcode();
Joey Gouly0e76fa72013-09-12 10:28:05 +00008227 const MCInstrDesc &MCID = MII.get(Opc);
Jim Grosbach3e941ae2011-08-16 20:45:50 +00008228 if (MCID.TSFlags & ARMII::ThumbArithFlagSetting) {
8229 assert(MCID.hasOptionalDef() &&
8230 "optionally flag setting instruction missing optional def operand");
8231 assert(MCID.NumOperands == Inst.getNumOperands() &&
8232 "operand count mismatch!");
8233 // Find the optional-def operand (cc_out).
8234 unsigned OpNo;
8235 for (OpNo = 0;
8236 !MCID.OpInfo[OpNo].isOptionalDef() && OpNo < MCID.NumOperands;
8237 ++OpNo)
8238 ;
8239 // If we're parsing Thumb1, reject it completely.
8240 if (isThumbOne() && Inst.getOperand(OpNo).getReg() != ARM::CPSR)
8241 return Match_MnemonicFail;
8242 // If we're parsing Thumb2, which form is legal depends on whether we're
8243 // in an IT block.
Jim Grosbached16ec42011-08-29 22:24:09 +00008244 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() != ARM::CPSR &&
8245 !inITBlock())
Jim Grosbach3e941ae2011-08-16 20:45:50 +00008246 return Match_RequiresITBlock;
Jim Grosbached16ec42011-08-29 22:24:09 +00008247 if (isThumbTwo() && Inst.getOperand(OpNo).getReg() == ARM::CPSR &&
8248 inITBlock())
8249 return Match_RequiresNotITBlock;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00008250 }
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00008251 // Some high-register supporting Thumb1 encodings only allow both registers
8252 // to be from r0-r7 when in Thumb2.
Renato Golin36c626e2014-09-26 16:14:29 +00008253 else if (Opc == ARM::tADDhirr && isThumbOne() && !hasV6MOps() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00008254 isARMLowRegister(Inst.getOperand(1).getReg()) &&
8255 isARMLowRegister(Inst.getOperand(2).getReg()))
8256 return Match_RequiresThumb2;
8257 // Others only require ARMv6 or later.
Jim Grosbachf86cd372011-08-19 20:46:54 +00008258 else if (Opc == ARM::tMOVr && isThumbOne() && !hasV6Ops() &&
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00008259 isARMLowRegister(Inst.getOperand(0).getReg()) &&
8260 isARMLowRegister(Inst.getOperand(1).getReg()))
8261 return Match_RequiresV6;
Jim Grosbach3e941ae2011-08-16 20:45:50 +00008262 return Match_Success;
8263}
8264
Benjamin Kramer44a53da2014-04-12 18:45:24 +00008265namespace llvm {
8266template <> inline bool IsCPSRDead<MCInst>(MCInst *Instr) {
Artyom Skrobov1a6cd1d2014-02-26 11:27:28 +00008267 return true; // In an assembly source, no need to second-guess
8268}
Benjamin Kramer44a53da2014-04-12 18:45:24 +00008269}
Artyom Skrobov1a6cd1d2014-02-26 11:27:28 +00008270
Tim Northover26bb14e2014-08-18 11:49:42 +00008271static const char *getSubtargetFeatureName(uint64_t Val);
David Blaikie960ea3f2014-06-08 16:18:35 +00008272bool ARMAsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
8273 OperandVector &Operands,
Tim Northover26bb14e2014-08-18 11:49:42 +00008274 MCStreamer &Out, uint64_t &ErrorInfo,
David Blaikie960ea3f2014-06-08 16:18:35 +00008275 bool MatchingInlineAsm) {
Chris Lattner9487de62010-10-28 21:28:01 +00008276 MCInst Inst;
Jim Grosbach120a96a2011-08-15 23:03:29 +00008277 unsigned MatchResult;
Weiming Zhao8f56f882012-11-16 21:55:34 +00008278
Chad Rosier2f480a82012-10-12 22:53:36 +00008279 MatchResult = MatchInstructionImpl(Operands, Inst, ErrorInfo,
Chad Rosier49963552012-10-13 00:26:04 +00008280 MatchingInlineAsm);
Kevin Enderby3164a342010-12-09 19:19:43 +00008281 switch (MatchResult) {
Jim Grosbach120a96a2011-08-15 23:03:29 +00008282 default: break;
Chris Lattnerd27b05e2010-10-28 21:41:58 +00008283 case Match_Success:
Jim Grosbachedaa35a2011-07-26 18:25:39 +00008284 // Context sensitive operand constraints aren't handled by the matcher,
8285 // so check them here.
Jim Grosbacha0d34d32011-09-02 23:22:08 +00008286 if (validateInstruction(Inst, Operands)) {
8287 // Still progress the IT block, otherwise one wrong condition causes
8288 // nasty cascading errors.
8289 forwardITPosition();
Jim Grosbachedaa35a2011-07-26 18:25:39 +00008290 return true;
Jim Grosbacha0d34d32011-09-02 23:22:08 +00008291 }
Jim Grosbachedaa35a2011-07-26 18:25:39 +00008292
Amara Emerson52cfb6a2013-10-03 09:31:51 +00008293 { // processInstruction() updates inITBlock state, we need to save it away
8294 bool wasInITBlock = inITBlock();
8295
8296 // Some instructions need post-processing to, for example, tweak which
8297 // encoding is selected. Loop on it while changes happen so the
8298 // individual transformations can chain off each other. E.g.,
8299 // tPOP(r8)->t2LDMIA_UPD(sp,r8)->t2STR_POST(sp,r8)
8300 while (processInstruction(Inst, Operands))
8301 ;
8302
8303 // Only after the instruction is fully processed, we can validate it
8304 if (wasInITBlock && hasV8Ops() && isThumb() &&
Weiming Zhao5930ae62014-01-23 19:55:33 +00008305 !isV8EligibleForIT(&Inst)) {
Amara Emerson52cfb6a2013-10-03 09:31:51 +00008306 Warning(IDLoc, "deprecated instruction in IT block");
8307 }
8308 }
Jim Grosbach8ba76c62011-08-11 17:35:48 +00008309
Jim Grosbacha0d34d32011-09-02 23:22:08 +00008310 // Only move forward at the very end so that everything in validate
8311 // and process gets a consistent answer about whether we're in an IT
8312 // block.
8313 forwardITPosition();
8314
Jim Grosbach82f76d12012-01-25 19:52:01 +00008315 // ITasm is an ARM mode pseudo-instruction that just sets the ITblock and
8316 // doesn't actually encode.
8317 if (Inst.getOpcode() == ARM::ITasm)
8318 return false;
8319
Jim Grosbach5e5eabb2012-01-26 23:20:15 +00008320 Inst.setLoc(IDLoc);
David Woodhousee6c13e42014-01-28 23:12:42 +00008321 Out.EmitInstruction(Inst, STI);
Chris Lattner9487de62010-10-28 21:28:01 +00008322 return false;
Jim Grosbach5117ef72012-04-24 22:40:08 +00008323 case Match_MissingFeature: {
8324 assert(ErrorInfo && "Unknown missing feature!");
8325 // Special case the error message for the very common case where only
8326 // a single subtarget feature is missing (Thumb vs. ARM, e.g.).
8327 std::string Msg = "instruction requires:";
Tim Northover26bb14e2014-08-18 11:49:42 +00008328 uint64_t Mask = 1;
Jim Grosbach5117ef72012-04-24 22:40:08 +00008329 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
8330 if (ErrorInfo & Mask) {
8331 Msg += " ";
8332 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
8333 }
8334 Mask <<= 1;
8335 }
8336 return Error(IDLoc, Msg);
8337 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00008338 case Match_InvalidOperand: {
8339 SMLoc ErrorLoc = IDLoc;
Tim Northover26bb14e2014-08-18 11:49:42 +00008340 if (ErrorInfo != ~0ULL) {
Chris Lattnerd27b05e2010-10-28 21:41:58 +00008341 if (ErrorInfo >= Operands.size())
8342 return Error(IDLoc, "too few operands for instruction");
Jim Grosbach624bcc72010-10-29 14:46:02 +00008343
David Blaikie960ea3f2014-06-08 16:18:35 +00008344 ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc();
Chris Lattnerd27b05e2010-10-28 21:41:58 +00008345 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
8346 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00008347
Chris Lattnerd27b05e2010-10-28 21:41:58 +00008348 return Error(ErrorLoc, "invalid operand for instruction");
Chris Lattner9487de62010-10-28 21:28:01 +00008349 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00008350 case Match_MnemonicFail:
Benjamin Kramer673824b2012-04-15 17:04:27 +00008351 return Error(IDLoc, "invalid instruction",
David Blaikie960ea3f2014-06-08 16:18:35 +00008352 ((ARMOperand &)*Operands[0]).getLocRange());
Jim Grosbached16ec42011-08-29 22:24:09 +00008353 case Match_RequiresNotITBlock:
8354 return Error(IDLoc, "flag setting instruction only valid outside IT block");
Jim Grosbach3e941ae2011-08-16 20:45:50 +00008355 case Match_RequiresITBlock:
8356 return Error(IDLoc, "instruction only valid inside IT block");
Jim Grosbachb7fa2c02011-08-16 22:20:01 +00008357 case Match_RequiresV6:
8358 return Error(IDLoc, "instruction variant requires ARMv6 or later");
8359 case Match_RequiresThumb2:
8360 return Error(IDLoc, "instruction variant requires Thumb2");
Jim Grosbach087affe2012-06-22 23:56:48 +00008361 case Match_ImmRange0_15: {
David Blaikie960ea3f2014-06-08 16:18:35 +00008362 SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc();
Jim Grosbach087affe2012-06-22 23:56:48 +00008363 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
8364 return Error(ErrorLoc, "immediate operand must be in the range [0,15]");
8365 }
Artyom Skrobovfc12e702013-10-23 10:14:40 +00008366 case Match_ImmRange0_239: {
David Blaikie960ea3f2014-06-08 16:18:35 +00008367 SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getStartLoc();
Artyom Skrobovfc12e702013-10-23 10:14:40 +00008368 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
8369 return Error(ErrorLoc, "immediate operand must be in the range [0,239]");
8370 }
Kevin Enderby488f20b2014-04-10 20:18:58 +00008371 case Match_AlignedMemoryRequiresNone:
8372 case Match_DupAlignedMemoryRequiresNone:
8373 case Match_AlignedMemoryRequires16:
8374 case Match_DupAlignedMemoryRequires16:
8375 case Match_AlignedMemoryRequires32:
8376 case Match_DupAlignedMemoryRequires32:
8377 case Match_AlignedMemoryRequires64:
8378 case Match_DupAlignedMemoryRequires64:
8379 case Match_AlignedMemoryRequires64or128:
8380 case Match_DupAlignedMemoryRequires64or128:
8381 case Match_AlignedMemoryRequires64or128or256:
8382 {
David Blaikie960ea3f2014-06-08 16:18:35 +00008383 SMLoc ErrorLoc = ((ARMOperand &)*Operands[ErrorInfo]).getAlignmentLoc();
Kevin Enderby488f20b2014-04-10 20:18:58 +00008384 if (ErrorLoc == SMLoc()) ErrorLoc = IDLoc;
8385 switch (MatchResult) {
8386 default:
8387 llvm_unreachable("Missing Match_Aligned type");
8388 case Match_AlignedMemoryRequiresNone:
8389 case Match_DupAlignedMemoryRequiresNone:
8390 return Error(ErrorLoc, "alignment must be omitted");
8391 case Match_AlignedMemoryRequires16:
8392 case Match_DupAlignedMemoryRequires16:
8393 return Error(ErrorLoc, "alignment must be 16 or omitted");
8394 case Match_AlignedMemoryRequires32:
8395 case Match_DupAlignedMemoryRequires32:
8396 return Error(ErrorLoc, "alignment must be 32 or omitted");
8397 case Match_AlignedMemoryRequires64:
8398 case Match_DupAlignedMemoryRequires64:
8399 return Error(ErrorLoc, "alignment must be 64 or omitted");
8400 case Match_AlignedMemoryRequires64or128:
8401 case Match_DupAlignedMemoryRequires64or128:
8402 return Error(ErrorLoc, "alignment must be 64, 128 or omitted");
8403 case Match_AlignedMemoryRequires64or128or256:
8404 return Error(ErrorLoc, "alignment must be 64, 128, 256 or omitted");
8405 }
8406 }
Chris Lattnerd27b05e2010-10-28 21:41:58 +00008407 }
Jim Grosbach624bcc72010-10-29 14:46:02 +00008408
Eric Christopher91d7b902010-10-29 09:26:59 +00008409 llvm_unreachable("Implement any new match types added!");
Chris Lattner9487de62010-10-28 21:28:01 +00008410}
8411
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008412/// parseDirective parses the arm specific directives
Kevin Enderbyccab3172009-09-15 00:27:25 +00008413bool ARMAsmParser::ParseDirective(AsmToken DirectiveID) {
Saleem Abdulrasooldd979e62014-04-05 22:09:51 +00008414 const MCObjectFileInfo::Environment Format =
8415 getContext().getObjectFileInfo()->getObjectFileType();
8416 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Saleem Abdulrasoolbfdfb142014-09-18 04:28:29 +00008417 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Saleem Abdulrasooldd979e62014-04-05 22:09:51 +00008418
Kevin Enderbyccab3172009-09-15 00:27:25 +00008419 StringRef IDVal = DirectiveID.getIdentifier();
8420 if (IDVal == ".word")
Saleem Abdulrasool38976512014-02-23 06:22:09 +00008421 return parseLiteralValues(4, DirectiveID.getLoc());
8422 else if (IDVal == ".short" || IDVal == ".hword")
8423 return parseLiteralValues(2, DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00008424 else if (IDVal == ".thumb")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008425 return parseDirectiveThumb(DirectiveID.getLoc());
Jim Grosbach7f882392011-12-07 18:04:19 +00008426 else if (IDVal == ".arm")
8427 return parseDirectiveARM(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00008428 else if (IDVal == ".thumb_func")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008429 return parseDirectiveThumbFunc(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00008430 else if (IDVal == ".code")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008431 return parseDirectiveCode(DirectiveID.getLoc());
Kevin Enderby146dcf22009-10-15 20:48:48 +00008432 else if (IDVal == ".syntax")
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008433 return parseDirectiveSyntax(DirectiveID.getLoc());
Jim Grosbachab5830e2011-12-14 02:16:11 +00008434 else if (IDVal == ".unreq")
8435 return parseDirectiveUnreq(DirectiveID.getLoc());
Logan Chien4ea23b52013-05-10 16:17:24 +00008436 else if (IDVal == ".fnend")
8437 return parseDirectiveFnEnd(DirectiveID.getLoc());
8438 else if (IDVal == ".cantunwind")
8439 return parseDirectiveCantUnwind(DirectiveID.getLoc());
8440 else if (IDVal == ".personality")
8441 return parseDirectivePersonality(DirectiveID.getLoc());
8442 else if (IDVal == ".handlerdata")
8443 return parseDirectiveHandlerData(DirectiveID.getLoc());
8444 else if (IDVal == ".setfp")
8445 return parseDirectiveSetFP(DirectiveID.getLoc());
8446 else if (IDVal == ".pad")
8447 return parseDirectivePad(DirectiveID.getLoc());
8448 else if (IDVal == ".save")
8449 return parseDirectiveRegSave(DirectiveID.getLoc(), false);
8450 else if (IDVal == ".vsave")
8451 return parseDirectiveRegSave(DirectiveID.getLoc(), true);
Saleem Abdulrasool6e6c2392013-12-20 07:21:16 +00008452 else if (IDVal == ".ltorg" || IDVal == ".pool")
David Peixotto80c083a2013-12-19 18:26:07 +00008453 return parseDirectiveLtorg(DirectiveID.getLoc());
Saleem Abdulrasoola5549682013-12-26 01:52:28 +00008454 else if (IDVal == ".even")
8455 return parseDirectiveEven(DirectiveID.getLoc());
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +00008456 else if (IDVal == ".personalityindex")
8457 return parseDirectivePersonalityIndex(DirectiveID.getLoc());
Saleem Abdulrasoold9f08602014-01-21 02:33:10 +00008458 else if (IDVal == ".unwind_raw")
8459 return parseDirectiveUnwindRaw(DirectiveID.getLoc());
Saleem Abdulrasool5d962d32014-01-30 04:46:24 +00008460 else if (IDVal == ".movsp")
8461 return parseDirectiveMovSP(DirectiveID.getLoc());
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00008462 else if (IDVal == ".arch_extension")
8463 return parseDirectiveArchExtension(DirectiveID.getLoc());
Saleem Abdulrasoolfd6ed1e2014-02-23 17:45:32 +00008464 else if (IDVal == ".align")
8465 return parseDirectiveAlign(DirectiveID.getLoc());
Saleem Abdulrasool39f773f2014-03-20 06:05:33 +00008466 else if (IDVal == ".thumb_set")
8467 return parseDirectiveThumbSet(DirectiveID.getLoc());
Saleem Abdulrasooldd979e62014-04-05 22:09:51 +00008468
Saleem Abdulrasoolbfdfb142014-09-18 04:28:29 +00008469 if (!IsMachO && !IsCOFF) {
Saleem Abdulrasooldd979e62014-04-05 22:09:51 +00008470 if (IDVal == ".arch")
8471 return parseDirectiveArch(DirectiveID.getLoc());
8472 else if (IDVal == ".cpu")
8473 return parseDirectiveCPU(DirectiveID.getLoc());
8474 else if (IDVal == ".eabi_attribute")
8475 return parseDirectiveEabiAttr(DirectiveID.getLoc());
8476 else if (IDVal == ".fpu")
8477 return parseDirectiveFPU(DirectiveID.getLoc());
8478 else if (IDVal == ".fnstart")
8479 return parseDirectiveFnStart(DirectiveID.getLoc());
8480 else if (IDVal == ".inst")
8481 return parseDirectiveInst(DirectiveID.getLoc());
8482 else if (IDVal == ".inst.n")
8483 return parseDirectiveInst(DirectiveID.getLoc(), 'n');
8484 else if (IDVal == ".inst.w")
8485 return parseDirectiveInst(DirectiveID.getLoc(), 'w');
8486 else if (IDVal == ".object_arch")
8487 return parseDirectiveObjectArch(DirectiveID.getLoc());
8488 else if (IDVal == ".tlsdescseq")
8489 return parseDirectiveTLSDescSeq(DirectiveID.getLoc());
8490 }
8491
Kevin Enderbyccab3172009-09-15 00:27:25 +00008492 return true;
8493}
8494
Saleem Abdulrasool38976512014-02-23 06:22:09 +00008495/// parseLiteralValues
8496/// ::= .hword expression [, expression]*
8497/// ::= .short expression [, expression]*
8498/// ::= .word expression [, expression]*
8499bool ARMAsmParser::parseLiteralValues(unsigned Size, SMLoc L) {
Kevin Enderbyccab3172009-09-15 00:27:25 +00008500 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8501 for (;;) {
8502 const MCExpr *Value;
Saleem Abdulrasoola9036612014-01-26 22:29:50 +00008503 if (getParser().parseExpression(Value)) {
8504 Parser.eatToEndOfStatement();
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008505 return false;
Saleem Abdulrasoola9036612014-01-26 22:29:50 +00008506 }
Kevin Enderbyccab3172009-09-15 00:27:25 +00008507
Eric Christopherbf7bc492013-01-09 03:52:05 +00008508 getParser().getStreamer().EmitValue(Value, Size);
Kevin Enderbyccab3172009-09-15 00:27:25 +00008509
8510 if (getLexer().is(AsmToken::EndOfStatement))
8511 break;
Jim Grosbach624bcc72010-10-29 14:46:02 +00008512
Kevin Enderbyccab3172009-09-15 00:27:25 +00008513 // FIXME: Improve diagnostic.
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008514 if (getLexer().isNot(AsmToken::Comma)) {
8515 Error(L, "unexpected token in directive");
8516 return false;
8517 }
Sean Callanana83fd7d2010-01-19 20:27:46 +00008518 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00008519 }
8520 }
8521
Sean Callanana83fd7d2010-01-19 20:27:46 +00008522 Parser.Lex();
Kevin Enderbyccab3172009-09-15 00:27:25 +00008523 return false;
8524}
8525
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008526/// parseDirectiveThumb
Kevin Enderby146dcf22009-10-15 20:48:48 +00008527/// ::= .thumb
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008528bool ARMAsmParser::parseDirectiveThumb(SMLoc L) {
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008529 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8530 Error(L, "unexpected token in directive");
8531 return false;
8532 }
Sean Callanana83fd7d2010-01-19 20:27:46 +00008533 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00008534
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008535 if (!hasThumb()) {
8536 Error(L, "target does not support Thumb mode");
8537 return false;
8538 }
Tim Northovera2292d02013-06-10 23:20:58 +00008539
Jim Grosbach7f882392011-12-07 18:04:19 +00008540 if (!isThumb())
8541 SwitchMode();
Saleem Abdulrasool44419fc2014-03-22 19:26:18 +00008542
Jim Grosbach7f882392011-12-07 18:04:19 +00008543 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
8544 return false;
8545}
8546
8547/// parseDirectiveARM
8548/// ::= .arm
8549bool ARMAsmParser::parseDirectiveARM(SMLoc L) {
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008550 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8551 Error(L, "unexpected token in directive");
8552 return false;
8553 }
Jim Grosbach7f882392011-12-07 18:04:19 +00008554 Parser.Lex();
8555
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008556 if (!hasARM()) {
8557 Error(L, "target does not support ARM mode");
8558 return false;
8559 }
Tim Northovera2292d02013-06-10 23:20:58 +00008560
Jim Grosbach7f882392011-12-07 18:04:19 +00008561 if (isThumb())
8562 SwitchMode();
Saleem Abdulrasool44419fc2014-03-22 19:26:18 +00008563
Jim Grosbach7f882392011-12-07 18:04:19 +00008564 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Kevin Enderby146dcf22009-10-15 20:48:48 +00008565 return false;
8566}
8567
Tim Northover1744d0a2013-10-25 12:49:50 +00008568void ARMAsmParser::onLabelParsed(MCSymbol *Symbol) {
8569 if (NextSymbolIsThumb) {
8570 getParser().getStreamer().EmitThumbFunc(Symbol);
8571 NextSymbolIsThumb = false;
8572 }
8573}
8574
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008575/// parseDirectiveThumbFunc
Kevin Enderby146dcf22009-10-15 20:48:48 +00008576/// ::= .thumbfunc symbol_name
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008577bool ARMAsmParser::parseDirectiveThumbFunc(SMLoc L) {
Saleem Abdulrasool8c61c6c2014-09-18 03:49:55 +00008578 const auto Format = getContext().getObjectFileInfo()->getObjectFileType();
8579 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00008580
Jim Grosbach1152cc02011-12-21 22:30:16 +00008581 // Darwin asm has (optionally) function name after .thumb_func direction
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00008582 // ELF doesn't
Saleem Abdulrasool8c61c6c2014-09-18 03:49:55 +00008583 if (IsMachO) {
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00008584 const AsmToken &Tok = Parser.getTok();
Jim Grosbach1152cc02011-12-21 22:30:16 +00008585 if (Tok.isNot(AsmToken::EndOfStatement)) {
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008586 if (Tok.isNot(AsmToken::Identifier) && Tok.isNot(AsmToken::String)) {
8587 Error(L, "unexpected token in .thumb_func directive");
8588 return false;
8589 }
8590
Tim Northover1744d0a2013-10-25 12:49:50 +00008591 MCSymbol *Func =
8592 getParser().getContext().GetOrCreateSymbol(Tok.getIdentifier());
8593 getParser().getStreamer().EmitThumbFunc(Func);
Jim Grosbach1152cc02011-12-21 22:30:16 +00008594 Parser.Lex(); // Consume the identifier token.
Tim Northover1744d0a2013-10-25 12:49:50 +00008595 return false;
Jim Grosbach1152cc02011-12-21 22:30:16 +00008596 }
Rafael Espindolae90c1cb2011-05-16 16:17:21 +00008597 }
8598
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008599 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Saleem Abdulrasool8c61c6c2014-09-18 03:49:55 +00008600 Error(Parser.getTok().getLoc(), "unexpected token in directive");
8601 Parser.eatToEndOfStatement();
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008602 return false;
8603 }
Jim Grosbach1152cc02011-12-21 22:30:16 +00008604
Tim Northover1744d0a2013-10-25 12:49:50 +00008605 NextSymbolIsThumb = true;
Kevin Enderby146dcf22009-10-15 20:48:48 +00008606 return false;
8607}
8608
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008609/// parseDirectiveSyntax
Kevin Enderby146dcf22009-10-15 20:48:48 +00008610/// ::= .syntax unified | divided
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008611bool ARMAsmParser::parseDirectiveSyntax(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00008612 const AsmToken &Tok = Parser.getTok();
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008613 if (Tok.isNot(AsmToken::Identifier)) {
8614 Error(L, "unexpected token in .syntax directive");
8615 return false;
8616 }
8617
Benjamin Kramer92d89982010-07-14 22:38:02 +00008618 StringRef Mode = Tok.getString();
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008619 if (Mode == "unified" || Mode == "UNIFIED") {
Sean Callanana83fd7d2010-01-19 20:27:46 +00008620 Parser.Lex();
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00008621 } else if (Mode == "divided" || Mode == "DIVIDED") {
8622 Error(L, "'.syntax divided' arm asssembly not supported");
8623 return false;
8624 } else {
8625 Error(L, "unrecognized syntax mode in .syntax directive");
8626 return false;
8627 }
Kevin Enderby146dcf22009-10-15 20:48:48 +00008628
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008629 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8630 Error(Parser.getTok().getLoc(), "unexpected token in directive");
8631 return false;
8632 }
Sean Callanana83fd7d2010-01-19 20:27:46 +00008633 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00008634
8635 // TODO tell the MC streamer the mode
8636 // getParser().getStreamer().Emit???();
8637 return false;
8638}
8639
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008640/// parseDirectiveCode
Kevin Enderby146dcf22009-10-15 20:48:48 +00008641/// ::= .code 16 | 32
Jim Grosbacheab1c0d2011-07-26 17:10:22 +00008642bool ARMAsmParser::parseDirectiveCode(SMLoc L) {
Sean Callanan936b0d32010-01-19 21:44:56 +00008643 const AsmToken &Tok = Parser.getTok();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008644 if (Tok.isNot(AsmToken::Integer)) {
8645 Error(L, "unexpected token in .code directive");
8646 return false;
8647 }
Sean Callanan936b0d32010-01-19 21:44:56 +00008648 int64_t Val = Parser.getTok().getIntVal();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008649 if (Val != 16 && Val != 32) {
8650 Error(L, "invalid operand to .code directive");
8651 return false;
8652 }
8653 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00008654
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008655 if (getLexer().isNot(AsmToken::EndOfStatement)) {
8656 Error(Parser.getTok().getLoc(), "unexpected token in directive");
8657 return false;
8658 }
Sean Callanana83fd7d2010-01-19 20:27:46 +00008659 Parser.Lex();
Kevin Enderby146dcf22009-10-15 20:48:48 +00008660
Evan Cheng284b4672011-07-08 22:36:29 +00008661 if (Val == 16) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008662 if (!hasThumb()) {
8663 Error(L, "target does not support Thumb mode");
8664 return false;
8665 }
Tim Northovera2292d02013-06-10 23:20:58 +00008666
Jim Grosbachf471ac32011-09-06 18:46:23 +00008667 if (!isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00008668 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00008669 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code16);
Evan Cheng284b4672011-07-08 22:36:29 +00008670 } else {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008671 if (!hasARM()) {
8672 Error(L, "target does not support ARM mode");
8673 return false;
8674 }
Tim Northovera2292d02013-06-10 23:20:58 +00008675
Jim Grosbachf471ac32011-09-06 18:46:23 +00008676 if (isThumb())
Evan Cheng91111d22011-07-09 05:47:46 +00008677 SwitchMode();
Jim Grosbachf471ac32011-09-06 18:46:23 +00008678 getParser().getStreamer().EmitAssemblerFlag(MCAF_Code32);
Evan Cheng45543ba2011-07-08 22:49:55 +00008679 }
Jim Grosbach2db0ea02010-11-05 22:40:53 +00008680
Kevin Enderby146dcf22009-10-15 20:48:48 +00008681 return false;
8682}
8683
Jim Grosbachab5830e2011-12-14 02:16:11 +00008684/// parseDirectiveReq
8685/// ::= name .req registername
8686bool ARMAsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
8687 Parser.Lex(); // Eat the '.req' token.
8688 unsigned Reg;
8689 SMLoc SRegLoc, ERegLoc;
8690 if (ParseRegister(Reg, SRegLoc, ERegLoc)) {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00008691 Parser.eatToEndOfStatement();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008692 Error(SRegLoc, "register name expected");
8693 return false;
Jim Grosbachab5830e2011-12-14 02:16:11 +00008694 }
8695
8696 // Shouldn't be anything else.
8697 if (Parser.getTok().isNot(AsmToken::EndOfStatement)) {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00008698 Parser.eatToEndOfStatement();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008699 Error(Parser.getTok().getLoc(), "unexpected input in .req directive.");
8700 return false;
Jim Grosbachab5830e2011-12-14 02:16:11 +00008701 }
8702
8703 Parser.Lex(); // Consume the EndOfStatement
8704
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008705 if (RegisterReqs.GetOrCreateValue(Name, Reg).getValue() != Reg) {
8706 Error(SRegLoc, "redefinition of '" + Name + "' does not match original.");
8707 return false;
8708 }
Jim Grosbachab5830e2011-12-14 02:16:11 +00008709
8710 return false;
8711}
8712
8713/// parseDirectiveUneq
8714/// ::= .unreq registername
8715bool ARMAsmParser::parseDirectiveUnreq(SMLoc L) {
8716 if (Parser.getTok().isNot(AsmToken::Identifier)) {
Jim Grosbachd2037eb2013-02-20 22:21:35 +00008717 Parser.eatToEndOfStatement();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008718 Error(L, "unexpected input in .unreq directive.");
8719 return false;
Jim Grosbachab5830e2011-12-14 02:16:11 +00008720 }
Duncan P. N. Exon Smith29db0eb2014-03-07 16:16:52 +00008721 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
Jim Grosbachab5830e2011-12-14 02:16:11 +00008722 Parser.Lex(); // Eat the identifier.
8723 return false;
8724}
8725
Jason W Kim135d2442011-12-20 17:38:12 +00008726/// parseDirectiveArch
8727/// ::= .arch token
8728bool ARMAsmParser::parseDirectiveArch(SMLoc L) {
Logan Chien439e8f92013-12-11 17:16:25 +00008729 StringRef Arch = getParser().parseStringToEndOfStatement().trim();
8730
8731 unsigned ID = StringSwitch<unsigned>(Arch)
8732#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
8733 .Case(NAME, ARM::ID)
Joerg Sonnenbergera13f8b42013-12-26 11:50:28 +00008734#define ARM_ARCH_ALIAS(NAME, ID) \
8735 .Case(NAME, ARM::ID)
Logan Chien439e8f92013-12-11 17:16:25 +00008736#include "MCTargetDesc/ARMArchName.def"
8737 .Default(ARM::INVALID_ARCH);
8738
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008739 if (ID == ARM::INVALID_ARCH) {
8740 Error(L, "Unknown arch name");
8741 return false;
8742 }
Logan Chien439e8f92013-12-11 17:16:25 +00008743
8744 getTargetStreamer().emitArch(ID);
8745 return false;
Jason W Kim135d2442011-12-20 17:38:12 +00008746}
8747
8748/// parseDirectiveEabiAttr
Saleem Abdulrasool87ccd362014-01-07 02:28:42 +00008749/// ::= .eabi_attribute int, int [, "str"]
8750/// ::= .eabi_attribute Tag_name, int [, "str"]
Jason W Kim135d2442011-12-20 17:38:12 +00008751bool ARMAsmParser::parseDirectiveEabiAttr(SMLoc L) {
Saleem Abdulrasool87ccd362014-01-07 02:28:42 +00008752 int64_t Tag;
8753 SMLoc TagLoc;
Saleem Abdulrasool87ccd362014-01-07 02:28:42 +00008754 TagLoc = Parser.getTok().getLoc();
8755 if (Parser.getTok().is(AsmToken::Identifier)) {
8756 StringRef Name = Parser.getTok().getIdentifier();
8757 Tag = ARMBuildAttrs::AttrTypeFromString(Name);
8758 if (Tag == -1) {
8759 Error(TagLoc, "attribute name not recognised: " + Name);
8760 Parser.eatToEndOfStatement();
8761 return false;
8762 }
8763 Parser.Lex();
8764 } else {
8765 const MCExpr *AttrExpr;
8766
8767 TagLoc = Parser.getTok().getLoc();
8768 if (Parser.parseExpression(AttrExpr)) {
8769 Parser.eatToEndOfStatement();
8770 return false;
8771 }
8772
8773 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(AttrExpr);
8774 if (!CE) {
8775 Error(TagLoc, "expected numeric constant");
8776 Parser.eatToEndOfStatement();
8777 return false;
8778 }
8779
8780 Tag = CE->getValue();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008781 }
Logan Chien8cbb80d2013-10-28 17:51:12 +00008782
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008783 if (Parser.getTok().isNot(AsmToken::Comma)) {
Saleem Abdulrasool87ccd362014-01-07 02:28:42 +00008784 Error(Parser.getTok().getLoc(), "comma expected");
8785 Parser.eatToEndOfStatement();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008786 return false;
8787 }
Logan Chien8cbb80d2013-10-28 17:51:12 +00008788 Parser.Lex(); // skip comma
8789
Saleem Abdulrasool87ccd362014-01-07 02:28:42 +00008790 StringRef StringValue = "";
8791 bool IsStringValue = false;
Logan Chien8cbb80d2013-10-28 17:51:12 +00008792
Saleem Abdulrasool87ccd362014-01-07 02:28:42 +00008793 int64_t IntegerValue = 0;
8794 bool IsIntegerValue = false;
8795
8796 if (Tag == ARMBuildAttrs::CPU_raw_name || Tag == ARMBuildAttrs::CPU_name)
8797 IsStringValue = true;
8798 else if (Tag == ARMBuildAttrs::compatibility) {
8799 IsStringValue = true;
8800 IsIntegerValue = true;
Saleem Abdulrasool9dedf642014-01-19 08:25:19 +00008801 } else if (Tag < 32 || Tag % 2 == 0)
Saleem Abdulrasool87ccd362014-01-07 02:28:42 +00008802 IsIntegerValue = true;
8803 else if (Tag % 2 == 1)
8804 IsStringValue = true;
8805 else
8806 llvm_unreachable("invalid tag type");
8807
8808 if (IsIntegerValue) {
8809 const MCExpr *ValueExpr;
8810 SMLoc ValueExprLoc = Parser.getTok().getLoc();
8811 if (Parser.parseExpression(ValueExpr)) {
8812 Parser.eatToEndOfStatement();
8813 return false;
8814 }
8815
8816 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(ValueExpr);
8817 if (!CE) {
8818 Error(ValueExprLoc, "expected numeric constant");
8819 Parser.eatToEndOfStatement();
8820 return false;
8821 }
8822
8823 IntegerValue = CE->getValue();
8824 }
8825
8826 if (Tag == ARMBuildAttrs::compatibility) {
8827 if (Parser.getTok().isNot(AsmToken::Comma))
8828 IsStringValue = false;
8829 else
8830 Parser.Lex();
8831 }
8832
8833 if (IsStringValue) {
8834 if (Parser.getTok().isNot(AsmToken::String)) {
8835 Error(Parser.getTok().getLoc(), "bad string constant");
8836 Parser.eatToEndOfStatement();
8837 return false;
8838 }
8839
8840 StringValue = Parser.getTok().getStringContents();
8841 Parser.Lex();
8842 }
8843
8844 if (IsIntegerValue && IsStringValue) {
8845 assert(Tag == ARMBuildAttrs::compatibility);
8846 getTargetStreamer().emitIntTextAttribute(Tag, IntegerValue, StringValue);
8847 } else if (IsIntegerValue)
8848 getTargetStreamer().emitAttribute(Tag, IntegerValue);
8849 else if (IsStringValue)
8850 getTargetStreamer().emitTextAttribute(Tag, StringValue);
Logan Chien8cbb80d2013-10-28 17:51:12 +00008851 return false;
8852}
8853
8854/// parseDirectiveCPU
8855/// ::= .cpu str
8856bool ARMAsmParser::parseDirectiveCPU(SMLoc L) {
8857 StringRef CPU = getParser().parseStringToEndOfStatement().trim();
8858 getTargetStreamer().emitTextAttribute(ARMBuildAttrs::CPU_name, CPU);
8859 return false;
8860}
8861
Nico Weberae050bb2014-08-16 05:37:51 +00008862// FIXME: This is duplicated in getARMFPUFeatures() in
8863// tools/clang/lib/Driver/Tools.cpp
8864static const struct {
8865 const unsigned Fpu;
8866 const uint64_t Enabled;
8867 const uint64_t Disabled;
8868} Fpus[] = {
8869 {ARM::VFP, ARM::FeatureVFP2, ARM::FeatureNEON},
8870 {ARM::VFPV2, ARM::FeatureVFP2, ARM::FeatureNEON},
8871 {ARM::VFPV3, ARM::FeatureVFP3, ARM::FeatureNEON},
8872 {ARM::VFPV3_D16, ARM::FeatureVFP3 | ARM::FeatureD16, ARM::FeatureNEON},
8873 {ARM::VFPV4, ARM::FeatureVFP4, ARM::FeatureNEON},
8874 {ARM::VFPV4_D16, ARM::FeatureVFP4 | ARM::FeatureD16, ARM::FeatureNEON},
Oliver Stannard37e4daa2014-10-01 09:02:17 +00008875 {ARM::FPV5_D16, ARM::FeatureFPARMv8 | ARM::FeatureD16,
8876 ARM::FeatureNEON | ARM::FeatureCrypto},
Nico Weberae050bb2014-08-16 05:37:51 +00008877 {ARM::FP_ARMV8, ARM::FeatureFPARMv8,
8878 ARM::FeatureNEON | ARM::FeatureCrypto},
8879 {ARM::NEON, ARM::FeatureNEON, 0},
8880 {ARM::NEON_VFPV4, ARM::FeatureVFP4 | ARM::FeatureNEON, 0},
8881 {ARM::NEON_FP_ARMV8, ARM::FeatureFPARMv8 | ARM::FeatureNEON,
8882 ARM::FeatureCrypto},
8883 {ARM::CRYPTO_NEON_FP_ARMV8,
8884 ARM::FeatureFPARMv8 | ARM::FeatureNEON | ARM::FeatureCrypto, 0},
8885 {ARM::SOFTVFP, 0, 0},
8886};
8887
Logan Chien8cbb80d2013-10-28 17:51:12 +00008888/// parseDirectiveFPU
8889/// ::= .fpu str
8890bool ARMAsmParser::parseDirectiveFPU(SMLoc L) {
8891 StringRef FPU = getParser().parseStringToEndOfStatement().trim();
8892
8893 unsigned ID = StringSwitch<unsigned>(FPU)
8894#define ARM_FPU_NAME(NAME, ID) .Case(NAME, ARM::ID)
8895#include "ARMFPUName.def"
8896 .Default(ARM::INVALID_FPU);
8897
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008898 if (ID == ARM::INVALID_FPU) {
8899 Error(L, "Unknown FPU name");
8900 return false;
8901 }
Logan Chien8cbb80d2013-10-28 17:51:12 +00008902
Nico Weberae050bb2014-08-16 05:37:51 +00008903 for (const auto &Fpu : Fpus) {
8904 if (Fpu.Fpu != ID)
8905 continue;
8906
8907 // Need to toggle features that should be on but are off and that
8908 // should off but are on.
Tim Northover26bb14e2014-08-18 11:49:42 +00008909 uint64_t Toggle = (Fpu.Enabled & ~STI.getFeatureBits()) |
Nico Weberae050bb2014-08-16 05:37:51 +00008910 (Fpu.Disabled & STI.getFeatureBits());
8911 setAvailableFeatures(ComputeAvailableFeatures(STI.ToggleFeature(Toggle)));
8912 break;
8913 }
8914
Logan Chien8cbb80d2013-10-28 17:51:12 +00008915 getTargetStreamer().emitFPU(ID);
8916 return false;
Jason W Kim135d2442011-12-20 17:38:12 +00008917}
8918
Logan Chien4ea23b52013-05-10 16:17:24 +00008919/// parseDirectiveFnStart
8920/// ::= .fnstart
8921bool ARMAsmParser::parseDirectiveFnStart(SMLoc L) {
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008922 if (UC.hasFnStart()) {
Logan Chien4ea23b52013-05-10 16:17:24 +00008923 Error(L, ".fnstart starts before the end of previous one");
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008924 UC.emitFnStartLocNotes();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008925 return false;
Logan Chien4ea23b52013-05-10 16:17:24 +00008926 }
8927
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +00008928 // Reset the unwind directives parser state
8929 UC.reset();
8930
Rafael Espindolaa17151a2013-10-08 13:08:17 +00008931 getTargetStreamer().emitFnStart();
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008932
8933 UC.recordFnStart(L);
Logan Chien4ea23b52013-05-10 16:17:24 +00008934 return false;
8935}
8936
8937/// parseDirectiveFnEnd
8938/// ::= .fnend
8939bool ARMAsmParser::parseDirectiveFnEnd(SMLoc L) {
8940 // Check the ordering of unwind directives
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008941 if (!UC.hasFnStart()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008942 Error(L, ".fnstart must precede .fnend directive");
8943 return false;
8944 }
Logan Chien4ea23b52013-05-10 16:17:24 +00008945
8946 // Reset the unwind directives parser state
Rafael Espindolaa17151a2013-10-08 13:08:17 +00008947 getTargetStreamer().emitFnEnd();
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008948
8949 UC.reset();
Logan Chien4ea23b52013-05-10 16:17:24 +00008950 return false;
8951}
8952
8953/// parseDirectiveCantUnwind
8954/// ::= .cantunwind
8955bool ARMAsmParser::parseDirectiveCantUnwind(SMLoc L) {
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008956 UC.recordCantUnwind(L);
8957
Logan Chien4ea23b52013-05-10 16:17:24 +00008958 // Check the ordering of unwind directives
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008959 if (!UC.hasFnStart()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008960 Error(L, ".fnstart must precede .cantunwind directive");
8961 return false;
8962 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008963 if (UC.hasHandlerData()) {
Logan Chien4ea23b52013-05-10 16:17:24 +00008964 Error(L, ".cantunwind can't be used with .handlerdata directive");
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008965 UC.emitHandlerDataLocNotes();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008966 return false;
Logan Chien4ea23b52013-05-10 16:17:24 +00008967 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008968 if (UC.hasPersonality()) {
Logan Chien4ea23b52013-05-10 16:17:24 +00008969 Error(L, ".cantunwind can't be used with .personality directive");
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008970 UC.emitPersonalityLocNotes();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008971 return false;
Logan Chien4ea23b52013-05-10 16:17:24 +00008972 }
8973
Rafael Espindolaa17151a2013-10-08 13:08:17 +00008974 getTargetStreamer().emitCantUnwind();
Logan Chien4ea23b52013-05-10 16:17:24 +00008975 return false;
8976}
8977
8978/// parseDirectivePersonality
8979/// ::= .personality name
8980bool ARMAsmParser::parseDirectivePersonality(SMLoc L) {
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +00008981 bool HasExistingPersonality = UC.hasPersonality();
8982
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008983 UC.recordPersonality(L);
8984
Logan Chien4ea23b52013-05-10 16:17:24 +00008985 // Check the ordering of unwind directives
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008986 if (!UC.hasFnStart()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008987 Error(L, ".fnstart must precede .personality directive");
8988 return false;
8989 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008990 if (UC.cantUnwind()) {
Logan Chien4ea23b52013-05-10 16:17:24 +00008991 Error(L, ".personality can't be used with .cantunwind directive");
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008992 UC.emitCantUnwindLocNotes();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008993 return false;
Logan Chien4ea23b52013-05-10 16:17:24 +00008994 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008995 if (UC.hasHandlerData()) {
Logan Chien4ea23b52013-05-10 16:17:24 +00008996 Error(L, ".personality must precede .handlerdata directive");
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00008997 UC.emitHandlerDataLocNotes();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00008998 return false;
Logan Chien4ea23b52013-05-10 16:17:24 +00008999 }
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +00009000 if (HasExistingPersonality) {
9001 Parser.eatToEndOfStatement();
9002 Error(L, "multiple personality directives");
9003 UC.emitPersonalityLocNotes();
9004 return false;
9005 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009006
9007 // Parse the name of the personality routine
9008 if (Parser.getTok().isNot(AsmToken::Identifier)) {
9009 Parser.eatToEndOfStatement();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009010 Error(L, "unexpected input in .personality directive.");
9011 return false;
Logan Chien4ea23b52013-05-10 16:17:24 +00009012 }
9013 StringRef Name(Parser.getTok().getIdentifier());
9014 Parser.Lex();
9015
9016 MCSymbol *PR = getParser().getContext().GetOrCreateSymbol(Name);
Rafael Espindolaa17151a2013-10-08 13:08:17 +00009017 getTargetStreamer().emitPersonality(PR);
Logan Chien4ea23b52013-05-10 16:17:24 +00009018 return false;
9019}
9020
9021/// parseDirectiveHandlerData
9022/// ::= .handlerdata
9023bool ARMAsmParser::parseDirectiveHandlerData(SMLoc L) {
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009024 UC.recordHandlerData(L);
9025
Logan Chien4ea23b52013-05-10 16:17:24 +00009026 // Check the ordering of unwind directives
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009027 if (!UC.hasFnStart()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009028 Error(L, ".fnstart must precede .personality directive");
9029 return false;
9030 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009031 if (UC.cantUnwind()) {
Logan Chien4ea23b52013-05-10 16:17:24 +00009032 Error(L, ".handlerdata can't be used with .cantunwind directive");
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009033 UC.emitCantUnwindLocNotes();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009034 return false;
Logan Chien4ea23b52013-05-10 16:17:24 +00009035 }
9036
Rafael Espindolaa17151a2013-10-08 13:08:17 +00009037 getTargetStreamer().emitHandlerData();
Logan Chien4ea23b52013-05-10 16:17:24 +00009038 return false;
9039}
9040
9041/// parseDirectiveSetFP
9042/// ::= .setfp fpreg, spreg [, offset]
9043bool ARMAsmParser::parseDirectiveSetFP(SMLoc L) {
9044 // Check the ordering of unwind directives
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009045 if (!UC.hasFnStart()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009046 Error(L, ".fnstart must precede .setfp directive");
9047 return false;
9048 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009049 if (UC.hasHandlerData()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009050 Error(L, ".setfp must precede .handlerdata directive");
9051 return false;
9052 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009053
9054 // Parse fpreg
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009055 SMLoc FPRegLoc = Parser.getTok().getLoc();
9056 int FPReg = tryParseRegister();
9057 if (FPReg == -1) {
9058 Error(FPRegLoc, "frame pointer register expected");
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009059 return false;
9060 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009061
9062 // Consume comma
Saleem Abdulrasool5d962d32014-01-30 04:46:24 +00009063 if (Parser.getTok().isNot(AsmToken::Comma)) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009064 Error(Parser.getTok().getLoc(), "comma expected");
9065 return false;
9066 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009067 Parser.Lex(); // skip comma
9068
9069 // Parse spreg
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009070 SMLoc SPRegLoc = Parser.getTok().getLoc();
9071 int SPReg = tryParseRegister();
9072 if (SPReg == -1) {
9073 Error(SPRegLoc, "stack pointer register expected");
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009074 return false;
9075 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009076
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009077 if (SPReg != ARM::SP && SPReg != UC.getFPReg()) {
9078 Error(SPRegLoc, "register should be either $sp or the latest fp register");
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009079 return false;
9080 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009081
9082 // Update the frame pointer register
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009083 UC.saveFPReg(FPReg);
Logan Chien4ea23b52013-05-10 16:17:24 +00009084
9085 // Parse offset
9086 int64_t Offset = 0;
9087 if (Parser.getTok().is(AsmToken::Comma)) {
9088 Parser.Lex(); // skip comma
9089
9090 if (Parser.getTok().isNot(AsmToken::Hash) &&
9091 Parser.getTok().isNot(AsmToken::Dollar)) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009092 Error(Parser.getTok().getLoc(), "'#' expected");
9093 return false;
Logan Chien4ea23b52013-05-10 16:17:24 +00009094 }
9095 Parser.Lex(); // skip hash token.
9096
9097 const MCExpr *OffsetExpr;
9098 SMLoc ExLoc = Parser.getTok().getLoc();
9099 SMLoc EndLoc;
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009100 if (getParser().parseExpression(OffsetExpr, EndLoc)) {
9101 Error(ExLoc, "malformed setfp offset");
9102 return false;
9103 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009104 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009105 if (!CE) {
9106 Error(ExLoc, "setfp offset must be an immediate");
9107 return false;
9108 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009109
9110 Offset = CE->getValue();
9111 }
9112
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009113 getTargetStreamer().emitSetFP(static_cast<unsigned>(FPReg),
9114 static_cast<unsigned>(SPReg), Offset);
Logan Chien4ea23b52013-05-10 16:17:24 +00009115 return false;
9116}
9117
9118/// parseDirective
9119/// ::= .pad offset
9120bool ARMAsmParser::parseDirectivePad(SMLoc L) {
9121 // Check the ordering of unwind directives
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009122 if (!UC.hasFnStart()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009123 Error(L, ".fnstart must precede .pad directive");
9124 return false;
9125 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009126 if (UC.hasHandlerData()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009127 Error(L, ".pad must precede .handlerdata directive");
9128 return false;
9129 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009130
9131 // Parse the offset
9132 if (Parser.getTok().isNot(AsmToken::Hash) &&
9133 Parser.getTok().isNot(AsmToken::Dollar)) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009134 Error(Parser.getTok().getLoc(), "'#' expected");
9135 return false;
Logan Chien4ea23b52013-05-10 16:17:24 +00009136 }
9137 Parser.Lex(); // skip hash token.
9138
9139 const MCExpr *OffsetExpr;
9140 SMLoc ExLoc = Parser.getTok().getLoc();
9141 SMLoc EndLoc;
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009142 if (getParser().parseExpression(OffsetExpr, EndLoc)) {
9143 Error(ExLoc, "malformed pad offset");
9144 return false;
9145 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009146 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009147 if (!CE) {
9148 Error(ExLoc, "pad offset must be an immediate");
9149 return false;
9150 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009151
Rafael Espindolaa17151a2013-10-08 13:08:17 +00009152 getTargetStreamer().emitPad(CE->getValue());
Logan Chien4ea23b52013-05-10 16:17:24 +00009153 return false;
9154}
9155
9156/// parseDirectiveRegSave
9157/// ::= .save { registers }
9158/// ::= .vsave { registers }
9159bool ARMAsmParser::parseDirectiveRegSave(SMLoc L, bool IsVector) {
9160 // Check the ordering of unwind directives
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009161 if (!UC.hasFnStart()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009162 Error(L, ".fnstart must precede .save or .vsave directives");
9163 return false;
9164 }
Saleem Abdulrasoolc493d142014-01-07 02:28:55 +00009165 if (UC.hasHandlerData()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009166 Error(L, ".save or .vsave must precede .handlerdata directive");
9167 return false;
9168 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009169
Benjamin Kramer23632bd2013-08-03 22:16:24 +00009170 // RAII object to make sure parsed operands are deleted.
David Blaikie960ea3f2014-06-08 16:18:35 +00009171 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> Operands;
Benjamin Kramer23632bd2013-08-03 22:16:24 +00009172
Logan Chien4ea23b52013-05-10 16:17:24 +00009173 // Parse the register list
David Blaikie960ea3f2014-06-08 16:18:35 +00009174 if (parseRegisterList(Operands))
Saleem Abdulrasoola6505ca2014-01-13 01:15:39 +00009175 return false;
David Blaikie960ea3f2014-06-08 16:18:35 +00009176 ARMOperand &Op = (ARMOperand &)*Operands[0];
9177 if (!IsVector && !Op.isRegList()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009178 Error(L, ".save expects GPR registers");
9179 return false;
9180 }
David Blaikie960ea3f2014-06-08 16:18:35 +00009181 if (IsVector && !Op.isDPRRegList()) {
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009182 Error(L, ".vsave expects DPR registers");
9183 return false;
9184 }
Logan Chien4ea23b52013-05-10 16:17:24 +00009185
David Blaikie960ea3f2014-06-08 16:18:35 +00009186 getTargetStreamer().emitRegSave(Op.getRegList(), IsVector);
Logan Chien4ea23b52013-05-10 16:17:24 +00009187 return false;
9188}
9189
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +00009190/// parseDirectiveInst
9191/// ::= .inst opcode [, ...]
9192/// ::= .inst.n opcode [, ...]
9193/// ::= .inst.w opcode [, ...]
9194bool ARMAsmParser::parseDirectiveInst(SMLoc Loc, char Suffix) {
9195 int Width;
9196
9197 if (isThumb()) {
9198 switch (Suffix) {
9199 case 'n':
9200 Width = 2;
9201 break;
9202 case 'w':
9203 Width = 4;
9204 break;
9205 default:
9206 Parser.eatToEndOfStatement();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009207 Error(Loc, "cannot determine Thumb instruction size, "
9208 "use inst.n/inst.w instead");
9209 return false;
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +00009210 }
9211 } else {
9212 if (Suffix) {
9213 Parser.eatToEndOfStatement();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009214 Error(Loc, "width suffixes are invalid in ARM mode");
9215 return false;
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +00009216 }
9217 Width = 4;
9218 }
9219
9220 if (getLexer().is(AsmToken::EndOfStatement)) {
9221 Parser.eatToEndOfStatement();
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009222 Error(Loc, "expected expression following directive");
9223 return false;
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +00009224 }
9225
9226 for (;;) {
9227 const MCExpr *Expr;
9228
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009229 if (getParser().parseExpression(Expr)) {
9230 Error(Loc, "expected expression");
9231 return false;
9232 }
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +00009233
9234 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009235 if (!Value) {
9236 Error(Loc, "expected constant expression");
9237 return false;
9238 }
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +00009239
9240 switch (Width) {
9241 case 2:
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009242 if (Value->getValue() > 0xffff) {
9243 Error(Loc, "inst.n operand is too big, use inst.w instead");
9244 return false;
9245 }
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +00009246 break;
9247 case 4:
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009248 if (Value->getValue() > 0xffffffff) {
9249 Error(Loc,
9250 StringRef(Suffix ? "inst.w" : "inst") + " operand is too big");
9251 return false;
9252 }
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +00009253 break;
9254 default:
9255 llvm_unreachable("only supported widths are 2 and 4");
9256 }
9257
9258 getTargetStreamer().emitInst(Value->getValue(), Suffix);
9259
9260 if (getLexer().is(AsmToken::EndOfStatement))
9261 break;
9262
Saleem Abdulrasool0c4b1022013-12-28 22:47:53 +00009263 if (getLexer().isNot(AsmToken::Comma)) {
9264 Error(Loc, "unexpected token in directive");
9265 return false;
9266 }
Saleem Abdulrasoolc0da2cb2013-12-19 05:17:58 +00009267
9268 Parser.Lex();
9269 }
9270
9271 Parser.Lex();
9272 return false;
9273}
9274
David Peixotto80c083a2013-12-19 18:26:07 +00009275/// parseDirectiveLtorg
Saleem Abdulrasool6e6c2392013-12-20 07:21:16 +00009276/// ::= .ltorg | .pool
David Peixotto80c083a2013-12-19 18:26:07 +00009277bool ARMAsmParser::parseDirectiveLtorg(SMLoc L) {
David Peixottob9b73622014-02-04 17:22:40 +00009278 getTargetStreamer().emitCurrentConstantPool();
David Peixotto80c083a2013-12-19 18:26:07 +00009279 return false;
9280}
9281
Saleem Abdulrasoola5549682013-12-26 01:52:28 +00009282bool ARMAsmParser::parseDirectiveEven(SMLoc L) {
9283 const MCSection *Section = getStreamer().getCurrentSection().first;
9284
9285 if (getLexer().isNot(AsmToken::EndOfStatement)) {
9286 TokError("unexpected token in directive");
9287 return false;
9288 }
9289
9290 if (!Section) {
Rafael Espindola7b61ddf2014-10-15 16:12:52 +00009291 getStreamer().InitSections(false);
Saleem Abdulrasoola5549682013-12-26 01:52:28 +00009292 Section = getStreamer().getCurrentSection().first;
9293 }
9294
Saleem Abdulrasool42b233a2014-03-18 05:26:55 +00009295 assert(Section && "must have section to emit alignment");
Saleem Abdulrasoola5549682013-12-26 01:52:28 +00009296 if (Section->UseCodeAlign())
Rafael Espindola7b514962014-02-04 18:34:04 +00009297 getStreamer().EmitCodeAlignment(2);
Saleem Abdulrasoola5549682013-12-26 01:52:28 +00009298 else
Rafael Espindola7b514962014-02-04 18:34:04 +00009299 getStreamer().EmitValueToAlignment(2);
Saleem Abdulrasoola5549682013-12-26 01:52:28 +00009300
9301 return false;
9302}
9303
Saleem Abdulrasool662f5c12014-01-21 02:33:02 +00009304/// parseDirectivePersonalityIndex
9305/// ::= .personalityindex index
9306bool ARMAsmParser::parseDirectivePersonalityIndex(SMLoc L) {
9307 bool HasExistingPersonality = UC.hasPersonality();
9308
9309 UC.recordPersonalityIndex(L);
9310
9311 if (!UC.hasFnStart()) {
9312 Parser.eatToEndOfStatement();
9313 Error(L, ".fnstart must precede .personalityindex directive");
9314 return false;
9315 }
9316 if (UC.cantUnwind()) {
9317 Parser.eatToEndOfStatement();
9318 Error(L, ".personalityindex cannot be used with .cantunwind");
9319 UC.emitCantUnwindLocNotes();
9320 return false;
9321 }
9322 if (UC.hasHandlerData()) {
9323 Parser.eatToEndOfStatement();
9324 Error(L, ".personalityindex must precede .handlerdata directive");
9325 UC.emitHandlerDataLocNotes();
9326 return false;
9327 }
9328 if (HasExistingPersonality) {
9329 Parser.eatToEndOfStatement();
9330 Error(L, "multiple personality directives");
9331 UC.emitPersonalityLocNotes();
9332 return false;
9333 }
9334
9335 const MCExpr *IndexExpression;
9336 SMLoc IndexLoc = Parser.getTok().getLoc();
9337 if (Parser.parseExpression(IndexExpression)) {
9338 Parser.eatToEndOfStatement();
9339 return false;
9340 }
9341
9342 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(IndexExpression);
9343 if (!CE) {
9344 Parser.eatToEndOfStatement();
9345 Error(IndexLoc, "index must be a constant number");
9346 return false;
9347 }
9348 if (CE->getValue() < 0 ||
9349 CE->getValue() >= ARM::EHABI::NUM_PERSONALITY_INDEX) {
9350 Parser.eatToEndOfStatement();
9351 Error(IndexLoc, "personality routine index should be in range [0-3]");
9352 return false;
9353 }
9354
9355 getTargetStreamer().emitPersonalityIndex(CE->getValue());
9356 return false;
9357}
9358
Saleem Abdulrasoold9f08602014-01-21 02:33:10 +00009359/// parseDirectiveUnwindRaw
9360/// ::= .unwind_raw offset, opcode [, opcode...]
9361bool ARMAsmParser::parseDirectiveUnwindRaw(SMLoc L) {
9362 if (!UC.hasFnStart()) {
9363 Parser.eatToEndOfStatement();
9364 Error(L, ".fnstart must precede .unwind_raw directives");
9365 return false;
9366 }
9367
9368 int64_t StackOffset;
9369
9370 const MCExpr *OffsetExpr;
9371 SMLoc OffsetLoc = getLexer().getLoc();
9372 if (getLexer().is(AsmToken::EndOfStatement) ||
9373 getParser().parseExpression(OffsetExpr)) {
9374 Error(OffsetLoc, "expected expression");
9375 Parser.eatToEndOfStatement();
9376 return false;
9377 }
9378
9379 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
9380 if (!CE) {
9381 Error(OffsetLoc, "offset must be a constant");
9382 Parser.eatToEndOfStatement();
9383 return false;
9384 }
9385
9386 StackOffset = CE->getValue();
9387
9388 if (getLexer().isNot(AsmToken::Comma)) {
9389 Error(getLexer().getLoc(), "expected comma");
9390 Parser.eatToEndOfStatement();
9391 return false;
9392 }
9393 Parser.Lex();
9394
9395 SmallVector<uint8_t, 16> Opcodes;
9396 for (;;) {
9397 const MCExpr *OE;
9398
9399 SMLoc OpcodeLoc = getLexer().getLoc();
9400 if (getLexer().is(AsmToken::EndOfStatement) || Parser.parseExpression(OE)) {
9401 Error(OpcodeLoc, "expected opcode expression");
9402 Parser.eatToEndOfStatement();
9403 return false;
9404 }
9405
9406 const MCConstantExpr *OC = dyn_cast<MCConstantExpr>(OE);
9407 if (!OC) {
9408 Error(OpcodeLoc, "opcode value must be a constant");
9409 Parser.eatToEndOfStatement();
9410 return false;
9411 }
9412
9413 const int64_t Opcode = OC->getValue();
9414 if (Opcode & ~0xff) {
9415 Error(OpcodeLoc, "invalid opcode");
9416 Parser.eatToEndOfStatement();
9417 return false;
9418 }
9419
9420 Opcodes.push_back(uint8_t(Opcode));
9421
9422 if (getLexer().is(AsmToken::EndOfStatement))
9423 break;
9424
9425 if (getLexer().isNot(AsmToken::Comma)) {
9426 Error(getLexer().getLoc(), "unexpected token in directive");
9427 Parser.eatToEndOfStatement();
9428 return false;
9429 }
9430
9431 Parser.Lex();
9432 }
9433
9434 getTargetStreamer().emitUnwindRaw(StackOffset, Opcodes);
9435
9436 Parser.Lex();
9437 return false;
9438}
9439
Saleem Abdulrasool56e06e82014-01-30 04:02:47 +00009440/// parseDirectiveTLSDescSeq
9441/// ::= .tlsdescseq tls-variable
9442bool ARMAsmParser::parseDirectiveTLSDescSeq(SMLoc L) {
9443 if (getLexer().isNot(AsmToken::Identifier)) {
9444 TokError("expected variable after '.tlsdescseq' directive");
9445 Parser.eatToEndOfStatement();
9446 return false;
9447 }
9448
9449 const MCSymbolRefExpr *SRE =
9450 MCSymbolRefExpr::Create(Parser.getTok().getIdentifier(),
9451 MCSymbolRefExpr::VK_ARM_TLSDESCSEQ, getContext());
9452 Lex();
9453
9454 if (getLexer().isNot(AsmToken::EndOfStatement)) {
9455 Error(Parser.getTok().getLoc(), "unexpected token");
9456 Parser.eatToEndOfStatement();
9457 return false;
9458 }
9459
9460 getTargetStreamer().AnnotateTLSDescriptorSequence(SRE);
9461 return false;
9462}
9463
Saleem Abdulrasool5d962d32014-01-30 04:46:24 +00009464/// parseDirectiveMovSP
9465/// ::= .movsp reg [, #offset]
9466bool ARMAsmParser::parseDirectiveMovSP(SMLoc L) {
9467 if (!UC.hasFnStart()) {
9468 Parser.eatToEndOfStatement();
9469 Error(L, ".fnstart must precede .movsp directives");
9470 return false;
9471 }
9472 if (UC.getFPReg() != ARM::SP) {
9473 Parser.eatToEndOfStatement();
9474 Error(L, "unexpected .movsp directive");
9475 return false;
9476 }
9477
9478 SMLoc SPRegLoc = Parser.getTok().getLoc();
9479 int SPReg = tryParseRegister();
9480 if (SPReg == -1) {
9481 Parser.eatToEndOfStatement();
9482 Error(SPRegLoc, "register expected");
9483 return false;
9484 }
9485
9486 if (SPReg == ARM::SP || SPReg == ARM::PC) {
9487 Parser.eatToEndOfStatement();
9488 Error(SPRegLoc, "sp and pc are not permitted in .movsp directive");
9489 return false;
9490 }
9491
9492 int64_t Offset = 0;
9493 if (Parser.getTok().is(AsmToken::Comma)) {
9494 Parser.Lex();
9495
9496 if (Parser.getTok().isNot(AsmToken::Hash)) {
9497 Error(Parser.getTok().getLoc(), "expected #constant");
9498 Parser.eatToEndOfStatement();
9499 return false;
9500 }
9501 Parser.Lex();
9502
9503 const MCExpr *OffsetExpr;
9504 SMLoc OffsetLoc = Parser.getTok().getLoc();
9505 if (Parser.parseExpression(OffsetExpr)) {
9506 Parser.eatToEndOfStatement();
9507 Error(OffsetLoc, "malformed offset expression");
9508 return false;
9509 }
9510
9511 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(OffsetExpr);
9512 if (!CE) {
9513 Parser.eatToEndOfStatement();
9514 Error(OffsetLoc, "offset must be an immediate constant");
9515 return false;
9516 }
9517
9518 Offset = CE->getValue();
9519 }
9520
9521 getTargetStreamer().emitMovSP(SPReg, Offset);
9522 UC.saveFPReg(SPReg);
9523
9524 return false;
9525}
9526
Saleem Abdulrasool4c4789b2014-01-30 04:46:41 +00009527/// parseDirectiveObjectArch
9528/// ::= .object_arch name
9529bool ARMAsmParser::parseDirectiveObjectArch(SMLoc L) {
9530 if (getLexer().isNot(AsmToken::Identifier)) {
9531 Error(getLexer().getLoc(), "unexpected token");
9532 Parser.eatToEndOfStatement();
9533 return false;
9534 }
9535
9536 StringRef Arch = Parser.getTok().getString();
9537 SMLoc ArchLoc = Parser.getTok().getLoc();
9538 getLexer().Lex();
9539
9540 unsigned ID = StringSwitch<unsigned>(Arch)
9541#define ARM_ARCH_NAME(NAME, ID, DEFAULT_CPU_NAME, DEFAULT_CPU_ARCH) \
9542 .Case(NAME, ARM::ID)
9543#define ARM_ARCH_ALIAS(NAME, ID) \
9544 .Case(NAME, ARM::ID)
9545#include "MCTargetDesc/ARMArchName.def"
9546#undef ARM_ARCH_NAME
9547#undef ARM_ARCH_ALIAS
9548 .Default(ARM::INVALID_ARCH);
9549
9550 if (ID == ARM::INVALID_ARCH) {
9551 Error(ArchLoc, "unknown architecture '" + Arch + "'");
9552 Parser.eatToEndOfStatement();
9553 return false;
9554 }
9555
9556 getTargetStreamer().emitObjectArch(ID);
9557
9558 if (getLexer().isNot(AsmToken::EndOfStatement)) {
9559 Error(getLexer().getLoc(), "unexpected token");
9560 Parser.eatToEndOfStatement();
9561 }
9562
9563 return false;
9564}
9565
Saleem Abdulrasoolfd6ed1e2014-02-23 17:45:32 +00009566/// parseDirectiveAlign
9567/// ::= .align
9568bool ARMAsmParser::parseDirectiveAlign(SMLoc L) {
9569 // NOTE: if this is not the end of the statement, fall back to the target
9570 // agnostic handling for this directive which will correctly handle this.
9571 if (getLexer().isNot(AsmToken::EndOfStatement))
9572 return true;
9573
9574 // '.align' is target specifically handled to mean 2**2 byte alignment.
9575 if (getStreamer().getCurrentSection().first->UseCodeAlign())
9576 getStreamer().EmitCodeAlignment(4, 0);
9577 else
9578 getStreamer().EmitValueToAlignment(4, 0, 1, 0);
9579
9580 return false;
9581}
9582
Saleem Abdulrasool39f773f2014-03-20 06:05:33 +00009583/// parseDirectiveThumbSet
9584/// ::= .thumb_set name, value
9585bool ARMAsmParser::parseDirectiveThumbSet(SMLoc L) {
9586 StringRef Name;
9587 if (Parser.parseIdentifier(Name)) {
9588 TokError("expected identifier after '.thumb_set'");
9589 Parser.eatToEndOfStatement();
9590 return false;
9591 }
9592
9593 if (getLexer().isNot(AsmToken::Comma)) {
9594 TokError("expected comma after name '" + Name + "'");
9595 Parser.eatToEndOfStatement();
9596 return false;
9597 }
9598 Lex();
9599
9600 const MCExpr *Value;
9601 if (Parser.parseExpression(Value)) {
9602 TokError("missing expression");
9603 Parser.eatToEndOfStatement();
9604 return false;
9605 }
9606
9607 if (getLexer().isNot(AsmToken::EndOfStatement)) {
9608 TokError("unexpected token");
9609 Parser.eatToEndOfStatement();
9610 return false;
9611 }
9612 Lex();
9613
9614 MCSymbol *Alias = getContext().GetOrCreateSymbol(Name);
Rafael Espindola466d6632014-04-27 20:23:58 +00009615 getTargetStreamer().emitThumbSet(Alias, Value);
Saleem Abdulrasool39f773f2014-03-20 06:05:33 +00009616 return false;
9617}
9618
Kevin Enderby8be42bd2009-10-30 22:55:57 +00009619/// Force static initialization.
Kevin Enderbyccab3172009-09-15 00:27:25 +00009620extern "C" void LLVMInitializeARMAsmParser() {
Christian Pirkerdc9ff752014-04-01 15:19:30 +00009621 RegisterMCAsmParser<ARMAsmParser> X(TheARMLETarget);
9622 RegisterMCAsmParser<ARMAsmParser> Y(TheARMBETarget);
9623 RegisterMCAsmParser<ARMAsmParser> A(TheThumbLETarget);
9624 RegisterMCAsmParser<ARMAsmParser> B(TheThumbBETarget);
Kevin Enderbyccab3172009-09-15 00:27:25 +00009625}
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00009626
Chris Lattner3e4582a2010-09-06 19:11:01 +00009627#define GET_REGISTER_MATCHER
Craig Topper3ec7c2a2012-04-25 06:56:34 +00009628#define GET_SUBTARGET_FEATURE_NAME
Chris Lattner3e4582a2010-09-06 19:11:01 +00009629#define GET_MATCHER_IMPLEMENTATION
Daniel Dunbar5cd4d0f2010-08-11 05:24:50 +00009630#include "ARMGenAsmMatcher.inc"
Jim Grosbach231e7aa2013-02-06 06:00:11 +00009631
Saleem Abdulrasool45cf67b2014-07-27 19:07:05 +00009632static const struct {
9633 const char *Name;
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00009634 const unsigned ArchCheck;
9635 const uint64_t Features;
9636} Extensions[] = {
9637 { "crc", Feature_HasV8, ARM::FeatureCRC },
9638 { "crypto", Feature_HasV8,
9639 ARM::FeatureCrypto | ARM::FeatureNEON | ARM::FeatureFPARMv8 },
9640 { "fp", Feature_HasV8, ARM::FeatureFPARMv8 },
9641 { "idiv", Feature_HasV7 | Feature_IsNotMClass,
9642 ARM::FeatureHWDiv | ARM::FeatureHWDivARM },
9643 // FIXME: iWMMXT not supported
9644 { "iwmmxt", Feature_None, 0 },
9645 // FIXME: iWMMXT2 not supported
9646 { "iwmmxt2", Feature_None, 0 },
9647 // FIXME: Maverick not supported
9648 { "maverick", Feature_None, 0 },
9649 { "mp", Feature_HasV7 | Feature_IsNotMClass, ARM::FeatureMP },
9650 // FIXME: ARMv6-m OS Extensions feature not checked
9651 { "os", Feature_None, 0 },
9652 // FIXME: Also available in ARMv6-K
9653 { "sec", Feature_HasV7, ARM::FeatureTrustZone },
9654 { "simd", Feature_HasV8, ARM::FeatureNEON | ARM::FeatureFPARMv8 },
9655 // FIXME: Only available in A-class, isel not predicated
9656 { "virt", Feature_HasV7, ARM::FeatureVirtualization },
9657 // FIXME: xscale not supported
9658 { "xscale", Feature_None, 0 },
9659};
9660
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00009661/// parseDirectiveArchExtension
9662/// ::= .arch_extension [no]feature
9663bool ARMAsmParser::parseDirectiveArchExtension(SMLoc L) {
9664 if (getLexer().isNot(AsmToken::Identifier)) {
9665 Error(getLexer().getLoc(), "unexpected token");
9666 Parser.eatToEndOfStatement();
9667 return false;
9668 }
9669
Saleem Abdulrasool45cf67b2014-07-27 19:07:05 +00009670 StringRef Name = Parser.getTok().getString();
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00009671 SMLoc ExtLoc = Parser.getTok().getLoc();
9672 getLexer().Lex();
9673
9674 bool EnableFeature = true;
Saleem Abdulrasool45cf67b2014-07-27 19:07:05 +00009675 if (Name.startswith_lower("no")) {
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00009676 EnableFeature = false;
Saleem Abdulrasool45cf67b2014-07-27 19:07:05 +00009677 Name = Name.substr(2);
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00009678 }
9679
Saleem Abdulrasool45cf67b2014-07-27 19:07:05 +00009680 for (const auto &Extension : Extensions) {
9681 if (Extension.Name != Name)
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00009682 continue;
9683
Saleem Abdulrasool8988c2a2014-07-27 19:07:09 +00009684 if (!Extension.Features)
9685 report_fatal_error("unsupported architectural extension: " + Name);
9686
9687 if ((getAvailableFeatures() & Extension.ArchCheck) != Extension.ArchCheck) {
Saleem Abdulrasool45cf67b2014-07-27 19:07:05 +00009688 Error(ExtLoc, "architectural extension '" + Name + "' is not "
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00009689 "allowed for the current base architecture");
9690 return false;
9691 }
9692
Tim Northover26bb14e2014-08-18 11:49:42 +00009693 uint64_t ToggleFeatures = EnableFeature
Saleem Abdulrasool78c44722014-08-17 19:20:38 +00009694 ? (~STI.getFeatureBits() & Extension.Features)
9695 : ( STI.getFeatureBits() & Extension.Features);
Tim Northover26bb14e2014-08-18 11:49:42 +00009696 uint64_t Features =
Saleem Abdulrasool78c44722014-08-17 19:20:38 +00009697 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
9698 setAvailableFeatures(Features);
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00009699 return false;
9700 }
9701
Saleem Abdulrasool45cf67b2014-07-27 19:07:05 +00009702 Error(ExtLoc, "unknown architectural extension: " + Name);
Saleem Abdulrasool49480bf2014-02-16 00:16:41 +00009703 Parser.eatToEndOfStatement();
9704 return false;
9705}
9706
Jim Grosbach231e7aa2013-02-06 06:00:11 +00009707// Define this matcher function after the auto-generated include so we
9708// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00009709unsigned ARMAsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Jim Grosbach231e7aa2013-02-06 06:00:11 +00009710 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00009711 ARMOperand &Op = static_cast<ARMOperand &>(AsmOp);
Jim Grosbach231e7aa2013-02-06 06:00:11 +00009712 // If the kind is a token for a literal immediate, check if our asm
9713 // operand matches. This is for InstAliases which have a fixed-value
9714 // immediate in the syntax.
Saleem Abdulrasoold88affb2014-01-08 03:28:14 +00009715 switch (Kind) {
9716 default: break;
9717 case MCK__35_0:
David Blaikie960ea3f2014-06-08 16:18:35 +00009718 if (Op.isImm())
9719 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm()))
Saleem Abdulrasoold88affb2014-01-08 03:28:14 +00009720 if (CE->getValue() == 0)
9721 return Match_Success;
9722 break;
9723 case MCK_ARMSOImm:
David Blaikie960ea3f2014-06-08 16:18:35 +00009724 if (Op.isImm()) {
9725 const MCExpr *SOExpr = Op.getImm();
Saleem Abdulrasoold88affb2014-01-08 03:28:14 +00009726 int64_t Value;
9727 if (!SOExpr->EvaluateAsAbsolute(Value))
Stepan Dyatkovskiydf657cc2014-03-29 13:12:40 +00009728 return Match_Success;
Richard Barton3db1d582014-05-01 11:37:44 +00009729 assert((Value >= INT32_MIN && Value <= UINT32_MAX) &&
9730 "expression value must be representable in 32 bits");
Saleem Abdulrasoold88affb2014-01-08 03:28:14 +00009731 }
9732 break;
Saleem Abdulrasoole6e6d712014-01-10 04:38:35 +00009733 case MCK_GPRPair:
David Blaikie960ea3f2014-06-08 16:18:35 +00009734 if (Op.isReg() &&
9735 MRI->getRegClass(ARM::GPRRegClassID).contains(Op.getReg()))
Saleem Abdulrasoole6e6d712014-01-10 04:38:35 +00009736 return Match_Success;
9737 break;
Jim Grosbach231e7aa2013-02-06 06:00:11 +00009738 }
9739 return Match_InvalidOperand;
9740}