blob: e18498c8a4d50ee896badb003577fb5c040112fb [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
David Green9dd1d452018-08-22 11:31:39 +00002456 // Leave anything with a bracket to the default for SVE
2457 if (getParser().getTok().is(AsmToken::LBrac))
2458 return MatchOperand_NoMatch;
2459
2460 if (getParser().getTok().is(AsmToken::Hash))
2461 getParser().Lex(); // Eat hash token.
2462
2463 if (parseSymbolicImmVal(Expr))
2464 return MatchOperand_ParseFail;
2465
2466 AArch64MCExpr::VariantKind ELFRefKind;
2467 MCSymbolRefExpr::VariantKind DarwinRefKind;
2468 int64_t Addend;
2469 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2470 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2471 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2472 // No modifier was specified at all; this is the syntax for an ELF basic
2473 // ADR relocation (unfortunately).
2474 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2475 } else {
2476 Error(S, "unexpected adr label");
Sander de Smalenc69944c2018-07-09 09:58:24 +00002477 return MatchOperand_ParseFail;
David Green9dd1d452018-08-22 11:31:39 +00002478 }
Sander de Smalenc69944c2018-07-09 09:58:24 +00002479 }
David Green9dd1d452018-08-22 11:31:39 +00002480
2481 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2482 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2483 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002484}
2485
2486/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002487template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002488OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002489AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002490 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002491 SMLoc S = getLoc();
2492
Nirav Davee833c6c2016-11-08 18:31:04 +00002493 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002494
2495 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002496 bool isNegative = parseOptionalToken(AsmToken::Minus);
2497
Tim Northover3b0846e2014-05-24 12:50:23 +00002498 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002499 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2500 if (!Hash)
2501 return MatchOperand_NoMatch;
2502 TokError("invalid floating point immediate");
2503 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002504 }
2505
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002506 // Parse hexadecimal representation.
2507 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2508 if (Tok.getIntVal() > 255 || isNegative) {
2509 TokError("encoded floating point value out of range");
2510 return MatchOperand_ParseFail;
2511 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002512
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002513 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2514 Operands.push_back(
2515 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2516 } else {
2517 // Parse FP representation.
2518 APFloat RealVal(APFloat::IEEEdouble());
2519 auto Status =
2520 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2521 if (isNegative)
2522 RealVal.changeSign();
2523
2524 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2525 Operands.push_back(
2526 AArch64Operand::CreateToken("#0", false, S, getContext()));
2527 Operands.push_back(
2528 AArch64Operand::CreateToken(".0", false, S, getContext()));
2529 } else
2530 Operands.push_back(AArch64Operand::CreateFPImm(
2531 RealVal, Status == APFloat::opOK, S, getContext()));
2532 }
2533
2534 Parser.Lex(); // Eat the token.
2535
2536 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002537}
2538
Sander de Smalen62770792018-05-25 09:47:52 +00002539/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2540/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002541OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002542AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002543 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002544 SMLoc S = getLoc();
2545
2546 if (Parser.getTok().is(AsmToken::Hash))
2547 Parser.Lex(); // Eat '#'
2548 else if (Parser.getTok().isNot(AsmToken::Integer))
2549 // Operand should start from # or should be integer, emit error otherwise.
2550 return MatchOperand_NoMatch;
2551
2552 const MCExpr *Imm;
2553 if (parseSymbolicImmVal(Imm))
2554 return MatchOperand_ParseFail;
2555 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002556 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002557 Operands.push_back(
2558 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002559 return MatchOperand_Success;
2560 }
2561
2562 // Eat ','
2563 Parser.Lex();
2564
2565 // The optional operand must be "lsl #N" where N is non-negative.
2566 if (!Parser.getTok().is(AsmToken::Identifier) ||
2567 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2568 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2569 return MatchOperand_ParseFail;
2570 }
2571
2572 // Eat 'lsl'
2573 Parser.Lex();
2574
Nirav Davee833c6c2016-11-08 18:31:04 +00002575 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002576
2577 if (Parser.getTok().isNot(AsmToken::Integer)) {
2578 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2579 return MatchOperand_ParseFail;
2580 }
2581
2582 int64_t ShiftAmount = Parser.getTok().getIntVal();
2583
2584 if (ShiftAmount < 0) {
2585 Error(Parser.getTok().getLoc(), "positive shift amount required");
2586 return MatchOperand_ParseFail;
2587 }
2588 Parser.Lex(); // Eat the number
2589
Sander de Smalen62770792018-05-25 09:47:52 +00002590 // Just in case the optional lsl #0 is used for immediates other than zero.
2591 if (ShiftAmount == 0 && Imm != 0) {
2592 SMLoc E = Parser.getTok().getLoc();
2593 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2594 return MatchOperand_Success;
2595 }
2596
Tim Northover3b0846e2014-05-24 12:50:23 +00002597 SMLoc E = Parser.getTok().getLoc();
2598 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2599 S, E, getContext()));
2600 return MatchOperand_Success;
2601}
2602
2603/// parseCondCodeString - Parse a Condition Code string.
2604AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2605 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2606 .Case("eq", AArch64CC::EQ)
2607 .Case("ne", AArch64CC::NE)
2608 .Case("cs", AArch64CC::HS)
2609 .Case("hs", AArch64CC::HS)
2610 .Case("cc", AArch64CC::LO)
2611 .Case("lo", AArch64CC::LO)
2612 .Case("mi", AArch64CC::MI)
2613 .Case("pl", AArch64CC::PL)
2614 .Case("vs", AArch64CC::VS)
2615 .Case("vc", AArch64CC::VC)
2616 .Case("hi", AArch64CC::HI)
2617 .Case("ls", AArch64CC::LS)
2618 .Case("ge", AArch64CC::GE)
2619 .Case("lt", AArch64CC::LT)
2620 .Case("gt", AArch64CC::GT)
2621 .Case("le", AArch64CC::LE)
2622 .Case("al", AArch64CC::AL)
2623 .Case("nv", AArch64CC::NV)
2624 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002625
2626 if (CC == AArch64CC::Invalid &&
2627 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2628 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2629 .Case("none", AArch64CC::EQ)
2630 .Case("any", AArch64CC::NE)
2631 .Case("nlast", AArch64CC::HS)
2632 .Case("last", AArch64CC::LO)
2633 .Case("first", AArch64CC::MI)
2634 .Case("nfrst", AArch64CC::PL)
2635 .Case("pmore", AArch64CC::HI)
2636 .Case("plast", AArch64CC::LS)
2637 .Case("tcont", AArch64CC::GE)
2638 .Case("tstop", AArch64CC::LT)
2639 .Default(AArch64CC::Invalid);
2640
Tim Northover3b0846e2014-05-24 12:50:23 +00002641 return CC;
2642}
2643
2644/// parseCondCode - Parse a Condition Code operand.
2645bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2646 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002647 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002648 SMLoc S = getLoc();
2649 const AsmToken &Tok = Parser.getTok();
2650 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2651
2652 StringRef Cond = Tok.getString();
2653 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2654 if (CC == AArch64CC::Invalid)
2655 return TokError("invalid condition code");
2656 Parser.Lex(); // Eat identifier token.
2657
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002658 if (invertCondCode) {
2659 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2660 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002661 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002662 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002663
2664 Operands.push_back(
2665 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2666 return false;
2667}
2668
2669/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2670/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002671OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002672AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002673 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002674 const AsmToken &Tok = Parser.getTok();
2675 std::string LowerID = Tok.getString().lower();
2676 AArch64_AM::ShiftExtendType ShOp =
2677 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2678 .Case("lsl", AArch64_AM::LSL)
2679 .Case("lsr", AArch64_AM::LSR)
2680 .Case("asr", AArch64_AM::ASR)
2681 .Case("ror", AArch64_AM::ROR)
2682 .Case("msl", AArch64_AM::MSL)
2683 .Case("uxtb", AArch64_AM::UXTB)
2684 .Case("uxth", AArch64_AM::UXTH)
2685 .Case("uxtw", AArch64_AM::UXTW)
2686 .Case("uxtx", AArch64_AM::UXTX)
2687 .Case("sxtb", AArch64_AM::SXTB)
2688 .Case("sxth", AArch64_AM::SXTH)
2689 .Case("sxtw", AArch64_AM::SXTW)
2690 .Case("sxtx", AArch64_AM::SXTX)
2691 .Default(AArch64_AM::InvalidShiftExtend);
2692
2693 if (ShOp == AArch64_AM::InvalidShiftExtend)
2694 return MatchOperand_NoMatch;
2695
2696 SMLoc S = Tok.getLoc();
2697 Parser.Lex();
2698
Nirav Davee833c6c2016-11-08 18:31:04 +00002699 bool Hash = parseOptionalToken(AsmToken::Hash);
2700
Tim Northover3b0846e2014-05-24 12:50:23 +00002701 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2702 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2703 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2704 ShOp == AArch64_AM::MSL) {
2705 // We expect a number here.
2706 TokError("expected #imm after shift specifier");
2707 return MatchOperand_ParseFail;
2708 }
2709
Chad Rosier2ff37b82016-12-27 16:58:09 +00002710 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002711 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2712 Operands.push_back(
2713 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2714 return MatchOperand_Success;
2715 }
2716
Chad Rosier2ff37b82016-12-27 16:58:09 +00002717 // Make sure we do actually have a number, identifier or a parenthesized
2718 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002719 SMLoc E = Parser.getTok().getLoc();
2720 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002721 !Parser.getTok().is(AsmToken::LParen) &&
2722 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002723 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002724 return MatchOperand_ParseFail;
2725 }
2726
2727 const MCExpr *ImmVal;
2728 if (getParser().parseExpression(ImmVal))
2729 return MatchOperand_ParseFail;
2730
2731 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2732 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002733 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002734 return MatchOperand_ParseFail;
2735 }
2736
Jim Grosbach57fd2622014-09-23 22:16:02 +00002737 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002738 Operands.push_back(AArch64Operand::CreateShiftExtend(
2739 ShOp, MCE->getValue(), true, S, E, getContext()));
2740 return MatchOperand_Success;
2741}
2742
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002743static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2744 if (FBS[AArch64::HasV8_1aOps])
2745 Str += "ARMv8.1a";
2746 else if (FBS[AArch64::HasV8_2aOps])
2747 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002748 else if (FBS[AArch64::HasV8_3aOps])
2749 Str += "ARMv8.3a";
2750 else if (FBS[AArch64::HasV8_4aOps])
2751 Str += "ARMv8.4a";
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002752 else
2753 Str += "(unknown)";
2754}
2755
2756void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2757 SMLoc S) {
2758 const uint16_t Op2 = Encoding & 7;
2759 const uint16_t Cm = (Encoding & 0x78) >> 3;
2760 const uint16_t Cn = (Encoding & 0x780) >> 7;
2761 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2762
2763 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2764
2765 Operands.push_back(
2766 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2767 Operands.push_back(
2768 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2769 Operands.push_back(
2770 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2771 Expr = MCConstantExpr::create(Op2, getContext());
2772 Operands.push_back(
2773 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2774}
2775
Tim Northover3b0846e2014-05-24 12:50:23 +00002776/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2777/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2778bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2779 OperandVector &Operands) {
2780 if (Name.find('.') != StringRef::npos)
2781 return TokError("invalid operand");
2782
2783 Mnemonic = Name;
2784 Operands.push_back(
2785 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2786
Rafael Espindola961d4692014-11-11 05:18:41 +00002787 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002788 const AsmToken &Tok = Parser.getTok();
2789 StringRef Op = Tok.getString();
2790 SMLoc S = Tok.getLoc();
2791
Tim Northover3b0846e2014-05-24 12:50:23 +00002792 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002793 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2794 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002795 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002796 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2797 std::string Str("IC " + std::string(IC->Name) + " requires ");
2798 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2799 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002800 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002801 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002802 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002803 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2804 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002805 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002806 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2807 std::string Str("DC " + std::string(DC->Name) + " requires ");
2808 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2809 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002810 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002811 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002812 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002813 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2814 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002815 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002816 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2817 std::string Str("AT " + std::string(AT->Name) + " requires ");
2818 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2819 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002820 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002821 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002822 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002823 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2824 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002825 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002826 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2827 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2828 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2829 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002830 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002831 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002832 }
2833
Tim Northover3b0846e2014-05-24 12:50:23 +00002834 Parser.Lex(); // Eat operand.
2835
2836 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2837 bool HasRegister = false;
2838
2839 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002840 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002841 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2842 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002843 HasRegister = true;
2844 }
2845
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002846 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002847 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002848 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002849 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002850
Nirav Davee833c6c2016-11-08 18:31:04 +00002851 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2852 return true;
2853
Tim Northover3b0846e2014-05-24 12:50:23 +00002854 return false;
2855}
2856
Alex Bradbury58eba092016-11-01 16:32:05 +00002857OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002858AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002859 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002860 const AsmToken &Tok = Parser.getTok();
2861
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002862 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2863 TokError("'csync' operand expected");
2864 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002865 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002866 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002867 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002868 const MCExpr *ImmVal;
2869 SMLoc ExprLoc = getLoc();
2870 if (getParser().parseExpression(ImmVal))
2871 return MatchOperand_ParseFail;
2872 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2873 if (!MCE) {
2874 Error(ExprLoc, "immediate value expected for barrier operand");
2875 return MatchOperand_ParseFail;
2876 }
2877 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2878 Error(ExprLoc, "barrier operand out of range");
2879 return MatchOperand_ParseFail;
2880 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002881 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2882 Operands.push_back(AArch64Operand::CreateBarrier(
2883 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002884 return MatchOperand_Success;
2885 }
2886
2887 if (Tok.isNot(AsmToken::Identifier)) {
2888 TokError("invalid operand for instruction");
2889 return MatchOperand_ParseFail;
2890 }
2891
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002892 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002893 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002894 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2895 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002896 TokError("'sy' or #imm operand expected");
2897 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002898 // The only valid named option for TSB is 'csync'
2899 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
2900 TokError("'csync' operand expected");
2901 return MatchOperand_ParseFail;
2902 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002903 TokError("invalid barrier option name");
2904 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002905 }
2906
Tim Northovere6ae6762016-07-05 21:23:04 +00002907 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002908 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002909 Parser.Lex(); // Consume the option
2910
2911 return MatchOperand_Success;
2912}
2913
Alex Bradbury58eba092016-11-01 16:32:05 +00002914OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002915AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002916 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002917 const AsmToken &Tok = Parser.getTok();
2918
2919 if (Tok.isNot(AsmToken::Identifier))
2920 return MatchOperand_NoMatch;
2921
Tim Northovere6ae6762016-07-05 21:23:04 +00002922 int MRSReg, MSRReg;
2923 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2924 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2925 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2926 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2927 } else
2928 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002929
Tim Northovere6ae6762016-07-05 21:23:04 +00002930 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2931 unsigned PStateImm = -1;
2932 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2933 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002934
Tim Northovere6ae6762016-07-05 21:23:04 +00002935 Operands.push_back(
2936 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2937 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002938 Parser.Lex(); // Eat identifier
2939
2940 return MatchOperand_Success;
2941}
2942
Florian Hahnc4422242017-11-07 13:07:50 +00002943/// tryParseNeonVectorRegister - Parse a vector register operand.
2944bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002945 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002946 if (Parser.getTok().isNot(AsmToken::Identifier))
2947 return true;
2948
2949 SMLoc S = getLoc();
2950 // Check for a vector register specifier first.
2951 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002952 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002953 OperandMatchResultTy Res =
2954 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2955 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002956 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002957
2958 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2959 if (!KindRes)
2960 return true;
2961
2962 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002963 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002964 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2965 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00002966
Tim Northover3b0846e2014-05-24 12:50:23 +00002967 // If there was an explicit qualifier, that goes on as a literal text
2968 // operand.
2969 if (!Kind.empty())
2970 Operands.push_back(
2971 AArch64Operand::CreateToken(Kind, false, S, getContext()));
2972
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002973 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
2974}
2975
2976OperandMatchResultTy
2977AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00002978 SMLoc SIdx = getLoc();
2979 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002980 const MCExpr *ImmVal;
2981 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002982 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002983 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2984 if (!MCE) {
2985 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002986 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002987 }
2988
2989 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00002990
Nirav Davee833c6c2016-11-08 18:31:04 +00002991 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002992 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00002993
2994 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
2995 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002996 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002997 }
2998
Sander de Smalenc88f9a12018-04-11 14:10:37 +00002999 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003000}
3001
Sander de Smalen73937b72018-04-11 07:36:10 +00003002// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00003003// optional kind specifier. If it is a register specifier, eat the token
3004// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00003005OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00003006AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00003007 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00003008 MCAsmParser &Parser = getParser();
3009 const AsmToken &Tok = Parser.getTok();
3010
Florian Hahn91f11e52017-11-07 16:45:48 +00003011 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00003012 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003013
3014 StringRef Name = Tok.getString();
3015 // If there is a kind specifier, it's separated from the register name by
3016 // a '.'.
3017 size_t Start = 0, Next = Name.find('.');
3018 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003019 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003020
3021 if (RegNum) {
3022 if (Next != StringRef::npos) {
3023 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003024 if (!isValidVectorKind(Kind, MatchKind)) {
3025 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003026 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003027 }
3028 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003029 Parser.Lex(); // Eat the register token.
3030
3031 Reg = RegNum;
3032 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003033 }
3034
Sander de Smalen8e607342017-11-15 15:44:43 +00003035 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003036}
3037
Sander de Smalencd6be962017-12-20 11:02:42 +00003038/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3039OperandMatchResultTy
3040AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3041 // Check for a SVE predicate register specifier first.
3042 const SMLoc S = getLoc();
3043 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003044 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003045 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003046 if (Res != MatchOperand_Success)
3047 return Res;
3048
Sander de Smalen73937b72018-04-11 07:36:10 +00003049 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3050 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003051 return MatchOperand_NoMatch;
3052
Sander de Smalen73937b72018-04-11 07:36:10 +00003053 unsigned ElementWidth = KindRes->second;
3054 Operands.push_back(AArch64Operand::CreateVectorReg(
3055 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3056 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003057
Sander de Smalen7868e742018-01-09 11:17:06 +00003058 // Not all predicates are followed by a '/m' or '/z'.
3059 MCAsmParser &Parser = getParser();
3060 if (Parser.getTok().isNot(AsmToken::Slash))
3061 return MatchOperand_Success;
3062
3063 // But when they do they shouldn't have an element type suffix.
3064 if (!Kind.empty()) {
3065 Error(S, "not expecting size suffix");
3066 return MatchOperand_ParseFail;
3067 }
3068
3069 // Add a literal slash as operand
3070 Operands.push_back(
3071 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3072
3073 Parser.Lex(); // Eat the slash.
3074
3075 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003076 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003077 if (Pred != "z" && Pred != "m") {
3078 Error(getLoc(), "expecting 'm' or 'z' predication");
3079 return MatchOperand_ParseFail;
3080 }
3081
3082 // Add zero/merge token.
3083 const char *ZM = Pred == "z" ? "z" : "m";
3084 Operands.push_back(
3085 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3086
3087 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003088 return MatchOperand_Success;
3089}
3090
Sander de Smalen50d87022018-04-19 07:35:08 +00003091/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003092bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003093 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003094 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003095 return false;
3096
Sander de Smalen149916d2018-04-20 07:24:20 +00003097 // Otherwise try for a scalar register.
3098 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3099 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003100
Sander de Smalen149916d2018-04-20 07:24:20 +00003101 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003102}
3103
3104bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003105 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003106 bool HasELFModifier = false;
3107 AArch64MCExpr::VariantKind RefKind;
3108
Nirav Davee833c6c2016-11-08 18:31:04 +00003109 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003110 HasELFModifier = true;
3111
Nirav Davee833c6c2016-11-08 18:31:04 +00003112 if (Parser.getTok().isNot(AsmToken::Identifier))
3113 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003114
3115 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3116 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3117 .Case("lo12", AArch64MCExpr::VK_LO12)
3118 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3119 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3120 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3121 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3122 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3123 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3124 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3125 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3126 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3127 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3128 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3129 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3130 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3131 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3132 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3133 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3134 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3135 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3136 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3137 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3138 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3139 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3140 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3141 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3142 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3143 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3144 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3145 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3146 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3147 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3148 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3149 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3150 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3151 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003152 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3153 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003154 .Default(AArch64MCExpr::VK_INVALID);
3155
Nirav Davee833c6c2016-11-08 18:31:04 +00003156 if (RefKind == AArch64MCExpr::VK_INVALID)
3157 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003158
3159 Parser.Lex(); // Eat identifier
3160
Nirav Davee833c6c2016-11-08 18:31:04 +00003161 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003162 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003163 }
3164
3165 if (getParser().parseExpression(ImmVal))
3166 return true;
3167
3168 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003169 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003170
3171 return false;
3172}
3173
Sander de Smalen650234b2018-04-12 11:40:52 +00003174template <RegKind VectorKind>
3175OperandMatchResultTy
3176AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3177 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003178 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003179 if (!Parser.getTok().is(AsmToken::LCurly))
3180 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003181
3182 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003183 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003184 bool NoMatchIsError) {
3185 auto RegTok = Parser.getTok();
3186 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3187 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003188 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003189 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003190 llvm_unreachable("Expected a valid vector kind");
3191 }
3192
Sander de Smalen650234b2018-04-12 11:40:52 +00003193 if (RegTok.isNot(AsmToken::Identifier) ||
3194 ParseRes == MatchOperand_ParseFail ||
3195 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3196 Error(Loc, "vector register expected");
3197 return MatchOperand_ParseFail;
3198 }
3199
3200 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003201 };
3202
Tim Northover3b0846e2014-05-24 12:50:23 +00003203 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003204 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003205 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003206
Tim Northover3b0846e2014-05-24 12:50:23 +00003207 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003208 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003209 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3210
3211 // Put back the original left bracket if there was no match, so that
3212 // different types of list-operands can be matched (e.g. SVE, Neon).
3213 if (ParseRes == MatchOperand_NoMatch)
3214 Parser.getLexer().UnLex(LCurly);
3215
3216 if (ParseRes != MatchOperand_Success)
3217 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003218
Tim Northover3b0846e2014-05-24 12:50:23 +00003219 int64_t PrevReg = FirstReg;
3220 unsigned Count = 1;
3221
Nirav Davee833c6c2016-11-08 18:31:04 +00003222 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003223 SMLoc Loc = getLoc();
3224 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003225
Sander de Smalen50d87022018-04-19 07:35:08 +00003226 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003227 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3228 if (ParseRes != MatchOperand_Success)
3229 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003230
Tim Northover3b0846e2014-05-24 12:50:23 +00003231 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003232 if (Kind != NextKind) {
3233 Error(Loc, "mismatched register size suffix");
3234 return MatchOperand_ParseFail;
3235 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003236
3237 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3238
3239 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003240 Error(Loc, "invalid number of vectors");
3241 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003242 }
3243
3244 Count += Space;
3245 }
3246 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003247 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003248 SMLoc Loc = getLoc();
3249 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003250 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003251 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3252 if (ParseRes != MatchOperand_Success)
3253 return ParseRes;
3254
Tim Northover3b0846e2014-05-24 12:50:23 +00003255 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003256 if (Kind != NextKind) {
3257 Error(Loc, "mismatched register size suffix");
3258 return MatchOperand_ParseFail;
3259 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003260
3261 // Registers must be incremental (with wraparound at 31)
3262 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003263 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3264 Error(Loc, "registers must be sequential");
3265 return MatchOperand_ParseFail;
3266 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003267
3268 PrevReg = Reg;
3269 ++Count;
3270 }
3271 }
3272
Nirav Davee833c6c2016-11-08 18:31:04 +00003273 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003274 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003275
Sander de Smalen650234b2018-04-12 11:40:52 +00003276 if (Count > 4) {
3277 Error(S, "invalid number of vectors");
3278 return MatchOperand_ParseFail;
3279 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003280
3281 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003282 unsigned ElementWidth = 0;
3283 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003284 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003285 std::tie(NumElements, ElementWidth) = *VK;
3286 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003287
3288 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003289 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3290 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003291
Sander de Smalen650234b2018-04-12 11:40:52 +00003292 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003293}
3294
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003295/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3296bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003297 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3298 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003299 return true;
3300
3301 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3302}
3303
Alex Bradbury58eba092016-11-01 16:32:05 +00003304OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003305AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003306 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003307
Sander de Smalen50d87022018-04-19 07:35:08 +00003308 unsigned RegNum;
3309 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3310 if (Res != MatchOperand_Success)
3311 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003312
Nirav Davee833c6c2016-11-08 18:31:04 +00003313 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003314 Operands.push_back(AArch64Operand::CreateReg(
3315 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003316 return MatchOperand_Success;
3317 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003318
Nirav Davee833c6c2016-11-08 18:31:04 +00003319 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003320
Sander de Smalen50d87022018-04-19 07:35:08 +00003321 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003322 Error(getLoc(), "index must be absent or #0");
3323 return MatchOperand_ParseFail;
3324 }
3325
3326 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003327 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003328 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3329 Error(getLoc(), "index must be absent or #0");
3330 return MatchOperand_ParseFail;
3331 }
3332
Sander de Smalen50d87022018-04-19 07:35:08 +00003333 Operands.push_back(AArch64Operand::CreateReg(
3334 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003335 return MatchOperand_Success;
3336}
3337
Sander de Smalen0325e302018-07-02 07:34:52 +00003338template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003339OperandMatchResultTy
3340AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3341 SMLoc StartLoc = getLoc();
3342
3343 unsigned RegNum;
3344 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3345 if (Res != MatchOperand_Success)
3346 return Res;
3347
3348 // No shift/extend is the default.
3349 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3350 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003351 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003352 return MatchOperand_Success;
3353 }
3354
3355 // Eat the comma
3356 getParser().Lex();
3357
3358 // Match the shift
3359 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3360 Res = tryParseOptionalShiftExtend(ExtOpnd);
3361 if (Res != MatchOperand_Success)
3362 return Res;
3363
3364 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003365 Operands.push_back(AArch64Operand::CreateReg(
3366 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3367 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3368 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003369
3370 return MatchOperand_Success;
3371}
3372
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003373bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003374 MCAsmParser &Parser = getParser();
3375
3376 // Some SVE instructions have a decoration after the immediate, i.e.
3377 // "mul vl". We parse them here and add tokens, which must be present in the
3378 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003379 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3380 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003381 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003382 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003383 return true;
3384
Sander de Smalen5c625982018-04-13 12:56:14 +00003385 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003386 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003387 Parser.Lex(); // Eat the "mul"
3388
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003389 if (NextIsVL) {
3390 Operands.push_back(
3391 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3392 Parser.Lex(); // Eat the "vl"
3393 return false;
3394 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003395
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003396 if (NextIsHash) {
3397 Parser.Lex(); // Eat the #
3398 SMLoc S = getLoc();
3399
3400 // Parse immediate operand.
3401 const MCExpr *ImmVal;
3402 if (!Parser.parseExpression(ImmVal))
3403 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3404 Operands.push_back(AArch64Operand::CreateImm(
3405 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3406 getContext()));
3407 return MatchOperand_Success;
3408 }
3409 }
3410
3411 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003412}
3413
Tim Northover3b0846e2014-05-24 12:50:23 +00003414/// parseOperand - Parse a arm instruction operand. For now this parses the
3415/// operand regardless of the mnemonic.
3416bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3417 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003418 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003419
3420 OperandMatchResultTy ResTy =
3421 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3422
Tim Northover3b0846e2014-05-24 12:50:23 +00003423 // Check if the current operand has a custom associated parser, if so, try to
3424 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003425 if (ResTy == MatchOperand_Success)
3426 return false;
3427 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3428 // there was a match, but an error occurred, in which case, just return that
3429 // the operand parsing failed.
3430 if (ResTy == MatchOperand_ParseFail)
3431 return true;
3432
3433 // Nothing custom, so do general case parsing.
3434 SMLoc S, E;
3435 switch (getLexer().getKind()) {
3436 default: {
3437 SMLoc S = getLoc();
3438 const MCExpr *Expr;
3439 if (parseSymbolicImmVal(Expr))
3440 return Error(S, "invalid operand");
3441
3442 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3443 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3444 return false;
3445 }
3446 case AsmToken::LBrac: {
3447 SMLoc Loc = Parser.getTok().getLoc();
3448 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3449 getContext()));
3450 Parser.Lex(); // Eat '['
3451
3452 // There's no comma after a '[', so we can parse the next operand
3453 // immediately.
3454 return parseOperand(Operands, false, false);
3455 }
3456 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003457 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003458 case AsmToken::Identifier: {
3459 // If we're expecting a Condition Code operand, then just parse that.
3460 if (isCondCode)
3461 return parseCondCode(Operands, invertCondCode);
3462
3463 // If it's a register name, parse it.
3464 if (!parseRegister(Operands))
3465 return false;
3466
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003467 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3468 // by SVE instructions.
3469 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003470 return false;
3471
Tim Northover3b0846e2014-05-24 12:50:23 +00003472 // This could be an optional "shift" or "extend" operand.
3473 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3474 // We can only continue if no tokens were eaten.
3475 if (GotShift != MatchOperand_NoMatch)
3476 return GotShift;
3477
3478 // This was not a register so parse other operands that start with an
3479 // identifier (like labels) as expressions and create them as immediates.
3480 const MCExpr *IdVal;
3481 S = getLoc();
3482 if (getParser().parseExpression(IdVal))
3483 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003484 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3485 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3486 return false;
3487 }
3488 case AsmToken::Integer:
3489 case AsmToken::Real:
3490 case AsmToken::Hash: {
3491 // #42 -> immediate.
3492 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003493
3494 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003495
3496 // Parse a negative sign
3497 bool isNegative = false;
3498 if (Parser.getTok().is(AsmToken::Minus)) {
3499 isNegative = true;
3500 // We need to consume this token only when we have a Real, otherwise
3501 // we let parseSymbolicImmVal take care of it
3502 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3503 Parser.Lex();
3504 }
3505
3506 // The only Real that should come through here is a literal #0.0 for
3507 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3508 // so convert the value.
3509 const AsmToken &Tok = Parser.getTok();
3510 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003511 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003512 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3513 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3514 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003515 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003516 return TokError("unexpected floating point literal");
3517 else if (IntVal != 0 || isNegative)
3518 return TokError("expected floating-point constant #0.0");
3519 Parser.Lex(); // Eat the token.
3520
3521 Operands.push_back(
3522 AArch64Operand::CreateToken("#0", false, S, getContext()));
3523 Operands.push_back(
3524 AArch64Operand::CreateToken(".0", false, S, getContext()));
3525 return false;
3526 }
3527
3528 const MCExpr *ImmVal;
3529 if (parseSymbolicImmVal(ImmVal))
3530 return true;
3531
3532 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3533 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3534 return false;
3535 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003536 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003537 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003538 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003539 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003540 Parser.Lex(); // Eat '='
3541 const MCExpr *SubExprVal;
3542 if (getParser().parseExpression(SubExprVal))
3543 return true;
3544
David Peixottoae5ba762014-07-18 16:05:14 +00003545 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003546 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003547 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003548
3549 bool IsXReg =
3550 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3551 Operands[1]->getReg());
3552
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003553 MCContext& Ctx = getContext();
3554 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3555 // 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 +00003556 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003557 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3558 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3559 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3560 ShiftAmt += 16;
3561 Imm >>= 16;
3562 }
3563 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3564 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3565 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003566 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003567 if (ShiftAmt)
3568 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3569 ShiftAmt, true, S, E, Ctx));
3570 return false;
3571 }
David Peixottoae5ba762014-07-18 16:05:14 +00003572 APInt Simm = APInt(64, Imm << ShiftAmt);
3573 // check if the immediate is an unsigned or signed 32-bit int for W regs
3574 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3575 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003576 }
3577 // 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 +00003578 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003579 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003580 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3581 return false;
3582 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003583 }
3584}
3585
Sander de Smalen0325e302018-07-02 07:34:52 +00003586bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3587 const MCParsedAsmOperand &Op2) const {
3588 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3589 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3590 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3591 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3592 return MCTargetAsmParser::regsEqual(Op1, Op2);
3593
3594 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3595 "Testing equality of non-scalar registers not supported");
3596
3597 // Check if a registers match their sub/super register classes.
3598 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3599 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3600 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3601 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3602 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3603 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3604 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3605 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3606
3607 return false;
3608}
3609
Tim Northover3b0846e2014-05-24 12:50:23 +00003610/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3611/// operands.
3612bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3613 StringRef Name, SMLoc NameLoc,
3614 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003615 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003616 Name = StringSwitch<StringRef>(Name.lower())
3617 .Case("beq", "b.eq")
3618 .Case("bne", "b.ne")
3619 .Case("bhs", "b.hs")
3620 .Case("bcs", "b.cs")
3621 .Case("blo", "b.lo")
3622 .Case("bcc", "b.cc")
3623 .Case("bmi", "b.mi")
3624 .Case("bpl", "b.pl")
3625 .Case("bvs", "b.vs")
3626 .Case("bvc", "b.vc")
3627 .Case("bhi", "b.hi")
3628 .Case("bls", "b.ls")
3629 .Case("bge", "b.ge")
3630 .Case("blt", "b.lt")
3631 .Case("bgt", "b.gt")
3632 .Case("ble", "b.le")
3633 .Case("bal", "b.al")
3634 .Case("bnv", "b.nv")
3635 .Default(Name);
3636
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003637 // First check for the AArch64-specific .req directive.
3638 if (Parser.getTok().is(AsmToken::Identifier) &&
3639 Parser.getTok().getIdentifier() == ".req") {
3640 parseDirectiveReq(Name, NameLoc);
3641 // We always return 'error' for this, as we're done with this
3642 // statement and don't need to match the 'instruction."
3643 return true;
3644 }
3645
Tim Northover3b0846e2014-05-24 12:50:23 +00003646 // Create the leading tokens for the mnemonic, split by '.' characters.
3647 size_t Start = 0, Next = Name.find('.');
3648 StringRef Head = Name.slice(Start, Next);
3649
3650 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003651 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3652 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003653
3654 Operands.push_back(
3655 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3656 Mnemonic = Head;
3657
3658 // Handle condition codes for a branch mnemonic
3659 if (Head == "b" && Next != StringRef::npos) {
3660 Start = Next;
3661 Next = Name.find('.', Start + 1);
3662 Head = Name.slice(Start + 1, Next);
3663
3664 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3665 (Head.data() - Name.data()));
3666 AArch64CC::CondCode CC = parseCondCodeString(Head);
3667 if (CC == AArch64CC::Invalid)
3668 return Error(SuffixLoc, "invalid condition code");
3669 Operands.push_back(
3670 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3671 Operands.push_back(
3672 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3673 }
3674
3675 // Add the remaining tokens in the mnemonic.
3676 while (Next != StringRef::npos) {
3677 Start = Next;
3678 Next = Name.find('.', Start + 1);
3679 Head = Name.slice(Start, Next);
3680 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3681 (Head.data() - Name.data()) + 1);
3682 Operands.push_back(
3683 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3684 }
3685
3686 // Conditional compare instructions have a Condition Code operand, which needs
3687 // to be parsed and an immediate operand created.
3688 bool condCodeFourthOperand =
3689 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3690 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3691 Head == "csinc" || Head == "csinv" || Head == "csneg");
3692
3693 // These instructions are aliases to some of the conditional select
3694 // instructions. However, the condition code is inverted in the aliased
3695 // instruction.
3696 //
3697 // FIXME: Is this the correct way to handle these? Or should the parser
3698 // generate the aliased instructions directly?
3699 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3700 bool condCodeThirdOperand =
3701 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3702
3703 // Read the remaining operands.
3704 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3705 // Read the first operand.
3706 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003707 return true;
3708 }
3709
3710 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003711 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003712 // Parse and remember the operand.
3713 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3714 (N == 3 && condCodeThirdOperand) ||
3715 (N == 2 && condCodeSecondOperand),
3716 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003717 return true;
3718 }
3719
3720 // After successfully parsing some operands there are two special cases to
3721 // consider (i.e. notional operands not separated by commas). Both are due
3722 // to memory specifiers:
3723 // + An RBrac will end an address for load/store/prefetch
3724 // + An '!' will indicate a pre-indexed operation.
3725 //
3726 // It's someone else's responsibility to make sure these tokens are sane
3727 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003728
Nirav Davee833c6c2016-11-08 18:31:04 +00003729 SMLoc RLoc = Parser.getTok().getLoc();
3730 if (parseOptionalToken(AsmToken::RBrac))
3731 Operands.push_back(
3732 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3733 SMLoc ELoc = Parser.getTok().getLoc();
3734 if (parseOptionalToken(AsmToken::Exclaim))
3735 Operands.push_back(
3736 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003737
3738 ++N;
3739 }
3740 }
3741
Nirav Davee833c6c2016-11-08 18:31:04 +00003742 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3743 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003744
Tim Northover3b0846e2014-05-24 12:50:23 +00003745 return false;
3746}
3747
Sander de Smalen9b333092018-07-30 15:42:46 +00003748static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3749 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3750 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3751 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3752 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3753 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3754 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3755 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3756}
3757
Tim Northover3b0846e2014-05-24 12:50:23 +00003758// FIXME: This entire function is a giant hack to provide us with decent
3759// operand range validation/diagnostics until TableGen/MC can be extended
3760// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003761bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3762 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003763 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003764 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3765
3766 // A prefix only applies to the instruction following it. Here we extract
3767 // prefix information for the next instruction before validating the current
3768 // one so that in the case of failure we don't erronously continue using the
3769 // current prefix.
3770 PrefixInfo Prefix = NextPrefix;
3771 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3772
3773 // Before validating the instruction in isolation we run through the rules
3774 // applicable when it follows a prefix instruction.
3775 // NOTE: brk & hlt can be prefixed but require no additional validation.
3776 if (Prefix.isActive() &&
3777 (Inst.getOpcode() != AArch64::BRK) &&
3778 (Inst.getOpcode() != AArch64::HLT)) {
3779
3780 // Prefixed intructions must have a destructive operand.
3781 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3782 AArch64::NotDestructive)
3783 return Error(IDLoc, "instruction is unpredictable when following a"
3784 " movprfx, suggest replacing movprfx with mov");
3785
3786 // Destination operands must match.
3787 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3788 return Error(Loc[0], "instruction is unpredictable when following a"
3789 " movprfx writing to a different destination");
3790
3791 // Destination operand must not be used in any other location.
3792 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3793 if (Inst.getOperand(i).isReg() &&
3794 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3795 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3796 return Error(Loc[0], "instruction is unpredictable when following a"
3797 " movprfx and destination also used as non-destructive"
3798 " source");
3799 }
3800
3801 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3802 if (Prefix.isPredicated()) {
3803 int PgIdx = -1;
3804
3805 // Find the instructions general predicate.
3806 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3807 if (Inst.getOperand(i).isReg() &&
3808 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3809 PgIdx = i;
3810 break;
3811 }
3812
3813 // Instruction must be predicated if the movprfx is predicated.
3814 if (PgIdx == -1 ||
3815 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3816 return Error(IDLoc, "instruction is unpredictable when following a"
3817 " predicated movprfx, suggest using unpredicated movprfx");
3818
3819 // Instruction must use same general predicate as the movprfx.
3820 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3821 return Error(IDLoc, "instruction is unpredictable when following a"
3822 " predicated movprfx using a different general predicate");
3823
3824 // Instruction element type must match the movprfx.
3825 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3826 return Error(IDLoc, "instruction is unpredictable when following a"
3827 " predicated movprfx with a different element size");
3828 }
3829 }
3830
Tim Northover3b0846e2014-05-24 12:50:23 +00003831 // Check for indexed addressing modes w/ the base register being the
3832 // same as a destination/source register or pair load where
3833 // the Rt == Rt2. All of those are undefined behaviour.
3834 switch (Inst.getOpcode()) {
3835 case AArch64::LDPSWpre:
3836 case AArch64::LDPWpost:
3837 case AArch64::LDPWpre:
3838 case AArch64::LDPXpost:
3839 case AArch64::LDPXpre: {
3840 unsigned Rt = Inst.getOperand(1).getReg();
3841 unsigned Rt2 = Inst.getOperand(2).getReg();
3842 unsigned Rn = Inst.getOperand(3).getReg();
3843 if (RI->isSubRegisterEq(Rn, Rt))
3844 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3845 "is also a destination");
3846 if (RI->isSubRegisterEq(Rn, Rt2))
3847 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3848 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003849 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003850 }
3851 case AArch64::LDPDi:
3852 case AArch64::LDPQi:
3853 case AArch64::LDPSi:
3854 case AArch64::LDPSWi:
3855 case AArch64::LDPWi:
3856 case AArch64::LDPXi: {
3857 unsigned Rt = Inst.getOperand(0).getReg();
3858 unsigned Rt2 = Inst.getOperand(1).getReg();
3859 if (Rt == Rt2)
3860 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3861 break;
3862 }
3863 case AArch64::LDPDpost:
3864 case AArch64::LDPDpre:
3865 case AArch64::LDPQpost:
3866 case AArch64::LDPQpre:
3867 case AArch64::LDPSpost:
3868 case AArch64::LDPSpre:
3869 case AArch64::LDPSWpost: {
3870 unsigned Rt = Inst.getOperand(1).getReg();
3871 unsigned Rt2 = Inst.getOperand(2).getReg();
3872 if (Rt == Rt2)
3873 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3874 break;
3875 }
3876 case AArch64::STPDpost:
3877 case AArch64::STPDpre:
3878 case AArch64::STPQpost:
3879 case AArch64::STPQpre:
3880 case AArch64::STPSpost:
3881 case AArch64::STPSpre:
3882 case AArch64::STPWpost:
3883 case AArch64::STPWpre:
3884 case AArch64::STPXpost:
3885 case AArch64::STPXpre: {
3886 unsigned Rt = Inst.getOperand(1).getReg();
3887 unsigned Rt2 = Inst.getOperand(2).getReg();
3888 unsigned Rn = Inst.getOperand(3).getReg();
3889 if (RI->isSubRegisterEq(Rn, Rt))
3890 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3891 "is also a source");
3892 if (RI->isSubRegisterEq(Rn, Rt2))
3893 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3894 "is also a source");
3895 break;
3896 }
3897 case AArch64::LDRBBpre:
3898 case AArch64::LDRBpre:
3899 case AArch64::LDRHHpre:
3900 case AArch64::LDRHpre:
3901 case AArch64::LDRSBWpre:
3902 case AArch64::LDRSBXpre:
3903 case AArch64::LDRSHWpre:
3904 case AArch64::LDRSHXpre:
3905 case AArch64::LDRSWpre:
3906 case AArch64::LDRWpre:
3907 case AArch64::LDRXpre:
3908 case AArch64::LDRBBpost:
3909 case AArch64::LDRBpost:
3910 case AArch64::LDRHHpost:
3911 case AArch64::LDRHpost:
3912 case AArch64::LDRSBWpost:
3913 case AArch64::LDRSBXpost:
3914 case AArch64::LDRSHWpost:
3915 case AArch64::LDRSHXpost:
3916 case AArch64::LDRSWpost:
3917 case AArch64::LDRWpost:
3918 case AArch64::LDRXpost: {
3919 unsigned Rt = Inst.getOperand(1).getReg();
3920 unsigned Rn = Inst.getOperand(2).getReg();
3921 if (RI->isSubRegisterEq(Rn, Rt))
3922 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3923 "is also a source");
3924 break;
3925 }
3926 case AArch64::STRBBpost:
3927 case AArch64::STRBpost:
3928 case AArch64::STRHHpost:
3929 case AArch64::STRHpost:
3930 case AArch64::STRWpost:
3931 case AArch64::STRXpost:
3932 case AArch64::STRBBpre:
3933 case AArch64::STRBpre:
3934 case AArch64::STRHHpre:
3935 case AArch64::STRHpre:
3936 case AArch64::STRWpre:
3937 case AArch64::STRXpre: {
3938 unsigned Rt = Inst.getOperand(1).getReg();
3939 unsigned Rn = Inst.getOperand(2).getReg();
3940 if (RI->isSubRegisterEq(Rn, Rt))
3941 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3942 "is also a source");
3943 break;
3944 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003945 case AArch64::STXRB:
3946 case AArch64::STXRH:
3947 case AArch64::STXRW:
3948 case AArch64::STXRX:
3949 case AArch64::STLXRB:
3950 case AArch64::STLXRH:
3951 case AArch64::STLXRW:
3952 case AArch64::STLXRX: {
3953 unsigned Rs = Inst.getOperand(0).getReg();
3954 unsigned Rt = Inst.getOperand(1).getReg();
3955 unsigned Rn = Inst.getOperand(2).getReg();
3956 if (RI->isSubRegisterEq(Rt, Rs) ||
3957 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3958 return Error(Loc[0],
3959 "unpredictable STXR instruction, status is also a source");
3960 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003961 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003962 case AArch64::STXPW:
3963 case AArch64::STXPX:
3964 case AArch64::STLXPW:
3965 case AArch64::STLXPX: {
3966 unsigned Rs = Inst.getOperand(0).getReg();
3967 unsigned Rt1 = Inst.getOperand(1).getReg();
3968 unsigned Rt2 = Inst.getOperand(2).getReg();
3969 unsigned Rn = Inst.getOperand(3).getReg();
3970 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
3971 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3972 return Error(Loc[0],
3973 "unpredictable STXP instruction, status is also a source");
3974 break;
3975 }
3976 }
3977
Tim Northover3b0846e2014-05-24 12:50:23 +00003978
3979 // Now check immediate ranges. Separate from the above as there is overlap
3980 // in the instructions being checked and this keeps the nested conditionals
3981 // to a minimum.
3982 switch (Inst.getOpcode()) {
3983 case AArch64::ADDSWri:
3984 case AArch64::ADDSXri:
3985 case AArch64::ADDWri:
3986 case AArch64::ADDXri:
3987 case AArch64::SUBSWri:
3988 case AArch64::SUBSXri:
3989 case AArch64::SUBWri:
3990 case AArch64::SUBXri: {
3991 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
3992 // some slight duplication here.
3993 if (Inst.getOperand(2).isExpr()) {
3994 const MCExpr *Expr = Inst.getOperand(2).getExpr();
3995 AArch64MCExpr::VariantKind ELFRefKind;
3996 MCSymbolRefExpr::VariantKind DarwinRefKind;
3997 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00003998 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
3999
4000 // Only allow these with ADDXri.
4001 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4002 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4003 Inst.getOpcode() == AArch64::ADDXri)
4004 return false;
4005
4006 // Only allow these with ADDXri/ADDWri
4007 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4008 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4009 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4010 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4011 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4012 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4013 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00004014 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4015 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4016 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004017 (Inst.getOpcode() == AArch64::ADDXri ||
4018 Inst.getOpcode() == AArch64::ADDWri))
4019 return false;
4020
4021 // Don't allow symbol refs in the immediate field otherwise
4022 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4023 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4024 // 'cmp w0, 'borked')
4025 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004026 }
Diana Picusc93518d2016-10-11 09:17:47 +00004027 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004028 }
4029 return false;
4030 }
4031 default:
4032 return false;
4033 }
4034}
4035
Craig Topper05515562017-10-26 06:46:41 +00004036static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
4037 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004038
4039bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004040 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004041 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004042 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004043 case Match_InvalidTiedOperand: {
4044 RegConstraintEqualityTy EqTy =
4045 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4046 .getRegEqualityTy();
4047 switch (EqTy) {
4048 case RegConstraintEqualityTy::EqualsSubReg:
4049 return Error(Loc, "operand must be 64-bit form of destination register");
4050 case RegConstraintEqualityTy::EqualsSuperReg:
4051 return Error(Loc, "operand must be 32-bit form of destination register");
4052 case RegConstraintEqualityTy::EqualsReg:
4053 return Error(Loc, "operand must match destination register");
4054 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004055 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004056 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004057 case Match_MissingFeature:
4058 return Error(Loc,
4059 "instruction requires a CPU feature not currently enabled");
4060 case Match_InvalidOperand:
4061 return Error(Loc, "invalid operand for instruction");
4062 case Match_InvalidSuffix:
4063 return Error(Loc, "invalid type suffix for instruction");
4064 case Match_InvalidCondCode:
4065 return Error(Loc, "expected AArch64 condition code");
4066 case Match_AddSubRegExtendSmall:
4067 return Error(Loc,
4068 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
4069 case Match_AddSubRegExtendLarge:
4070 return Error(Loc,
4071 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4072 case Match_AddSubSecondSource:
4073 return Error(Loc,
4074 "expected compatible register, symbol or integer in range [0, 4095]");
4075 case Match_LogicalSecondSource:
4076 return Error(Loc, "expected compatible register or logical immediate");
4077 case Match_InvalidMovImm32Shift:
4078 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4079 case Match_InvalidMovImm64Shift:
4080 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4081 case Match_AddSubRegShift32:
4082 return Error(Loc,
4083 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4084 case Match_AddSubRegShift64:
4085 return Error(Loc,
4086 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4087 case Match_InvalidFPImm:
4088 return Error(Loc,
4089 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004090 case Match_InvalidMemoryIndexedSImm6:
4091 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004092 case Match_InvalidMemoryIndexedSImm5:
4093 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004094 case Match_InvalidMemoryIndexed1SImm4:
4095 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004096 case Match_InvalidMemoryIndexed2SImm4:
4097 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004098 case Match_InvalidMemoryIndexed3SImm4:
4099 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004100 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004101 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004102 case Match_InvalidMemoryIndexed16SImm4:
4103 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004104 case Match_InvalidMemoryIndexed1SImm6:
4105 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004106 case Match_InvalidMemoryIndexedSImm8:
4107 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004108 case Match_InvalidMemoryIndexedSImm9:
4109 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004110 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004111 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004112 case Match_InvalidMemoryIndexed4SImm7:
4113 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4114 case Match_InvalidMemoryIndexed8SImm7:
4115 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4116 case Match_InvalidMemoryIndexed16SImm7:
4117 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004118 case Match_InvalidMemoryIndexed8UImm5:
4119 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4120 case Match_InvalidMemoryIndexed4UImm5:
4121 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4122 case Match_InvalidMemoryIndexed2UImm5:
4123 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004124 case Match_InvalidMemoryIndexed8UImm6:
4125 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
4126 case Match_InvalidMemoryIndexed4UImm6:
4127 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4128 case Match_InvalidMemoryIndexed2UImm6:
4129 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4130 case Match_InvalidMemoryIndexed1UImm6:
4131 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004132 case Match_InvalidMemoryWExtend8:
4133 return Error(Loc,
4134 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4135 case Match_InvalidMemoryWExtend16:
4136 return Error(Loc,
4137 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4138 case Match_InvalidMemoryWExtend32:
4139 return Error(Loc,
4140 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4141 case Match_InvalidMemoryWExtend64:
4142 return Error(Loc,
4143 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4144 case Match_InvalidMemoryWExtend128:
4145 return Error(Loc,
4146 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4147 case Match_InvalidMemoryXExtend8:
4148 return Error(Loc,
4149 "expected 'lsl' or 'sxtx' with optional shift of #0");
4150 case Match_InvalidMemoryXExtend16:
4151 return Error(Loc,
4152 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4153 case Match_InvalidMemoryXExtend32:
4154 return Error(Loc,
4155 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4156 case Match_InvalidMemoryXExtend64:
4157 return Error(Loc,
4158 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4159 case Match_InvalidMemoryXExtend128:
4160 return Error(Loc,
4161 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4162 case Match_InvalidMemoryIndexed1:
4163 return Error(Loc, "index must be an integer in range [0, 4095].");
4164 case Match_InvalidMemoryIndexed2:
4165 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4166 case Match_InvalidMemoryIndexed4:
4167 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4168 case Match_InvalidMemoryIndexed8:
4169 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4170 case Match_InvalidMemoryIndexed16:
4171 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004172 case Match_InvalidImm0_1:
4173 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004174 case Match_InvalidImm0_7:
4175 return Error(Loc, "immediate must be an integer in range [0, 7].");
4176 case Match_InvalidImm0_15:
4177 return Error(Loc, "immediate must be an integer in range [0, 15].");
4178 case Match_InvalidImm0_31:
4179 return Error(Loc, "immediate must be an integer in range [0, 31].");
4180 case Match_InvalidImm0_63:
4181 return Error(Loc, "immediate must be an integer in range [0, 63].");
4182 case Match_InvalidImm0_127:
4183 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004184 case Match_InvalidImm0_255:
4185 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004186 case Match_InvalidImm0_65535:
4187 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4188 case Match_InvalidImm1_8:
4189 return Error(Loc, "immediate must be an integer in range [1, 8].");
4190 case Match_InvalidImm1_16:
4191 return Error(Loc, "immediate must be an integer in range [1, 16].");
4192 case Match_InvalidImm1_32:
4193 return Error(Loc, "immediate must be an integer in range [1, 32].");
4194 case Match_InvalidImm1_64:
4195 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004196 case Match_InvalidSVEAddSubImm8:
4197 return Error(Loc, "immediate must be an integer in range [0, 255]"
4198 " with a shift amount of 0");
4199 case Match_InvalidSVEAddSubImm16:
4200 case Match_InvalidSVEAddSubImm32:
4201 case Match_InvalidSVEAddSubImm64:
4202 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4203 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004204 case Match_InvalidSVECpyImm8:
4205 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4206 " with a shift amount of 0");
4207 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004208 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4209 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004210 case Match_InvalidSVECpyImm32:
4211 case Match_InvalidSVECpyImm64:
4212 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4213 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004214 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004215 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004216 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004217 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004218 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004219 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004220 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004221 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004222 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004223 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004224 case Match_InvalidSVEIndexRange0_63:
4225 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4226 case Match_InvalidSVEIndexRange0_31:
4227 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4228 case Match_InvalidSVEIndexRange0_15:
4229 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4230 case Match_InvalidSVEIndexRange0_7:
4231 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4232 case Match_InvalidSVEIndexRange0_3:
4233 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004234 case Match_InvalidLabel:
4235 return Error(Loc, "expected label or encodable integer pc offset");
4236 case Match_MRS:
4237 return Error(Loc, "expected readable system register");
4238 case Match_MSR:
4239 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004240 case Match_InvalidComplexRotationEven:
4241 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4242 case Match_InvalidComplexRotationOdd:
4243 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004244 case Match_MnemonicFail: {
4245 std::string Suggestion = AArch64MnemonicSpellCheck(
4246 ((AArch64Operand &)*Operands[0]).getToken(),
4247 ComputeAvailableFeatures(STI->getFeatureBits()));
4248 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4249 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004250 case Match_InvalidGPR64shifted8:
4251 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4252 case Match_InvalidGPR64shifted16:
4253 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4254 case Match_InvalidGPR64shifted32:
4255 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4256 case Match_InvalidGPR64shifted64:
4257 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4258 case Match_InvalidGPR64NoXZRshifted8:
4259 return Error(Loc, "register must be x0..x30 without shift");
4260 case Match_InvalidGPR64NoXZRshifted16:
4261 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4262 case Match_InvalidGPR64NoXZRshifted32:
4263 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4264 case Match_InvalidGPR64NoXZRshifted64:
4265 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004266 case Match_InvalidZPR32UXTW8:
4267 case Match_InvalidZPR32SXTW8:
4268 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4269 case Match_InvalidZPR32UXTW16:
4270 case Match_InvalidZPR32SXTW16:
4271 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4272 case Match_InvalidZPR32UXTW32:
4273 case Match_InvalidZPR32SXTW32:
4274 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4275 case Match_InvalidZPR32UXTW64:
4276 case Match_InvalidZPR32SXTW64:
4277 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4278 case Match_InvalidZPR64UXTW8:
4279 case Match_InvalidZPR64SXTW8:
4280 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4281 case Match_InvalidZPR64UXTW16:
4282 case Match_InvalidZPR64SXTW16:
4283 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4284 case Match_InvalidZPR64UXTW32:
4285 case Match_InvalidZPR64SXTW32:
4286 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4287 case Match_InvalidZPR64UXTW64:
4288 case Match_InvalidZPR64SXTW64:
4289 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004290 case Match_InvalidZPR32LSL8:
4291 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4292 case Match_InvalidZPR32LSL16:
4293 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4294 case Match_InvalidZPR32LSL32:
4295 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4296 case Match_InvalidZPR32LSL64:
4297 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004298 case Match_InvalidZPR64LSL8:
4299 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4300 case Match_InvalidZPR64LSL16:
4301 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4302 case Match_InvalidZPR64LSL32:
4303 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4304 case Match_InvalidZPR64LSL64:
4305 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004306 case Match_InvalidZPR0:
4307 return Error(Loc, "expected register without element width sufix");
4308 case Match_InvalidZPR8:
4309 case Match_InvalidZPR16:
4310 case Match_InvalidZPR32:
4311 case Match_InvalidZPR64:
4312 case Match_InvalidZPR128:
4313 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004314 case Match_InvalidZPR_3b8:
4315 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4316 case Match_InvalidZPR_3b16:
4317 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4318 case Match_InvalidZPR_3b32:
4319 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4320 case Match_InvalidZPR_4b16:
4321 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4322 case Match_InvalidZPR_4b32:
4323 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4324 case Match_InvalidZPR_4b64:
4325 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004326 case Match_InvalidSVEPattern:
4327 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004328 case Match_InvalidSVEPredicateAnyReg:
4329 case Match_InvalidSVEPredicateBReg:
4330 case Match_InvalidSVEPredicateHReg:
4331 case Match_InvalidSVEPredicateSReg:
4332 case Match_InvalidSVEPredicateDReg:
4333 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004334 case Match_InvalidSVEPredicate3bAnyReg:
4335 case Match_InvalidSVEPredicate3bBReg:
4336 case Match_InvalidSVEPredicate3bHReg:
4337 case Match_InvalidSVEPredicate3bSReg:
4338 case Match_InvalidSVEPredicate3bDReg:
4339 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004340 case Match_InvalidSVEExactFPImmOperandHalfOne:
4341 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4342 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4343 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4344 case Match_InvalidSVEExactFPImmOperandZeroOne:
4345 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004346 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004347 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004348 }
4349}
4350
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004351static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004352
4353bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4354 OperandVector &Operands,
4355 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004356 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004357 bool MatchingInlineAsm) {
4358 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004359 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4360 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004361
David Blaikie960ea3f2014-06-08 16:18:35 +00004362 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004363 unsigned NumOperands = Operands.size();
4364
4365 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004366 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4367 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004368 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004369 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004370 if (Op3CE) {
4371 uint64_t Op3Val = Op3CE->getValue();
4372 uint64_t NewOp3Val = 0;
4373 uint64_t NewOp4Val = 0;
4374 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004375 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004376 NewOp3Val = (32 - Op3Val) & 0x1f;
4377 NewOp4Val = 31 - Op3Val;
4378 } else {
4379 NewOp3Val = (64 - Op3Val) & 0x3f;
4380 NewOp4Val = 63 - Op3Val;
4381 }
4382
Jim Grosbach13760bd2015-05-30 01:25:56 +00004383 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4384 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004385
4386 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004387 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004388 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004389 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4390 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4391 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004392 }
4393 }
Tim Northover03b99f62015-04-30 18:28:58 +00004394 } else if (NumOperands == 4 && Tok == "bfc") {
4395 // FIXME: Horrible hack to handle BFC->BFM alias.
4396 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4397 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4398 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4399
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004400 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004401 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4402 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4403
4404 if (LSBCE && WidthCE) {
4405 uint64_t LSB = LSBCE->getValue();
4406 uint64_t Width = WidthCE->getValue();
4407
4408 uint64_t RegWidth = 0;
4409 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4410 Op1.getReg()))
4411 RegWidth = 64;
4412 else
4413 RegWidth = 32;
4414
4415 if (LSB >= RegWidth)
4416 return Error(LSBOp.getStartLoc(),
4417 "expected integer in range [0, 31]");
4418 if (Width < 1 || Width > RegWidth)
4419 return Error(WidthOp.getStartLoc(),
4420 "expected integer in range [1, 32]");
4421
4422 uint64_t ImmR = 0;
4423 if (RegWidth == 32)
4424 ImmR = (32 - LSB) & 0x1f;
4425 else
4426 ImmR = (64 - LSB) & 0x3f;
4427
4428 uint64_t ImmS = Width - 1;
4429
4430 if (ImmR != 0 && ImmS >= ImmR)
4431 return Error(WidthOp.getStartLoc(),
4432 "requested insert overflows register");
4433
Jim Grosbach13760bd2015-05-30 01:25:56 +00004434 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4435 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004436 Operands[0] = AArch64Operand::CreateToken(
4437 "bfm", false, Op.getStartLoc(), getContext());
4438 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004439 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4440 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004441 Operands[3] = AArch64Operand::CreateImm(
4442 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4443 Operands.emplace_back(
4444 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4445 WidthOp.getEndLoc(), getContext()));
4446 }
4447 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004448 } else if (NumOperands == 5) {
4449 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4450 // UBFIZ -> UBFM aliases.
4451 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004452 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4453 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4454 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004455
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004456 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004457 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4458 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004459
4460 if (Op3CE && Op4CE) {
4461 uint64_t Op3Val = Op3CE->getValue();
4462 uint64_t Op4Val = Op4CE->getValue();
4463
4464 uint64_t RegWidth = 0;
4465 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004466 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004467 RegWidth = 64;
4468 else
4469 RegWidth = 32;
4470
4471 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004472 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004473 "expected integer in range [0, 31]");
4474 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004475 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004476 "expected integer in range [1, 32]");
4477
4478 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004479 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004480 NewOp3Val = (32 - Op3Val) & 0x1f;
4481 else
4482 NewOp3Val = (64 - Op3Val) & 0x3f;
4483
4484 uint64_t NewOp4Val = Op4Val - 1;
4485
4486 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004487 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004488 "requested insert overflows register");
4489
4490 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004491 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004492 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004493 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004494 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004495 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004496 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004497 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004498 if (Tok == "bfi")
4499 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004500 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004501 else if (Tok == "sbfiz")
4502 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004503 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004504 else if (Tok == "ubfiz")
4505 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004506 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004507 else
4508 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004509 }
4510 }
4511
4512 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4513 // UBFX -> UBFM aliases.
4514 } else if (NumOperands == 5 &&
4515 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004516 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4517 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4518 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004519
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004520 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004521 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4522 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004523
4524 if (Op3CE && Op4CE) {
4525 uint64_t Op3Val = Op3CE->getValue();
4526 uint64_t Op4Val = Op4CE->getValue();
4527
4528 uint64_t RegWidth = 0;
4529 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004530 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004531 RegWidth = 64;
4532 else
4533 RegWidth = 32;
4534
4535 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004536 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004537 "expected integer in range [0, 31]");
4538 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004539 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004540 "expected integer in range [1, 32]");
4541
4542 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4543
4544 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004545 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004546 "requested extract overflows register");
4547
4548 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004549 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004550 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004551 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004552 if (Tok == "bfxil")
4553 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004554 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004555 else if (Tok == "sbfx")
4556 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004557 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004558 else if (Tok == "ubfx")
4559 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004560 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004561 else
4562 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004563 }
4564 }
4565 }
4566 }
Tim Northover9097a072017-12-18 10:36:00 +00004567
4568 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4569 // instruction for FP registers correctly in some rare circumstances. Convert
4570 // it to a safe instruction and warn (because silently changing someone's
4571 // assembly is rude).
4572 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4573 NumOperands == 4 && Tok == "movi") {
4574 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4575 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4576 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4577 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4578 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4579 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4580 if (Suffix.lower() == ".2d" &&
4581 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4582 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4583 " correctly on this CPU, converting to equivalent movi.16b");
4584 // Switch the suffix to .16b.
4585 unsigned Idx = Op1.isToken() ? 1 : 2;
4586 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4587 getContext());
4588 }
4589 }
4590 }
4591
Tim Northover3b0846e2014-05-24 12:50:23 +00004592 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4593 // InstAlias can't quite handle this since the reg classes aren't
4594 // subclasses.
4595 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4596 // The source register can be Wn here, but the matcher expects a
4597 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004598 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004599 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004600 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004601 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4602 Op.getStartLoc(), Op.getEndLoc(),
4603 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004604 }
4605 }
4606 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4607 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
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 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004614 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004615 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004616 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004617 Operands[2] = 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 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4624 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004625 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004626 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004627 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004628 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004629 // The source register can be Wn here, but the matcher expects a
4630 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004631 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004632 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004633 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004634 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4635 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004636 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004637 }
4638 }
4639 }
4640
Tim Northover3b0846e2014-05-24 12:50:23 +00004641 MCInst Inst;
4642 // First try to match against the secondary set of tables containing the
4643 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4644 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004645 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004646
4647 // If that fails, try against the alternate table containing long-form NEON:
4648 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004649 if (MatchResult != Match_Success) {
4650 // But first, save the short-form match result: we can use it in case the
4651 // long-form match also fails.
4652 auto ShortFormNEONErrorInfo = ErrorInfo;
4653 auto ShortFormNEONMatchResult = MatchResult;
4654
Tim Northover3b0846e2014-05-24 12:50:23 +00004655 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004656 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004657
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004658 // Now, both matches failed, and the long-form match failed on the mnemonic
4659 // suffix token operand. The short-form match failure is probably more
4660 // relevant: use it instead.
4661 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004662 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004663 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4664 MatchResult = ShortFormNEONMatchResult;
4665 ErrorInfo = ShortFormNEONErrorInfo;
4666 }
4667 }
4668
Tim Northover3b0846e2014-05-24 12:50:23 +00004669 switch (MatchResult) {
4670 case Match_Success: {
4671 // Perform range checking and other semantic validations
4672 SmallVector<SMLoc, 8> OperandLocs;
4673 NumOperands = Operands.size();
4674 for (unsigned i = 1; i < NumOperands; ++i)
4675 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004676 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004677 return true;
4678
4679 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004680 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004681 return false;
4682 }
4683 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004684 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004685 // Special case the error message for the very common case where only
4686 // a single subtarget feature is missing (neon, e.g.).
4687 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004688 uint64_t Mask = 1;
4689 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4690 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004691 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004692 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004693 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004694 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004695 }
4696 return Error(IDLoc, Msg);
4697 }
4698 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004699 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004700 case Match_InvalidOperand: {
4701 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004702
Tim Northover26bb14e2014-08-18 11:49:42 +00004703 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004704 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004705 return Error(IDLoc, "too few operands for instruction",
4706 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004707
David Blaikie960ea3f2014-06-08 16:18:35 +00004708 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004709 if (ErrorLoc == SMLoc())
4710 ErrorLoc = IDLoc;
4711 }
4712 // If the match failed on a suffix token operand, tweak the diagnostic
4713 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004714 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4715 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004716 MatchResult = Match_InvalidSuffix;
4717
Sander de Smalen0325e302018-07-02 07:34:52 +00004718 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004719 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004720 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004721 case Match_InvalidMemoryIndexed1:
4722 case Match_InvalidMemoryIndexed2:
4723 case Match_InvalidMemoryIndexed4:
4724 case Match_InvalidMemoryIndexed8:
4725 case Match_InvalidMemoryIndexed16:
4726 case Match_InvalidCondCode:
4727 case Match_AddSubRegExtendSmall:
4728 case Match_AddSubRegExtendLarge:
4729 case Match_AddSubSecondSource:
4730 case Match_LogicalSecondSource:
4731 case Match_AddSubRegShift32:
4732 case Match_AddSubRegShift64:
4733 case Match_InvalidMovImm32Shift:
4734 case Match_InvalidMovImm64Shift:
4735 case Match_InvalidFPImm:
4736 case Match_InvalidMemoryWExtend8:
4737 case Match_InvalidMemoryWExtend16:
4738 case Match_InvalidMemoryWExtend32:
4739 case Match_InvalidMemoryWExtend64:
4740 case Match_InvalidMemoryWExtend128:
4741 case Match_InvalidMemoryXExtend8:
4742 case Match_InvalidMemoryXExtend16:
4743 case Match_InvalidMemoryXExtend32:
4744 case Match_InvalidMemoryXExtend64:
4745 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004746 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004747 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004748 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004749 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004750 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004751 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004752 case Match_InvalidMemoryIndexed4SImm7:
4753 case Match_InvalidMemoryIndexed8SImm7:
4754 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004755 case Match_InvalidMemoryIndexed8UImm5:
4756 case Match_InvalidMemoryIndexed4UImm5:
4757 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004758 case Match_InvalidMemoryIndexed1UImm6:
4759 case Match_InvalidMemoryIndexed2UImm6:
4760 case Match_InvalidMemoryIndexed4UImm6:
4761 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004762 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004763 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004764 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004765 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004766 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004767 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004768 case Match_InvalidImm0_7:
4769 case Match_InvalidImm0_15:
4770 case Match_InvalidImm0_31:
4771 case Match_InvalidImm0_63:
4772 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004773 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004774 case Match_InvalidImm0_65535:
4775 case Match_InvalidImm1_8:
4776 case Match_InvalidImm1_16:
4777 case Match_InvalidImm1_32:
4778 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004779 case Match_InvalidSVEAddSubImm8:
4780 case Match_InvalidSVEAddSubImm16:
4781 case Match_InvalidSVEAddSubImm32:
4782 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004783 case Match_InvalidSVECpyImm8:
4784 case Match_InvalidSVECpyImm16:
4785 case Match_InvalidSVECpyImm32:
4786 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004787 case Match_InvalidIndexRange1_1:
4788 case Match_InvalidIndexRange0_15:
4789 case Match_InvalidIndexRange0_7:
4790 case Match_InvalidIndexRange0_3:
4791 case Match_InvalidIndexRange0_1:
4792 case Match_InvalidSVEIndexRange0_63:
4793 case Match_InvalidSVEIndexRange0_31:
4794 case Match_InvalidSVEIndexRange0_15:
4795 case Match_InvalidSVEIndexRange0_7:
4796 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004797 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004798 case Match_InvalidComplexRotationEven:
4799 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004800 case Match_InvalidGPR64shifted8:
4801 case Match_InvalidGPR64shifted16:
4802 case Match_InvalidGPR64shifted32:
4803 case Match_InvalidGPR64shifted64:
4804 case Match_InvalidGPR64NoXZRshifted8:
4805 case Match_InvalidGPR64NoXZRshifted16:
4806 case Match_InvalidGPR64NoXZRshifted32:
4807 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004808 case Match_InvalidZPR32UXTW8:
4809 case Match_InvalidZPR32UXTW16:
4810 case Match_InvalidZPR32UXTW32:
4811 case Match_InvalidZPR32UXTW64:
4812 case Match_InvalidZPR32SXTW8:
4813 case Match_InvalidZPR32SXTW16:
4814 case Match_InvalidZPR32SXTW32:
4815 case Match_InvalidZPR32SXTW64:
4816 case Match_InvalidZPR64UXTW8:
4817 case Match_InvalidZPR64SXTW8:
4818 case Match_InvalidZPR64UXTW16:
4819 case Match_InvalidZPR64SXTW16:
4820 case Match_InvalidZPR64UXTW32:
4821 case Match_InvalidZPR64SXTW32:
4822 case Match_InvalidZPR64UXTW64:
4823 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004824 case Match_InvalidZPR32LSL8:
4825 case Match_InvalidZPR32LSL16:
4826 case Match_InvalidZPR32LSL32:
4827 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004828 case Match_InvalidZPR64LSL8:
4829 case Match_InvalidZPR64LSL16:
4830 case Match_InvalidZPR64LSL32:
4831 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004832 case Match_InvalidZPR0:
4833 case Match_InvalidZPR8:
4834 case Match_InvalidZPR16:
4835 case Match_InvalidZPR32:
4836 case Match_InvalidZPR64:
4837 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004838 case Match_InvalidZPR_3b8:
4839 case Match_InvalidZPR_3b16:
4840 case Match_InvalidZPR_3b32:
4841 case Match_InvalidZPR_4b16:
4842 case Match_InvalidZPR_4b32:
4843 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004844 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004845 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004846 case Match_InvalidSVEPredicateBReg:
4847 case Match_InvalidSVEPredicateHReg:
4848 case Match_InvalidSVEPredicateSReg:
4849 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004850 case Match_InvalidSVEPredicate3bAnyReg:
4851 case Match_InvalidSVEPredicate3bBReg:
4852 case Match_InvalidSVEPredicate3bHReg:
4853 case Match_InvalidSVEPredicate3bSReg:
4854 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004855 case Match_InvalidSVEExactFPImmOperandHalfOne:
4856 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4857 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004858 case Match_MSR:
4859 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004860 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004861 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004862 // Any time we get here, there's nothing fancy to do. Just get the
4863 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004864 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004865 if (ErrorLoc == SMLoc())
4866 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004867 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004868 }
4869 }
4870
4871 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004872}
4873
4874/// ParseDirective parses the arm specific directives
4875bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004876 const MCObjectFileInfo::Environment Format =
4877 getContext().getObjectFileInfo()->getObjectFileType();
4878 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004879
Tim Northover3b0846e2014-05-24 12:50:23 +00004880 StringRef IDVal = DirectiveID.getIdentifier();
4881 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004882 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004883 parseDirectiveArch(Loc);
4884 else if (IDVal == ".cpu")
4885 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004886 else if (IDVal == ".tlsdesccall")
4887 parseDirectiveTLSDescCall(Loc);
4888 else if (IDVal == ".ltorg" || IDVal == ".pool")
4889 parseDirectiveLtorg(Loc);
4890 else if (IDVal == ".unreq")
4891 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00004892 else if (IDVal == ".inst")
4893 parseDirectiveInst(Loc);
Martin Storsjod4590c32018-08-01 06:50:18 +00004894 else if (IsMachO) {
4895 if (IDVal == MCLOHDirectiveName())
4896 parseDirectiveLOH(IDVal, Loc);
4897 else
4898 return true;
4899 } else
Nirav Davee833c6c2016-11-08 18:31:04 +00004900 return true;
4901 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004902}
4903
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004904static const struct {
4905 const char *Name;
4906 const FeatureBitset Features;
4907} ExtensionMap[] = {
Sjoerd Meijerdc198342018-07-26 07:13:59 +00004908 { "crc", {AArch64::FeatureCRC} },
4909 { "sm4", {AArch64::FeatureSM4} },
4910 { "sha3", {AArch64::FeatureSHA3} },
4911 { "sha2", {AArch64::FeatureSHA2} },
4912 { "aes", {AArch64::FeatureAES} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004913 { "crypto", {AArch64::FeatureCrypto} },
4914 { "fp", {AArch64::FeatureFPARMv8} },
4915 { "simd", {AArch64::FeatureNEON} },
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004916 { "ras", {AArch64::FeatureRAS} },
Joel Jones75818bc2016-11-30 22:25:24 +00004917 { "lse", {AArch64::FeatureLSE} },
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004918
4919 // FIXME: Unsupported extensions
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00004920 { "pan", {} },
4921 { "lor", {} },
4922 { "rdma", {} },
4923 { "profile", {} },
4924};
4925
Sjoerd Meijerdc198342018-07-26 07:13:59 +00004926static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
4927 SmallVector<StringRef, 4> &RequestedExtensions) {
4928 const bool NoCrypto =
4929 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
4930 "nocrypto") != std::end(RequestedExtensions));
4931 const bool Crypto =
4932 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
4933 "crypto") != std::end(RequestedExtensions));
4934
4935 if (!NoCrypto && Crypto) {
4936 switch (ArchKind) {
4937 default:
4938 // Map 'generic' (and others) to sha2 and aes, because
4939 // that was the traditional meaning of crypto.
4940 case AArch64::ArchKind::ARMV8_1A:
4941 case AArch64::ArchKind::ARMV8_2A:
4942 case AArch64::ArchKind::ARMV8_3A:
4943 RequestedExtensions.push_back("sha2");
4944 RequestedExtensions.push_back("aes");
4945 break;
4946 case AArch64::ArchKind::ARMV8_4A:
4947 RequestedExtensions.push_back("sm4");
4948 RequestedExtensions.push_back("sha3");
4949 RequestedExtensions.push_back("sha2");
4950 RequestedExtensions.push_back("aes");
4951 break;
4952 }
4953 } else if (NoCrypto) {
4954 switch (ArchKind) {
4955 default:
4956 // Map 'generic' (and others) to sha2 and aes, because
4957 // that was the traditional meaning of crypto.
4958 case AArch64::ArchKind::ARMV8_1A:
4959 case AArch64::ArchKind::ARMV8_2A:
4960 case AArch64::ArchKind::ARMV8_3A:
4961 RequestedExtensions.push_back("nosha2");
4962 RequestedExtensions.push_back("noaes");
4963 break;
4964 case AArch64::ArchKind::ARMV8_4A:
4965 RequestedExtensions.push_back("nosm4");
4966 RequestedExtensions.push_back("nosha3");
4967 RequestedExtensions.push_back("nosha2");
4968 RequestedExtensions.push_back("noaes");
4969 break;
4970 }
4971 }
4972}
4973
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004974/// parseDirectiveArch
4975/// ::= .arch token
4976bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4977 SMLoc ArchLoc = getLoc();
4978
4979 StringRef Arch, ExtensionString;
4980 std::tie(Arch, ExtensionString) =
4981 getParser().parseStringToEndOfStatement().trim().split('+');
4982
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004983 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4984 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004985 return Error(ArchLoc, "unknown arch name");
4986
4987 if (parseToken(AsmToken::EndOfStatement))
4988 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004989
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004990 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00004991 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004992 AArch64::getArchFeatures(ID, AArch64Features);
4993 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
4994 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004995
Eric Christopher98ddbdb2016-09-08 17:27:03 +00004996 MCSubtargetInfo &STI = copySTI();
4997 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
4998 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
4999
5000 SmallVector<StringRef, 4> RequestedExtensions;
5001 if (!ExtensionString.empty())
5002 ExtensionString.split(RequestedExtensions, '+');
5003
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005004 ExpandCryptoAEK(ID, RequestedExtensions);
5005
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005006 FeatureBitset Features = STI.getFeatureBits();
5007 for (auto Name : RequestedExtensions) {
5008 bool EnableFeature = true;
5009
5010 if (Name.startswith_lower("no")) {
5011 EnableFeature = false;
5012 Name = Name.substr(2);
5013 }
5014
5015 for (const auto &Extension : ExtensionMap) {
5016 if (Extension.Name != Name)
5017 continue;
5018
5019 if (Extension.Features.none())
5020 report_fatal_error("unsupported architectural extension: " + Name);
5021
5022 FeatureBitset ToggleFeatures = EnableFeature
5023 ? (~Features & Extension.Features)
5024 : ( Features & Extension.Features);
5025 uint64_t Features =
5026 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5027 setAvailableFeatures(Features);
5028 break;
5029 }
5030 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005031 return false;
5032}
5033
Tim Northover8b96c7e2017-05-15 19:42:15 +00005034static SMLoc incrementLoc(SMLoc L, int Offset) {
5035 return SMLoc::getFromPointer(L.getPointer() + Offset);
5036}
5037
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005038/// parseDirectiveCPU
5039/// ::= .cpu id
5040bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005041 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005042
5043 StringRef CPU, ExtensionString;
5044 std::tie(CPU, ExtensionString) =
5045 getParser().parseStringToEndOfStatement().trim().split('+');
5046
Nirav Davee833c6c2016-11-08 18:31:04 +00005047 if (parseToken(AsmToken::EndOfStatement))
5048 return true;
5049
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005050 SmallVector<StringRef, 4> RequestedExtensions;
5051 if (!ExtensionString.empty())
5052 ExtensionString.split(RequestedExtensions, '+');
5053
5054 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5055 // once that is tablegen'ed
5056 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005057 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005058 return false;
5059 }
5060
5061 MCSubtargetInfo &STI = copySTI();
5062 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005063 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005064
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005065 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5066
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005067 FeatureBitset Features = STI.getFeatureBits();
5068 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005069 // Advance source location past '+'.
5070 CurLoc = incrementLoc(CurLoc, 1);
5071
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005072 bool EnableFeature = true;
5073
5074 if (Name.startswith_lower("no")) {
5075 EnableFeature = false;
5076 Name = Name.substr(2);
5077 }
5078
Tim Northover8b96c7e2017-05-15 19:42:15 +00005079 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005080 for (const auto &Extension : ExtensionMap) {
5081 if (Extension.Name != Name)
5082 continue;
5083
5084 if (Extension.Features.none())
5085 report_fatal_error("unsupported architectural extension: " + Name);
5086
5087 FeatureBitset ToggleFeatures = EnableFeature
5088 ? (~Features & Extension.Features)
5089 : ( Features & Extension.Features);
5090 uint64_t Features =
5091 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5092 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005093 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005094
5095 break;
5096 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005097
5098 if (!FoundExtension)
5099 Error(CurLoc, "unsupported architectural extension");
5100
5101 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005102 }
5103 return false;
5104}
5105
Chad Rosierdcd2a302014-10-22 20:35:57 +00005106/// parseDirectiveInst
5107/// ::= .inst opcode [, ...]
5108bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005109 if (getLexer().is(AsmToken::EndOfStatement))
5110 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005111
Nirav Davee833c6c2016-11-08 18:31:04 +00005112 auto parseOp = [&]() -> bool {
5113 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005114 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005115 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5116 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005117 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005118 if (check(!Value, L, "expected constant expression"))
5119 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005120 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005121 return false;
5122 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005123
Nirav Davee833c6c2016-11-08 18:31:04 +00005124 if (parseMany(parseOp))
5125 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005126 return false;
5127}
5128
Tim Northover3b0846e2014-05-24 12:50:23 +00005129// parseDirectiveTLSDescCall:
5130// ::= .tlsdesccall symbol
5131bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5132 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005133 if (check(getParser().parseIdentifier(Name), L,
5134 "expected symbol after directive") ||
5135 parseToken(AsmToken::EndOfStatement))
5136 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005137
Jim Grosbach6f482002015-05-18 18:43:14 +00005138 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005139 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5140 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005141
5142 MCInst Inst;
5143 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005144 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005145
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005146 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005147 return false;
5148}
5149
5150/// ::= .loh <lohName | lohId> label1, ..., labelN
5151/// The number of arguments depends on the loh identifier.
5152bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005153 MCLOHType Kind;
5154 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5155 if (getParser().getTok().isNot(AsmToken::Integer))
5156 return TokError("expected an identifier or a number in directive");
5157 // We successfully get a numeric value for the identifier.
5158 // Check if it is valid.
5159 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005160 if (Id <= -1U && !isValidMCLOHType(Id))
5161 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005162 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005163 } else {
5164 StringRef Name = getTok().getIdentifier();
5165 // We successfully parse an identifier.
5166 // Check if it is a recognized one.
5167 int Id = MCLOHNameToId(Name);
5168
5169 if (Id == -1)
5170 return TokError("invalid identifier in directive");
5171 Kind = (MCLOHType)Id;
5172 }
5173 // Consume the identifier.
5174 Lex();
5175 // Get the number of arguments of this LOH.
5176 int NbArgs = MCLOHIdToNbArgs(Kind);
5177
5178 assert(NbArgs != -1 && "Invalid number of arguments");
5179
5180 SmallVector<MCSymbol *, 3> Args;
5181 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5182 StringRef Name;
5183 if (getParser().parseIdentifier(Name))
5184 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005185 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005186
5187 if (Idx + 1 == NbArgs)
5188 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005189 if (parseToken(AsmToken::Comma,
5190 "unexpected token in '" + Twine(IDVal) + "' directive"))
5191 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005192 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005193 if (parseToken(AsmToken::EndOfStatement,
5194 "unexpected token in '" + Twine(IDVal) + "' directive"))
5195 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005196
5197 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5198 return false;
5199}
5200
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005201/// parseDirectiveLtorg
5202/// ::= .ltorg | .pool
5203bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005204 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5205 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005206 getTargetStreamer().emitCurrentConstantPool();
5207 return false;
5208}
5209
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005210/// parseDirectiveReq
5211/// ::= name .req registername
5212bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005213 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005214 Parser.Lex(); // Eat the '.req' token.
5215 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005216 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005217 unsigned RegNum;
5218 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005219
Sander de Smalen50d87022018-04-19 07:35:08 +00005220 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005221 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005222 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005223 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005224
Sander de Smalen50d87022018-04-19 07:35:08 +00005225 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005226 return true;
5227
Sander de Smalen50d87022018-04-19 07:35:08 +00005228 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005229 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005230 }
5231
Sander de Smalen50d87022018-04-19 07:35:08 +00005232 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005233 StringRef Kind;
5234 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005235 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005236 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005237
Sander de Smalen50d87022018-04-19 07:35:08 +00005238 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005239 return true;
5240
Sander de Smalen50d87022018-04-19 07:35:08 +00005241 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005242 return Error(SRegLoc,
5243 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005244 }
5245
Sander de Smalen50d87022018-04-19 07:35:08 +00005246 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005247 StringRef Kind;
5248 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005249 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005250
Sander de Smalen50d87022018-04-19 07:35:08 +00005251 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005252 return true;
5253
Sander de Smalen50d87022018-04-19 07:35:08 +00005254 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005255 return Error(SRegLoc,
5256 "sve predicate register without type specifier expected");
5257 }
5258
Sander de Smalen50d87022018-04-19 07:35:08 +00005259 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005260 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005261
5262 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005263 if (parseToken(AsmToken::EndOfStatement,
5264 "unexpected input in .req directive"))
5265 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005266
Sander de Smalen8e607342017-11-15 15:44:43 +00005267 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005268 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005269 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5270
Nirav Dave2364748a2016-09-16 18:30:20 +00005271 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005272}
5273
5274/// parseDirectiveUneq
5275/// ::= .unreq registername
5276bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005277 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005278 if (getTok().isNot(AsmToken::Identifier))
5279 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005280 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5281 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005282 if (parseToken(AsmToken::EndOfStatement))
5283 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005284 return false;
5285}
5286
Tim Northover3b0846e2014-05-24 12:50:23 +00005287bool
5288AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5289 AArch64MCExpr::VariantKind &ELFRefKind,
5290 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5291 int64_t &Addend) {
5292 ELFRefKind = AArch64MCExpr::VK_INVALID;
5293 DarwinRefKind = MCSymbolRefExpr::VK_None;
5294 Addend = 0;
5295
5296 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5297 ELFRefKind = AE->getKind();
5298 Expr = AE->getSubExpr();
5299 }
5300
5301 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5302 if (SE) {
5303 // It's a simple symbol reference with no addend.
5304 DarwinRefKind = SE->getKind();
5305 return true;
5306 }
5307
5308 const MCBinaryExpr *BE = dyn_cast<MCBinaryExpr>(Expr);
5309 if (!BE)
5310 return false;
5311
5312 SE = dyn_cast<MCSymbolRefExpr>(BE->getLHS());
5313 if (!SE)
5314 return false;
5315 DarwinRefKind = SE->getKind();
5316
5317 if (BE->getOpcode() != MCBinaryExpr::Add &&
5318 BE->getOpcode() != MCBinaryExpr::Sub)
5319 return false;
5320
Hiroshi Inoue9ff23802018-04-09 04:37:53 +00005321 // See if the addend is a constant, otherwise there's more going
Tim Northover3b0846e2014-05-24 12:50:23 +00005322 // on here than we can deal with.
5323 auto AddendExpr = dyn_cast<MCConstantExpr>(BE->getRHS());
5324 if (!AddendExpr)
5325 return false;
5326
5327 Addend = AddendExpr->getValue();
5328 if (BE->getOpcode() == MCBinaryExpr::Sub)
5329 Addend = -Addend;
5330
5331 // It's some symbol reference + a constant addend, but really
5332 // shouldn't use both Darwin and ELF syntax.
5333 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5334 DarwinRefKind == MCSymbolRefExpr::VK_None;
5335}
5336
5337/// Force static initialization.
5338extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005339 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5340 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5341 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005342}
5343
5344#define GET_REGISTER_MATCHER
5345#define GET_SUBTARGET_FEATURE_NAME
5346#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005347#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005348#include "AArch64GenAsmMatcher.inc"
5349
5350// Define this matcher function after the auto-generated include so we
5351// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005352unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005353 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005354 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005355 // If the kind is a token for a literal immediate, check if our asm
5356 // operand matches. This is for InstAliases which have a fixed-value
5357 // immediate in the syntax.
5358 int64_t ExpectedVal;
5359 switch (Kind) {
5360 default:
5361 return Match_InvalidOperand;
5362 case MCK__35_0:
5363 ExpectedVal = 0;
5364 break;
5365 case MCK__35_1:
5366 ExpectedVal = 1;
5367 break;
5368 case MCK__35_12:
5369 ExpectedVal = 12;
5370 break;
5371 case MCK__35_16:
5372 ExpectedVal = 16;
5373 break;
5374 case MCK__35_2:
5375 ExpectedVal = 2;
5376 break;
5377 case MCK__35_24:
5378 ExpectedVal = 24;
5379 break;
5380 case MCK__35_3:
5381 ExpectedVal = 3;
5382 break;
5383 case MCK__35_32:
5384 ExpectedVal = 32;
5385 break;
5386 case MCK__35_4:
5387 ExpectedVal = 4;
5388 break;
5389 case MCK__35_48:
5390 ExpectedVal = 48;
5391 break;
5392 case MCK__35_6:
5393 ExpectedVal = 6;
5394 break;
5395 case MCK__35_64:
5396 ExpectedVal = 64;
5397 break;
5398 case MCK__35_8:
5399 ExpectedVal = 8;
5400 break;
5401 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005402 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005403 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005404 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005405 if (!CE)
5406 return Match_InvalidOperand;
5407 if (CE->getValue() == ExpectedVal)
5408 return Match_Success;
5409 return Match_InvalidOperand;
5410}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005411
Alex Bradbury58eba092016-11-01 16:32:05 +00005412OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005413AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5414
5415 SMLoc S = getLoc();
5416
5417 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5418 Error(S, "expected register");
5419 return MatchOperand_ParseFail;
5420 }
5421
Sander de Smalen50d87022018-04-19 07:35:08 +00005422 unsigned FirstReg;
5423 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5424 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005425 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005426
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005427 const MCRegisterClass &WRegClass =
5428 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5429 const MCRegisterClass &XRegClass =
5430 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5431
5432 bool isXReg = XRegClass.contains(FirstReg),
5433 isWReg = WRegClass.contains(FirstReg);
5434 if (!isXReg && !isWReg) {
5435 Error(S, "expected first even register of a "
5436 "consecutive same-size even/odd register pair");
5437 return MatchOperand_ParseFail;
5438 }
5439
5440 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5441 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5442
5443 if (FirstEncoding & 0x1) {
5444 Error(S, "expected first even register of a "
5445 "consecutive same-size even/odd register pair");
5446 return MatchOperand_ParseFail;
5447 }
5448
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005449 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005450 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005451 return MatchOperand_ParseFail;
5452 }
5453 // Eat the comma
5454 getParser().Lex();
5455
5456 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005457 unsigned SecondReg;
5458 Res = tryParseScalarRegister(SecondReg);
5459 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005460 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005461
Eugene Zelenko049b0172017-01-06 00:30:53 +00005462 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005463 (isXReg && !XRegClass.contains(SecondReg)) ||
5464 (isWReg && !WRegClass.contains(SecondReg))) {
5465 Error(E,"expected second odd register of a "
5466 "consecutive same-size even/odd register pair");
5467 return MatchOperand_ParseFail;
5468 }
Joel Jones504bf332016-10-24 13:37:13 +00005469
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005470 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005471 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005472 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5473 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5474 } else {
5475 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5476 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5477 }
5478
Florian Hahnc4422242017-11-07 13:07:50 +00005479 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5480 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005481
5482 return MatchOperand_Success;
5483}
Florian Hahn91f11e52017-11-07 16:45:48 +00005484
Sander de Smaleneb896b12018-04-25 09:26:47 +00005485template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005486OperandMatchResultTy
5487AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005488 const SMLoc S = getLoc();
5489 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005490 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005491 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005492
Sander de Smalen8e607342017-11-15 15:44:43 +00005493 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005494 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005495
5496 if (Res != MatchOperand_Success)
5497 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005498
5499 if (ParseSuffix && Kind.empty())
5500 return MatchOperand_NoMatch;
5501
Sander de Smalen73937b72018-04-11 07:36:10 +00005502 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5503 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005504 return MatchOperand_NoMatch;
5505
Sander de Smalen73937b72018-04-11 07:36:10 +00005506 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005507
5508 // No shift/extend is the default.
5509 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5510 Operands.push_back(AArch64Operand::CreateVectorReg(
5511 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5512
Sander de Smalenc33d6682018-06-04 06:40:55 +00005513 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5514 if (Res == MatchOperand_ParseFail)
5515 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005516 return MatchOperand_Success;
5517 }
5518
5519 // Eat the comma
5520 getParser().Lex();
5521
5522 // Match the shift
5523 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5524 Res = tryParseOptionalShiftExtend(ExtOpnd);
5525 if (Res != MatchOperand_Success)
5526 return Res;
5527
5528 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005529 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005530 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5531 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5532 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005533
5534 return MatchOperand_Success;
5535}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005536
5537OperandMatchResultTy
5538AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5539 MCAsmParser &Parser = getParser();
5540
5541 SMLoc SS = getLoc();
5542 const AsmToken &TokE = Parser.getTok();
5543 bool IsHash = TokE.is(AsmToken::Hash);
5544
5545 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5546 return MatchOperand_NoMatch;
5547
5548 int64_t Pattern;
5549 if (IsHash) {
5550 Parser.Lex(); // Eat hash
5551
5552 // Parse the immediate operand.
5553 const MCExpr *ImmVal;
5554 SS = getLoc();
5555 if (Parser.parseExpression(ImmVal))
5556 return MatchOperand_ParseFail;
5557
5558 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5559 if (!MCE)
5560 return MatchOperand_ParseFail;
5561
5562 Pattern = MCE->getValue();
5563 } else {
5564 // Parse the pattern
5565 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5566 if (!Pat)
5567 return MatchOperand_NoMatch;
5568
5569 Parser.Lex();
5570 Pattern = Pat->Encoding;
5571 assert(Pattern >= 0 && Pattern < 32);
5572 }
5573
5574 Operands.push_back(
5575 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5576 SS, getLoc(), getContext()));
5577
5578 return MatchOperand_Success;
5579}