blob: 2c78818963c80869f40571e36988e25c650463a1 [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"
David Green85d6a552018-09-18 09:44:53 +000042#include "llvm/MC/MCValue.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000043#include "llvm/Support/Casting.h"
44#include "llvm/Support/Compiler.h"
Benjamin Kramer1f8930e2014-07-25 11:42:14 +000045#include "llvm/Support/ErrorHandling.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000046#include "llvm/Support/MathExtras.h"
47#include "llvm/Support/SMLoc.h"
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +000048#include "llvm/Support/TargetParser.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000049#include "llvm/Support/TargetRegistry.h"
Tim Northover3b0846e2014-05-24 12:50:23 +000050#include "llvm/Support/raw_ostream.h"
Eugene Zelenko049b0172017-01-06 00:30:53 +000051#include <cassert>
52#include <cctype>
53#include <cstdint>
Tim Northover3b0846e2014-05-24 12:50:23 +000054#include <cstdio>
Eugene Zelenko049b0172017-01-06 00:30:53 +000055#include <string>
56#include <tuple>
57#include <utility>
58#include <vector>
59
Tim Northover3b0846e2014-05-24 12:50:23 +000060using namespace llvm;
61
62namespace {
63
Sander de Smalencd6be962017-12-20 11:02:42 +000064enum class RegKind {
65 Scalar,
66 NeonVector,
67 SVEDataVector,
68 SVEPredicateVector
69};
Florian Hahnc4422242017-11-07 13:07:50 +000070
Sander de Smalen0325e302018-07-02 07:34:52 +000071enum RegConstraintEqualityTy {
72 EqualsReg,
73 EqualsSuperReg,
74 EqualsSubReg
75};
76
Tim Northover3b0846e2014-05-24 12:50:23 +000077class AArch64AsmParser : public MCTargetAsmParser {
Tim Northover3b0846e2014-05-24 12:50:23 +000078private:
79 StringRef Mnemonic; ///< Instruction mnemonic.
Tim Northover3b0846e2014-05-24 12:50:23 +000080
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000081 // Map of register aliases registers via the .req directive.
Florian Hahnc4422242017-11-07 13:07:50 +000082 StringMap<std::pair<RegKind, unsigned>> RegisterReqs;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +000083
Sander de Smalen9b333092018-07-30 15:42:46 +000084 class PrefixInfo {
85 public:
86 static PrefixInfo CreateFromInst(const MCInst &Inst, uint64_t TSFlags) {
87 PrefixInfo Prefix;
88 switch (Inst.getOpcode()) {
89 case AArch64::MOVPRFX_ZZ:
90 Prefix.Active = true;
91 Prefix.Dst = Inst.getOperand(0).getReg();
92 break;
93 case AArch64::MOVPRFX_ZPmZ_B:
94 case AArch64::MOVPRFX_ZPmZ_H:
95 case AArch64::MOVPRFX_ZPmZ_S:
96 case AArch64::MOVPRFX_ZPmZ_D:
97 Prefix.Active = true;
98 Prefix.Predicated = true;
99 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
100 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
101 "No destructive element size set for movprfx");
102 Prefix.Dst = Inst.getOperand(0).getReg();
103 Prefix.Pg = Inst.getOperand(2).getReg();
104 break;
105 case AArch64::MOVPRFX_ZPzZ_B:
106 case AArch64::MOVPRFX_ZPzZ_H:
107 case AArch64::MOVPRFX_ZPzZ_S:
108 case AArch64::MOVPRFX_ZPzZ_D:
109 Prefix.Active = true;
110 Prefix.Predicated = true;
111 Prefix.ElementSize = TSFlags & AArch64::ElementSizeMask;
112 assert(Prefix.ElementSize != AArch64::ElementSizeNone &&
113 "No destructive element size set for movprfx");
114 Prefix.Dst = Inst.getOperand(0).getReg();
115 Prefix.Pg = Inst.getOperand(1).getReg();
116 break;
117 default:
118 break;
119 }
120
121 return Prefix;
122 }
123
124 PrefixInfo() : Active(false), Predicated(false) {}
125 bool isActive() const { return Active; }
126 bool isPredicated() const { return Predicated; }
127 unsigned getElementSize() const {
128 assert(Predicated);
129 return ElementSize;
130 }
131 unsigned getDstReg() const { return Dst; }
132 unsigned getPgReg() const {
133 assert(Predicated);
134 return Pg;
135 }
136
137 private:
138 bool Active;
139 bool Predicated;
140 unsigned ElementSize;
141 unsigned Dst;
142 unsigned Pg;
143 } NextPrefix;
144
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000145 AArch64TargetStreamer &getTargetStreamer() {
146 MCTargetStreamer &TS = *getParser().getStreamer().getTargetStreamer();
147 return static_cast<AArch64TargetStreamer &>(TS);
148 }
149
Rafael Espindola961d4692014-11-11 05:18:41 +0000150 SMLoc getLoc() const { return getParser().getTok().getLoc(); }
Tim Northover3b0846e2014-05-24 12:50:23 +0000151
152 bool parseSysAlias(StringRef Name, SMLoc NameLoc, OperandVector &Operands);
Sjoerd Meijer69bccf92017-03-03 08:12:47 +0000153 void createSysAlias(uint16_t Encoding, OperandVector &Operands, SMLoc S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000154 AArch64CC::CondCode parseCondCodeString(StringRef Cond);
155 bool parseCondCode(OperandVector &Operands, bool invertCondCode);
Florian Hahnc4422242017-11-07 13:07:50 +0000156 unsigned matchRegisterNameAlias(StringRef Name, RegKind Kind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000157 bool parseRegister(OperandVector &Operands);
158 bool parseSymbolicImmVal(const MCExpr *&ImmVal);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000159 bool parseNeonVectorList(OperandVector &Operands);
Sander de Smalen18ac8f92018-06-15 15:47:44 +0000160 bool parseOptionalMulOperand(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000161 bool parseOperand(OperandVector &Operands, bool isCondCode,
162 bool invertCondCode);
163
Sander de Smalen0325e302018-07-02 07:34:52 +0000164 bool showMatchError(SMLoc Loc, unsigned ErrCode, uint64_t ErrorInfo,
165 OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000166
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +0000167 bool parseDirectiveArch(SMLoc L);
Saleem Abdulrasool85b436392016-04-02 19:29:52 +0000168 bool parseDirectiveCPU(SMLoc L);
Chad Rosierdcd2a302014-10-22 20:35:57 +0000169 bool parseDirectiveInst(SMLoc L);
170
Tim Northover3b0846e2014-05-24 12:50:23 +0000171 bool parseDirectiveTLSDescCall(SMLoc L);
172
173 bool parseDirectiveLOH(StringRef LOH, SMLoc L);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +0000174 bool parseDirectiveLtorg(SMLoc L);
Tim Northover3b0846e2014-05-24 12:50:23 +0000175
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +0000176 bool parseDirectiveReq(StringRef Name, SMLoc L);
177 bool parseDirectiveUnreq(SMLoc L);
178
Sander de Smalen9b333092018-07-30 15:42:46 +0000179 bool validateInstruction(MCInst &Inst, SMLoc &IDLoc,
180 SmallVectorImpl<SMLoc> &Loc);
Tim Northover3b0846e2014-05-24 12:50:23 +0000181 bool MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
182 OperandVector &Operands, MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +0000183 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +0000184 bool MatchingInlineAsm) override;
185/// @name Auto-generated Match Functions
186/// {
187
188#define GET_ASSEMBLER_HEADER
189#include "AArch64GenAsmMatcher.inc"
190
191 /// }
192
Sander de Smalen50d87022018-04-19 07:35:08 +0000193 OperandMatchResultTy tryParseScalarRegister(unsigned &Reg);
194 OperandMatchResultTy tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +0000195 RegKind MatchKind);
Tim Northover3b0846e2014-05-24 12:50:23 +0000196 OperandMatchResultTy tryParseOptionalShiftExtend(OperandVector &Operands);
197 OperandMatchResultTy tryParseBarrierOperand(OperandVector &Operands);
198 OperandMatchResultTy tryParseMRSSystemRegister(OperandVector &Operands);
199 OperandMatchResultTy tryParseSysReg(OperandVector &Operands);
200 OperandMatchResultTy tryParseSysCROperand(OperandVector &Operands);
Sander de Smalen93380372018-05-14 11:54:41 +0000201 template <bool IsSVEPrefetch = false>
Tim Northover3b0846e2014-05-24 12:50:23 +0000202 OperandMatchResultTy tryParsePrefetch(OperandVector &Operands);
Oliver Stannarda34e4702015-12-01 10:48:51 +0000203 OperandMatchResultTy tryParsePSBHint(OperandVector &Operands);
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000204 OperandMatchResultTy tryParseBTIHint(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000205 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
206 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000207 template<bool AddFPZeroAsLiteral>
Tim Northover3b0846e2014-05-24 12:50:23 +0000208 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000209 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000210 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000211 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000212 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000213 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen0325e302018-07-02 07:34:52 +0000214 template <bool ParseShiftExtend,
215 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
Sander de Smalen149916d2018-04-20 07:24:20 +0000216 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000217 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000218 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000219 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000220 template <RegKind VectorKind>
221 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
222 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000223 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000224
225public:
226 enum AArch64MatchResultTy {
227 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
228#define GET_OPERAND_DIAGNOSTIC_TYPES
229#include "AArch64GenAsmMatcher.inc"
230 };
Joel Jones504bf332016-10-24 13:37:13 +0000231 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000232
Akira Hatanakab11ef082015-11-14 06:35:56 +0000233 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000234 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000235 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000236 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000237 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000238 MCStreamer &S = getParser().getStreamer();
239 if (S.getTargetStreamer() == nullptr)
240 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000241
Alex Bradbury0a59f182018-05-23 11:17:20 +0000242 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
243 // directives as they have the same form and semantics:
244 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
245 Parser.addAliasForDirective(".hword", ".2byte");
246 Parser.addAliasForDirective(".word", ".4byte");
247 Parser.addAliasForDirective(".xword", ".8byte");
248
Tim Northover3b0846e2014-05-24 12:50:23 +0000249 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000250 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000251 }
252
Sander de Smalen0325e302018-07-02 07:34:52 +0000253 bool regsEqual(const MCParsedAsmOperand &Op1,
254 const MCParsedAsmOperand &Op2) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000255 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
256 SMLoc NameLoc, OperandVector &Operands) override;
257 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
258 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000259 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000260 unsigned Kind) override;
261
262 static bool classifySymbolRef(const MCExpr *Expr,
263 AArch64MCExpr::VariantKind &ELFRefKind,
264 MCSymbolRefExpr::VariantKind &DarwinRefKind,
265 int64_t &Addend);
266};
Tim Northover3b0846e2014-05-24 12:50:23 +0000267
268/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
269/// instruction.
270class AArch64Operand : public MCParsedAsmOperand {
271private:
272 enum KindTy {
273 k_Immediate,
274 k_ShiftedImm,
275 k_CondCode,
276 k_Register,
277 k_VectorList,
278 k_VectorIndex,
279 k_Token,
280 k_SysReg,
281 k_SysCR,
282 k_Prefetch,
283 k_ShiftExtend,
284 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000285 k_Barrier,
286 k_PSBHint,
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000287 k_BTIHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000288 } Kind;
289
290 SMLoc StartLoc, EndLoc;
291
292 struct TokOp {
293 const char *Data;
294 unsigned Length;
295 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
296 };
297
Sander de Smalen149916d2018-04-20 07:24:20 +0000298 // Separate shift/extend operand.
299 struct ShiftExtendOp {
300 AArch64_AM::ShiftExtendType Type;
301 unsigned Amount;
302 bool HasExplicitAmount;
303 };
304
Tim Northover3b0846e2014-05-24 12:50:23 +0000305 struct RegOp {
306 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000307 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000308 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000309
Sander de Smalen0325e302018-07-02 07:34:52 +0000310 // The register may be allowed as a different register class,
311 // e.g. for GPR64as32 or GPR32as64.
312 RegConstraintEqualityTy EqualityTy;
313
Sander de Smalen149916d2018-04-20 07:24:20 +0000314 // In some cases the shift/extend needs to be explicitly parsed together
315 // with the register, rather than as a separate operand. This is needed
316 // for addressing modes where the instruction as a whole dictates the
317 // scaling/extend, rather than specific bits in the instruction.
318 // By parsing them as a single operand, we avoid the need to pass an
319 // extra operand in all CodeGen patterns (because all operands need to
320 // have an associated value), and we avoid the need to update TableGen to
321 // accept operands that have no associated bits in the instruction.
322 //
323 // An added benefit of parsing them together is that the assembler
324 // can give a sensible diagnostic if the scaling is not correct.
325 //
326 // The default is 'lsl #0' (HasExplicitAmount = false) if no
327 // ShiftExtend is specified.
328 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000329 };
330
331 struct VectorListOp {
332 unsigned RegNum;
333 unsigned Count;
334 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000335 unsigned ElementWidth;
336 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000337 };
338
339 struct VectorIndexOp {
340 unsigned Val;
341 };
342
343 struct ImmOp {
344 const MCExpr *Val;
345 };
346
347 struct ShiftedImmOp {
348 const MCExpr *Val;
349 unsigned ShiftAmount;
350 };
351
352 struct CondCodeOp {
353 AArch64CC::CondCode Code;
354 };
355
356 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000357 uint64_t Val; // APFloat value bitcasted to uint64_t.
358 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000359 };
360
361 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000362 const char *Data;
363 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000364 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000365 };
366
367 struct SysRegOp {
368 const char *Data;
369 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000370 uint32_t MRSReg;
371 uint32_t MSRReg;
372 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000373 };
374
375 struct SysCRImmOp {
376 unsigned Val;
377 };
378
379 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000380 const char *Data;
381 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000382 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000383 };
384
Oliver Stannarda34e4702015-12-01 10:48:51 +0000385 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000386 const char *Data;
387 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000388 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000389 };
390
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000391 struct BTIHintOp {
392 const char *Data;
393 unsigned Length;
394 unsigned Val;
395 };
396
Tim Northover3b0846e2014-05-24 12:50:23 +0000397 struct ExtendOp {
398 unsigned Val;
399 };
400
401 union {
402 struct TokOp Tok;
403 struct RegOp Reg;
404 struct VectorListOp VectorList;
405 struct VectorIndexOp VectorIndex;
406 struct ImmOp Imm;
407 struct ShiftedImmOp ShiftedImm;
408 struct CondCodeOp CondCode;
409 struct FPImmOp FPImm;
410 struct BarrierOp Barrier;
411 struct SysRegOp SysReg;
412 struct SysCRImmOp SysCRImm;
413 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000414 struct PSBHintOp PSBHint;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000415 struct BTIHintOp BTIHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000416 struct ShiftExtendOp ShiftExtend;
417 };
418
419 // Keep the MCContext around as the MCExprs may need manipulated during
420 // the add<>Operands() calls.
421 MCContext &Ctx;
422
David Blaikie960ea3f2014-06-08 16:18:35 +0000423public:
David Blaikie9f380a32015-03-16 18:06:57 +0000424 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000425
Tim Northover3b0846e2014-05-24 12:50:23 +0000426 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
427 Kind = o.Kind;
428 StartLoc = o.StartLoc;
429 EndLoc = o.EndLoc;
430 switch (Kind) {
431 case k_Token:
432 Tok = o.Tok;
433 break;
434 case k_Immediate:
435 Imm = o.Imm;
436 break;
437 case k_ShiftedImm:
438 ShiftedImm = o.ShiftedImm;
439 break;
440 case k_CondCode:
441 CondCode = o.CondCode;
442 break;
443 case k_FPImm:
444 FPImm = o.FPImm;
445 break;
446 case k_Barrier:
447 Barrier = o.Barrier;
448 break;
449 case k_Register:
450 Reg = o.Reg;
451 break;
452 case k_VectorList:
453 VectorList = o.VectorList;
454 break;
455 case k_VectorIndex:
456 VectorIndex = o.VectorIndex;
457 break;
458 case k_SysReg:
459 SysReg = o.SysReg;
460 break;
461 case k_SysCR:
462 SysCRImm = o.SysCRImm;
463 break;
464 case k_Prefetch:
465 Prefetch = o.Prefetch;
466 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000467 case k_PSBHint:
468 PSBHint = o.PSBHint;
469 break;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000470 case k_BTIHint:
471 BTIHint = o.BTIHint;
472 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000473 case k_ShiftExtend:
474 ShiftExtend = o.ShiftExtend;
475 break;
476 }
477 }
478
479 /// getStartLoc - Get the location of the first token of this operand.
480 SMLoc getStartLoc() const override { return StartLoc; }
481 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000482 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000483
484 StringRef getToken() const {
485 assert(Kind == k_Token && "Invalid access!");
486 return StringRef(Tok.Data, Tok.Length);
487 }
488
489 bool isTokenSuffix() const {
490 assert(Kind == k_Token && "Invalid access!");
491 return Tok.IsSuffix;
492 }
493
494 const MCExpr *getImm() const {
495 assert(Kind == k_Immediate && "Invalid access!");
496 return Imm.Val;
497 }
498
499 const MCExpr *getShiftedImmVal() const {
500 assert(Kind == k_ShiftedImm && "Invalid access!");
501 return ShiftedImm.Val;
502 }
503
504 unsigned getShiftedImmShift() const {
505 assert(Kind == k_ShiftedImm && "Invalid access!");
506 return ShiftedImm.ShiftAmount;
507 }
508
509 AArch64CC::CondCode getCondCode() const {
510 assert(Kind == k_CondCode && "Invalid access!");
511 return CondCode.Code;
512 }
513
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000514 APFloat getFPImm() const {
515 assert (Kind == k_FPImm && "Invalid access!");
516 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
517 }
518
519 bool getFPImmIsExact() const {
520 assert (Kind == k_FPImm && "Invalid access!");
521 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000522 }
523
524 unsigned getBarrier() const {
525 assert(Kind == k_Barrier && "Invalid access!");
526 return Barrier.Val;
527 }
528
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000529 StringRef getBarrierName() const {
530 assert(Kind == k_Barrier && "Invalid access!");
531 return StringRef(Barrier.Data, Barrier.Length);
532 }
533
Tim Northover3b0846e2014-05-24 12:50:23 +0000534 unsigned getReg() const override {
535 assert(Kind == k_Register && "Invalid access!");
536 return Reg.RegNum;
537 }
538
Sander de Smalen0325e302018-07-02 07:34:52 +0000539 RegConstraintEqualityTy getRegEqualityTy() const {
540 assert(Kind == k_Register && "Invalid access!");
541 return Reg.EqualityTy;
542 }
543
Tim Northover3b0846e2014-05-24 12:50:23 +0000544 unsigned getVectorListStart() const {
545 assert(Kind == k_VectorList && "Invalid access!");
546 return VectorList.RegNum;
547 }
548
549 unsigned getVectorListCount() const {
550 assert(Kind == k_VectorList && "Invalid access!");
551 return VectorList.Count;
552 }
553
554 unsigned getVectorIndex() const {
555 assert(Kind == k_VectorIndex && "Invalid access!");
556 return VectorIndex.Val;
557 }
558
559 StringRef getSysReg() const {
560 assert(Kind == k_SysReg && "Invalid access!");
561 return StringRef(SysReg.Data, SysReg.Length);
562 }
563
Tim Northover3b0846e2014-05-24 12:50:23 +0000564 unsigned getSysCR() const {
565 assert(Kind == k_SysCR && "Invalid access!");
566 return SysCRImm.Val;
567 }
568
569 unsigned getPrefetch() const {
570 assert(Kind == k_Prefetch && "Invalid access!");
571 return Prefetch.Val;
572 }
573
Oliver Stannarda34e4702015-12-01 10:48:51 +0000574 unsigned getPSBHint() const {
575 assert(Kind == k_PSBHint && "Invalid access!");
576 return PSBHint.Val;
577 }
578
579 StringRef getPSBHintName() const {
580 assert(Kind == k_PSBHint && "Invalid access!");
581 return StringRef(PSBHint.Data, PSBHint.Length);
582 }
583
Oliver Stannarda9a5eee2018-09-27 14:54:33 +0000584 unsigned getBTIHint() const {
585 assert(Kind == k_BTIHint && "Invalid access!");
586 return BTIHint.Val;
587 }
588
589 StringRef getBTIHintName() const {
590 assert(Kind == k_BTIHint && "Invalid access!");
591 return StringRef(BTIHint.Data, BTIHint.Length);
592 }
593
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000594 StringRef getPrefetchName() const {
595 assert(Kind == k_Prefetch && "Invalid access!");
596 return StringRef(Prefetch.Data, Prefetch.Length);
597 }
598
Tim Northover3b0846e2014-05-24 12:50:23 +0000599 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000600 if (Kind == k_ShiftExtend)
601 return ShiftExtend.Type;
602 if (Kind == k_Register)
603 return Reg.ShiftExtend.Type;
604 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000605 }
606
607 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000608 if (Kind == k_ShiftExtend)
609 return ShiftExtend.Amount;
610 if (Kind == k_Register)
611 return Reg.ShiftExtend.Amount;
612 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000613 }
614
615 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000616 if (Kind == k_ShiftExtend)
617 return ShiftExtend.HasExplicitAmount;
618 if (Kind == k_Register)
619 return Reg.ShiftExtend.HasExplicitAmount;
620 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000621 }
622
623 bool isImm() const override { return Kind == k_Immediate; }
624 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000625
Sjoerd Meijera3dad802018-07-06 12:32:33 +0000626 bool isUImm6() const {
627 if (!isImm())
628 return false;
629 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
630 if (!MCE)
631 return false;
632 int64_t Val = MCE->getValue();
633 return (Val >= 0 && Val < 64);
634 }
635
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000636 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
637
Sander de Smalen50ded902018-04-29 17:33:38 +0000638 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
639 return isImmScaled<Bits, Scale>(true);
640 }
641
642 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
643 return isImmScaled<Bits, Scale>(false);
644 }
645
Sander de Smalenfe17a782018-04-26 12:54:42 +0000646 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000647 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000648 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000649 return DiagnosticPredicateTy::NoMatch;
650
Tim Northover3b0846e2014-05-24 12:50:23 +0000651 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
652 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000653 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000654
Sander de Smalen50ded902018-04-29 17:33:38 +0000655 int64_t MinVal, MaxVal;
656 if (Signed) {
657 int64_t Shift = Bits - 1;
658 MinVal = (int64_t(1) << Shift) * -Scale;
659 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
660 } else {
661 MinVal = 0;
662 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
663 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000664
Tim Northover3b0846e2014-05-24 12:50:23 +0000665 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000666 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
667 return DiagnosticPredicateTy::Match;
668
669 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000670 }
671
Sander de Smalen0325e302018-07-02 07:34:52 +0000672 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000673 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000674 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000675 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
676 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000677 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000678 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000679 if (Val >= 0 && Val < 32)
680 return DiagnosticPredicateTy::Match;
681 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000682 }
683
David Green85d6a552018-09-18 09:44:53 +0000684 bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000685 AArch64MCExpr::VariantKind ELFRefKind;
686 MCSymbolRefExpr::VariantKind DarwinRefKind;
687 int64_t Addend;
688 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
689 Addend)) {
690 // If we don't understand the expression, assume the best and
691 // let the fixup and relocation code deal with it.
692 return true;
693 }
694
695 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
696 ELFRefKind == AArch64MCExpr::VK_LO12 ||
697 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
698 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
699 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
700 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
701 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
702 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000703 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
704 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
705 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000706 // Note that we don't range-check the addend. It's adjusted modulo page
707 // size when converted, so there is no "out of range" condition when using
708 // @pageoff.
David Green85d6a552018-09-18 09:44:53 +0000709 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000710 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
711 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
712 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
713 return Addend == 0;
714 }
715
716 return false;
717 }
718
719 template <int Scale> bool isUImm12Offset() const {
720 if (!isImm())
721 return false;
722
723 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
724 if (!MCE)
David Green85d6a552018-09-18 09:44:53 +0000725 return isSymbolicUImm12Offset(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +0000726
727 int64_t Val = MCE->getValue();
728 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
729 }
730
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000731 template <int N, int M>
732 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000733 if (!isImm())
734 return false;
735 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
736 if (!MCE)
737 return false;
738 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000739 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000740 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000741
Sander de Smalena1c259c2018-01-29 13:05:38 +0000742 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
743 // a logical immediate can always be represented when inverted.
744 template <typename T>
745 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000746 if (!isImm())
747 return false;
748 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
749 if (!MCE)
750 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000751
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000752 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000753 int64_t SVal = typename std::make_signed<T>::type(Val);
754 int64_t UVal = typename std::make_unsigned<T>::type(Val);
755 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000756 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000757
Sander de Smalena1c259c2018-01-29 13:05:38 +0000758 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000759 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000760
Tim Northover3b0846e2014-05-24 12:50:23 +0000761 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000762
Sander de Smalen62770792018-05-25 09:47:52 +0000763 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
764 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
765 /// immediate that can be shifted by 'Shift'.
766 template <unsigned Width>
767 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
768 if (isShiftedImm() && Width == getShiftedImmShift())
769 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
770 return std::make_pair(CE->getValue(), Width);
771
772 if (isImm())
773 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
774 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000775 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000776 return std::make_pair(Val >> Width, Width);
777 else
778 return std::make_pair(Val, 0u);
779 }
780
781 return {};
782 }
783
Tim Northover3b0846e2014-05-24 12:50:23 +0000784 bool isAddSubImm() const {
785 if (!isShiftedImm() && !isImm())
786 return false;
787
788 const MCExpr *Expr;
789
790 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
791 if (isShiftedImm()) {
792 unsigned Shift = ShiftedImm.ShiftAmount;
793 Expr = ShiftedImm.Val;
794 if (Shift != 0 && Shift != 12)
795 return false;
796 } else {
797 Expr = getImm();
798 }
799
800 AArch64MCExpr::VariantKind ELFRefKind;
801 MCSymbolRefExpr::VariantKind DarwinRefKind;
802 int64_t Addend;
803 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
804 DarwinRefKind, Addend)) {
805 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
806 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
807 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
808 || ELFRefKind == AArch64MCExpr::VK_LO12
809 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
810 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
811 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
812 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
813 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
814 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000815 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
816 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
817 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000818 }
819
Sander de Smalen98686c62018-05-29 10:39:49 +0000820 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000821 if (auto ShiftedVal = getShiftedVal<12>())
822 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000823
824 // If it's an expression, we hope for the best and let the fixup/relocation
825 // code deal with it.
826 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000827 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000828
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000829 bool isAddSubImmNeg() const {
830 if (!isShiftedImm() && !isImm())
831 return false;
832
Sander de Smalen98686c62018-05-29 10:39:49 +0000833 // Otherwise it should be a real negative immediate in range.
834 if (auto ShiftedVal = getShiftedVal<12>())
835 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000836
Sander de Smalen98686c62018-05-29 10:39:49 +0000837 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000838 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000839
Sander de Smalen62770792018-05-25 09:47:52 +0000840 // Signed value in the range -128 to +127. For element widths of
841 // 16 bits or higher it may also be a signed multiple of 256 in the
842 // range -32768 to +32512.
843 // For element-width of 8 bits a range of -128 to 255 is accepted,
844 // since a copy of a byte can be either signed/unsigned.
845 template <typename T>
846 DiagnosticPredicate isSVECpyImm() const {
847 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
848 return DiagnosticPredicateTy::NoMatch;
849
850 bool IsByte =
851 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
852 if (auto ShiftedImm = getShiftedVal<8>())
853 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000854 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
855 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000856 return DiagnosticPredicateTy::Match;
857
858 return DiagnosticPredicateTy::NearMatch;
859 }
860
Sander de Smalen98686c62018-05-29 10:39:49 +0000861 // Unsigned value in the range 0 to 255. For element widths of
862 // 16 bits or higher it may also be a signed multiple of 256 in the
863 // range 0 to 65280.
864 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
865 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
866 return DiagnosticPredicateTy::NoMatch;
867
868 bool IsByte =
869 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
870 if (auto ShiftedImm = getShiftedVal<8>())
871 if (!(IsByte && ShiftedImm->second) &&
872 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
873 << ShiftedImm->second))
874 return DiagnosticPredicateTy::Match;
875
876 return DiagnosticPredicateTy::NearMatch;
877 }
878
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000879 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
880 if (isLogicalImm<T>() && !isSVECpyImm<T>())
881 return DiagnosticPredicateTy::Match;
882 return DiagnosticPredicateTy::NoMatch;
883 }
884
Tim Northover3b0846e2014-05-24 12:50:23 +0000885 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000886
Tim Northover3b0846e2014-05-24 12:50:23 +0000887 bool isSIMDImmType10() const {
888 if (!isImm())
889 return false;
890 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
891 if (!MCE)
892 return false;
893 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
894 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000895
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000896 template<int N>
897 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000898 if (!isImm())
899 return false;
900 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
901 if (!MCE)
902 return true;
903 int64_t Val = MCE->getValue();
904 if (Val & 0x3)
905 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000906 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
907 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000908 }
909
910 bool
911 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
912 if (!isImm())
913 return false;
914
915 AArch64MCExpr::VariantKind ELFRefKind;
916 MCSymbolRefExpr::VariantKind DarwinRefKind;
917 int64_t Addend;
918 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
919 DarwinRefKind, Addend)) {
920 return false;
921 }
922 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
923 return false;
924
925 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
926 if (ELFRefKind == AllowedModifiers[i])
David Green85d6a552018-09-18 09:44:53 +0000927 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000928 }
929
930 return false;
931 }
932
933 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000934 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000935 }
936
937 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000938 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
939 AArch64MCExpr::VK_TPREL_G2,
940 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000941 }
942
943 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000944 return isMovWSymbol({
945 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000946 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
947 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000948 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000949 }
950
951 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000952 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
953 AArch64MCExpr::VK_TPREL_G0,
954 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000955 }
956
957 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000958 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000959 }
960
961 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000962 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000963 }
964
965 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000966 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
967 AArch64MCExpr::VK_TPREL_G1_NC,
968 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000969 }
970
971 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000972 return isMovWSymbol(
973 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
974 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000975 }
976
977 template<int RegWidth, int Shift>
978 bool isMOVZMovAlias() const {
979 if (!isImm()) return false;
980
981 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
982 if (!CE) return false;
983 uint64_t Value = CE->getValue();
984
Tim Northoverdaa1c012016-06-16 01:42:25 +0000985 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000986 }
987
988 template<int RegWidth, int Shift>
989 bool isMOVNMovAlias() const {
990 if (!isImm()) return false;
991
992 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
993 if (!CE) return false;
994 uint64_t Value = CE->getValue();
995
Tim Northoverdaa1c012016-06-16 01:42:25 +0000996 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000997 }
998
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000999 bool isFPImm() const {
1000 return Kind == k_FPImm &&
1001 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
1002 }
1003
Tim Northover3b0846e2014-05-24 12:50:23 +00001004 bool isBarrier() const { return Kind == k_Barrier; }
1005 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001006
Tim Northover3b0846e2014-05-24 12:50:23 +00001007 bool isMRSSystemRegister() const {
1008 if (!isSysReg()) return false;
1009
Tim Northover7cd58932015-01-22 17:23:04 +00001010 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001011 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001012
Tim Northover3b0846e2014-05-24 12:50:23 +00001013 bool isMSRSystemRegister() const {
1014 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001015 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001016 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001017
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001018 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001019 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +00001020 return (SysReg.PStateField == AArch64PState::PAN ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +00001021 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard8459d342018-09-27 14:05:46 +00001022 SysReg.PStateField == AArch64PState::UAO ||
1023 SysReg.PStateField == AArch64PState::SSBS);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001024 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001025
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001026 bool isSystemPStateFieldWithImm0_15() const {
1027 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001028 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001029 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001030
Florian Hahnc4422242017-11-07 13:07:50 +00001031 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00001032 return Kind == k_Register;
1033 }
1034
1035 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001036 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1037 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001038
Florian Hahnc4422242017-11-07 13:07:50 +00001039 bool isNeonVectorReg() const {
1040 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1041 }
1042
1043 bool isNeonVectorRegLo() const {
1044 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001045 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1046 Reg.RegNum);
1047 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001048
Sander de Smalencd6be962017-12-20 11:02:42 +00001049 template <unsigned Class> bool isSVEVectorReg() const {
1050 RegKind RK;
1051 switch (Class) {
1052 case AArch64::ZPRRegClassID:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00001053 case AArch64::ZPR_3bRegClassID:
1054 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001055 RK = RegKind::SVEDataVector;
1056 break;
1057 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +00001058 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001059 RK = RegKind::SVEPredicateVector;
1060 break;
1061 default:
1062 llvm_unreachable("Unsupport register class");
1063 }
1064
1065 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +00001066 AArch64MCRegisterClasses[Class].contains(getReg());
1067 }
1068
Sander de Smalenfd54a782018-06-04 07:07:35 +00001069 template <unsigned Class> bool isFPRasZPR() const {
1070 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1071 AArch64MCRegisterClasses[Class].contains(getReg());
1072 }
1073
Sander de Smalencd6be962017-12-20 11:02:42 +00001074 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +00001075 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1076 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1077 return DiagnosticPredicateTy::NoMatch;
1078
1079 if (isSVEVectorReg<Class>() &&
1080 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1081 return DiagnosticPredicateTy::Match;
1082
1083 return DiagnosticPredicateTy::NearMatch;
1084 }
1085
1086 template <int ElementWidth, unsigned Class>
1087 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1088 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1089 return DiagnosticPredicateTy::NoMatch;
1090
1091 if (isSVEVectorReg<Class>() &&
1092 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1093 return DiagnosticPredicateTy::Match;
1094
1095 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00001096 }
1097
Sander de Smaleneb896b12018-04-25 09:26:47 +00001098 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001099 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1100 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001101 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1102 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1103 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001104 return DiagnosticPredicateTy::NoMatch;
1105
Sander de Smalen5861c262018-04-30 07:24:38 +00001106 // Give a more specific diagnostic when the user has explicitly typed in
1107 // a shift-amount that does not match what is expected, but for which
1108 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1109 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1110 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1111 ShiftExtendTy == AArch64_AM::SXTW) &&
1112 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1113 return DiagnosticPredicateTy::NoMatch;
1114
1115 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001116 return DiagnosticPredicateTy::Match;
1117
1118 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001119 }
1120
Tim Northover3b0846e2014-05-24 12:50:23 +00001121 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001122 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001123 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1124 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001125
Sander de Smalen0325e302018-07-02 07:34:52 +00001126 bool isGPR64as32() const {
1127 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1128 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1129 }
1130
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001131 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001132 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001133 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1134 Reg.RegNum);
1135 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001136
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001137 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001138 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001139 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1140 Reg.RegNum);
1141 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001142
Sam Parker5f934642017-08-31 09:27:04 +00001143 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001144 DiagnosticPredicate isComplexRotation() const {
1145 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001146
1147 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001148 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001149 uint64_t Value = CE->getValue();
1150
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001151 if (Value % Angle == Remainder && Value <= 270)
1152 return DiagnosticPredicateTy::Match;
1153 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001154 }
1155
Sander de Smalen149916d2018-04-20 07:24:20 +00001156 template <unsigned RegClassID> bool isGPR64() const {
1157 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1158 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1159 }
1160
1161 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001162 DiagnosticPredicate isGPR64WithShiftExtend() const {
1163 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1164 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001165
Sander de Smalenfe17a782018-04-26 12:54:42 +00001166 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1167 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1168 return DiagnosticPredicateTy::Match;
1169 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001170 }
1171
Tim Northover3b0846e2014-05-24 12:50:23 +00001172 /// Is this a vector list with the type implicit (presumably attached to the
1173 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001174 template <RegKind VectorKind, unsigned NumRegs>
1175 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001176 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001177 VectorList.NumElements == 0 &&
1178 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001179 }
1180
Sander de Smalen650234b2018-04-12 11:40:52 +00001181 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1182 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001183 bool isTypedVectorList() const {
1184 if (Kind != k_VectorList)
1185 return false;
1186 if (VectorList.Count != NumRegs)
1187 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001188 if (VectorList.RegisterKind != VectorKind)
1189 return false;
1190 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001191 return false;
1192 return VectorList.NumElements == NumElements;
1193 }
1194
Sander de Smalenc33d6682018-06-04 06:40:55 +00001195 template <int Min, int Max>
1196 DiagnosticPredicate isVectorIndex() const {
1197 if (Kind != k_VectorIndex)
1198 return DiagnosticPredicateTy::NoMatch;
1199 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1200 return DiagnosticPredicateTy::Match;
1201 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001202 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001203
Tim Northover3b0846e2014-05-24 12:50:23 +00001204 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001205
Tim Northover3b0846e2014-05-24 12:50:23 +00001206 bool isTokenEqual(StringRef Str) const {
1207 return Kind == k_Token && getToken() == Str;
1208 }
1209 bool isSysCR() const { return Kind == k_SysCR; }
1210 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001211 bool isPSBHint() const { return Kind == k_PSBHint; }
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001212 bool isBTIHint() const { return Kind == k_BTIHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001213 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1214 bool isShifter() const {
1215 if (!isShiftExtend())
1216 return false;
1217
1218 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1219 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1220 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1221 ST == AArch64_AM::MSL);
1222 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001223
1224 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1225 if (Kind != k_FPImm)
1226 return DiagnosticPredicateTy::NoMatch;
1227
1228 if (getFPImmIsExact()) {
1229 // Lookup the immediate from table of supported immediates.
1230 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1231 assert(Desc && "Unknown enum value");
1232
1233 // Calculate its FP value.
1234 APFloat RealVal(APFloat::IEEEdouble());
1235 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1236 APFloat::opOK)
1237 llvm_unreachable("FP immediate is not exact");
1238
1239 if (getFPImm().bitwiseIsEqual(RealVal))
1240 return DiagnosticPredicateTy::Match;
1241 }
1242
1243 return DiagnosticPredicateTy::NearMatch;
1244 }
1245
1246 template <unsigned ImmA, unsigned ImmB>
1247 DiagnosticPredicate isExactFPImm() const {
1248 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1249 if ((Res = isExactFPImm<ImmA>()))
1250 return DiagnosticPredicateTy::Match;
1251 if ((Res = isExactFPImm<ImmB>()))
1252 return DiagnosticPredicateTy::Match;
1253 return Res;
1254 }
1255
Tim Northover3b0846e2014-05-24 12:50:23 +00001256 bool isExtend() const {
1257 if (!isShiftExtend())
1258 return false;
1259
1260 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1261 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1262 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1263 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1264 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1265 ET == AArch64_AM::LSL) &&
1266 getShiftExtendAmount() <= 4;
1267 }
1268
1269 bool isExtend64() const {
1270 if (!isExtend())
1271 return false;
1272 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1273 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1274 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1275 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001276
Tim Northover3b0846e2014-05-24 12:50:23 +00001277 bool isExtendLSL64() const {
1278 if (!isExtend())
1279 return false;
1280 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1281 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1282 ET == AArch64_AM::LSL) &&
1283 getShiftExtendAmount() <= 4;
1284 }
1285
1286 template<int Width> bool isMemXExtend() const {
1287 if (!isExtend())
1288 return false;
1289 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1290 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1291 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1292 getShiftExtendAmount() == 0);
1293 }
1294
1295 template<int Width> bool isMemWExtend() const {
1296 if (!isExtend())
1297 return false;
1298 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1299 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1300 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1301 getShiftExtendAmount() == 0);
1302 }
1303
1304 template <unsigned width>
1305 bool isArithmeticShifter() const {
1306 if (!isShifter())
1307 return false;
1308
1309 // An arithmetic shifter is LSL, LSR, or ASR.
1310 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1311 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1312 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1313 }
1314
1315 template <unsigned width>
1316 bool isLogicalShifter() const {
1317 if (!isShifter())
1318 return false;
1319
1320 // A logical shifter is LSL, LSR, ASR or ROR.
1321 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1322 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1323 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1324 getShiftExtendAmount() < width;
1325 }
1326
1327 bool isMovImm32Shifter() const {
1328 if (!isShifter())
1329 return false;
1330
1331 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1332 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1333 if (ST != AArch64_AM::LSL)
1334 return false;
1335 uint64_t Val = getShiftExtendAmount();
1336 return (Val == 0 || Val == 16);
1337 }
1338
1339 bool isMovImm64Shifter() const {
1340 if (!isShifter())
1341 return false;
1342
1343 // A MOVi shifter is LSL of 0 or 16.
1344 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1345 if (ST != AArch64_AM::LSL)
1346 return false;
1347 uint64_t Val = getShiftExtendAmount();
1348 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1349 }
1350
1351 bool isLogicalVecShifter() const {
1352 if (!isShifter())
1353 return false;
1354
1355 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1356 unsigned Shift = getShiftExtendAmount();
1357 return getShiftExtendType() == AArch64_AM::LSL &&
1358 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1359 }
1360
1361 bool isLogicalVecHalfWordShifter() const {
1362 if (!isLogicalVecShifter())
1363 return false;
1364
1365 // A logical vector shifter is a left shift by 0 or 8.
1366 unsigned Shift = getShiftExtendAmount();
1367 return getShiftExtendType() == AArch64_AM::LSL &&
1368 (Shift == 0 || Shift == 8);
1369 }
1370
1371 bool isMoveVecShifter() const {
1372 if (!isShiftExtend())
1373 return false;
1374
1375 // A logical vector shifter is a left shift by 8 or 16.
1376 unsigned Shift = getShiftExtendAmount();
1377 return getShiftExtendType() == AArch64_AM::MSL &&
1378 (Shift == 8 || Shift == 16);
1379 }
1380
1381 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1382 // to LDUR/STUR when the offset is not legal for the former but is for
1383 // the latter. As such, in addition to checking for being a legal unscaled
1384 // address, also check that it is not a legal scaled address. This avoids
1385 // ambiguity in the matcher.
1386 template<int Width>
1387 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001388 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001389 }
1390
1391 bool isAdrpLabel() const {
1392 // Validation was handled during parsing, so we just sanity check that
1393 // something didn't go haywire.
1394 if (!isImm())
1395 return false;
1396
1397 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1398 int64_t Val = CE->getValue();
1399 int64_t Min = - (4096 * (1LL << (21 - 1)));
1400 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1401 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1402 }
1403
1404 return true;
1405 }
1406
1407 bool isAdrLabel() const {
1408 // Validation was handled during parsing, so we just sanity check that
1409 // something didn't go haywire.
1410 if (!isImm())
1411 return false;
1412
1413 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1414 int64_t Val = CE->getValue();
1415 int64_t Min = - (1LL << (21 - 1));
1416 int64_t Max = ((1LL << (21 - 1)) - 1);
1417 return Val >= Min && Val <= Max;
1418 }
1419
1420 return true;
1421 }
1422
1423 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1424 // Add as immediates when possible. Null MCExpr = 0.
1425 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001426 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001427 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001428 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001429 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001430 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001431 }
1432
1433 void addRegOperands(MCInst &Inst, unsigned N) const {
1434 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001435 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001436 }
1437
1438 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1439 assert(N == 1 && "Invalid number of operands!");
1440 assert(
1441 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1442
1443 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1444 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1445 RI->getEncodingValue(getReg()));
1446
Jim Grosbache9119e42015-05-13 18:37:00 +00001447 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001448 }
1449
Sander de Smalen0325e302018-07-02 07:34:52 +00001450 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1451 assert(N == 1 && "Invalid number of operands!");
1452 assert(
1453 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1454
1455 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1456 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1457 RI->getEncodingValue(getReg()));
1458
1459 Inst.addOperand(MCOperand::createReg(Reg));
1460 }
1461
Sander de Smalenfd54a782018-06-04 07:07:35 +00001462 template <int Width>
1463 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1464 unsigned Base;
1465 switch (Width) {
1466 case 8: Base = AArch64::B0; break;
1467 case 16: Base = AArch64::H0; break;
1468 case 32: Base = AArch64::S0; break;
1469 case 64: Base = AArch64::D0; break;
1470 case 128: Base = AArch64::Q0; break;
1471 default:
1472 llvm_unreachable("Unsupported width");
1473 }
1474 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1475 }
1476
Tim Northover3b0846e2014-05-24 12:50:23 +00001477 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1478 assert(N == 1 && "Invalid number of operands!");
1479 assert(
1480 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001481 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001482 }
1483
1484 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1485 assert(N == 1 && "Invalid number of operands!");
1486 assert(
1487 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001488 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001489 }
1490
1491 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1492 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001493 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001494 }
1495
Sander de Smalen525e3222018-04-12 13:19:32 +00001496 enum VecListIndexType {
1497 VecListIdx_DReg = 0,
1498 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001499 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001500 };
1501
1502 template <VecListIndexType RegTy, unsigned NumRegs>
1503 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001505 static const unsigned FirstRegs[][5] = {
1506 /* DReg */ { AArch64::Q0,
1507 AArch64::D0, AArch64::D0_D1,
1508 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1509 /* QReg */ { AArch64::Q0,
1510 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001511 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1512 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001513 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001514 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001515 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001516
Sander de Smalen7a210db2018-04-16 10:46:18 +00001517 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1518 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001519
Sander de Smalen525e3222018-04-12 13:19:32 +00001520 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1521 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1522 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001523 }
1524
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001525 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001526 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001527 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 }
1529
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001530 template <unsigned ImmIs0, unsigned ImmIs1>
1531 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1532 assert(N == 1 && "Invalid number of operands!");
1533 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1534 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1535 }
1536
Tim Northover3b0846e2014-05-24 12:50:23 +00001537 void addImmOperands(MCInst &Inst, unsigned N) const {
1538 assert(N == 1 && "Invalid number of operands!");
1539 // If this is a pageoff symrefexpr with an addend, adjust the addend
1540 // to be only the page-offset portion. Otherwise, just add the expr
1541 // as-is.
1542 addExpr(Inst, getImm());
1543 }
1544
Sander de Smalen62770792018-05-25 09:47:52 +00001545 template <int Shift>
1546 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001547 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001548 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1549 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1550 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1551 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001552 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001553 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001554 } else {
1555 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001556 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001557 }
1558 }
1559
Sander de Smalen62770792018-05-25 09:47:52 +00001560 template <int Shift>
1561 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001562 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001563 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1564 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1565 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1566 } else
1567 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001568 }
1569
Tim Northover3b0846e2014-05-24 12:50:23 +00001570 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1571 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001572 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001573 }
1574
1575 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1576 assert(N == 1 && "Invalid number of operands!");
1577 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1578 if (!MCE)
1579 addExpr(Inst, getImm());
1580 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001581 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001582 }
1583
1584 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1585 addImmOperands(Inst, N);
1586 }
1587
1588 template<int Scale>
1589 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1590 assert(N == 1 && "Invalid number of operands!");
1591 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1592
1593 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001594 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001595 return;
1596 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001597 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001598 }
1599
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001600 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1601 assert(N == 1 && "Invalid number of operands!");
1602 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1603 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1604 }
1605
Sander de Smalen5c625982018-04-13 12:56:14 +00001606 template <int Scale>
1607 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1608 assert(N == 1 && "Invalid number of operands!");
1609 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1610 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1611 }
1612
Sander de Smalena1c259c2018-01-29 13:05:38 +00001613 template <typename T>
1614 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001615 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001616 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001617 typename std::make_unsigned<T>::type Val = MCE->getValue();
1618 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001619 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001620 }
1621
Sander de Smalena1c259c2018-01-29 13:05:38 +00001622 template <typename T>
1623 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001624 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001625 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001626 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1627 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001628 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001629 }
1630
Tim Northover3b0846e2014-05-24 12:50:23 +00001631 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1632 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001633 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001634 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001635 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001636 }
1637
1638 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1639 // Branch operands don't encode the low bits, so shift them off
1640 // here. If it's a label, however, just put it on directly as there's
1641 // not enough information now to do anything.
1642 assert(N == 1 && "Invalid number of operands!");
1643 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1644 if (!MCE) {
1645 addExpr(Inst, getImm());
1646 return;
1647 }
1648 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001649 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001650 }
1651
1652 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1653 // Branch operands don't encode the low bits, so shift them off
1654 // here. If it's a label, however, just put it on directly as there's
1655 // not enough information now to do anything.
1656 assert(N == 1 && "Invalid number of operands!");
1657 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1658 if (!MCE) {
1659 addExpr(Inst, getImm());
1660 return;
1661 }
1662 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001663 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001664 }
1665
1666 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1667 // Branch operands don't encode the low bits, so shift them off
1668 // here. If it's a label, however, just put it on directly as there's
1669 // not enough information now to do anything.
1670 assert(N == 1 && "Invalid number of operands!");
1671 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1672 if (!MCE) {
1673 addExpr(Inst, getImm());
1674 return;
1675 }
1676 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001677 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001678 }
1679
1680 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1681 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001682 Inst.addOperand(MCOperand::createImm(
1683 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001684 }
1685
1686 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1687 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001688 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001689 }
1690
1691 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1692 assert(N == 1 && "Invalid number of operands!");
1693
Jim Grosbache9119e42015-05-13 18:37:00 +00001694 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001695 }
1696
1697 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1698 assert(N == 1 && "Invalid number of operands!");
1699
Jim Grosbache9119e42015-05-13 18:37:00 +00001700 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001701 }
1702
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001703 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1704 assert(N == 1 && "Invalid number of operands!");
1705
1706 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1707 }
1708
1709 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001710 assert(N == 1 && "Invalid number of operands!");
1711
Jim Grosbache9119e42015-05-13 18:37:00 +00001712 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001713 }
1714
1715 void addSysCROperands(MCInst &Inst, unsigned N) const {
1716 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001717 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001718 }
1719
1720 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1721 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001722 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001723 }
1724
Oliver Stannarda34e4702015-12-01 10:48:51 +00001725 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1726 assert(N == 1 && "Invalid number of operands!");
1727 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1728 }
1729
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001730 void addBTIHintOperands(MCInst &Inst, unsigned N) const {
1731 assert(N == 1 && "Invalid number of operands!");
1732 Inst.addOperand(MCOperand::createImm(getBTIHint()));
1733 }
1734
Tim Northover3b0846e2014-05-24 12:50:23 +00001735 void addShifterOperands(MCInst &Inst, unsigned N) const {
1736 assert(N == 1 && "Invalid number of operands!");
1737 unsigned Imm =
1738 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001739 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001740 }
1741
1742 void addExtendOperands(MCInst &Inst, unsigned N) const {
1743 assert(N == 1 && "Invalid number of operands!");
1744 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1745 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1746 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001747 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001748 }
1749
1750 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1751 assert(N == 1 && "Invalid number of operands!");
1752 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1753 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1754 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001755 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001756 }
1757
1758 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1759 assert(N == 2 && "Invalid number of operands!");
1760 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1761 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001762 Inst.addOperand(MCOperand::createImm(IsSigned));
1763 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001764 }
1765
1766 // For 8-bit load/store instructions with a register offset, both the
1767 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1768 // they're disambiguated by whether the shift was explicit or implicit rather
1769 // than its size.
1770 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1771 assert(N == 2 && "Invalid number of operands!");
1772 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1773 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001774 Inst.addOperand(MCOperand::createImm(IsSigned));
1775 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001776 }
1777
1778 template<int Shift>
1779 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1780 assert(N == 1 && "Invalid number of operands!");
1781
1782 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1783 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001784 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001785 }
1786
1787 template<int Shift>
1788 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1789 assert(N == 1 && "Invalid number of operands!");
1790
1791 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1792 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001793 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001794 }
1795
Sam Parker5f934642017-08-31 09:27:04 +00001796 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1797 assert(N == 1 && "Invalid number of operands!");
1798 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1799 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1800 }
1801
1802 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1803 assert(N == 1 && "Invalid number of operands!");
1804 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1805 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1806 }
1807
Tim Northover3b0846e2014-05-24 12:50:23 +00001808 void print(raw_ostream &OS) const override;
1809
David Blaikie960ea3f2014-06-08 16:18:35 +00001810 static std::unique_ptr<AArch64Operand>
1811 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1812 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001813 Op->Tok.Data = Str.data();
1814 Op->Tok.Length = Str.size();
1815 Op->Tok.IsSuffix = IsSuffix;
1816 Op->StartLoc = S;
1817 Op->EndLoc = S;
1818 return Op;
1819 }
1820
David Blaikie960ea3f2014-06-08 16:18:35 +00001821 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001822 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001823 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001824 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1825 unsigned ShiftAmount = 0,
1826 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001827 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001828 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001829 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001830 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001831 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001832 Op->Reg.ShiftExtend.Type = ExtTy;
1833 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1834 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
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>
Sander de Smalen73937b72018-04-11 07:36:10 +00001841 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001842 SMLoc S, SMLoc E, MCContext &Ctx,
1843 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1844 unsigned ShiftAmount = 0,
1845 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001846 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1847 Kind == RegKind::SVEPredicateVector) &&
1848 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001849 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001850 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001851 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001852 return Op;
1853 }
1854
1855 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001856 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001857 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1858 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001859 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001860 Op->VectorList.RegNum = RegNum;
1861 Op->VectorList.Count = Count;
1862 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001863 Op->VectorList.ElementWidth = ElementWidth;
1864 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001865 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 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1872 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001873 Op->VectorIndex.Val = Idx;
1874 Op->StartLoc = S;
1875 Op->EndLoc = E;
1876 return Op;
1877 }
1878
David Blaikie960ea3f2014-06-08 16:18:35 +00001879 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1880 SMLoc E, MCContext &Ctx) {
1881 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001882 Op->Imm.Val = Val;
1883 Op->StartLoc = S;
1884 Op->EndLoc = E;
1885 return Op;
1886 }
1887
David Blaikie960ea3f2014-06-08 16:18:35 +00001888 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1889 unsigned ShiftAmount,
1890 SMLoc S, SMLoc E,
1891 MCContext &Ctx) {
1892 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001893 Op->ShiftedImm .Val = Val;
1894 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1895 Op->StartLoc = S;
1896 Op->EndLoc = E;
1897 return Op;
1898 }
1899
David Blaikie960ea3f2014-06-08 16:18:35 +00001900 static std::unique_ptr<AArch64Operand>
1901 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1902 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001903 Op->CondCode.Code = Code;
1904 Op->StartLoc = S;
1905 Op->EndLoc = E;
1906 return Op;
1907 }
1908
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001909 static std::unique_ptr<AArch64Operand>
1910 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001911 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001912 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1913 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001914 Op->StartLoc = S;
1915 Op->EndLoc = S;
1916 return Op;
1917 }
1918
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001919 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1920 StringRef Str,
1921 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001922 MCContext &Ctx) {
1923 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001924 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001925 Op->Barrier.Data = Str.data();
1926 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001927 Op->StartLoc = S;
1928 Op->EndLoc = S;
1929 return Op;
1930 }
1931
Tim Northover7cd58932015-01-22 17:23:04 +00001932 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1933 uint32_t MRSReg,
1934 uint32_t MSRReg,
1935 uint32_t PStateField,
1936 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001937 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001938 Op->SysReg.Data = Str.data();
1939 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001940 Op->SysReg.MRSReg = MRSReg;
1941 Op->SysReg.MSRReg = MSRReg;
1942 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001943 Op->StartLoc = S;
1944 Op->EndLoc = S;
1945 return Op;
1946 }
1947
David Blaikie960ea3f2014-06-08 16:18:35 +00001948 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1949 SMLoc E, MCContext &Ctx) {
1950 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001951 Op->SysCRImm.Val = Val;
1952 Op->StartLoc = S;
1953 Op->EndLoc = E;
1954 return Op;
1955 }
1956
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001957 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1958 StringRef Str,
1959 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001960 MCContext &Ctx) {
1961 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001962 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001963 Op->Barrier.Data = Str.data();
1964 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001965 Op->StartLoc = S;
1966 Op->EndLoc = S;
1967 return Op;
1968 }
1969
Oliver Stannarda34e4702015-12-01 10:48:51 +00001970 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1971 StringRef Str,
1972 SMLoc S,
1973 MCContext &Ctx) {
1974 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1975 Op->PSBHint.Val = Val;
1976 Op->PSBHint.Data = Str.data();
1977 Op->PSBHint.Length = Str.size();
1978 Op->StartLoc = S;
1979 Op->EndLoc = S;
1980 return Op;
1981 }
1982
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00001983 static std::unique_ptr<AArch64Operand> CreateBTIHint(unsigned Val,
1984 StringRef Str,
1985 SMLoc S,
1986 MCContext &Ctx) {
1987 auto Op = make_unique<AArch64Operand>(k_BTIHint, Ctx);
1988 Op->BTIHint.Val = Val << 1 | 32;
1989 Op->BTIHint.Data = Str.data();
1990 Op->BTIHint.Length = Str.size();
1991 Op->StartLoc = S;
1992 Op->EndLoc = S;
1993 return Op;
1994 }
1995
David Blaikie960ea3f2014-06-08 16:18:35 +00001996 static std::unique_ptr<AArch64Operand>
1997 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1998 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1999 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00002000 Op->ShiftExtend.Type = ShOp;
2001 Op->ShiftExtend.Amount = Val;
2002 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
2003 Op->StartLoc = S;
2004 Op->EndLoc = E;
2005 return Op;
2006 }
2007};
2008
2009} // end anonymous namespace.
2010
2011void AArch64Operand::print(raw_ostream &OS) const {
2012 switch (Kind) {
2013 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002014 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
2015 if (!getFPImmIsExact())
2016 OS << " (inexact)";
2017 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00002018 break;
2019 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002020 StringRef Name = getBarrierName();
2021 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002022 OS << "<barrier " << Name << ">";
2023 else
2024 OS << "<barrier invalid #" << getBarrier() << ">";
2025 break;
2026 }
2027 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002028 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00002029 break;
2030 case k_ShiftedImm: {
2031 unsigned Shift = getShiftedImmShift();
2032 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00002033 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00002034 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
2035 break;
2036 }
2037 case k_CondCode:
2038 OS << "<condcode " << getCondCode() << ">";
2039 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00002040 case k_VectorList: {
2041 OS << "<vectorlist ";
2042 unsigned Reg = getVectorListStart();
2043 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2044 OS << Reg + i << " ";
2045 OS << ">";
2046 break;
2047 }
2048 case k_VectorIndex:
2049 OS << "<vectorindex " << getVectorIndex() << ">";
2050 break;
2051 case k_SysReg:
2052 OS << "<sysreg: " << getSysReg() << '>';
2053 break;
2054 case k_Token:
2055 OS << "'" << getToken() << "'";
2056 break;
2057 case k_SysCR:
2058 OS << "c" << getSysCR();
2059 break;
2060 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002061 StringRef Name = getPrefetchName();
2062 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002063 OS << "<prfop " << Name << ">";
2064 else
2065 OS << "<prfop invalid #" << getPrefetch() << ">";
2066 break;
2067 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00002068 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00002069 OS << getPSBHintName();
2070 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00002071 case k_Register:
2072 OS << "<register " << getReg() << ">";
2073 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2074 break;
2075 LLVM_FALLTHROUGH;
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002076 case k_BTIHint:
2077 OS << getBTIHintName();
2078 break;
Eugene Zelenko049b0172017-01-06 00:30:53 +00002079 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00002080 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2081 << getShiftExtendAmount();
2082 if (!hasShiftExtendAmount())
2083 OS << "<imp>";
2084 OS << '>';
2085 break;
2086 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002087}
2088
2089/// @name Auto-generated Match Functions
2090/// {
2091
2092static unsigned MatchRegisterName(StringRef Name);
2093
2094/// }
2095
Florian Hahnc4422242017-11-07 13:07:50 +00002096static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00002097 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00002098 .Case("v0", AArch64::Q0)
2099 .Case("v1", AArch64::Q1)
2100 .Case("v2", AArch64::Q2)
2101 .Case("v3", AArch64::Q3)
2102 .Case("v4", AArch64::Q4)
2103 .Case("v5", AArch64::Q5)
2104 .Case("v6", AArch64::Q6)
2105 .Case("v7", AArch64::Q7)
2106 .Case("v8", AArch64::Q8)
2107 .Case("v9", AArch64::Q9)
2108 .Case("v10", AArch64::Q10)
2109 .Case("v11", AArch64::Q11)
2110 .Case("v12", AArch64::Q12)
2111 .Case("v13", AArch64::Q13)
2112 .Case("v14", AArch64::Q14)
2113 .Case("v15", AArch64::Q15)
2114 .Case("v16", AArch64::Q16)
2115 .Case("v17", AArch64::Q17)
2116 .Case("v18", AArch64::Q18)
2117 .Case("v19", AArch64::Q19)
2118 .Case("v20", AArch64::Q20)
2119 .Case("v21", AArch64::Q21)
2120 .Case("v22", AArch64::Q22)
2121 .Case("v23", AArch64::Q23)
2122 .Case("v24", AArch64::Q24)
2123 .Case("v25", AArch64::Q25)
2124 .Case("v26", AArch64::Q26)
2125 .Case("v27", AArch64::Q27)
2126 .Case("v28", AArch64::Q28)
2127 .Case("v29", AArch64::Q29)
2128 .Case("v30", AArch64::Q30)
2129 .Case("v31", AArch64::Q31)
2130 .Default(0);
2131}
2132
Sander de Smalen73937b72018-04-11 07:36:10 +00002133/// Returns an optional pair of (#elements, element-width) if Suffix
2134/// is a valid vector kind. Where the number of elements in a vector
2135/// or the vector width is implicit or explicitly unknown (but still a
2136/// valid suffix kind), 0 is used.
2137static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2138 RegKind VectorKind) {
2139 std::pair<int, int> Res = {-1, -1};
2140
2141 switch (VectorKind) {
2142 case RegKind::NeonVector:
2143 Res =
2144 StringSwitch<std::pair<int, int>>(Suffix.lower())
2145 .Case("", {0, 0})
2146 .Case(".1d", {1, 64})
2147 .Case(".1q", {1, 128})
2148 // '.2h' needed for fp16 scalar pairwise reductions
2149 .Case(".2h", {2, 16})
2150 .Case(".2s", {2, 32})
2151 .Case(".2d", {2, 64})
2152 // '.4b' is another special case for the ARMv8.2a dot product
2153 // operand
2154 .Case(".4b", {4, 8})
2155 .Case(".4h", {4, 16})
2156 .Case(".4s", {4, 32})
2157 .Case(".8b", {8, 8})
2158 .Case(".8h", {8, 16})
2159 .Case(".16b", {16, 8})
2160 // Accept the width neutral ones, too, for verbose syntax. If those
2161 // aren't used in the right places, the token operand won't match so
2162 // all will work out.
2163 .Case(".b", {0, 8})
2164 .Case(".h", {0, 16})
2165 .Case(".s", {0, 32})
2166 .Case(".d", {0, 64})
2167 .Default({-1, -1});
2168 break;
2169 case RegKind::SVEPredicateVector:
2170 case RegKind::SVEDataVector:
2171 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2172 .Case("", {0, 0})
2173 .Case(".b", {0, 8})
2174 .Case(".h", {0, 16})
2175 .Case(".s", {0, 32})
2176 .Case(".d", {0, 64})
2177 .Case(".q", {0, 128})
2178 .Default({-1, -1});
2179 break;
2180 default:
2181 llvm_unreachable("Unsupported RegKind");
2182 }
2183
2184 if (Res == std::make_pair(-1, -1))
2185 return Optional<std::pair<int, int>>();
2186
2187 return Optional<std::pair<int, int>>(Res);
2188}
2189
2190static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2191 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002192}
2193
Florian Hahn91f11e52017-11-07 16:45:48 +00002194static unsigned matchSVEDataVectorRegName(StringRef Name) {
2195 return StringSwitch<unsigned>(Name.lower())
2196 .Case("z0", AArch64::Z0)
2197 .Case("z1", AArch64::Z1)
2198 .Case("z2", AArch64::Z2)
2199 .Case("z3", AArch64::Z3)
2200 .Case("z4", AArch64::Z4)
2201 .Case("z5", AArch64::Z5)
2202 .Case("z6", AArch64::Z6)
2203 .Case("z7", AArch64::Z7)
2204 .Case("z8", AArch64::Z8)
2205 .Case("z9", AArch64::Z9)
2206 .Case("z10", AArch64::Z10)
2207 .Case("z11", AArch64::Z11)
2208 .Case("z12", AArch64::Z12)
2209 .Case("z13", AArch64::Z13)
2210 .Case("z14", AArch64::Z14)
2211 .Case("z15", AArch64::Z15)
2212 .Case("z16", AArch64::Z16)
2213 .Case("z17", AArch64::Z17)
2214 .Case("z18", AArch64::Z18)
2215 .Case("z19", AArch64::Z19)
2216 .Case("z20", AArch64::Z20)
2217 .Case("z21", AArch64::Z21)
2218 .Case("z22", AArch64::Z22)
2219 .Case("z23", AArch64::Z23)
2220 .Case("z24", AArch64::Z24)
2221 .Case("z25", AArch64::Z25)
2222 .Case("z26", AArch64::Z26)
2223 .Case("z27", AArch64::Z27)
2224 .Case("z28", AArch64::Z28)
2225 .Case("z29", AArch64::Z29)
2226 .Case("z30", AArch64::Z30)
2227 .Case("z31", AArch64::Z31)
2228 .Default(0);
2229}
2230
Sander de Smalencd6be962017-12-20 11:02:42 +00002231static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2232 return StringSwitch<unsigned>(Name.lower())
2233 .Case("p0", AArch64::P0)
2234 .Case("p1", AArch64::P1)
2235 .Case("p2", AArch64::P2)
2236 .Case("p3", AArch64::P3)
2237 .Case("p4", AArch64::P4)
2238 .Case("p5", AArch64::P5)
2239 .Case("p6", AArch64::P6)
2240 .Case("p7", AArch64::P7)
2241 .Case("p8", AArch64::P8)
2242 .Case("p9", AArch64::P9)
2243 .Case("p10", AArch64::P10)
2244 .Case("p11", AArch64::P11)
2245 .Case("p12", AArch64::P12)
2246 .Case("p13", AArch64::P13)
2247 .Case("p14", AArch64::P14)
2248 .Case("p15", AArch64::P15)
2249 .Default(0);
2250}
2251
Tim Northover3b0846e2014-05-24 12:50:23 +00002252bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2253 SMLoc &EndLoc) {
2254 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002255 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002256 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002257 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002258}
2259
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002260// Matches a register name or register alias previously defined by '.req'
2261unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002262 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002263 unsigned RegNum = 0;
2264 if ((RegNum = matchSVEDataVectorRegName(Name)))
2265 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2266
Sander de Smalencd6be962017-12-20 11:02:42 +00002267 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2268 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2269
Sander de Smalenc067c302017-12-20 09:45:45 +00002270 if ((RegNum = MatchNeonVectorRegName(Name)))
2271 return Kind == RegKind::NeonVector ? RegNum : 0;
2272
2273 // The parsed register must be of RegKind Scalar
2274 if ((RegNum = MatchRegisterName(Name)))
2275 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002276
Florian Hahnc4422242017-11-07 13:07:50 +00002277 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002278 // Handle a few common aliases of registers.
2279 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2280 .Case("fp", AArch64::FP)
2281 .Case("lr", AArch64::LR)
2282 .Case("x31", AArch64::XZR)
2283 .Case("w31", AArch64::WZR)
2284 .Default(0))
2285 return Kind == RegKind::Scalar ? RegNum : 0;
2286
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002287 // Check for aliases registered via .req. Canonicalize to lower case.
2288 // That's more consistent since register names are case insensitive, and
2289 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2290 auto Entry = RegisterReqs.find(Name.lower());
2291 if (Entry == RegisterReqs.end())
2292 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002293
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002294 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002295 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002296 RegNum = Entry->getValue().second;
2297 }
2298 return RegNum;
2299}
2300
Sander de Smalen50d87022018-04-19 07:35:08 +00002301/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002302/// Identifier when called, and if it is a register name the token is eaten and
2303/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002304OperandMatchResultTy
2305AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002306 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002307 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002308 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002309 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002310
2311 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002312 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2313 if (Reg == 0)
2314 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002315
Sander de Smalen50d87022018-04-19 07:35:08 +00002316 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002317 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002318 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002319}
2320
Tim Northover3b0846e2014-05-24 12:50:23 +00002321/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002322OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002323AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002324 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002325 SMLoc S = getLoc();
2326
2327 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2328 Error(S, "Expected cN operand where 0 <= N <= 15");
2329 return MatchOperand_ParseFail;
2330 }
2331
2332 StringRef Tok = Parser.getTok().getIdentifier();
2333 if (Tok[0] != 'c' && Tok[0] != 'C') {
2334 Error(S, "Expected cN operand where 0 <= N <= 15");
2335 return MatchOperand_ParseFail;
2336 }
2337
2338 uint32_t CRNum;
2339 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2340 if (BadNum || CRNum > 15) {
2341 Error(S, "Expected cN operand where 0 <= N <= 15");
2342 return MatchOperand_ParseFail;
2343 }
2344
2345 Parser.Lex(); // Eat identifier token.
2346 Operands.push_back(
2347 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2348 return MatchOperand_Success;
2349}
2350
2351/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002352template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002353OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002354AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002355 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002356 SMLoc S = getLoc();
2357 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002358
2359 auto LookupByName = [](StringRef N) {
2360 if (IsSVEPrefetch) {
2361 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2362 return Optional<unsigned>(Res->Encoding);
2363 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2364 return Optional<unsigned>(Res->Encoding);
2365 return Optional<unsigned>();
2366 };
2367
2368 auto LookupByEncoding = [](unsigned E) {
2369 if (IsSVEPrefetch) {
2370 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2371 return Optional<StringRef>(Res->Name);
2372 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2373 return Optional<StringRef>(Res->Name);
2374 return Optional<StringRef>();
2375 };
2376 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2377
Tim Northover3b0846e2014-05-24 12:50:23 +00002378 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002379 // Eat optional hash.
2380 if (parseOptionalToken(AsmToken::Hash) ||
2381 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002382 const MCExpr *ImmVal;
2383 if (getParser().parseExpression(ImmVal))
2384 return MatchOperand_ParseFail;
2385
2386 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2387 if (!MCE) {
2388 TokError("immediate value expected for prefetch operand");
2389 return MatchOperand_ParseFail;
2390 }
2391 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002392 if (prfop > MaxVal) {
2393 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2394 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002395 return MatchOperand_ParseFail;
2396 }
2397
Sander de Smalen93380372018-05-14 11:54:41 +00002398 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002399 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002400 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002401 return MatchOperand_Success;
2402 }
2403
2404 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002405 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002406 return MatchOperand_ParseFail;
2407 }
2408
Sander de Smalen93380372018-05-14 11:54:41 +00002409 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002410 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002411 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002412 return MatchOperand_ParseFail;
2413 }
2414
2415 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002416 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002417 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002418 return MatchOperand_Success;
2419}
2420
Oliver Stannarda34e4702015-12-01 10:48:51 +00002421/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002422OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002423AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2424 MCAsmParser &Parser = getParser();
2425 SMLoc S = getLoc();
2426 const AsmToken &Tok = Parser.getTok();
2427 if (Tok.isNot(AsmToken::Identifier)) {
2428 TokError("invalid operand for instruction");
2429 return MatchOperand_ParseFail;
2430 }
2431
Tim Northovere6ae6762016-07-05 21:23:04 +00002432 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2433 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002434 TokError("invalid operand for instruction");
2435 return MatchOperand_ParseFail;
2436 }
2437
2438 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002439 Operands.push_back(AArch64Operand::CreatePSBHint(
2440 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002441 return MatchOperand_Success;
2442}
2443
Oliver Stannarda9a5eee2018-09-27 14:54:33 +00002444/// tryParseBTIHint - Try to parse a BTI operand, mapped to Hint command
2445OperandMatchResultTy
2446AArch64AsmParser::tryParseBTIHint(OperandVector &Operands) {
2447 MCAsmParser &Parser = getParser();
2448 SMLoc S = getLoc();
2449 const AsmToken &Tok = Parser.getTok();
2450 if (Tok.isNot(AsmToken::Identifier)) {
2451 TokError("invalid operand for instruction");
2452 return MatchOperand_ParseFail;
2453 }
2454
2455 auto BTI = AArch64BTIHint::lookupBTIByName(Tok.getString());
2456 if (!BTI) {
2457 TokError("invalid operand for instruction");
2458 return MatchOperand_ParseFail;
2459 }
2460
2461 Parser.Lex(); // Eat identifier token.
2462 Operands.push_back(AArch64Operand::CreateBTIHint(
2463 BTI->Encoding, Tok.getString(), S, getContext()));
2464 return MatchOperand_Success;
2465}
2466
Tim Northover3b0846e2014-05-24 12:50:23 +00002467/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2468/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002469OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002470AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002471 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002472 SMLoc S = getLoc();
2473 const MCExpr *Expr;
2474
2475 if (Parser.getTok().is(AsmToken::Hash)) {
2476 Parser.Lex(); // Eat hash token.
2477 }
2478
2479 if (parseSymbolicImmVal(Expr))
2480 return MatchOperand_ParseFail;
2481
2482 AArch64MCExpr::VariantKind ELFRefKind;
2483 MCSymbolRefExpr::VariantKind DarwinRefKind;
2484 int64_t Addend;
2485 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2486 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2487 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2488 // No modifier was specified at all; this is the syntax for an ELF basic
2489 // ADRP relocation (unfortunately).
2490 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002491 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002492 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2493 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2494 Addend != 0) {
2495 Error(S, "gotpage label reference not allowed an addend");
2496 return MatchOperand_ParseFail;
2497 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2498 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2499 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2500 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2501 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2502 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2503 // The operand must be an @page or @gotpage qualified symbolref.
2504 Error(S, "page or gotpage label reference expected");
2505 return MatchOperand_ParseFail;
2506 }
2507 }
2508
2509 // We have either a label reference possibly with addend or an immediate. The
2510 // addend is a raw value here. The linker will adjust it to only reference the
2511 // page.
2512 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2513 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2514
2515 return MatchOperand_Success;
2516}
2517
2518/// tryParseAdrLabel - Parse and validate a source label for the ADR
2519/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002520OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002521AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2522 SMLoc S = getLoc();
2523 const MCExpr *Expr;
2524
David Green9dd1d452018-08-22 11:31:39 +00002525 // Leave anything with a bracket to the default for SVE
2526 if (getParser().getTok().is(AsmToken::LBrac))
2527 return MatchOperand_NoMatch;
2528
2529 if (getParser().getTok().is(AsmToken::Hash))
2530 getParser().Lex(); // Eat hash token.
2531
2532 if (parseSymbolicImmVal(Expr))
2533 return MatchOperand_ParseFail;
2534
2535 AArch64MCExpr::VariantKind ELFRefKind;
2536 MCSymbolRefExpr::VariantKind DarwinRefKind;
2537 int64_t Addend;
2538 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2539 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2540 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2541 // No modifier was specified at all; this is the syntax for an ELF basic
2542 // ADR relocation (unfortunately).
2543 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2544 } else {
2545 Error(S, "unexpected adr label");
Sander de Smalenc69944c2018-07-09 09:58:24 +00002546 return MatchOperand_ParseFail;
David Green9dd1d452018-08-22 11:31:39 +00002547 }
Sander de Smalenc69944c2018-07-09 09:58:24 +00002548 }
David Green9dd1d452018-08-22 11:31:39 +00002549
2550 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2551 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2552 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002553}
2554
2555/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002556template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002557OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002558AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002559 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 SMLoc S = getLoc();
2561
Nirav Davee833c6c2016-11-08 18:31:04 +00002562 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002563
2564 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002565 bool isNegative = parseOptionalToken(AsmToken::Minus);
2566
Tim Northover3b0846e2014-05-24 12:50:23 +00002567 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002568 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2569 if (!Hash)
2570 return MatchOperand_NoMatch;
2571 TokError("invalid floating point immediate");
2572 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002573 }
2574
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002575 // Parse hexadecimal representation.
2576 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2577 if (Tok.getIntVal() > 255 || isNegative) {
2578 TokError("encoded floating point value out of range");
2579 return MatchOperand_ParseFail;
2580 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002581
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002582 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2583 Operands.push_back(
2584 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2585 } else {
2586 // Parse FP representation.
2587 APFloat RealVal(APFloat::IEEEdouble());
2588 auto Status =
2589 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2590 if (isNegative)
2591 RealVal.changeSign();
2592
2593 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2594 Operands.push_back(
2595 AArch64Operand::CreateToken("#0", false, S, getContext()));
2596 Operands.push_back(
2597 AArch64Operand::CreateToken(".0", false, S, getContext()));
2598 } else
2599 Operands.push_back(AArch64Operand::CreateFPImm(
2600 RealVal, Status == APFloat::opOK, S, getContext()));
2601 }
2602
2603 Parser.Lex(); // Eat the token.
2604
2605 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002606}
2607
Sander de Smalen62770792018-05-25 09:47:52 +00002608/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2609/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002610OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002611AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002612 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002613 SMLoc S = getLoc();
2614
2615 if (Parser.getTok().is(AsmToken::Hash))
2616 Parser.Lex(); // Eat '#'
2617 else if (Parser.getTok().isNot(AsmToken::Integer))
2618 // Operand should start from # or should be integer, emit error otherwise.
2619 return MatchOperand_NoMatch;
2620
2621 const MCExpr *Imm;
2622 if (parseSymbolicImmVal(Imm))
2623 return MatchOperand_ParseFail;
2624 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002625 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002626 Operands.push_back(
2627 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002628 return MatchOperand_Success;
2629 }
2630
2631 // Eat ','
2632 Parser.Lex();
2633
2634 // The optional operand must be "lsl #N" where N is non-negative.
2635 if (!Parser.getTok().is(AsmToken::Identifier) ||
2636 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2637 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2638 return MatchOperand_ParseFail;
2639 }
2640
2641 // Eat 'lsl'
2642 Parser.Lex();
2643
Nirav Davee833c6c2016-11-08 18:31:04 +00002644 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002645
2646 if (Parser.getTok().isNot(AsmToken::Integer)) {
2647 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2648 return MatchOperand_ParseFail;
2649 }
2650
2651 int64_t ShiftAmount = Parser.getTok().getIntVal();
2652
2653 if (ShiftAmount < 0) {
2654 Error(Parser.getTok().getLoc(), "positive shift amount required");
2655 return MatchOperand_ParseFail;
2656 }
2657 Parser.Lex(); // Eat the number
2658
Sander de Smalen62770792018-05-25 09:47:52 +00002659 // Just in case the optional lsl #0 is used for immediates other than zero.
2660 if (ShiftAmount == 0 && Imm != 0) {
2661 SMLoc E = Parser.getTok().getLoc();
2662 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2663 return MatchOperand_Success;
2664 }
2665
Tim Northover3b0846e2014-05-24 12:50:23 +00002666 SMLoc E = Parser.getTok().getLoc();
2667 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2668 S, E, getContext()));
2669 return MatchOperand_Success;
2670}
2671
2672/// parseCondCodeString - Parse a Condition Code string.
2673AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2674 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2675 .Case("eq", AArch64CC::EQ)
2676 .Case("ne", AArch64CC::NE)
2677 .Case("cs", AArch64CC::HS)
2678 .Case("hs", AArch64CC::HS)
2679 .Case("cc", AArch64CC::LO)
2680 .Case("lo", AArch64CC::LO)
2681 .Case("mi", AArch64CC::MI)
2682 .Case("pl", AArch64CC::PL)
2683 .Case("vs", AArch64CC::VS)
2684 .Case("vc", AArch64CC::VC)
2685 .Case("hi", AArch64CC::HI)
2686 .Case("ls", AArch64CC::LS)
2687 .Case("ge", AArch64CC::GE)
2688 .Case("lt", AArch64CC::LT)
2689 .Case("gt", AArch64CC::GT)
2690 .Case("le", AArch64CC::LE)
2691 .Case("al", AArch64CC::AL)
2692 .Case("nv", AArch64CC::NV)
2693 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002694
2695 if (CC == AArch64CC::Invalid &&
2696 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2697 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2698 .Case("none", AArch64CC::EQ)
2699 .Case("any", AArch64CC::NE)
2700 .Case("nlast", AArch64CC::HS)
2701 .Case("last", AArch64CC::LO)
2702 .Case("first", AArch64CC::MI)
2703 .Case("nfrst", AArch64CC::PL)
2704 .Case("pmore", AArch64CC::HI)
2705 .Case("plast", AArch64CC::LS)
2706 .Case("tcont", AArch64CC::GE)
2707 .Case("tstop", AArch64CC::LT)
2708 .Default(AArch64CC::Invalid);
2709
Tim Northover3b0846e2014-05-24 12:50:23 +00002710 return CC;
2711}
2712
2713/// parseCondCode - Parse a Condition Code operand.
2714bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2715 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002716 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002717 SMLoc S = getLoc();
2718 const AsmToken &Tok = Parser.getTok();
2719 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2720
2721 StringRef Cond = Tok.getString();
2722 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2723 if (CC == AArch64CC::Invalid)
2724 return TokError("invalid condition code");
2725 Parser.Lex(); // Eat identifier token.
2726
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002727 if (invertCondCode) {
2728 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2729 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002730 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002731 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002732
2733 Operands.push_back(
2734 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2735 return false;
2736}
2737
2738/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2739/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002740OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002741AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002742 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002743 const AsmToken &Tok = Parser.getTok();
2744 std::string LowerID = Tok.getString().lower();
2745 AArch64_AM::ShiftExtendType ShOp =
2746 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2747 .Case("lsl", AArch64_AM::LSL)
2748 .Case("lsr", AArch64_AM::LSR)
2749 .Case("asr", AArch64_AM::ASR)
2750 .Case("ror", AArch64_AM::ROR)
2751 .Case("msl", AArch64_AM::MSL)
2752 .Case("uxtb", AArch64_AM::UXTB)
2753 .Case("uxth", AArch64_AM::UXTH)
2754 .Case("uxtw", AArch64_AM::UXTW)
2755 .Case("uxtx", AArch64_AM::UXTX)
2756 .Case("sxtb", AArch64_AM::SXTB)
2757 .Case("sxth", AArch64_AM::SXTH)
2758 .Case("sxtw", AArch64_AM::SXTW)
2759 .Case("sxtx", AArch64_AM::SXTX)
2760 .Default(AArch64_AM::InvalidShiftExtend);
2761
2762 if (ShOp == AArch64_AM::InvalidShiftExtend)
2763 return MatchOperand_NoMatch;
2764
2765 SMLoc S = Tok.getLoc();
2766 Parser.Lex();
2767
Nirav Davee833c6c2016-11-08 18:31:04 +00002768 bool Hash = parseOptionalToken(AsmToken::Hash);
2769
Tim Northover3b0846e2014-05-24 12:50:23 +00002770 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2771 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2772 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2773 ShOp == AArch64_AM::MSL) {
2774 // We expect a number here.
2775 TokError("expected #imm after shift specifier");
2776 return MatchOperand_ParseFail;
2777 }
2778
Chad Rosier2ff37b82016-12-27 16:58:09 +00002779 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002780 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2781 Operands.push_back(
2782 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2783 return MatchOperand_Success;
2784 }
2785
Chad Rosier2ff37b82016-12-27 16:58:09 +00002786 // Make sure we do actually have a number, identifier or a parenthesized
2787 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002788 SMLoc E = Parser.getTok().getLoc();
2789 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002790 !Parser.getTok().is(AsmToken::LParen) &&
2791 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002792 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002793 return MatchOperand_ParseFail;
2794 }
2795
2796 const MCExpr *ImmVal;
2797 if (getParser().parseExpression(ImmVal))
2798 return MatchOperand_ParseFail;
2799
2800 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2801 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002802 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002803 return MatchOperand_ParseFail;
2804 }
2805
Jim Grosbach57fd2622014-09-23 22:16:02 +00002806 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002807 Operands.push_back(AArch64Operand::CreateShiftExtend(
2808 ShOp, MCE->getValue(), true, S, E, getContext()));
2809 return MatchOperand_Success;
2810}
2811
Oliver Stannard89b16042018-09-26 13:52:27 +00002812static const struct Extension {
2813 const char *Name;
2814 const FeatureBitset Features;
2815} ExtensionMap[] = {
Diogo N. Sampaio9c906732018-12-06 15:39:17 +00002816 {"crc", {AArch64::FeatureCRC}},
2817 {"sm4", {AArch64::FeatureSM4}},
2818 {"sha3", {AArch64::FeatureSHA3}},
2819 {"sha2", {AArch64::FeatureSHA2}},
2820 {"aes", {AArch64::FeatureAES}},
2821 {"crypto", {AArch64::FeatureCrypto}},
2822 {"fp", {AArch64::FeatureFPARMv8}},
2823 {"simd", {AArch64::FeatureNEON}},
2824 {"ras", {AArch64::FeatureRAS}},
2825 {"lse", {AArch64::FeatureLSE}},
2826 {"predctrl", {AArch64::FeaturePredCtrl}},
2827 {"ccdp", {AArch64::FeatureCacheDeepPersist}},
2828 {"mte", {AArch64::FeatureMTE}},
2829 {"tlb-rmi", {AArch64::FeatureTLB_RMI}},
2830 {"pan-rwv", {AArch64::FeaturePAN_RWV}},
2831 {"ccpp", {AArch64::FeatureCCPP}},
2832 // FIXME: Unsupported extensions
2833 {"pan", {}},
2834 {"lor", {}},
2835 {"rdma", {}},
2836 {"profile", {}},
Oliver Stannard89b16042018-09-26 13:52:27 +00002837};
2838
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002839static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2840 if (FBS[AArch64::HasV8_1aOps])
2841 Str += "ARMv8.1a";
2842 else if (FBS[AArch64::HasV8_2aOps])
2843 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002844 else if (FBS[AArch64::HasV8_3aOps])
2845 Str += "ARMv8.3a";
2846 else if (FBS[AArch64::HasV8_4aOps])
2847 Str += "ARMv8.4a";
Oliver Stannard89b16042018-09-26 13:52:27 +00002848 else if (FBS[AArch64::HasV8_5aOps])
2849 Str += "ARMv8.5a";
2850 else {
2851 auto ext = std::find_if(std::begin(ExtensionMap),
2852 std::end(ExtensionMap),
2853 [&](const Extension& e)
2854 // Use & in case multiple features are enabled
2855 { return (FBS & e.Features) != FeatureBitset(); }
2856 );
2857
2858 Str += ext != std::end(ExtensionMap) ? ext->Name : "(unknown)";
2859 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002860}
2861
2862void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2863 SMLoc S) {
2864 const uint16_t Op2 = Encoding & 7;
2865 const uint16_t Cm = (Encoding & 0x78) >> 3;
2866 const uint16_t Cn = (Encoding & 0x780) >> 7;
2867 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2868
2869 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2870
2871 Operands.push_back(
2872 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2873 Operands.push_back(
2874 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2875 Operands.push_back(
2876 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2877 Expr = MCConstantExpr::create(Op2, getContext());
2878 Operands.push_back(
2879 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2880}
2881
Tim Northover3b0846e2014-05-24 12:50:23 +00002882/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2883/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2884bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2885 OperandVector &Operands) {
2886 if (Name.find('.') != StringRef::npos)
2887 return TokError("invalid operand");
2888
2889 Mnemonic = Name;
2890 Operands.push_back(
2891 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2892
Rafael Espindola961d4692014-11-11 05:18:41 +00002893 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002894 const AsmToken &Tok = Parser.getTok();
2895 StringRef Op = Tok.getString();
2896 SMLoc S = Tok.getLoc();
2897
Tim Northover3b0846e2014-05-24 12:50:23 +00002898 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002899 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2900 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002901 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002902 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2903 std::string Str("IC " + std::string(IC->Name) + " requires ");
2904 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2905 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002906 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002907 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002908 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002909 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2910 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002911 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002912 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2913 std::string Str("DC " + std::string(DC->Name) + " requires ");
2914 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2915 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002916 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002917 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002918 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002919 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2920 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002921 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002922 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2923 std::string Str("AT " + std::string(AT->Name) + " requires ");
2924 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2925 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002926 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002927 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002928 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002929 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2930 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002931 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002932 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2933 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2934 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2935 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002936 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002937 createSysAlias(TLBI->Encoding, Operands, S);
Oliver Stannard224428c2018-09-27 13:47:40 +00002938 } else if (Mnemonic == "cfp" || Mnemonic == "dvp" || Mnemonic == "cpp") {
2939 const AArch64PRCTX::PRCTX *PRCTX = AArch64PRCTX::lookupPRCTXByName(Op);
2940 if (!PRCTX)
2941 return TokError("invalid operand for prediction restriction instruction");
2942 else if (!PRCTX->haveFeatures(getSTI().getFeatureBits())) {
2943 std::string Str(
2944 Mnemonic.upper() + std::string(PRCTX->Name) + " requires ");
2945 setRequiredFeatureString(PRCTX->getRequiredFeatures(), Str);
2946 return TokError(Str.c_str());
2947 }
2948 uint16_t PRCTX_Op2 =
2949 Mnemonic == "cfp" ? 4 :
2950 Mnemonic == "dvp" ? 5 :
2951 Mnemonic == "cpp" ? 7 :
2952 0;
2953 assert(PRCTX_Op2 && "Invalid mnemonic for prediction restriction instruction");
2954 createSysAlias(PRCTX->Encoding << 3 | PRCTX_Op2 , Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002955 }
2956
Tim Northover3b0846e2014-05-24 12:50:23 +00002957 Parser.Lex(); // Eat operand.
2958
2959 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2960 bool HasRegister = false;
2961
2962 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002963 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002964 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2965 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002966 HasRegister = true;
2967 }
2968
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002969 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002970 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002971 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002972 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002973
Nirav Davee833c6c2016-11-08 18:31:04 +00002974 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2975 return true;
2976
Tim Northover3b0846e2014-05-24 12:50:23 +00002977 return false;
2978}
2979
Alex Bradbury58eba092016-11-01 16:32:05 +00002980OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002981AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002982 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002983 const AsmToken &Tok = Parser.getTok();
2984
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002985 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2986 TokError("'csync' operand expected");
2987 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002988 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002989 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002990 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002991 const MCExpr *ImmVal;
2992 SMLoc ExprLoc = getLoc();
2993 if (getParser().parseExpression(ImmVal))
2994 return MatchOperand_ParseFail;
2995 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2996 if (!MCE) {
2997 Error(ExprLoc, "immediate value expected for barrier operand");
2998 return MatchOperand_ParseFail;
2999 }
3000 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
3001 Error(ExprLoc, "barrier operand out of range");
3002 return MatchOperand_ParseFail;
3003 }
Tim Northovere6ae6762016-07-05 21:23:04 +00003004 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
3005 Operands.push_back(AArch64Operand::CreateBarrier(
3006 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003007 return MatchOperand_Success;
3008 }
3009
3010 if (Tok.isNot(AsmToken::Identifier)) {
3011 TokError("invalid operand for instruction");
3012 return MatchOperand_ParseFail;
3013 }
3014
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003015 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003016 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003017 auto DB = AArch64DB::lookupDBByName(Tok.getString());
3018 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003019 TokError("'sy' or #imm operand expected");
3020 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003021 // The only valid named option for TSB is 'csync'
3022 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
3023 TokError("'csync' operand expected");
3024 return MatchOperand_ParseFail;
3025 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00003026 TokError("invalid barrier option name");
3027 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003028 }
3029
Tim Northovere6ae6762016-07-05 21:23:04 +00003030 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00003031 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003032 Parser.Lex(); // Consume the option
3033
3034 return MatchOperand_Success;
3035}
3036
Alex Bradbury58eba092016-11-01 16:32:05 +00003037OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003038AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003039 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003040 const AsmToken &Tok = Parser.getTok();
3041
3042 if (Tok.isNot(AsmToken::Identifier))
3043 return MatchOperand_NoMatch;
3044
Tim Northovere6ae6762016-07-05 21:23:04 +00003045 int MRSReg, MSRReg;
3046 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
3047 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
3048 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
3049 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
3050 } else
3051 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00003052
Tim Northovere6ae6762016-07-05 21:23:04 +00003053 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
3054 unsigned PStateImm = -1;
3055 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
3056 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00003057
Tim Northovere6ae6762016-07-05 21:23:04 +00003058 Operands.push_back(
3059 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
3060 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003061 Parser.Lex(); // Eat identifier
3062
3063 return MatchOperand_Success;
3064}
3065
Florian Hahnc4422242017-11-07 13:07:50 +00003066/// tryParseNeonVectorRegister - Parse a vector register operand.
3067bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003068 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003069 if (Parser.getTok().isNot(AsmToken::Identifier))
3070 return true;
3071
3072 SMLoc S = getLoc();
3073 // Check for a vector register specifier first.
3074 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003075 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00003076 OperandMatchResultTy Res =
3077 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
3078 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00003079 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00003080
3081 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
3082 if (!KindRes)
3083 return true;
3084
3085 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00003086 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00003087 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
3088 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00003089
Tim Northover3b0846e2014-05-24 12:50:23 +00003090 // If there was an explicit qualifier, that goes on as a literal text
3091 // operand.
3092 if (!Kind.empty())
3093 Operands.push_back(
3094 AArch64Operand::CreateToken(Kind, false, S, getContext()));
3095
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003096 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3097}
3098
3099OperandMatchResultTy
3100AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003101 SMLoc SIdx = getLoc();
3102 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003103 const MCExpr *ImmVal;
3104 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003105 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003106 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3107 if (!MCE) {
3108 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003109 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003110 }
3111
3112 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003113
Nirav Davee833c6c2016-11-08 18:31:04 +00003114 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003115 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003116
3117 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3118 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003119 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003120 }
3121
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003122 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003123}
3124
Sander de Smalen73937b72018-04-11 07:36:10 +00003125// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00003126// optional kind specifier. If it is a register specifier, eat the token
3127// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00003128OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00003129AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00003130 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00003131 MCAsmParser &Parser = getParser();
3132 const AsmToken &Tok = Parser.getTok();
3133
Florian Hahn91f11e52017-11-07 16:45:48 +00003134 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00003135 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003136
3137 StringRef Name = Tok.getString();
3138 // If there is a kind specifier, it's separated from the register name by
3139 // a '.'.
3140 size_t Start = 0, Next = Name.find('.');
3141 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003142 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003143
3144 if (RegNum) {
3145 if (Next != StringRef::npos) {
3146 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003147 if (!isValidVectorKind(Kind, MatchKind)) {
3148 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003149 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003150 }
3151 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003152 Parser.Lex(); // Eat the register token.
3153
3154 Reg = RegNum;
3155 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003156 }
3157
Sander de Smalen8e607342017-11-15 15:44:43 +00003158 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003159}
3160
Sander de Smalencd6be962017-12-20 11:02:42 +00003161/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3162OperandMatchResultTy
3163AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3164 // Check for a SVE predicate register specifier first.
3165 const SMLoc S = getLoc();
3166 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003167 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003168 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003169 if (Res != MatchOperand_Success)
3170 return Res;
3171
Sander de Smalen73937b72018-04-11 07:36:10 +00003172 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3173 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003174 return MatchOperand_NoMatch;
3175
Sander de Smalen73937b72018-04-11 07:36:10 +00003176 unsigned ElementWidth = KindRes->second;
3177 Operands.push_back(AArch64Operand::CreateVectorReg(
3178 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3179 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003180
Sander de Smalen7868e742018-01-09 11:17:06 +00003181 // Not all predicates are followed by a '/m' or '/z'.
3182 MCAsmParser &Parser = getParser();
3183 if (Parser.getTok().isNot(AsmToken::Slash))
3184 return MatchOperand_Success;
3185
3186 // But when they do they shouldn't have an element type suffix.
3187 if (!Kind.empty()) {
3188 Error(S, "not expecting size suffix");
3189 return MatchOperand_ParseFail;
3190 }
3191
3192 // Add a literal slash as operand
3193 Operands.push_back(
3194 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3195
3196 Parser.Lex(); // Eat the slash.
3197
3198 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003199 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003200 if (Pred != "z" && Pred != "m") {
3201 Error(getLoc(), "expecting 'm' or 'z' predication");
3202 return MatchOperand_ParseFail;
3203 }
3204
3205 // Add zero/merge token.
3206 const char *ZM = Pred == "z" ? "z" : "m";
3207 Operands.push_back(
3208 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3209
3210 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003211 return MatchOperand_Success;
3212}
3213
Sander de Smalen50d87022018-04-19 07:35:08 +00003214/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003215bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003216 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003217 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003218 return false;
3219
Sander de Smalen149916d2018-04-20 07:24:20 +00003220 // Otherwise try for a scalar register.
3221 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3222 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003223
Sander de Smalen149916d2018-04-20 07:24:20 +00003224 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003225}
3226
3227bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003228 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003229 bool HasELFModifier = false;
3230 AArch64MCExpr::VariantKind RefKind;
3231
Nirav Davee833c6c2016-11-08 18:31:04 +00003232 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003233 HasELFModifier = true;
3234
Nirav Davee833c6c2016-11-08 18:31:04 +00003235 if (Parser.getTok().isNot(AsmToken::Identifier))
3236 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003237
3238 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3239 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3240 .Case("lo12", AArch64MCExpr::VK_LO12)
3241 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3242 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3243 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3244 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3245 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3246 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3247 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3248 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3249 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3250 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3251 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3252 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3253 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3254 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3255 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3256 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3257 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3258 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3259 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3260 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3261 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3262 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3263 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3264 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3265 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3266 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3267 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3268 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3269 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3270 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3271 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3272 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3273 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3274 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003275 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3276 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003277 .Default(AArch64MCExpr::VK_INVALID);
3278
Nirav Davee833c6c2016-11-08 18:31:04 +00003279 if (RefKind == AArch64MCExpr::VK_INVALID)
3280 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003281
3282 Parser.Lex(); // Eat identifier
3283
Nirav Davee833c6c2016-11-08 18:31:04 +00003284 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003285 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003286 }
3287
3288 if (getParser().parseExpression(ImmVal))
3289 return true;
3290
3291 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003292 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003293
3294 return false;
3295}
3296
Sander de Smalen650234b2018-04-12 11:40:52 +00003297template <RegKind VectorKind>
3298OperandMatchResultTy
3299AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3300 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003301 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003302 if (!Parser.getTok().is(AsmToken::LCurly))
3303 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003304
3305 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003306 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003307 bool NoMatchIsError) {
3308 auto RegTok = Parser.getTok();
3309 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3310 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003311 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003312 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003313 llvm_unreachable("Expected a valid vector kind");
3314 }
3315
Sander de Smalen650234b2018-04-12 11:40:52 +00003316 if (RegTok.isNot(AsmToken::Identifier) ||
3317 ParseRes == MatchOperand_ParseFail ||
3318 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3319 Error(Loc, "vector register expected");
3320 return MatchOperand_ParseFail;
3321 }
3322
3323 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003324 };
3325
Tim Northover3b0846e2014-05-24 12:50:23 +00003326 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003327 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003328 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003329
Tim Northover3b0846e2014-05-24 12:50:23 +00003330 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003331 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003332 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3333
3334 // Put back the original left bracket if there was no match, so that
3335 // different types of list-operands can be matched (e.g. SVE, Neon).
3336 if (ParseRes == MatchOperand_NoMatch)
3337 Parser.getLexer().UnLex(LCurly);
3338
3339 if (ParseRes != MatchOperand_Success)
3340 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003341
Tim Northover3b0846e2014-05-24 12:50:23 +00003342 int64_t PrevReg = FirstReg;
3343 unsigned Count = 1;
3344
Nirav Davee833c6c2016-11-08 18:31:04 +00003345 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003346 SMLoc Loc = getLoc();
3347 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003348
Sander de Smalen50d87022018-04-19 07:35:08 +00003349 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003350 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3351 if (ParseRes != MatchOperand_Success)
3352 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003353
Tim Northover3b0846e2014-05-24 12:50:23 +00003354 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003355 if (Kind != NextKind) {
3356 Error(Loc, "mismatched register size suffix");
3357 return MatchOperand_ParseFail;
3358 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003359
3360 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3361
3362 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003363 Error(Loc, "invalid number of vectors");
3364 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003365 }
3366
3367 Count += Space;
3368 }
3369 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003370 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003371 SMLoc Loc = getLoc();
3372 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003373 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003374 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3375 if (ParseRes != MatchOperand_Success)
3376 return ParseRes;
3377
Tim Northover3b0846e2014-05-24 12:50:23 +00003378 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003379 if (Kind != NextKind) {
3380 Error(Loc, "mismatched register size suffix");
3381 return MatchOperand_ParseFail;
3382 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003383
3384 // Registers must be incremental (with wraparound at 31)
3385 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003386 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3387 Error(Loc, "registers must be sequential");
3388 return MatchOperand_ParseFail;
3389 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003390
3391 PrevReg = Reg;
3392 ++Count;
3393 }
3394 }
3395
Nirav Davee833c6c2016-11-08 18:31:04 +00003396 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003397 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003398
Sander de Smalen650234b2018-04-12 11:40:52 +00003399 if (Count > 4) {
3400 Error(S, "invalid number of vectors");
3401 return MatchOperand_ParseFail;
3402 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003403
3404 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003405 unsigned ElementWidth = 0;
3406 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003407 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003408 std::tie(NumElements, ElementWidth) = *VK;
3409 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003410
3411 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003412 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3413 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003414
Sander de Smalen650234b2018-04-12 11:40:52 +00003415 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003416}
3417
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003418/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3419bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003420 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3421 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003422 return true;
3423
3424 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3425}
3426
Alex Bradbury58eba092016-11-01 16:32:05 +00003427OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003428AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003429 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003430
Sander de Smalen50d87022018-04-19 07:35:08 +00003431 unsigned RegNum;
3432 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3433 if (Res != MatchOperand_Success)
3434 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003435
Nirav Davee833c6c2016-11-08 18:31:04 +00003436 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003437 Operands.push_back(AArch64Operand::CreateReg(
3438 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003439 return MatchOperand_Success;
3440 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003441
Nirav Davee833c6c2016-11-08 18:31:04 +00003442 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003443
Sander de Smalen50d87022018-04-19 07:35:08 +00003444 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003445 Error(getLoc(), "index must be absent or #0");
3446 return MatchOperand_ParseFail;
3447 }
3448
3449 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003450 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003451 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3452 Error(getLoc(), "index must be absent or #0");
3453 return MatchOperand_ParseFail;
3454 }
3455
Sander de Smalen50d87022018-04-19 07:35:08 +00003456 Operands.push_back(AArch64Operand::CreateReg(
3457 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003458 return MatchOperand_Success;
3459}
3460
Sander de Smalen0325e302018-07-02 07:34:52 +00003461template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003462OperandMatchResultTy
3463AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3464 SMLoc StartLoc = getLoc();
3465
3466 unsigned RegNum;
3467 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3468 if (Res != MatchOperand_Success)
3469 return Res;
3470
3471 // No shift/extend is the default.
3472 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3473 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003474 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003475 return MatchOperand_Success;
3476 }
3477
3478 // Eat the comma
3479 getParser().Lex();
3480
3481 // Match the shift
3482 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3483 Res = tryParseOptionalShiftExtend(ExtOpnd);
3484 if (Res != MatchOperand_Success)
3485 return Res;
3486
3487 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003488 Operands.push_back(AArch64Operand::CreateReg(
3489 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3490 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3491 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003492
3493 return MatchOperand_Success;
3494}
3495
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003496bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003497 MCAsmParser &Parser = getParser();
3498
3499 // Some SVE instructions have a decoration after the immediate, i.e.
3500 // "mul vl". We parse them here and add tokens, which must be present in the
3501 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003502 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3503 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003504 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003505 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003506 return true;
3507
Sander de Smalen5c625982018-04-13 12:56:14 +00003508 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003509 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003510 Parser.Lex(); // Eat the "mul"
3511
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003512 if (NextIsVL) {
3513 Operands.push_back(
3514 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3515 Parser.Lex(); // Eat the "vl"
3516 return false;
3517 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003518
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003519 if (NextIsHash) {
3520 Parser.Lex(); // Eat the #
3521 SMLoc S = getLoc();
3522
3523 // Parse immediate operand.
3524 const MCExpr *ImmVal;
3525 if (!Parser.parseExpression(ImmVal))
3526 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3527 Operands.push_back(AArch64Operand::CreateImm(
3528 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3529 getContext()));
3530 return MatchOperand_Success;
3531 }
3532 }
3533
3534 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003535}
3536
Tim Northover3b0846e2014-05-24 12:50:23 +00003537/// parseOperand - Parse a arm instruction operand. For now this parses the
3538/// operand regardless of the mnemonic.
3539bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3540 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003541 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003542
3543 OperandMatchResultTy ResTy =
3544 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3545
Tim Northover3b0846e2014-05-24 12:50:23 +00003546 // Check if the current operand has a custom associated parser, if so, try to
3547 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003548 if (ResTy == MatchOperand_Success)
3549 return false;
3550 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3551 // there was a match, but an error occurred, in which case, just return that
3552 // the operand parsing failed.
3553 if (ResTy == MatchOperand_ParseFail)
3554 return true;
3555
3556 // Nothing custom, so do general case parsing.
3557 SMLoc S, E;
3558 switch (getLexer().getKind()) {
3559 default: {
3560 SMLoc S = getLoc();
3561 const MCExpr *Expr;
3562 if (parseSymbolicImmVal(Expr))
3563 return Error(S, "invalid operand");
3564
3565 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3566 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3567 return false;
3568 }
3569 case AsmToken::LBrac: {
3570 SMLoc Loc = Parser.getTok().getLoc();
3571 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3572 getContext()));
3573 Parser.Lex(); // Eat '['
3574
3575 // There's no comma after a '[', so we can parse the next operand
3576 // immediately.
3577 return parseOperand(Operands, false, false);
3578 }
3579 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003580 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003581 case AsmToken::Identifier: {
3582 // If we're expecting a Condition Code operand, then just parse that.
3583 if (isCondCode)
3584 return parseCondCode(Operands, invertCondCode);
3585
3586 // If it's a register name, parse it.
3587 if (!parseRegister(Operands))
3588 return false;
3589
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003590 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3591 // by SVE instructions.
3592 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003593 return false;
3594
Tim Northover3b0846e2014-05-24 12:50:23 +00003595 // This could be an optional "shift" or "extend" operand.
3596 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3597 // We can only continue if no tokens were eaten.
3598 if (GotShift != MatchOperand_NoMatch)
3599 return GotShift;
3600
3601 // This was not a register so parse other operands that start with an
3602 // identifier (like labels) as expressions and create them as immediates.
3603 const MCExpr *IdVal;
3604 S = getLoc();
3605 if (getParser().parseExpression(IdVal))
3606 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003607 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3608 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3609 return false;
3610 }
3611 case AsmToken::Integer:
3612 case AsmToken::Real:
3613 case AsmToken::Hash: {
3614 // #42 -> immediate.
3615 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003616
3617 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003618
3619 // Parse a negative sign
3620 bool isNegative = false;
3621 if (Parser.getTok().is(AsmToken::Minus)) {
3622 isNegative = true;
3623 // We need to consume this token only when we have a Real, otherwise
3624 // we let parseSymbolicImmVal take care of it
3625 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3626 Parser.Lex();
3627 }
3628
3629 // The only Real that should come through here is a literal #0.0 for
3630 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3631 // so convert the value.
3632 const AsmToken &Tok = Parser.getTok();
3633 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003634 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003635 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3636 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3637 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003638 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003639 return TokError("unexpected floating point literal");
3640 else if (IntVal != 0 || isNegative)
3641 return TokError("expected floating-point constant #0.0");
3642 Parser.Lex(); // Eat the token.
3643
3644 Operands.push_back(
3645 AArch64Operand::CreateToken("#0", false, S, getContext()));
3646 Operands.push_back(
3647 AArch64Operand::CreateToken(".0", false, S, getContext()));
3648 return false;
3649 }
3650
3651 const MCExpr *ImmVal;
3652 if (parseSymbolicImmVal(ImmVal))
3653 return true;
3654
3655 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3656 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3657 return false;
3658 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003659 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003660 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003661 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003662 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003663 Parser.Lex(); // Eat '='
3664 const MCExpr *SubExprVal;
3665 if (getParser().parseExpression(SubExprVal))
3666 return true;
3667
David Peixottoae5ba762014-07-18 16:05:14 +00003668 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003669 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003670 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003671
3672 bool IsXReg =
3673 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3674 Operands[1]->getReg());
3675
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003676 MCContext& Ctx = getContext();
3677 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3678 // 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 +00003679 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003680 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3681 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3682 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3683 ShiftAmt += 16;
3684 Imm >>= 16;
3685 }
3686 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3687 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3688 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003689 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003690 if (ShiftAmt)
3691 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3692 ShiftAmt, true, S, E, Ctx));
3693 return false;
3694 }
David Peixottoae5ba762014-07-18 16:05:14 +00003695 APInt Simm = APInt(64, Imm << ShiftAmt);
3696 // check if the immediate is an unsigned or signed 32-bit int for W regs
3697 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3698 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003699 }
3700 // 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 +00003701 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003702 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003703 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3704 return false;
3705 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003706 }
3707}
3708
Sander de Smalen0325e302018-07-02 07:34:52 +00003709bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3710 const MCParsedAsmOperand &Op2) const {
3711 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3712 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3713 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3714 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3715 return MCTargetAsmParser::regsEqual(Op1, Op2);
3716
3717 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3718 "Testing equality of non-scalar registers not supported");
3719
3720 // Check if a registers match their sub/super register classes.
3721 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3722 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3723 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3724 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3725 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3726 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3727 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3728 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3729
3730 return false;
3731}
3732
Tim Northover3b0846e2014-05-24 12:50:23 +00003733/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3734/// operands.
3735bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3736 StringRef Name, SMLoc NameLoc,
3737 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003738 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003739 Name = StringSwitch<StringRef>(Name.lower())
3740 .Case("beq", "b.eq")
3741 .Case("bne", "b.ne")
3742 .Case("bhs", "b.hs")
3743 .Case("bcs", "b.cs")
3744 .Case("blo", "b.lo")
3745 .Case("bcc", "b.cc")
3746 .Case("bmi", "b.mi")
3747 .Case("bpl", "b.pl")
3748 .Case("bvs", "b.vs")
3749 .Case("bvc", "b.vc")
3750 .Case("bhi", "b.hi")
3751 .Case("bls", "b.ls")
3752 .Case("bge", "b.ge")
3753 .Case("blt", "b.lt")
3754 .Case("bgt", "b.gt")
3755 .Case("ble", "b.le")
3756 .Case("bal", "b.al")
3757 .Case("bnv", "b.nv")
3758 .Default(Name);
3759
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003760 // First check for the AArch64-specific .req directive.
3761 if (Parser.getTok().is(AsmToken::Identifier) &&
3762 Parser.getTok().getIdentifier() == ".req") {
3763 parseDirectiveReq(Name, NameLoc);
3764 // We always return 'error' for this, as we're done with this
3765 // statement and don't need to match the 'instruction."
3766 return true;
3767 }
3768
Tim Northover3b0846e2014-05-24 12:50:23 +00003769 // Create the leading tokens for the mnemonic, split by '.' characters.
3770 size_t Start = 0, Next = Name.find('.');
3771 StringRef Head = Name.slice(Start, Next);
3772
Oliver Stannard224428c2018-09-27 13:47:40 +00003773 // IC, DC, AT, TLBI and Prediction invalidation instructions are aliases for
3774 // the SYS instruction.
3775 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi" ||
3776 Head == "cfp" || Head == "dvp" || Head == "cpp")
Nirav Davee833c6c2016-11-08 18:31:04 +00003777 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003778
3779 Operands.push_back(
3780 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3781 Mnemonic = Head;
3782
3783 // Handle condition codes for a branch mnemonic
3784 if (Head == "b" && Next != StringRef::npos) {
3785 Start = Next;
3786 Next = Name.find('.', Start + 1);
3787 Head = Name.slice(Start + 1, Next);
3788
3789 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3790 (Head.data() - Name.data()));
3791 AArch64CC::CondCode CC = parseCondCodeString(Head);
3792 if (CC == AArch64CC::Invalid)
3793 return Error(SuffixLoc, "invalid condition code");
3794 Operands.push_back(
3795 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3796 Operands.push_back(
3797 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3798 }
3799
3800 // Add the remaining tokens in the mnemonic.
3801 while (Next != StringRef::npos) {
3802 Start = Next;
3803 Next = Name.find('.', Start + 1);
3804 Head = Name.slice(Start, Next);
3805 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3806 (Head.data() - Name.data()) + 1);
3807 Operands.push_back(
3808 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3809 }
3810
3811 // Conditional compare instructions have a Condition Code operand, which needs
3812 // to be parsed and an immediate operand created.
3813 bool condCodeFourthOperand =
3814 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3815 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3816 Head == "csinc" || Head == "csinv" || Head == "csneg");
3817
3818 // These instructions are aliases to some of the conditional select
3819 // instructions. However, the condition code is inverted in the aliased
3820 // instruction.
3821 //
3822 // FIXME: Is this the correct way to handle these? Or should the parser
3823 // generate the aliased instructions directly?
3824 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3825 bool condCodeThirdOperand =
3826 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3827
3828 // Read the remaining operands.
3829 if (getLexer().isNot(AsmToken::EndOfStatement)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003830
Oliver Stannardc4190282018-10-02 10:04:39 +00003831 unsigned N = 1;
3832 do {
Tim Northover3b0846e2014-05-24 12:50:23 +00003833 // Parse and remember the operand.
3834 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3835 (N == 3 && condCodeThirdOperand) ||
3836 (N == 2 && condCodeSecondOperand),
3837 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003838 return true;
3839 }
3840
3841 // After successfully parsing some operands there are two special cases to
3842 // consider (i.e. notional operands not separated by commas). Both are due
3843 // to memory specifiers:
3844 // + An RBrac will end an address for load/store/prefetch
3845 // + An '!' will indicate a pre-indexed operation.
3846 //
3847 // It's someone else's responsibility to make sure these tokens are sane
3848 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003849
Nirav Davee833c6c2016-11-08 18:31:04 +00003850 SMLoc RLoc = Parser.getTok().getLoc();
3851 if (parseOptionalToken(AsmToken::RBrac))
3852 Operands.push_back(
3853 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3854 SMLoc ELoc = Parser.getTok().getLoc();
3855 if (parseOptionalToken(AsmToken::Exclaim))
3856 Operands.push_back(
3857 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003858
3859 ++N;
Oliver Stannardc4190282018-10-02 10:04:39 +00003860 } while (parseOptionalToken(AsmToken::Comma));
Tim Northover3b0846e2014-05-24 12:50:23 +00003861 }
3862
Nirav Davee833c6c2016-11-08 18:31:04 +00003863 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3864 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003865
Tim Northover3b0846e2014-05-24 12:50:23 +00003866 return false;
3867}
3868
Sander de Smalen9b333092018-07-30 15:42:46 +00003869static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3870 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3871 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3872 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3873 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3874 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3875 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3876 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3877}
3878
Tim Northover3b0846e2014-05-24 12:50:23 +00003879// FIXME: This entire function is a giant hack to provide us with decent
3880// operand range validation/diagnostics until TableGen/MC can be extended
3881// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003882bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3883 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003884 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003885 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3886
3887 // A prefix only applies to the instruction following it. Here we extract
3888 // prefix information for the next instruction before validating the current
3889 // one so that in the case of failure we don't erronously continue using the
3890 // current prefix.
3891 PrefixInfo Prefix = NextPrefix;
3892 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3893
3894 // Before validating the instruction in isolation we run through the rules
3895 // applicable when it follows a prefix instruction.
3896 // NOTE: brk & hlt can be prefixed but require no additional validation.
3897 if (Prefix.isActive() &&
3898 (Inst.getOpcode() != AArch64::BRK) &&
3899 (Inst.getOpcode() != AArch64::HLT)) {
3900
3901 // Prefixed intructions must have a destructive operand.
3902 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3903 AArch64::NotDestructive)
3904 return Error(IDLoc, "instruction is unpredictable when following a"
3905 " movprfx, suggest replacing movprfx with mov");
3906
3907 // Destination operands must match.
3908 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3909 return Error(Loc[0], "instruction is unpredictable when following a"
3910 " movprfx writing to a different destination");
3911
3912 // Destination operand must not be used in any other location.
3913 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3914 if (Inst.getOperand(i).isReg() &&
3915 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3916 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3917 return Error(Loc[0], "instruction is unpredictable when following a"
3918 " movprfx and destination also used as non-destructive"
3919 " source");
3920 }
3921
3922 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3923 if (Prefix.isPredicated()) {
3924 int PgIdx = -1;
3925
3926 // Find the instructions general predicate.
3927 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3928 if (Inst.getOperand(i).isReg() &&
3929 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3930 PgIdx = i;
3931 break;
3932 }
3933
3934 // Instruction must be predicated if the movprfx is predicated.
3935 if (PgIdx == -1 ||
3936 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3937 return Error(IDLoc, "instruction is unpredictable when following a"
3938 " predicated movprfx, suggest using unpredicated movprfx");
3939
3940 // Instruction must use same general predicate as the movprfx.
3941 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3942 return Error(IDLoc, "instruction is unpredictable when following a"
3943 " predicated movprfx using a different general predicate");
3944
3945 // Instruction element type must match the movprfx.
3946 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3947 return Error(IDLoc, "instruction is unpredictable when following a"
3948 " predicated movprfx with a different element size");
3949 }
3950 }
3951
Tim Northover3b0846e2014-05-24 12:50:23 +00003952 // Check for indexed addressing modes w/ the base register being the
3953 // same as a destination/source register or pair load where
3954 // the Rt == Rt2. All of those are undefined behaviour.
3955 switch (Inst.getOpcode()) {
3956 case AArch64::LDPSWpre:
3957 case AArch64::LDPWpost:
3958 case AArch64::LDPWpre:
3959 case AArch64::LDPXpost:
3960 case AArch64::LDPXpre: {
3961 unsigned Rt = Inst.getOperand(1).getReg();
3962 unsigned Rt2 = Inst.getOperand(2).getReg();
3963 unsigned Rn = Inst.getOperand(3).getReg();
3964 if (RI->isSubRegisterEq(Rn, Rt))
3965 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3966 "is also a destination");
3967 if (RI->isSubRegisterEq(Rn, Rt2))
3968 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3969 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003970 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003971 }
3972 case AArch64::LDPDi:
3973 case AArch64::LDPQi:
3974 case AArch64::LDPSi:
3975 case AArch64::LDPSWi:
3976 case AArch64::LDPWi:
3977 case AArch64::LDPXi: {
3978 unsigned Rt = Inst.getOperand(0).getReg();
3979 unsigned Rt2 = Inst.getOperand(1).getReg();
3980 if (Rt == Rt2)
3981 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3982 break;
3983 }
3984 case AArch64::LDPDpost:
3985 case AArch64::LDPDpre:
3986 case AArch64::LDPQpost:
3987 case AArch64::LDPQpre:
3988 case AArch64::LDPSpost:
3989 case AArch64::LDPSpre:
3990 case AArch64::LDPSWpost: {
3991 unsigned Rt = Inst.getOperand(1).getReg();
3992 unsigned Rt2 = Inst.getOperand(2).getReg();
3993 if (Rt == Rt2)
3994 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3995 break;
3996 }
3997 case AArch64::STPDpost:
3998 case AArch64::STPDpre:
3999 case AArch64::STPQpost:
4000 case AArch64::STPQpre:
4001 case AArch64::STPSpost:
4002 case AArch64::STPSpre:
4003 case AArch64::STPWpost:
4004 case AArch64::STPWpre:
4005 case AArch64::STPXpost:
4006 case AArch64::STPXpre: {
4007 unsigned Rt = Inst.getOperand(1).getReg();
4008 unsigned Rt2 = Inst.getOperand(2).getReg();
4009 unsigned Rn = Inst.getOperand(3).getReg();
4010 if (RI->isSubRegisterEq(Rn, Rt))
4011 return Error(Loc[0], "unpredictable STP instruction, writeback base "
4012 "is also a source");
4013 if (RI->isSubRegisterEq(Rn, Rt2))
4014 return Error(Loc[1], "unpredictable STP instruction, writeback base "
4015 "is also a source");
4016 break;
4017 }
4018 case AArch64::LDRBBpre:
4019 case AArch64::LDRBpre:
4020 case AArch64::LDRHHpre:
4021 case AArch64::LDRHpre:
4022 case AArch64::LDRSBWpre:
4023 case AArch64::LDRSBXpre:
4024 case AArch64::LDRSHWpre:
4025 case AArch64::LDRSHXpre:
4026 case AArch64::LDRSWpre:
4027 case AArch64::LDRWpre:
4028 case AArch64::LDRXpre:
4029 case AArch64::LDRBBpost:
4030 case AArch64::LDRBpost:
4031 case AArch64::LDRHHpost:
4032 case AArch64::LDRHpost:
4033 case AArch64::LDRSBWpost:
4034 case AArch64::LDRSBXpost:
4035 case AArch64::LDRSHWpost:
4036 case AArch64::LDRSHXpost:
4037 case AArch64::LDRSWpost:
4038 case AArch64::LDRWpost:
4039 case AArch64::LDRXpost: {
4040 unsigned Rt = Inst.getOperand(1).getReg();
4041 unsigned Rn = Inst.getOperand(2).getReg();
4042 if (RI->isSubRegisterEq(Rn, Rt))
4043 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
4044 "is also a source");
4045 break;
4046 }
4047 case AArch64::STRBBpost:
4048 case AArch64::STRBpost:
4049 case AArch64::STRHHpost:
4050 case AArch64::STRHpost:
4051 case AArch64::STRWpost:
4052 case AArch64::STRXpost:
4053 case AArch64::STRBBpre:
4054 case AArch64::STRBpre:
4055 case AArch64::STRHHpre:
4056 case AArch64::STRHpre:
4057 case AArch64::STRWpre:
4058 case AArch64::STRXpre: {
4059 unsigned Rt = Inst.getOperand(1).getReg();
4060 unsigned Rn = Inst.getOperand(2).getReg();
4061 if (RI->isSubRegisterEq(Rn, Rt))
4062 return Error(Loc[0], "unpredictable STR instruction, writeback base "
4063 "is also a source");
4064 break;
4065 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004066 case AArch64::STXRB:
4067 case AArch64::STXRH:
4068 case AArch64::STXRW:
4069 case AArch64::STXRX:
4070 case AArch64::STLXRB:
4071 case AArch64::STLXRH:
4072 case AArch64::STLXRW:
4073 case AArch64::STLXRX: {
4074 unsigned Rs = Inst.getOperand(0).getReg();
4075 unsigned Rt = Inst.getOperand(1).getReg();
4076 unsigned Rn = Inst.getOperand(2).getReg();
4077 if (RI->isSubRegisterEq(Rt, Rs) ||
4078 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4079 return Error(Loc[0],
4080 "unpredictable STXR instruction, status is also a source");
4081 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00004082 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004083 case AArch64::STXPW:
4084 case AArch64::STXPX:
4085 case AArch64::STLXPW:
4086 case AArch64::STLXPX: {
4087 unsigned Rs = Inst.getOperand(0).getReg();
4088 unsigned Rt1 = Inst.getOperand(1).getReg();
4089 unsigned Rt2 = Inst.getOperand(2).getReg();
4090 unsigned Rn = Inst.getOperand(3).getReg();
4091 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
4092 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4093 return Error(Loc[0],
4094 "unpredictable STXP instruction, status is also a source");
4095 break;
4096 }
Oliver Stannardc4190282018-10-02 10:04:39 +00004097 case AArch64::LDGV: {
4098 unsigned Rt = Inst.getOperand(0).getReg();
4099 unsigned Rn = Inst.getOperand(1).getReg();
4100 if (RI->isSubRegisterEq(Rt, Rn)) {
4101 return Error(Loc[0],
4102 "unpredictable LDGV instruction, writeback register is also "
4103 "the target register");
4104 }
4105 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00004106 }
4107
Tim Northover3b0846e2014-05-24 12:50:23 +00004108
4109 // Now check immediate ranges. Separate from the above as there is overlap
4110 // in the instructions being checked and this keeps the nested conditionals
4111 // to a minimum.
4112 switch (Inst.getOpcode()) {
4113 case AArch64::ADDSWri:
4114 case AArch64::ADDSXri:
4115 case AArch64::ADDWri:
4116 case AArch64::ADDXri:
4117 case AArch64::SUBSWri:
4118 case AArch64::SUBSXri:
4119 case AArch64::SUBWri:
4120 case AArch64::SUBXri: {
4121 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4122 // some slight duplication here.
4123 if (Inst.getOperand(2).isExpr()) {
4124 const MCExpr *Expr = Inst.getOperand(2).getExpr();
4125 AArch64MCExpr::VariantKind ELFRefKind;
4126 MCSymbolRefExpr::VariantKind DarwinRefKind;
4127 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00004128 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
4129
4130 // Only allow these with ADDXri.
4131 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4132 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4133 Inst.getOpcode() == AArch64::ADDXri)
4134 return false;
4135
4136 // Only allow these with ADDXri/ADDWri
4137 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4138 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4139 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4140 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4141 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4142 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4143 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00004144 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4145 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4146 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004147 (Inst.getOpcode() == AArch64::ADDXri ||
4148 Inst.getOpcode() == AArch64::ADDWri))
4149 return false;
4150
4151 // Don't allow symbol refs in the immediate field otherwise
4152 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4153 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4154 // 'cmp w0, 'borked')
4155 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004156 }
Diana Picusc93518d2016-10-11 09:17:47 +00004157 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004158 }
4159 return false;
4160 }
4161 default:
4162 return false;
4163 }
4164}
4165
Craig Topper05515562017-10-26 06:46:41 +00004166static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
4167 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004168
4169bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004170 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004171 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004172 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004173 case Match_InvalidTiedOperand: {
4174 RegConstraintEqualityTy EqTy =
4175 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4176 .getRegEqualityTy();
4177 switch (EqTy) {
4178 case RegConstraintEqualityTy::EqualsSubReg:
4179 return Error(Loc, "operand must be 64-bit form of destination register");
4180 case RegConstraintEqualityTy::EqualsSuperReg:
4181 return Error(Loc, "operand must be 32-bit form of destination register");
4182 case RegConstraintEqualityTy::EqualsReg:
4183 return Error(Loc, "operand must match destination register");
4184 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004185 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004186 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004187 case Match_MissingFeature:
4188 return Error(Loc,
4189 "instruction requires a CPU feature not currently enabled");
4190 case Match_InvalidOperand:
4191 return Error(Loc, "invalid operand for instruction");
4192 case Match_InvalidSuffix:
4193 return Error(Loc, "invalid type suffix for instruction");
4194 case Match_InvalidCondCode:
4195 return Error(Loc, "expected AArch64 condition code");
4196 case Match_AddSubRegExtendSmall:
4197 return Error(Loc,
4198 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
4199 case Match_AddSubRegExtendLarge:
4200 return Error(Loc,
4201 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4202 case Match_AddSubSecondSource:
4203 return Error(Loc,
4204 "expected compatible register, symbol or integer in range [0, 4095]");
4205 case Match_LogicalSecondSource:
4206 return Error(Loc, "expected compatible register or logical immediate");
4207 case Match_InvalidMovImm32Shift:
4208 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4209 case Match_InvalidMovImm64Shift:
4210 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4211 case Match_AddSubRegShift32:
4212 return Error(Loc,
4213 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4214 case Match_AddSubRegShift64:
4215 return Error(Loc,
4216 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4217 case Match_InvalidFPImm:
4218 return Error(Loc,
4219 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004220 case Match_InvalidMemoryIndexedSImm6:
4221 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004222 case Match_InvalidMemoryIndexedSImm5:
4223 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004224 case Match_InvalidMemoryIndexed1SImm4:
4225 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004226 case Match_InvalidMemoryIndexed2SImm4:
4227 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004228 case Match_InvalidMemoryIndexed3SImm4:
4229 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004230 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004231 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004232 case Match_InvalidMemoryIndexed16SImm4:
4233 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004234 case Match_InvalidMemoryIndexed1SImm6:
4235 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004236 case Match_InvalidMemoryIndexedSImm8:
4237 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004238 case Match_InvalidMemoryIndexedSImm9:
4239 return Error(Loc, "index must be an integer in range [-256, 255].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004240 case Match_InvalidMemoryIndexed16SImm9:
4241 return Error(Loc, "index must be a multiple of 16 in range [-4096, 4080].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004242 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004243 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004244 case Match_InvalidMemoryIndexed4SImm7:
4245 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4246 case Match_InvalidMemoryIndexed8SImm7:
4247 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4248 case Match_InvalidMemoryIndexed16SImm7:
4249 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004250 case Match_InvalidMemoryIndexed8UImm5:
4251 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4252 case Match_InvalidMemoryIndexed4UImm5:
4253 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4254 case Match_InvalidMemoryIndexed2UImm5:
4255 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004256 case Match_InvalidMemoryIndexed8UImm6:
4257 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
Oliver Stannardc4190282018-10-02 10:04:39 +00004258 case Match_InvalidMemoryIndexed16UImm6:
4259 return Error(Loc, "index must be a multiple of 16 in range [0, 1008].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004260 case Match_InvalidMemoryIndexed4UImm6:
4261 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4262 case Match_InvalidMemoryIndexed2UImm6:
4263 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4264 case Match_InvalidMemoryIndexed1UImm6:
4265 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004266 case Match_InvalidMemoryWExtend8:
4267 return Error(Loc,
4268 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4269 case Match_InvalidMemoryWExtend16:
4270 return Error(Loc,
4271 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4272 case Match_InvalidMemoryWExtend32:
4273 return Error(Loc,
4274 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4275 case Match_InvalidMemoryWExtend64:
4276 return Error(Loc,
4277 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4278 case Match_InvalidMemoryWExtend128:
4279 return Error(Loc,
4280 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4281 case Match_InvalidMemoryXExtend8:
4282 return Error(Loc,
4283 "expected 'lsl' or 'sxtx' with optional shift of #0");
4284 case Match_InvalidMemoryXExtend16:
4285 return Error(Loc,
4286 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4287 case Match_InvalidMemoryXExtend32:
4288 return Error(Loc,
4289 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4290 case Match_InvalidMemoryXExtend64:
4291 return Error(Loc,
4292 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4293 case Match_InvalidMemoryXExtend128:
4294 return Error(Loc,
4295 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4296 case Match_InvalidMemoryIndexed1:
4297 return Error(Loc, "index must be an integer in range [0, 4095].");
4298 case Match_InvalidMemoryIndexed2:
4299 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4300 case Match_InvalidMemoryIndexed4:
4301 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4302 case Match_InvalidMemoryIndexed8:
4303 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4304 case Match_InvalidMemoryIndexed16:
4305 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004306 case Match_InvalidImm0_1:
4307 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004308 case Match_InvalidImm0_7:
4309 return Error(Loc, "immediate must be an integer in range [0, 7].");
4310 case Match_InvalidImm0_15:
4311 return Error(Loc, "immediate must be an integer in range [0, 15].");
4312 case Match_InvalidImm0_31:
4313 return Error(Loc, "immediate must be an integer in range [0, 31].");
4314 case Match_InvalidImm0_63:
4315 return Error(Loc, "immediate must be an integer in range [0, 63].");
4316 case Match_InvalidImm0_127:
4317 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004318 case Match_InvalidImm0_255:
4319 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004320 case Match_InvalidImm0_65535:
4321 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4322 case Match_InvalidImm1_8:
4323 return Error(Loc, "immediate must be an integer in range [1, 8].");
4324 case Match_InvalidImm1_16:
4325 return Error(Loc, "immediate must be an integer in range [1, 16].");
4326 case Match_InvalidImm1_32:
4327 return Error(Loc, "immediate must be an integer in range [1, 32].");
4328 case Match_InvalidImm1_64:
4329 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004330 case Match_InvalidSVEAddSubImm8:
4331 return Error(Loc, "immediate must be an integer in range [0, 255]"
4332 " with a shift amount of 0");
4333 case Match_InvalidSVEAddSubImm16:
4334 case Match_InvalidSVEAddSubImm32:
4335 case Match_InvalidSVEAddSubImm64:
4336 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4337 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004338 case Match_InvalidSVECpyImm8:
4339 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4340 " with a shift amount of 0");
4341 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004342 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4343 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004344 case Match_InvalidSVECpyImm32:
4345 case Match_InvalidSVECpyImm64:
4346 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4347 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004348 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004349 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004350 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004351 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004352 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004353 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004354 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004355 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004356 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004357 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004358 case Match_InvalidSVEIndexRange0_63:
4359 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4360 case Match_InvalidSVEIndexRange0_31:
4361 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4362 case Match_InvalidSVEIndexRange0_15:
4363 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4364 case Match_InvalidSVEIndexRange0_7:
4365 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4366 case Match_InvalidSVEIndexRange0_3:
4367 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004368 case Match_InvalidLabel:
4369 return Error(Loc, "expected label or encodable integer pc offset");
4370 case Match_MRS:
4371 return Error(Loc, "expected readable system register");
4372 case Match_MSR:
4373 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004374 case Match_InvalidComplexRotationEven:
4375 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4376 case Match_InvalidComplexRotationOdd:
4377 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004378 case Match_MnemonicFail: {
4379 std::string Suggestion = AArch64MnemonicSpellCheck(
4380 ((AArch64Operand &)*Operands[0]).getToken(),
4381 ComputeAvailableFeatures(STI->getFeatureBits()));
4382 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4383 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004384 case Match_InvalidGPR64shifted8:
4385 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4386 case Match_InvalidGPR64shifted16:
4387 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4388 case Match_InvalidGPR64shifted32:
4389 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4390 case Match_InvalidGPR64shifted64:
4391 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4392 case Match_InvalidGPR64NoXZRshifted8:
4393 return Error(Loc, "register must be x0..x30 without shift");
4394 case Match_InvalidGPR64NoXZRshifted16:
4395 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4396 case Match_InvalidGPR64NoXZRshifted32:
4397 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4398 case Match_InvalidGPR64NoXZRshifted64:
4399 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004400 case Match_InvalidZPR32UXTW8:
4401 case Match_InvalidZPR32SXTW8:
4402 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4403 case Match_InvalidZPR32UXTW16:
4404 case Match_InvalidZPR32SXTW16:
4405 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4406 case Match_InvalidZPR32UXTW32:
4407 case Match_InvalidZPR32SXTW32:
4408 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4409 case Match_InvalidZPR32UXTW64:
4410 case Match_InvalidZPR32SXTW64:
4411 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4412 case Match_InvalidZPR64UXTW8:
4413 case Match_InvalidZPR64SXTW8:
4414 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4415 case Match_InvalidZPR64UXTW16:
4416 case Match_InvalidZPR64SXTW16:
4417 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4418 case Match_InvalidZPR64UXTW32:
4419 case Match_InvalidZPR64SXTW32:
4420 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4421 case Match_InvalidZPR64UXTW64:
4422 case Match_InvalidZPR64SXTW64:
4423 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004424 case Match_InvalidZPR32LSL8:
4425 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4426 case Match_InvalidZPR32LSL16:
4427 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4428 case Match_InvalidZPR32LSL32:
4429 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4430 case Match_InvalidZPR32LSL64:
4431 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004432 case Match_InvalidZPR64LSL8:
4433 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4434 case Match_InvalidZPR64LSL16:
4435 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4436 case Match_InvalidZPR64LSL32:
4437 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4438 case Match_InvalidZPR64LSL64:
4439 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004440 case Match_InvalidZPR0:
4441 return Error(Loc, "expected register without element width sufix");
4442 case Match_InvalidZPR8:
4443 case Match_InvalidZPR16:
4444 case Match_InvalidZPR32:
4445 case Match_InvalidZPR64:
4446 case Match_InvalidZPR128:
4447 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004448 case Match_InvalidZPR_3b8:
4449 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4450 case Match_InvalidZPR_3b16:
4451 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4452 case Match_InvalidZPR_3b32:
4453 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4454 case Match_InvalidZPR_4b16:
4455 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4456 case Match_InvalidZPR_4b32:
4457 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4458 case Match_InvalidZPR_4b64:
4459 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004460 case Match_InvalidSVEPattern:
4461 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004462 case Match_InvalidSVEPredicateAnyReg:
4463 case Match_InvalidSVEPredicateBReg:
4464 case Match_InvalidSVEPredicateHReg:
4465 case Match_InvalidSVEPredicateSReg:
4466 case Match_InvalidSVEPredicateDReg:
4467 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004468 case Match_InvalidSVEPredicate3bAnyReg:
4469 case Match_InvalidSVEPredicate3bBReg:
4470 case Match_InvalidSVEPredicate3bHReg:
4471 case Match_InvalidSVEPredicate3bSReg:
4472 case Match_InvalidSVEPredicate3bDReg:
4473 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004474 case Match_InvalidSVEExactFPImmOperandHalfOne:
4475 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4476 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4477 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4478 case Match_InvalidSVEExactFPImmOperandZeroOne:
4479 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004480 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004481 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004482 }
4483}
4484
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004485static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004486
4487bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4488 OperandVector &Operands,
4489 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004490 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004491 bool MatchingInlineAsm) {
4492 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004493 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4494 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004495
David Blaikie960ea3f2014-06-08 16:18:35 +00004496 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004497 unsigned NumOperands = Operands.size();
4498
4499 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004500 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4501 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004502 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004503 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004504 if (Op3CE) {
4505 uint64_t Op3Val = Op3CE->getValue();
4506 uint64_t NewOp3Val = 0;
4507 uint64_t NewOp4Val = 0;
4508 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004509 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004510 NewOp3Val = (32 - Op3Val) & 0x1f;
4511 NewOp4Val = 31 - Op3Val;
4512 } else {
4513 NewOp3Val = (64 - Op3Val) & 0x3f;
4514 NewOp4Val = 63 - Op3Val;
4515 }
4516
Jim Grosbach13760bd2015-05-30 01:25:56 +00004517 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4518 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004519
4520 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004521 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004522 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004523 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4524 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4525 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004526 }
4527 }
Tim Northover03b99f62015-04-30 18:28:58 +00004528 } else if (NumOperands == 4 && Tok == "bfc") {
4529 // FIXME: Horrible hack to handle BFC->BFM alias.
4530 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4531 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4532 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4533
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004534 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004535 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4536 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4537
4538 if (LSBCE && WidthCE) {
4539 uint64_t LSB = LSBCE->getValue();
4540 uint64_t Width = WidthCE->getValue();
4541
4542 uint64_t RegWidth = 0;
4543 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4544 Op1.getReg()))
4545 RegWidth = 64;
4546 else
4547 RegWidth = 32;
4548
4549 if (LSB >= RegWidth)
4550 return Error(LSBOp.getStartLoc(),
4551 "expected integer in range [0, 31]");
4552 if (Width < 1 || Width > RegWidth)
4553 return Error(WidthOp.getStartLoc(),
4554 "expected integer in range [1, 32]");
4555
4556 uint64_t ImmR = 0;
4557 if (RegWidth == 32)
4558 ImmR = (32 - LSB) & 0x1f;
4559 else
4560 ImmR = (64 - LSB) & 0x3f;
4561
4562 uint64_t ImmS = Width - 1;
4563
4564 if (ImmR != 0 && ImmS >= ImmR)
4565 return Error(WidthOp.getStartLoc(),
4566 "requested insert overflows register");
4567
Jim Grosbach13760bd2015-05-30 01:25:56 +00004568 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4569 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004570 Operands[0] = AArch64Operand::CreateToken(
4571 "bfm", false, Op.getStartLoc(), getContext());
4572 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004573 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4574 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004575 Operands[3] = AArch64Operand::CreateImm(
4576 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4577 Operands.emplace_back(
4578 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4579 WidthOp.getEndLoc(), getContext()));
4580 }
4581 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004582 } else if (NumOperands == 5) {
4583 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4584 // UBFIZ -> UBFM aliases.
4585 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004586 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4587 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4588 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004589
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004590 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004591 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4592 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004593
4594 if (Op3CE && Op4CE) {
4595 uint64_t Op3Val = Op3CE->getValue();
4596 uint64_t Op4Val = Op4CE->getValue();
4597
4598 uint64_t RegWidth = 0;
4599 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004600 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004601 RegWidth = 64;
4602 else
4603 RegWidth = 32;
4604
4605 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004606 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004607 "expected integer in range [0, 31]");
4608 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004609 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004610 "expected integer in range [1, 32]");
4611
4612 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004613 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004614 NewOp3Val = (32 - Op3Val) & 0x1f;
4615 else
4616 NewOp3Val = (64 - Op3Val) & 0x3f;
4617
4618 uint64_t NewOp4Val = Op4Val - 1;
4619
4620 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004621 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004622 "requested insert overflows register");
4623
4624 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004625 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004627 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004628 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004629 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004630 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004631 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004632 if (Tok == "bfi")
4633 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004634 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004635 else if (Tok == "sbfiz")
4636 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004637 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004638 else if (Tok == "ubfiz")
4639 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004640 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004641 else
4642 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004643 }
4644 }
4645
4646 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4647 // UBFX -> UBFM aliases.
4648 } else if (NumOperands == 5 &&
4649 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004650 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4651 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4652 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004653
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004654 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004655 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4656 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004657
4658 if (Op3CE && Op4CE) {
4659 uint64_t Op3Val = Op3CE->getValue();
4660 uint64_t Op4Val = Op4CE->getValue();
4661
4662 uint64_t RegWidth = 0;
4663 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004664 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004665 RegWidth = 64;
4666 else
4667 RegWidth = 32;
4668
4669 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004670 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004671 "expected integer in range [0, 31]");
4672 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004673 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004674 "expected integer in range [1, 32]");
4675
4676 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4677
4678 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004679 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004680 "requested extract overflows register");
4681
4682 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004683 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004684 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004685 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004686 if (Tok == "bfxil")
4687 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004688 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004689 else if (Tok == "sbfx")
4690 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004691 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004692 else if (Tok == "ubfx")
4693 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004694 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004695 else
4696 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004697 }
4698 }
4699 }
4700 }
Tim Northover9097a072017-12-18 10:36:00 +00004701
4702 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4703 // instruction for FP registers correctly in some rare circumstances. Convert
4704 // it to a safe instruction and warn (because silently changing someone's
4705 // assembly is rude).
4706 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4707 NumOperands == 4 && Tok == "movi") {
4708 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4709 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4710 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4711 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4712 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4713 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4714 if (Suffix.lower() == ".2d" &&
4715 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4716 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4717 " correctly on this CPU, converting to equivalent movi.16b");
4718 // Switch the suffix to .16b.
4719 unsigned Idx = Op1.isToken() ? 1 : 2;
4720 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4721 getContext());
4722 }
4723 }
4724 }
4725
Tim Northover3b0846e2014-05-24 12:50:23 +00004726 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4727 // InstAlias can't quite handle this since the reg classes aren't
4728 // subclasses.
4729 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4730 // The source register can be Wn here, but the matcher expects a
4731 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004732 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004733 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004734 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004735 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4736 Op.getStartLoc(), Op.getEndLoc(),
4737 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004738 }
4739 }
4740 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4741 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004742 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004743 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004744 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004745 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004746 // The source register can be Wn here, but the matcher expects a
4747 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004748 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004749 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004750 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004751 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4752 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004753 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004754 }
4755 }
4756 }
4757 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4758 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004759 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004760 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004761 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004762 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004763 // The source register can be Wn here, but the matcher expects a
4764 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004765 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004766 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004767 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004768 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4769 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004770 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004771 }
4772 }
4773 }
4774
Tim Northover3b0846e2014-05-24 12:50:23 +00004775 MCInst Inst;
4776 // First try to match against the secondary set of tables containing the
4777 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4778 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004779 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004780
4781 // If that fails, try against the alternate table containing long-form NEON:
4782 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004783 if (MatchResult != Match_Success) {
4784 // But first, save the short-form match result: we can use it in case the
4785 // long-form match also fails.
4786 auto ShortFormNEONErrorInfo = ErrorInfo;
4787 auto ShortFormNEONMatchResult = MatchResult;
4788
Tim Northover3b0846e2014-05-24 12:50:23 +00004789 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004790 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004791
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004792 // Now, both matches failed, and the long-form match failed on the mnemonic
4793 // suffix token operand. The short-form match failure is probably more
4794 // relevant: use it instead.
4795 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004796 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004797 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4798 MatchResult = ShortFormNEONMatchResult;
4799 ErrorInfo = ShortFormNEONErrorInfo;
4800 }
4801 }
4802
Tim Northover3b0846e2014-05-24 12:50:23 +00004803 switch (MatchResult) {
4804 case Match_Success: {
4805 // Perform range checking and other semantic validations
4806 SmallVector<SMLoc, 8> OperandLocs;
4807 NumOperands = Operands.size();
4808 for (unsigned i = 1; i < NumOperands; ++i)
4809 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004810 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004811 return true;
4812
4813 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004814 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004815 return false;
4816 }
4817 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004818 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004819 // Special case the error message for the very common case where only
4820 // a single subtarget feature is missing (neon, e.g.).
4821 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004822 uint64_t Mask = 1;
4823 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4824 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004825 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004826 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004827 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004828 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004829 }
4830 return Error(IDLoc, Msg);
4831 }
4832 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004833 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004834 case Match_InvalidOperand: {
4835 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004836
Tim Northover26bb14e2014-08-18 11:49:42 +00004837 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004838 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004839 return Error(IDLoc, "too few operands for instruction",
4840 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004841
David Blaikie960ea3f2014-06-08 16:18:35 +00004842 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004843 if (ErrorLoc == SMLoc())
4844 ErrorLoc = IDLoc;
4845 }
4846 // If the match failed on a suffix token operand, tweak the diagnostic
4847 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004848 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4849 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004850 MatchResult = Match_InvalidSuffix;
4851
Sander de Smalen0325e302018-07-02 07:34:52 +00004852 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004853 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004854 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004855 case Match_InvalidMemoryIndexed1:
4856 case Match_InvalidMemoryIndexed2:
4857 case Match_InvalidMemoryIndexed4:
4858 case Match_InvalidMemoryIndexed8:
4859 case Match_InvalidMemoryIndexed16:
4860 case Match_InvalidCondCode:
4861 case Match_AddSubRegExtendSmall:
4862 case Match_AddSubRegExtendLarge:
4863 case Match_AddSubSecondSource:
4864 case Match_LogicalSecondSource:
4865 case Match_AddSubRegShift32:
4866 case Match_AddSubRegShift64:
4867 case Match_InvalidMovImm32Shift:
4868 case Match_InvalidMovImm64Shift:
4869 case Match_InvalidFPImm:
4870 case Match_InvalidMemoryWExtend8:
4871 case Match_InvalidMemoryWExtend16:
4872 case Match_InvalidMemoryWExtend32:
4873 case Match_InvalidMemoryWExtend64:
4874 case Match_InvalidMemoryWExtend128:
4875 case Match_InvalidMemoryXExtend8:
4876 case Match_InvalidMemoryXExtend16:
4877 case Match_InvalidMemoryXExtend32:
4878 case Match_InvalidMemoryXExtend64:
4879 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004880 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004881 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004882 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004883 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004884 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004885 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004886 case Match_InvalidMemoryIndexed4SImm7:
4887 case Match_InvalidMemoryIndexed8SImm7:
4888 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004889 case Match_InvalidMemoryIndexed8UImm5:
4890 case Match_InvalidMemoryIndexed4UImm5:
4891 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004892 case Match_InvalidMemoryIndexed1UImm6:
4893 case Match_InvalidMemoryIndexed2UImm6:
4894 case Match_InvalidMemoryIndexed4UImm6:
4895 case Match_InvalidMemoryIndexed8UImm6:
Oliver Stannardc4190282018-10-02 10:04:39 +00004896 case Match_InvalidMemoryIndexed16UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004897 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004898 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004899 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004900 case Match_InvalidMemoryIndexedSImm9:
Oliver Stannardc4190282018-10-02 10:04:39 +00004901 case Match_InvalidMemoryIndexed16SImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004902 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004903 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004904 case Match_InvalidImm0_7:
4905 case Match_InvalidImm0_15:
4906 case Match_InvalidImm0_31:
4907 case Match_InvalidImm0_63:
4908 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004909 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004910 case Match_InvalidImm0_65535:
4911 case Match_InvalidImm1_8:
4912 case Match_InvalidImm1_16:
4913 case Match_InvalidImm1_32:
4914 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004915 case Match_InvalidSVEAddSubImm8:
4916 case Match_InvalidSVEAddSubImm16:
4917 case Match_InvalidSVEAddSubImm32:
4918 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004919 case Match_InvalidSVECpyImm8:
4920 case Match_InvalidSVECpyImm16:
4921 case Match_InvalidSVECpyImm32:
4922 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004923 case Match_InvalidIndexRange1_1:
4924 case Match_InvalidIndexRange0_15:
4925 case Match_InvalidIndexRange0_7:
4926 case Match_InvalidIndexRange0_3:
4927 case Match_InvalidIndexRange0_1:
4928 case Match_InvalidSVEIndexRange0_63:
4929 case Match_InvalidSVEIndexRange0_31:
4930 case Match_InvalidSVEIndexRange0_15:
4931 case Match_InvalidSVEIndexRange0_7:
4932 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004933 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004934 case Match_InvalidComplexRotationEven:
4935 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004936 case Match_InvalidGPR64shifted8:
4937 case Match_InvalidGPR64shifted16:
4938 case Match_InvalidGPR64shifted32:
4939 case Match_InvalidGPR64shifted64:
4940 case Match_InvalidGPR64NoXZRshifted8:
4941 case Match_InvalidGPR64NoXZRshifted16:
4942 case Match_InvalidGPR64NoXZRshifted32:
4943 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004944 case Match_InvalidZPR32UXTW8:
4945 case Match_InvalidZPR32UXTW16:
4946 case Match_InvalidZPR32UXTW32:
4947 case Match_InvalidZPR32UXTW64:
4948 case Match_InvalidZPR32SXTW8:
4949 case Match_InvalidZPR32SXTW16:
4950 case Match_InvalidZPR32SXTW32:
4951 case Match_InvalidZPR32SXTW64:
4952 case Match_InvalidZPR64UXTW8:
4953 case Match_InvalidZPR64SXTW8:
4954 case Match_InvalidZPR64UXTW16:
4955 case Match_InvalidZPR64SXTW16:
4956 case Match_InvalidZPR64UXTW32:
4957 case Match_InvalidZPR64SXTW32:
4958 case Match_InvalidZPR64UXTW64:
4959 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004960 case Match_InvalidZPR32LSL8:
4961 case Match_InvalidZPR32LSL16:
4962 case Match_InvalidZPR32LSL32:
4963 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004964 case Match_InvalidZPR64LSL8:
4965 case Match_InvalidZPR64LSL16:
4966 case Match_InvalidZPR64LSL32:
4967 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004968 case Match_InvalidZPR0:
4969 case Match_InvalidZPR8:
4970 case Match_InvalidZPR16:
4971 case Match_InvalidZPR32:
4972 case Match_InvalidZPR64:
4973 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004974 case Match_InvalidZPR_3b8:
4975 case Match_InvalidZPR_3b16:
4976 case Match_InvalidZPR_3b32:
4977 case Match_InvalidZPR_4b16:
4978 case Match_InvalidZPR_4b32:
4979 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004980 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004981 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004982 case Match_InvalidSVEPredicateBReg:
4983 case Match_InvalidSVEPredicateHReg:
4984 case Match_InvalidSVEPredicateSReg:
4985 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004986 case Match_InvalidSVEPredicate3bAnyReg:
4987 case Match_InvalidSVEPredicate3bBReg:
4988 case Match_InvalidSVEPredicate3bHReg:
4989 case Match_InvalidSVEPredicate3bSReg:
4990 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004991 case Match_InvalidSVEExactFPImmOperandHalfOne:
4992 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4993 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004994 case Match_MSR:
4995 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004996 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004997 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004998 // Any time we get here, there's nothing fancy to do. Just get the
4999 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00005000 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00005001 if (ErrorLoc == SMLoc())
5002 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00005003 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00005004 }
5005 }
5006
5007 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00005008}
5009
5010/// ParseDirective parses the arm specific directives
5011bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00005012 const MCObjectFileInfo::Environment Format =
5013 getContext().getObjectFileInfo()->getObjectFileType();
5014 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005015
Tim Northover3b0846e2014-05-24 12:50:23 +00005016 StringRef IDVal = DirectiveID.getIdentifier();
5017 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005018 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00005019 parseDirectiveArch(Loc);
5020 else if (IDVal == ".cpu")
5021 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00005022 else if (IDVal == ".tlsdesccall")
5023 parseDirectiveTLSDescCall(Loc);
5024 else if (IDVal == ".ltorg" || IDVal == ".pool")
5025 parseDirectiveLtorg(Loc);
5026 else if (IDVal == ".unreq")
5027 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00005028 else if (IDVal == ".inst")
5029 parseDirectiveInst(Loc);
Martin Storsjod4590c32018-08-01 06:50:18 +00005030 else if (IsMachO) {
5031 if (IDVal == MCLOHDirectiveName())
5032 parseDirectiveLOH(IDVal, Loc);
5033 else
5034 return true;
5035 } else
Nirav Davee833c6c2016-11-08 18:31:04 +00005036 return true;
5037 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00005038}
5039
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005040static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
5041 SmallVector<StringRef, 4> &RequestedExtensions) {
5042 const bool NoCrypto =
5043 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5044 "nocrypto") != std::end(RequestedExtensions));
5045 const bool Crypto =
5046 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
5047 "crypto") != std::end(RequestedExtensions));
5048
5049 if (!NoCrypto && Crypto) {
5050 switch (ArchKind) {
5051 default:
5052 // Map 'generic' (and others) to sha2 and aes, because
5053 // that was the traditional meaning of crypto.
5054 case AArch64::ArchKind::ARMV8_1A:
5055 case AArch64::ArchKind::ARMV8_2A:
5056 case AArch64::ArchKind::ARMV8_3A:
5057 RequestedExtensions.push_back("sha2");
5058 RequestedExtensions.push_back("aes");
5059 break;
5060 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005061 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005062 RequestedExtensions.push_back("sm4");
5063 RequestedExtensions.push_back("sha3");
5064 RequestedExtensions.push_back("sha2");
5065 RequestedExtensions.push_back("aes");
5066 break;
5067 }
5068 } else if (NoCrypto) {
5069 switch (ArchKind) {
5070 default:
5071 // Map 'generic' (and others) to sha2 and aes, because
5072 // that was the traditional meaning of crypto.
5073 case AArch64::ArchKind::ARMV8_1A:
5074 case AArch64::ArchKind::ARMV8_2A:
5075 case AArch64::ArchKind::ARMV8_3A:
5076 RequestedExtensions.push_back("nosha2");
5077 RequestedExtensions.push_back("noaes");
5078 break;
5079 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00005080 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005081 RequestedExtensions.push_back("nosm4");
5082 RequestedExtensions.push_back("nosha3");
5083 RequestedExtensions.push_back("nosha2");
5084 RequestedExtensions.push_back("noaes");
5085 break;
5086 }
5087 }
5088}
5089
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005090/// parseDirectiveArch
5091/// ::= .arch token
5092bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
5093 SMLoc ArchLoc = getLoc();
5094
5095 StringRef Arch, ExtensionString;
5096 std::tie(Arch, ExtensionString) =
5097 getParser().parseStringToEndOfStatement().trim().split('+');
5098
Florian Hahn67ddd1d2017-07-27 16:27:56 +00005099 AArch64::ArchKind ID = AArch64::parseArch(Arch);
5100 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00005101 return Error(ArchLoc, "unknown arch name");
5102
5103 if (parseToken(AsmToken::EndOfStatement))
5104 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005105
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005106 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00005107 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005108 AArch64::getArchFeatures(ID, AArch64Features);
5109 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
5110 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005111
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005112 MCSubtargetInfo &STI = copySTI();
5113 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
5114 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
5115
5116 SmallVector<StringRef, 4> RequestedExtensions;
5117 if (!ExtensionString.empty())
5118 ExtensionString.split(RequestedExtensions, '+');
5119
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005120 ExpandCryptoAEK(ID, RequestedExtensions);
5121
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005122 FeatureBitset Features = STI.getFeatureBits();
5123 for (auto Name : RequestedExtensions) {
5124 bool EnableFeature = true;
5125
5126 if (Name.startswith_lower("no")) {
5127 EnableFeature = false;
5128 Name = Name.substr(2);
5129 }
5130
5131 for (const auto &Extension : ExtensionMap) {
5132 if (Extension.Name != Name)
5133 continue;
5134
5135 if (Extension.Features.none())
5136 report_fatal_error("unsupported architectural extension: " + Name);
5137
5138 FeatureBitset ToggleFeatures = EnableFeature
5139 ? (~Features & Extension.Features)
5140 : ( Features & Extension.Features);
5141 uint64_t Features =
5142 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5143 setAvailableFeatures(Features);
5144 break;
5145 }
5146 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005147 return false;
5148}
5149
Tim Northover8b96c7e2017-05-15 19:42:15 +00005150static SMLoc incrementLoc(SMLoc L, int Offset) {
5151 return SMLoc::getFromPointer(L.getPointer() + Offset);
5152}
5153
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005154/// parseDirectiveCPU
5155/// ::= .cpu id
5156bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005157 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005158
5159 StringRef CPU, ExtensionString;
5160 std::tie(CPU, ExtensionString) =
5161 getParser().parseStringToEndOfStatement().trim().split('+');
5162
Nirav Davee833c6c2016-11-08 18:31:04 +00005163 if (parseToken(AsmToken::EndOfStatement))
5164 return true;
5165
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005166 SmallVector<StringRef, 4> RequestedExtensions;
5167 if (!ExtensionString.empty())
5168 ExtensionString.split(RequestedExtensions, '+');
5169
5170 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5171 // once that is tablegen'ed
5172 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005173 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005174 return false;
5175 }
5176
5177 MCSubtargetInfo &STI = copySTI();
5178 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005179 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005180
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005181 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5182
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005183 FeatureBitset Features = STI.getFeatureBits();
5184 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005185 // Advance source location past '+'.
5186 CurLoc = incrementLoc(CurLoc, 1);
5187
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005188 bool EnableFeature = true;
5189
5190 if (Name.startswith_lower("no")) {
5191 EnableFeature = false;
5192 Name = Name.substr(2);
5193 }
5194
Tim Northover8b96c7e2017-05-15 19:42:15 +00005195 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005196 for (const auto &Extension : ExtensionMap) {
5197 if (Extension.Name != Name)
5198 continue;
5199
5200 if (Extension.Features.none())
5201 report_fatal_error("unsupported architectural extension: " + Name);
5202
5203 FeatureBitset ToggleFeatures = EnableFeature
5204 ? (~Features & Extension.Features)
5205 : ( Features & Extension.Features);
5206 uint64_t Features =
5207 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5208 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005209 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005210
5211 break;
5212 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005213
5214 if (!FoundExtension)
5215 Error(CurLoc, "unsupported architectural extension");
5216
5217 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005218 }
5219 return false;
5220}
5221
Chad Rosierdcd2a302014-10-22 20:35:57 +00005222/// parseDirectiveInst
5223/// ::= .inst opcode [, ...]
5224bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005225 if (getLexer().is(AsmToken::EndOfStatement))
5226 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005227
Nirav Davee833c6c2016-11-08 18:31:04 +00005228 auto parseOp = [&]() -> bool {
5229 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005230 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005231 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5232 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005233 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005234 if (check(!Value, L, "expected constant expression"))
5235 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005236 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005237 return false;
5238 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005239
Nirav Davee833c6c2016-11-08 18:31:04 +00005240 if (parseMany(parseOp))
5241 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005242 return false;
5243}
5244
Tim Northover3b0846e2014-05-24 12:50:23 +00005245// parseDirectiveTLSDescCall:
5246// ::= .tlsdesccall symbol
5247bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5248 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005249 if (check(getParser().parseIdentifier(Name), L,
5250 "expected symbol after directive") ||
5251 parseToken(AsmToken::EndOfStatement))
5252 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005253
Jim Grosbach6f482002015-05-18 18:43:14 +00005254 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005255 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5256 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005257
5258 MCInst Inst;
5259 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005260 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005261
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005262 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005263 return false;
5264}
5265
5266/// ::= .loh <lohName | lohId> label1, ..., labelN
5267/// The number of arguments depends on the loh identifier.
5268bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005269 MCLOHType Kind;
5270 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5271 if (getParser().getTok().isNot(AsmToken::Integer))
5272 return TokError("expected an identifier or a number in directive");
5273 // We successfully get a numeric value for the identifier.
5274 // Check if it is valid.
5275 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005276 if (Id <= -1U && !isValidMCLOHType(Id))
5277 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005278 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005279 } else {
5280 StringRef Name = getTok().getIdentifier();
5281 // We successfully parse an identifier.
5282 // Check if it is a recognized one.
5283 int Id = MCLOHNameToId(Name);
5284
5285 if (Id == -1)
5286 return TokError("invalid identifier in directive");
5287 Kind = (MCLOHType)Id;
5288 }
5289 // Consume the identifier.
5290 Lex();
5291 // Get the number of arguments of this LOH.
5292 int NbArgs = MCLOHIdToNbArgs(Kind);
5293
5294 assert(NbArgs != -1 && "Invalid number of arguments");
5295
5296 SmallVector<MCSymbol *, 3> Args;
5297 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5298 StringRef Name;
5299 if (getParser().parseIdentifier(Name))
5300 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005301 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005302
5303 if (Idx + 1 == NbArgs)
5304 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005305 if (parseToken(AsmToken::Comma,
5306 "unexpected token in '" + Twine(IDVal) + "' directive"))
5307 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005308 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005309 if (parseToken(AsmToken::EndOfStatement,
5310 "unexpected token in '" + Twine(IDVal) + "' directive"))
5311 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005312
5313 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5314 return false;
5315}
5316
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005317/// parseDirectiveLtorg
5318/// ::= .ltorg | .pool
5319bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005320 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5321 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005322 getTargetStreamer().emitCurrentConstantPool();
5323 return false;
5324}
5325
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005326/// parseDirectiveReq
5327/// ::= name .req registername
5328bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005329 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005330 Parser.Lex(); // Eat the '.req' token.
5331 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005332 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005333 unsigned RegNum;
5334 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005335
Sander de Smalen50d87022018-04-19 07:35:08 +00005336 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005337 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005338 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005339 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005340
Sander de Smalen50d87022018-04-19 07:35:08 +00005341 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005342 return true;
5343
Sander de Smalen50d87022018-04-19 07:35:08 +00005344 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005345 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005346 }
5347
Sander de Smalen50d87022018-04-19 07:35:08 +00005348 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005349 StringRef Kind;
5350 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005351 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005352 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005353
Sander de Smalen50d87022018-04-19 07:35:08 +00005354 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005355 return true;
5356
Sander de Smalen50d87022018-04-19 07:35:08 +00005357 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005358 return Error(SRegLoc,
5359 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005360 }
5361
Sander de Smalen50d87022018-04-19 07:35:08 +00005362 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005363 StringRef Kind;
5364 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005365 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005366
Sander de Smalen50d87022018-04-19 07:35:08 +00005367 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005368 return true;
5369
Sander de Smalen50d87022018-04-19 07:35:08 +00005370 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005371 return Error(SRegLoc,
5372 "sve predicate register without type specifier expected");
5373 }
5374
Sander de Smalen50d87022018-04-19 07:35:08 +00005375 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005376 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005377
5378 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005379 if (parseToken(AsmToken::EndOfStatement,
5380 "unexpected input in .req directive"))
5381 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005382
Sander de Smalen8e607342017-11-15 15:44:43 +00005383 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005384 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005385 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5386
Nirav Dave2364748a2016-09-16 18:30:20 +00005387 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005388}
5389
5390/// parseDirectiveUneq
5391/// ::= .unreq registername
5392bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005393 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005394 if (getTok().isNot(AsmToken::Identifier))
5395 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005396 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5397 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005398 if (parseToken(AsmToken::EndOfStatement))
5399 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005400 return false;
5401}
5402
Tim Northover3b0846e2014-05-24 12:50:23 +00005403bool
5404AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5405 AArch64MCExpr::VariantKind &ELFRefKind,
5406 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5407 int64_t &Addend) {
5408 ELFRefKind = AArch64MCExpr::VK_INVALID;
5409 DarwinRefKind = MCSymbolRefExpr::VK_None;
5410 Addend = 0;
5411
5412 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5413 ELFRefKind = AE->getKind();
5414 Expr = AE->getSubExpr();
5415 }
5416
5417 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5418 if (SE) {
5419 // It's a simple symbol reference with no addend.
5420 DarwinRefKind = SE->getKind();
5421 return true;
5422 }
5423
David Green85d6a552018-09-18 09:44:53 +00005424 // Check that it looks like a symbol + an addend
5425 MCValue Res;
5426 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
5427 if (!Relocatable || !Res.getSymA() || Res.getSymB())
Tim Northover3b0846e2014-05-24 12:50:23 +00005428 return false;
5429
David Green85d6a552018-09-18 09:44:53 +00005430 DarwinRefKind = Res.getSymA()->getKind();
5431 Addend = Res.getConstant();
Tim Northover3b0846e2014-05-24 12:50:23 +00005432
5433 // It's some symbol reference + a constant addend, but really
5434 // shouldn't use both Darwin and ELF syntax.
5435 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5436 DarwinRefKind == MCSymbolRefExpr::VK_None;
5437}
5438
5439/// Force static initialization.
5440extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005441 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5442 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5443 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005444}
5445
5446#define GET_REGISTER_MATCHER
5447#define GET_SUBTARGET_FEATURE_NAME
5448#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005449#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005450#include "AArch64GenAsmMatcher.inc"
5451
5452// Define this matcher function after the auto-generated include so we
5453// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005454unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005455 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005456 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005457 // If the kind is a token for a literal immediate, check if our asm
5458 // operand matches. This is for InstAliases which have a fixed-value
5459 // immediate in the syntax.
5460 int64_t ExpectedVal;
5461 switch (Kind) {
5462 default:
5463 return Match_InvalidOperand;
5464 case MCK__35_0:
5465 ExpectedVal = 0;
5466 break;
5467 case MCK__35_1:
5468 ExpectedVal = 1;
5469 break;
5470 case MCK__35_12:
5471 ExpectedVal = 12;
5472 break;
5473 case MCK__35_16:
5474 ExpectedVal = 16;
5475 break;
5476 case MCK__35_2:
5477 ExpectedVal = 2;
5478 break;
5479 case MCK__35_24:
5480 ExpectedVal = 24;
5481 break;
5482 case MCK__35_3:
5483 ExpectedVal = 3;
5484 break;
5485 case MCK__35_32:
5486 ExpectedVal = 32;
5487 break;
5488 case MCK__35_4:
5489 ExpectedVal = 4;
5490 break;
5491 case MCK__35_48:
5492 ExpectedVal = 48;
5493 break;
5494 case MCK__35_6:
5495 ExpectedVal = 6;
5496 break;
5497 case MCK__35_64:
5498 ExpectedVal = 64;
5499 break;
5500 case MCK__35_8:
5501 ExpectedVal = 8;
5502 break;
5503 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005504 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005505 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005506 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005507 if (!CE)
5508 return Match_InvalidOperand;
5509 if (CE->getValue() == ExpectedVal)
5510 return Match_Success;
5511 return Match_InvalidOperand;
5512}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005513
Alex Bradbury58eba092016-11-01 16:32:05 +00005514OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005515AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5516
5517 SMLoc S = getLoc();
5518
5519 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5520 Error(S, "expected register");
5521 return MatchOperand_ParseFail;
5522 }
5523
Sander de Smalen50d87022018-04-19 07:35:08 +00005524 unsigned FirstReg;
5525 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5526 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005527 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005528
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005529 const MCRegisterClass &WRegClass =
5530 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5531 const MCRegisterClass &XRegClass =
5532 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5533
5534 bool isXReg = XRegClass.contains(FirstReg),
5535 isWReg = WRegClass.contains(FirstReg);
5536 if (!isXReg && !isWReg) {
5537 Error(S, "expected first even register of a "
5538 "consecutive same-size even/odd register pair");
5539 return MatchOperand_ParseFail;
5540 }
5541
5542 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5543 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5544
5545 if (FirstEncoding & 0x1) {
5546 Error(S, "expected first even register of a "
5547 "consecutive same-size even/odd register pair");
5548 return MatchOperand_ParseFail;
5549 }
5550
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005551 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005552 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005553 return MatchOperand_ParseFail;
5554 }
5555 // Eat the comma
5556 getParser().Lex();
5557
5558 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005559 unsigned SecondReg;
5560 Res = tryParseScalarRegister(SecondReg);
5561 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005562 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005563
Eugene Zelenko049b0172017-01-06 00:30:53 +00005564 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005565 (isXReg && !XRegClass.contains(SecondReg)) ||
5566 (isWReg && !WRegClass.contains(SecondReg))) {
5567 Error(E,"expected second odd register of a "
5568 "consecutive same-size even/odd register pair");
5569 return MatchOperand_ParseFail;
5570 }
Joel Jones504bf332016-10-24 13:37:13 +00005571
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005572 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005573 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005574 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5575 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5576 } else {
5577 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5578 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5579 }
5580
Florian Hahnc4422242017-11-07 13:07:50 +00005581 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5582 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005583
5584 return MatchOperand_Success;
5585}
Florian Hahn91f11e52017-11-07 16:45:48 +00005586
Sander de Smaleneb896b12018-04-25 09:26:47 +00005587template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005588OperandMatchResultTy
5589AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005590 const SMLoc S = getLoc();
5591 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005592 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005593 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005594
Sander de Smalen8e607342017-11-15 15:44:43 +00005595 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005596 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005597
5598 if (Res != MatchOperand_Success)
5599 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005600
5601 if (ParseSuffix && Kind.empty())
5602 return MatchOperand_NoMatch;
5603
Sander de Smalen73937b72018-04-11 07:36:10 +00005604 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5605 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005606 return MatchOperand_NoMatch;
5607
Sander de Smalen73937b72018-04-11 07:36:10 +00005608 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005609
5610 // No shift/extend is the default.
5611 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5612 Operands.push_back(AArch64Operand::CreateVectorReg(
5613 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5614
Sander de Smalenc33d6682018-06-04 06:40:55 +00005615 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5616 if (Res == MatchOperand_ParseFail)
5617 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005618 return MatchOperand_Success;
5619 }
5620
5621 // Eat the comma
5622 getParser().Lex();
5623
5624 // Match the shift
5625 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5626 Res = tryParseOptionalShiftExtend(ExtOpnd);
5627 if (Res != MatchOperand_Success)
5628 return Res;
5629
5630 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005631 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005632 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5633 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5634 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005635
5636 return MatchOperand_Success;
5637}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005638
5639OperandMatchResultTy
5640AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5641 MCAsmParser &Parser = getParser();
5642
5643 SMLoc SS = getLoc();
5644 const AsmToken &TokE = Parser.getTok();
5645 bool IsHash = TokE.is(AsmToken::Hash);
5646
5647 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5648 return MatchOperand_NoMatch;
5649
5650 int64_t Pattern;
5651 if (IsHash) {
5652 Parser.Lex(); // Eat hash
5653
5654 // Parse the immediate operand.
5655 const MCExpr *ImmVal;
5656 SS = getLoc();
5657 if (Parser.parseExpression(ImmVal))
5658 return MatchOperand_ParseFail;
5659
5660 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5661 if (!MCE)
5662 return MatchOperand_ParseFail;
5663
5664 Pattern = MCE->getValue();
5665 } else {
5666 // Parse the pattern
5667 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5668 if (!Pat)
5669 return MatchOperand_NoMatch;
5670
5671 Parser.Lex();
5672 Pattern = Pat->Encoding;
5673 assert(Pattern >= 0 && Pattern < 32);
5674 }
5675
5676 Operands.push_back(
5677 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5678 SS, getLoc(), getContext()));
5679
5680 return MatchOperand_Success;
5681}