blob: 39ccfeb85f8109bd3bf5ed6d6d4fbdd2ab569be9 [file] [log] [blame]
Tim Northover3b0846e2014-05-24 12:50:23 +00001//==- AArch64AsmParser.cpp - Parse AArch64 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
10#include "MCTargetDesc/AArch64AddressingModes.h"
11#include "MCTargetDesc/AArch64MCExpr.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000012#include "MCTargetDesc/AArch64MCTargetDesc.h"
Benjamin Kramer1d1b9242015-05-23 16:15:10 +000013#include "MCTargetDesc/AArch64TargetStreamer.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000014#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000015#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000016#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000017#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000019#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000020#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000021#include "llvm/ADT/StringMap.h"
22#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000023#include "llvm/ADT/StringSwitch.h"
24#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000025#include "llvm/MC/MCContext.h"
26#include "llvm/MC/MCExpr.h"
27#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000028#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000029#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000030#include "llvm/MC/MCParser/MCAsmLexer.h"
31#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000032#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000033#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000034#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000035#include "llvm/MC/MCRegisterInfo.h"
36#include "llvm/MC/MCStreamer.h"
37#include "llvm/MC/MCSubtargetInfo.h"
38#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000039#include "llvm/MC/MCTargetOptions.h"
40#include "llvm/MC/SubtargetFeature.h"
41#include "llvm/Support/Casting.h"
42#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000043#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000044#include "llvm/Support/MathExtras.h"
45#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000046#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000047#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000049#include <cassert>
50#include <cctype>
51#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000052#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000053#include <string>
54#include <tuple>
55#include <utility>
56#include <vector>
57
Tim Northover3b0846e2014-05-24 12:50:23 +000058using namespace llvm;
59
60namespace {
61
Sander de Smalencd6be962017-12-20 11:02:42 +000062enum class RegKind {
63 Scalar,
64 NeonVector,
65 SVEDataVector,
66 SVEPredicateVector
67};
Florian Hahnc4422242017-11-07 13:07:50 +000068
Tim Northover3b0846e2014-05-24 12:50:23 +000069class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000070private:
71 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000072
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000073 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000074 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000075
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +000076 AArch64TargetStreamer &getTargetStreamer() {
77 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
78 return static_cast<AArch64TargetStreamer &>(TS);
79 }
80
Rafael Espindola961d4692014-11-11 05:18:41 +000081 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +000082
83 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +000084 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +000085 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
86 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +000087 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +000088 int tryParseRegister();
Tim Northover3b0846e2014-05-24 12:50:23 +000089 bool parseRegister(OperandVector &Operands);
90 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +000091 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen5c625982018-04-13 12:56:14 +000092 bool parseOptionalMulVl(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000093 bool parseOperand(OperandVector &Operands, bool isCondCode,
94 bool invertCondCode);
95
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +000096 bool showMatchError(SMLoc Loc, unsigned ErrCode, OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +000097
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000098 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +000099 bool parseDirectiveCPU(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000100 bool parseDirectiveWord(unsigned Size, SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000101 bool parseDirectiveInst(SMLoc L);
102
Tim Northover3b0846e2014-05-24 12:50:23 +0000103 bool parseDirectiveTLSDescCall(SMLoc L);
104
105 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000106 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000107
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000108 bool parseDirectiveReq(StringRef Name, SMLoc L);
109 bool parseDirectiveUnreq(SMLoc L);
110
Tim Northover3b0846e2014-05-24 12:50:23 +0000111 bool validateInstruction(MCInst &Inst, SmallVectorImpl<SMLoc> &Loc);
112 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
113 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000114 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000115 bool MatchingInlineAsm) override;
116/// @name Auto-generated Match Functions
117/// {
118
119#define GET_ASSEMBLER_HEADER
120#include "AArch64GenAsmMatcher.inc"
121
122 /// }
123
Sander de Smalen73937b72018-04-11 07:36:10 +0000124 OperandMatchResultTy tryParseVectorRegister(int &Reg, StringRef &Kind,
125 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000126 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
127 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
128 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
129 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
130 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
131 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000132 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000133 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
134 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
135 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
136 OperandMatchResultTy tryParseAddSubImm(OperandVector &Operands);
137 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000138 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000139 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000140 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Florian Hahn91f11e52017-11-07 16:45:48 +0000141 template <bool ParseSuffix>
142 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000143 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000144 template <RegKind VectorKind>
145 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
146 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000147 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000148
149public:
150 enum AArch64MatchResultTy {
151 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
152#define GET_OPERAND_DIAGNOSTIC_TYPES
153#include "AArch64GenAsmMatcher.inc"
154 };
Joel Jones504bf332016-10-24 13:37:13 +0000155 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000156
Akira Hatanakab11ef082015-11-14 06:35:56 +0000157 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000158 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000159 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000160 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000161 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000162 MCStreamer &S = getParser().getStreamer();
163 if (S.getTargetStreamer() == nullptr)
164 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000165
166 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000167 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000168 }
169
170 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
171 SMLoc NameLoc, OperandVector &Operands) override;
172 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
173 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000174 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000175 unsigned Kind) override;
176
177 static bool classifySymbolRef(const MCExpr *Expr,
178 AArch64MCExpr::VariantKind &ELFRefKind,
179 MCSymbolRefExpr::VariantKind &DarwinRefKind,
180 int64_t &Addend);
181};
Tim Northover3b0846e2014-05-24 12:50:23 +0000182
183/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
184/// instruction.
185class AArch64Operand : public MCParsedAsmOperand {
186private:
187 enum KindTy {
188 k_Immediate,
189 k_ShiftedImm,
190 k_CondCode,
191 k_Register,
192 k_VectorList,
193 k_VectorIndex,
194 k_Token,
195 k_SysReg,
196 k_SysCR,
197 k_Prefetch,
198 k_ShiftExtend,
199 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000200 k_Barrier,
201 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000202 } Kind;
203
204 SMLoc StartLoc, EndLoc;
205
206 struct TokOp {
207 const char *Data;
208 unsigned Length;
209 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
210 };
211
212 struct RegOp {
213 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000214 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000215
216 int ElementWidth;
Tim Northover3b0846e2014-05-24 12:50:23 +0000217 };
218
219 struct VectorListOp {
220 unsigned RegNum;
221 unsigned Count;
222 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000223 unsigned ElementWidth;
224 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000225 };
226
227 struct VectorIndexOp {
228 unsigned Val;
229 };
230
231 struct ImmOp {
232 const MCExpr *Val;
233 };
234
235 struct ShiftedImmOp {
236 const MCExpr *Val;
237 unsigned ShiftAmount;
238 };
239
240 struct CondCodeOp {
241 AArch64CC::CondCode Code;
242 };
243
244 struct FPImmOp {
245 unsigned Val; // Encoded 8-bit representation.
246 };
247
248 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000249 const char *Data;
250 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000251 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000252 };
253
254 struct SysRegOp {
255 const char *Data;
256 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000257 uint32_t MRSReg;
258 uint32_t MSRReg;
259 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000260 };
261
262 struct SysCRImmOp {
263 unsigned Val;
264 };
265
266 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000267 const char *Data;
268 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000269 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000270 };
271
Oliver Stannarda34e4702015-12-01 10:48:51 +0000272 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000273 const char *Data;
274 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000275 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000276 };
277
Tim Northover3b0846e2014-05-24 12:50:23 +0000278 struct ShiftExtendOp {
279 AArch64_AM::ShiftExtendType Type;
280 unsigned Amount;
281 bool HasExplicitAmount;
282 };
283
284 struct ExtendOp {
285 unsigned Val;
286 };
287
288 union {
289 struct TokOp Tok;
290 struct RegOp Reg;
291 struct VectorListOp VectorList;
292 struct VectorIndexOp VectorIndex;
293 struct ImmOp Imm;
294 struct ShiftedImmOp ShiftedImm;
295 struct CondCodeOp CondCode;
296 struct FPImmOp FPImm;
297 struct BarrierOp Barrier;
298 struct SysRegOp SysReg;
299 struct SysCRImmOp SysCRImm;
300 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000301 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000302 struct ShiftExtendOp ShiftExtend;
303 };
304
305 // Keep the MCContext around as the MCExprs may need manipulated during
306 // the add<>Operands() calls.
307 MCContext &Ctx;
308
David Blaikie960ea3f2014-06-08 16:18:35 +0000309public:
David Blaikie9f380a32015-03-16 18:06:57 +0000310 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000311
Tim Northover3b0846e2014-05-24 12:50:23 +0000312 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
313 Kind = o.Kind;
314 StartLoc = o.StartLoc;
315 EndLoc = o.EndLoc;
316 switch (Kind) {
317 case k_Token:
318 Tok = o.Tok;
319 break;
320 case k_Immediate:
321 Imm = o.Imm;
322 break;
323 case k_ShiftedImm:
324 ShiftedImm = o.ShiftedImm;
325 break;
326 case k_CondCode:
327 CondCode = o.CondCode;
328 break;
329 case k_FPImm:
330 FPImm = o.FPImm;
331 break;
332 case k_Barrier:
333 Barrier = o.Barrier;
334 break;
335 case k_Register:
336 Reg = o.Reg;
337 break;
338 case k_VectorList:
339 VectorList = o.VectorList;
340 break;
341 case k_VectorIndex:
342 VectorIndex = o.VectorIndex;
343 break;
344 case k_SysReg:
345 SysReg = o.SysReg;
346 break;
347 case k_SysCR:
348 SysCRImm = o.SysCRImm;
349 break;
350 case k_Prefetch:
351 Prefetch = o.Prefetch;
352 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000353 case k_PSBHint:
354 PSBHint = o.PSBHint;
355 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000356 case k_ShiftExtend:
357 ShiftExtend = o.ShiftExtend;
358 break;
359 }
360 }
361
362 /// getStartLoc - Get the location of the first token of this operand.
363 SMLoc getStartLoc() const override { return StartLoc; }
364 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000365 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000366
367 StringRef getToken() const {
368 assert(Kind == k_Token && "Invalid access!");
369 return StringRef(Tok.Data, Tok.Length);
370 }
371
372 bool isTokenSuffix() const {
373 assert(Kind == k_Token && "Invalid access!");
374 return Tok.IsSuffix;
375 }
376
377 const MCExpr *getImm() const {
378 assert(Kind == k_Immediate && "Invalid access!");
379 return Imm.Val;
380 }
381
382 const MCExpr *getShiftedImmVal() const {
383 assert(Kind == k_ShiftedImm && "Invalid access!");
384 return ShiftedImm.Val;
385 }
386
387 unsigned getShiftedImmShift() const {
388 assert(Kind == k_ShiftedImm && "Invalid access!");
389 return ShiftedImm.ShiftAmount;
390 }
391
392 AArch64CC::CondCode getCondCode() const {
393 assert(Kind == k_CondCode && "Invalid access!");
394 return CondCode.Code;
395 }
396
397 unsigned getFPImm() const {
398 assert(Kind == k_FPImm && "Invalid access!");
399 return FPImm.Val;
400 }
401
402 unsigned getBarrier() const {
403 assert(Kind == k_Barrier && "Invalid access!");
404 return Barrier.Val;
405 }
406
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000407 StringRef getBarrierName() const {
408 assert(Kind == k_Barrier && "Invalid access!");
409 return StringRef(Barrier.Data, Barrier.Length);
410 }
411
Tim Northover3b0846e2014-05-24 12:50:23 +0000412 unsigned getReg() const override {
413 assert(Kind == k_Register && "Invalid access!");
414 return Reg.RegNum;
415 }
416
417 unsigned getVectorListStart() const {
418 assert(Kind == k_VectorList && "Invalid access!");
419 return VectorList.RegNum;
420 }
421
422 unsigned getVectorListCount() const {
423 assert(Kind == k_VectorList && "Invalid access!");
424 return VectorList.Count;
425 }
426
427 unsigned getVectorIndex() const {
428 assert(Kind == k_VectorIndex && "Invalid access!");
429 return VectorIndex.Val;
430 }
431
432 StringRef getSysReg() const {
433 assert(Kind == k_SysReg && "Invalid access!");
434 return StringRef(SysReg.Data, SysReg.Length);
435 }
436
Tim Northover3b0846e2014-05-24 12:50:23 +0000437 unsigned getSysCR() const {
438 assert(Kind == k_SysCR && "Invalid access!");
439 return SysCRImm.Val;
440 }
441
442 unsigned getPrefetch() const {
443 assert(Kind == k_Prefetch && "Invalid access!");
444 return Prefetch.Val;
445 }
446
Oliver Stannarda34e4702015-12-01 10:48:51 +0000447 unsigned getPSBHint() const {
448 assert(Kind == k_PSBHint && "Invalid access!");
449 return PSBHint.Val;
450 }
451
452 StringRef getPSBHintName() const {
453 assert(Kind == k_PSBHint && "Invalid access!");
454 return StringRef(PSBHint.Data, PSBHint.Length);
455 }
456
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000457 StringRef getPrefetchName() const {
458 assert(Kind == k_Prefetch && "Invalid access!");
459 return StringRef(Prefetch.Data, Prefetch.Length);
460 }
461
Tim Northover3b0846e2014-05-24 12:50:23 +0000462 AArch64_AM::ShiftExtendType getShiftExtendType() const {
463 assert(Kind == k_ShiftExtend && "Invalid access!");
464 return ShiftExtend.Type;
465 }
466
467 unsigned getShiftExtendAmount() const {
468 assert(Kind == k_ShiftExtend && "Invalid access!");
469 return ShiftExtend.Amount;
470 }
471
472 bool hasShiftExtendAmount() const {
473 assert(Kind == k_ShiftExtend && "Invalid access!");
474 return ShiftExtend.HasExplicitAmount;
475 }
476
477 bool isImm() const override { return Kind == k_Immediate; }
478 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000479
480 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
481
482 template <int Bits, int Scale> bool isSImmScaled() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000483 if (!isImm())
484 return false;
485 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
486 if (!MCE)
487 return false;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000488
489 int64_t Shift = Bits - 1;
490 int64_t MinVal = (int64_t(1) << Shift) * -Scale;
491 int64_t MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
492
Tim Northover3b0846e2014-05-24 12:50:23 +0000493 int64_t Val = MCE->getValue();
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000494 return Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0;
Tim Northover3b0846e2014-05-24 12:50:23 +0000495 }
496
Sander de Smalen245e0e62018-01-22 10:46:00 +0000497 bool isSVEPattern() const {
498 if (!isImm())
499 return false;
500 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
501 if (!MCE)
502 return false;
503 int64_t Val = MCE->getValue();
504 return Val >= 0 && Val < 32;
505 }
506
Tim Northover3b0846e2014-05-24 12:50:23 +0000507 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
508 AArch64MCExpr::VariantKind ELFRefKind;
509 MCSymbolRefExpr::VariantKind DarwinRefKind;
510 int64_t Addend;
511 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
512 Addend)) {
513 // If we don't understand the expression, assume the best and
514 // let the fixup and relocation code deal with it.
515 return true;
516 }
517
518 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
519 ELFRefKind == AArch64MCExpr::VK_LO12 ||
520 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
521 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
522 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
523 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
524 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
525 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000526 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
527 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
528 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000529 // Note that we don't range-check the addend. It's adjusted modulo page
530 // size when converted, so there is no "out of range" condition when using
531 // @pageoff.
532 return Addend >= 0 && (Addend % Scale) == 0;
533 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
534 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
535 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
536 return Addend == 0;
537 }
538
539 return false;
540 }
541
542 template <int Scale> bool isUImm12Offset() const {
543 if (!isImm())
544 return false;
545
546 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
547 if (!MCE)
548 return isSymbolicUImm12Offset(getImm(), Scale);
549
550 int64_t Val = MCE->getValue();
551 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
552 }
553
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000554 template <int N, int M>
555 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000556 if (!isImm())
557 return false;
558 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
559 if (!MCE)
560 return false;
561 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000562 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000563 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000564
Sander de Smalena1c259c2018-01-29 13:05:38 +0000565 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
566 // a logical immediate can always be represented when inverted.
567 template <typename T>
568 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000569 if (!isImm())
570 return false;
571 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
572 if (!MCE)
573 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000574
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000575 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000576 int64_t SVal = typename std::make_signed<T>::type(Val);
577 int64_t UVal = typename std::make_unsigned<T>::type(Val);
578 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000579 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000580
Sander de Smalena1c259c2018-01-29 13:05:38 +0000581 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000582 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000583
Tim Northover3b0846e2014-05-24 12:50:23 +0000584 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000585
Tim Northover3b0846e2014-05-24 12:50:23 +0000586 bool isAddSubImm() const {
587 if (!isShiftedImm() && !isImm())
588 return false;
589
590 const MCExpr *Expr;
591
592 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
593 if (isShiftedImm()) {
594 unsigned Shift = ShiftedImm.ShiftAmount;
595 Expr = ShiftedImm.Val;
596 if (Shift != 0 && Shift != 12)
597 return false;
598 } else {
599 Expr = getImm();
600 }
601
602 AArch64MCExpr::VariantKind ELFRefKind;
603 MCSymbolRefExpr::VariantKind DarwinRefKind;
604 int64_t Addend;
605 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
606 DarwinRefKind, Addend)) {
607 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
608 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
609 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
610 || ELFRefKind == AArch64MCExpr::VK_LO12
611 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
612 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
613 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
614 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
615 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
616 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000617 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
618 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
619 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000620 }
621
Diana Picusc93518d2016-10-11 09:17:47 +0000622 // If it's a constant, it should be a real immediate in range:
623 if (auto *CE = dyn_cast<MCConstantExpr>(Expr))
624 return CE->getValue() >= 0 && CE->getValue() <= 0xfff;
625
626 // If it's an expression, we hope for the best and let the fixup/relocation
627 // code deal with it.
628 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000629 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000630
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000631 bool isAddSubImmNeg() const {
632 if (!isShiftedImm() && !isImm())
633 return false;
634
635 const MCExpr *Expr;
636
637 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
638 if (isShiftedImm()) {
639 unsigned Shift = ShiftedImm.ShiftAmount;
640 Expr = ShiftedImm.Val;
641 if (Shift != 0 && Shift != 12)
642 return false;
643 } else
644 Expr = getImm();
645
646 // Otherwise it should be a real negative immediate in range:
647 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr);
648 return CE != nullptr && CE->getValue() < 0 && -CE->getValue() <= 0xfff;
649 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000650
Tim Northover3b0846e2014-05-24 12:50:23 +0000651 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000652
Tim Northover3b0846e2014-05-24 12:50:23 +0000653 bool isSIMDImmType10() const {
654 if (!isImm())
655 return false;
656 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
657 if (!MCE)
658 return false;
659 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
660 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000661
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000662 template<int N>
663 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000664 if (!isImm())
665 return false;
666 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
667 if (!MCE)
668 return true;
669 int64_t Val = MCE->getValue();
670 if (Val & 0x3)
671 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000672 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
673 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000674 }
675
676 bool
677 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
678 if (!isImm())
679 return false;
680
681 AArch64MCExpr::VariantKind ELFRefKind;
682 MCSymbolRefExpr::VariantKind DarwinRefKind;
683 int64_t Addend;
684 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
685 DarwinRefKind, Addend)) {
686 return false;
687 }
688 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
689 return false;
690
691 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
692 if (ELFRefKind == AllowedModifiers[i])
693 return Addend == 0;
694 }
695
696 return false;
697 }
698
699 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000700 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000701 }
702
703 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000704 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
705 AArch64MCExpr::VK_TPREL_G2,
706 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000707 }
708
709 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000710 return isMovWSymbol({
711 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000712 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
713 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000714 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000715 }
716
717 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000718 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
719 AArch64MCExpr::VK_TPREL_G0,
720 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000721 }
722
723 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000724 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000725 }
726
727 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000728 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000729 }
730
731 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000732 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
733 AArch64MCExpr::VK_TPREL_G1_NC,
734 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000735 }
736
737 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000738 return isMovWSymbol(
739 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
740 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000741 }
742
743 template<int RegWidth, int Shift>
744 bool isMOVZMovAlias() const {
745 if (!isImm()) return false;
746
747 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
748 if (!CE) return false;
749 uint64_t Value = CE->getValue();
750
Tim Northoverdaa1c012016-06-16 01:42:25 +0000751 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000752 }
753
754 template<int RegWidth, int Shift>
755 bool isMOVNMovAlias() const {
756 if (!isImm()) return false;
757
758 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
759 if (!CE) return false;
760 uint64_t Value = CE->getValue();
761
Tim Northoverdaa1c012016-06-16 01:42:25 +0000762 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000763 }
764
765 bool isFPImm() const { return Kind == k_FPImm; }
766 bool isBarrier() const { return Kind == k_Barrier; }
767 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000768
Tim Northover3b0846e2014-05-24 12:50:23 +0000769 bool isMRSSystemRegister() const {
770 if (!isSysReg()) return false;
771
Tim Northover7cd58932015-01-22 17:23:04 +0000772 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000773 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000774
Tim Northover3b0846e2014-05-24 12:50:23 +0000775 bool isMSRSystemRegister() const {
776 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000777 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000778 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000779
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000780 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000781 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000782 return (SysReg.PStateField == AArch64PState::PAN ||
783 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000784 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000785
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000786 bool isSystemPStateFieldWithImm0_15() const {
787 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000788 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000789 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000790
Florian Hahnc4422242017-11-07 13:07:50 +0000791 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +0000792 return Kind == k_Register;
793 }
794
795 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000796 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
797 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000798
Florian Hahnc4422242017-11-07 13:07:50 +0000799 bool isNeonVectorReg() const {
800 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
801 }
802
803 bool isNeonVectorRegLo() const {
804 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
806 Reg.RegNum);
807 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000808
Sander de Smalencd6be962017-12-20 11:02:42 +0000809 template <unsigned Class> bool isSVEVectorReg() const {
810 RegKind RK;
811 switch (Class) {
812 case AArch64::ZPRRegClassID:
813 RK = RegKind::SVEDataVector;
814 break;
815 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +0000816 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +0000817 RK = RegKind::SVEPredicateVector;
818 break;
819 default:
820 llvm_unreachable("Unsupport register class");
821 }
822
823 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +0000824 AArch64MCRegisterClasses[Class].contains(getReg());
825 }
826
Sander de Smalencd6be962017-12-20 11:02:42 +0000827 template <int ElementWidth, unsigned Class>
828 bool isSVEVectorRegOfWidth() const {
829 return isSVEVectorReg<Class>() &&
Sander de Smalen73937b72018-04-11 07:36:10 +0000830 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth);
Florian Hahn91f11e52017-11-07 16:45:48 +0000831 }
832
Tim Northover3b0846e2014-05-24 12:50:23 +0000833 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000834 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000835 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
836 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000837
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000838 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000839 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000840 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
841 Reg.RegNum);
842 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000843
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000844 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000845 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000846 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
847 Reg.RegNum);
848 }
Tim Northover3b0846e2014-05-24 12:50:23 +0000849
850 bool isGPR64sp0() const {
Florian Hahnc4422242017-11-07 13:07:50 +0000851 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +0000852 AArch64MCRegisterClasses[AArch64::GPR64spRegClassID].contains(Reg.RegNum);
853 }
854
Sam Parker5f934642017-08-31 09:27:04 +0000855 template<int64_t Angle, int64_t Remainder>
856 bool isComplexRotation() const {
857 if (!isImm()) return false;
858
859 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
860 if (!CE) return false;
861 uint64_t Value = CE->getValue();
862
863 return (Value % Angle == Remainder && Value <= 270);
864 }
865
Tim Northover3b0846e2014-05-24 12:50:23 +0000866 /// Is this a vector list with the type implicit (presumably attached to the
867 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +0000868 template <RegKind VectorKind, unsigned NumRegs>
869 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000870 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +0000871 VectorList.NumElements == 0 &&
872 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000873 }
874
Sander de Smalen650234b2018-04-12 11:40:52 +0000875 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
876 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +0000877 bool isTypedVectorList() const {
878 if (Kind != k_VectorList)
879 return false;
880 if (VectorList.Count != NumRegs)
881 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +0000882 if (VectorList.RegisterKind != VectorKind)
883 return false;
884 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +0000885 return false;
886 return VectorList.NumElements == NumElements;
887 }
888
889 bool isVectorIndex1() const {
890 return Kind == k_VectorIndex && VectorIndex.Val == 1;
891 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000892
Tim Northover3b0846e2014-05-24 12:50:23 +0000893 bool isVectorIndexB() const {
894 return Kind == k_VectorIndex && VectorIndex.Val < 16;
895 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000896
Tim Northover3b0846e2014-05-24 12:50:23 +0000897 bool isVectorIndexH() const {
898 return Kind == k_VectorIndex && VectorIndex.Val < 8;
899 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000900
Tim Northover3b0846e2014-05-24 12:50:23 +0000901 bool isVectorIndexS() const {
902 return Kind == k_VectorIndex && VectorIndex.Val < 4;
903 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000904
Tim Northover3b0846e2014-05-24 12:50:23 +0000905 bool isVectorIndexD() const {
906 return Kind == k_VectorIndex && VectorIndex.Val < 2;
907 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000908
Tim Northover3b0846e2014-05-24 12:50:23 +0000909 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000910
Tim Northover3b0846e2014-05-24 12:50:23 +0000911 bool isTokenEqual(StringRef Str) const {
912 return Kind == k_Token && getToken() == Str;
913 }
914 bool isSysCR() const { return Kind == k_SysCR; }
915 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +0000916 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000917 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
918 bool isShifter() const {
919 if (!isShiftExtend())
920 return false;
921
922 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
923 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
924 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
925 ST == AArch64_AM::MSL);
926 }
927 bool isExtend() const {
928 if (!isShiftExtend())
929 return false;
930
931 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
932 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
933 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
934 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
935 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
936 ET == AArch64_AM::LSL) &&
937 getShiftExtendAmount() <= 4;
938 }
939
940 bool isExtend64() const {
941 if (!isExtend())
942 return false;
943 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
944 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
945 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
946 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000947
Tim Northover3b0846e2014-05-24 12:50:23 +0000948 bool isExtendLSL64() const {
949 if (!isExtend())
950 return false;
951 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
952 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
953 ET == AArch64_AM::LSL) &&
954 getShiftExtendAmount() <= 4;
955 }
956
957 template<int Width> bool isMemXExtend() const {
958 if (!isExtend())
959 return false;
960 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
961 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
962 (getShiftExtendAmount() == Log2_32(Width / 8) ||
963 getShiftExtendAmount() == 0);
964 }
965
966 template<int Width> bool isMemWExtend() const {
967 if (!isExtend())
968 return false;
969 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
970 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
971 (getShiftExtendAmount() == Log2_32(Width / 8) ||
972 getShiftExtendAmount() == 0);
973 }
974
975 template <unsigned width>
976 bool isArithmeticShifter() const {
977 if (!isShifter())
978 return false;
979
980 // An arithmetic shifter is LSL, LSR, or ASR.
981 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
982 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
983 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
984 }
985
986 template <unsigned width>
987 bool isLogicalShifter() const {
988 if (!isShifter())
989 return false;
990
991 // A logical shifter is LSL, LSR, ASR or ROR.
992 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
993 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
994 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
995 getShiftExtendAmount() < width;
996 }
997
998 bool isMovImm32Shifter() const {
999 if (!isShifter())
1000 return false;
1001
1002 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1003 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1004 if (ST != AArch64_AM::LSL)
1005 return false;
1006 uint64_t Val = getShiftExtendAmount();
1007 return (Val == 0 || Val == 16);
1008 }
1009
1010 bool isMovImm64Shifter() const {
1011 if (!isShifter())
1012 return false;
1013
1014 // A MOVi shifter is LSL of 0 or 16.
1015 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1016 if (ST != AArch64_AM::LSL)
1017 return false;
1018 uint64_t Val = getShiftExtendAmount();
1019 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1020 }
1021
1022 bool isLogicalVecShifter() const {
1023 if (!isShifter())
1024 return false;
1025
1026 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1027 unsigned Shift = getShiftExtendAmount();
1028 return getShiftExtendType() == AArch64_AM::LSL &&
1029 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1030 }
1031
1032 bool isLogicalVecHalfWordShifter() const {
1033 if (!isLogicalVecShifter())
1034 return false;
1035
1036 // A logical vector shifter is a left shift by 0 or 8.
1037 unsigned Shift = getShiftExtendAmount();
1038 return getShiftExtendType() == AArch64_AM::LSL &&
1039 (Shift == 0 || Shift == 8);
1040 }
1041
1042 bool isMoveVecShifter() const {
1043 if (!isShiftExtend())
1044 return false;
1045
1046 // A logical vector shifter is a left shift by 8 or 16.
1047 unsigned Shift = getShiftExtendAmount();
1048 return getShiftExtendType() == AArch64_AM::MSL &&
1049 (Shift == 8 || Shift == 16);
1050 }
1051
1052 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1053 // to LDUR/STUR when the offset is not legal for the former but is for
1054 // the latter. As such, in addition to checking for being a legal unscaled
1055 // address, also check that it is not a legal scaled address. This avoids
1056 // ambiguity in the matcher.
1057 template<int Width>
1058 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001059 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001060 }
1061
1062 bool isAdrpLabel() const {
1063 // Validation was handled during parsing, so we just sanity check that
1064 // something didn't go haywire.
1065 if (!isImm())
1066 return false;
1067
1068 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1069 int64_t Val = CE->getValue();
1070 int64_t Min = - (4096 * (1LL << (21 - 1)));
1071 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1072 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1073 }
1074
1075 return true;
1076 }
1077
1078 bool isAdrLabel() const {
1079 // Validation was handled during parsing, so we just sanity check that
1080 // something didn't go haywire.
1081 if (!isImm())
1082 return false;
1083
1084 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1085 int64_t Val = CE->getValue();
1086 int64_t Min = - (1LL << (21 - 1));
1087 int64_t Max = ((1LL << (21 - 1)) - 1);
1088 return Val >= Min && Val <= Max;
1089 }
1090
1091 return true;
1092 }
1093
1094 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1095 // Add as immediates when possible. Null MCExpr = 0.
1096 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001097 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001098 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001099 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001100 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001101 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001102 }
1103
1104 void addRegOperands(MCInst &Inst, unsigned N) const {
1105 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001106 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001107 }
1108
1109 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1110 assert(N == 1 && "Invalid number of operands!");
1111 assert(
1112 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1113
1114 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1115 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1116 RI->getEncodingValue(getReg()));
1117
Jim Grosbache9119e42015-05-13 18:37:00 +00001118 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001119 }
1120
1121 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1122 assert(N == 1 && "Invalid number of operands!");
1123 assert(
1124 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001125 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001126 }
1127
1128 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1129 assert(N == 1 && "Invalid number of operands!");
1130 assert(
1131 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001132 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001133 }
1134
1135 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1136 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001137 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001138 }
1139
Sander de Smalen525e3222018-04-12 13:19:32 +00001140 enum VecListIndexType {
1141 VecListIdx_DReg = 0,
1142 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001143 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001144 };
1145
1146 template <VecListIndexType RegTy, unsigned NumRegs>
1147 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001148 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001149 static const unsigned FirstRegs[][5] = {
1150 /* DReg */ { AArch64::Q0,
1151 AArch64::D0, AArch64::D0_D1,
1152 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1153 /* QReg */ { AArch64::Q0,
1154 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001155 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1156 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001157 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001158 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001159 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001160
Sander de Smalen7a210db2018-04-16 10:46:18 +00001161 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1162 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001163
Sander de Smalen525e3222018-04-12 13:19:32 +00001164 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1165 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1166 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001167 }
1168
1169 void addVectorIndex1Operands(MCInst &Inst, unsigned N) const {
1170 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001171 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001172 }
1173
1174 void addVectorIndexBOperands(MCInst &Inst, unsigned N) const {
1175 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001176 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001177 }
1178
1179 void addVectorIndexHOperands(MCInst &Inst, unsigned N) const {
1180 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001181 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 }
1183
1184 void addVectorIndexSOperands(MCInst &Inst, unsigned N) const {
1185 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001186 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001187 }
1188
1189 void addVectorIndexDOperands(MCInst &Inst, unsigned N) const {
1190 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001191 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001192 }
1193
1194 void addImmOperands(MCInst &Inst, unsigned N) const {
1195 assert(N == 1 && "Invalid number of operands!");
1196 // If this is a pageoff symrefexpr with an addend, adjust the addend
1197 // to be only the page-offset portion. Otherwise, just add the expr
1198 // as-is.
1199 addExpr(Inst, getImm());
1200 }
1201
1202 void addAddSubImmOperands(MCInst &Inst, unsigned N) const {
1203 assert(N == 2 && "Invalid number of operands!");
1204 if (isShiftedImm()) {
1205 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001206 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001207 } else {
1208 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001209 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001210 }
1211 }
1212
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001213 void addAddSubImmNegOperands(MCInst &Inst, unsigned N) const {
1214 assert(N == 2 && "Invalid number of operands!");
1215
1216 const MCExpr *MCE = isShiftedImm() ? getShiftedImmVal() : getImm();
1217 const MCConstantExpr *CE = cast<MCConstantExpr>(MCE);
1218 int64_t Val = -CE->getValue();
1219 unsigned ShiftAmt = isShiftedImm() ? ShiftedImm.ShiftAmount : 0;
1220
1221 Inst.addOperand(MCOperand::createImm(Val));
1222 Inst.addOperand(MCOperand::createImm(ShiftAmt));
1223 }
1224
Tim Northover3b0846e2014-05-24 12:50:23 +00001225 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1226 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001227 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001228 }
1229
1230 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1231 assert(N == 1 && "Invalid number of operands!");
1232 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1233 if (!MCE)
1234 addExpr(Inst, getImm());
1235 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001236 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001237 }
1238
1239 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1240 addImmOperands(Inst, N);
1241 }
1242
1243 template<int Scale>
1244 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1245 assert(N == 1 && "Invalid number of operands!");
1246 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1247
1248 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001249 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001250 return;
1251 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001252 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001253 }
1254
1255 void addSImm9Operands(MCInst &Inst, unsigned N) const {
1256 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001257 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001258 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001259 }
1260
Sam Parker6d42de72017-08-11 13:14:00 +00001261 void addSImm10s8Operands(MCInst &Inst, unsigned N) const {
1262 assert(N == 1 && "Invalid number of operands!");
1263 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1264 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
1265 }
1266
Tim Northover3b0846e2014-05-24 12:50:23 +00001267 void addSImm7s4Operands(MCInst &Inst, unsigned N) const {
1268 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001269 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001270 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 4));
Tim Northover3b0846e2014-05-24 12:50:23 +00001271 }
1272
1273 void addSImm7s8Operands(MCInst &Inst, unsigned N) const {
1274 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001275 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001276 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 8));
Tim Northover3b0846e2014-05-24 12:50:23 +00001277 }
1278
1279 void addSImm7s16Operands(MCInst &Inst, unsigned N) const {
1280 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001281 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001282 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 16));
Tim Northover3b0846e2014-05-24 12:50:23 +00001283 }
1284
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001285 void addImm0_1Operands(MCInst &Inst, unsigned N) const {
1286 assert(N == 1 && "Invalid number of operands!");
1287 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1288 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1289 }
1290
Tim Northover3b0846e2014-05-24 12:50:23 +00001291 void addImm0_7Operands(MCInst &Inst, unsigned N) const {
1292 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001293 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001294 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001295 }
1296
1297 void addImm1_8Operands(MCInst &Inst, unsigned N) const {
1298 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001299 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001300 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001301 }
1302
1303 void addImm0_15Operands(MCInst &Inst, unsigned N) const {
1304 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001305 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001306 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001307 }
1308
1309 void addImm1_16Operands(MCInst &Inst, unsigned N) const {
1310 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001311 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001312 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001313 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001314 }
1315
1316 void addImm0_31Operands(MCInst &Inst, unsigned N) const {
1317 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001318 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001319 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001320 }
1321
1322 void addImm1_31Operands(MCInst &Inst, unsigned N) const {
1323 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001324 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001325 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001326 }
1327
1328 void addImm1_32Operands(MCInst &Inst, unsigned N) const {
1329 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001330 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001331 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001332 }
1333
1334 void addImm0_63Operands(MCInst &Inst, unsigned N) const {
1335 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001336 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001337 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001338 }
1339
1340 void addImm1_63Operands(MCInst &Inst, unsigned N) const {
1341 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001342 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001343 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001344 }
1345
1346 void addImm1_64Operands(MCInst &Inst, unsigned N) const {
1347 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001348 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001349 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001350 }
1351
1352 void addImm0_127Operands(MCInst &Inst, unsigned N) const {
1353 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001354 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001355 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001356 }
1357
1358 void addImm0_255Operands(MCInst &Inst, unsigned N) const {
1359 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001360 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001361 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001362 }
1363
1364 void addImm0_65535Operands(MCInst &Inst, unsigned N) const {
1365 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001366 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001367 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001368 }
1369
1370 void addImm32_63Operands(MCInst &Inst, unsigned N) const {
1371 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001372 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001373 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001374 }
1375
Sander de Smalen5c625982018-04-13 12:56:14 +00001376 template <int Scale>
1377 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1378 assert(N == 1 && "Invalid number of operands!");
1379 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1380 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1381 }
1382
Sander de Smalena1c259c2018-01-29 13:05:38 +00001383 template <typename T>
1384 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001385 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001386 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001387 typename std::make_unsigned<T>::type Val = MCE->getValue();
1388 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001389 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001390 }
1391
Sander de Smalena1c259c2018-01-29 13:05:38 +00001392 template <typename T>
1393 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001394 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001395 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001396 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1397 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001398 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001399 }
1400
Tim Northover3b0846e2014-05-24 12:50:23 +00001401 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1402 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001403 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001405 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 }
1407
1408 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1409 // Branch operands don't encode the low bits, so shift them off
1410 // here. If it's a label, however, just put it on directly as there's
1411 // not enough information now to do anything.
1412 assert(N == 1 && "Invalid number of operands!");
1413 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1414 if (!MCE) {
1415 addExpr(Inst, getImm());
1416 return;
1417 }
1418 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001419 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001420 }
1421
1422 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1423 // Branch operands don't encode the low bits, so shift them off
1424 // here. If it's a label, however, just put it on directly as there's
1425 // not enough information now to do anything.
1426 assert(N == 1 && "Invalid number of operands!");
1427 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1428 if (!MCE) {
1429 addExpr(Inst, getImm());
1430 return;
1431 }
1432 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001433 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001434 }
1435
1436 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1437 // Branch operands don't encode the low bits, so shift them off
1438 // here. If it's a label, however, just put it on directly as there's
1439 // not enough information now to do anything.
1440 assert(N == 1 && "Invalid number of operands!");
1441 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1442 if (!MCE) {
1443 addExpr(Inst, getImm());
1444 return;
1445 }
1446 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001447 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001448 }
1449
1450 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1451 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001452 Inst.addOperand(MCOperand::createImm(getFPImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 }
1454
1455 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1456 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001457 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 }
1459
1460 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462
Jim Grosbache9119e42015-05-13 18:37:00 +00001463 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 }
1465
1466 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1467 assert(N == 1 && "Invalid number of operands!");
1468
Jim Grosbache9119e42015-05-13 18:37:00 +00001469 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001472 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1473 assert(N == 1 && "Invalid number of operands!");
1474
1475 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1476 }
1477
1478 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001479 assert(N == 1 && "Invalid number of operands!");
1480
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
1484 void addSysCROperands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001486 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001487 }
1488
1489 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1490 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001491 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001492 }
1493
Oliver Stannarda34e4702015-12-01 10:48:51 +00001494 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1495 assert(N == 1 && "Invalid number of operands!");
1496 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1497 }
1498
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 void addShifterOperands(MCInst &Inst, unsigned N) const {
1500 assert(N == 1 && "Invalid number of operands!");
1501 unsigned Imm =
1502 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001503 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
1506 void addExtendOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1509 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1510 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001511 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001512 }
1513
1514 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1515 assert(N == 1 && "Invalid number of operands!");
1516 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1517 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1518 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001519 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001520 }
1521
1522 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1523 assert(N == 2 && "Invalid number of operands!");
1524 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1525 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001526 Inst.addOperand(MCOperand::createImm(IsSigned));
1527 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
1530 // For 8-bit load/store instructions with a register offset, both the
1531 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1532 // they're disambiguated by whether the shift was explicit or implicit rather
1533 // than its size.
1534 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1535 assert(N == 2 && "Invalid number of operands!");
1536 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1537 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001538 Inst.addOperand(MCOperand::createImm(IsSigned));
1539 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001540 }
1541
1542 template<int Shift>
1543 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1544 assert(N == 1 && "Invalid number of operands!");
1545
1546 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1547 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001548 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001549 }
1550
1551 template<int Shift>
1552 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1553 assert(N == 1 && "Invalid number of operands!");
1554
1555 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1556 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001557 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001558 }
1559
Sam Parker5f934642017-08-31 09:27:04 +00001560 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1561 assert(N == 1 && "Invalid number of operands!");
1562 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1563 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1564 }
1565
1566 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1567 assert(N == 1 && "Invalid number of operands!");
1568 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1569 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1570 }
1571
Tim Northover3b0846e2014-05-24 12:50:23 +00001572 void print(raw_ostream &OS) const override;
1573
David Blaikie960ea3f2014-06-08 16:18:35 +00001574 static std::unique_ptr<AArch64Operand>
1575 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1576 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001577 Op->Tok.Data = Str.data();
1578 Op->Tok.Length = Str.size();
1579 Op->Tok.IsSuffix = IsSuffix;
1580 Op->StartLoc = S;
1581 Op->EndLoc = S;
1582 return Op;
1583 }
1584
David Blaikie960ea3f2014-06-08 16:18:35 +00001585 static std::unique_ptr<AArch64Operand>
Florian Hahnc4422242017-11-07 13:07:50 +00001586 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001587 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001588 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001589 Op->Reg.Kind = Kind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001590 Op->StartLoc = S;
1591 Op->EndLoc = E;
1592 return Op;
1593 }
1594
David Blaikie960ea3f2014-06-08 16:18:35 +00001595 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001596 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
1597 SMLoc S, SMLoc E, MCContext &Ctx) {
1598 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1599 Kind == RegKind::SVEPredicateVector) &&
1600 "Invalid vector kind");
Florian Hahn91f11e52017-11-07 16:45:48 +00001601 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
1602 Op->Reg.RegNum = RegNum;
1603 Op->Reg.ElementWidth = ElementWidth;
1604 Op->Reg.Kind = Kind;
1605 Op->StartLoc = S;
1606 Op->EndLoc = E;
1607 return Op;
1608 }
1609
1610 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001611 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001612 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1613 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001614 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001615 Op->VectorList.RegNum = RegNum;
1616 Op->VectorList.Count = Count;
1617 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001618 Op->VectorList.ElementWidth = ElementWidth;
1619 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001620 Op->StartLoc = S;
1621 Op->EndLoc = E;
1622 return Op;
1623 }
1624
David Blaikie960ea3f2014-06-08 16:18:35 +00001625 static std::unique_ptr<AArch64Operand>
1626 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1627 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001628 Op->VectorIndex.Val = Idx;
1629 Op->StartLoc = S;
1630 Op->EndLoc = E;
1631 return Op;
1632 }
1633
David Blaikie960ea3f2014-06-08 16:18:35 +00001634 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1635 SMLoc E, MCContext &Ctx) {
1636 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001637 Op->Imm.Val = Val;
1638 Op->StartLoc = S;
1639 Op->EndLoc = E;
1640 return Op;
1641 }
1642
David Blaikie960ea3f2014-06-08 16:18:35 +00001643 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1644 unsigned ShiftAmount,
1645 SMLoc S, SMLoc E,
1646 MCContext &Ctx) {
1647 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001648 Op->ShiftedImm .Val = Val;
1649 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1650 Op->StartLoc = S;
1651 Op->EndLoc = E;
1652 return Op;
1653 }
1654
David Blaikie960ea3f2014-06-08 16:18:35 +00001655 static std::unique_ptr<AArch64Operand>
1656 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1657 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001658 Op->CondCode.Code = Code;
1659 Op->StartLoc = S;
1660 Op->EndLoc = E;
1661 return Op;
1662 }
1663
David Blaikie960ea3f2014-06-08 16:18:35 +00001664 static std::unique_ptr<AArch64Operand> CreateFPImm(unsigned Val, SMLoc S,
1665 MCContext &Ctx) {
1666 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001667 Op->FPImm.Val = Val;
1668 Op->StartLoc = S;
1669 Op->EndLoc = S;
1670 return Op;
1671 }
1672
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001673 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1674 StringRef Str,
1675 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001676 MCContext &Ctx) {
1677 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001678 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001679 Op->Barrier.Data = Str.data();
1680 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001681 Op->StartLoc = S;
1682 Op->EndLoc = S;
1683 return Op;
1684 }
1685
Tim Northover7cd58932015-01-22 17:23:04 +00001686 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1687 uint32_t MRSReg,
1688 uint32_t MSRReg,
1689 uint32_t PStateField,
1690 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001691 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001692 Op->SysReg.Data = Str.data();
1693 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001694 Op->SysReg.MRSReg = MRSReg;
1695 Op->SysReg.MSRReg = MSRReg;
1696 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001697 Op->StartLoc = S;
1698 Op->EndLoc = S;
1699 return Op;
1700 }
1701
David Blaikie960ea3f2014-06-08 16:18:35 +00001702 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1703 SMLoc E, MCContext &Ctx) {
1704 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001705 Op->SysCRImm.Val = Val;
1706 Op->StartLoc = S;
1707 Op->EndLoc = E;
1708 return Op;
1709 }
1710
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001711 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1712 StringRef Str,
1713 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001714 MCContext &Ctx) {
1715 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001716 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001717 Op->Barrier.Data = Str.data();
1718 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 Op->StartLoc = S;
1720 Op->EndLoc = S;
1721 return Op;
1722 }
1723
Oliver Stannarda34e4702015-12-01 10:48:51 +00001724 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1725 StringRef Str,
1726 SMLoc S,
1727 MCContext &Ctx) {
1728 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1729 Op->PSBHint.Val = Val;
1730 Op->PSBHint.Data = Str.data();
1731 Op->PSBHint.Length = Str.size();
1732 Op->StartLoc = S;
1733 Op->EndLoc = S;
1734 return Op;
1735 }
1736
David Blaikie960ea3f2014-06-08 16:18:35 +00001737 static std::unique_ptr<AArch64Operand>
1738 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1739 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1740 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001741 Op->ShiftExtend.Type = ShOp;
1742 Op->ShiftExtend.Amount = Val;
1743 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1744 Op->StartLoc = S;
1745 Op->EndLoc = E;
1746 return Op;
1747 }
1748};
1749
1750} // end anonymous namespace.
1751
1752void AArch64Operand::print(raw_ostream &OS) const {
1753 switch (Kind) {
1754 case k_FPImm:
1755 OS << "<fpimm " << getFPImm() << "("
1756 << AArch64_AM::getFPImmFloat(getFPImm()) << ") >";
1757 break;
1758 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001759 StringRef Name = getBarrierName();
1760 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001761 OS << "<barrier " << Name << ">";
1762 else
1763 OS << "<barrier invalid #" << getBarrier() << ">";
1764 break;
1765 }
1766 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001767 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001768 break;
1769 case k_ShiftedImm: {
1770 unsigned Shift = getShiftedImmShift();
1771 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001772 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001773 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1774 break;
1775 }
1776 case k_CondCode:
1777 OS << "<condcode " << getCondCode() << ">";
1778 break;
1779 case k_Register:
1780 OS << "<register " << getReg() << ">";
1781 break;
1782 case k_VectorList: {
1783 OS << "<vectorlist ";
1784 unsigned Reg = getVectorListStart();
1785 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
1786 OS << Reg + i << " ";
1787 OS << ">";
1788 break;
1789 }
1790 case k_VectorIndex:
1791 OS << "<vectorindex " << getVectorIndex() << ">";
1792 break;
1793 case k_SysReg:
1794 OS << "<sysreg: " << getSysReg() << '>';
1795 break;
1796 case k_Token:
1797 OS << "'" << getToken() << "'";
1798 break;
1799 case k_SysCR:
1800 OS << "c" << getSysCR();
1801 break;
1802 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001803 StringRef Name = getPrefetchName();
1804 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001805 OS << "<prfop " << Name << ">";
1806 else
1807 OS << "<prfop invalid #" << getPrefetch() << ">";
1808 break;
1809 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001810 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00001811 OS << getPSBHintName();
1812 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00001813 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00001814 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
1815 << getShiftExtendAmount();
1816 if (!hasShiftExtendAmount())
1817 OS << "<imp>";
1818 OS << '>';
1819 break;
1820 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001821}
1822
1823/// @name Auto-generated Match Functions
1824/// {
1825
1826static unsigned MatchRegisterName(StringRef Name);
1827
1828/// }
1829
Florian Hahnc4422242017-11-07 13:07:50 +00001830static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00001831 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00001832 .Case("v0", AArch64::Q0)
1833 .Case("v1", AArch64::Q1)
1834 .Case("v2", AArch64::Q2)
1835 .Case("v3", AArch64::Q3)
1836 .Case("v4", AArch64::Q4)
1837 .Case("v5", AArch64::Q5)
1838 .Case("v6", AArch64::Q6)
1839 .Case("v7", AArch64::Q7)
1840 .Case("v8", AArch64::Q8)
1841 .Case("v9", AArch64::Q9)
1842 .Case("v10", AArch64::Q10)
1843 .Case("v11", AArch64::Q11)
1844 .Case("v12", AArch64::Q12)
1845 .Case("v13", AArch64::Q13)
1846 .Case("v14", AArch64::Q14)
1847 .Case("v15", AArch64::Q15)
1848 .Case("v16", AArch64::Q16)
1849 .Case("v17", AArch64::Q17)
1850 .Case("v18", AArch64::Q18)
1851 .Case("v19", AArch64::Q19)
1852 .Case("v20", AArch64::Q20)
1853 .Case("v21", AArch64::Q21)
1854 .Case("v22", AArch64::Q22)
1855 .Case("v23", AArch64::Q23)
1856 .Case("v24", AArch64::Q24)
1857 .Case("v25", AArch64::Q25)
1858 .Case("v26", AArch64::Q26)
1859 .Case("v27", AArch64::Q27)
1860 .Case("v28", AArch64::Q28)
1861 .Case("v29", AArch64::Q29)
1862 .Case("v30", AArch64::Q30)
1863 .Case("v31", AArch64::Q31)
1864 .Default(0);
1865}
1866
Sander de Smalen73937b72018-04-11 07:36:10 +00001867/// Returns an optional pair of (#elements, element-width) if Suffix
1868/// is a valid vector kind. Where the number of elements in a vector
1869/// or the vector width is implicit or explicitly unknown (but still a
1870/// valid suffix kind), 0 is used.
1871static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
1872 RegKind VectorKind) {
1873 std::pair<int, int> Res = {-1, -1};
1874
1875 switch (VectorKind) {
1876 case RegKind::NeonVector:
1877 Res =
1878 StringSwitch<std::pair<int, int>>(Suffix.lower())
1879 .Case("", {0, 0})
1880 .Case(".1d", {1, 64})
1881 .Case(".1q", {1, 128})
1882 // '.2h' needed for fp16 scalar pairwise reductions
1883 .Case(".2h", {2, 16})
1884 .Case(".2s", {2, 32})
1885 .Case(".2d", {2, 64})
1886 // '.4b' is another special case for the ARMv8.2a dot product
1887 // operand
1888 .Case(".4b", {4, 8})
1889 .Case(".4h", {4, 16})
1890 .Case(".4s", {4, 32})
1891 .Case(".8b", {8, 8})
1892 .Case(".8h", {8, 16})
1893 .Case(".16b", {16, 8})
1894 // Accept the width neutral ones, too, for verbose syntax. If those
1895 // aren't used in the right places, the token operand won't match so
1896 // all will work out.
1897 .Case(".b", {0, 8})
1898 .Case(".h", {0, 16})
1899 .Case(".s", {0, 32})
1900 .Case(".d", {0, 64})
1901 .Default({-1, -1});
1902 break;
1903 case RegKind::SVEPredicateVector:
1904 case RegKind::SVEDataVector:
1905 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
1906 .Case("", {0, 0})
1907 .Case(".b", {0, 8})
1908 .Case(".h", {0, 16})
1909 .Case(".s", {0, 32})
1910 .Case(".d", {0, 64})
1911 .Case(".q", {0, 128})
1912 .Default({-1, -1});
1913 break;
1914 default:
1915 llvm_unreachable("Unsupported RegKind");
1916 }
1917
1918 if (Res == std::make_pair(-1, -1))
1919 return Optional<std::pair<int, int>>();
1920
1921 return Optional<std::pair<int, int>>(Res);
1922}
1923
1924static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
1925 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00001926}
1927
Florian Hahn91f11e52017-11-07 16:45:48 +00001928static unsigned matchSVEDataVectorRegName(StringRef Name) {
1929 return StringSwitch<unsigned>(Name.lower())
1930 .Case("z0", AArch64::Z0)
1931 .Case("z1", AArch64::Z1)
1932 .Case("z2", AArch64::Z2)
1933 .Case("z3", AArch64::Z3)
1934 .Case("z4", AArch64::Z4)
1935 .Case("z5", AArch64::Z5)
1936 .Case("z6", AArch64::Z6)
1937 .Case("z7", AArch64::Z7)
1938 .Case("z8", AArch64::Z8)
1939 .Case("z9", AArch64::Z9)
1940 .Case("z10", AArch64::Z10)
1941 .Case("z11", AArch64::Z11)
1942 .Case("z12", AArch64::Z12)
1943 .Case("z13", AArch64::Z13)
1944 .Case("z14", AArch64::Z14)
1945 .Case("z15", AArch64::Z15)
1946 .Case("z16", AArch64::Z16)
1947 .Case("z17", AArch64::Z17)
1948 .Case("z18", AArch64::Z18)
1949 .Case("z19", AArch64::Z19)
1950 .Case("z20", AArch64::Z20)
1951 .Case("z21", AArch64::Z21)
1952 .Case("z22", AArch64::Z22)
1953 .Case("z23", AArch64::Z23)
1954 .Case("z24", AArch64::Z24)
1955 .Case("z25", AArch64::Z25)
1956 .Case("z26", AArch64::Z26)
1957 .Case("z27", AArch64::Z27)
1958 .Case("z28", AArch64::Z28)
1959 .Case("z29", AArch64::Z29)
1960 .Case("z30", AArch64::Z30)
1961 .Case("z31", AArch64::Z31)
1962 .Default(0);
1963}
1964
Sander de Smalencd6be962017-12-20 11:02:42 +00001965static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
1966 return StringSwitch<unsigned>(Name.lower())
1967 .Case("p0", AArch64::P0)
1968 .Case("p1", AArch64::P1)
1969 .Case("p2", AArch64::P2)
1970 .Case("p3", AArch64::P3)
1971 .Case("p4", AArch64::P4)
1972 .Case("p5", AArch64::P5)
1973 .Case("p6", AArch64::P6)
1974 .Case("p7", AArch64::P7)
1975 .Case("p8", AArch64::P8)
1976 .Case("p9", AArch64::P9)
1977 .Case("p10", AArch64::P10)
1978 .Case("p11", AArch64::P11)
1979 .Case("p12", AArch64::P12)
1980 .Case("p13", AArch64::P13)
1981 .Case("p14", AArch64::P14)
1982 .Case("p15", AArch64::P15)
1983 .Default(0);
1984}
1985
Tim Northover3b0846e2014-05-24 12:50:23 +00001986bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
1987 SMLoc &EndLoc) {
1988 StartLoc = getLoc();
1989 RegNo = tryParseRegister();
1990 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
1991 return (RegNo == (unsigned)-1);
1992}
1993
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00001994// Matches a register name or register alias previously defined by '.req'
1995unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00001996 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00001997 unsigned RegNum = 0;
1998 if ((RegNum = matchSVEDataVectorRegName(Name)))
1999 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2000
Sander de Smalencd6be962017-12-20 11:02:42 +00002001 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2002 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2003
Sander de Smalenc067c302017-12-20 09:45:45 +00002004 if ((RegNum = MatchNeonVectorRegName(Name)))
2005 return Kind == RegKind::NeonVector ? RegNum : 0;
2006
2007 // The parsed register must be of RegKind Scalar
2008 if ((RegNum = MatchRegisterName(Name)))
2009 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002010
Florian Hahnc4422242017-11-07 13:07:50 +00002011 if (!RegNum) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002012 // Check for aliases registered via .req. Canonicalize to lower case.
2013 // That's more consistent since register names are case insensitive, and
2014 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2015 auto Entry = RegisterReqs.find(Name.lower());
2016 if (Entry == RegisterReqs.end())
2017 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002018
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002019 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002020 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002021 RegNum = Entry->getValue().second;
2022 }
2023 return RegNum;
2024}
2025
Tim Northover3b0846e2014-05-24 12:50:23 +00002026/// tryParseRegister - Try to parse a register name. The token must be an
2027/// Identifier when called, and if it is a register name the token is eaten and
2028/// the register is added to the operand list.
2029int AArch64AsmParser::tryParseRegister() {
Rafael Espindola961d4692014-11-11 05:18:41 +00002030 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002031 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002032 if (Tok.isNot(AsmToken::Identifier))
2033 return -1;
Tim Northover3b0846e2014-05-24 12:50:23 +00002034
2035 std::string lowerCase = Tok.getString().lower();
Florian Hahnc4422242017-11-07 13:07:50 +00002036 unsigned RegNum = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
Sander de Smalenc067c302017-12-20 09:45:45 +00002037
Tim Northover3b0846e2014-05-24 12:50:23 +00002038 // Also handle a few aliases of registers.
2039 if (RegNum == 0)
2040 RegNum = StringSwitch<unsigned>(lowerCase)
2041 .Case("fp", AArch64::FP)
2042 .Case("lr", AArch64::LR)
2043 .Case("x31", AArch64::XZR)
2044 .Case("w31", AArch64::WZR)
2045 .Default(0);
2046
2047 if (RegNum == 0)
2048 return -1;
2049
2050 Parser.Lex(); // Eat identifier token.
2051 return RegNum;
2052}
2053
Tim Northover3b0846e2014-05-24 12:50:23 +00002054/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002055OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002056AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002057 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002058 SMLoc S = getLoc();
2059
2060 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2061 Error(S, "Expected cN operand where 0 <= N <= 15");
2062 return MatchOperand_ParseFail;
2063 }
2064
2065 StringRef Tok = Parser.getTok().getIdentifier();
2066 if (Tok[0] != 'c' && Tok[0] != 'C') {
2067 Error(S, "Expected cN operand where 0 <= N <= 15");
2068 return MatchOperand_ParseFail;
2069 }
2070
2071 uint32_t CRNum;
2072 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2073 if (BadNum || CRNum > 15) {
2074 Error(S, "Expected cN operand where 0 <= N <= 15");
2075 return MatchOperand_ParseFail;
2076 }
2077
2078 Parser.Lex(); // Eat identifier token.
2079 Operands.push_back(
2080 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2081 return MatchOperand_Success;
2082}
2083
2084/// tryParsePrefetch - Try to parse a prefetch operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002085OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002086AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002087 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002088 SMLoc S = getLoc();
2089 const AsmToken &Tok = Parser.getTok();
2090 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002091 // Eat optional hash.
2092 if (parseOptionalToken(AsmToken::Hash) ||
2093 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002094 const MCExpr *ImmVal;
2095 if (getParser().parseExpression(ImmVal))
2096 return MatchOperand_ParseFail;
2097
2098 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2099 if (!MCE) {
2100 TokError("immediate value expected for prefetch operand");
2101 return MatchOperand_ParseFail;
2102 }
2103 unsigned prfop = MCE->getValue();
2104 if (prfop > 31) {
2105 TokError("prefetch operand out of range, [0,31] expected");
2106 return MatchOperand_ParseFail;
2107 }
2108
Tim Northovere6ae6762016-07-05 21:23:04 +00002109 auto PRFM = AArch64PRFM::lookupPRFMByEncoding(MCE->getValue());
2110 Operands.push_back(AArch64Operand::CreatePrefetch(
2111 prfop, PRFM ? PRFM->Name : "", S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002112 return MatchOperand_Success;
2113 }
2114
2115 if (Tok.isNot(AsmToken::Identifier)) {
2116 TokError("pre-fetch hint expected");
2117 return MatchOperand_ParseFail;
2118 }
2119
Tim Northovere6ae6762016-07-05 21:23:04 +00002120 auto PRFM = AArch64PRFM::lookupPRFMByName(Tok.getString());
2121 if (!PRFM) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002122 TokError("pre-fetch hint expected");
2123 return MatchOperand_ParseFail;
2124 }
2125
2126 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002127 Operands.push_back(AArch64Operand::CreatePrefetch(
2128 PRFM->Encoding, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002129 return MatchOperand_Success;
2130}
2131
Oliver Stannarda34e4702015-12-01 10:48:51 +00002132/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002133OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002134AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2135 MCAsmParser &Parser = getParser();
2136 SMLoc S = getLoc();
2137 const AsmToken &Tok = Parser.getTok();
2138 if (Tok.isNot(AsmToken::Identifier)) {
2139 TokError("invalid operand for instruction");
2140 return MatchOperand_ParseFail;
2141 }
2142
Tim Northovere6ae6762016-07-05 21:23:04 +00002143 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2144 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002145 TokError("invalid operand for instruction");
2146 return MatchOperand_ParseFail;
2147 }
2148
2149 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002150 Operands.push_back(AArch64Operand::CreatePSBHint(
2151 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002152 return MatchOperand_Success;
2153}
2154
Tim Northover3b0846e2014-05-24 12:50:23 +00002155/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2156/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002157OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002158AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002159 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002160 SMLoc S = getLoc();
2161 const MCExpr *Expr;
2162
2163 if (Parser.getTok().is(AsmToken::Hash)) {
2164 Parser.Lex(); // Eat hash token.
2165 }
2166
2167 if (parseSymbolicImmVal(Expr))
2168 return MatchOperand_ParseFail;
2169
2170 AArch64MCExpr::VariantKind ELFRefKind;
2171 MCSymbolRefExpr::VariantKind DarwinRefKind;
2172 int64_t Addend;
2173 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2174 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2175 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2176 // No modifier was specified at all; this is the syntax for an ELF basic
2177 // ADRP relocation (unfortunately).
2178 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002179 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002180 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2181 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2182 Addend != 0) {
2183 Error(S, "gotpage label reference not allowed an addend");
2184 return MatchOperand_ParseFail;
2185 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2186 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2187 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2188 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2189 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2190 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2191 // The operand must be an @page or @gotpage qualified symbolref.
2192 Error(S, "page or gotpage label reference expected");
2193 return MatchOperand_ParseFail;
2194 }
2195 }
2196
2197 // We have either a label reference possibly with addend or an immediate. The
2198 // addend is a raw value here. The linker will adjust it to only reference the
2199 // page.
2200 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2201 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2202
2203 return MatchOperand_Success;
2204}
2205
2206/// tryParseAdrLabel - Parse and validate a source label for the ADR
2207/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002208OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002209AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2210 SMLoc S = getLoc();
2211 const MCExpr *Expr;
2212
Nirav Davee833c6c2016-11-08 18:31:04 +00002213 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002214 if (getParser().parseExpression(Expr))
2215 return MatchOperand_ParseFail;
2216
2217 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2218 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2219
2220 return MatchOperand_Success;
2221}
2222
2223/// tryParseFPImm - A floating point immediate expression operand.
Alex Bradbury58eba092016-11-01 16:32:05 +00002224OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002225AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002226 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002227 SMLoc S = getLoc();
2228
Nirav Davee833c6c2016-11-08 18:31:04 +00002229 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002230
2231 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002232 bool isNegative = parseOptionalToken(AsmToken::Minus);
2233
Tim Northover3b0846e2014-05-24 12:50:23 +00002234 const AsmToken &Tok = Parser.getTok();
John Brawndcf037a2017-04-20 10:10:10 +00002235 if (Tok.is(AsmToken::Real) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002236 int64_t Val;
John Brawndcf037a2017-04-20 10:10:10 +00002237 if (Tok.is(AsmToken::Integer) && !isNegative && Tok.getString().startswith("0x")) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002238 Val = Tok.getIntVal();
2239 if (Val > 255 || Val < 0) {
2240 TokError("encoded floating point value out of range");
2241 return MatchOperand_ParseFail;
2242 }
2243 } else {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00002244 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
John Brawndcf037a2017-04-20 10:10:10 +00002245 if (isNegative)
2246 RealVal.changeSign();
2247
Tim Northover3b0846e2014-05-24 12:50:23 +00002248 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002249 Val = AArch64_AM::getFP64Imm(APInt(64, IntVal));
John Brawndcf037a2017-04-20 10:10:10 +00002250
John Brawn5ca5daa2017-04-20 10:13:54 +00002251 // Check for out of range values. As an exception we let Zero through,
2252 // but as tokens instead of an FPImm so that it can be matched by the
2253 // appropriate alias if one exists.
2254 if (RealVal.isPosZero()) {
2255 Parser.Lex(); // Eat the token.
2256 Operands.push_back(AArch64Operand::CreateToken("#0", false, S, getContext()));
2257 Operands.push_back(AArch64Operand::CreateToken(".0", false, S, getContext()));
2258 return MatchOperand_Success;
2259 } else if (Val == -1) {
John Brawndcf037a2017-04-20 10:10:10 +00002260 TokError("expected compatible register or floating-point constant");
2261 return MatchOperand_ParseFail;
2262 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002263 }
2264 Parser.Lex(); // Eat the token.
2265 Operands.push_back(AArch64Operand::CreateFPImm(Val, S, getContext()));
2266 return MatchOperand_Success;
2267 }
2268
2269 if (!Hash)
2270 return MatchOperand_NoMatch;
2271
2272 TokError("invalid floating point immediate");
2273 return MatchOperand_ParseFail;
2274}
2275
2276/// tryParseAddSubImm - Parse ADD/SUB shifted immediate operand
Alex Bradbury58eba092016-11-01 16:32:05 +00002277OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002278AArch64AsmParser::tryParseAddSubImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002279 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002280 SMLoc S = getLoc();
2281
2282 if (Parser.getTok().is(AsmToken::Hash))
2283 Parser.Lex(); // Eat '#'
2284 else if (Parser.getTok().isNot(AsmToken::Integer))
2285 // Operand should start from # or should be integer, emit error otherwise.
2286 return MatchOperand_NoMatch;
2287
2288 const MCExpr *Imm;
2289 if (parseSymbolicImmVal(Imm))
2290 return MatchOperand_ParseFail;
2291 else if (Parser.getTok().isNot(AsmToken::Comma)) {
2292 uint64_t ShiftAmount = 0;
2293 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(Imm);
2294 if (MCE) {
2295 int64_t Val = MCE->getValue();
2296 if (Val > 0xfff && (Val & 0xfff) == 0) {
Jim Grosbach13760bd2015-05-30 01:25:56 +00002297 Imm = MCConstantExpr::create(Val >> 12, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002298 ShiftAmount = 12;
2299 }
2300 }
2301 SMLoc E = Parser.getTok().getLoc();
2302 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount, S, E,
2303 getContext()));
2304 return MatchOperand_Success;
2305 }
2306
2307 // Eat ','
2308 Parser.Lex();
2309
2310 // The optional operand must be "lsl #N" where N is non-negative.
2311 if (!Parser.getTok().is(AsmToken::Identifier) ||
2312 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2313 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2314 return MatchOperand_ParseFail;
2315 }
2316
2317 // Eat 'lsl'
2318 Parser.Lex();
2319
Nirav Davee833c6c2016-11-08 18:31:04 +00002320 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002321
2322 if (Parser.getTok().isNot(AsmToken::Integer)) {
2323 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2324 return MatchOperand_ParseFail;
2325 }
2326
2327 int64_t ShiftAmount = Parser.getTok().getIntVal();
2328
2329 if (ShiftAmount < 0) {
2330 Error(Parser.getTok().getLoc(), "positive shift amount required");
2331 return MatchOperand_ParseFail;
2332 }
2333 Parser.Lex(); // Eat the number
2334
2335 SMLoc E = Parser.getTok().getLoc();
2336 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2337 S, E, getContext()));
2338 return MatchOperand_Success;
2339}
2340
2341/// parseCondCodeString - Parse a Condition Code string.
2342AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2343 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2344 .Case("eq", AArch64CC::EQ)
2345 .Case("ne", AArch64CC::NE)
2346 .Case("cs", AArch64CC::HS)
2347 .Case("hs", AArch64CC::HS)
2348 .Case("cc", AArch64CC::LO)
2349 .Case("lo", AArch64CC::LO)
2350 .Case("mi", AArch64CC::MI)
2351 .Case("pl", AArch64CC::PL)
2352 .Case("vs", AArch64CC::VS)
2353 .Case("vc", AArch64CC::VC)
2354 .Case("hi", AArch64CC::HI)
2355 .Case("ls", AArch64CC::LS)
2356 .Case("ge", AArch64CC::GE)
2357 .Case("lt", AArch64CC::LT)
2358 .Case("gt", AArch64CC::GT)
2359 .Case("le", AArch64CC::LE)
2360 .Case("al", AArch64CC::AL)
2361 .Case("nv", AArch64CC::NV)
2362 .Default(AArch64CC::Invalid);
2363 return CC;
2364}
2365
2366/// parseCondCode - Parse a Condition Code operand.
2367bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2368 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002369 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002370 SMLoc S = getLoc();
2371 const AsmToken &Tok = Parser.getTok();
2372 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2373
2374 StringRef Cond = Tok.getString();
2375 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2376 if (CC == AArch64CC::Invalid)
2377 return TokError("invalid condition code");
2378 Parser.Lex(); // Eat identifier token.
2379
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002380 if (invertCondCode) {
2381 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2382 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002383 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002384 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002385
2386 Operands.push_back(
2387 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2388 return false;
2389}
2390
2391/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2392/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002393OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002394AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002395 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002396 const AsmToken &Tok = Parser.getTok();
2397 std::string LowerID = Tok.getString().lower();
2398 AArch64_AM::ShiftExtendType ShOp =
2399 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2400 .Case("lsl", AArch64_AM::LSL)
2401 .Case("lsr", AArch64_AM::LSR)
2402 .Case("asr", AArch64_AM::ASR)
2403 .Case("ror", AArch64_AM::ROR)
2404 .Case("msl", AArch64_AM::MSL)
2405 .Case("uxtb", AArch64_AM::UXTB)
2406 .Case("uxth", AArch64_AM::UXTH)
2407 .Case("uxtw", AArch64_AM::UXTW)
2408 .Case("uxtx", AArch64_AM::UXTX)
2409 .Case("sxtb", AArch64_AM::SXTB)
2410 .Case("sxth", AArch64_AM::SXTH)
2411 .Case("sxtw", AArch64_AM::SXTW)
2412 .Case("sxtx", AArch64_AM::SXTX)
2413 .Default(AArch64_AM::InvalidShiftExtend);
2414
2415 if (ShOp == AArch64_AM::InvalidShiftExtend)
2416 return MatchOperand_NoMatch;
2417
2418 SMLoc S = Tok.getLoc();
2419 Parser.Lex();
2420
Nirav Davee833c6c2016-11-08 18:31:04 +00002421 bool Hash = parseOptionalToken(AsmToken::Hash);
2422
Tim Northover3b0846e2014-05-24 12:50:23 +00002423 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2424 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2425 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2426 ShOp == AArch64_AM::MSL) {
2427 // We expect a number here.
2428 TokError("expected #imm after shift specifier");
2429 return MatchOperand_ParseFail;
2430 }
2431
Chad Rosier2ff37b82016-12-27 16:58:09 +00002432 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002433 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2434 Operands.push_back(
2435 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2436 return MatchOperand_Success;
2437 }
2438
Chad Rosier2ff37b82016-12-27 16:58:09 +00002439 // Make sure we do actually have a number, identifier or a parenthesized
2440 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002441 SMLoc E = Parser.getTok().getLoc();
2442 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002443 !Parser.getTok().is(AsmToken::LParen) &&
2444 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002445 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002446 return MatchOperand_ParseFail;
2447 }
2448
2449 const MCExpr *ImmVal;
2450 if (getParser().parseExpression(ImmVal))
2451 return MatchOperand_ParseFail;
2452
2453 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2454 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002455 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002456 return MatchOperand_ParseFail;
2457 }
2458
Jim Grosbach57fd2622014-09-23 22:16:02 +00002459 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002460 Operands.push_back(AArch64Operand::CreateShiftExtend(
2461 ShOp, MCE->getValue(), true, S, E, getContext()));
2462 return MatchOperand_Success;
2463}
2464
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002465static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2466 if (FBS[AArch64::HasV8_1aOps])
2467 Str += "ARMv8.1a";
2468 else if (FBS[AArch64::HasV8_2aOps])
2469 Str += "ARMv8.2a";
2470 else
2471 Str += "(unknown)";
2472}
2473
2474void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2475 SMLoc S) {
2476 const uint16_t Op2 = Encoding & 7;
2477 const uint16_t Cm = (Encoding & 0x78) >> 3;
2478 const uint16_t Cn = (Encoding & 0x780) >> 7;
2479 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2480
2481 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2482
2483 Operands.push_back(
2484 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2485 Operands.push_back(
2486 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2487 Operands.push_back(
2488 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2489 Expr = MCConstantExpr::create(Op2, getContext());
2490 Operands.push_back(
2491 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2492}
2493
Tim Northover3b0846e2014-05-24 12:50:23 +00002494/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2495/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2496bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2497 OperandVector &Operands) {
2498 if (Name.find('.') != StringRef::npos)
2499 return TokError("invalid operand");
2500
2501 Mnemonic = Name;
2502 Operands.push_back(
2503 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2504
Rafael Espindola961d4692014-11-11 05:18:41 +00002505 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002506 const AsmToken &Tok = Parser.getTok();
2507 StringRef Op = Tok.getString();
2508 SMLoc S = Tok.getLoc();
2509
Tim Northover3b0846e2014-05-24 12:50:23 +00002510 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002511 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2512 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002513 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002514 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2515 std::string Str("IC " + std::string(IC->Name) + " requires ");
2516 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2517 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002518 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002519 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002520 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002521 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2522 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002523 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002524 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2525 std::string Str("DC " + std::string(DC->Name) + " requires ");
2526 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2527 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002528 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002529 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002530 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002531 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2532 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002533 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002534 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2535 std::string Str("AT " + std::string(AT->Name) + " requires ");
2536 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2537 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002538 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002539 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002540 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002541 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2542 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002543 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002544 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2545 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2546 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2547 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002548 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002549 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002550 }
2551
Tim Northover3b0846e2014-05-24 12:50:23 +00002552 Parser.Lex(); // Eat operand.
2553
2554 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2555 bool HasRegister = false;
2556
2557 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002558 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002559 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2560 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002561 HasRegister = true;
2562 }
2563
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002564 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002565 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002566 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002567 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002568
Nirav Davee833c6c2016-11-08 18:31:04 +00002569 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2570 return true;
2571
Tim Northover3b0846e2014-05-24 12:50:23 +00002572 return false;
2573}
2574
Alex Bradbury58eba092016-11-01 16:32:05 +00002575OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002576AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002577 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002578 const AsmToken &Tok = Parser.getTok();
2579
2580 // Can be either a #imm style literal or an option name
Nirav Davee833c6c2016-11-08 18:31:04 +00002581 if (parseOptionalToken(AsmToken::Hash) ||
2582 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002583 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002584 const MCExpr *ImmVal;
2585 SMLoc ExprLoc = getLoc();
2586 if (getParser().parseExpression(ImmVal))
2587 return MatchOperand_ParseFail;
2588 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2589 if (!MCE) {
2590 Error(ExprLoc, "immediate value expected for barrier operand");
2591 return MatchOperand_ParseFail;
2592 }
2593 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2594 Error(ExprLoc, "barrier operand out of range");
2595 return MatchOperand_ParseFail;
2596 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002597 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2598 Operands.push_back(AArch64Operand::CreateBarrier(
2599 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002600 return MatchOperand_Success;
2601 }
2602
2603 if (Tok.isNot(AsmToken::Identifier)) {
2604 TokError("invalid operand for instruction");
2605 return MatchOperand_ParseFail;
2606 }
2607
Tim Northover3b0846e2014-05-24 12:50:23 +00002608 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002609 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2610 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002611 TokError("'sy' or #imm operand expected");
2612 return MatchOperand_ParseFail;
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002613 } else if (!DB) {
2614 TokError("invalid barrier option name");
2615 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002616 }
2617
Tim Northovere6ae6762016-07-05 21:23:04 +00002618 Operands.push_back(AArch64Operand::CreateBarrier(
2619 DB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002620 Parser.Lex(); // Consume the option
2621
2622 return MatchOperand_Success;
2623}
2624
Alex Bradbury58eba092016-11-01 16:32:05 +00002625OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002626AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002627 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002628 const AsmToken &Tok = Parser.getTok();
2629
2630 if (Tok.isNot(AsmToken::Identifier))
2631 return MatchOperand_NoMatch;
2632
Tim Northovere6ae6762016-07-05 21:23:04 +00002633 int MRSReg, MSRReg;
2634 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2635 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2636 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2637 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2638 } else
2639 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002640
Tim Northovere6ae6762016-07-05 21:23:04 +00002641 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2642 unsigned PStateImm = -1;
2643 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2644 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002645
Tim Northovere6ae6762016-07-05 21:23:04 +00002646 Operands.push_back(
2647 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2648 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002649 Parser.Lex(); // Eat identifier
2650
2651 return MatchOperand_Success;
2652}
2653
Florian Hahnc4422242017-11-07 13:07:50 +00002654/// tryParseNeonVectorRegister - Parse a vector register operand.
2655bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002656 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002657 if (Parser.getTok().isNot(AsmToken::Identifier))
2658 return true;
2659
2660 SMLoc S = getLoc();
2661 // Check for a vector register specifier first.
2662 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002663 int Reg = -1;
2664 OperandMatchResultTy Res =
2665 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2666 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002667 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002668
2669 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2670 if (!KindRes)
2671 return true;
2672
2673 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002674 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002675 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2676 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002677
Tim Northover3b0846e2014-05-24 12:50:23 +00002678 // If there was an explicit qualifier, that goes on as a literal text
2679 // operand.
2680 if (!Kind.empty())
2681 Operands.push_back(
2682 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2683
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002684 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2685}
2686
2687OperandMatchResultTy
2688AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002689 SMLoc SIdx = getLoc();
2690 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002691 const MCExpr *ImmVal;
2692 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002693 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002694 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2695 if (!MCE) {
2696 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002697 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002698 }
2699
2700 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002701
Nirav Davee833c6c2016-11-08 18:31:04 +00002702 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002703 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002704
2705 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2706 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002707 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002708 }
2709
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002710 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002711}
2712
Sander de Smalen73937b72018-04-11 07:36:10 +00002713// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002714// optional kind specifier. If it is a register specifier, eat the token
2715// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002716OperandMatchResultTy
Sander de Smalen73937b72018-04-11 07:36:10 +00002717AArch64AsmParser::tryParseVectorRegister(int &Reg, StringRef &Kind,
2718 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002719 MCAsmParser &Parser = getParser();
2720 const AsmToken &Tok = Parser.getTok();
2721
Florian Hahn91f11e52017-11-07 16:45:48 +00002722 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002723 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002724
2725 StringRef Name = Tok.getString();
2726 // If there is a kind specifier, it's separated from the register name by
2727 // a '.'.
2728 size_t Start = 0, Next = Name.find('.');
2729 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00002730 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00002731
2732 if (RegNum) {
2733 if (Next != StringRef::npos) {
2734 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00002735 if (!isValidVectorKind(Kind, MatchKind)) {
2736 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00002737 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00002738 }
2739 }
Sander de Smalen8e607342017-11-15 15:44:43 +00002740 Parser.Lex(); // Eat the register token.
2741
2742 Reg = RegNum;
2743 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00002744 }
2745
Sander de Smalen8e607342017-11-15 15:44:43 +00002746 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002747}
2748
Sander de Smalencd6be962017-12-20 11:02:42 +00002749/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
2750OperandMatchResultTy
2751AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
2752 // Check for a SVE predicate register specifier first.
2753 const SMLoc S = getLoc();
2754 StringRef Kind;
2755 int RegNum = -1;
Sander de Smalen73937b72018-04-11 07:36:10 +00002756 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00002757 if (Res != MatchOperand_Success)
2758 return Res;
2759
Sander de Smalen73937b72018-04-11 07:36:10 +00002760 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
2761 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00002762 return MatchOperand_NoMatch;
2763
Sander de Smalen73937b72018-04-11 07:36:10 +00002764 unsigned ElementWidth = KindRes->second;
2765 Operands.push_back(AArch64Operand::CreateVectorReg(
2766 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
2767 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00002768
Sander de Smalen7868e742018-01-09 11:17:06 +00002769 // Not all predicates are followed by a '/m' or '/z'.
2770 MCAsmParser &Parser = getParser();
2771 if (Parser.getTok().isNot(AsmToken::Slash))
2772 return MatchOperand_Success;
2773
2774 // But when they do they shouldn't have an element type suffix.
2775 if (!Kind.empty()) {
2776 Error(S, "not expecting size suffix");
2777 return MatchOperand_ParseFail;
2778 }
2779
2780 // Add a literal slash as operand
2781 Operands.push_back(
2782 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
2783
2784 Parser.Lex(); // Eat the slash.
2785
2786 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00002787 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00002788 if (Pred != "z" && Pred != "m") {
2789 Error(getLoc(), "expecting 'm' or 'z' predication");
2790 return MatchOperand_ParseFail;
2791 }
2792
2793 // Add zero/merge token.
2794 const char *ZM = Pred == "z" ? "z" : "m";
2795 Operands.push_back(
2796 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
2797
2798 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00002799 return MatchOperand_Success;
2800}
2801
Tim Northover3b0846e2014-05-24 12:50:23 +00002802/// parseRegister - Parse a non-vector register operand.
2803bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
2804 SMLoc S = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00002805 // Try for a vector (neon) register.
2806 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00002807 return false;
2808
2809 // Try for a scalar register.
2810 int64_t Reg = tryParseRegister();
2811 if (Reg == -1)
2812 return true;
Florian Hahnc4422242017-11-07 13:07:50 +00002813 Operands.push_back(AArch64Operand::CreateReg(Reg, RegKind::Scalar, S,
2814 getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002815
Tim Northover3b0846e2014-05-24 12:50:23 +00002816 return false;
2817}
2818
2819bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002820 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002821 bool HasELFModifier = false;
2822 AArch64MCExpr::VariantKind RefKind;
2823
Nirav Davee833c6c2016-11-08 18:31:04 +00002824 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002825 HasELFModifier = true;
2826
Nirav Davee833c6c2016-11-08 18:31:04 +00002827 if (Parser.getTok().isNot(AsmToken::Identifier))
2828 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002829
2830 std::string LowerCase = Parser.getTok().getIdentifier().lower();
2831 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
2832 .Case("lo12", AArch64MCExpr::VK_LO12)
2833 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
2834 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
2835 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
2836 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
2837 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
2838 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
2839 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
2840 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
2841 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
2842 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
2843 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
2844 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
2845 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
2846 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
2847 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
2848 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
2849 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
2850 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
2851 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
2852 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
2853 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
2854 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
2855 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
2856 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
2857 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
2858 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
2859 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
2860 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
2861 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
2862 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
2863 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
2864 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
2865 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
2866 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00002867 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
2868 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00002869 .Default(AArch64MCExpr::VK_INVALID);
2870
Nirav Davee833c6c2016-11-08 18:31:04 +00002871 if (RefKind == AArch64MCExpr::VK_INVALID)
2872 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00002873
2874 Parser.Lex(); // Eat identifier
2875
Nirav Davee833c6c2016-11-08 18:31:04 +00002876 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00002877 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00002878 }
2879
2880 if (getParser().parseExpression(ImmVal))
2881 return true;
2882
2883 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00002884 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002885
2886 return false;
2887}
2888
Sander de Smalen650234b2018-04-12 11:40:52 +00002889template <RegKind VectorKind>
2890OperandMatchResultTy
2891AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
2892 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002893 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00002894 if (!Parser.getTok().is(AsmToken::LCurly))
2895 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002896
2897 // Wrapper around parse function
Sander de Smalen650234b2018-04-12 11:40:52 +00002898 auto ParseVector = [this, &Parser](int &Reg, StringRef &Kind, SMLoc Loc,
2899 bool NoMatchIsError) {
2900 auto RegTok = Parser.getTok();
2901 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
2902 if (ParseRes == MatchOperand_Success) {
Sander de Smalen73937b72018-04-11 07:36:10 +00002903 if (parseVectorKind(Kind, RegKind::NeonVector))
Sander de Smalen650234b2018-04-12 11:40:52 +00002904 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002905 llvm_unreachable("Expected a valid vector kind");
2906 }
2907
Sander de Smalen650234b2018-04-12 11:40:52 +00002908 if (RegTok.isNot(AsmToken::Identifier) ||
2909 ParseRes == MatchOperand_ParseFail ||
2910 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
2911 Error(Loc, "vector register expected");
2912 return MatchOperand_ParseFail;
2913 }
2914
2915 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00002916 };
2917
Tim Northover3b0846e2014-05-24 12:50:23 +00002918 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00002919 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00002920 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00002921
Tim Northover3b0846e2014-05-24 12:50:23 +00002922 StringRef Kind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002923 int FirstReg = -1;
Sander de Smalen650234b2018-04-12 11:40:52 +00002924 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
2925
2926 // Put back the original left bracket if there was no match, so that
2927 // different types of list-operands can be matched (e.g. SVE, Neon).
2928 if (ParseRes == MatchOperand_NoMatch)
2929 Parser.getLexer().UnLex(LCurly);
2930
2931 if (ParseRes != MatchOperand_Success)
2932 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002933
Tim Northover3b0846e2014-05-24 12:50:23 +00002934 int64_t PrevReg = FirstReg;
2935 unsigned Count = 1;
2936
Nirav Davee833c6c2016-11-08 18:31:04 +00002937 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002938 SMLoc Loc = getLoc();
2939 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002940
2941 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002942 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2943 if (ParseRes != MatchOperand_Success)
2944 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00002945
Tim Northover3b0846e2014-05-24 12:50:23 +00002946 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002947 if (Kind != NextKind) {
2948 Error(Loc, "mismatched register size suffix");
2949 return MatchOperand_ParseFail;
2950 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002951
2952 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
2953
2954 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002955 Error(Loc, "invalid number of vectors");
2956 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002957 }
2958
2959 Count += Space;
2960 }
2961 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00002962 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002963 SMLoc Loc = getLoc();
2964 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00002965 int Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00002966 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
2967 if (ParseRes != MatchOperand_Success)
2968 return ParseRes;
2969
Tim Northover3b0846e2014-05-24 12:50:23 +00002970 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00002971 if (Kind != NextKind) {
2972 Error(Loc, "mismatched register size suffix");
2973 return MatchOperand_ParseFail;
2974 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002975
2976 // Registers must be incremental (with wraparound at 31)
2977 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00002978 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
2979 Error(Loc, "registers must be sequential");
2980 return MatchOperand_ParseFail;
2981 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002982
2983 PrevReg = Reg;
2984 ++Count;
2985 }
2986 }
2987
Nirav Davee833c6c2016-11-08 18:31:04 +00002988 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00002989 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002990
Sander de Smalen650234b2018-04-12 11:40:52 +00002991 if (Count > 4) {
2992 Error(S, "invalid number of vectors");
2993 return MatchOperand_ParseFail;
2994 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002995
2996 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00002997 unsigned ElementWidth = 0;
2998 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00002999 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003000 std::tie(NumElements, ElementWidth) = *VK;
3001 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003002
3003 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003004 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3005 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003006
Sander de Smalen650234b2018-04-12 11:40:52 +00003007 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003008}
3009
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003010/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3011bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003012 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3013 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003014 return true;
3015
3016 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3017}
3018
Alex Bradbury58eba092016-11-01 16:32:05 +00003019OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003020AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003021 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003022 const AsmToken &Tok = Parser.getTok();
3023 if (!Tok.is(AsmToken::Identifier))
3024 return MatchOperand_NoMatch;
3025
Florian Hahnc4422242017-11-07 13:07:50 +00003026 unsigned RegNum = matchRegisterNameAlias(Tok.getString().lower(), RegKind::Scalar);
Tim Northover3b0846e2014-05-24 12:50:23 +00003027
3028 MCContext &Ctx = getContext();
3029 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
3030 if (!RI->getRegClass(AArch64::GPR64spRegClassID).contains(RegNum))
3031 return MatchOperand_NoMatch;
3032
3033 SMLoc S = getLoc();
3034 Parser.Lex(); // Eat register
3035
Nirav Davee833c6c2016-11-08 18:31:04 +00003036 if (!parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003037 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003038 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003039 return MatchOperand_Success;
3040 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003041
Nirav Davee833c6c2016-11-08 18:31:04 +00003042 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003043
3044 if (Parser.getTok().isNot(AsmToken::Integer)) {
3045 Error(getLoc(), "index must be absent or #0");
3046 return MatchOperand_ParseFail;
3047 }
3048
3049 const MCExpr *ImmVal;
3050 if (Parser.parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
3051 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3052 Error(getLoc(), "index must be absent or #0");
3053 return MatchOperand_ParseFail;
3054 }
3055
3056 Operands.push_back(
Florian Hahnc4422242017-11-07 13:07:50 +00003057 AArch64Operand::CreateReg(RegNum, RegKind::Scalar, S, getLoc(), Ctx));
Tim Northover3b0846e2014-05-24 12:50:23 +00003058 return MatchOperand_Success;
3059}
3060
Sander de Smalen5c625982018-04-13 12:56:14 +00003061bool AArch64AsmParser::parseOptionalMulVl(OperandVector &Operands) {
3062 MCAsmParser &Parser = getParser();
3063
3064 // Some SVE instructions have a decoration after the immediate, i.e.
3065 // "mul vl". We parse them here and add tokens, which must be present in the
3066 // asm string in the tablegen instruction.
3067 if (!Parser.getTok().getString().equals_lower("mul") ||
3068 !Parser.getLexer().peekTok().getString().equals_lower("vl"))
3069 return true;
3070
3071 SMLoc S = getLoc();
3072 Operands.push_back(
3073 AArch64Operand::CreateToken("mul", false, S, getContext()));
3074 Parser.Lex(); // Eat the "mul"
3075
3076 S = getLoc();
3077 Operands.push_back(
3078 AArch64Operand::CreateToken("vl", false, S, getContext()));
3079 Parser.Lex(); // Eat the "vl"
3080
3081 return false;
3082}
3083
Tim Northover3b0846e2014-05-24 12:50:23 +00003084/// parseOperand - Parse a arm instruction operand. For now this parses the
3085/// operand regardless of the mnemonic.
3086bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3087 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003088 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003089
3090 OperandMatchResultTy ResTy =
3091 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3092
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 // Check if the current operand has a custom associated parser, if so, try to
3094 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003095 if (ResTy == MatchOperand_Success)
3096 return false;
3097 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3098 // there was a match, but an error occurred, in which case, just return that
3099 // the operand parsing failed.
3100 if (ResTy == MatchOperand_ParseFail)
3101 return true;
3102
3103 // Nothing custom, so do general case parsing.
3104 SMLoc S, E;
3105 switch (getLexer().getKind()) {
3106 default: {
3107 SMLoc S = getLoc();
3108 const MCExpr *Expr;
3109 if (parseSymbolicImmVal(Expr))
3110 return Error(S, "invalid operand");
3111
3112 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3113 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3114 return false;
3115 }
3116 case AsmToken::LBrac: {
3117 SMLoc Loc = Parser.getTok().getLoc();
3118 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3119 getContext()));
3120 Parser.Lex(); // Eat '['
3121
3122 // There's no comma after a '[', so we can parse the next operand
3123 // immediately.
3124 return parseOperand(Operands, false, false);
3125 }
3126 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003127 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003128 case AsmToken::Identifier: {
3129 // If we're expecting a Condition Code operand, then just parse that.
3130 if (isCondCode)
3131 return parseCondCode(Operands, invertCondCode);
3132
3133 // If it's a register name, parse it.
3134 if (!parseRegister(Operands))
3135 return false;
3136
Sander de Smalen5c625982018-04-13 12:56:14 +00003137 // See if this is a "mul vl" decoration used by SVE instructions.
3138 if (!parseOptionalMulVl(Operands))
3139 return false;
3140
Tim Northover3b0846e2014-05-24 12:50:23 +00003141 // This could be an optional "shift" or "extend" operand.
3142 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3143 // We can only continue if no tokens were eaten.
3144 if (GotShift != MatchOperand_NoMatch)
3145 return GotShift;
3146
3147 // This was not a register so parse other operands that start with an
3148 // identifier (like labels) as expressions and create them as immediates.
3149 const MCExpr *IdVal;
3150 S = getLoc();
3151 if (getParser().parseExpression(IdVal))
3152 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003153 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3154 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3155 return false;
3156 }
3157 case AsmToken::Integer:
3158 case AsmToken::Real:
3159 case AsmToken::Hash: {
3160 // #42 -> immediate.
3161 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003162
3163 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003164
3165 // Parse a negative sign
3166 bool isNegative = false;
3167 if (Parser.getTok().is(AsmToken::Minus)) {
3168 isNegative = true;
3169 // We need to consume this token only when we have a Real, otherwise
3170 // we let parseSymbolicImmVal take care of it
3171 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3172 Parser.Lex();
3173 }
3174
3175 // The only Real that should come through here is a literal #0.0 for
3176 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3177 // so convert the value.
3178 const AsmToken &Tok = Parser.getTok();
3179 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003180 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003181 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3182 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3183 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
3184 Mnemonic != "fcmlt")
3185 return TokError("unexpected floating point literal");
3186 else if (IntVal != 0 || isNegative)
3187 return TokError("expected floating-point constant #0.0");
3188 Parser.Lex(); // Eat the token.
3189
3190 Operands.push_back(
3191 AArch64Operand::CreateToken("#0", false, S, getContext()));
3192 Operands.push_back(
3193 AArch64Operand::CreateToken(".0", false, S, getContext()));
3194 return false;
3195 }
3196
3197 const MCExpr *ImmVal;
3198 if (parseSymbolicImmVal(ImmVal))
3199 return true;
3200
3201 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3202 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3203 return false;
3204 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003205 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003206 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003207 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003208 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003209 Parser.Lex(); // Eat '='
3210 const MCExpr *SubExprVal;
3211 if (getParser().parseExpression(SubExprVal))
3212 return true;
3213
David Peixottoae5ba762014-07-18 16:05:14 +00003214 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003215 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003216 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003217
3218 bool IsXReg =
3219 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3220 Operands[1]->getReg());
3221
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003222 MCContext& Ctx = getContext();
3223 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3224 // If the op is an imm and can be fit into a mov, then replace ldr with mov.
David Peixottoae5ba762014-07-18 16:05:14 +00003225 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003226 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3227 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3228 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3229 ShiftAmt += 16;
3230 Imm >>= 16;
3231 }
3232 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3233 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3234 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003235 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003236 if (ShiftAmt)
3237 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3238 ShiftAmt, true, S, E, Ctx));
3239 return false;
3240 }
David Peixottoae5ba762014-07-18 16:05:14 +00003241 APInt Simm = APInt(64, Imm << ShiftAmt);
3242 // check if the immediate is an unsigned or signed 32-bit int for W regs
3243 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3244 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003245 }
3246 // If it is a label or an imm that cannot fit in a movz, put it into CP.
David Peixottoae5ba762014-07-18 16:05:14 +00003247 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003248 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003249 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3250 return false;
3251 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003252 }
3253}
3254
3255/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3256/// operands.
3257bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3258 StringRef Name, SMLoc NameLoc,
3259 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003260 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003261 Name = StringSwitch<StringRef>(Name.lower())
3262 .Case("beq", "b.eq")
3263 .Case("bne", "b.ne")
3264 .Case("bhs", "b.hs")
3265 .Case("bcs", "b.cs")
3266 .Case("blo", "b.lo")
3267 .Case("bcc", "b.cc")
3268 .Case("bmi", "b.mi")
3269 .Case("bpl", "b.pl")
3270 .Case("bvs", "b.vs")
3271 .Case("bvc", "b.vc")
3272 .Case("bhi", "b.hi")
3273 .Case("bls", "b.ls")
3274 .Case("bge", "b.ge")
3275 .Case("blt", "b.lt")
3276 .Case("bgt", "b.gt")
3277 .Case("ble", "b.le")
3278 .Case("bal", "b.al")
3279 .Case("bnv", "b.nv")
3280 .Default(Name);
3281
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003282 // First check for the AArch64-specific .req directive.
3283 if (Parser.getTok().is(AsmToken::Identifier) &&
3284 Parser.getTok().getIdentifier() == ".req") {
3285 parseDirectiveReq(Name, NameLoc);
3286 // We always return 'error' for this, as we're done with this
3287 // statement and don't need to match the 'instruction."
3288 return true;
3289 }
3290
Tim Northover3b0846e2014-05-24 12:50:23 +00003291 // Create the leading tokens for the mnemonic, split by '.' characters.
3292 size_t Start = 0, Next = Name.find('.');
3293 StringRef Head = Name.slice(Start, Next);
3294
3295 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003296 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3297 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003298
3299 Operands.push_back(
3300 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3301 Mnemonic = Head;
3302
3303 // Handle condition codes for a branch mnemonic
3304 if (Head == "b" && Next != StringRef::npos) {
3305 Start = Next;
3306 Next = Name.find('.', Start + 1);
3307 Head = Name.slice(Start + 1, Next);
3308
3309 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3310 (Head.data() - Name.data()));
3311 AArch64CC::CondCode CC = parseCondCodeString(Head);
3312 if (CC == AArch64CC::Invalid)
3313 return Error(SuffixLoc, "invalid condition code");
3314 Operands.push_back(
3315 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3316 Operands.push_back(
3317 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3318 }
3319
3320 // Add the remaining tokens in the mnemonic.
3321 while (Next != StringRef::npos) {
3322 Start = Next;
3323 Next = Name.find('.', Start + 1);
3324 Head = Name.slice(Start, Next);
3325 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3326 (Head.data() - Name.data()) + 1);
3327 Operands.push_back(
3328 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3329 }
3330
3331 // Conditional compare instructions have a Condition Code operand, which needs
3332 // to be parsed and an immediate operand created.
3333 bool condCodeFourthOperand =
3334 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3335 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3336 Head == "csinc" || Head == "csinv" || Head == "csneg");
3337
3338 // These instructions are aliases to some of the conditional select
3339 // instructions. However, the condition code is inverted in the aliased
3340 // instruction.
3341 //
3342 // FIXME: Is this the correct way to handle these? Or should the parser
3343 // generate the aliased instructions directly?
3344 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3345 bool condCodeThirdOperand =
3346 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3347
3348 // Read the remaining operands.
3349 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3350 // Read the first operand.
3351 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003352 return true;
3353 }
3354
3355 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003356 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003357 // Parse and remember the operand.
3358 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3359 (N == 3 && condCodeThirdOperand) ||
3360 (N == 2 && condCodeSecondOperand),
3361 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003362 return true;
3363 }
3364
3365 // After successfully parsing some operands there are two special cases to
3366 // consider (i.e. notional operands not separated by commas). Both are due
3367 // to memory specifiers:
3368 // + An RBrac will end an address for load/store/prefetch
3369 // + An '!' will indicate a pre-indexed operation.
3370 //
3371 // It's someone else's responsibility to make sure these tokens are sane
3372 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003373
Nirav Davee833c6c2016-11-08 18:31:04 +00003374 SMLoc RLoc = Parser.getTok().getLoc();
3375 if (parseOptionalToken(AsmToken::RBrac))
3376 Operands.push_back(
3377 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3378 SMLoc ELoc = Parser.getTok().getLoc();
3379 if (parseOptionalToken(AsmToken::Exclaim))
3380 Operands.push_back(
3381 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003382
3383 ++N;
3384 }
3385 }
3386
Nirav Davee833c6c2016-11-08 18:31:04 +00003387 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3388 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003389
Tim Northover3b0846e2014-05-24 12:50:23 +00003390 return false;
3391}
3392
3393// FIXME: This entire function is a giant hack to provide us with decent
3394// operand range validation/diagnostics until TableGen/MC can be extended
3395// to support autogeneration of this kind of validation.
3396bool AArch64AsmParser::validateInstruction(MCInst &Inst,
3397 SmallVectorImpl<SMLoc> &Loc) {
3398 const MCRegisterInfo *RI = getContext().getRegisterInfo();
3399 // Check for indexed addressing modes w/ the base register being the
3400 // same as a destination/source register or pair load where
3401 // the Rt == Rt2. All of those are undefined behaviour.
3402 switch (Inst.getOpcode()) {
3403 case AArch64::LDPSWpre:
3404 case AArch64::LDPWpost:
3405 case AArch64::LDPWpre:
3406 case AArch64::LDPXpost:
3407 case AArch64::LDPXpre: {
3408 unsigned Rt = Inst.getOperand(1).getReg();
3409 unsigned Rt2 = Inst.getOperand(2).getReg();
3410 unsigned Rn = Inst.getOperand(3).getReg();
3411 if (RI->isSubRegisterEq(Rn, Rt))
3412 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3413 "is also a destination");
3414 if (RI->isSubRegisterEq(Rn, Rt2))
3415 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3416 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003417 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003418 }
3419 case AArch64::LDPDi:
3420 case AArch64::LDPQi:
3421 case AArch64::LDPSi:
3422 case AArch64::LDPSWi:
3423 case AArch64::LDPWi:
3424 case AArch64::LDPXi: {
3425 unsigned Rt = Inst.getOperand(0).getReg();
3426 unsigned Rt2 = Inst.getOperand(1).getReg();
3427 if (Rt == Rt2)
3428 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3429 break;
3430 }
3431 case AArch64::LDPDpost:
3432 case AArch64::LDPDpre:
3433 case AArch64::LDPQpost:
3434 case AArch64::LDPQpre:
3435 case AArch64::LDPSpost:
3436 case AArch64::LDPSpre:
3437 case AArch64::LDPSWpost: {
3438 unsigned Rt = Inst.getOperand(1).getReg();
3439 unsigned Rt2 = Inst.getOperand(2).getReg();
3440 if (Rt == Rt2)
3441 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3442 break;
3443 }
3444 case AArch64::STPDpost:
3445 case AArch64::STPDpre:
3446 case AArch64::STPQpost:
3447 case AArch64::STPQpre:
3448 case AArch64::STPSpost:
3449 case AArch64::STPSpre:
3450 case AArch64::STPWpost:
3451 case AArch64::STPWpre:
3452 case AArch64::STPXpost:
3453 case AArch64::STPXpre: {
3454 unsigned Rt = Inst.getOperand(1).getReg();
3455 unsigned Rt2 = Inst.getOperand(2).getReg();
3456 unsigned Rn = Inst.getOperand(3).getReg();
3457 if (RI->isSubRegisterEq(Rn, Rt))
3458 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3459 "is also a source");
3460 if (RI->isSubRegisterEq(Rn, Rt2))
3461 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3462 "is also a source");
3463 break;
3464 }
3465 case AArch64::LDRBBpre:
3466 case AArch64::LDRBpre:
3467 case AArch64::LDRHHpre:
3468 case AArch64::LDRHpre:
3469 case AArch64::LDRSBWpre:
3470 case AArch64::LDRSBXpre:
3471 case AArch64::LDRSHWpre:
3472 case AArch64::LDRSHXpre:
3473 case AArch64::LDRSWpre:
3474 case AArch64::LDRWpre:
3475 case AArch64::LDRXpre:
3476 case AArch64::LDRBBpost:
3477 case AArch64::LDRBpost:
3478 case AArch64::LDRHHpost:
3479 case AArch64::LDRHpost:
3480 case AArch64::LDRSBWpost:
3481 case AArch64::LDRSBXpost:
3482 case AArch64::LDRSHWpost:
3483 case AArch64::LDRSHXpost:
3484 case AArch64::LDRSWpost:
3485 case AArch64::LDRWpost:
3486 case AArch64::LDRXpost: {
3487 unsigned Rt = Inst.getOperand(1).getReg();
3488 unsigned Rn = Inst.getOperand(2).getReg();
3489 if (RI->isSubRegisterEq(Rn, Rt))
3490 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3491 "is also a source");
3492 break;
3493 }
3494 case AArch64::STRBBpost:
3495 case AArch64::STRBpost:
3496 case AArch64::STRHHpost:
3497 case AArch64::STRHpost:
3498 case AArch64::STRWpost:
3499 case AArch64::STRXpost:
3500 case AArch64::STRBBpre:
3501 case AArch64::STRBpre:
3502 case AArch64::STRHHpre:
3503 case AArch64::STRHpre:
3504 case AArch64::STRWpre:
3505 case AArch64::STRXpre: {
3506 unsigned Rt = Inst.getOperand(1).getReg();
3507 unsigned Rn = Inst.getOperand(2).getReg();
3508 if (RI->isSubRegisterEq(Rn, Rt))
3509 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3510 "is also a source");
3511 break;
3512 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003513 case AArch64::STXRB:
3514 case AArch64::STXRH:
3515 case AArch64::STXRW:
3516 case AArch64::STXRX:
3517 case AArch64::STLXRB:
3518 case AArch64::STLXRH:
3519 case AArch64::STLXRW:
3520 case AArch64::STLXRX: {
3521 unsigned Rs = Inst.getOperand(0).getReg();
3522 unsigned Rt = Inst.getOperand(1).getReg();
3523 unsigned Rn = Inst.getOperand(2).getReg();
3524 if (RI->isSubRegisterEq(Rt, Rs) ||
3525 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3526 return Error(Loc[0],
3527 "unpredictable STXR instruction, status is also a source");
3528 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003529 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003530 case AArch64::STXPW:
3531 case AArch64::STXPX:
3532 case AArch64::STLXPW:
3533 case AArch64::STLXPX: {
3534 unsigned Rs = Inst.getOperand(0).getReg();
3535 unsigned Rt1 = Inst.getOperand(1).getReg();
3536 unsigned Rt2 = Inst.getOperand(2).getReg();
3537 unsigned Rn = Inst.getOperand(3).getReg();
3538 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3539 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3540 return Error(Loc[0],
3541 "unpredictable STXP instruction, status is also a source");
3542 break;
3543 }
3544 }
3545
Tim Northover3b0846e2014-05-24 12:50:23 +00003546
3547 // Now check immediate ranges. Separate from the above as there is overlap
3548 // in the instructions being checked and this keeps the nested conditionals
3549 // to a minimum.
3550 switch (Inst.getOpcode()) {
3551 case AArch64::ADDSWri:
3552 case AArch64::ADDSXri:
3553 case AArch64::ADDWri:
3554 case AArch64::ADDXri:
3555 case AArch64::SUBSWri:
3556 case AArch64::SUBSXri:
3557 case AArch64::SUBWri:
3558 case AArch64::SUBXri: {
3559 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3560 // some slight duplication here.
3561 if (Inst.getOperand(2).isExpr()) {
3562 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3563 AArch64MCExpr::VariantKind ELFRefKind;
3564 MCSymbolRefExpr::VariantKind DarwinRefKind;
3565 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003566 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3567
3568 // Only allow these with ADDXri.
3569 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3570 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3571 Inst.getOpcode() == AArch64::ADDXri)
3572 return false;
3573
3574 // Only allow these with ADDXri/ADDWri
3575 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3576 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3577 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3578 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3579 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3580 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3581 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003582 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3583 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3584 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00003585 (Inst.getOpcode() == AArch64::ADDXri ||
3586 Inst.getOpcode() == AArch64::ADDWri))
3587 return false;
3588
3589 // Don't allow symbol refs in the immediate field otherwise
3590 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
3591 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
3592 // 'cmp w0, 'borked')
3593 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00003594 }
Diana Picusc93518d2016-10-11 09:17:47 +00003595 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00003596 }
3597 return false;
3598 }
3599 default:
3600 return false;
3601 }
3602}
3603
Craig Topper05515562017-10-26 06:46:41 +00003604static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
3605 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003606
3607bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
3608 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003609 switch (ErrCode) {
Sander de Smalen886510f2018-01-10 10:10:56 +00003610 case Match_InvalidTiedOperand:
3611 return Error(Loc, "operand must match destination register");
Tim Northover3b0846e2014-05-24 12:50:23 +00003612 case Match_MissingFeature:
3613 return Error(Loc,
3614 "instruction requires a CPU feature not currently enabled");
3615 case Match_InvalidOperand:
3616 return Error(Loc, "invalid operand for instruction");
3617 case Match_InvalidSuffix:
3618 return Error(Loc, "invalid type suffix for instruction");
3619 case Match_InvalidCondCode:
3620 return Error(Loc, "expected AArch64 condition code");
3621 case Match_AddSubRegExtendSmall:
3622 return Error(Loc,
3623 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
3624 case Match_AddSubRegExtendLarge:
3625 return Error(Loc,
3626 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
3627 case Match_AddSubSecondSource:
3628 return Error(Loc,
3629 "expected compatible register, symbol or integer in range [0, 4095]");
3630 case Match_LogicalSecondSource:
3631 return Error(Loc, "expected compatible register or logical immediate");
3632 case Match_InvalidMovImm32Shift:
3633 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
3634 case Match_InvalidMovImm64Shift:
3635 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
3636 case Match_AddSubRegShift32:
3637 return Error(Loc,
3638 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
3639 case Match_AddSubRegShift64:
3640 return Error(Loc,
3641 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
3642 case Match_InvalidFPImm:
3643 return Error(Loc,
3644 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00003645 case Match_InvalidMemoryIndexedSImm6:
3646 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00003647 case Match_InvalidMemoryIndexedSImm5:
3648 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00003649 case Match_InvalidMemoryIndexed1SImm4:
3650 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00003651 case Match_InvalidMemoryIndexed2SImm4:
3652 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00003653 case Match_InvalidMemoryIndexed3SImm4:
3654 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00003655 case Match_InvalidMemoryIndexed4SImm4:
3656 return Error(Loc, "index must be a multiple of 3 in range [-32, 28].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003657 case Match_InvalidMemoryIndexedSImm9:
3658 return Error(Loc, "index must be an integer in range [-256, 255].");
Sam Parker6d42de72017-08-11 13:14:00 +00003659 case Match_InvalidMemoryIndexedSImm10:
3660 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003661 case Match_InvalidMemoryIndexed4SImm7:
3662 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
3663 case Match_InvalidMemoryIndexed8SImm7:
3664 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
3665 case Match_InvalidMemoryIndexed16SImm7:
3666 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
3667 case Match_InvalidMemoryWExtend8:
3668 return Error(Loc,
3669 "expected 'uxtw' or 'sxtw' with optional shift of #0");
3670 case Match_InvalidMemoryWExtend16:
3671 return Error(Loc,
3672 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
3673 case Match_InvalidMemoryWExtend32:
3674 return Error(Loc,
3675 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
3676 case Match_InvalidMemoryWExtend64:
3677 return Error(Loc,
3678 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
3679 case Match_InvalidMemoryWExtend128:
3680 return Error(Loc,
3681 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
3682 case Match_InvalidMemoryXExtend8:
3683 return Error(Loc,
3684 "expected 'lsl' or 'sxtx' with optional shift of #0");
3685 case Match_InvalidMemoryXExtend16:
3686 return Error(Loc,
3687 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
3688 case Match_InvalidMemoryXExtend32:
3689 return Error(Loc,
3690 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
3691 case Match_InvalidMemoryXExtend64:
3692 return Error(Loc,
3693 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
3694 case Match_InvalidMemoryXExtend128:
3695 return Error(Loc,
3696 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
3697 case Match_InvalidMemoryIndexed1:
3698 return Error(Loc, "index must be an integer in range [0, 4095].");
3699 case Match_InvalidMemoryIndexed2:
3700 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
3701 case Match_InvalidMemoryIndexed4:
3702 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
3703 case Match_InvalidMemoryIndexed8:
3704 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
3705 case Match_InvalidMemoryIndexed16:
3706 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00003707 case Match_InvalidImm0_1:
3708 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003709 case Match_InvalidImm0_7:
3710 return Error(Loc, "immediate must be an integer in range [0, 7].");
3711 case Match_InvalidImm0_15:
3712 return Error(Loc, "immediate must be an integer in range [0, 15].");
3713 case Match_InvalidImm0_31:
3714 return Error(Loc, "immediate must be an integer in range [0, 31].");
3715 case Match_InvalidImm0_63:
3716 return Error(Loc, "immediate must be an integer in range [0, 63].");
3717 case Match_InvalidImm0_127:
3718 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00003719 case Match_InvalidImm0_255:
3720 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003721 case Match_InvalidImm0_65535:
3722 return Error(Loc, "immediate must be an integer in range [0, 65535].");
3723 case Match_InvalidImm1_8:
3724 return Error(Loc, "immediate must be an integer in range [1, 8].");
3725 case Match_InvalidImm1_16:
3726 return Error(Loc, "immediate must be an integer in range [1, 16].");
3727 case Match_InvalidImm1_32:
3728 return Error(Loc, "immediate must be an integer in range [1, 32].");
3729 case Match_InvalidImm1_64:
3730 return Error(Loc, "immediate must be an integer in range [1, 64].");
3731 case Match_InvalidIndex1:
3732 return Error(Loc, "expected lane specifier '[1]'");
3733 case Match_InvalidIndexB:
3734 return Error(Loc, "vector lane must be an integer in range [0, 15].");
3735 case Match_InvalidIndexH:
3736 return Error(Loc, "vector lane must be an integer in range [0, 7].");
3737 case Match_InvalidIndexS:
3738 return Error(Loc, "vector lane must be an integer in range [0, 3].");
3739 case Match_InvalidIndexD:
3740 return Error(Loc, "vector lane must be an integer in range [0, 1].");
3741 case Match_InvalidLabel:
3742 return Error(Loc, "expected label or encodable integer pc offset");
3743 case Match_MRS:
3744 return Error(Loc, "expected readable system register");
3745 case Match_MSR:
3746 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00003747 case Match_InvalidComplexRotationEven:
3748 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
3749 case Match_InvalidComplexRotationOdd:
3750 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00003751 case Match_MnemonicFail: {
3752 std::string Suggestion = AArch64MnemonicSpellCheck(
3753 ((AArch64Operand &)*Operands[0]).getToken(),
3754 ComputeAvailableFeatures(STI->getFeatureBits()));
3755 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
3756 }
Sander de Smalen7ab96f52018-01-22 15:29:19 +00003757 case Match_InvalidSVEPattern:
3758 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00003759 case Match_InvalidSVEPredicateAnyReg:
3760 case Match_InvalidSVEPredicateBReg:
3761 case Match_InvalidSVEPredicateHReg:
3762 case Match_InvalidSVEPredicateSReg:
3763 case Match_InvalidSVEPredicateDReg:
3764 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00003765 case Match_InvalidSVEPredicate3bAnyReg:
3766 case Match_InvalidSVEPredicate3bBReg:
3767 case Match_InvalidSVEPredicate3bHReg:
3768 case Match_InvalidSVEPredicate3bSReg:
3769 case Match_InvalidSVEPredicate3bDReg:
3770 return Error(Loc, "restricted predicate has range [0, 7].");
Tim Northover3b0846e2014-05-24 12:50:23 +00003771 default:
Craig Topper35b2f752014-06-19 06:10:58 +00003772 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003773 }
3774}
3775
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00003776static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00003777
3778bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
3779 OperandVector &Operands,
3780 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00003781 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00003782 bool MatchingInlineAsm) {
3783 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00003784 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
3785 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00003786
David Blaikie960ea3f2014-06-08 16:18:35 +00003787 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00003788 unsigned NumOperands = Operands.size();
3789
3790 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003791 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
3792 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003793 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003794 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003795 if (Op3CE) {
3796 uint64_t Op3Val = Op3CE->getValue();
3797 uint64_t NewOp3Val = 0;
3798 uint64_t NewOp4Val = 0;
3799 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003800 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003801 NewOp3Val = (32 - Op3Val) & 0x1f;
3802 NewOp4Val = 31 - Op3Val;
3803 } else {
3804 NewOp3Val = (64 - Op3Val) & 0x3f;
3805 NewOp4Val = 63 - Op3Val;
3806 }
3807
Jim Grosbach13760bd2015-05-30 01:25:56 +00003808 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
3809 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003810
3811 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003812 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003813 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003814 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
3815 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
3816 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003817 }
3818 }
Tim Northover03b99f62015-04-30 18:28:58 +00003819 } else if (NumOperands == 4 && Tok == "bfc") {
3820 // FIXME: Horrible hack to handle BFC->BFM alias.
3821 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3822 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
3823 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
3824
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003825 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00003826 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
3827 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
3828
3829 if (LSBCE && WidthCE) {
3830 uint64_t LSB = LSBCE->getValue();
3831 uint64_t Width = WidthCE->getValue();
3832
3833 uint64_t RegWidth = 0;
3834 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3835 Op1.getReg()))
3836 RegWidth = 64;
3837 else
3838 RegWidth = 32;
3839
3840 if (LSB >= RegWidth)
3841 return Error(LSBOp.getStartLoc(),
3842 "expected integer in range [0, 31]");
3843 if (Width < 1 || Width > RegWidth)
3844 return Error(WidthOp.getStartLoc(),
3845 "expected integer in range [1, 32]");
3846
3847 uint64_t ImmR = 0;
3848 if (RegWidth == 32)
3849 ImmR = (32 - LSB) & 0x1f;
3850 else
3851 ImmR = (64 - LSB) & 0x3f;
3852
3853 uint64_t ImmS = Width - 1;
3854
3855 if (ImmR != 0 && ImmS >= ImmR)
3856 return Error(WidthOp.getStartLoc(),
3857 "requested insert overflows register");
3858
Jim Grosbach13760bd2015-05-30 01:25:56 +00003859 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
3860 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003861 Operands[0] = AArch64Operand::CreateToken(
3862 "bfm", false, Op.getStartLoc(), getContext());
3863 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00003864 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
3865 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00003866 Operands[3] = AArch64Operand::CreateImm(
3867 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
3868 Operands.emplace_back(
3869 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
3870 WidthOp.getEndLoc(), getContext()));
3871 }
3872 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003873 } else if (NumOperands == 5) {
3874 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
3875 // UBFIZ -> UBFM aliases.
3876 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00003877 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3878 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3879 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003880
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003881 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003882 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3883 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003884
3885 if (Op3CE && Op4CE) {
3886 uint64_t Op3Val = Op3CE->getValue();
3887 uint64_t Op4Val = Op4CE->getValue();
3888
3889 uint64_t RegWidth = 0;
3890 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003891 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003892 RegWidth = 64;
3893 else
3894 RegWidth = 32;
3895
3896 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003897 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003898 "expected integer in range [0, 31]");
3899 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003900 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003901 "expected integer in range [1, 32]");
3902
3903 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00003904 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00003905 NewOp3Val = (32 - Op3Val) & 0x1f;
3906 else
3907 NewOp3Val = (64 - Op3Val) & 0x3f;
3908
3909 uint64_t NewOp4Val = Op4Val - 1;
3910
3911 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003912 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003913 "requested insert overflows register");
3914
3915 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003916 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003917 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003918 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003919 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003920 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003921 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003922 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003923 if (Tok == "bfi")
3924 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003925 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003926 else if (Tok == "sbfiz")
3927 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003928 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003929 else if (Tok == "ubfiz")
3930 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003931 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003932 else
3933 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003934 }
3935 }
3936
3937 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
3938 // UBFX -> UBFM aliases.
3939 } else if (NumOperands == 5 &&
3940 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003941 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
3942 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
3943 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00003944
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003945 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00003946 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
3947 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00003948
3949 if (Op3CE && Op4CE) {
3950 uint64_t Op3Val = Op3CE->getValue();
3951 uint64_t Op4Val = Op4CE->getValue();
3952
3953 uint64_t RegWidth = 0;
3954 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00003955 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00003956 RegWidth = 64;
3957 else
3958 RegWidth = 32;
3959
3960 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003961 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003962 "expected integer in range [0, 31]");
3963 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00003964 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003965 "expected integer in range [1, 32]");
3966
3967 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
3968
3969 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00003970 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00003971 "requested extract overflows register");
3972
3973 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00003974 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003975 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00003976 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003977 if (Tok == "bfxil")
3978 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003979 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003980 else if (Tok == "sbfx")
3981 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003982 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003983 else if (Tok == "ubfx")
3984 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00003985 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003986 else
3987 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00003988 }
3989 }
3990 }
3991 }
Tim Northover9097a072017-12-18 10:36:00 +00003992
3993 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
3994 // instruction for FP registers correctly in some rare circumstances. Convert
3995 // it to a safe instruction and warn (because silently changing someone's
3996 // assembly is rude).
3997 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
3998 NumOperands == 4 && Tok == "movi") {
3999 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4000 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4001 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4002 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4003 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4004 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4005 if (Suffix.lower() == ".2d" &&
4006 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4007 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4008 " correctly on this CPU, converting to equivalent movi.16b");
4009 // Switch the suffix to .16b.
4010 unsigned Idx = Op1.isToken() ? 1 : 2;
4011 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4012 getContext());
4013 }
4014 }
4015 }
4016
Tim Northover3b0846e2014-05-24 12:50:23 +00004017 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4018 // InstAlias can't quite handle this since the reg classes aren't
4019 // subclasses.
4020 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4021 // The source register can be Wn here, but the matcher expects a
4022 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004023 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004024 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004025 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004026 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4027 Op.getStartLoc(), Op.getEndLoc(),
4028 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004029 }
4030 }
4031 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4032 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004033 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004034 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004035 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004036 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004037 // The source register can be Wn here, but the matcher expects a
4038 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004039 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004040 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004041 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004042 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4043 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004044 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004045 }
4046 }
4047 }
4048 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4049 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004050 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004051 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004052 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004053 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004054 // The source register can be Wn here, but the matcher expects a
4055 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004056 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004057 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004058 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004059 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4060 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004061 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004062 }
4063 }
4064 }
4065
Tim Northover3b0846e2014-05-24 12:50:23 +00004066 MCInst Inst;
4067 // First try to match against the secondary set of tables containing the
4068 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4069 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004070 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004071
4072 // If that fails, try against the alternate table containing long-form NEON:
4073 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004074 if (MatchResult != Match_Success) {
4075 // But first, save the short-form match result: we can use it in case the
4076 // long-form match also fails.
4077 auto ShortFormNEONErrorInfo = ErrorInfo;
4078 auto ShortFormNEONMatchResult = MatchResult;
4079
Tim Northover3b0846e2014-05-24 12:50:23 +00004080 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004081 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004082
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004083 // Now, both matches failed, and the long-form match failed on the mnemonic
4084 // suffix token operand. The short-form match failure is probably more
4085 // relevant: use it instead.
4086 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004087 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004088 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4089 MatchResult = ShortFormNEONMatchResult;
4090 ErrorInfo = ShortFormNEONErrorInfo;
4091 }
4092 }
4093
Tim Northover3b0846e2014-05-24 12:50:23 +00004094 switch (MatchResult) {
4095 case Match_Success: {
4096 // Perform range checking and other semantic validations
4097 SmallVector<SMLoc, 8> OperandLocs;
4098 NumOperands = Operands.size();
4099 for (unsigned i = 1; i < NumOperands; ++i)
4100 OperandLocs.push_back(Operands[i]->getStartLoc());
4101 if (validateInstruction(Inst, OperandLocs))
4102 return true;
4103
4104 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004105 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004106 return false;
4107 }
4108 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004109 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004110 // Special case the error message for the very common case where only
4111 // a single subtarget feature is missing (neon, e.g.).
4112 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004113 uint64_t Mask = 1;
4114 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4115 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004116 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004117 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004118 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004119 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004120 }
4121 return Error(IDLoc, Msg);
4122 }
4123 case Match_MnemonicFail:
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004124 return showMatchError(IDLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004125 case Match_InvalidOperand: {
4126 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004127
Tim Northover26bb14e2014-08-18 11:49:42 +00004128 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004129 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004130 return Error(IDLoc, "too few operands for instruction",
4131 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004132
David Blaikie960ea3f2014-06-08 16:18:35 +00004133 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004134 if (ErrorLoc == SMLoc())
4135 ErrorLoc = IDLoc;
4136 }
4137 // If the match failed on a suffix token operand, tweak the diagnostic
4138 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004139 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4140 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004141 MatchResult = Match_InvalidSuffix;
4142
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004143 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004144 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004145 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004146 case Match_InvalidMemoryIndexed1:
4147 case Match_InvalidMemoryIndexed2:
4148 case Match_InvalidMemoryIndexed4:
4149 case Match_InvalidMemoryIndexed8:
4150 case Match_InvalidMemoryIndexed16:
4151 case Match_InvalidCondCode:
4152 case Match_AddSubRegExtendSmall:
4153 case Match_AddSubRegExtendLarge:
4154 case Match_AddSubSecondSource:
4155 case Match_LogicalSecondSource:
4156 case Match_AddSubRegShift32:
4157 case Match_AddSubRegShift64:
4158 case Match_InvalidMovImm32Shift:
4159 case Match_InvalidMovImm64Shift:
4160 case Match_InvalidFPImm:
4161 case Match_InvalidMemoryWExtend8:
4162 case Match_InvalidMemoryWExtend16:
4163 case Match_InvalidMemoryWExtend32:
4164 case Match_InvalidMemoryWExtend64:
4165 case Match_InvalidMemoryWExtend128:
4166 case Match_InvalidMemoryXExtend8:
4167 case Match_InvalidMemoryXExtend16:
4168 case Match_InvalidMemoryXExtend32:
4169 case Match_InvalidMemoryXExtend64:
4170 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004171 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004172 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004173 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004174 case Match_InvalidMemoryIndexed4SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004175 case Match_InvalidMemoryIndexed4SImm7:
4176 case Match_InvalidMemoryIndexed8SImm7:
4177 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen5c625982018-04-13 12:56:14 +00004178 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004179 case Match_InvalidMemoryIndexedSImm5:
Tim Northover3b0846e2014-05-24 12:50:23 +00004180 case Match_InvalidMemoryIndexedSImm9:
Sam Parker6d42de72017-08-11 13:14:00 +00004181 case Match_InvalidMemoryIndexedSImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004182 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004183 case Match_InvalidImm0_7:
4184 case Match_InvalidImm0_15:
4185 case Match_InvalidImm0_31:
4186 case Match_InvalidImm0_63:
4187 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004188 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004189 case Match_InvalidImm0_65535:
4190 case Match_InvalidImm1_8:
4191 case Match_InvalidImm1_16:
4192 case Match_InvalidImm1_32:
4193 case Match_InvalidImm1_64:
4194 case Match_InvalidIndex1:
4195 case Match_InvalidIndexB:
4196 case Match_InvalidIndexH:
4197 case Match_InvalidIndexS:
4198 case Match_InvalidIndexD:
4199 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004200 case Match_InvalidComplexRotationEven:
4201 case Match_InvalidComplexRotationOdd:
Sander de Smalencd6be962017-12-20 11:02:42 +00004202 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004203 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004204 case Match_InvalidSVEPredicateBReg:
4205 case Match_InvalidSVEPredicateHReg:
4206 case Match_InvalidSVEPredicateSReg:
4207 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004208 case Match_InvalidSVEPredicate3bAnyReg:
4209 case Match_InvalidSVEPredicate3bBReg:
4210 case Match_InvalidSVEPredicate3bHReg:
4211 case Match_InvalidSVEPredicate3bSReg:
4212 case Match_InvalidSVEPredicate3bDReg:
Tim Northover3b0846e2014-05-24 12:50:23 +00004213 case Match_MSR:
4214 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004215 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004216 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004217 // Any time we get here, there's nothing fancy to do. Just get the
4218 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004219 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004220 if (ErrorLoc == SMLoc())
4221 ErrorLoc = IDLoc;
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004222 return showMatchError(ErrorLoc, MatchResult, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004223 }
4224 }
4225
4226 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004227}
4228
4229/// ParseDirective parses the arm specific directives
4230bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004231 const MCObjectFileInfo::Environment Format =
4232 getContext().getObjectFileInfo()->getObjectFileType();
4233 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4234 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004235
Tim Northover3b0846e2014-05-24 12:50:23 +00004236 StringRef IDVal = DirectiveID.getIdentifier();
4237 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004238 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004239 parseDirectiveArch(Loc);
4240 else if (IDVal == ".cpu")
4241 parseDirectiveCPU(Loc);
4242 else if (IDVal == ".hword")
4243 parseDirectiveWord(2, Loc);
4244 else if (IDVal == ".word")
4245 parseDirectiveWord(4, Loc);
4246 else if (IDVal == ".xword")
4247 parseDirectiveWord(8, Loc);
4248 else if (IDVal == ".tlsdesccall")
4249 parseDirectiveTLSDescCall(Loc);
4250 else if (IDVal == ".ltorg" || IDVal == ".pool")
4251 parseDirectiveLtorg(Loc);
4252 else if (IDVal == ".unreq")
4253 parseDirectiveUnreq(Loc);
4254 else if (!IsMachO && !IsCOFF) {
Chad Rosierdcd2a302014-10-22 20:35:57 +00004255 if (IDVal == ".inst")
Nirav Davee833c6c2016-11-08 18:31:04 +00004256 parseDirectiveInst(Loc);
4257 else
4258 return true;
4259 } else if (IDVal == MCLOHDirectiveName())
4260 parseDirectiveLOH(IDVal, Loc);
4261 else
4262 return true;
4263 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004264}
4265
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004266static const struct {
4267 const char *Name;
4268 const FeatureBitset Features;
4269} ExtensionMap[] = {
4270 { "crc", {AArch64::FeatureCRC} },
4271 { "crypto", {AArch64::FeatureCrypto} },
4272 { "fp", {AArch64::FeatureFPARMv8} },
4273 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004274 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004275 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004276
4277 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004278 { "pan", {} },
4279 { "lor", {} },
4280 { "rdma", {} },
4281 { "profile", {} },
4282};
4283
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004284/// parseDirectiveArch
4285/// ::= .arch token
4286bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4287 SMLoc ArchLoc = getLoc();
4288
4289 StringRef Arch, ExtensionString;
4290 std::tie(Arch, ExtensionString) =
4291 getParser().parseStringToEndOfStatement().trim().split('+');
4292
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004293 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4294 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004295 return Error(ArchLoc, "unknown arch name");
4296
4297 if (parseToken(AsmToken::EndOfStatement))
4298 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004299
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004300 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004301 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004302 AArch64::getArchFeatures(ID, AArch64Features);
4303 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4304 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004305
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004306 MCSubtargetInfo &STI = copySTI();
4307 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4308 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4309
4310 SmallVector<StringRef, 4> RequestedExtensions;
4311 if (!ExtensionString.empty())
4312 ExtensionString.split(RequestedExtensions, '+');
4313
4314 FeatureBitset Features = STI.getFeatureBits();
4315 for (auto Name : RequestedExtensions) {
4316 bool EnableFeature = true;
4317
4318 if (Name.startswith_lower("no")) {
4319 EnableFeature = false;
4320 Name = Name.substr(2);
4321 }
4322
4323 for (const auto &Extension : ExtensionMap) {
4324 if (Extension.Name != Name)
4325 continue;
4326
4327 if (Extension.Features.none())
4328 report_fatal_error("unsupported architectural extension: " + Name);
4329
4330 FeatureBitset ToggleFeatures = EnableFeature
4331 ? (~Features & Extension.Features)
4332 : ( Features & Extension.Features);
4333 uint64_t Features =
4334 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4335 setAvailableFeatures(Features);
4336 break;
4337 }
4338 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004339 return false;
4340}
4341
Tim Northover8b96c7e2017-05-15 19:42:15 +00004342static SMLoc incrementLoc(SMLoc L, int Offset) {
4343 return SMLoc::getFromPointer(L.getPointer() + Offset);
4344}
4345
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004346/// parseDirectiveCPU
4347/// ::= .cpu id
4348bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004349 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004350
4351 StringRef CPU, ExtensionString;
4352 std::tie(CPU, ExtensionString) =
4353 getParser().parseStringToEndOfStatement().trim().split('+');
4354
Nirav Davee833c6c2016-11-08 18:31:04 +00004355 if (parseToken(AsmToken::EndOfStatement))
4356 return true;
4357
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004358 SmallVector<StringRef, 4> RequestedExtensions;
4359 if (!ExtensionString.empty())
4360 ExtensionString.split(RequestedExtensions, '+');
4361
4362 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
4363 // once that is tablegen'ed
4364 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004365 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004366 return false;
4367 }
4368
4369 MCSubtargetInfo &STI = copySTI();
4370 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00004371 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004372
4373 FeatureBitset Features = STI.getFeatureBits();
4374 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00004375 // Advance source location past '+'.
4376 CurLoc = incrementLoc(CurLoc, 1);
4377
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004378 bool EnableFeature = true;
4379
4380 if (Name.startswith_lower("no")) {
4381 EnableFeature = false;
4382 Name = Name.substr(2);
4383 }
4384
Tim Northover8b96c7e2017-05-15 19:42:15 +00004385 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004386 for (const auto &Extension : ExtensionMap) {
4387 if (Extension.Name != Name)
4388 continue;
4389
4390 if (Extension.Features.none())
4391 report_fatal_error("unsupported architectural extension: " + Name);
4392
4393 FeatureBitset ToggleFeatures = EnableFeature
4394 ? (~Features & Extension.Features)
4395 : ( Features & Extension.Features);
4396 uint64_t Features =
4397 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
4398 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00004399 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004400
4401 break;
4402 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00004403
4404 if (!FoundExtension)
4405 Error(CurLoc, "unsupported architectural extension");
4406
4407 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004408 }
4409 return false;
4410}
4411
Tim Northover3b0846e2014-05-24 12:50:23 +00004412/// parseDirectiveWord
4413/// ::= .word [ expression (, expression)* ]
4414bool AArch64AsmParser::parseDirectiveWord(unsigned Size, SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004415 auto parseOp = [&]() -> bool {
4416 const MCExpr *Value;
4417 if (getParser().parseExpression(Value))
4418 return true;
4419 getParser().getStreamer().EmitValue(Value, Size, L);
4420 return false;
4421 };
Tim Northover3b0846e2014-05-24 12:50:23 +00004422
Nirav Davee833c6c2016-11-08 18:31:04 +00004423 if (parseMany(parseOp))
4424 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004425 return false;
4426}
4427
Chad Rosierdcd2a302014-10-22 20:35:57 +00004428/// parseDirectiveInst
4429/// ::= .inst opcode [, ...]
4430bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004431 if (getLexer().is(AsmToken::EndOfStatement))
4432 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004433
Nirav Davee833c6c2016-11-08 18:31:04 +00004434 auto parseOp = [&]() -> bool {
4435 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00004436 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00004437 if (check(getParser().parseExpression(Expr), L, "expected expression"))
4438 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004439 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00004440 if (check(!Value, L, "expected constant expression"))
4441 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004442 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00004443 return false;
4444 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00004445
Nirav Davee833c6c2016-11-08 18:31:04 +00004446 if (parseMany(parseOp))
4447 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00004448 return false;
4449}
4450
Tim Northover3b0846e2014-05-24 12:50:23 +00004451// parseDirectiveTLSDescCall:
4452// ::= .tlsdesccall symbol
4453bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
4454 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00004455 if (check(getParser().parseIdentifier(Name), L,
4456 "expected symbol after directive") ||
4457 parseToken(AsmToken::EndOfStatement))
4458 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004459
Jim Grosbach6f482002015-05-18 18:43:14 +00004460 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00004461 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
4462 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004463
4464 MCInst Inst;
4465 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00004466 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00004467
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004468 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004469 return false;
4470}
4471
4472/// ::= .loh <lohName | lohId> label1, ..., labelN
4473/// The number of arguments depends on the loh identifier.
4474bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004475 MCLOHType Kind;
4476 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4477 if (getParser().getTok().isNot(AsmToken::Integer))
4478 return TokError("expected an identifier or a number in directive");
4479 // We successfully get a numeric value for the identifier.
4480 // Check if it is valid.
4481 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00004482 if (Id <= -1U && !isValidMCLOHType(Id))
4483 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00004484 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00004485 } else {
4486 StringRef Name = getTok().getIdentifier();
4487 // We successfully parse an identifier.
4488 // Check if it is a recognized one.
4489 int Id = MCLOHNameToId(Name);
4490
4491 if (Id == -1)
4492 return TokError("invalid identifier in directive");
4493 Kind = (MCLOHType)Id;
4494 }
4495 // Consume the identifier.
4496 Lex();
4497 // Get the number of arguments of this LOH.
4498 int NbArgs = MCLOHIdToNbArgs(Kind);
4499
4500 assert(NbArgs != -1 && "Invalid number of arguments");
4501
4502 SmallVector<MCSymbol *, 3> Args;
4503 for (int Idx = 0; Idx < NbArgs; ++Idx) {
4504 StringRef Name;
4505 if (getParser().parseIdentifier(Name))
4506 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00004507 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00004508
4509 if (Idx + 1 == NbArgs)
4510 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00004511 if (parseToken(AsmToken::Comma,
4512 "unexpected token in '" + Twine(IDVal) + "' directive"))
4513 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004514 }
Nirav Davee833c6c2016-11-08 18:31:04 +00004515 if (parseToken(AsmToken::EndOfStatement,
4516 "unexpected token in '" + Twine(IDVal) + "' directive"))
4517 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00004518
4519 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
4520 return false;
4521}
4522
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004523/// parseDirectiveLtorg
4524/// ::= .ltorg | .pool
4525bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00004526 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
4527 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00004528 getTargetStreamer().emitCurrentConstantPool();
4529 return false;
4530}
4531
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004532/// parseDirectiveReq
4533/// ::= name .req registername
4534bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004535 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004536 Parser.Lex(); // Eat the '.req' token.
4537 SMLoc SRegLoc = getLoc();
Sander de Smalen8e607342017-11-15 15:44:43 +00004538 int RegNum = tryParseRegister();
Florian Hahnc4422242017-11-07 13:07:50 +00004539 RegKind RegisterKind = RegKind::Scalar;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004540
Sander de Smalen8e607342017-11-15 15:44:43 +00004541 if (RegNum == -1) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004542 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00004543 RegisterKind = RegKind::NeonVector;
Sander de Smalen73937b72018-04-11 07:36:10 +00004544 OperandMatchResultTy Res =
4545 tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
4546
4547 if (Res == MatchOperand_ParseFail)
4548 return true;
4549
4550 if (Res == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00004551 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004552 }
4553
Sander de Smalen8e607342017-11-15 15:44:43 +00004554 if (RegNum == -1) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004555 StringRef Kind;
4556 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen8e607342017-11-15 15:44:43 +00004557 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004558 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004559
4560 if (Res == MatchOperand_ParseFail)
4561 return true;
4562
4563 if (Res == MatchOperand_Success && !Kind.empty())
4564 return Error(SRegLoc,
4565 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00004566 }
4567
Sander de Smalencd6be962017-12-20 11:02:42 +00004568 if (RegNum == -1) {
4569 StringRef Kind;
4570 RegisterKind = RegKind::SVEPredicateVector;
4571 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004572 tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00004573
4574 if (Res == MatchOperand_ParseFail)
4575 return true;
4576
4577 if (Res == MatchOperand_Success && !Kind.empty())
4578 return Error(SRegLoc,
4579 "sve predicate register without type specifier expected");
4580 }
4581
Sander de Smalen8e607342017-11-15 15:44:43 +00004582 if (RegNum == -1)
Nirav Dave2364748a2016-09-16 18:30:20 +00004583 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004584
4585 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00004586 if (parseToken(AsmToken::EndOfStatement,
4587 "unexpected input in .req directive"))
4588 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004589
Sander de Smalen8e607342017-11-15 15:44:43 +00004590 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00004591 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004592 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
4593
Nirav Dave2364748a2016-09-16 18:30:20 +00004594 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004595}
4596
4597/// parseDirectiveUneq
4598/// ::= .unreq registername
4599bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00004600 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00004601 if (getTok().isNot(AsmToken::Identifier))
4602 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004603 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
4604 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00004605 if (parseToken(AsmToken::EndOfStatement))
4606 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00004607 return false;
4608}
4609
Tim Northover3b0846e2014-05-24 12:50:23 +00004610bool
4611AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
4612 AArch64MCExpr::VariantKind &ELFRefKind,
4613 MCSymbolRefExpr::VariantKind &DarwinRefKind,
4614 int64_t &Addend) {
4615 ELFRefKind = AArch64MCExpr::VK_INVALID;
4616 DarwinRefKind = MCSymbolRefExpr::VK_None;
4617 Addend = 0;
4618
4619 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
4620 ELFRefKind = AE->getKind();
4621 Expr = AE->getSubExpr();
4622 }
4623
4624 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
4625 if (SE) {
4626 // It's a simple symbol reference with no addend.
4627 DarwinRefKind = SE->getKind();
4628 return true;
4629 }
4630
4631 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
4632 if (!BE)
4633 return false;
4634
4635 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
4636 if (!SE)
4637 return false;
4638 DarwinRefKind = SE->getKind();
4639
4640 if (BE->getOpcode() != MCBinaryExpr::Add &&
4641 BE->getOpcode() != MCBinaryExpr::Sub)
4642 return false;
4643
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00004644 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00004645 // on here than we can deal with.
4646 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
4647 if (!AddendExpr)
4648 return false;
4649
4650 Addend = AddendExpr->getValue();
4651 if (BE->getOpcode() == MCBinaryExpr::Sub)
4652 Addend = -Addend;
4653
4654 // It's some symbol reference + a constant addend, but really
4655 // shouldn't use both Darwin and ELF syntax.
4656 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
4657 DarwinRefKind == MCSymbolRefExpr::VK_None;
4658}
4659
4660/// Force static initialization.
4661extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00004662 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
4663 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
4664 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00004665}
4666
4667#define GET_REGISTER_MATCHER
4668#define GET_SUBTARGET_FEATURE_NAME
4669#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00004670#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00004671#include "AArch64GenAsmMatcher.inc"
4672
4673// Define this matcher function after the auto-generated include so we
4674// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00004675unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00004676 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004677 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00004678 // If the kind is a token for a literal immediate, check if our asm
4679 // operand matches. This is for InstAliases which have a fixed-value
4680 // immediate in the syntax.
4681 int64_t ExpectedVal;
4682 switch (Kind) {
4683 default:
4684 return Match_InvalidOperand;
4685 case MCK__35_0:
4686 ExpectedVal = 0;
4687 break;
4688 case MCK__35_1:
4689 ExpectedVal = 1;
4690 break;
4691 case MCK__35_12:
4692 ExpectedVal = 12;
4693 break;
4694 case MCK__35_16:
4695 ExpectedVal = 16;
4696 break;
4697 case MCK__35_2:
4698 ExpectedVal = 2;
4699 break;
4700 case MCK__35_24:
4701 ExpectedVal = 24;
4702 break;
4703 case MCK__35_3:
4704 ExpectedVal = 3;
4705 break;
4706 case MCK__35_32:
4707 ExpectedVal = 32;
4708 break;
4709 case MCK__35_4:
4710 ExpectedVal = 4;
4711 break;
4712 case MCK__35_48:
4713 ExpectedVal = 48;
4714 break;
4715 case MCK__35_6:
4716 ExpectedVal = 6;
4717 break;
4718 case MCK__35_64:
4719 ExpectedVal = 64;
4720 break;
4721 case MCK__35_8:
4722 ExpectedVal = 8;
4723 break;
4724 }
David Blaikie960ea3f2014-06-08 16:18:35 +00004725 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00004726 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00004727 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004728 if (!CE)
4729 return Match_InvalidOperand;
4730 if (CE->getValue() == ExpectedVal)
4731 return Match_Success;
4732 return Match_InvalidOperand;
4733}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004734
Alex Bradbury58eba092016-11-01 16:32:05 +00004735OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004736AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
4737
4738 SMLoc S = getLoc();
4739
4740 if (getParser().getTok().isNot(AsmToken::Identifier)) {
4741 Error(S, "expected register");
4742 return MatchOperand_ParseFail;
4743 }
4744
4745 int FirstReg = tryParseRegister();
4746 if (FirstReg == -1) {
4747 return MatchOperand_ParseFail;
4748 }
4749 const MCRegisterClass &WRegClass =
4750 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
4751 const MCRegisterClass &XRegClass =
4752 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
4753
4754 bool isXReg = XRegClass.contains(FirstReg),
4755 isWReg = WRegClass.contains(FirstReg);
4756 if (!isXReg && !isWReg) {
4757 Error(S, "expected first even register of a "
4758 "consecutive same-size even/odd register pair");
4759 return MatchOperand_ParseFail;
4760 }
4761
4762 const MCRegisterInfo *RI = getContext().getRegisterInfo();
4763 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
4764
4765 if (FirstEncoding & 0x1) {
4766 Error(S, "expected first even register of a "
4767 "consecutive same-size even/odd register pair");
4768 return MatchOperand_ParseFail;
4769 }
4770
4771 SMLoc M = getLoc();
4772 if (getParser().getTok().isNot(AsmToken::Comma)) {
4773 Error(M, "expected comma");
4774 return MatchOperand_ParseFail;
4775 }
4776 // Eat the comma
4777 getParser().Lex();
4778
4779 SMLoc E = getLoc();
4780 int SecondReg = tryParseRegister();
4781 if (SecondReg ==-1) {
4782 return MatchOperand_ParseFail;
4783 }
4784
Eugene Zelenko049b0172017-01-06 00:30:53 +00004785 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004786 (isXReg && !XRegClass.contains(SecondReg)) ||
4787 (isWReg && !WRegClass.contains(SecondReg))) {
4788 Error(E,"expected second odd register of a "
4789 "consecutive same-size even/odd register pair");
4790 return MatchOperand_ParseFail;
4791 }
Joel Jones504bf332016-10-24 13:37:13 +00004792
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004793 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00004794 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004795 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
4796 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
4797 } else {
4798 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
4799 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
4800 }
4801
Florian Hahnc4422242017-11-07 13:07:50 +00004802 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
4803 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00004804
4805 return MatchOperand_Success;
4806}
Florian Hahn91f11e52017-11-07 16:45:48 +00004807
4808template <bool ParseSuffix>
4809OperandMatchResultTy
4810AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00004811 const SMLoc S = getLoc();
4812 // Check for a SVE vector register specifier first.
Sander de Smalen8e607342017-11-15 15:44:43 +00004813 int RegNum = -1;
Florian Hahn91f11e52017-11-07 16:45:48 +00004814 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00004815
Sander de Smalen8e607342017-11-15 15:44:43 +00004816 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00004817 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00004818
4819 if (Res != MatchOperand_Success)
4820 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00004821
4822 if (ParseSuffix && Kind.empty())
4823 return MatchOperand_NoMatch;
4824
Sander de Smalen73937b72018-04-11 07:36:10 +00004825 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
4826 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00004827 return MatchOperand_NoMatch;
4828
Sander de Smalen73937b72018-04-11 07:36:10 +00004829 unsigned ElementWidth = KindRes->second;
4830 Operands.push_back(AArch64Operand::CreateVectorReg(
4831 RegNum, RegKind::SVEDataVector, ElementWidth, S, S,
4832 getContext()));
Florian Hahn91f11e52017-11-07 16:45:48 +00004833
4834 return MatchOperand_Success;
4835}
Sander de Smalen245e0e62018-01-22 10:46:00 +00004836
4837OperandMatchResultTy
4838AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
4839 MCAsmParser &Parser = getParser();
4840
4841 SMLoc SS = getLoc();
4842 const AsmToken &TokE = Parser.getTok();
4843 bool IsHash = TokE.is(AsmToken::Hash);
4844
4845 if (!IsHash && TokE.isNot(AsmToken::Identifier))
4846 return MatchOperand_NoMatch;
4847
4848 int64_t Pattern;
4849 if (IsHash) {
4850 Parser.Lex(); // Eat hash
4851
4852 // Parse the immediate operand.
4853 const MCExpr *ImmVal;
4854 SS = getLoc();
4855 if (Parser.parseExpression(ImmVal))
4856 return MatchOperand_ParseFail;
4857
4858 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
4859 if (!MCE)
4860 return MatchOperand_ParseFail;
4861
4862 Pattern = MCE->getValue();
4863 } else {
4864 // Parse the pattern
4865 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
4866 if (!Pat)
4867 return MatchOperand_NoMatch;
4868
4869 Parser.Lex();
4870 Pattern = Pat->Encoding;
4871 assert(Pattern >= 0 && Pattern < 32);
4872 }
4873
4874 Operands.push_back(
4875 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
4876 SS, getLoc(), getContext()));
4877
4878 return MatchOperand_Success;
4879}