blob: ee9443b3f71df957a5768a74a8c8c47f7d38c47d [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"
Sander de Smalen9b333092018-07-30 15:42:46 +000014#include "AArch64InstrInfo.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000015#include "Utils/AArch64BaseInfo.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000016#include "llvm/ADT/APFloat.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000017#include "llvm/ADT/APInt.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000018#include "llvm/ADT/ArrayRef.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000019#include "llvm/ADT/STLExtras.h"
Chandler Carruth6bda14b2017-06-06 11:49:48 +000020#include "llvm/ADT/SmallVector.h"
Eric Christopher98ddbdb2016-09-08 17:27:03 +000021#include "llvm/ADT/StringExtras.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000022#include "llvm/ADT/StringMap.h"
23#include "llvm/ADT/StringRef.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000024#include "llvm/ADT/StringSwitch.h"
25#include "llvm/ADT/Twine.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000026#include "llvm/MC/MCContext.h"
27#include "llvm/MC/MCExpr.h"
28#include "llvm/MC/MCInst.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000029#include "llvm/MC/MCLinkerOptimizationHint.h"
Chad Rosierdcd2a302014-10-22 20:35:57 +000030#include "llvm/MC/MCObjectFileInfo.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000031#include "llvm/MC/MCParser/MCAsmLexer.h"
32#include "llvm/MC/MCParser/MCAsmParser.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000033#include "llvm/MC/MCParser/MCAsmParserExtension.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000034#include "llvm/MC/MCParser/MCParsedAsmOperand.h"
Benjamin Kramerb3e8a6d2016-01-27 10:01:28 +000035#include "llvm/MC/MCParser/MCTargetAsmParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000036#include "llvm/MC/MCRegisterInfo.h"
37#include "llvm/MC/MCStreamer.h"
38#include "llvm/MC/MCSubtargetInfo.h"
39#include "llvm/MC/MCSymbol.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000040#include "llvm/MC/MCTargetOptions.h"
41#include "llvm/MC/SubtargetFeature.h"
42#include "llvm/Support/Casting.h"
43#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000044#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000045#include "llvm/Support/MathExtras.h"
46#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000047#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000048#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000049#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000050#include <cassert>
51#include <cctype>
52#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000053#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000054#include <string>
55#include <tuple>
56#include <utility>
57#include <vector>
58
Tim Northover3b0846e2014-05-24 12:50:23 +000059using namespace llvm;
60
61namespace {
62
Sander de Smalencd6be962017-12-20 11:02:42 +000063enum class RegKind {
64 Scalar,
65 NeonVector,
66 SVEDataVector,
67 SVEPredicateVector
68};
Florian Hahnc4422242017-11-07 13:07:50 +000069
Sander de Smalen0325e302018-07-02 07:34:52 +000070enum RegConstraintEqualityTy {
71 EqualsReg,
72 EqualsSuperReg,
73 EqualsSubReg
74};
75
Tim Northover3b0846e2014-05-24 12:50:23 +000076class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000077private:
78 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000079
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000080 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000081 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000082
Sander de Smalen9b333092018-07-30 15:42:46 +000083 class PrefixInfo {
84 public:
85 static PrefixInfo CreateFromInst(const MCInst &Inst, uint64_t TSFlags) {
86 PrefixInfo Prefix;
87 switch (Inst.getOpcode()) {
88 case AArch64::MOVPRFX_ZZ:
89 Prefix.Active = true;
90 Prefix.Dst = Inst.getOperand(0).getReg();
91 break;
92 case AArch64::MOVPRFX_ZPmZ_B:
93 case AArch64::MOVPRFX_ZPmZ_H:
94 case AArch64::MOVPRFX_ZPmZ_S:
95 case AArch64::MOVPRFX_ZPmZ_D:
96 Prefix.Active = true;
97 Prefix.Predicated = true;
98 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
99 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
100 "No destructive element size set for movprfx");
101 Prefix.Dst = Inst.getOperand(0).getReg();
102 Prefix.Pg = Inst.getOperand(2).getReg();
103 break;
104 case AArch64::MOVPRFX_ZPzZ_B:
105 case AArch64::MOVPRFX_ZPzZ_H:
106 case AArch64::MOVPRFX_ZPzZ_S:
107 case AArch64::MOVPRFX_ZPzZ_D:
108 Prefix.Active = true;
109 Prefix.Predicated = true;
110 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
111 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
112 "No destructive element size set for movprfx");
113 Prefix.Dst = Inst.getOperand(0).getReg();
114 Prefix.Pg = Inst.getOperand(1).getReg();
115 break;
116 default:
117 break;
118 }
119
120 return Prefix;
121 }
122
123 PrefixInfo() : Active(false), Predicated(false) {}
124 bool isActive() const { return Active; }
125 bool isPredicated() const { return Predicated; }
126 unsigned getElementSize() const {
127 assert(Predicated);
128 return ElementSize;
129 }
130 unsigned getDstReg() const { return Dst; }
131 unsigned getPgReg() const {
132 assert(Predicated);
133 return Pg;
134 }
135
136 private:
137 bool Active;
138 bool Predicated;
139 unsigned ElementSize;
140 unsigned Dst;
141 unsigned Pg;
142 } NextPrefix;
143
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000144 AArch64TargetStreamer &getTargetStreamer() {
145 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
146 return static_cast<AArch64TargetStreamer &>(TS);
147 }
148
Rafael Espindola961d4692014-11-11 05:18:41 +0000149 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +0000150
151 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +0000152 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000153 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
154 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +0000155 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000156 bool parseRegister(OperandVector &Operands);
157 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000158 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen18ac8f92018-06-15 15:47:44 +0000159 bool parseOptionalMulOperand(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000160 bool parseOperand(OperandVector &Operands, bool isCondCode,
161 bool invertCondCode);
162
Sander de Smalen0325e302018-07-02 07:34:52 +0000163 bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
164 OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000165
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +0000166 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +0000167 bool parseDirectiveCPU(SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000168 bool parseDirectiveInst(SMLoc L);
169
Tim Northover3b0846e2014-05-24 12:50:23 +0000170 bool parseDirectiveTLSDescCall(SMLoc L);
171
172 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000173 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000174
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000175 bool parseDirectiveReq(StringRef Name, SMLoc L);
176 bool parseDirectiveUnreq(SMLoc L);
177
Sander de Smalen9b333092018-07-30 15:42:46 +0000178 bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
179 SmallVectorImpl<SMLoc> &Loc);
Tim Northover3b0846e2014-05-24 12:50:23 +0000180 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
181 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000182 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000183 bool MatchingInlineAsm) override;
184/// @name Auto-generated Match Functions
185/// {
186
187#define GET_ASSEMBLER_HEADER
188#include "AArch64GenAsmMatcher.inc"
189
190 /// }
191
Sander de Smalen50d87022018-04-19 07:35:08 +0000192 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
193 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000194 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000195 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
196 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
197 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
198 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
199 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000200 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000201 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000202 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000203 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
204 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000205 template<bool AddFPZeroAsLiteral>
Tim Northover3b0846e2014-05-24 12:50:23 +0000206 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000207 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000208 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000209 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000210 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000211 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen0325e302018-07-02 07:34:52 +0000212 template <bool ParseShiftExtend,
213 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
Sander de Smalen149916d2018-04-20 07:24:20 +0000214 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000215 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000216 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000217 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000218 template <RegKind VectorKind>
219 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
220 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000221 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000222
223public:
224 enum AArch64MatchResultTy {
225 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
226#define GET_OPERAND_DIAGNOSTIC_TYPES
227#include "AArch64GenAsmMatcher.inc"
228 };
Joel Jones504bf332016-10-24 13:37:13 +0000229 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000230
Akira Hatanakab11ef082015-11-14 06:35:56 +0000231 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000232 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000233 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000234 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000235 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000236 MCStreamer &S = getParser().getStreamer();
237 if (S.getTargetStreamer() == nullptr)
238 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000239
Alex Bradbury0a59f182018-05-23 11:17:20 +0000240 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
241 // directives as they have the same form and semantics:
242 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
243 Parser.addAliasForDirective(".hword", ".2byte");
244 Parser.addAliasForDirective(".word", ".4byte");
245 Parser.addAliasForDirective(".xword", ".8byte");
246
Tim Northover3b0846e2014-05-24 12:50:23 +0000247 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000248 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000249 }
250
Sander de Smalen0325e302018-07-02 07:34:52 +0000251 bool regsEqual(const MCParsedAsmOperand &Op1,
252 const MCParsedAsmOperand &Op2) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000253 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
254 SMLoc NameLoc, OperandVector &Operands) override;
255 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
256 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000257 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000258 unsigned Kind) override;
259
260 static bool classifySymbolRef(const MCExpr *Expr,
261 AArch64MCExpr::VariantKind &ELFRefKind,
262 MCSymbolRefExpr::VariantKind &DarwinRefKind,
263 int64_t &Addend);
264};
Tim Northover3b0846e2014-05-24 12:50:23 +0000265
266/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
267/// instruction.
268class AArch64Operand : public MCParsedAsmOperand {
269private:
270 enum KindTy {
271 k_Immediate,
272 k_ShiftedImm,
273 k_CondCode,
274 k_Register,
275 k_VectorList,
276 k_VectorIndex,
277 k_Token,
278 k_SysReg,
279 k_SysCR,
280 k_Prefetch,
281 k_ShiftExtend,
282 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000283 k_Barrier,
284 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000285 } Kind;
286
287 SMLoc StartLoc, EndLoc;
288
289 struct TokOp {
290 const char *Data;
291 unsigned Length;
292 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
293 };
294
Sander de Smalen149916d2018-04-20 07:24:20 +0000295 // Separate shift/extend operand.
296 struct ShiftExtendOp {
297 AArch64_AM::ShiftExtendType Type;
298 unsigned Amount;
299 bool HasExplicitAmount;
300 };
301
Tim Northover3b0846e2014-05-24 12:50:23 +0000302 struct RegOp {
303 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000304 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000305 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000306
Sander de Smalen0325e302018-07-02 07:34:52 +0000307 // The register may be allowed as a different register class,
308 // e.g. for GPR64as32 or GPR32as64.
309 RegConstraintEqualityTy EqualityTy;
310
Sander de Smalen149916d2018-04-20 07:24:20 +0000311 // In some cases the shift/extend needs to be explicitly parsed together
312 // with the register, rather than as a separate operand. This is needed
313 // for addressing modes where the instruction as a whole dictates the
314 // scaling/extend, rather than specific bits in the instruction.
315 // By parsing them as a single operand, we avoid the need to pass an
316 // extra operand in all CodeGen patterns (because all operands need to
317 // have an associated value), and we avoid the need to update TableGen to
318 // accept operands that have no associated bits in the instruction.
319 //
320 // An added benefit of parsing them together is that the assembler
321 // can give a sensible diagnostic if the scaling is not correct.
322 //
323 // The default is 'lsl #0' (HasExplicitAmount = false) if no
324 // ShiftExtend is specified.
325 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000326 };
327
328 struct VectorListOp {
329 unsigned RegNum;
330 unsigned Count;
331 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000332 unsigned ElementWidth;
333 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000334 };
335
336 struct VectorIndexOp {
337 unsigned Val;
338 };
339
340 struct ImmOp {
341 const MCExpr *Val;
342 };
343
344 struct ShiftedImmOp {
345 const MCExpr *Val;
346 unsigned ShiftAmount;
347 };
348
349 struct CondCodeOp {
350 AArch64CC::CondCode Code;
351 };
352
353 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000354 uint64_t Val; // APFloat value bitcasted to uint64_t.
355 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000356 };
357
358 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000359 const char *Data;
360 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000361 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000362 };
363
364 struct SysRegOp {
365 const char *Data;
366 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000367 uint32_t MRSReg;
368 uint32_t MSRReg;
369 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000370 };
371
372 struct SysCRImmOp {
373 unsigned Val;
374 };
375
376 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000377 const char *Data;
378 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000379 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000380 };
381
Oliver Stannarda34e4702015-12-01 10:48:51 +0000382 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000383 const char *Data;
384 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000385 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000386 };
387
Tim Northover3b0846e2014-05-24 12:50:23 +0000388 struct ExtendOp {
389 unsigned Val;
390 };
391
392 union {
393 struct TokOp Tok;
394 struct RegOp Reg;
395 struct VectorListOp VectorList;
396 struct VectorIndexOp VectorIndex;
397 struct ImmOp Imm;
398 struct ShiftedImmOp ShiftedImm;
399 struct CondCodeOp CondCode;
400 struct FPImmOp FPImm;
401 struct BarrierOp Barrier;
402 struct SysRegOp SysReg;
403 struct SysCRImmOp SysCRImm;
404 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000405 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000406 struct ShiftExtendOp ShiftExtend;
407 };
408
409 // Keep the MCContext around as the MCExprs may need manipulated during
410 // the add<>Operands() calls.
411 MCContext &Ctx;
412
David Blaikie960ea3f2014-06-08 16:18:35 +0000413public:
David Blaikie9f380a32015-03-16 18:06:57 +0000414 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000415
Tim Northover3b0846e2014-05-24 12:50:23 +0000416 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
417 Kind = o.Kind;
418 StartLoc = o.StartLoc;
419 EndLoc = o.EndLoc;
420 switch (Kind) {
421 case k_Token:
422 Tok = o.Tok;
423 break;
424 case k_Immediate:
425 Imm = o.Imm;
426 break;
427 case k_ShiftedImm:
428 ShiftedImm = o.ShiftedImm;
429 break;
430 case k_CondCode:
431 CondCode = o.CondCode;
432 break;
433 case k_FPImm:
434 FPImm = o.FPImm;
435 break;
436 case k_Barrier:
437 Barrier = o.Barrier;
438 break;
439 case k_Register:
440 Reg = o.Reg;
441 break;
442 case k_VectorList:
443 VectorList = o.VectorList;
444 break;
445 case k_VectorIndex:
446 VectorIndex = o.VectorIndex;
447 break;
448 case k_SysReg:
449 SysReg = o.SysReg;
450 break;
451 case k_SysCR:
452 SysCRImm = o.SysCRImm;
453 break;
454 case k_Prefetch:
455 Prefetch = o.Prefetch;
456 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000457 case k_PSBHint:
458 PSBHint = o.PSBHint;
459 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000460 case k_ShiftExtend:
461 ShiftExtend = o.ShiftExtend;
462 break;
463 }
464 }
465
466 /// getStartLoc - Get the location of the first token of this operand.
467 SMLoc getStartLoc() const override { return StartLoc; }
468 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000469 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000470
471 StringRef getToken() const {
472 assert(Kind == k_Token && "Invalid access!");
473 return StringRef(Tok.Data, Tok.Length);
474 }
475
476 bool isTokenSuffix() const {
477 assert(Kind == k_Token && "Invalid access!");
478 return Tok.IsSuffix;
479 }
480
481 const MCExpr *getImm() const {
482 assert(Kind == k_Immediate && "Invalid access!");
483 return Imm.Val;
484 }
485
486 const MCExpr *getShiftedImmVal() const {
487 assert(Kind == k_ShiftedImm && "Invalid access!");
488 return ShiftedImm.Val;
489 }
490
491 unsigned getShiftedImmShift() const {
492 assert(Kind == k_ShiftedImm && "Invalid access!");
493 return ShiftedImm.ShiftAmount;
494 }
495
496 AArch64CC::CondCode getCondCode() const {
497 assert(Kind == k_CondCode && "Invalid access!");
498 return CondCode.Code;
499 }
500
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000501 APFloat getFPImm() const {
502 assert (Kind == k_FPImm && "Invalid access!");
503 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
504 }
505
506 bool getFPImmIsExact() const {
507 assert (Kind == k_FPImm && "Invalid access!");
508 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000509 }
510
511 unsigned getBarrier() const {
512 assert(Kind == k_Barrier && "Invalid access!");
513 return Barrier.Val;
514 }
515
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000516 StringRef getBarrierName() const {
517 assert(Kind == k_Barrier && "Invalid access!");
518 return StringRef(Barrier.Data, Barrier.Length);
519 }
520
Tim Northover3b0846e2014-05-24 12:50:23 +0000521 unsigned getReg() const override {
522 assert(Kind == k_Register && "Invalid access!");
523 return Reg.RegNum;
524 }
525
Sander de Smalen0325e302018-07-02 07:34:52 +0000526 RegConstraintEqualityTy getRegEqualityTy() const {
527 assert(Kind == k_Register && "Invalid access!");
528 return Reg.EqualityTy;
529 }
530
Tim Northover3b0846e2014-05-24 12:50:23 +0000531 unsigned getVectorListStart() const {
532 assert(Kind == k_VectorList && "Invalid access!");
533 return VectorList.RegNum;
534 }
535
536 unsigned getVectorListCount() const {
537 assert(Kind == k_VectorList && "Invalid access!");
538 return VectorList.Count;
539 }
540
541 unsigned getVectorIndex() const {
542 assert(Kind == k_VectorIndex && "Invalid access!");
543 return VectorIndex.Val;
544 }
545
546 StringRef getSysReg() const {
547 assert(Kind == k_SysReg && "Invalid access!");
548 return StringRef(SysReg.Data, SysReg.Length);
549 }
550
Tim Northover3b0846e2014-05-24 12:50:23 +0000551 unsigned getSysCR() const {
552 assert(Kind == k_SysCR && "Invalid access!");
553 return SysCRImm.Val;
554 }
555
556 unsigned getPrefetch() const {
557 assert(Kind == k_Prefetch && "Invalid access!");
558 return Prefetch.Val;
559 }
560
Oliver Stannarda34e4702015-12-01 10:48:51 +0000561 unsigned getPSBHint() const {
562 assert(Kind == k_PSBHint && "Invalid access!");
563 return PSBHint.Val;
564 }
565
566 StringRef getPSBHintName() const {
567 assert(Kind == k_PSBHint && "Invalid access!");
568 return StringRef(PSBHint.Data, PSBHint.Length);
569 }
570
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000571 StringRef getPrefetchName() const {
572 assert(Kind == k_Prefetch && "Invalid access!");
573 return StringRef(Prefetch.Data, Prefetch.Length);
574 }
575
Tim Northover3b0846e2014-05-24 12:50:23 +0000576 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000577 if (Kind == k_ShiftExtend)
578 return ShiftExtend.Type;
579 if (Kind == k_Register)
580 return Reg.ShiftExtend.Type;
581 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000582 }
583
584 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000585 if (Kind == k_ShiftExtend)
586 return ShiftExtend.Amount;
587 if (Kind == k_Register)
588 return Reg.ShiftExtend.Amount;
589 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000590 }
591
592 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000593 if (Kind == k_ShiftExtend)
594 return ShiftExtend.HasExplicitAmount;
595 if (Kind == k_Register)
596 return Reg.ShiftExtend.HasExplicitAmount;
597 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000598 }
599
600 bool isImm() const override { return Kind == k_Immediate; }
601 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000602
Sjoerd Meijera3dad802018-07-06 12:32:33 +0000603 bool isUImm6() const {
604 if (!isImm())
605 return false;
606 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
607 if (!MCE)
608 return false;
609 int64_t Val = MCE->getValue();
610 return (Val >= 0 && Val < 64);
611 }
612
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000613 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
614
Sander de Smalen50ded902018-04-29 17:33:38 +0000615 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
616 return isImmScaled<Bits, Scale>(true);
617 }
618
619 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
620 return isImmScaled<Bits, Scale>(false);
621 }
622
Sander de Smalenfe17a782018-04-26 12:54:42 +0000623 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000624 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000625 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000626 return DiagnosticPredicateTy::NoMatch;
627
Tim Northover3b0846e2014-05-24 12:50:23 +0000628 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
629 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000630 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000631
Sander de Smalen50ded902018-04-29 17:33:38 +0000632 int64_t MinVal, MaxVal;
633 if (Signed) {
634 int64_t Shift = Bits - 1;
635 MinVal = (int64_t(1) << Shift) * -Scale;
636 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
637 } else {
638 MinVal = 0;
639 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
640 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000641
Tim Northover3b0846e2014-05-24 12:50:23 +0000642 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000643 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
644 return DiagnosticPredicateTy::Match;
645
646 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000647 }
648
Sander de Smalen0325e302018-07-02 07:34:52 +0000649 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000650 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000651 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000652 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
653 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000654 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000655 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000656 if (Val >= 0 && Val < 32)
657 return DiagnosticPredicateTy::Match;
658 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000659 }
660
Tim Northover3b0846e2014-05-24 12:50:23 +0000661 bool isSymbolicUImm12Offset(const MCExpr *Expr, unsigned Scale) const {
662 AArch64MCExpr::VariantKind ELFRefKind;
663 MCSymbolRefExpr::VariantKind DarwinRefKind;
664 int64_t Addend;
665 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
666 Addend)) {
667 // If we don't understand the expression, assume the best and
668 // let the fixup and relocation code deal with it.
669 return true;
670 }
671
672 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
673 ELFRefKind == AArch64MCExpr::VK_LO12 ||
674 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
675 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
676 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
677 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
678 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
679 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000680 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
681 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
682 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000683 // Note that we don't range-check the addend. It's adjusted modulo page
684 // size when converted, so there is no "out of range" condition when using
685 // @pageoff.
686 return Addend >= 0 && (Addend % Scale) == 0;
687 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
688 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
689 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
690 return Addend == 0;
691 }
692
693 return false;
694 }
695
696 template <int Scale> bool isUImm12Offset() const {
697 if (!isImm())
698 return false;
699
700 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
701 if (!MCE)
702 return isSymbolicUImm12Offset(getImm(), Scale);
703
704 int64_t Val = MCE->getValue();
705 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
706 }
707
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000708 template <int N, int M>
709 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000710 if (!isImm())
711 return false;
712 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
713 if (!MCE)
714 return false;
715 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000716 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000717 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000718
Sander de Smalena1c259c2018-01-29 13:05:38 +0000719 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
720 // a logical immediate can always be represented when inverted.
721 template <typename T>
722 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000723 if (!isImm())
724 return false;
725 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
726 if (!MCE)
727 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000728
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000729 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000730 int64_t SVal = typename std::make_signed<T>::type(Val);
731 int64_t UVal = typename std::make_unsigned<T>::type(Val);
732 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000733 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000734
Sander de Smalena1c259c2018-01-29 13:05:38 +0000735 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000736 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000737
Tim Northover3b0846e2014-05-24 12:50:23 +0000738 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000739
Sander de Smalen62770792018-05-25 09:47:52 +0000740 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
741 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
742 /// immediate that can be shifted by 'Shift'.
743 template <unsigned Width>
744 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
745 if (isShiftedImm() && Width == getShiftedImmShift())
746 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
747 return std::make_pair(CE->getValue(), Width);
748
749 if (isImm())
750 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
751 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000752 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000753 return std::make_pair(Val >> Width, Width);
754 else
755 return std::make_pair(Val, 0u);
756 }
757
758 return {};
759 }
760
Tim Northover3b0846e2014-05-24 12:50:23 +0000761 bool isAddSubImm() const {
762 if (!isShiftedImm() && !isImm())
763 return false;
764
765 const MCExpr *Expr;
766
767 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
768 if (isShiftedImm()) {
769 unsigned Shift = ShiftedImm.ShiftAmount;
770 Expr = ShiftedImm.Val;
771 if (Shift != 0 && Shift != 12)
772 return false;
773 } else {
774 Expr = getImm();
775 }
776
777 AArch64MCExpr::VariantKind ELFRefKind;
778 MCSymbolRefExpr::VariantKind DarwinRefKind;
779 int64_t Addend;
780 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
781 DarwinRefKind, Addend)) {
782 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
783 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
784 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
785 || ELFRefKind == AArch64MCExpr::VK_LO12
786 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
787 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
788 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
789 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
790 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
791 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000792 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
793 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
794 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000795 }
796
Sander de Smalen98686c62018-05-29 10:39:49 +0000797 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000798 if (auto ShiftedVal = getShiftedVal<12>())
799 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000800
801 // If it's an expression, we hope for the best and let the fixup/relocation
802 // code deal with it.
803 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000804 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000805
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000806 bool isAddSubImmNeg() const {
807 if (!isShiftedImm() && !isImm())
808 return false;
809
Sander de Smalen98686c62018-05-29 10:39:49 +0000810 // Otherwise it should be a real negative immediate in range.
811 if (auto ShiftedVal = getShiftedVal<12>())
812 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000813
Sander de Smalen98686c62018-05-29 10:39:49 +0000814 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000815 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000816
Sander de Smalen62770792018-05-25 09:47:52 +0000817 // Signed value in the range -128 to +127. For element widths of
818 // 16 bits or higher it may also be a signed multiple of 256 in the
819 // range -32768 to +32512.
820 // For element-width of 8 bits a range of -128 to 255 is accepted,
821 // since a copy of a byte can be either signed/unsigned.
822 template <typename T>
823 DiagnosticPredicate isSVECpyImm() const {
824 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
825 return DiagnosticPredicateTy::NoMatch;
826
827 bool IsByte =
828 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
829 if (auto ShiftedImm = getShiftedVal<8>())
830 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000831 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
832 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000833 return DiagnosticPredicateTy::Match;
834
835 return DiagnosticPredicateTy::NearMatch;
836 }
837
Sander de Smalen98686c62018-05-29 10:39:49 +0000838 // Unsigned value in the range 0 to 255. For element widths of
839 // 16 bits or higher it may also be a signed multiple of 256 in the
840 // range 0 to 65280.
841 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
842 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
843 return DiagnosticPredicateTy::NoMatch;
844
845 bool IsByte =
846 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
847 if (auto ShiftedImm = getShiftedVal<8>())
848 if (!(IsByte && ShiftedImm->second) &&
849 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
850 << ShiftedImm->second))
851 return DiagnosticPredicateTy::Match;
852
853 return DiagnosticPredicateTy::NearMatch;
854 }
855
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000856 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
857 if (isLogicalImm<T>() && !isSVECpyImm<T>())
858 return DiagnosticPredicateTy::Match;
859 return DiagnosticPredicateTy::NoMatch;
860 }
861
Tim Northover3b0846e2014-05-24 12:50:23 +0000862 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000863
Tim Northover3b0846e2014-05-24 12:50:23 +0000864 bool isSIMDImmType10() const {
865 if (!isImm())
866 return false;
867 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
868 if (!MCE)
869 return false;
870 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
871 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000872
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000873 template<int N>
874 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000875 if (!isImm())
876 return false;
877 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
878 if (!MCE)
879 return true;
880 int64_t Val = MCE->getValue();
881 if (Val & 0x3)
882 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000883 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
884 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000885 }
886
887 bool
888 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
889 if (!isImm())
890 return false;
891
892 AArch64MCExpr::VariantKind ELFRefKind;
893 MCSymbolRefExpr::VariantKind DarwinRefKind;
894 int64_t Addend;
895 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
896 DarwinRefKind, Addend)) {
897 return false;
898 }
899 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
900 return false;
901
902 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
903 if (ELFRefKind == AllowedModifiers[i])
904 return Addend == 0;
905 }
906
907 return false;
908 }
909
910 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000911 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000912 }
913
914 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000915 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
916 AArch64MCExpr::VK_TPREL_G2,
917 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000918 }
919
920 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000921 return isMovWSymbol({
922 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000923 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
924 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000925 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000926 }
927
928 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000929 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
930 AArch64MCExpr::VK_TPREL_G0,
931 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000932 }
933
934 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000935 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000936 }
937
938 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000939 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000940 }
941
942 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000943 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
944 AArch64MCExpr::VK_TPREL_G1_NC,
945 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000946 }
947
948 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000949 return isMovWSymbol(
950 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
951 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000952 }
953
954 template<int RegWidth, int Shift>
955 bool isMOVZMovAlias() const {
956 if (!isImm()) return false;
957
958 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
959 if (!CE) return false;
960 uint64_t Value = CE->getValue();
961
Tim Northoverdaa1c012016-06-16 01:42:25 +0000962 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000963 }
964
965 template<int RegWidth, int Shift>
966 bool isMOVNMovAlias() const {
967 if (!isImm()) return false;
968
969 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
970 if (!CE) return false;
971 uint64_t Value = CE->getValue();
972
Tim Northoverdaa1c012016-06-16 01:42:25 +0000973 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000974 }
975
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000976 bool isFPImm() const {
977 return Kind == k_FPImm &&
978 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
979 }
980
Tim Northover3b0846e2014-05-24 12:50:23 +0000981 bool isBarrier() const { return Kind == k_Barrier; }
982 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000983
Tim Northover3b0846e2014-05-24 12:50:23 +0000984 bool isMRSSystemRegister() const {
985 if (!isSysReg()) return false;
986
Tim Northover7cd58932015-01-22 17:23:04 +0000987 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000988 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000989
Tim Northover3b0846e2014-05-24 12:50:23 +0000990 bool isMSRSystemRegister() const {
991 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000992 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000993 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000994
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000995 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000996 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000997 return (SysReg.PStateField == AArch64PState::PAN ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +0000998 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard911ea202015-11-26 15:32:30 +0000999 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001000 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001001
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001002 bool isSystemPStateFieldWithImm0_15() const {
1003 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001004 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001005 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001006
Florian Hahnc4422242017-11-07 13:07:50 +00001007 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00001008 return Kind == k_Register;
1009 }
1010
1011 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001012 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1013 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001014
Florian Hahnc4422242017-11-07 13:07:50 +00001015 bool isNeonVectorReg() const {
1016 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1017 }
1018
1019 bool isNeonVectorRegLo() const {
1020 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001021 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1022 Reg.RegNum);
1023 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001024
Sander de Smalencd6be962017-12-20 11:02:42 +00001025 template <unsigned Class> bool isSVEVectorReg() const {
1026 RegKind RK;
1027 switch (Class) {
1028 case AArch64::ZPRRegClassID:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00001029 case AArch64::ZPR_3bRegClassID:
1030 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001031 RK = RegKind::SVEDataVector;
1032 break;
1033 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +00001034 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001035 RK = RegKind::SVEPredicateVector;
1036 break;
1037 default:
1038 llvm_unreachable("Unsupport register class");
1039 }
1040
1041 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +00001042 AArch64MCRegisterClasses[Class].contains(getReg());
1043 }
1044
Sander de Smalenfd54a782018-06-04 07:07:35 +00001045 template <unsigned Class> bool isFPRasZPR() const {
1046 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1047 AArch64MCRegisterClasses[Class].contains(getReg());
1048 }
1049
Sander de Smalencd6be962017-12-20 11:02:42 +00001050 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +00001051 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1052 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1053 return DiagnosticPredicateTy::NoMatch;
1054
1055 if (isSVEVectorReg<Class>() &&
1056 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1057 return DiagnosticPredicateTy::Match;
1058
1059 return DiagnosticPredicateTy::NearMatch;
1060 }
1061
1062 template <int ElementWidth, unsigned Class>
1063 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1064 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1065 return DiagnosticPredicateTy::NoMatch;
1066
1067 if (isSVEVectorReg<Class>() &&
1068 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1069 return DiagnosticPredicateTy::Match;
1070
1071 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00001072 }
1073
Sander de Smaleneb896b12018-04-25 09:26:47 +00001074 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001075 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1076 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001077 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1078 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1079 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001080 return DiagnosticPredicateTy::NoMatch;
1081
Sander de Smalen5861c262018-04-30 07:24:38 +00001082 // Give a more specific diagnostic when the user has explicitly typed in
1083 // a shift-amount that does not match what is expected, but for which
1084 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1085 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1086 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1087 ShiftExtendTy == AArch64_AM::SXTW) &&
1088 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1089 return DiagnosticPredicateTy::NoMatch;
1090
1091 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001092 return DiagnosticPredicateTy::Match;
1093
1094 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001095 }
1096
Tim Northover3b0846e2014-05-24 12:50:23 +00001097 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001098 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001099 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1100 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001101
Sander de Smalen0325e302018-07-02 07:34:52 +00001102 bool isGPR64as32() const {
1103 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1104 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1105 }
1106
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001107 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001108 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001109 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1110 Reg.RegNum);
1111 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001112
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001113 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001114 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001115 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1116 Reg.RegNum);
1117 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001118
Sam Parker5f934642017-08-31 09:27:04 +00001119 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001120 DiagnosticPredicate isComplexRotation() const {
1121 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001122
1123 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001124 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001125 uint64_t Value = CE->getValue();
1126
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001127 if (Value % Angle == Remainder && Value <= 270)
1128 return DiagnosticPredicateTy::Match;
1129 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001130 }
1131
Sander de Smalen149916d2018-04-20 07:24:20 +00001132 template <unsigned RegClassID> bool isGPR64() const {
1133 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1134 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1135 }
1136
1137 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001138 DiagnosticPredicate isGPR64WithShiftExtend() const {
1139 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1140 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001141
Sander de Smalenfe17a782018-04-26 12:54:42 +00001142 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1143 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1144 return DiagnosticPredicateTy::Match;
1145 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001146 }
1147
Tim Northover3b0846e2014-05-24 12:50:23 +00001148 /// Is this a vector list with the type implicit (presumably attached to the
1149 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001150 template <RegKind VectorKind, unsigned NumRegs>
1151 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001152 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001153 VectorList.NumElements == 0 &&
1154 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001155 }
1156
Sander de Smalen650234b2018-04-12 11:40:52 +00001157 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1158 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001159 bool isTypedVectorList() const {
1160 if (Kind != k_VectorList)
1161 return false;
1162 if (VectorList.Count != NumRegs)
1163 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001164 if (VectorList.RegisterKind != VectorKind)
1165 return false;
1166 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001167 return false;
1168 return VectorList.NumElements == NumElements;
1169 }
1170
Sander de Smalenc33d6682018-06-04 06:40:55 +00001171 template <int Min, int Max>
1172 DiagnosticPredicate isVectorIndex() const {
1173 if (Kind != k_VectorIndex)
1174 return DiagnosticPredicateTy::NoMatch;
1175 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1176 return DiagnosticPredicateTy::Match;
1177 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001178 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001179
Tim Northover3b0846e2014-05-24 12:50:23 +00001180 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001181
Tim Northover3b0846e2014-05-24 12:50:23 +00001182 bool isTokenEqual(StringRef Str) const {
1183 return Kind == k_Token && getToken() == Str;
1184 }
1185 bool isSysCR() const { return Kind == k_SysCR; }
1186 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001187 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001188 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1189 bool isShifter() const {
1190 if (!isShiftExtend())
1191 return false;
1192
1193 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1194 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1195 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1196 ST == AArch64_AM::MSL);
1197 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001198
1199 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1200 if (Kind != k_FPImm)
1201 return DiagnosticPredicateTy::NoMatch;
1202
1203 if (getFPImmIsExact()) {
1204 // Lookup the immediate from table of supported immediates.
1205 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1206 assert(Desc && "Unknown enum value");
1207
1208 // Calculate its FP value.
1209 APFloat RealVal(APFloat::IEEEdouble());
1210 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1211 APFloat::opOK)
1212 llvm_unreachable("FP immediate is not exact");
1213
1214 if (getFPImm().bitwiseIsEqual(RealVal))
1215 return DiagnosticPredicateTy::Match;
1216 }
1217
1218 return DiagnosticPredicateTy::NearMatch;
1219 }
1220
1221 template <unsigned ImmA, unsigned ImmB>
1222 DiagnosticPredicate isExactFPImm() const {
1223 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1224 if ((Res = isExactFPImm<ImmA>()))
1225 return DiagnosticPredicateTy::Match;
1226 if ((Res = isExactFPImm<ImmB>()))
1227 return DiagnosticPredicateTy::Match;
1228 return Res;
1229 }
1230
Tim Northover3b0846e2014-05-24 12:50:23 +00001231 bool isExtend() const {
1232 if (!isShiftExtend())
1233 return false;
1234
1235 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1236 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1237 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1238 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1239 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1240 ET == AArch64_AM::LSL) &&
1241 getShiftExtendAmount() <= 4;
1242 }
1243
1244 bool isExtend64() const {
1245 if (!isExtend())
1246 return false;
1247 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1248 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1249 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1250 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001251
Tim Northover3b0846e2014-05-24 12:50:23 +00001252 bool isExtendLSL64() const {
1253 if (!isExtend())
1254 return false;
1255 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1256 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1257 ET == AArch64_AM::LSL) &&
1258 getShiftExtendAmount() <= 4;
1259 }
1260
1261 template<int Width> bool isMemXExtend() const {
1262 if (!isExtend())
1263 return false;
1264 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1265 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1266 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1267 getShiftExtendAmount() == 0);
1268 }
1269
1270 template<int Width> bool isMemWExtend() const {
1271 if (!isExtend())
1272 return false;
1273 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1274 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1275 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1276 getShiftExtendAmount() == 0);
1277 }
1278
1279 template <unsigned width>
1280 bool isArithmeticShifter() const {
1281 if (!isShifter())
1282 return false;
1283
1284 // An arithmetic shifter is LSL, LSR, or ASR.
1285 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1286 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1287 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1288 }
1289
1290 template <unsigned width>
1291 bool isLogicalShifter() const {
1292 if (!isShifter())
1293 return false;
1294
1295 // A logical shifter is LSL, LSR, ASR or ROR.
1296 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1297 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1298 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1299 getShiftExtendAmount() < width;
1300 }
1301
1302 bool isMovImm32Shifter() const {
1303 if (!isShifter())
1304 return false;
1305
1306 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1307 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1308 if (ST != AArch64_AM::LSL)
1309 return false;
1310 uint64_t Val = getShiftExtendAmount();
1311 return (Val == 0 || Val == 16);
1312 }
1313
1314 bool isMovImm64Shifter() const {
1315 if (!isShifter())
1316 return false;
1317
1318 // A MOVi shifter is LSL of 0 or 16.
1319 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1320 if (ST != AArch64_AM::LSL)
1321 return false;
1322 uint64_t Val = getShiftExtendAmount();
1323 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1324 }
1325
1326 bool isLogicalVecShifter() const {
1327 if (!isShifter())
1328 return false;
1329
1330 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1331 unsigned Shift = getShiftExtendAmount();
1332 return getShiftExtendType() == AArch64_AM::LSL &&
1333 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1334 }
1335
1336 bool isLogicalVecHalfWordShifter() const {
1337 if (!isLogicalVecShifter())
1338 return false;
1339
1340 // A logical vector shifter is a left shift by 0 or 8.
1341 unsigned Shift = getShiftExtendAmount();
1342 return getShiftExtendType() == AArch64_AM::LSL &&
1343 (Shift == 0 || Shift == 8);
1344 }
1345
1346 bool isMoveVecShifter() const {
1347 if (!isShiftExtend())
1348 return false;
1349
1350 // A logical vector shifter is a left shift by 8 or 16.
1351 unsigned Shift = getShiftExtendAmount();
1352 return getShiftExtendType() == AArch64_AM::MSL &&
1353 (Shift == 8 || Shift == 16);
1354 }
1355
1356 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1357 // to LDUR/STUR when the offset is not legal for the former but is for
1358 // the latter. As such, in addition to checking for being a legal unscaled
1359 // address, also check that it is not a legal scaled address. This avoids
1360 // ambiguity in the matcher.
1361 template<int Width>
1362 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001363 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001364 }
1365
1366 bool isAdrpLabel() const {
1367 // Validation was handled during parsing, so we just sanity check that
1368 // something didn't go haywire.
1369 if (!isImm())
1370 return false;
1371
1372 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1373 int64_t Val = CE->getValue();
1374 int64_t Min = - (4096 * (1LL << (21 - 1)));
1375 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1376 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1377 }
1378
1379 return true;
1380 }
1381
1382 bool isAdrLabel() const {
1383 // Validation was handled during parsing, so we just sanity check that
1384 // something didn't go haywire.
1385 if (!isImm())
1386 return false;
1387
1388 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1389 int64_t Val = CE->getValue();
1390 int64_t Min = - (1LL << (21 - 1));
1391 int64_t Max = ((1LL << (21 - 1)) - 1);
1392 return Val >= Min && Val <= Max;
1393 }
1394
1395 return true;
1396 }
1397
1398 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1399 // Add as immediates when possible. Null MCExpr = 0.
1400 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001401 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001402 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001403 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001404 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001405 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001406 }
1407
1408 void addRegOperands(MCInst &Inst, unsigned N) const {
1409 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001410 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001411 }
1412
1413 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1414 assert(N == 1 && "Invalid number of operands!");
1415 assert(
1416 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1417
1418 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1419 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1420 RI->getEncodingValue(getReg()));
1421
Jim Grosbache9119e42015-05-13 18:37:00 +00001422 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001423 }
1424
Sander de Smalen0325e302018-07-02 07:34:52 +00001425 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1426 assert(N == 1 && "Invalid number of operands!");
1427 assert(
1428 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1429
1430 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1431 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1432 RI->getEncodingValue(getReg()));
1433
1434 Inst.addOperand(MCOperand::createReg(Reg));
1435 }
1436
Sander de Smalenfd54a782018-06-04 07:07:35 +00001437 template <int Width>
1438 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1439 unsigned Base;
1440 switch (Width) {
1441 case 8: Base = AArch64::B0; break;
1442 case 16: Base = AArch64::H0; break;
1443 case 32: Base = AArch64::S0; break;
1444 case 64: Base = AArch64::D0; break;
1445 case 128: Base = AArch64::Q0; break;
1446 default:
1447 llvm_unreachable("Unsupported width");
1448 }
1449 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1450 }
1451
Tim Northover3b0846e2014-05-24 12:50:23 +00001452 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1453 assert(N == 1 && "Invalid number of operands!");
1454 assert(
1455 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001456 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001457 }
1458
1459 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1460 assert(N == 1 && "Invalid number of operands!");
1461 assert(
1462 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001463 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001464 }
1465
1466 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1467 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001468 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001469 }
1470
Sander de Smalen525e3222018-04-12 13:19:32 +00001471 enum VecListIndexType {
1472 VecListIdx_DReg = 0,
1473 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001474 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001475 };
1476
1477 template <VecListIndexType RegTy, unsigned NumRegs>
1478 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001479 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001480 static const unsigned FirstRegs[][5] = {
1481 /* DReg */ { AArch64::Q0,
1482 AArch64::D0, AArch64::D0_D1,
1483 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1484 /* QReg */ { AArch64::Q0,
1485 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001486 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1487 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001488 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001489 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001490 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001491
Sander de Smalen7a210db2018-04-16 10:46:18 +00001492 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1493 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001494
Sander de Smalen525e3222018-04-12 13:19:32 +00001495 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1496 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1497 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001498 }
1499
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001500 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001501 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001502 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001503 }
1504
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001505 template <unsigned ImmIs0, unsigned ImmIs1>
1506 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1507 assert(N == 1 && "Invalid number of operands!");
1508 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1509 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1510 }
1511
Tim Northover3b0846e2014-05-24 12:50:23 +00001512 void addImmOperands(MCInst &Inst, unsigned N) const {
1513 assert(N == 1 && "Invalid number of operands!");
1514 // If this is a pageoff symrefexpr with an addend, adjust the addend
1515 // to be only the page-offset portion. Otherwise, just add the expr
1516 // as-is.
1517 addExpr(Inst, getImm());
1518 }
1519
Sander de Smalen62770792018-05-25 09:47:52 +00001520 template <int Shift>
1521 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001522 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001523 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1524 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1525 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1526 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001527 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001528 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001529 } else {
1530 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001531 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001532 }
1533 }
1534
Sander de Smalen62770792018-05-25 09:47:52 +00001535 template <int Shift>
1536 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001537 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001538 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1539 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1540 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1541 } else
1542 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001543 }
1544
Tim Northover3b0846e2014-05-24 12:50:23 +00001545 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1546 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001547 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001548 }
1549
1550 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1551 assert(N == 1 && "Invalid number of operands!");
1552 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1553 if (!MCE)
1554 addExpr(Inst, getImm());
1555 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001556 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 }
1558
1559 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1560 addImmOperands(Inst, N);
1561 }
1562
1563 template<int Scale>
1564 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1565 assert(N == 1 && "Invalid number of operands!");
1566 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1567
1568 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001569 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001570 return;
1571 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001572 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001573 }
1574
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001575 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1578 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1579 }
1580
Sander de Smalen5c625982018-04-13 12:56:14 +00001581 template <int Scale>
1582 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1583 assert(N == 1 && "Invalid number of operands!");
1584 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1585 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1586 }
1587
Sander de Smalena1c259c2018-01-29 13:05:38 +00001588 template <typename T>
1589 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001590 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001591 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001592 typename std::make_unsigned<T>::type Val = MCE->getValue();
1593 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001594 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001595 }
1596
Sander de Smalena1c259c2018-01-29 13:05:38 +00001597 template <typename T>
1598 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001599 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001600 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001601 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1602 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001603 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001604 }
1605
Tim Northover3b0846e2014-05-24 12:50:23 +00001606 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1607 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001608 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001609 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001610 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001611 }
1612
1613 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1614 // Branch operands don't encode the low bits, so shift them off
1615 // here. If it's a label, however, just put it on directly as there's
1616 // not enough information now to do anything.
1617 assert(N == 1 && "Invalid number of operands!");
1618 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1619 if (!MCE) {
1620 addExpr(Inst, getImm());
1621 return;
1622 }
1623 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001624 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001625 }
1626
1627 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1628 // Branch operands don't encode the low bits, so shift them off
1629 // here. If it's a label, however, just put it on directly as there's
1630 // not enough information now to do anything.
1631 assert(N == 1 && "Invalid number of operands!");
1632 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1633 if (!MCE) {
1634 addExpr(Inst, getImm());
1635 return;
1636 }
1637 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001638 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001639 }
1640
1641 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1642 // Branch operands don't encode the low bits, so shift them off
1643 // here. If it's a label, however, just put it on directly as there's
1644 // not enough information now to do anything.
1645 assert(N == 1 && "Invalid number of operands!");
1646 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1647 if (!MCE) {
1648 addExpr(Inst, getImm());
1649 return;
1650 }
1651 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001652 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001653 }
1654
1655 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1656 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001657 Inst.addOperand(MCOperand::createImm(
1658 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001659 }
1660
1661 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1662 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001663 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001664 }
1665
1666 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1667 assert(N == 1 && "Invalid number of operands!");
1668
Jim Grosbache9119e42015-05-13 18:37:00 +00001669 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001670 }
1671
1672 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1673 assert(N == 1 && "Invalid number of operands!");
1674
Jim Grosbache9119e42015-05-13 18:37:00 +00001675 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001676 }
1677
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001678 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1679 assert(N == 1 && "Invalid number of operands!");
1680
1681 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1682 }
1683
1684 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001685 assert(N == 1 && "Invalid number of operands!");
1686
Jim Grosbache9119e42015-05-13 18:37:00 +00001687 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001688 }
1689
1690 void addSysCROperands(MCInst &Inst, unsigned N) const {
1691 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001692 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001693 }
1694
1695 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1696 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001697 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001698 }
1699
Oliver Stannarda34e4702015-12-01 10:48:51 +00001700 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1701 assert(N == 1 && "Invalid number of operands!");
1702 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1703 }
1704
Tim Northover3b0846e2014-05-24 12:50:23 +00001705 void addShifterOperands(MCInst &Inst, unsigned N) const {
1706 assert(N == 1 && "Invalid number of operands!");
1707 unsigned Imm =
1708 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001709 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001710 }
1711
1712 void addExtendOperands(MCInst &Inst, unsigned N) const {
1713 assert(N == 1 && "Invalid number of operands!");
1714 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1715 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1716 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001717 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001718 }
1719
1720 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1721 assert(N == 1 && "Invalid number of operands!");
1722 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1723 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1724 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001725 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001726 }
1727
1728 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1729 assert(N == 2 && "Invalid number of operands!");
1730 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1731 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001732 Inst.addOperand(MCOperand::createImm(IsSigned));
1733 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001734 }
1735
1736 // For 8-bit load/store instructions with a register offset, both the
1737 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1738 // they're disambiguated by whether the shift was explicit or implicit rather
1739 // than its size.
1740 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1741 assert(N == 2 && "Invalid number of operands!");
1742 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1743 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001744 Inst.addOperand(MCOperand::createImm(IsSigned));
1745 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001746 }
1747
1748 template<int Shift>
1749 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1750 assert(N == 1 && "Invalid number of operands!");
1751
1752 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1753 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001754 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001755 }
1756
1757 template<int Shift>
1758 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1759 assert(N == 1 && "Invalid number of operands!");
1760
1761 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1762 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001763 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001764 }
1765
Sam Parker5f934642017-08-31 09:27:04 +00001766 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1767 assert(N == 1 && "Invalid number of operands!");
1768 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1769 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1770 }
1771
1772 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1773 assert(N == 1 && "Invalid number of operands!");
1774 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1775 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1776 }
1777
Tim Northover3b0846e2014-05-24 12:50:23 +00001778 void print(raw_ostream &OS) const override;
1779
David Blaikie960ea3f2014-06-08 16:18:35 +00001780 static std::unique_ptr<AArch64Operand>
1781 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1782 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001783 Op->Tok.Data = Str.data();
1784 Op->Tok.Length = Str.size();
1785 Op->Tok.IsSuffix = IsSuffix;
1786 Op->StartLoc = S;
1787 Op->EndLoc = S;
1788 return Op;
1789 }
1790
David Blaikie960ea3f2014-06-08 16:18:35 +00001791 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001792 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001793 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001794 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1795 unsigned ShiftAmount = 0,
1796 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001797 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001798 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001799 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001800 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001801 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001802 Op->Reg.ShiftExtend.Type = ExtTy;
1803 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1804 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001805 Op->StartLoc = S;
1806 Op->EndLoc = E;
1807 return Op;
1808 }
1809
David Blaikie960ea3f2014-06-08 16:18:35 +00001810 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001811 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001812 SMLoc S, SMLoc E, MCContext &Ctx,
1813 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1814 unsigned ShiftAmount = 0,
1815 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001816 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1817 Kind == RegKind::SVEPredicateVector) &&
1818 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001819 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001820 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001821 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001822 return Op;
1823 }
1824
1825 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001826 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001827 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1828 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001829 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001830 Op->VectorList.RegNum = RegNum;
1831 Op->VectorList.Count = Count;
1832 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001833 Op->VectorList.ElementWidth = ElementWidth;
1834 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001835 Op->StartLoc = S;
1836 Op->EndLoc = E;
1837 return Op;
1838 }
1839
David Blaikie960ea3f2014-06-08 16:18:35 +00001840 static std::unique_ptr<AArch64Operand>
1841 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1842 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001843 Op->VectorIndex.Val = Idx;
1844 Op->StartLoc = S;
1845 Op->EndLoc = E;
1846 return Op;
1847 }
1848
David Blaikie960ea3f2014-06-08 16:18:35 +00001849 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1850 SMLoc E, MCContext &Ctx) {
1851 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001852 Op->Imm.Val = Val;
1853 Op->StartLoc = S;
1854 Op->EndLoc = E;
1855 return Op;
1856 }
1857
David Blaikie960ea3f2014-06-08 16:18:35 +00001858 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1859 unsigned ShiftAmount,
1860 SMLoc S, SMLoc E,
1861 MCContext &Ctx) {
1862 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001863 Op->ShiftedImm .Val = Val;
1864 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1865 Op->StartLoc = S;
1866 Op->EndLoc = E;
1867 return Op;
1868 }
1869
David Blaikie960ea3f2014-06-08 16:18:35 +00001870 static std::unique_ptr<AArch64Operand>
1871 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1872 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001873 Op->CondCode.Code = Code;
1874 Op->StartLoc = S;
1875 Op->EndLoc = E;
1876 return Op;
1877 }
1878
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001879 static std::unique_ptr<AArch64Operand>
1880 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001881 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001882 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1883 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001884 Op->StartLoc = S;
1885 Op->EndLoc = S;
1886 return Op;
1887 }
1888
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001889 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1890 StringRef Str,
1891 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001892 MCContext &Ctx) {
1893 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001894 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001895 Op->Barrier.Data = Str.data();
1896 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001897 Op->StartLoc = S;
1898 Op->EndLoc = S;
1899 return Op;
1900 }
1901
Tim Northover7cd58932015-01-22 17:23:04 +00001902 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1903 uint32_t MRSReg,
1904 uint32_t MSRReg,
1905 uint32_t PStateField,
1906 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001907 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001908 Op->SysReg.Data = Str.data();
1909 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001910 Op->SysReg.MRSReg = MRSReg;
1911 Op->SysReg.MSRReg = MSRReg;
1912 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001913 Op->StartLoc = S;
1914 Op->EndLoc = S;
1915 return Op;
1916 }
1917
David Blaikie960ea3f2014-06-08 16:18:35 +00001918 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1919 SMLoc E, MCContext &Ctx) {
1920 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001921 Op->SysCRImm.Val = Val;
1922 Op->StartLoc = S;
1923 Op->EndLoc = E;
1924 return Op;
1925 }
1926
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001927 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1928 StringRef Str,
1929 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001930 MCContext &Ctx) {
1931 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001932 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001933 Op->Barrier.Data = Str.data();
1934 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001935 Op->StartLoc = S;
1936 Op->EndLoc = S;
1937 return Op;
1938 }
1939
Oliver Stannarda34e4702015-12-01 10:48:51 +00001940 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1941 StringRef Str,
1942 SMLoc S,
1943 MCContext &Ctx) {
1944 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1945 Op->PSBHint.Val = Val;
1946 Op->PSBHint.Data = Str.data();
1947 Op->PSBHint.Length = Str.size();
1948 Op->StartLoc = S;
1949 Op->EndLoc = S;
1950 return Op;
1951 }
1952
David Blaikie960ea3f2014-06-08 16:18:35 +00001953 static std::unique_ptr<AArch64Operand>
1954 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1955 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1956 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001957 Op->ShiftExtend.Type = ShOp;
1958 Op->ShiftExtend.Amount = Val;
1959 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1960 Op->StartLoc = S;
1961 Op->EndLoc = E;
1962 return Op;
1963 }
1964};
1965
1966} // end anonymous namespace.
1967
1968void AArch64Operand::print(raw_ostream &OS) const {
1969 switch (Kind) {
1970 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001971 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
1972 if (!getFPImmIsExact())
1973 OS << " (inexact)";
1974 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00001975 break;
1976 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001977 StringRef Name = getBarrierName();
1978 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001979 OS << "<barrier " << Name << ">";
1980 else
1981 OS << "<barrier invalid #" << getBarrier() << ">";
1982 break;
1983 }
1984 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001985 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001986 break;
1987 case k_ShiftedImm: {
1988 unsigned Shift = getShiftedImmShift();
1989 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001990 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001991 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1992 break;
1993 }
1994 case k_CondCode:
1995 OS << "<condcode " << getCondCode() << ">";
1996 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001997 case k_VectorList: {
1998 OS << "<vectorlist ";
1999 unsigned Reg = getVectorListStart();
2000 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2001 OS << Reg + i << " ";
2002 OS << ">";
2003 break;
2004 }
2005 case k_VectorIndex:
2006 OS << "<vectorindex " << getVectorIndex() << ">";
2007 break;
2008 case k_SysReg:
2009 OS << "<sysreg: " << getSysReg() << '>';
2010 break;
2011 case k_Token:
2012 OS << "'" << getToken() << "'";
2013 break;
2014 case k_SysCR:
2015 OS << "c" << getSysCR();
2016 break;
2017 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002018 StringRef Name = getPrefetchName();
2019 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002020 OS << "<prfop " << Name << ">";
2021 else
2022 OS << "<prfop invalid #" << getPrefetch() << ">";
2023 break;
2024 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00002025 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00002026 OS << getPSBHintName();
2027 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00002028 case k_Register:
2029 OS << "<register " << getReg() << ">";
2030 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2031 break;
2032 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00002033 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00002034 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2035 << getShiftExtendAmount();
2036 if (!hasShiftExtendAmount())
2037 OS << "<imp>";
2038 OS << '>';
2039 break;
2040 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002041}
2042
2043/// @name Auto-generated Match Functions
2044/// {
2045
2046static unsigned MatchRegisterName(StringRef Name);
2047
2048/// }
2049
Florian Hahnc4422242017-11-07 13:07:50 +00002050static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00002051 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00002052 .Case("v0", AArch64::Q0)
2053 .Case("v1", AArch64::Q1)
2054 .Case("v2", AArch64::Q2)
2055 .Case("v3", AArch64::Q3)
2056 .Case("v4", AArch64::Q4)
2057 .Case("v5", AArch64::Q5)
2058 .Case("v6", AArch64::Q6)
2059 .Case("v7", AArch64::Q7)
2060 .Case("v8", AArch64::Q8)
2061 .Case("v9", AArch64::Q9)
2062 .Case("v10", AArch64::Q10)
2063 .Case("v11", AArch64::Q11)
2064 .Case("v12", AArch64::Q12)
2065 .Case("v13", AArch64::Q13)
2066 .Case("v14", AArch64::Q14)
2067 .Case("v15", AArch64::Q15)
2068 .Case("v16", AArch64::Q16)
2069 .Case("v17", AArch64::Q17)
2070 .Case("v18", AArch64::Q18)
2071 .Case("v19", AArch64::Q19)
2072 .Case("v20", AArch64::Q20)
2073 .Case("v21", AArch64::Q21)
2074 .Case("v22", AArch64::Q22)
2075 .Case("v23", AArch64::Q23)
2076 .Case("v24", AArch64::Q24)
2077 .Case("v25", AArch64::Q25)
2078 .Case("v26", AArch64::Q26)
2079 .Case("v27", AArch64::Q27)
2080 .Case("v28", AArch64::Q28)
2081 .Case("v29", AArch64::Q29)
2082 .Case("v30", AArch64::Q30)
2083 .Case("v31", AArch64::Q31)
2084 .Default(0);
2085}
2086
Sander de Smalen73937b72018-04-11 07:36:10 +00002087/// Returns an optional pair of (#elements, element-width) if Suffix
2088/// is a valid vector kind. Where the number of elements in a vector
2089/// or the vector width is implicit or explicitly unknown (but still a
2090/// valid suffix kind), 0 is used.
2091static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2092 RegKind VectorKind) {
2093 std::pair<int, int> Res = {-1, -1};
2094
2095 switch (VectorKind) {
2096 case RegKind::NeonVector:
2097 Res =
2098 StringSwitch<std::pair<int, int>>(Suffix.lower())
2099 .Case("", {0, 0})
2100 .Case(".1d", {1, 64})
2101 .Case(".1q", {1, 128})
2102 // '.2h' needed for fp16 scalar pairwise reductions
2103 .Case(".2h", {2, 16})
2104 .Case(".2s", {2, 32})
2105 .Case(".2d", {2, 64})
2106 // '.4b' is another special case for the ARMv8.2a dot product
2107 // operand
2108 .Case(".4b", {4, 8})
2109 .Case(".4h", {4, 16})
2110 .Case(".4s", {4, 32})
2111 .Case(".8b", {8, 8})
2112 .Case(".8h", {8, 16})
2113 .Case(".16b", {16, 8})
2114 // Accept the width neutral ones, too, for verbose syntax. If those
2115 // aren't used in the right places, the token operand won't match so
2116 // all will work out.
2117 .Case(".b", {0, 8})
2118 .Case(".h", {0, 16})
2119 .Case(".s", {0, 32})
2120 .Case(".d", {0, 64})
2121 .Default({-1, -1});
2122 break;
2123 case RegKind::SVEPredicateVector:
2124 case RegKind::SVEDataVector:
2125 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2126 .Case("", {0, 0})
2127 .Case(".b", {0, 8})
2128 .Case(".h", {0, 16})
2129 .Case(".s", {0, 32})
2130 .Case(".d", {0, 64})
2131 .Case(".q", {0, 128})
2132 .Default({-1, -1});
2133 break;
2134 default:
2135 llvm_unreachable("Unsupported RegKind");
2136 }
2137
2138 if (Res == std::make_pair(-1, -1))
2139 return Optional<std::pair<int, int>>();
2140
2141 return Optional<std::pair<int, int>>(Res);
2142}
2143
2144static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2145 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002146}
2147
Florian Hahn91f11e52017-11-07 16:45:48 +00002148static unsigned matchSVEDataVectorRegName(StringRef Name) {
2149 return StringSwitch<unsigned>(Name.lower())
2150 .Case("z0", AArch64::Z0)
2151 .Case("z1", AArch64::Z1)
2152 .Case("z2", AArch64::Z2)
2153 .Case("z3", AArch64::Z3)
2154 .Case("z4", AArch64::Z4)
2155 .Case("z5", AArch64::Z5)
2156 .Case("z6", AArch64::Z6)
2157 .Case("z7", AArch64::Z7)
2158 .Case("z8", AArch64::Z8)
2159 .Case("z9", AArch64::Z9)
2160 .Case("z10", AArch64::Z10)
2161 .Case("z11", AArch64::Z11)
2162 .Case("z12", AArch64::Z12)
2163 .Case("z13", AArch64::Z13)
2164 .Case("z14", AArch64::Z14)
2165 .Case("z15", AArch64::Z15)
2166 .Case("z16", AArch64::Z16)
2167 .Case("z17", AArch64::Z17)
2168 .Case("z18", AArch64::Z18)
2169 .Case("z19", AArch64::Z19)
2170 .Case("z20", AArch64::Z20)
2171 .Case("z21", AArch64::Z21)
2172 .Case("z22", AArch64::Z22)
2173 .Case("z23", AArch64::Z23)
2174 .Case("z24", AArch64::Z24)
2175 .Case("z25", AArch64::Z25)
2176 .Case("z26", AArch64::Z26)
2177 .Case("z27", AArch64::Z27)
2178 .Case("z28", AArch64::Z28)
2179 .Case("z29", AArch64::Z29)
2180 .Case("z30", AArch64::Z30)
2181 .Case("z31", AArch64::Z31)
2182 .Default(0);
2183}
2184
Sander de Smalencd6be962017-12-20 11:02:42 +00002185static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2186 return StringSwitch<unsigned>(Name.lower())
2187 .Case("p0", AArch64::P0)
2188 .Case("p1", AArch64::P1)
2189 .Case("p2", AArch64::P2)
2190 .Case("p3", AArch64::P3)
2191 .Case("p4", AArch64::P4)
2192 .Case("p5", AArch64::P5)
2193 .Case("p6", AArch64::P6)
2194 .Case("p7", AArch64::P7)
2195 .Case("p8", AArch64::P8)
2196 .Case("p9", AArch64::P9)
2197 .Case("p10", AArch64::P10)
2198 .Case("p11", AArch64::P11)
2199 .Case("p12", AArch64::P12)
2200 .Case("p13", AArch64::P13)
2201 .Case("p14", AArch64::P14)
2202 .Case("p15", AArch64::P15)
2203 .Default(0);
2204}
2205
Tim Northover3b0846e2014-05-24 12:50:23 +00002206bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2207 SMLoc &EndLoc) {
2208 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002209 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002210 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002211 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002212}
2213
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002214// Matches a register name or register alias previously defined by '.req'
2215unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002216 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002217 unsigned RegNum = 0;
2218 if ((RegNum = matchSVEDataVectorRegName(Name)))
2219 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2220
Sander de Smalencd6be962017-12-20 11:02:42 +00002221 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2222 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2223
Sander de Smalenc067c302017-12-20 09:45:45 +00002224 if ((RegNum = MatchNeonVectorRegName(Name)))
2225 return Kind == RegKind::NeonVector ? RegNum : 0;
2226
2227 // The parsed register must be of RegKind Scalar
2228 if ((RegNum = MatchRegisterName(Name)))
2229 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002230
Florian Hahnc4422242017-11-07 13:07:50 +00002231 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002232 // Handle a few common aliases of registers.
2233 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2234 .Case("fp", AArch64::FP)
2235 .Case("lr", AArch64::LR)
2236 .Case("x31", AArch64::XZR)
2237 .Case("w31", AArch64::WZR)
2238 .Default(0))
2239 return Kind == RegKind::Scalar ? RegNum : 0;
2240
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002241 // Check for aliases registered via .req. Canonicalize to lower case.
2242 // That's more consistent since register names are case insensitive, and
2243 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2244 auto Entry = RegisterReqs.find(Name.lower());
2245 if (Entry == RegisterReqs.end())
2246 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002247
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002248 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002249 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002250 RegNum = Entry->getValue().second;
2251 }
2252 return RegNum;
2253}
2254
Sander de Smalen50d87022018-04-19 07:35:08 +00002255/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002256/// Identifier when called, and if it is a register name the token is eaten and
2257/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002258OperandMatchResultTy
2259AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002260 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002261 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002262 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002263 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002264
2265 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002266 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2267 if (Reg == 0)
2268 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002269
Sander de Smalen50d87022018-04-19 07:35:08 +00002270 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002271 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002272 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002273}
2274
Tim Northover3b0846e2014-05-24 12:50:23 +00002275/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002276OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002277AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002278 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002279 SMLoc S = getLoc();
2280
2281 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2282 Error(S, "Expected cN operand where 0 <= N <= 15");
2283 return MatchOperand_ParseFail;
2284 }
2285
2286 StringRef Tok = Parser.getTok().getIdentifier();
2287 if (Tok[0] != 'c' && Tok[0] != 'C') {
2288 Error(S, "Expected cN operand where 0 <= N <= 15");
2289 return MatchOperand_ParseFail;
2290 }
2291
2292 uint32_t CRNum;
2293 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2294 if (BadNum || CRNum > 15) {
2295 Error(S, "Expected cN operand where 0 <= N <= 15");
2296 return MatchOperand_ParseFail;
2297 }
2298
2299 Parser.Lex(); // Eat identifier token.
2300 Operands.push_back(
2301 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2302 return MatchOperand_Success;
2303}
2304
2305/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002306template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002307OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002308AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002309 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002310 SMLoc S = getLoc();
2311 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002312
2313 auto LookupByName = [](StringRef N) {
2314 if (IsSVEPrefetch) {
2315 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2316 return Optional<unsigned>(Res->Encoding);
2317 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2318 return Optional<unsigned>(Res->Encoding);
2319 return Optional<unsigned>();
2320 };
2321
2322 auto LookupByEncoding = [](unsigned E) {
2323 if (IsSVEPrefetch) {
2324 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2325 return Optional<StringRef>(Res->Name);
2326 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2327 return Optional<StringRef>(Res->Name);
2328 return Optional<StringRef>();
2329 };
2330 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2331
Tim Northover3b0846e2014-05-24 12:50:23 +00002332 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002333 // Eat optional hash.
2334 if (parseOptionalToken(AsmToken::Hash) ||
2335 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002336 const MCExpr *ImmVal;
2337 if (getParser().parseExpression(ImmVal))
2338 return MatchOperand_ParseFail;
2339
2340 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2341 if (!MCE) {
2342 TokError("immediate value expected for prefetch operand");
2343 return MatchOperand_ParseFail;
2344 }
2345 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002346 if (prfop > MaxVal) {
2347 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2348 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002349 return MatchOperand_ParseFail;
2350 }
2351
Sander de Smalen93380372018-05-14 11:54:41 +00002352 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002353 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002354 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002355 return MatchOperand_Success;
2356 }
2357
2358 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002359 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002360 return MatchOperand_ParseFail;
2361 }
2362
Sander de Smalen93380372018-05-14 11:54:41 +00002363 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002364 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002365 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002366 return MatchOperand_ParseFail;
2367 }
2368
2369 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002370 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002371 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002372 return MatchOperand_Success;
2373}
2374
Oliver Stannarda34e4702015-12-01 10:48:51 +00002375/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002376OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002377AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2378 MCAsmParser &Parser = getParser();
2379 SMLoc S = getLoc();
2380 const AsmToken &Tok = Parser.getTok();
2381 if (Tok.isNot(AsmToken::Identifier)) {
2382 TokError("invalid operand for instruction");
2383 return MatchOperand_ParseFail;
2384 }
2385
Tim Northovere6ae6762016-07-05 21:23:04 +00002386 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2387 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002388 TokError("invalid operand for instruction");
2389 return MatchOperand_ParseFail;
2390 }
2391
2392 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002393 Operands.push_back(AArch64Operand::CreatePSBHint(
2394 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002395 return MatchOperand_Success;
2396}
2397
Tim Northover3b0846e2014-05-24 12:50:23 +00002398/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2399/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002400OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002401AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002402 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002403 SMLoc S = getLoc();
2404 const MCExpr *Expr;
2405
2406 if (Parser.getTok().is(AsmToken::Hash)) {
2407 Parser.Lex(); // Eat hash token.
2408 }
2409
2410 if (parseSymbolicImmVal(Expr))
2411 return MatchOperand_ParseFail;
2412
2413 AArch64MCExpr::VariantKind ELFRefKind;
2414 MCSymbolRefExpr::VariantKind DarwinRefKind;
2415 int64_t Addend;
2416 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2417 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2418 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2419 // No modifier was specified at all; this is the syntax for an ELF basic
2420 // ADRP relocation (unfortunately).
2421 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002422 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002423 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2424 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2425 Addend != 0) {
2426 Error(S, "gotpage label reference not allowed an addend");
2427 return MatchOperand_ParseFail;
2428 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2429 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2430 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2431 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2432 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2433 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2434 // The operand must be an @page or @gotpage qualified symbolref.
2435 Error(S, "page or gotpage label reference expected");
2436 return MatchOperand_ParseFail;
2437 }
2438 }
2439
2440 // We have either a label reference possibly with addend or an immediate. The
2441 // addend is a raw value here. The linker will adjust it to only reference the
2442 // page.
2443 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2444 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2445
2446 return MatchOperand_Success;
2447}
2448
2449/// tryParseAdrLabel - Parse and validate a source label for the ADR
2450/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002451OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002452AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2453 SMLoc S = getLoc();
2454 const MCExpr *Expr;
2455
Sander de Smalenc69944c2018-07-09 09:58:24 +00002456 const AsmToken &Tok = getParser().getTok();
2457 if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
2458 if (getParser().parseExpression(Expr))
2459 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002460
Sander de Smalenc69944c2018-07-09 09:58:24 +00002461 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2462 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002463
Sander de Smalenc69944c2018-07-09 09:58:24 +00002464 return MatchOperand_Success;
2465 }
2466 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002467}
2468
2469/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002470template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002471OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002472AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002473 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002474 SMLoc S = getLoc();
2475
Nirav Davee833c6c2016-11-08 18:31:04 +00002476 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002477
2478 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002479 bool isNegative = parseOptionalToken(AsmToken::Minus);
2480
Tim Northover3b0846e2014-05-24 12:50:23 +00002481 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002482 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2483 if (!Hash)
2484 return MatchOperand_NoMatch;
2485 TokError("invalid floating point immediate");
2486 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002487 }
2488
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002489 // Parse hexadecimal representation.
2490 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2491 if (Tok.getIntVal() > 255 || isNegative) {
2492 TokError("encoded floating point value out of range");
2493 return MatchOperand_ParseFail;
2494 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002495
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002496 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2497 Operands.push_back(
2498 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2499 } else {
2500 // Parse FP representation.
2501 APFloat RealVal(APFloat::IEEEdouble());
2502 auto Status =
2503 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2504 if (isNegative)
2505 RealVal.changeSign();
2506
2507 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2508 Operands.push_back(
2509 AArch64Operand::CreateToken("#0", false, S, getContext()));
2510 Operands.push_back(
2511 AArch64Operand::CreateToken(".0", false, S, getContext()));
2512 } else
2513 Operands.push_back(AArch64Operand::CreateFPImm(
2514 RealVal, Status == APFloat::opOK, S, getContext()));
2515 }
2516
2517 Parser.Lex(); // Eat the token.
2518
2519 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002520}
2521
Sander de Smalen62770792018-05-25 09:47:52 +00002522/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2523/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002524OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002525AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002526 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002527 SMLoc S = getLoc();
2528
2529 if (Parser.getTok().is(AsmToken::Hash))
2530 Parser.Lex(); // Eat '#'
2531 else if (Parser.getTok().isNot(AsmToken::Integer))
2532 // Operand should start from # or should be integer, emit error otherwise.
2533 return MatchOperand_NoMatch;
2534
2535 const MCExpr *Imm;
2536 if (parseSymbolicImmVal(Imm))
2537 return MatchOperand_ParseFail;
2538 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002539 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002540 Operands.push_back(
2541 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002542 return MatchOperand_Success;
2543 }
2544
2545 // Eat ','
2546 Parser.Lex();
2547
2548 // The optional operand must be "lsl #N" where N is non-negative.
2549 if (!Parser.getTok().is(AsmToken::Identifier) ||
2550 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2551 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2552 return MatchOperand_ParseFail;
2553 }
2554
2555 // Eat 'lsl'
2556 Parser.Lex();
2557
Nirav Davee833c6c2016-11-08 18:31:04 +00002558 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002559
2560 if (Parser.getTok().isNot(AsmToken::Integer)) {
2561 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2562 return MatchOperand_ParseFail;
2563 }
2564
2565 int64_t ShiftAmount = Parser.getTok().getIntVal();
2566
2567 if (ShiftAmount < 0) {
2568 Error(Parser.getTok().getLoc(), "positive shift amount required");
2569 return MatchOperand_ParseFail;
2570 }
2571 Parser.Lex(); // Eat the number
2572
Sander de Smalen62770792018-05-25 09:47:52 +00002573 // Just in case the optional lsl #0 is used for immediates other than zero.
2574 if (ShiftAmount == 0 && Imm != 0) {
2575 SMLoc E = Parser.getTok().getLoc();
2576 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2577 return MatchOperand_Success;
2578 }
2579
Tim Northover3b0846e2014-05-24 12:50:23 +00002580 SMLoc E = Parser.getTok().getLoc();
2581 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2582 S, E, getContext()));
2583 return MatchOperand_Success;
2584}
2585
2586/// parseCondCodeString - Parse a Condition Code string.
2587AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2588 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2589 .Case("eq", AArch64CC::EQ)
2590 .Case("ne", AArch64CC::NE)
2591 .Case("cs", AArch64CC::HS)
2592 .Case("hs", AArch64CC::HS)
2593 .Case("cc", AArch64CC::LO)
2594 .Case("lo", AArch64CC::LO)
2595 .Case("mi", AArch64CC::MI)
2596 .Case("pl", AArch64CC::PL)
2597 .Case("vs", AArch64CC::VS)
2598 .Case("vc", AArch64CC::VC)
2599 .Case("hi", AArch64CC::HI)
2600 .Case("ls", AArch64CC::LS)
2601 .Case("ge", AArch64CC::GE)
2602 .Case("lt", AArch64CC::LT)
2603 .Case("gt", AArch64CC::GT)
2604 .Case("le", AArch64CC::LE)
2605 .Case("al", AArch64CC::AL)
2606 .Case("nv", AArch64CC::NV)
2607 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002608
2609 if (CC == AArch64CC::Invalid &&
2610 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2611 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2612 .Case("none", AArch64CC::EQ)
2613 .Case("any", AArch64CC::NE)
2614 .Case("nlast", AArch64CC::HS)
2615 .Case("last", AArch64CC::LO)
2616 .Case("first", AArch64CC::MI)
2617 .Case("nfrst", AArch64CC::PL)
2618 .Case("pmore", AArch64CC::HI)
2619 .Case("plast", AArch64CC::LS)
2620 .Case("tcont", AArch64CC::GE)
2621 .Case("tstop", AArch64CC::LT)
2622 .Default(AArch64CC::Invalid);
2623
Tim Northover3b0846e2014-05-24 12:50:23 +00002624 return CC;
2625}
2626
2627/// parseCondCode - Parse a Condition Code operand.
2628bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2629 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002630 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002631 SMLoc S = getLoc();
2632 const AsmToken &Tok = Parser.getTok();
2633 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2634
2635 StringRef Cond = Tok.getString();
2636 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2637 if (CC == AArch64CC::Invalid)
2638 return TokError("invalid condition code");
2639 Parser.Lex(); // Eat identifier token.
2640
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002641 if (invertCondCode) {
2642 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2643 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002644 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002645 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002646
2647 Operands.push_back(
2648 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2649 return false;
2650}
2651
2652/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2653/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002654OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002655AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002656 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002657 const AsmToken &Tok = Parser.getTok();
2658 std::string LowerID = Tok.getString().lower();
2659 AArch64_AM::ShiftExtendType ShOp =
2660 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2661 .Case("lsl", AArch64_AM::LSL)
2662 .Case("lsr", AArch64_AM::LSR)
2663 .Case("asr", AArch64_AM::ASR)
2664 .Case("ror", AArch64_AM::ROR)
2665 .Case("msl", AArch64_AM::MSL)
2666 .Case("uxtb", AArch64_AM::UXTB)
2667 .Case("uxth", AArch64_AM::UXTH)
2668 .Case("uxtw", AArch64_AM::UXTW)
2669 .Case("uxtx", AArch64_AM::UXTX)
2670 .Case("sxtb", AArch64_AM::SXTB)
2671 .Case("sxth", AArch64_AM::SXTH)
2672 .Case("sxtw", AArch64_AM::SXTW)
2673 .Case("sxtx", AArch64_AM::SXTX)
2674 .Default(AArch64_AM::InvalidShiftExtend);
2675
2676 if (ShOp == AArch64_AM::InvalidShiftExtend)
2677 return MatchOperand_NoMatch;
2678
2679 SMLoc S = Tok.getLoc();
2680 Parser.Lex();
2681
Nirav Davee833c6c2016-11-08 18:31:04 +00002682 bool Hash = parseOptionalToken(AsmToken::Hash);
2683
Tim Northover3b0846e2014-05-24 12:50:23 +00002684 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2685 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2686 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2687 ShOp == AArch64_AM::MSL) {
2688 // We expect a number here.
2689 TokError("expected #imm after shift specifier");
2690 return MatchOperand_ParseFail;
2691 }
2692
Chad Rosier2ff37b82016-12-27 16:58:09 +00002693 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002694 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2695 Operands.push_back(
2696 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2697 return MatchOperand_Success;
2698 }
2699
Chad Rosier2ff37b82016-12-27 16:58:09 +00002700 // Make sure we do actually have a number, identifier or a parenthesized
2701 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002702 SMLoc E = Parser.getTok().getLoc();
2703 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002704 !Parser.getTok().is(AsmToken::LParen) &&
2705 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002706 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002707 return MatchOperand_ParseFail;
2708 }
2709
2710 const MCExpr *ImmVal;
2711 if (getParser().parseExpression(ImmVal))
2712 return MatchOperand_ParseFail;
2713
2714 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2715 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002716 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002717 return MatchOperand_ParseFail;
2718 }
2719
Jim Grosbach57fd2622014-09-23 22:16:02 +00002720 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002721 Operands.push_back(AArch64Operand::CreateShiftExtend(
2722 ShOp, MCE->getValue(), true, S, E, getContext()));
2723 return MatchOperand_Success;
2724}
2725
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002726static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2727 if (FBS[AArch64::HasV8_1aOps])
2728 Str += "ARMv8.1a";
2729 else if (FBS[AArch64::HasV8_2aOps])
2730 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002731 else if (FBS[AArch64::HasV8_3aOps])
2732 Str += "ARMv8.3a";
2733 else if (FBS[AArch64::HasV8_4aOps])
2734 Str += "ARMv8.4a";
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002735 else
2736 Str += "(unknown)";
2737}
2738
2739void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2740 SMLoc S) {
2741 const uint16_t Op2 = Encoding & 7;
2742 const uint16_t Cm = (Encoding & 0x78) >> 3;
2743 const uint16_t Cn = (Encoding & 0x780) >> 7;
2744 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2745
2746 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2747
2748 Operands.push_back(
2749 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2750 Operands.push_back(
2751 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2752 Operands.push_back(
2753 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2754 Expr = MCConstantExpr::create(Op2, getContext());
2755 Operands.push_back(
2756 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2757}
2758
Tim Northover3b0846e2014-05-24 12:50:23 +00002759/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2760/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2761bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2762 OperandVector &Operands) {
2763 if (Name.find('.') != StringRef::npos)
2764 return TokError("invalid operand");
2765
2766 Mnemonic = Name;
2767 Operands.push_back(
2768 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2769
Rafael Espindola961d4692014-11-11 05:18:41 +00002770 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002771 const AsmToken &Tok = Parser.getTok();
2772 StringRef Op = Tok.getString();
2773 SMLoc S = Tok.getLoc();
2774
Tim Northover3b0846e2014-05-24 12:50:23 +00002775 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002776 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2777 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002778 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002779 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2780 std::string Str("IC " + std::string(IC->Name) + " requires ");
2781 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2782 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002783 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002784 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002785 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002786 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2787 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002788 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002789 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2790 std::string Str("DC " + std::string(DC->Name) + " requires ");
2791 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2792 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002793 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002794 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002795 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002796 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2797 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002798 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002799 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2800 std::string Str("AT " + std::string(AT->Name) + " requires ");
2801 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2802 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002803 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002804 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002805 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002806 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2807 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002808 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002809 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2810 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2811 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2812 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002813 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002814 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002815 }
2816
Tim Northover3b0846e2014-05-24 12:50:23 +00002817 Parser.Lex(); // Eat operand.
2818
2819 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2820 bool HasRegister = false;
2821
2822 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002823 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002824 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2825 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002826 HasRegister = true;
2827 }
2828
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002829 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002830 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002831 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002832 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002833
Nirav Davee833c6c2016-11-08 18:31:04 +00002834 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2835 return true;
2836
Tim Northover3b0846e2014-05-24 12:50:23 +00002837 return false;
2838}
2839
Alex Bradbury58eba092016-11-01 16:32:05 +00002840OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002841AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002842 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002843 const AsmToken &Tok = Parser.getTok();
2844
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002845 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2846 TokError("'csync' operand expected");
2847 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002848 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002849 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002850 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002851 const MCExpr *ImmVal;
2852 SMLoc ExprLoc = getLoc();
2853 if (getParser().parseExpression(ImmVal))
2854 return MatchOperand_ParseFail;
2855 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2856 if (!MCE) {
2857 Error(ExprLoc, "immediate value expected for barrier operand");
2858 return MatchOperand_ParseFail;
2859 }
2860 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2861 Error(ExprLoc, "barrier operand out of range");
2862 return MatchOperand_ParseFail;
2863 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002864 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2865 Operands.push_back(AArch64Operand::CreateBarrier(
2866 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002867 return MatchOperand_Success;
2868 }
2869
2870 if (Tok.isNot(AsmToken::Identifier)) {
2871 TokError("invalid operand for instruction");
2872 return MatchOperand_ParseFail;
2873 }
2874
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002875 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002876 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002877 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2878 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002879 TokError("'sy' or #imm operand expected");
2880 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002881 // The only valid named option for TSB is 'csync'
2882 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
2883 TokError("'csync' operand expected");
2884 return MatchOperand_ParseFail;
2885 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002886 TokError("invalid barrier option name");
2887 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002888 }
2889
Tim Northovere6ae6762016-07-05 21:23:04 +00002890 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002891 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002892 Parser.Lex(); // Consume the option
2893
2894 return MatchOperand_Success;
2895}
2896
Alex Bradbury58eba092016-11-01 16:32:05 +00002897OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002898AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002899 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002900 const AsmToken &Tok = Parser.getTok();
2901
2902 if (Tok.isNot(AsmToken::Identifier))
2903 return MatchOperand_NoMatch;
2904
Tim Northovere6ae6762016-07-05 21:23:04 +00002905 int MRSReg, MSRReg;
2906 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2907 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2908 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2909 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2910 } else
2911 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002912
Tim Northovere6ae6762016-07-05 21:23:04 +00002913 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2914 unsigned PStateImm = -1;
2915 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2916 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002917
Tim Northovere6ae6762016-07-05 21:23:04 +00002918 Operands.push_back(
2919 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2920 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002921 Parser.Lex(); // Eat identifier
2922
2923 return MatchOperand_Success;
2924}
2925
Florian Hahnc4422242017-11-07 13:07:50 +00002926/// tryParseNeonVectorRegister - Parse a vector register operand.
2927bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002928 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002929 if (Parser.getTok().isNot(AsmToken::Identifier))
2930 return true;
2931
2932 SMLoc S = getLoc();
2933 // Check for a vector register specifier first.
2934 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002935 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002936 OperandMatchResultTy Res =
2937 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2938 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002939 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002940
2941 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2942 if (!KindRes)
2943 return true;
2944
2945 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002946 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002947 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2948 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002949
Tim Northover3b0846e2014-05-24 12:50:23 +00002950 // If there was an explicit qualifier, that goes on as a literal text
2951 // operand.
2952 if (!Kind.empty())
2953 Operands.push_back(
2954 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2955
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002956 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2957}
2958
2959OperandMatchResultTy
2960AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002961 SMLoc SIdx = getLoc();
2962 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002963 const MCExpr *ImmVal;
2964 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002965 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002966 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2967 if (!MCE) {
2968 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002969 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002970 }
2971
2972 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002973
Nirav Davee833c6c2016-11-08 18:31:04 +00002974 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002975 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002976
2977 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2978 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002979 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002980 }
2981
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002982 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002983}
2984
Sander de Smalen73937b72018-04-11 07:36:10 +00002985// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00002986// optional kind specifier. If it is a register specifier, eat the token
2987// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00002988OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00002989AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00002990 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00002991 MCAsmParser &Parser = getParser();
2992 const AsmToken &Tok = Parser.getTok();
2993
Florian Hahn91f11e52017-11-07 16:45:48 +00002994 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00002995 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00002996
2997 StringRef Name = Tok.getString();
2998 // If there is a kind specifier, it's separated from the register name by
2999 // a '.'.
3000 size_t Start = 0, Next = Name.find('.');
3001 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003002 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003003
3004 if (RegNum) {
3005 if (Next != StringRef::npos) {
3006 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003007 if (!isValidVectorKind(Kind, MatchKind)) {
3008 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003009 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003010 }
3011 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003012 Parser.Lex(); // Eat the register token.
3013
3014 Reg = RegNum;
3015 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003016 }
3017
Sander de Smalen8e607342017-11-15 15:44:43 +00003018 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003019}
3020
Sander de Smalencd6be962017-12-20 11:02:42 +00003021/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3022OperandMatchResultTy
3023AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3024 // Check for a SVE predicate register specifier first.
3025 const SMLoc S = getLoc();
3026 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003027 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003028 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003029 if (Res != MatchOperand_Success)
3030 return Res;
3031
Sander de Smalen73937b72018-04-11 07:36:10 +00003032 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3033 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003034 return MatchOperand_NoMatch;
3035
Sander de Smalen73937b72018-04-11 07:36:10 +00003036 unsigned ElementWidth = KindRes->second;
3037 Operands.push_back(AArch64Operand::CreateVectorReg(
3038 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3039 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003040
Sander de Smalen7868e742018-01-09 11:17:06 +00003041 // Not all predicates are followed by a '/m' or '/z'.
3042 MCAsmParser &Parser = getParser();
3043 if (Parser.getTok().isNot(AsmToken::Slash))
3044 return MatchOperand_Success;
3045
3046 // But when they do they shouldn't have an element type suffix.
3047 if (!Kind.empty()) {
3048 Error(S, "not expecting size suffix");
3049 return MatchOperand_ParseFail;
3050 }
3051
3052 // Add a literal slash as operand
3053 Operands.push_back(
3054 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3055
3056 Parser.Lex(); // Eat the slash.
3057
3058 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003059 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003060 if (Pred != "z" && Pred != "m") {
3061 Error(getLoc(), "expecting 'm' or 'z' predication");
3062 return MatchOperand_ParseFail;
3063 }
3064
3065 // Add zero/merge token.
3066 const char *ZM = Pred == "z" ? "z" : "m";
3067 Operands.push_back(
3068 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3069
3070 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003071 return MatchOperand_Success;
3072}
3073
Sander de Smalen50d87022018-04-19 07:35:08 +00003074/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003075bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003076 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003077 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003078 return false;
3079
Sander de Smalen149916d2018-04-20 07:24:20 +00003080 // Otherwise try for a scalar register.
3081 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3082 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003083
Sander de Smalen149916d2018-04-20 07:24:20 +00003084 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003085}
3086
3087bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003088 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003089 bool HasELFModifier = false;
3090 AArch64MCExpr::VariantKind RefKind;
3091
Nirav Davee833c6c2016-11-08 18:31:04 +00003092 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003093 HasELFModifier = true;
3094
Nirav Davee833c6c2016-11-08 18:31:04 +00003095 if (Parser.getTok().isNot(AsmToken::Identifier))
3096 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003097
3098 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3099 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3100 .Case("lo12", AArch64MCExpr::VK_LO12)
3101 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3102 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3103 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3104 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3105 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3106 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3107 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3108 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3109 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3110 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3111 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3112 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3113 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3114 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3115 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3116 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3117 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3118 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3119 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3120 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3121 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3122 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3123 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3124 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3125 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3126 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3127 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3128 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3129 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3130 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3131 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3132 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3133 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3134 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003135 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3136 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003137 .Default(AArch64MCExpr::VK_INVALID);
3138
Nirav Davee833c6c2016-11-08 18:31:04 +00003139 if (RefKind == AArch64MCExpr::VK_INVALID)
3140 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003141
3142 Parser.Lex(); // Eat identifier
3143
Nirav Davee833c6c2016-11-08 18:31:04 +00003144 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003145 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003146 }
3147
3148 if (getParser().parseExpression(ImmVal))
3149 return true;
3150
3151 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003152 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003153
3154 return false;
3155}
3156
Sander de Smalen650234b2018-04-12 11:40:52 +00003157template <RegKind VectorKind>
3158OperandMatchResultTy
3159AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3160 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003161 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003162 if (!Parser.getTok().is(AsmToken::LCurly))
3163 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003164
3165 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003166 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003167 bool NoMatchIsError) {
3168 auto RegTok = Parser.getTok();
3169 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3170 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003171 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003172 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003173 llvm_unreachable("Expected a valid vector kind");
3174 }
3175
Sander de Smalen650234b2018-04-12 11:40:52 +00003176 if (RegTok.isNot(AsmToken::Identifier) ||
3177 ParseRes == MatchOperand_ParseFail ||
3178 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3179 Error(Loc, "vector register expected");
3180 return MatchOperand_ParseFail;
3181 }
3182
3183 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003184 };
3185
Tim Northover3b0846e2014-05-24 12:50:23 +00003186 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003187 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003188 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003189
Tim Northover3b0846e2014-05-24 12:50:23 +00003190 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003191 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003192 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3193
3194 // Put back the original left bracket if there was no match, so that
3195 // different types of list-operands can be matched (e.g. SVE, Neon).
3196 if (ParseRes == MatchOperand_NoMatch)
3197 Parser.getLexer().UnLex(LCurly);
3198
3199 if (ParseRes != MatchOperand_Success)
3200 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003201
Tim Northover3b0846e2014-05-24 12:50:23 +00003202 int64_t PrevReg = FirstReg;
3203 unsigned Count = 1;
3204
Nirav Davee833c6c2016-11-08 18:31:04 +00003205 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003206 SMLoc Loc = getLoc();
3207 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003208
Sander de Smalen50d87022018-04-19 07:35:08 +00003209 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003210 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3211 if (ParseRes != MatchOperand_Success)
3212 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003213
Tim Northover3b0846e2014-05-24 12:50:23 +00003214 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003215 if (Kind != NextKind) {
3216 Error(Loc, "mismatched register size suffix");
3217 return MatchOperand_ParseFail;
3218 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003219
3220 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3221
3222 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003223 Error(Loc, "invalid number of vectors");
3224 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003225 }
3226
3227 Count += Space;
3228 }
3229 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003230 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003231 SMLoc Loc = getLoc();
3232 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003233 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003234 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3235 if (ParseRes != MatchOperand_Success)
3236 return ParseRes;
3237
Tim Northover3b0846e2014-05-24 12:50:23 +00003238 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003239 if (Kind != NextKind) {
3240 Error(Loc, "mismatched register size suffix");
3241 return MatchOperand_ParseFail;
3242 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003243
3244 // Registers must be incremental (with wraparound at 31)
3245 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003246 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3247 Error(Loc, "registers must be sequential");
3248 return MatchOperand_ParseFail;
3249 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003250
3251 PrevReg = Reg;
3252 ++Count;
3253 }
3254 }
3255
Nirav Davee833c6c2016-11-08 18:31:04 +00003256 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003257 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003258
Sander de Smalen650234b2018-04-12 11:40:52 +00003259 if (Count > 4) {
3260 Error(S, "invalid number of vectors");
3261 return MatchOperand_ParseFail;
3262 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003263
3264 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003265 unsigned ElementWidth = 0;
3266 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003267 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003268 std::tie(NumElements, ElementWidth) = *VK;
3269 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003270
3271 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003272 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3273 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003274
Sander de Smalen650234b2018-04-12 11:40:52 +00003275 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003276}
3277
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003278/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3279bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003280 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3281 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003282 return true;
3283
3284 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3285}
3286
Alex Bradbury58eba092016-11-01 16:32:05 +00003287OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003288AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003289 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003290
Sander de Smalen50d87022018-04-19 07:35:08 +00003291 unsigned RegNum;
3292 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3293 if (Res != MatchOperand_Success)
3294 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003295
Nirav Davee833c6c2016-11-08 18:31:04 +00003296 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003297 Operands.push_back(AArch64Operand::CreateReg(
3298 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003299 return MatchOperand_Success;
3300 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003301
Nirav Davee833c6c2016-11-08 18:31:04 +00003302 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003303
Sander de Smalen50d87022018-04-19 07:35:08 +00003304 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003305 Error(getLoc(), "index must be absent or #0");
3306 return MatchOperand_ParseFail;
3307 }
3308
3309 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003310 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003311 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3312 Error(getLoc(), "index must be absent or #0");
3313 return MatchOperand_ParseFail;
3314 }
3315
Sander de Smalen50d87022018-04-19 07:35:08 +00003316 Operands.push_back(AArch64Operand::CreateReg(
3317 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003318 return MatchOperand_Success;
3319}
3320
Sander de Smalen0325e302018-07-02 07:34:52 +00003321template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003322OperandMatchResultTy
3323AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3324 SMLoc StartLoc = getLoc();
3325
3326 unsigned RegNum;
3327 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3328 if (Res != MatchOperand_Success)
3329 return Res;
3330
3331 // No shift/extend is the default.
3332 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3333 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003334 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003335 return MatchOperand_Success;
3336 }
3337
3338 // Eat the comma
3339 getParser().Lex();
3340
3341 // Match the shift
3342 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3343 Res = tryParseOptionalShiftExtend(ExtOpnd);
3344 if (Res != MatchOperand_Success)
3345 return Res;
3346
3347 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003348 Operands.push_back(AArch64Operand::CreateReg(
3349 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3350 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3351 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003352
3353 return MatchOperand_Success;
3354}
3355
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003356bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003357 MCAsmParser &Parser = getParser();
3358
3359 // Some SVE instructions have a decoration after the immediate, i.e.
3360 // "mul vl". We parse them here and add tokens, which must be present in the
3361 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003362 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3363 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003364 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003365 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003366 return true;
3367
Sander de Smalen5c625982018-04-13 12:56:14 +00003368 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003369 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003370 Parser.Lex(); // Eat the "mul"
3371
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003372 if (NextIsVL) {
3373 Operands.push_back(
3374 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3375 Parser.Lex(); // Eat the "vl"
3376 return false;
3377 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003378
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003379 if (NextIsHash) {
3380 Parser.Lex(); // Eat the #
3381 SMLoc S = getLoc();
3382
3383 // Parse immediate operand.
3384 const MCExpr *ImmVal;
3385 if (!Parser.parseExpression(ImmVal))
3386 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3387 Operands.push_back(AArch64Operand::CreateImm(
3388 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3389 getContext()));
3390 return MatchOperand_Success;
3391 }
3392 }
3393
3394 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003395}
3396
Tim Northover3b0846e2014-05-24 12:50:23 +00003397/// parseOperand - Parse a arm instruction operand. For now this parses the
3398/// operand regardless of the mnemonic.
3399bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3400 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003401 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003402
3403 OperandMatchResultTy ResTy =
3404 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3405
Tim Northover3b0846e2014-05-24 12:50:23 +00003406 // Check if the current operand has a custom associated parser, if so, try to
3407 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003408 if (ResTy == MatchOperand_Success)
3409 return false;
3410 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3411 // there was a match, but an error occurred, in which case, just return that
3412 // the operand parsing failed.
3413 if (ResTy == MatchOperand_ParseFail)
3414 return true;
3415
3416 // Nothing custom, so do general case parsing.
3417 SMLoc S, E;
3418 switch (getLexer().getKind()) {
3419 default: {
3420 SMLoc S = getLoc();
3421 const MCExpr *Expr;
3422 if (parseSymbolicImmVal(Expr))
3423 return Error(S, "invalid operand");
3424
3425 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3426 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3427 return false;
3428 }
3429 case AsmToken::LBrac: {
3430 SMLoc Loc = Parser.getTok().getLoc();
3431 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3432 getContext()));
3433 Parser.Lex(); // Eat '['
3434
3435 // There's no comma after a '[', so we can parse the next operand
3436 // immediately.
3437 return parseOperand(Operands, false, false);
3438 }
3439 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003440 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003441 case AsmToken::Identifier: {
3442 // If we're expecting a Condition Code operand, then just parse that.
3443 if (isCondCode)
3444 return parseCondCode(Operands, invertCondCode);
3445
3446 // If it's a register name, parse it.
3447 if (!parseRegister(Operands))
3448 return false;
3449
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003450 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3451 // by SVE instructions.
3452 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003453 return false;
3454
Tim Northover3b0846e2014-05-24 12:50:23 +00003455 // This could be an optional "shift" or "extend" operand.
3456 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3457 // We can only continue if no tokens were eaten.
3458 if (GotShift != MatchOperand_NoMatch)
3459 return GotShift;
3460
3461 // This was not a register so parse other operands that start with an
3462 // identifier (like labels) as expressions and create them as immediates.
3463 const MCExpr *IdVal;
3464 S = getLoc();
3465 if (getParser().parseExpression(IdVal))
3466 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003467 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3468 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3469 return false;
3470 }
3471 case AsmToken::Integer:
3472 case AsmToken::Real:
3473 case AsmToken::Hash: {
3474 // #42 -> immediate.
3475 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003476
3477 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003478
3479 // Parse a negative sign
3480 bool isNegative = false;
3481 if (Parser.getTok().is(AsmToken::Minus)) {
3482 isNegative = true;
3483 // We need to consume this token only when we have a Real, otherwise
3484 // we let parseSymbolicImmVal take care of it
3485 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3486 Parser.Lex();
3487 }
3488
3489 // The only Real that should come through here is a literal #0.0 for
3490 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3491 // so convert the value.
3492 const AsmToken &Tok = Parser.getTok();
3493 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003494 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003495 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3496 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3497 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003498 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003499 return TokError("unexpected floating point literal");
3500 else if (IntVal != 0 || isNegative)
3501 return TokError("expected floating-point constant #0.0");
3502 Parser.Lex(); // Eat the token.
3503
3504 Operands.push_back(
3505 AArch64Operand::CreateToken("#0", false, S, getContext()));
3506 Operands.push_back(
3507 AArch64Operand::CreateToken(".0", false, S, getContext()));
3508 return false;
3509 }
3510
3511 const MCExpr *ImmVal;
3512 if (parseSymbolicImmVal(ImmVal))
3513 return true;
3514
3515 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3516 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3517 return false;
3518 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003519 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003520 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003521 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003522 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003523 Parser.Lex(); // Eat '='
3524 const MCExpr *SubExprVal;
3525 if (getParser().parseExpression(SubExprVal))
3526 return true;
3527
David Peixottoae5ba762014-07-18 16:05:14 +00003528 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003529 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003530 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003531
3532 bool IsXReg =
3533 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3534 Operands[1]->getReg());
3535
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003536 MCContext& Ctx = getContext();
3537 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3538 // 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 +00003539 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003540 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3541 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3542 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3543 ShiftAmt += 16;
3544 Imm >>= 16;
3545 }
3546 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3547 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3548 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003549 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003550 if (ShiftAmt)
3551 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3552 ShiftAmt, true, S, E, Ctx));
3553 return false;
3554 }
David Peixottoae5ba762014-07-18 16:05:14 +00003555 APInt Simm = APInt(64, Imm << ShiftAmt);
3556 // check if the immediate is an unsigned or signed 32-bit int for W regs
3557 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3558 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003559 }
3560 // 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 +00003561 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003562 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003563 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3564 return false;
3565 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003566 }
3567}
3568
Sander de Smalen0325e302018-07-02 07:34:52 +00003569bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3570 const MCParsedAsmOperand &Op2) const {
3571 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3572 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3573 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3574 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3575 return MCTargetAsmParser::regsEqual(Op1, Op2);
3576
3577 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3578 "Testing equality of non-scalar registers not supported");
3579
3580 // Check if a registers match their sub/super register classes.
3581 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3582 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3583 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3584 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3585 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3586 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3587 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3588 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3589
3590 return false;
3591}
3592
Tim Northover3b0846e2014-05-24 12:50:23 +00003593/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3594/// operands.
3595bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3596 StringRef Name, SMLoc NameLoc,
3597 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003598 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003599 Name = StringSwitch<StringRef>(Name.lower())
3600 .Case("beq", "b.eq")
3601 .Case("bne", "b.ne")
3602 .Case("bhs", "b.hs")
3603 .Case("bcs", "b.cs")
3604 .Case("blo", "b.lo")
3605 .Case("bcc", "b.cc")
3606 .Case("bmi", "b.mi")
3607 .Case("bpl", "b.pl")
3608 .Case("bvs", "b.vs")
3609 .Case("bvc", "b.vc")
3610 .Case("bhi", "b.hi")
3611 .Case("bls", "b.ls")
3612 .Case("bge", "b.ge")
3613 .Case("blt", "b.lt")
3614 .Case("bgt", "b.gt")
3615 .Case("ble", "b.le")
3616 .Case("bal", "b.al")
3617 .Case("bnv", "b.nv")
3618 .Default(Name);
3619
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003620 // First check for the AArch64-specific .req directive.
3621 if (Parser.getTok().is(AsmToken::Identifier) &&
3622 Parser.getTok().getIdentifier() == ".req") {
3623 parseDirectiveReq(Name, NameLoc);
3624 // We always return 'error' for this, as we're done with this
3625 // statement and don't need to match the 'instruction."
3626 return true;
3627 }
3628
Tim Northover3b0846e2014-05-24 12:50:23 +00003629 // Create the leading tokens for the mnemonic, split by '.' characters.
3630 size_t Start = 0, Next = Name.find('.');
3631 StringRef Head = Name.slice(Start, Next);
3632
3633 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003634 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3635 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003636
3637 Operands.push_back(
3638 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3639 Mnemonic = Head;
3640
3641 // Handle condition codes for a branch mnemonic
3642 if (Head == "b" && Next != StringRef::npos) {
3643 Start = Next;
3644 Next = Name.find('.', Start + 1);
3645 Head = Name.slice(Start + 1, Next);
3646
3647 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3648 (Head.data() - Name.data()));
3649 AArch64CC::CondCode CC = parseCondCodeString(Head);
3650 if (CC == AArch64CC::Invalid)
3651 return Error(SuffixLoc, "invalid condition code");
3652 Operands.push_back(
3653 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3654 Operands.push_back(
3655 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3656 }
3657
3658 // Add the remaining tokens in the mnemonic.
3659 while (Next != StringRef::npos) {
3660 Start = Next;
3661 Next = Name.find('.', Start + 1);
3662 Head = Name.slice(Start, Next);
3663 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3664 (Head.data() - Name.data()) + 1);
3665 Operands.push_back(
3666 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3667 }
3668
3669 // Conditional compare instructions have a Condition Code operand, which needs
3670 // to be parsed and an immediate operand created.
3671 bool condCodeFourthOperand =
3672 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3673 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3674 Head == "csinc" || Head == "csinv" || Head == "csneg");
3675
3676 // These instructions are aliases to some of the conditional select
3677 // instructions. However, the condition code is inverted in the aliased
3678 // instruction.
3679 //
3680 // FIXME: Is this the correct way to handle these? Or should the parser
3681 // generate the aliased instructions directly?
3682 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3683 bool condCodeThirdOperand =
3684 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3685
3686 // Read the remaining operands.
3687 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3688 // Read the first operand.
3689 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003690 return true;
3691 }
3692
3693 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003694 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003695 // Parse and remember the operand.
3696 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3697 (N == 3 && condCodeThirdOperand) ||
3698 (N == 2 && condCodeSecondOperand),
3699 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003700 return true;
3701 }
3702
3703 // After successfully parsing some operands there are two special cases to
3704 // consider (i.e. notional operands not separated by commas). Both are due
3705 // to memory specifiers:
3706 // + An RBrac will end an address for load/store/prefetch
3707 // + An '!' will indicate a pre-indexed operation.
3708 //
3709 // It's someone else's responsibility to make sure these tokens are sane
3710 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003711
Nirav Davee833c6c2016-11-08 18:31:04 +00003712 SMLoc RLoc = Parser.getTok().getLoc();
3713 if (parseOptionalToken(AsmToken::RBrac))
3714 Operands.push_back(
3715 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3716 SMLoc ELoc = Parser.getTok().getLoc();
3717 if (parseOptionalToken(AsmToken::Exclaim))
3718 Operands.push_back(
3719 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003720
3721 ++N;
3722 }
3723 }
3724
Nirav Davee833c6c2016-11-08 18:31:04 +00003725 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3726 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003727
Tim Northover3b0846e2014-05-24 12:50:23 +00003728 return false;
3729}
3730
Sander de Smalen9b333092018-07-30 15:42:46 +00003731static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3732 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3733 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3734 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3735 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3736 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3737 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3738 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3739}
3740
Tim Northover3b0846e2014-05-24 12:50:23 +00003741// FIXME: This entire function is a giant hack to provide us with decent
3742// operand range validation/diagnostics until TableGen/MC can be extended
3743// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003744bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3745 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003746 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003747 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3748
3749 // A prefix only applies to the instruction following it. Here we extract
3750 // prefix information for the next instruction before validating the current
3751 // one so that in the case of failure we don't erronously continue using the
3752 // current prefix.
3753 PrefixInfo Prefix = NextPrefix;
3754 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3755
3756 // Before validating the instruction in isolation we run through the rules
3757 // applicable when it follows a prefix instruction.
3758 // NOTE: brk & hlt can be prefixed but require no additional validation.
3759 if (Prefix.isActive() &&
3760 (Inst.getOpcode() != AArch64::BRK) &&
3761 (Inst.getOpcode() != AArch64::HLT)) {
3762
3763 // Prefixed intructions must have a destructive operand.
3764 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3765 AArch64::NotDestructive)
3766 return Error(IDLoc, "instruction is unpredictable when following a"
3767 " movprfx, suggest replacing movprfx with mov");
3768
3769 // Destination operands must match.
3770 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3771 return Error(Loc[0], "instruction is unpredictable when following a"
3772 " movprfx writing to a different destination");
3773
3774 // Destination operand must not be used in any other location.
3775 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3776 if (Inst.getOperand(i).isReg() &&
3777 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3778 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3779 return Error(Loc[0], "instruction is unpredictable when following a"
3780 " movprfx and destination also used as non-destructive"
3781 " source");
3782 }
3783
3784 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3785 if (Prefix.isPredicated()) {
3786 int PgIdx = -1;
3787
3788 // Find the instructions general predicate.
3789 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3790 if (Inst.getOperand(i).isReg() &&
3791 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3792 PgIdx = i;
3793 break;
3794 }
3795
3796 // Instruction must be predicated if the movprfx is predicated.
3797 if (PgIdx == -1 ||
3798 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3799 return Error(IDLoc, "instruction is unpredictable when following a"
3800 " predicated movprfx, suggest using unpredicated movprfx");
3801
3802 // Instruction must use same general predicate as the movprfx.
3803 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3804 return Error(IDLoc, "instruction is unpredictable when following a"
3805 " predicated movprfx using a different general predicate");
3806
3807 // Instruction element type must match the movprfx.
3808 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3809 return Error(IDLoc, "instruction is unpredictable when following a"
3810 " predicated movprfx with a different element size");
3811 }
3812 }
3813
Tim Northover3b0846e2014-05-24 12:50:23 +00003814 // Check for indexed addressing modes w/ the base register being the
3815 // same as a destination/source register or pair load where
3816 // the Rt == Rt2. All of those are undefined behaviour.
3817 switch (Inst.getOpcode()) {
3818 case AArch64::LDPSWpre:
3819 case AArch64::LDPWpost:
3820 case AArch64::LDPWpre:
3821 case AArch64::LDPXpost:
3822 case AArch64::LDPXpre: {
3823 unsigned Rt = Inst.getOperand(1).getReg();
3824 unsigned Rt2 = Inst.getOperand(2).getReg();
3825 unsigned Rn = Inst.getOperand(3).getReg();
3826 if (RI->isSubRegisterEq(Rn, Rt))
3827 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3828 "is also a destination");
3829 if (RI->isSubRegisterEq(Rn, Rt2))
3830 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3831 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003832 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003833 }
3834 case AArch64::LDPDi:
3835 case AArch64::LDPQi:
3836 case AArch64::LDPSi:
3837 case AArch64::LDPSWi:
3838 case AArch64::LDPWi:
3839 case AArch64::LDPXi: {
3840 unsigned Rt = Inst.getOperand(0).getReg();
3841 unsigned Rt2 = Inst.getOperand(1).getReg();
3842 if (Rt == Rt2)
3843 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3844 break;
3845 }
3846 case AArch64::LDPDpost:
3847 case AArch64::LDPDpre:
3848 case AArch64::LDPQpost:
3849 case AArch64::LDPQpre:
3850 case AArch64::LDPSpost:
3851 case AArch64::LDPSpre:
3852 case AArch64::LDPSWpost: {
3853 unsigned Rt = Inst.getOperand(1).getReg();
3854 unsigned Rt2 = Inst.getOperand(2).getReg();
3855 if (Rt == Rt2)
3856 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3857 break;
3858 }
3859 case AArch64::STPDpost:
3860 case AArch64::STPDpre:
3861 case AArch64::STPQpost:
3862 case AArch64::STPQpre:
3863 case AArch64::STPSpost:
3864 case AArch64::STPSpre:
3865 case AArch64::STPWpost:
3866 case AArch64::STPWpre:
3867 case AArch64::STPXpost:
3868 case AArch64::STPXpre: {
3869 unsigned Rt = Inst.getOperand(1).getReg();
3870 unsigned Rt2 = Inst.getOperand(2).getReg();
3871 unsigned Rn = Inst.getOperand(3).getReg();
3872 if (RI->isSubRegisterEq(Rn, Rt))
3873 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3874 "is also a source");
3875 if (RI->isSubRegisterEq(Rn, Rt2))
3876 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3877 "is also a source");
3878 break;
3879 }
3880 case AArch64::LDRBBpre:
3881 case AArch64::LDRBpre:
3882 case AArch64::LDRHHpre:
3883 case AArch64::LDRHpre:
3884 case AArch64::LDRSBWpre:
3885 case AArch64::LDRSBXpre:
3886 case AArch64::LDRSHWpre:
3887 case AArch64::LDRSHXpre:
3888 case AArch64::LDRSWpre:
3889 case AArch64::LDRWpre:
3890 case AArch64::LDRXpre:
3891 case AArch64::LDRBBpost:
3892 case AArch64::LDRBpost:
3893 case AArch64::LDRHHpost:
3894 case AArch64::LDRHpost:
3895 case AArch64::LDRSBWpost:
3896 case AArch64::LDRSBXpost:
3897 case AArch64::LDRSHWpost:
3898 case AArch64::LDRSHXpost:
3899 case AArch64::LDRSWpost:
3900 case AArch64::LDRWpost:
3901 case AArch64::LDRXpost: {
3902 unsigned Rt = Inst.getOperand(1).getReg();
3903 unsigned Rn = Inst.getOperand(2).getReg();
3904 if (RI->isSubRegisterEq(Rn, Rt))
3905 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3906 "is also a source");
3907 break;
3908 }
3909 case AArch64::STRBBpost:
3910 case AArch64::STRBpost:
3911 case AArch64::STRHHpost:
3912 case AArch64::STRHpost:
3913 case AArch64::STRWpost:
3914 case AArch64::STRXpost:
3915 case AArch64::STRBBpre:
3916 case AArch64::STRBpre:
3917 case AArch64::STRHHpre:
3918 case AArch64::STRHpre:
3919 case AArch64::STRWpre:
3920 case AArch64::STRXpre: {
3921 unsigned Rt = Inst.getOperand(1).getReg();
3922 unsigned Rn = Inst.getOperand(2).getReg();
3923 if (RI->isSubRegisterEq(Rn, Rt))
3924 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3925 "is also a source");
3926 break;
3927 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003928 case AArch64::STXRB:
3929 case AArch64::STXRH:
3930 case AArch64::STXRW:
3931 case AArch64::STXRX:
3932 case AArch64::STLXRB:
3933 case AArch64::STLXRH:
3934 case AArch64::STLXRW:
3935 case AArch64::STLXRX: {
3936 unsigned Rs = Inst.getOperand(0).getReg();
3937 unsigned Rt = Inst.getOperand(1).getReg();
3938 unsigned Rn = Inst.getOperand(2).getReg();
3939 if (RI->isSubRegisterEq(Rt, Rs) ||
3940 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3941 return Error(Loc[0],
3942 "unpredictable STXR instruction, status is also a source");
3943 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003944 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003945 case AArch64::STXPW:
3946 case AArch64::STXPX:
3947 case AArch64::STLXPW:
3948 case AArch64::STLXPX: {
3949 unsigned Rs = Inst.getOperand(0).getReg();
3950 unsigned Rt1 = Inst.getOperand(1).getReg();
3951 unsigned Rt2 = Inst.getOperand(2).getReg();
3952 unsigned Rn = Inst.getOperand(3).getReg();
3953 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3954 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3955 return Error(Loc[0],
3956 "unpredictable STXP instruction, status is also a source");
3957 break;
3958 }
3959 }
3960
Tim Northover3b0846e2014-05-24 12:50:23 +00003961
3962 // Now check immediate ranges. Separate from the above as there is overlap
3963 // in the instructions being checked and this keeps the nested conditionals
3964 // to a minimum.
3965 switch (Inst.getOpcode()) {
3966 case AArch64::ADDSWri:
3967 case AArch64::ADDSXri:
3968 case AArch64::ADDWri:
3969 case AArch64::ADDXri:
3970 case AArch64::SUBSWri:
3971 case AArch64::SUBSXri:
3972 case AArch64::SUBWri:
3973 case AArch64::SUBXri: {
3974 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3975 // some slight duplication here.
3976 if (Inst.getOperand(2).isExpr()) {
3977 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3978 AArch64MCExpr::VariantKind ELFRefKind;
3979 MCSymbolRefExpr::VariantKind DarwinRefKind;
3980 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003981 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3982
3983 // Only allow these with ADDXri.
3984 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
3985 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
3986 Inst.getOpcode() == AArch64::ADDXri)
3987 return false;
3988
3989 // Only allow these with ADDXri/ADDWri
3990 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
3991 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
3992 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
3993 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
3994 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
3995 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
3996 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003997 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
3998 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
3999 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004000 (Inst.getOpcode() == AArch64::ADDXri ||
4001 Inst.getOpcode() == AArch64::ADDWri))
4002 return false;
4003
4004 // Don't allow symbol refs in the immediate field otherwise
4005 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4006 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4007 // 'cmp w0, 'borked')
4008 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004009 }
Diana Picusc93518d2016-10-11 09:17:47 +00004010 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004011 }
4012 return false;
4013 }
4014 default:
4015 return false;
4016 }
4017}
4018
Craig Topper05515562017-10-26 06:46:41 +00004019static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
4020 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004021
4022bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004023 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004024 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004025 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004026 case Match_InvalidTiedOperand: {
4027 RegConstraintEqualityTy EqTy =
4028 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4029 .getRegEqualityTy();
4030 switch (EqTy) {
4031 case RegConstraintEqualityTy::EqualsSubReg:
4032 return Error(Loc, "operand must be 64-bit form of destination register");
4033 case RegConstraintEqualityTy::EqualsSuperReg:
4034 return Error(Loc, "operand must be 32-bit form of destination register");
4035 case RegConstraintEqualityTy::EqualsReg:
4036 return Error(Loc, "operand must match destination register");
4037 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004038 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004039 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004040 case Match_MissingFeature:
4041 return Error(Loc,
4042 "instruction requires a CPU feature not currently enabled");
4043 case Match_InvalidOperand:
4044 return Error(Loc, "invalid operand for instruction");
4045 case Match_InvalidSuffix:
4046 return Error(Loc, "invalid type suffix for instruction");
4047 case Match_InvalidCondCode:
4048 return Error(Loc, "expected AArch64 condition code");
4049 case Match_AddSubRegExtendSmall:
4050 return Error(Loc,
4051 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
4052 case Match_AddSubRegExtendLarge:
4053 return Error(Loc,
4054 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4055 case Match_AddSubSecondSource:
4056 return Error(Loc,
4057 "expected compatible register, symbol or integer in range [0, 4095]");
4058 case Match_LogicalSecondSource:
4059 return Error(Loc, "expected compatible register or logical immediate");
4060 case Match_InvalidMovImm32Shift:
4061 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4062 case Match_InvalidMovImm64Shift:
4063 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4064 case Match_AddSubRegShift32:
4065 return Error(Loc,
4066 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4067 case Match_AddSubRegShift64:
4068 return Error(Loc,
4069 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4070 case Match_InvalidFPImm:
4071 return Error(Loc,
4072 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004073 case Match_InvalidMemoryIndexedSImm6:
4074 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004075 case Match_InvalidMemoryIndexedSImm5:
4076 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004077 case Match_InvalidMemoryIndexed1SImm4:
4078 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004079 case Match_InvalidMemoryIndexed2SImm4:
4080 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004081 case Match_InvalidMemoryIndexed3SImm4:
4082 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004083 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004084 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004085 case Match_InvalidMemoryIndexed16SImm4:
4086 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004087 case Match_InvalidMemoryIndexed1SImm6:
4088 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004089 case Match_InvalidMemoryIndexedSImm8:
4090 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004091 case Match_InvalidMemoryIndexedSImm9:
4092 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004093 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004094 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004095 case Match_InvalidMemoryIndexed4SImm7:
4096 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4097 case Match_InvalidMemoryIndexed8SImm7:
4098 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4099 case Match_InvalidMemoryIndexed16SImm7:
4100 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004101 case Match_InvalidMemoryIndexed8UImm5:
4102 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4103 case Match_InvalidMemoryIndexed4UImm5:
4104 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4105 case Match_InvalidMemoryIndexed2UImm5:
4106 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004107 case Match_InvalidMemoryIndexed8UImm6:
4108 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
4109 case Match_InvalidMemoryIndexed4UImm6:
4110 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4111 case Match_InvalidMemoryIndexed2UImm6:
4112 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4113 case Match_InvalidMemoryIndexed1UImm6:
4114 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004115 case Match_InvalidMemoryWExtend8:
4116 return Error(Loc,
4117 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4118 case Match_InvalidMemoryWExtend16:
4119 return Error(Loc,
4120 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4121 case Match_InvalidMemoryWExtend32:
4122 return Error(Loc,
4123 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4124 case Match_InvalidMemoryWExtend64:
4125 return Error(Loc,
4126 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4127 case Match_InvalidMemoryWExtend128:
4128 return Error(Loc,
4129 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4130 case Match_InvalidMemoryXExtend8:
4131 return Error(Loc,
4132 "expected 'lsl' or 'sxtx' with optional shift of #0");
4133 case Match_InvalidMemoryXExtend16:
4134 return Error(Loc,
4135 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4136 case Match_InvalidMemoryXExtend32:
4137 return Error(Loc,
4138 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4139 case Match_InvalidMemoryXExtend64:
4140 return Error(Loc,
4141 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4142 case Match_InvalidMemoryXExtend128:
4143 return Error(Loc,
4144 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4145 case Match_InvalidMemoryIndexed1:
4146 return Error(Loc, "index must be an integer in range [0, 4095].");
4147 case Match_InvalidMemoryIndexed2:
4148 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4149 case Match_InvalidMemoryIndexed4:
4150 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4151 case Match_InvalidMemoryIndexed8:
4152 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4153 case Match_InvalidMemoryIndexed16:
4154 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004155 case Match_InvalidImm0_1:
4156 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004157 case Match_InvalidImm0_7:
4158 return Error(Loc, "immediate must be an integer in range [0, 7].");
4159 case Match_InvalidImm0_15:
4160 return Error(Loc, "immediate must be an integer in range [0, 15].");
4161 case Match_InvalidImm0_31:
4162 return Error(Loc, "immediate must be an integer in range [0, 31].");
4163 case Match_InvalidImm0_63:
4164 return Error(Loc, "immediate must be an integer in range [0, 63].");
4165 case Match_InvalidImm0_127:
4166 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004167 case Match_InvalidImm0_255:
4168 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004169 case Match_InvalidImm0_65535:
4170 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4171 case Match_InvalidImm1_8:
4172 return Error(Loc, "immediate must be an integer in range [1, 8].");
4173 case Match_InvalidImm1_16:
4174 return Error(Loc, "immediate must be an integer in range [1, 16].");
4175 case Match_InvalidImm1_32:
4176 return Error(Loc, "immediate must be an integer in range [1, 32].");
4177 case Match_InvalidImm1_64:
4178 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004179 case Match_InvalidSVEAddSubImm8:
4180 return Error(Loc, "immediate must be an integer in range [0, 255]"
4181 " with a shift amount of 0");
4182 case Match_InvalidSVEAddSubImm16:
4183 case Match_InvalidSVEAddSubImm32:
4184 case Match_InvalidSVEAddSubImm64:
4185 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4186 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004187 case Match_InvalidSVECpyImm8:
4188 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4189 " with a shift amount of 0");
4190 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004191 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4192 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004193 case Match_InvalidSVECpyImm32:
4194 case Match_InvalidSVECpyImm64:
4195 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4196 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004197 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004198 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004199 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004200 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004201 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004202 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004203 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004204 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004205 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004206 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004207 case Match_InvalidSVEIndexRange0_63:
4208 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4209 case Match_InvalidSVEIndexRange0_31:
4210 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4211 case Match_InvalidSVEIndexRange0_15:
4212 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4213 case Match_InvalidSVEIndexRange0_7:
4214 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4215 case Match_InvalidSVEIndexRange0_3:
4216 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004217 case Match_InvalidLabel:
4218 return Error(Loc, "expected label or encodable integer pc offset");
4219 case Match_MRS:
4220 return Error(Loc, "expected readable system register");
4221 case Match_MSR:
4222 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004223 case Match_InvalidComplexRotationEven:
4224 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4225 case Match_InvalidComplexRotationOdd:
4226 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004227 case Match_MnemonicFail: {
4228 std::string Suggestion = AArch64MnemonicSpellCheck(
4229 ((AArch64Operand &)*Operands[0]).getToken(),
4230 ComputeAvailableFeatures(STI->getFeatureBits()));
4231 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4232 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004233 case Match_InvalidGPR64shifted8:
4234 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4235 case Match_InvalidGPR64shifted16:
4236 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4237 case Match_InvalidGPR64shifted32:
4238 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4239 case Match_InvalidGPR64shifted64:
4240 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4241 case Match_InvalidGPR64NoXZRshifted8:
4242 return Error(Loc, "register must be x0..x30 without shift");
4243 case Match_InvalidGPR64NoXZRshifted16:
4244 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4245 case Match_InvalidGPR64NoXZRshifted32:
4246 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4247 case Match_InvalidGPR64NoXZRshifted64:
4248 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004249 case Match_InvalidZPR32UXTW8:
4250 case Match_InvalidZPR32SXTW8:
4251 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4252 case Match_InvalidZPR32UXTW16:
4253 case Match_InvalidZPR32SXTW16:
4254 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4255 case Match_InvalidZPR32UXTW32:
4256 case Match_InvalidZPR32SXTW32:
4257 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4258 case Match_InvalidZPR32UXTW64:
4259 case Match_InvalidZPR32SXTW64:
4260 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4261 case Match_InvalidZPR64UXTW8:
4262 case Match_InvalidZPR64SXTW8:
4263 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4264 case Match_InvalidZPR64UXTW16:
4265 case Match_InvalidZPR64SXTW16:
4266 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4267 case Match_InvalidZPR64UXTW32:
4268 case Match_InvalidZPR64SXTW32:
4269 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4270 case Match_InvalidZPR64UXTW64:
4271 case Match_InvalidZPR64SXTW64:
4272 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004273 case Match_InvalidZPR32LSL8:
4274 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4275 case Match_InvalidZPR32LSL16:
4276 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4277 case Match_InvalidZPR32LSL32:
4278 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4279 case Match_InvalidZPR32LSL64:
4280 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004281 case Match_InvalidZPR64LSL8:
4282 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4283 case Match_InvalidZPR64LSL16:
4284 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4285 case Match_InvalidZPR64LSL32:
4286 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4287 case Match_InvalidZPR64LSL64:
4288 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004289 case Match_InvalidZPR0:
4290 return Error(Loc, "expected register without element width sufix");
4291 case Match_InvalidZPR8:
4292 case Match_InvalidZPR16:
4293 case Match_InvalidZPR32:
4294 case Match_InvalidZPR64:
4295 case Match_InvalidZPR128:
4296 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004297 case Match_InvalidZPR_3b8:
4298 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4299 case Match_InvalidZPR_3b16:
4300 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4301 case Match_InvalidZPR_3b32:
4302 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4303 case Match_InvalidZPR_4b16:
4304 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4305 case Match_InvalidZPR_4b32:
4306 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4307 case Match_InvalidZPR_4b64:
4308 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004309 case Match_InvalidSVEPattern:
4310 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004311 case Match_InvalidSVEPredicateAnyReg:
4312 case Match_InvalidSVEPredicateBReg:
4313 case Match_InvalidSVEPredicateHReg:
4314 case Match_InvalidSVEPredicateSReg:
4315 case Match_InvalidSVEPredicateDReg:
4316 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004317 case Match_InvalidSVEPredicate3bAnyReg:
4318 case Match_InvalidSVEPredicate3bBReg:
4319 case Match_InvalidSVEPredicate3bHReg:
4320 case Match_InvalidSVEPredicate3bSReg:
4321 case Match_InvalidSVEPredicate3bDReg:
4322 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004323 case Match_InvalidSVEExactFPImmOperandHalfOne:
4324 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4325 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4326 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4327 case Match_InvalidSVEExactFPImmOperandZeroOne:
4328 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004329 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004330 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004331 }
4332}
4333
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004334static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004335
4336bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4337 OperandVector &Operands,
4338 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004339 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004340 bool MatchingInlineAsm) {
4341 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004342 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4343 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004344
David Blaikie960ea3f2014-06-08 16:18:35 +00004345 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004346 unsigned NumOperands = Operands.size();
4347
4348 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004349 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4350 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004351 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004352 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 if (Op3CE) {
4354 uint64_t Op3Val = Op3CE->getValue();
4355 uint64_t NewOp3Val = 0;
4356 uint64_t NewOp4Val = 0;
4357 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004358 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004359 NewOp3Val = (32 - Op3Val) & 0x1f;
4360 NewOp4Val = 31 - Op3Val;
4361 } else {
4362 NewOp3Val = (64 - Op3Val) & 0x3f;
4363 NewOp4Val = 63 - Op3Val;
4364 }
4365
Jim Grosbach13760bd2015-05-30 01:25:56 +00004366 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4367 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004368
4369 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004370 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004371 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004372 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4373 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4374 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004375 }
4376 }
Tim Northover03b99f62015-04-30 18:28:58 +00004377 } else if (NumOperands == 4 && Tok == "bfc") {
4378 // FIXME: Horrible hack to handle BFC->BFM alias.
4379 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4380 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4381 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4382
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004383 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004384 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4385 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4386
4387 if (LSBCE && WidthCE) {
4388 uint64_t LSB = LSBCE->getValue();
4389 uint64_t Width = WidthCE->getValue();
4390
4391 uint64_t RegWidth = 0;
4392 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4393 Op1.getReg()))
4394 RegWidth = 64;
4395 else
4396 RegWidth = 32;
4397
4398 if (LSB >= RegWidth)
4399 return Error(LSBOp.getStartLoc(),
4400 "expected integer in range [0, 31]");
4401 if (Width < 1 || Width > RegWidth)
4402 return Error(WidthOp.getStartLoc(),
4403 "expected integer in range [1, 32]");
4404
4405 uint64_t ImmR = 0;
4406 if (RegWidth == 32)
4407 ImmR = (32 - LSB) & 0x1f;
4408 else
4409 ImmR = (64 - LSB) & 0x3f;
4410
4411 uint64_t ImmS = Width - 1;
4412
4413 if (ImmR != 0 && ImmS >= ImmR)
4414 return Error(WidthOp.getStartLoc(),
4415 "requested insert overflows register");
4416
Jim Grosbach13760bd2015-05-30 01:25:56 +00004417 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4418 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004419 Operands[0] = AArch64Operand::CreateToken(
4420 "bfm", false, Op.getStartLoc(), getContext());
4421 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004422 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4423 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004424 Operands[3] = AArch64Operand::CreateImm(
4425 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4426 Operands.emplace_back(
4427 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4428 WidthOp.getEndLoc(), getContext()));
4429 }
4430 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004431 } else if (NumOperands == 5) {
4432 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4433 // UBFIZ -> UBFM aliases.
4434 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004435 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4436 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4437 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004438
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004439 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004440 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4441 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004442
4443 if (Op3CE && Op4CE) {
4444 uint64_t Op3Val = Op3CE->getValue();
4445 uint64_t Op4Val = Op4CE->getValue();
4446
4447 uint64_t RegWidth = 0;
4448 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004449 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004450 RegWidth = 64;
4451 else
4452 RegWidth = 32;
4453
4454 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004455 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004456 "expected integer in range [0, 31]");
4457 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004458 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004459 "expected integer in range [1, 32]");
4460
4461 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004462 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004463 NewOp3Val = (32 - Op3Val) & 0x1f;
4464 else
4465 NewOp3Val = (64 - Op3Val) & 0x3f;
4466
4467 uint64_t NewOp4Val = Op4Val - 1;
4468
4469 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004470 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004471 "requested insert overflows register");
4472
4473 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004474 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004475 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004476 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004477 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004478 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004479 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004480 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004481 if (Tok == "bfi")
4482 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004483 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004484 else if (Tok == "sbfiz")
4485 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004486 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004487 else if (Tok == "ubfiz")
4488 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004489 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004490 else
4491 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004492 }
4493 }
4494
4495 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4496 // UBFX -> UBFM aliases.
4497 } else if (NumOperands == 5 &&
4498 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004499 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4500 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4501 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004502
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004503 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004504 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4505 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004506
4507 if (Op3CE && Op4CE) {
4508 uint64_t Op3Val = Op3CE->getValue();
4509 uint64_t Op4Val = Op4CE->getValue();
4510
4511 uint64_t RegWidth = 0;
4512 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004513 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004514 RegWidth = 64;
4515 else
4516 RegWidth = 32;
4517
4518 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004519 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004520 "expected integer in range [0, 31]");
4521 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004522 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004523 "expected integer in range [1, 32]");
4524
4525 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4526
4527 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004528 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004529 "requested extract overflows register");
4530
4531 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004532 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004533 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004534 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004535 if (Tok == "bfxil")
4536 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004537 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004538 else if (Tok == "sbfx")
4539 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004540 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004541 else if (Tok == "ubfx")
4542 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004543 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004544 else
4545 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004546 }
4547 }
4548 }
4549 }
Tim Northover9097a072017-12-18 10:36:00 +00004550
4551 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4552 // instruction for FP registers correctly in some rare circumstances. Convert
4553 // it to a safe instruction and warn (because silently changing someone's
4554 // assembly is rude).
4555 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4556 NumOperands == 4 && Tok == "movi") {
4557 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4558 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4559 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4560 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4561 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4562 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4563 if (Suffix.lower() == ".2d" &&
4564 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4565 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4566 " correctly on this CPU, converting to equivalent movi.16b");
4567 // Switch the suffix to .16b.
4568 unsigned Idx = Op1.isToken() ? 1 : 2;
4569 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4570 getContext());
4571 }
4572 }
4573 }
4574
Tim Northover3b0846e2014-05-24 12:50:23 +00004575 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4576 // InstAlias can't quite handle this since the reg classes aren't
4577 // subclasses.
4578 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4579 // The source register can be Wn here, but the matcher expects a
4580 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004581 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004582 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004583 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004584 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4585 Op.getStartLoc(), Op.getEndLoc(),
4586 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004587 }
4588 }
4589 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4590 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004591 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004592 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004593 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004594 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004595 // The source register can be Wn here, but the matcher expects a
4596 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004597 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004598 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004599 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004600 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4601 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004602 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004603 }
4604 }
4605 }
4606 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4607 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004608 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004609 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004610 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004611 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004612 // The source register can be Wn here, but the matcher expects a
4613 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004614 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004615 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004616 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004617 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4618 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004619 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004620 }
4621 }
4622 }
4623
Tim Northover3b0846e2014-05-24 12:50:23 +00004624 MCInst Inst;
4625 // First try to match against the secondary set of tables containing the
4626 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4627 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004628 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004629
4630 // If that fails, try against the alternate table containing long-form NEON:
4631 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004632 if (MatchResult != Match_Success) {
4633 // But first, save the short-form match result: we can use it in case the
4634 // long-form match also fails.
4635 auto ShortFormNEONErrorInfo = ErrorInfo;
4636 auto ShortFormNEONMatchResult = MatchResult;
4637
Tim Northover3b0846e2014-05-24 12:50:23 +00004638 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004639 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004640
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004641 // Now, both matches failed, and the long-form match failed on the mnemonic
4642 // suffix token operand. The short-form match failure is probably more
4643 // relevant: use it instead.
4644 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004645 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004646 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4647 MatchResult = ShortFormNEONMatchResult;
4648 ErrorInfo = ShortFormNEONErrorInfo;
4649 }
4650 }
4651
Tim Northover3b0846e2014-05-24 12:50:23 +00004652 switch (MatchResult) {
4653 case Match_Success: {
4654 // Perform range checking and other semantic validations
4655 SmallVector<SMLoc, 8> OperandLocs;
4656 NumOperands = Operands.size();
4657 for (unsigned i = 1; i < NumOperands; ++i)
4658 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004659 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004660 return true;
4661
4662 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004663 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004664 return false;
4665 }
4666 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004667 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004668 // Special case the error message for the very common case where only
4669 // a single subtarget feature is missing (neon, e.g.).
4670 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004671 uint64_t Mask = 1;
4672 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4673 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004674 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004675 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004676 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004677 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004678 }
4679 return Error(IDLoc, Msg);
4680 }
4681 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004682 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004683 case Match_InvalidOperand: {
4684 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004685
Tim Northover26bb14e2014-08-18 11:49:42 +00004686 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004687 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004688 return Error(IDLoc, "too few operands for instruction",
4689 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004690
David Blaikie960ea3f2014-06-08 16:18:35 +00004691 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004692 if (ErrorLoc == SMLoc())
4693 ErrorLoc = IDLoc;
4694 }
4695 // If the match failed on a suffix token operand, tweak the diagnostic
4696 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004697 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4698 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004699 MatchResult = Match_InvalidSuffix;
4700
Sander de Smalen0325e302018-07-02 07:34:52 +00004701 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004702 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004703 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004704 case Match_InvalidMemoryIndexed1:
4705 case Match_InvalidMemoryIndexed2:
4706 case Match_InvalidMemoryIndexed4:
4707 case Match_InvalidMemoryIndexed8:
4708 case Match_InvalidMemoryIndexed16:
4709 case Match_InvalidCondCode:
4710 case Match_AddSubRegExtendSmall:
4711 case Match_AddSubRegExtendLarge:
4712 case Match_AddSubSecondSource:
4713 case Match_LogicalSecondSource:
4714 case Match_AddSubRegShift32:
4715 case Match_AddSubRegShift64:
4716 case Match_InvalidMovImm32Shift:
4717 case Match_InvalidMovImm64Shift:
4718 case Match_InvalidFPImm:
4719 case Match_InvalidMemoryWExtend8:
4720 case Match_InvalidMemoryWExtend16:
4721 case Match_InvalidMemoryWExtend32:
4722 case Match_InvalidMemoryWExtend64:
4723 case Match_InvalidMemoryWExtend128:
4724 case Match_InvalidMemoryXExtend8:
4725 case Match_InvalidMemoryXExtend16:
4726 case Match_InvalidMemoryXExtend32:
4727 case Match_InvalidMemoryXExtend64:
4728 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004729 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004730 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004731 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004732 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004733 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004734 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004735 case Match_InvalidMemoryIndexed4SImm7:
4736 case Match_InvalidMemoryIndexed8SImm7:
4737 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004738 case Match_InvalidMemoryIndexed8UImm5:
4739 case Match_InvalidMemoryIndexed4UImm5:
4740 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004741 case Match_InvalidMemoryIndexed1UImm6:
4742 case Match_InvalidMemoryIndexed2UImm6:
4743 case Match_InvalidMemoryIndexed4UImm6:
4744 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004745 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004746 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004747 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004748 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004749 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004750 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004751 case Match_InvalidImm0_7:
4752 case Match_InvalidImm0_15:
4753 case Match_InvalidImm0_31:
4754 case Match_InvalidImm0_63:
4755 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004756 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004757 case Match_InvalidImm0_65535:
4758 case Match_InvalidImm1_8:
4759 case Match_InvalidImm1_16:
4760 case Match_InvalidImm1_32:
4761 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004762 case Match_InvalidSVEAddSubImm8:
4763 case Match_InvalidSVEAddSubImm16:
4764 case Match_InvalidSVEAddSubImm32:
4765 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004766 case Match_InvalidSVECpyImm8:
4767 case Match_InvalidSVECpyImm16:
4768 case Match_InvalidSVECpyImm32:
4769 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004770 case Match_InvalidIndexRange1_1:
4771 case Match_InvalidIndexRange0_15:
4772 case Match_InvalidIndexRange0_7:
4773 case Match_InvalidIndexRange0_3:
4774 case Match_InvalidIndexRange0_1:
4775 case Match_InvalidSVEIndexRange0_63:
4776 case Match_InvalidSVEIndexRange0_31:
4777 case Match_InvalidSVEIndexRange0_15:
4778 case Match_InvalidSVEIndexRange0_7:
4779 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004780 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004781 case Match_InvalidComplexRotationEven:
4782 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004783 case Match_InvalidGPR64shifted8:
4784 case Match_InvalidGPR64shifted16:
4785 case Match_InvalidGPR64shifted32:
4786 case Match_InvalidGPR64shifted64:
4787 case Match_InvalidGPR64NoXZRshifted8:
4788 case Match_InvalidGPR64NoXZRshifted16:
4789 case Match_InvalidGPR64NoXZRshifted32:
4790 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004791 case Match_InvalidZPR32UXTW8:
4792 case Match_InvalidZPR32UXTW16:
4793 case Match_InvalidZPR32UXTW32:
4794 case Match_InvalidZPR32UXTW64:
4795 case Match_InvalidZPR32SXTW8:
4796 case Match_InvalidZPR32SXTW16:
4797 case Match_InvalidZPR32SXTW32:
4798 case Match_InvalidZPR32SXTW64:
4799 case Match_InvalidZPR64UXTW8:
4800 case Match_InvalidZPR64SXTW8:
4801 case Match_InvalidZPR64UXTW16:
4802 case Match_InvalidZPR64SXTW16:
4803 case Match_InvalidZPR64UXTW32:
4804 case Match_InvalidZPR64SXTW32:
4805 case Match_InvalidZPR64UXTW64:
4806 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004807 case Match_InvalidZPR32LSL8:
4808 case Match_InvalidZPR32LSL16:
4809 case Match_InvalidZPR32LSL32:
4810 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004811 case Match_InvalidZPR64LSL8:
4812 case Match_InvalidZPR64LSL16:
4813 case Match_InvalidZPR64LSL32:
4814 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004815 case Match_InvalidZPR0:
4816 case Match_InvalidZPR8:
4817 case Match_InvalidZPR16:
4818 case Match_InvalidZPR32:
4819 case Match_InvalidZPR64:
4820 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004821 case Match_InvalidZPR_3b8:
4822 case Match_InvalidZPR_3b16:
4823 case Match_InvalidZPR_3b32:
4824 case Match_InvalidZPR_4b16:
4825 case Match_InvalidZPR_4b32:
4826 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004827 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004828 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004829 case Match_InvalidSVEPredicateBReg:
4830 case Match_InvalidSVEPredicateHReg:
4831 case Match_InvalidSVEPredicateSReg:
4832 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004833 case Match_InvalidSVEPredicate3bAnyReg:
4834 case Match_InvalidSVEPredicate3bBReg:
4835 case Match_InvalidSVEPredicate3bHReg:
4836 case Match_InvalidSVEPredicate3bSReg:
4837 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004838 case Match_InvalidSVEExactFPImmOperandHalfOne:
4839 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4840 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004841 case Match_MSR:
4842 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004843 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004844 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004845 // Any time we get here, there's nothing fancy to do. Just get the
4846 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004847 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004848 if (ErrorLoc == SMLoc())
4849 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004850 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004851 }
4852 }
4853
4854 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004855}
4856
4857/// ParseDirective parses the arm specific directives
4858bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004859 const MCObjectFileInfo::Environment Format =
4860 getContext().getObjectFileInfo()->getObjectFileType();
4861 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
4862 bool IsCOFF = Format == MCObjectFileInfo::IsCOFF;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004863
Tim Northover3b0846e2014-05-24 12:50:23 +00004864 StringRef IDVal = DirectiveID.getIdentifier();
4865 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004866 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004867 parseDirectiveArch(Loc);
4868 else if (IDVal == ".cpu")
4869 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004870 else if (IDVal == ".tlsdesccall")
4871 parseDirectiveTLSDescCall(Loc);
4872 else if (IDVal == ".ltorg" || IDVal == ".pool")
4873 parseDirectiveLtorg(Loc);
4874 else if (IDVal == ".unreq")
4875 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00004876 else if (IDVal == ".inst")
4877 parseDirectiveInst(Loc);
4878 else if (!IsMachO && !IsCOFF)
4879 return true;
4880 else if (IDVal == MCLOHDirectiveName())
Nirav Davee833c6c2016-11-08 18:31:04 +00004881 parseDirectiveLOH(IDVal, Loc);
4882 else
4883 return true;
4884 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004885}
4886
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004887static const struct {
4888 const char *Name;
4889 const FeatureBitset Features;
4890} ExtensionMap[] = {
Sjoerd Meijerdc198342018-07-26 07:13:59 +00004891 { "crc", {AArch64::FeatureCRC} },
4892 { "sm4", {AArch64::FeatureSM4} },
4893 { "sha3", {AArch64::FeatureSHA3} },
4894 { "sha2", {AArch64::FeatureSHA2} },
4895 { "aes", {AArch64::FeatureAES} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004896 { "crypto", {AArch64::FeatureCrypto} },
4897 { "fp", {AArch64::FeatureFPARMv8} },
4898 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004899 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004900 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004901
4902 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004903 { "pan", {} },
4904 { "lor", {} },
4905 { "rdma", {} },
4906 { "profile", {} },
4907};
4908
Sjoerd Meijerdc198342018-07-26 07:13:59 +00004909static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
4910 SmallVector<StringRef, 4> &RequestedExtensions) {
4911 const bool NoCrypto =
4912 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
4913 "nocrypto") != std::end(RequestedExtensions));
4914 const bool Crypto =
4915 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
4916 "crypto") != std::end(RequestedExtensions));
4917
4918 if (!NoCrypto && Crypto) {
4919 switch (ArchKind) {
4920 default:
4921 // Map 'generic' (and others) to sha2 and aes, because
4922 // that was the traditional meaning of crypto.
4923 case AArch64::ArchKind::ARMV8_1A:
4924 case AArch64::ArchKind::ARMV8_2A:
4925 case AArch64::ArchKind::ARMV8_3A:
4926 RequestedExtensions.push_back("sha2");
4927 RequestedExtensions.push_back("aes");
4928 break;
4929 case AArch64::ArchKind::ARMV8_4A:
4930 RequestedExtensions.push_back("sm4");
4931 RequestedExtensions.push_back("sha3");
4932 RequestedExtensions.push_back("sha2");
4933 RequestedExtensions.push_back("aes");
4934 break;
4935 }
4936 } else if (NoCrypto) {
4937 switch (ArchKind) {
4938 default:
4939 // Map 'generic' (and others) to sha2 and aes, because
4940 // that was the traditional meaning of crypto.
4941 case AArch64::ArchKind::ARMV8_1A:
4942 case AArch64::ArchKind::ARMV8_2A:
4943 case AArch64::ArchKind::ARMV8_3A:
4944 RequestedExtensions.push_back("nosha2");
4945 RequestedExtensions.push_back("noaes");
4946 break;
4947 case AArch64::ArchKind::ARMV8_4A:
4948 RequestedExtensions.push_back("nosm4");
4949 RequestedExtensions.push_back("nosha3");
4950 RequestedExtensions.push_back("nosha2");
4951 RequestedExtensions.push_back("noaes");
4952 break;
4953 }
4954 }
4955}
4956
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004957/// parseDirectiveArch
4958/// ::= .arch token
4959bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4960 SMLoc ArchLoc = getLoc();
4961
4962 StringRef Arch, ExtensionString;
4963 std::tie(Arch, ExtensionString) =
4964 getParser().parseStringToEndOfStatement().trim().split('+');
4965
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004966 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4967 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004968 return Error(ArchLoc, "unknown arch name");
4969
4970 if (parseToken(AsmToken::EndOfStatement))
4971 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004972
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004973 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004974 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004975 AArch64::getArchFeatures(ID, AArch64Features);
4976 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4977 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004978
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004979 MCSubtargetInfo &STI = copySTI();
4980 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4981 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4982
4983 SmallVector<StringRef, 4> RequestedExtensions;
4984 if (!ExtensionString.empty())
4985 ExtensionString.split(RequestedExtensions, '+');
4986
Sjoerd Meijerdc198342018-07-26 07:13:59 +00004987 ExpandCryptoAEK(ID, RequestedExtensions);
4988
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004989 FeatureBitset Features = STI.getFeatureBits();
4990 for (auto Name : RequestedExtensions) {
4991 bool EnableFeature = true;
4992
4993 if (Name.startswith_lower("no")) {
4994 EnableFeature = false;
4995 Name = Name.substr(2);
4996 }
4997
4998 for (const auto &Extension : ExtensionMap) {
4999 if (Extension.Name != Name)
5000 continue;
5001
5002 if (Extension.Features.none())
5003 report_fatal_error("unsupported architectural extension: " + Name);
5004
5005 FeatureBitset ToggleFeatures = EnableFeature
5006 ? (~Features & Extension.Features)
5007 : ( Features & Extension.Features);
5008 uint64_t Features =
5009 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5010 setAvailableFeatures(Features);
5011 break;
5012 }
5013 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005014 return false;
5015}
5016
Tim Northover8b96c7e2017-05-15 19:42:15 +00005017static SMLoc incrementLoc(SMLoc L, int Offset) {
5018 return SMLoc::getFromPointer(L.getPointer() + Offset);
5019}
5020
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005021/// parseDirectiveCPU
5022/// ::= .cpu id
5023bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005024 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005025
5026 StringRef CPU, ExtensionString;
5027 std::tie(CPU, ExtensionString) =
5028 getParser().parseStringToEndOfStatement().trim().split('+');
5029
Nirav Davee833c6c2016-11-08 18:31:04 +00005030 if (parseToken(AsmToken::EndOfStatement))
5031 return true;
5032
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005033 SmallVector<StringRef, 4> RequestedExtensions;
5034 if (!ExtensionString.empty())
5035 ExtensionString.split(RequestedExtensions, '+');
5036
5037 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5038 // once that is tablegen'ed
5039 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005040 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005041 return false;
5042 }
5043
5044 MCSubtargetInfo &STI = copySTI();
5045 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005046 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005047
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005048 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5049
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005050 FeatureBitset Features = STI.getFeatureBits();
5051 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005052 // Advance source location past '+'.
5053 CurLoc = incrementLoc(CurLoc, 1);
5054
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005055 bool EnableFeature = true;
5056
5057 if (Name.startswith_lower("no")) {
5058 EnableFeature = false;
5059 Name = Name.substr(2);
5060 }
5061
Tim Northover8b96c7e2017-05-15 19:42:15 +00005062 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005063 for (const auto &Extension : ExtensionMap) {
5064 if (Extension.Name != Name)
5065 continue;
5066
5067 if (Extension.Features.none())
5068 report_fatal_error("unsupported architectural extension: " + Name);
5069
5070 FeatureBitset ToggleFeatures = EnableFeature
5071 ? (~Features & Extension.Features)
5072 : ( Features & Extension.Features);
5073 uint64_t Features =
5074 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5075 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005076 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005077
5078 break;
5079 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005080
5081 if (!FoundExtension)
5082 Error(CurLoc, "unsupported architectural extension");
5083
5084 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005085 }
5086 return false;
5087}
5088
Chad Rosierdcd2a302014-10-22 20:35:57 +00005089/// parseDirectiveInst
5090/// ::= .inst opcode [, ...]
5091bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005092 if (getLexer().is(AsmToken::EndOfStatement))
5093 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005094
Nirav Davee833c6c2016-11-08 18:31:04 +00005095 auto parseOp = [&]() -> bool {
5096 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005097 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005098 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5099 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005100 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005101 if (check(!Value, L, "expected constant expression"))
5102 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005103 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005104 return false;
5105 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005106
Nirav Davee833c6c2016-11-08 18:31:04 +00005107 if (parseMany(parseOp))
5108 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005109 return false;
5110}
5111
Tim Northover3b0846e2014-05-24 12:50:23 +00005112// parseDirectiveTLSDescCall:
5113// ::= .tlsdesccall symbol
5114bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5115 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005116 if (check(getParser().parseIdentifier(Name), L,
5117 "expected symbol after directive") ||
5118 parseToken(AsmToken::EndOfStatement))
5119 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005120
Jim Grosbach6f482002015-05-18 18:43:14 +00005121 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005122 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5123 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005124
5125 MCInst Inst;
5126 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005127 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005128
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005129 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005130 return false;
5131}
5132
5133/// ::= .loh <lohName | lohId> label1, ..., labelN
5134/// The number of arguments depends on the loh identifier.
5135bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005136 MCLOHType Kind;
5137 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5138 if (getParser().getTok().isNot(AsmToken::Integer))
5139 return TokError("expected an identifier or a number in directive");
5140 // We successfully get a numeric value for the identifier.
5141 // Check if it is valid.
5142 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005143 if (Id <= -1U && !isValidMCLOHType(Id))
5144 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005145 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005146 } else {
5147 StringRef Name = getTok().getIdentifier();
5148 // We successfully parse an identifier.
5149 // Check if it is a recognized one.
5150 int Id = MCLOHNameToId(Name);
5151
5152 if (Id == -1)
5153 return TokError("invalid identifier in directive");
5154 Kind = (MCLOHType)Id;
5155 }
5156 // Consume the identifier.
5157 Lex();
5158 // Get the number of arguments of this LOH.
5159 int NbArgs = MCLOHIdToNbArgs(Kind);
5160
5161 assert(NbArgs != -1 && "Invalid number of arguments");
5162
5163 SmallVector<MCSymbol *, 3> Args;
5164 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5165 StringRef Name;
5166 if (getParser().parseIdentifier(Name))
5167 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005168 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005169
5170 if (Idx + 1 == NbArgs)
5171 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005172 if (parseToken(AsmToken::Comma,
5173 "unexpected token in '" + Twine(IDVal) + "' directive"))
5174 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005175 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005176 if (parseToken(AsmToken::EndOfStatement,
5177 "unexpected token in '" + Twine(IDVal) + "' directive"))
5178 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005179
5180 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5181 return false;
5182}
5183
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005184/// parseDirectiveLtorg
5185/// ::= .ltorg | .pool
5186bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005187 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5188 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005189 getTargetStreamer().emitCurrentConstantPool();
5190 return false;
5191}
5192
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005193/// parseDirectiveReq
5194/// ::= name .req registername
5195bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005196 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005197 Parser.Lex(); // Eat the '.req' token.
5198 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005199 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005200 unsigned RegNum;
5201 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005202
Sander de Smalen50d87022018-04-19 07:35:08 +00005203 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005204 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005205 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005206 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005207
Sander de Smalen50d87022018-04-19 07:35:08 +00005208 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005209 return true;
5210
Sander de Smalen50d87022018-04-19 07:35:08 +00005211 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005212 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005213 }
5214
Sander de Smalen50d87022018-04-19 07:35:08 +00005215 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005216 StringRef Kind;
5217 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005218 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005219 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005220
Sander de Smalen50d87022018-04-19 07:35:08 +00005221 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005222 return true;
5223
Sander de Smalen50d87022018-04-19 07:35:08 +00005224 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005225 return Error(SRegLoc,
5226 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005227 }
5228
Sander de Smalen50d87022018-04-19 07:35:08 +00005229 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005230 StringRef Kind;
5231 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005232 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005233
Sander de Smalen50d87022018-04-19 07:35:08 +00005234 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005235 return true;
5236
Sander de Smalen50d87022018-04-19 07:35:08 +00005237 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005238 return Error(SRegLoc,
5239 "sve predicate register without type specifier expected");
5240 }
5241
Sander de Smalen50d87022018-04-19 07:35:08 +00005242 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005243 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005244
5245 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005246 if (parseToken(AsmToken::EndOfStatement,
5247 "unexpected input in .req directive"))
5248 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005249
Sander de Smalen8e607342017-11-15 15:44:43 +00005250 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005251 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005252 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5253
Nirav Dave2364748a2016-09-16 18:30:20 +00005254 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005255}
5256
5257/// parseDirectiveUneq
5258/// ::= .unreq registername
5259bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005260 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005261 if (getTok().isNot(AsmToken::Identifier))
5262 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005263 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5264 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005265 if (parseToken(AsmToken::EndOfStatement))
5266 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005267 return false;
5268}
5269
Tim Northover3b0846e2014-05-24 12:50:23 +00005270bool
5271AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5272 AArch64MCExpr::VariantKind &ELFRefKind,
5273 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5274 int64_t &Addend) {
5275 ELFRefKind = AArch64MCExpr::VK_INVALID;
5276 DarwinRefKind = MCSymbolRefExpr::VK_None;
5277 Addend = 0;
5278
5279 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5280 ELFRefKind = AE->getKind();
5281 Expr = AE->getSubExpr();
5282 }
5283
5284 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5285 if (SE) {
5286 // It's a simple symbol reference with no addend.
5287 DarwinRefKind = SE->getKind();
5288 return true;
5289 }
5290
5291 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5292 if (!BE)
5293 return false;
5294
5295 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
5296 if (!SE)
5297 return false;
5298 DarwinRefKind = SE->getKind();
5299
5300 if (BE->getOpcode() != MCBinaryExpr::Add &&
5301 BE->getOpcode() != MCBinaryExpr::Sub)
5302 return false;
5303
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00005304 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00005305 // on here than we can deal with.
5306 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
5307 if (!AddendExpr)
5308 return false;
5309
5310 Addend = AddendExpr->getValue();
5311 if (BE->getOpcode() == MCBinaryExpr::Sub)
5312 Addend = -Addend;
5313
5314 // It's some symbol reference + a constant addend, but really
5315 // shouldn't use both Darwin and ELF syntax.
5316 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5317 DarwinRefKind == MCSymbolRefExpr::VK_None;
5318}
5319
5320/// Force static initialization.
5321extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005322 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5323 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5324 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005325}
5326
5327#define GET_REGISTER_MATCHER
5328#define GET_SUBTARGET_FEATURE_NAME
5329#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005330#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005331#include "AArch64GenAsmMatcher.inc"
5332
5333// Define this matcher function after the auto-generated include so we
5334// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005335unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005336 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005337 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005338 // If the kind is a token for a literal immediate, check if our asm
5339 // operand matches. This is for InstAliases which have a fixed-value
5340 // immediate in the syntax.
5341 int64_t ExpectedVal;
5342 switch (Kind) {
5343 default:
5344 return Match_InvalidOperand;
5345 case MCK__35_0:
5346 ExpectedVal = 0;
5347 break;
5348 case MCK__35_1:
5349 ExpectedVal = 1;
5350 break;
5351 case MCK__35_12:
5352 ExpectedVal = 12;
5353 break;
5354 case MCK__35_16:
5355 ExpectedVal = 16;
5356 break;
5357 case MCK__35_2:
5358 ExpectedVal = 2;
5359 break;
5360 case MCK__35_24:
5361 ExpectedVal = 24;
5362 break;
5363 case MCK__35_3:
5364 ExpectedVal = 3;
5365 break;
5366 case MCK__35_32:
5367 ExpectedVal = 32;
5368 break;
5369 case MCK__35_4:
5370 ExpectedVal = 4;
5371 break;
5372 case MCK__35_48:
5373 ExpectedVal = 48;
5374 break;
5375 case MCK__35_6:
5376 ExpectedVal = 6;
5377 break;
5378 case MCK__35_64:
5379 ExpectedVal = 64;
5380 break;
5381 case MCK__35_8:
5382 ExpectedVal = 8;
5383 break;
5384 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005385 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005386 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005387 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005388 if (!CE)
5389 return Match_InvalidOperand;
5390 if (CE->getValue() == ExpectedVal)
5391 return Match_Success;
5392 return Match_InvalidOperand;
5393}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005394
Alex Bradbury58eba092016-11-01 16:32:05 +00005395OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005396AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5397
5398 SMLoc S = getLoc();
5399
5400 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5401 Error(S, "expected register");
5402 return MatchOperand_ParseFail;
5403 }
5404
Sander de Smalen50d87022018-04-19 07:35:08 +00005405 unsigned FirstReg;
5406 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5407 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005408 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005409
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005410 const MCRegisterClass &WRegClass =
5411 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5412 const MCRegisterClass &XRegClass =
5413 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5414
5415 bool isXReg = XRegClass.contains(FirstReg),
5416 isWReg = WRegClass.contains(FirstReg);
5417 if (!isXReg && !isWReg) {
5418 Error(S, "expected first even register of a "
5419 "consecutive same-size even/odd register pair");
5420 return MatchOperand_ParseFail;
5421 }
5422
5423 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5424 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5425
5426 if (FirstEncoding & 0x1) {
5427 Error(S, "expected first even register of a "
5428 "consecutive same-size even/odd register pair");
5429 return MatchOperand_ParseFail;
5430 }
5431
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005432 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005433 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005434 return MatchOperand_ParseFail;
5435 }
5436 // Eat the comma
5437 getParser().Lex();
5438
5439 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005440 unsigned SecondReg;
5441 Res = tryParseScalarRegister(SecondReg);
5442 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005443 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005444
Eugene Zelenko049b0172017-01-06 00:30:53 +00005445 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005446 (isXReg && !XRegClass.contains(SecondReg)) ||
5447 (isWReg && !WRegClass.contains(SecondReg))) {
5448 Error(E,"expected second odd register of a "
5449 "consecutive same-size even/odd register pair");
5450 return MatchOperand_ParseFail;
5451 }
Joel Jones504bf332016-10-24 13:37:13 +00005452
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005453 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005454 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005455 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5456 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5457 } else {
5458 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5459 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5460 }
5461
Florian Hahnc4422242017-11-07 13:07:50 +00005462 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5463 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005464
5465 return MatchOperand_Success;
5466}
Florian Hahn91f11e52017-11-07 16:45:48 +00005467
Sander de Smaleneb896b12018-04-25 09:26:47 +00005468template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005469OperandMatchResultTy
5470AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005471 const SMLoc S = getLoc();
5472 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005473 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005474 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005475
Sander de Smalen8e607342017-11-15 15:44:43 +00005476 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005477 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005478
5479 if (Res != MatchOperand_Success)
5480 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005481
5482 if (ParseSuffix && Kind.empty())
5483 return MatchOperand_NoMatch;
5484
Sander de Smalen73937b72018-04-11 07:36:10 +00005485 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5486 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005487 return MatchOperand_NoMatch;
5488
Sander de Smalen73937b72018-04-11 07:36:10 +00005489 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005490
5491 // No shift/extend is the default.
5492 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5493 Operands.push_back(AArch64Operand::CreateVectorReg(
5494 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5495
Sander de Smalenc33d6682018-06-04 06:40:55 +00005496 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5497 if (Res == MatchOperand_ParseFail)
5498 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005499 return MatchOperand_Success;
5500 }
5501
5502 // Eat the comma
5503 getParser().Lex();
5504
5505 // Match the shift
5506 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5507 Res = tryParseOptionalShiftExtend(ExtOpnd);
5508 if (Res != MatchOperand_Success)
5509 return Res;
5510
5511 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005512 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005513 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5514 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5515 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005516
5517 return MatchOperand_Success;
5518}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005519
5520OperandMatchResultTy
5521AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5522 MCAsmParser &Parser = getParser();
5523
5524 SMLoc SS = getLoc();
5525 const AsmToken &TokE = Parser.getTok();
5526 bool IsHash = TokE.is(AsmToken::Hash);
5527
5528 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5529 return MatchOperand_NoMatch;
5530
5531 int64_t Pattern;
5532 if (IsHash) {
5533 Parser.Lex(); // Eat hash
5534
5535 // Parse the immediate operand.
5536 const MCExpr *ImmVal;
5537 SS = getLoc();
5538 if (Parser.parseExpression(ImmVal))
5539 return MatchOperand_ParseFail;
5540
5541 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5542 if (!MCE)
5543 return MatchOperand_ParseFail;
5544
5545 Pattern = MCE->getValue();
5546 } else {
5547 // Parse the pattern
5548 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5549 if (!Pat)
5550 return MatchOperand_NoMatch;
5551
5552 Parser.Lex();
5553 Pattern = Pat->Encoding;
5554 assert(Pattern >= 0 && Pattern < 32);
5555 }
5556
5557 Operands.push_back(
5558 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5559 SS, getLoc(), getContext()));
5560
5561 return MatchOperand_Success;
5562}