blob: 8b5db516bad1c39fde06506b89bae4590713eb3d [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);
Tim Northover3b0846e2014-05-24 12:50:23 +0000204 OperandMatchResultTy tryParseAdrpLabel(OperandVector &Operands);
205 OperandMatchResultTy tryParseAdrLabel(OperandVector &Operands);
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000206 template<bool AddFPZeroAsLiteral>
Tim Northover3b0846e2014-05-24 12:50:23 +0000207 OperandMatchResultTy tryParseFPImm(OperandVector &Operands);
Sander de Smalen62770792018-05-25 09:47:52 +0000208 OperandMatchResultTy tryParseImmWithOptionalShift(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000209 OperandMatchResultTy tryParseGPR64sp0Operand(OperandVector &Operands);
Florian Hahnc4422242017-11-07 13:07:50 +0000210 bool tryParseNeonVectorRegister(OperandVector &Operands);
Sander de Smalenc88f9a12018-04-11 14:10:37 +0000211 OperandMatchResultTy tryParseVectorIndex(OperandVector &Operands);
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +0000212 OperandMatchResultTy tryParseGPRSeqPair(OperandVector &Operands);
Sander de Smalen0325e302018-07-02 07:34:52 +0000213 template <bool ParseShiftExtend,
214 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg>
Sander de Smalen149916d2018-04-20 07:24:20 +0000215 OperandMatchResultTy tryParseGPROperand(OperandVector &Operands);
Sander de Smaleneb896b12018-04-25 09:26:47 +0000216 template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +0000217 OperandMatchResultTy tryParseSVEDataVector(OperandVector &Operands);
Sander de Smalencd6be962017-12-20 11:02:42 +0000218 OperandMatchResultTy tryParseSVEPredicateVector(OperandVector &Operands);
Sander de Smalen650234b2018-04-12 11:40:52 +0000219 template <RegKind VectorKind>
220 OperandMatchResultTy tryParseVectorList(OperandVector &Operands,
221 bool ExpectMatch = false);
Sander de Smalen7ab96f52018-01-22 15:29:19 +0000222 OperandMatchResultTy tryParseSVEPattern(OperandVector &Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +0000223
224public:
225 enum AArch64MatchResultTy {
226 Match_InvalidSuffix = FIRST_TARGET_MATCH_RESULT_TY,
227#define GET_OPERAND_DIAGNOSTIC_TYPES
228#include "AArch64GenAsmMatcher.inc"
229 };
Joel Jones504bf332016-10-24 13:37:13 +0000230 bool IsILP32;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000231
Akira Hatanakab11ef082015-11-14 06:35:56 +0000232 AArch64AsmParser(const MCSubtargetInfo &STI, MCAsmParser &Parser,
David Blaikie9f380a32015-03-16 18:06:57 +0000233 const MCInstrInfo &MII, const MCTargetOptions &Options)
Oliver Stannard4191b9e2017-10-11 09:17:43 +0000234 : MCTargetAsmParser(Options, STI, MII) {
Joel Jones504bf332016-10-24 13:37:13 +0000235 IsILP32 = Options.getABIName() == "ilp32";
David Blaikie9f380a32015-03-16 18:06:57 +0000236 MCAsmParserExtension::Initialize(Parser);
Rafael Espindola961d4692014-11-11 05:18:41 +0000237 MCStreamer &S = getParser().getStreamer();
238 if (S.getTargetStreamer() == nullptr)
239 new AArch64TargetStreamer(S);
Tim Northover3b0846e2014-05-24 12:50:23 +0000240
Alex Bradbury0a59f182018-05-23 11:17:20 +0000241 // Alias .hword/.word/xword to the target-independent .2byte/.4byte/.8byte
242 // directives as they have the same form and semantics:
243 /// ::= (.hword | .word | .xword ) [ expression (, expression)* ]
244 Parser.addAliasForDirective(".hword", ".2byte");
245 Parser.addAliasForDirective(".word", ".4byte");
246 Parser.addAliasForDirective(".xword", ".8byte");
247
Tim Northover3b0846e2014-05-24 12:50:23 +0000248 // Initialize the set of available features.
Akira Hatanakabd9fc282015-11-14 05:20:05 +0000249 setAvailableFeatures(ComputeAvailableFeatures(getSTI().getFeatureBits()));
Tim Northover3b0846e2014-05-24 12:50:23 +0000250 }
251
Sander de Smalen0325e302018-07-02 07:34:52 +0000252 bool regsEqual(const MCParsedAsmOperand &Op1,
253 const MCParsedAsmOperand &Op2) const override;
Tim Northover3b0846e2014-05-24 12:50:23 +0000254 bool ParseInstruction(ParseInstructionInfo &Info, StringRef Name,
255 SMLoc NameLoc, OperandVector &Operands) override;
256 bool ParseRegister(unsigned &RegNo, SMLoc &StartLoc, SMLoc &EndLoc) override;
257 bool ParseDirective(AsmToken DirectiveID) override;
David Blaikie960ea3f2014-06-08 16:18:35 +0000258 unsigned validateTargetOperandClass(MCParsedAsmOperand &Op,
Tim Northover3b0846e2014-05-24 12:50:23 +0000259 unsigned Kind) override;
260
261 static bool classifySymbolRef(const MCExpr *Expr,
262 AArch64MCExpr::VariantKind &ELFRefKind,
263 MCSymbolRefExpr::VariantKind &DarwinRefKind,
264 int64_t &Addend);
265};
Tim Northover3b0846e2014-05-24 12:50:23 +0000266
267/// AArch64Operand - Instances of this class represent a parsed AArch64 machine
268/// instruction.
269class AArch64Operand : public MCParsedAsmOperand {
270private:
271 enum KindTy {
272 k_Immediate,
273 k_ShiftedImm,
274 k_CondCode,
275 k_Register,
276 k_VectorList,
277 k_VectorIndex,
278 k_Token,
279 k_SysReg,
280 k_SysCR,
281 k_Prefetch,
282 k_ShiftExtend,
283 k_FPImm,
Oliver Stannarda34e4702015-12-01 10:48:51 +0000284 k_Barrier,
285 k_PSBHint,
Tim Northover3b0846e2014-05-24 12:50:23 +0000286 } Kind;
287
288 SMLoc StartLoc, EndLoc;
289
290 struct TokOp {
291 const char *Data;
292 unsigned Length;
293 bool IsSuffix; // Is the operand actually a suffix on the mnemonic.
294 };
295
Sander de Smalen149916d2018-04-20 07:24:20 +0000296 // Separate shift/extend operand.
297 struct ShiftExtendOp {
298 AArch64_AM::ShiftExtendType Type;
299 unsigned Amount;
300 bool HasExplicitAmount;
301 };
302
Tim Northover3b0846e2014-05-24 12:50:23 +0000303 struct RegOp {
304 unsigned RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +0000305 RegKind Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +0000306 int ElementWidth;
Sander de Smalen149916d2018-04-20 07:24:20 +0000307
Sander de Smalen0325e302018-07-02 07:34:52 +0000308 // The register may be allowed as a different register class,
309 // e.g. for GPR64as32 or GPR32as64.
310 RegConstraintEqualityTy EqualityTy;
311
Sander de Smalen149916d2018-04-20 07:24:20 +0000312 // In some cases the shift/extend needs to be explicitly parsed together
313 // with the register, rather than as a separate operand. This is needed
314 // for addressing modes where the instruction as a whole dictates the
315 // scaling/extend, rather than specific bits in the instruction.
316 // By parsing them as a single operand, we avoid the need to pass an
317 // extra operand in all CodeGen patterns (because all operands need to
318 // have an associated value), and we avoid the need to update TableGen to
319 // accept operands that have no associated bits in the instruction.
320 //
321 // An added benefit of parsing them together is that the assembler
322 // can give a sensible diagnostic if the scaling is not correct.
323 //
324 // The default is 'lsl #0' (HasExplicitAmount = false) if no
325 // ShiftExtend is specified.
326 ShiftExtendOp ShiftExtend;
Tim Northover3b0846e2014-05-24 12:50:23 +0000327 };
328
329 struct VectorListOp {
330 unsigned RegNum;
331 unsigned Count;
332 unsigned NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +0000333 unsigned ElementWidth;
334 RegKind RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +0000335 };
336
337 struct VectorIndexOp {
338 unsigned Val;
339 };
340
341 struct ImmOp {
342 const MCExpr *Val;
343 };
344
345 struct ShiftedImmOp {
346 const MCExpr *Val;
347 unsigned ShiftAmount;
348 };
349
350 struct CondCodeOp {
351 AArch64CC::CondCode Code;
352 };
353
354 struct FPImmOp {
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000355 uint64_t Val; // APFloat value bitcasted to uint64_t.
356 bool IsExact; // describes whether parsed value was exact.
Tim Northover3b0846e2014-05-24 12:50:23 +0000357 };
358
359 struct BarrierOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000360 const char *Data;
361 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000362 unsigned Val; // Not the enum since not all values have names.
Tim Northover3b0846e2014-05-24 12:50:23 +0000363 };
364
365 struct SysRegOp {
366 const char *Data;
367 unsigned Length;
Tim Northover7cd58932015-01-22 17:23:04 +0000368 uint32_t MRSReg;
369 uint32_t MSRReg;
370 uint32_t PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +0000371 };
372
373 struct SysCRImmOp {
374 unsigned Val;
375 };
376
377 struct PrefetchOp {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000378 const char *Data;
379 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000380 unsigned Val;
Tim Northover3b0846e2014-05-24 12:50:23 +0000381 };
382
Oliver Stannarda34e4702015-12-01 10:48:51 +0000383 struct PSBHintOp {
Oliver Stannarda34e4702015-12-01 10:48:51 +0000384 const char *Data;
385 unsigned Length;
Saleem Abdulrasooldab786f2016-08-18 22:35:06 +0000386 unsigned Val;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000387 };
388
Tim Northover3b0846e2014-05-24 12:50:23 +0000389 struct ExtendOp {
390 unsigned Val;
391 };
392
393 union {
394 struct TokOp Tok;
395 struct RegOp Reg;
396 struct VectorListOp VectorList;
397 struct VectorIndexOp VectorIndex;
398 struct ImmOp Imm;
399 struct ShiftedImmOp ShiftedImm;
400 struct CondCodeOp CondCode;
401 struct FPImmOp FPImm;
402 struct BarrierOp Barrier;
403 struct SysRegOp SysReg;
404 struct SysCRImmOp SysCRImm;
405 struct PrefetchOp Prefetch;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000406 struct PSBHintOp PSBHint;
Tim Northover3b0846e2014-05-24 12:50:23 +0000407 struct ShiftExtendOp ShiftExtend;
408 };
409
410 // Keep the MCContext around as the MCExprs may need manipulated during
411 // the add<>Operands() calls.
412 MCContext &Ctx;
413
David Blaikie960ea3f2014-06-08 16:18:35 +0000414public:
David Blaikie9f380a32015-03-16 18:06:57 +0000415 AArch64Operand(KindTy K, MCContext &Ctx) : Kind(K), Ctx(Ctx) {}
Tim Northover3b0846e2014-05-24 12:50:23 +0000416
Tim Northover3b0846e2014-05-24 12:50:23 +0000417 AArch64Operand(const AArch64Operand &o) : MCParsedAsmOperand(), Ctx(o.Ctx) {
418 Kind = o.Kind;
419 StartLoc = o.StartLoc;
420 EndLoc = o.EndLoc;
421 switch (Kind) {
422 case k_Token:
423 Tok = o.Tok;
424 break;
425 case k_Immediate:
426 Imm = o.Imm;
427 break;
428 case k_ShiftedImm:
429 ShiftedImm = o.ShiftedImm;
430 break;
431 case k_CondCode:
432 CondCode = o.CondCode;
433 break;
434 case k_FPImm:
435 FPImm = o.FPImm;
436 break;
437 case k_Barrier:
438 Barrier = o.Barrier;
439 break;
440 case k_Register:
441 Reg = o.Reg;
442 break;
443 case k_VectorList:
444 VectorList = o.VectorList;
445 break;
446 case k_VectorIndex:
447 VectorIndex = o.VectorIndex;
448 break;
449 case k_SysReg:
450 SysReg = o.SysReg;
451 break;
452 case k_SysCR:
453 SysCRImm = o.SysCRImm;
454 break;
455 case k_Prefetch:
456 Prefetch = o.Prefetch;
457 break;
Oliver Stannarda34e4702015-12-01 10:48:51 +0000458 case k_PSBHint:
459 PSBHint = o.PSBHint;
460 break;
Tim Northover3b0846e2014-05-24 12:50:23 +0000461 case k_ShiftExtend:
462 ShiftExtend = o.ShiftExtend;
463 break;
464 }
465 }
466
467 /// getStartLoc - Get the location of the first token of this operand.
468 SMLoc getStartLoc() const override { return StartLoc; }
469 /// getEndLoc - Get the location of the last token of this operand.
Peter Collingbourne0da86302016-10-10 22:49:37 +0000470 SMLoc getEndLoc() const override { return EndLoc; }
Tim Northover3b0846e2014-05-24 12:50:23 +0000471
472 StringRef getToken() const {
473 assert(Kind == k_Token && "Invalid access!");
474 return StringRef(Tok.Data, Tok.Length);
475 }
476
477 bool isTokenSuffix() const {
478 assert(Kind == k_Token && "Invalid access!");
479 return Tok.IsSuffix;
480 }
481
482 const MCExpr *getImm() const {
483 assert(Kind == k_Immediate && "Invalid access!");
484 return Imm.Val;
485 }
486
487 const MCExpr *getShiftedImmVal() const {
488 assert(Kind == k_ShiftedImm && "Invalid access!");
489 return ShiftedImm.Val;
490 }
491
492 unsigned getShiftedImmShift() const {
493 assert(Kind == k_ShiftedImm && "Invalid access!");
494 return ShiftedImm.ShiftAmount;
495 }
496
497 AArch64CC::CondCode getCondCode() const {
498 assert(Kind == k_CondCode && "Invalid access!");
499 return CondCode.Code;
500 }
501
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000502 APFloat getFPImm() const {
503 assert (Kind == k_FPImm && "Invalid access!");
504 return APFloat(APFloat::IEEEdouble(), APInt(64, FPImm.Val, true));
505 }
506
507 bool getFPImmIsExact() const {
508 assert (Kind == k_FPImm && "Invalid access!");
509 return FPImm.IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +0000510 }
511
512 unsigned getBarrier() const {
513 assert(Kind == k_Barrier && "Invalid access!");
514 return Barrier.Val;
515 }
516
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000517 StringRef getBarrierName() const {
518 assert(Kind == k_Barrier && "Invalid access!");
519 return StringRef(Barrier.Data, Barrier.Length);
520 }
521
Tim Northover3b0846e2014-05-24 12:50:23 +0000522 unsigned getReg() const override {
523 assert(Kind == k_Register && "Invalid access!");
524 return Reg.RegNum;
525 }
526
Sander de Smalen0325e302018-07-02 07:34:52 +0000527 RegConstraintEqualityTy getRegEqualityTy() const {
528 assert(Kind == k_Register && "Invalid access!");
529 return Reg.EqualityTy;
530 }
531
Tim Northover3b0846e2014-05-24 12:50:23 +0000532 unsigned getVectorListStart() const {
533 assert(Kind == k_VectorList && "Invalid access!");
534 return VectorList.RegNum;
535 }
536
537 unsigned getVectorListCount() const {
538 assert(Kind == k_VectorList && "Invalid access!");
539 return VectorList.Count;
540 }
541
542 unsigned getVectorIndex() const {
543 assert(Kind == k_VectorIndex && "Invalid access!");
544 return VectorIndex.Val;
545 }
546
547 StringRef getSysReg() const {
548 assert(Kind == k_SysReg && "Invalid access!");
549 return StringRef(SysReg.Data, SysReg.Length);
550 }
551
Tim Northover3b0846e2014-05-24 12:50:23 +0000552 unsigned getSysCR() const {
553 assert(Kind == k_SysCR && "Invalid access!");
554 return SysCRImm.Val;
555 }
556
557 unsigned getPrefetch() const {
558 assert(Kind == k_Prefetch && "Invalid access!");
559 return Prefetch.Val;
560 }
561
Oliver Stannarda34e4702015-12-01 10:48:51 +0000562 unsigned getPSBHint() const {
563 assert(Kind == k_PSBHint && "Invalid access!");
564 return PSBHint.Val;
565 }
566
567 StringRef getPSBHintName() const {
568 assert(Kind == k_PSBHint && "Invalid access!");
569 return StringRef(PSBHint.Data, PSBHint.Length);
570 }
571
Vladimir Sukharev017d10b2015-03-26 17:29:53 +0000572 StringRef getPrefetchName() const {
573 assert(Kind == k_Prefetch && "Invalid access!");
574 return StringRef(Prefetch.Data, Prefetch.Length);
575 }
576
Tim Northover3b0846e2014-05-24 12:50:23 +0000577 AArch64_AM::ShiftExtendType getShiftExtendType() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000578 if (Kind == k_ShiftExtend)
579 return ShiftExtend.Type;
580 if (Kind == k_Register)
581 return Reg.ShiftExtend.Type;
582 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000583 }
584
585 unsigned getShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000586 if (Kind == k_ShiftExtend)
587 return ShiftExtend.Amount;
588 if (Kind == k_Register)
589 return Reg.ShiftExtend.Amount;
590 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000591 }
592
593 bool hasShiftExtendAmount() const {
Sander de Smalen149916d2018-04-20 07:24:20 +0000594 if (Kind == k_ShiftExtend)
595 return ShiftExtend.HasExplicitAmount;
596 if (Kind == k_Register)
597 return Reg.ShiftExtend.HasExplicitAmount;
598 llvm_unreachable("Invalid access!");
Tim Northover3b0846e2014-05-24 12:50:23 +0000599 }
600
601 bool isImm() const override { return Kind == k_Immediate; }
602 bool isMem() const override { return false; }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000603
Sjoerd Meijera3dad802018-07-06 12:32:33 +0000604 bool isUImm6() const {
605 if (!isImm())
606 return false;
607 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
608 if (!MCE)
609 return false;
610 int64_t Val = MCE->getValue();
611 return (Val >= 0 && Val < 64);
612 }
613
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000614 template <int Width> bool isSImm() const { return isSImmScaled<Width, 1>(); }
615
Sander de Smalen50ded902018-04-29 17:33:38 +0000616 template <int Bits, int Scale> DiagnosticPredicate isSImmScaled() const {
617 return isImmScaled<Bits, Scale>(true);
618 }
619
620 template <int Bits, int Scale> DiagnosticPredicate isUImmScaled() const {
621 return isImmScaled<Bits, Scale>(false);
622 }
623
Sander de Smalenfe17a782018-04-26 12:54:42 +0000624 template <int Bits, int Scale>
Sander de Smalen50ded902018-04-29 17:33:38 +0000625 DiagnosticPredicate isImmScaled(bool Signed) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000626 if (!isImm())
Sander de Smalenfe17a782018-04-26 12:54:42 +0000627 return DiagnosticPredicateTy::NoMatch;
628
Tim Northover3b0846e2014-05-24 12:50:23 +0000629 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
630 if (!MCE)
Sander de Smalenfe17a782018-04-26 12:54:42 +0000631 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000632
Sander de Smalen50ded902018-04-29 17:33:38 +0000633 int64_t MinVal, MaxVal;
634 if (Signed) {
635 int64_t Shift = Bits - 1;
636 MinVal = (int64_t(1) << Shift) * -Scale;
637 MaxVal = ((int64_t(1) << Shift) - 1) * Scale;
638 } else {
639 MinVal = 0;
640 MaxVal = ((int64_t(1) << Bits) - 1) * Scale;
641 }
Sander de Smalen5aa809d2018-01-15 12:47:17 +0000642
Tim Northover3b0846e2014-05-24 12:50:23 +0000643 int64_t Val = MCE->getValue();
Sander de Smalenfe17a782018-04-26 12:54:42 +0000644 if (Val >= MinVal && Val <= MaxVal && (Val % Scale) == 0)
645 return DiagnosticPredicateTy::Match;
646
647 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +0000648 }
649
Sander de Smalen0325e302018-07-02 07:34:52 +0000650 DiagnosticPredicate isSVEPattern() const {
Sander de Smalen245e0e62018-01-22 10:46:00 +0000651 if (!isImm())
Sander de Smalen0325e302018-07-02 07:34:52 +0000652 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000653 auto *MCE = dyn_cast<MCConstantExpr>(getImm());
654 if (!MCE)
Sander de Smalen0325e302018-07-02 07:34:52 +0000655 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000656 int64_t Val = MCE->getValue();
Sander de Smalen0325e302018-07-02 07:34:52 +0000657 if (Val >= 0 && Val < 32)
658 return DiagnosticPredicateTy::Match;
659 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen245e0e62018-01-22 10:46:00 +0000660 }
661
David Green85d6a552018-09-18 09:44:53 +0000662 bool isSymbolicUImm12Offset(const MCExpr *Expr) const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000663 AArch64MCExpr::VariantKind ELFRefKind;
664 MCSymbolRefExpr::VariantKind DarwinRefKind;
665 int64_t Addend;
666 if (!AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind, DarwinRefKind,
667 Addend)) {
668 // If we don't understand the expression, assume the best and
669 // let the fixup and relocation code deal with it.
670 return true;
671 }
672
673 if (DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
674 ELFRefKind == AArch64MCExpr::VK_LO12 ||
675 ELFRefKind == AArch64MCExpr::VK_GOT_LO12 ||
676 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
677 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
678 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
679 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
680 ELFRefKind == AArch64MCExpr::VK_GOTTPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000681 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
682 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
683 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) {
Tim Northover3b0846e2014-05-24 12:50:23 +0000684 // Note that we don't range-check the addend. It's adjusted modulo page
685 // size when converted, so there is no "out of range" condition when using
686 // @pageoff.
David Green85d6a552018-09-18 09:44:53 +0000687 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000688 } else if (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF ||
689 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) {
690 // @gotpageoff/@tlvppageoff can only be used directly, not with an addend.
691 return Addend == 0;
692 }
693
694 return false;
695 }
696
697 template <int Scale> bool isUImm12Offset() const {
698 if (!isImm())
699 return false;
700
701 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
702 if (!MCE)
David Green85d6a552018-09-18 09:44:53 +0000703 return isSymbolicUImm12Offset(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +0000704
705 int64_t Val = MCE->getValue();
706 return (Val % Scale) == 0 && Val >= 0 && (Val / Scale) < 0x1000;
707 }
708
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000709 template <int N, int M>
710 bool isImmInRange() const {
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000711 if (!isImm())
712 return false;
713 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
714 if (!MCE)
715 return false;
716 int64_t Val = MCE->getValue();
Sjoerd Meijercb2d9502017-02-16 15:52:22 +0000717 return (Val >= N && Val <= M);
Tim Northover3b0846e2014-05-24 12:50:23 +0000718 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000719
Sander de Smalena1c259c2018-01-29 13:05:38 +0000720 // NOTE: Also used for isLogicalImmNot as anything that can be represented as
721 // a logical immediate can always be represented when inverted.
722 template <typename T>
723 bool isLogicalImm() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000724 if (!isImm())
725 return false;
726 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
727 if (!MCE)
728 return false;
Sander de Smalena1c259c2018-01-29 13:05:38 +0000729
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000730 int64_t Val = MCE->getValue();
Sander de Smalena1c259c2018-01-29 13:05:38 +0000731 int64_t SVal = typename std::make_signed<T>::type(Val);
732 int64_t UVal = typename std::make_unsigned<T>::type(Val);
733 if (Val != SVal && Val != UVal)
Arnaud A. de Grandmaisond7827602014-07-08 09:53:04 +0000734 return false;
Eugene Zelenko049b0172017-01-06 00:30:53 +0000735
Sander de Smalena1c259c2018-01-29 13:05:38 +0000736 return AArch64_AM::isLogicalImmediate(UVal, sizeof(T) * 8);
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +0000737 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000738
Tim Northover3b0846e2014-05-24 12:50:23 +0000739 bool isShiftedImm() const { return Kind == k_ShiftedImm; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000740
Sander de Smalen62770792018-05-25 09:47:52 +0000741 /// Returns the immediate value as a pair of (imm, shift) if the immediate is
742 /// a shifted immediate by value 'Shift' or '0', or if it is an unshifted
743 /// immediate that can be shifted by 'Shift'.
744 template <unsigned Width>
745 Optional<std::pair<int64_t, unsigned> > getShiftedVal() const {
746 if (isShiftedImm() && Width == getShiftedImmShift())
747 if (auto *CE = dyn_cast<MCConstantExpr>(getShiftedImmVal()))
748 return std::make_pair(CE->getValue(), Width);
749
750 if (isImm())
751 if (auto *CE = dyn_cast<MCConstantExpr>(getImm())) {
752 int64_t Val = CE->getValue();
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000753 if ((Val != 0) && (uint64_t(Val >> Width) << Width) == uint64_t(Val))
Sander de Smalen62770792018-05-25 09:47:52 +0000754 return std::make_pair(Val >> Width, Width);
755 else
756 return std::make_pair(Val, 0u);
757 }
758
759 return {};
760 }
761
Tim Northover3b0846e2014-05-24 12:50:23 +0000762 bool isAddSubImm() const {
763 if (!isShiftedImm() && !isImm())
764 return false;
765
766 const MCExpr *Expr;
767
768 // An ADD/SUB shifter is either 'lsl #0' or 'lsl #12'.
769 if (isShiftedImm()) {
770 unsigned Shift = ShiftedImm.ShiftAmount;
771 Expr = ShiftedImm.Val;
772 if (Shift != 0 && Shift != 12)
773 return false;
774 } else {
775 Expr = getImm();
776 }
777
778 AArch64MCExpr::VariantKind ELFRefKind;
779 MCSymbolRefExpr::VariantKind DarwinRefKind;
780 int64_t Addend;
781 if (AArch64AsmParser::classifySymbolRef(Expr, ELFRefKind,
782 DarwinRefKind, Addend)) {
783 return DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF
784 || DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF
785 || (DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGEOFF && Addend == 0)
786 || ELFRefKind == AArch64MCExpr::VK_LO12
787 || ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12
788 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12
789 || ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC
790 || ELFRefKind == AArch64MCExpr::VK_TPREL_HI12
791 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12
792 || ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC
Martin Storsjoc61ff3b2018-03-01 20:42:28 +0000793 || ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12
794 || ELFRefKind == AArch64MCExpr::VK_SECREL_HI12
795 || ELFRefKind == AArch64MCExpr::VK_SECREL_LO12;
Tim Northover3b0846e2014-05-24 12:50:23 +0000796 }
797
Sander de Smalen98686c62018-05-29 10:39:49 +0000798 // If it's a constant, it should be a real immediate in range.
Sander de Smalen62770792018-05-25 09:47:52 +0000799 if (auto ShiftedVal = getShiftedVal<12>())
800 return ShiftedVal->first >= 0 && ShiftedVal->first <= 0xfff;
Diana Picusc93518d2016-10-11 09:17:47 +0000801
802 // If it's an expression, we hope for the best and let the fixup/relocation
803 // code deal with it.
804 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000805 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000806
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000807 bool isAddSubImmNeg() const {
808 if (!isShiftedImm() && !isImm())
809 return false;
810
Sander de Smalen98686c62018-05-29 10:39:49 +0000811 // Otherwise it should be a real negative immediate in range.
812 if (auto ShiftedVal = getShiftedVal<12>())
813 return ShiftedVal->first < 0 && -ShiftedVal->first <= 0xfff;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000814
Sander de Smalen98686c62018-05-29 10:39:49 +0000815 return false;
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +0000816 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000817
Sander de Smalen62770792018-05-25 09:47:52 +0000818 // Signed value in the range -128 to +127. For element widths of
819 // 16 bits or higher it may also be a signed multiple of 256 in the
820 // range -32768 to +32512.
821 // For element-width of 8 bits a range of -128 to 255 is accepted,
822 // since a copy of a byte can be either signed/unsigned.
823 template <typename T>
824 DiagnosticPredicate isSVECpyImm() const {
825 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
826 return DiagnosticPredicateTy::NoMatch;
827
828 bool IsByte =
829 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
830 if (auto ShiftedImm = getShiftedVal<8>())
831 if (!(IsByte && ShiftedImm->second) &&
Sander de Smalen6e2a5b42018-05-25 11:41:04 +0000832 AArch64_AM::isSVECpyImm<T>(uint64_t(ShiftedImm->first)
833 << ShiftedImm->second))
Sander de Smalen62770792018-05-25 09:47:52 +0000834 return DiagnosticPredicateTy::Match;
835
836 return DiagnosticPredicateTy::NearMatch;
837 }
838
Sander de Smalen98686c62018-05-29 10:39:49 +0000839 // Unsigned value in the range 0 to 255. For element widths of
840 // 16 bits or higher it may also be a signed multiple of 256 in the
841 // range 0 to 65280.
842 template <typename T> DiagnosticPredicate isSVEAddSubImm() const {
843 if (!isShiftedImm() && (!isImm() || !isa<MCConstantExpr>(getImm())))
844 return DiagnosticPredicateTy::NoMatch;
845
846 bool IsByte =
847 std::is_same<int8_t, typename std::make_signed<T>::type>::value;
848 if (auto ShiftedImm = getShiftedVal<8>())
849 if (!(IsByte && ShiftedImm->second) &&
850 AArch64_AM::isSVEAddSubImm<T>(ShiftedImm->first
851 << ShiftedImm->second))
852 return DiagnosticPredicateTy::Match;
853
854 return DiagnosticPredicateTy::NearMatch;
855 }
856
Sander de Smalen97ca6b92018-06-01 07:25:46 +0000857 template <typename T> DiagnosticPredicate isSVEPreferredLogicalImm() const {
858 if (isLogicalImm<T>() && !isSVECpyImm<T>())
859 return DiagnosticPredicateTy::Match;
860 return DiagnosticPredicateTy::NoMatch;
861 }
862
Tim Northover3b0846e2014-05-24 12:50:23 +0000863 bool isCondCode() const { return Kind == k_CondCode; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000864
Tim Northover3b0846e2014-05-24 12:50:23 +0000865 bool isSIMDImmType10() const {
866 if (!isImm())
867 return false;
868 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
869 if (!MCE)
870 return false;
871 return AArch64_AM::isAdvSIMDModImmType10(MCE->getValue());
872 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000873
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000874 template<int N>
875 bool isBranchTarget() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000876 if (!isImm())
877 return false;
878 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
879 if (!MCE)
880 return true;
881 int64_t Val = MCE->getValue();
882 if (Val & 0x3)
883 return false;
Sjoerd Meijere22a79e2017-02-20 10:57:54 +0000884 assert(N > 0 && "Branch target immediate cannot be 0 bits!");
885 return (Val >= -((1<<(N-1)) << 2) && Val <= (((1<<(N-1))-1) << 2));
Tim Northover3b0846e2014-05-24 12:50:23 +0000886 }
887
888 bool
889 isMovWSymbol(ArrayRef<AArch64MCExpr::VariantKind> AllowedModifiers) const {
890 if (!isImm())
891 return false;
892
893 AArch64MCExpr::VariantKind ELFRefKind;
894 MCSymbolRefExpr::VariantKind DarwinRefKind;
895 int64_t Addend;
896 if (!AArch64AsmParser::classifySymbolRef(getImm(), ELFRefKind,
897 DarwinRefKind, Addend)) {
898 return false;
899 }
900 if (DarwinRefKind != MCSymbolRefExpr::VK_None)
901 return false;
902
903 for (unsigned i = 0; i != AllowedModifiers.size(); ++i) {
904 if (ELFRefKind == AllowedModifiers[i])
David Green85d6a552018-09-18 09:44:53 +0000905 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +0000906 }
907
908 return false;
909 }
910
911 bool isMovZSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000912 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000913 }
914
915 bool isMovZSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000916 return isMovWSymbol({AArch64MCExpr::VK_ABS_G2, AArch64MCExpr::VK_ABS_G2_S,
917 AArch64MCExpr::VK_TPREL_G2,
918 AArch64MCExpr::VK_DTPREL_G2});
Tim Northover3b0846e2014-05-24 12:50:23 +0000919 }
920
921 bool isMovZSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000922 return isMovWSymbol({
923 AArch64MCExpr::VK_ABS_G1, AArch64MCExpr::VK_ABS_G1_S,
Tim Northover3b0846e2014-05-24 12:50:23 +0000924 AArch64MCExpr::VK_GOTTPREL_G1, AArch64MCExpr::VK_TPREL_G1,
925 AArch64MCExpr::VK_DTPREL_G1,
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000926 });
Tim Northover3b0846e2014-05-24 12:50:23 +0000927 }
928
929 bool isMovZSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000930 return isMovWSymbol({AArch64MCExpr::VK_ABS_G0, AArch64MCExpr::VK_ABS_G0_S,
931 AArch64MCExpr::VK_TPREL_G0,
932 AArch64MCExpr::VK_DTPREL_G0});
Tim Northover3b0846e2014-05-24 12:50:23 +0000933 }
934
935 bool isMovKSymbolG3() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000936 return isMovWSymbol(AArch64MCExpr::VK_ABS_G3);
Tim Northover3b0846e2014-05-24 12:50:23 +0000937 }
938
939 bool isMovKSymbolG2() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000940 return isMovWSymbol(AArch64MCExpr::VK_ABS_G2_NC);
Tim Northover3b0846e2014-05-24 12:50:23 +0000941 }
942
943 bool isMovKSymbolG1() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000944 return isMovWSymbol({AArch64MCExpr::VK_ABS_G1_NC,
945 AArch64MCExpr::VK_TPREL_G1_NC,
946 AArch64MCExpr::VK_DTPREL_G1_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000947 }
948
949 bool isMovKSymbolG0() const {
Benjamin Kramer57a3d082015-03-08 16:07:39 +0000950 return isMovWSymbol(
951 {AArch64MCExpr::VK_ABS_G0_NC, AArch64MCExpr::VK_GOTTPREL_G0_NC,
952 AArch64MCExpr::VK_TPREL_G0_NC, AArch64MCExpr::VK_DTPREL_G0_NC});
Tim Northover3b0846e2014-05-24 12:50:23 +0000953 }
954
955 template<int RegWidth, int Shift>
956 bool isMOVZMovAlias() const {
957 if (!isImm()) return false;
958
959 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
960 if (!CE) return false;
961 uint64_t Value = CE->getValue();
962
Tim Northoverdaa1c012016-06-16 01:42:25 +0000963 return AArch64_AM::isMOVZMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000964 }
965
966 template<int RegWidth, int Shift>
967 bool isMOVNMovAlias() const {
968 if (!isImm()) return false;
969
970 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
971 if (!CE) return false;
972 uint64_t Value = CE->getValue();
973
Tim Northoverdaa1c012016-06-16 01:42:25 +0000974 return AArch64_AM::isMOVNMovAlias(Value, Shift, RegWidth);
Tim Northover3b0846e2014-05-24 12:50:23 +0000975 }
976
Sander de Smalen3cbf1712018-06-15 13:11:49 +0000977 bool isFPImm() const {
978 return Kind == k_FPImm &&
979 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt()) != -1;
980 }
981
Tim Northover3b0846e2014-05-24 12:50:23 +0000982 bool isBarrier() const { return Kind == k_Barrier; }
983 bool isSysReg() const { return Kind == k_SysReg; }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000984
Tim Northover3b0846e2014-05-24 12:50:23 +0000985 bool isMRSSystemRegister() const {
986 if (!isSysReg()) return false;
987
Tim Northover7cd58932015-01-22 17:23:04 +0000988 return SysReg.MRSReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000989 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000990
Tim Northover3b0846e2014-05-24 12:50:23 +0000991 bool isMSRSystemRegister() const {
992 if (!isSysReg()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +0000993 return SysReg.MSRReg != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +0000994 }
Eugene Zelenko049b0172017-01-06 00:30:53 +0000995
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +0000996 bool isSystemPStateFieldWithImm0_1() const {
Tim Northover3b0846e2014-05-24 12:50:23 +0000997 if (!isSysReg()) return false;
Oliver Stannard911ea202015-11-26 15:32:30 +0000998 return (SysReg.PStateField == AArch64PState::PAN ||
Sjoerd Meijer173b7f02018-07-03 12:09:20 +0000999 SysReg.PStateField == AArch64PState::DIT ||
Oliver Stannard911ea202015-11-26 15:32:30 +00001000 SysReg.PStateField == AArch64PState::UAO);
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001001 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001002
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001003 bool isSystemPStateFieldWithImm0_15() const {
1004 if (!isSysReg() || isSystemPStateFieldWithImm0_1()) return false;
Tim Northover7cd58932015-01-22 17:23:04 +00001005 return SysReg.PStateField != -1U;
Tim Northover3b0846e2014-05-24 12:50:23 +00001006 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001007
Florian Hahnc4422242017-11-07 13:07:50 +00001008 bool isReg() const override {
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00001009 return Kind == k_Register;
1010 }
1011
1012 bool isScalarReg() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001013 return Kind == k_Register && Reg.Kind == RegKind::Scalar;
1014 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001015
Florian Hahnc4422242017-11-07 13:07:50 +00001016 bool isNeonVectorReg() const {
1017 return Kind == k_Register && Reg.Kind == RegKind::NeonVector;
1018 }
1019
1020 bool isNeonVectorRegLo() const {
1021 return Kind == k_Register && Reg.Kind == RegKind::NeonVector &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001022 AArch64MCRegisterClasses[AArch64::FPR128_loRegClassID].contains(
1023 Reg.RegNum);
1024 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001025
Sander de Smalencd6be962017-12-20 11:02:42 +00001026 template <unsigned Class> bool isSVEVectorReg() const {
1027 RegKind RK;
1028 switch (Class) {
1029 case AArch64::ZPRRegClassID:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00001030 case AArch64::ZPR_3bRegClassID:
1031 case AArch64::ZPR_4bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001032 RK = RegKind::SVEDataVector;
1033 break;
1034 case AArch64::PPRRegClassID:
Sander de Smalendc5e0812018-01-03 10:15:46 +00001035 case AArch64::PPR_3bRegClassID:
Sander de Smalencd6be962017-12-20 11:02:42 +00001036 RK = RegKind::SVEPredicateVector;
1037 break;
1038 default:
1039 llvm_unreachable("Unsupport register class");
1040 }
1041
1042 return (Kind == k_Register && Reg.Kind == RK) &&
Florian Hahn91f11e52017-11-07 16:45:48 +00001043 AArch64MCRegisterClasses[Class].contains(getReg());
1044 }
1045
Sander de Smalenfd54a782018-06-04 07:07:35 +00001046 template <unsigned Class> bool isFPRasZPR() const {
1047 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1048 AArch64MCRegisterClasses[Class].contains(getReg());
1049 }
1050
Sander de Smalencd6be962017-12-20 11:02:42 +00001051 template <int ElementWidth, unsigned Class>
Sander de Smalen22176a22018-05-16 15:45:17 +00001052 DiagnosticPredicate isSVEPredicateVectorRegOfWidth() const {
1053 if (Kind != k_Register || Reg.Kind != RegKind::SVEPredicateVector)
1054 return DiagnosticPredicateTy::NoMatch;
1055
1056 if (isSVEVectorReg<Class>() &&
1057 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1058 return DiagnosticPredicateTy::Match;
1059
1060 return DiagnosticPredicateTy::NearMatch;
1061 }
1062
1063 template <int ElementWidth, unsigned Class>
1064 DiagnosticPredicate isSVEDataVectorRegOfWidth() const {
1065 if (Kind != k_Register || Reg.Kind != RegKind::SVEDataVector)
1066 return DiagnosticPredicateTy::NoMatch;
1067
1068 if (isSVEVectorReg<Class>() &&
1069 (ElementWidth == 0 || Reg.ElementWidth == ElementWidth))
1070 return DiagnosticPredicateTy::Match;
1071
1072 return DiagnosticPredicateTy::NearMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00001073 }
1074
Sander de Smaleneb896b12018-04-25 09:26:47 +00001075 template <int ElementWidth, unsigned Class,
Sander de Smalen5861c262018-04-30 07:24:38 +00001076 AArch64_AM::ShiftExtendType ShiftExtendTy, int ShiftWidth,
1077 bool ShiftWidthAlwaysSame>
Sander de Smalen22176a22018-05-16 15:45:17 +00001078 DiagnosticPredicate isSVEDataVectorRegWithShiftExtend() const {
1079 auto VectorMatch = isSVEDataVectorRegOfWidth<ElementWidth, Class>();
1080 if (!VectorMatch.isMatch())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001081 return DiagnosticPredicateTy::NoMatch;
1082
Sander de Smalen5861c262018-04-30 07:24:38 +00001083 // Give a more specific diagnostic when the user has explicitly typed in
1084 // a shift-amount that does not match what is expected, but for which
1085 // there is also an unscaled addressing mode (e.g. sxtw/uxtw).
1086 bool MatchShift = getShiftExtendAmount() == Log2_32(ShiftWidth / 8);
1087 if (!MatchShift && (ShiftExtendTy == AArch64_AM::UXTW ||
1088 ShiftExtendTy == AArch64_AM::SXTW) &&
1089 !ShiftWidthAlwaysSame && hasShiftExtendAmount() && ShiftWidth == 8)
1090 return DiagnosticPredicateTy::NoMatch;
1091
1092 if (MatchShift && ShiftExtendTy == getShiftExtendType())
Sander de Smalenfe17a782018-04-26 12:54:42 +00001093 return DiagnosticPredicateTy::Match;
1094
1095 return DiagnosticPredicateTy::NearMatch;
Sander de Smaleneb896b12018-04-25 09:26:47 +00001096 }
1097
Tim Northover3b0846e2014-05-24 12:50:23 +00001098 bool isGPR32as64() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001099 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Tim Northover3b0846e2014-05-24 12:50:23 +00001100 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(Reg.RegNum);
1101 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001102
Sander de Smalen0325e302018-07-02 07:34:52 +00001103 bool isGPR64as32() const {
1104 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1105 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(Reg.RegNum);
1106 }
1107
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001108 bool isWSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001109 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001110 AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID].contains(
1111 Reg.RegNum);
1112 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001113
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001114 bool isXSeqPair() const {
Florian Hahnc4422242017-11-07 13:07:50 +00001115 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00001116 AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID].contains(
1117 Reg.RegNum);
1118 }
Tim Northover3b0846e2014-05-24 12:50:23 +00001119
Sam Parker5f934642017-08-31 09:27:04 +00001120 template<int64_t Angle, int64_t Remainder>
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001121 DiagnosticPredicate isComplexRotation() const {
1122 if (!isImm()) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001123
1124 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(getImm());
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001125 if (!CE) return DiagnosticPredicateTy::NoMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001126 uint64_t Value = CE->getValue();
1127
Sander de Smalen128fdfa2018-07-03 16:01:27 +00001128 if (Value % Angle == Remainder && Value <= 270)
1129 return DiagnosticPredicateTy::Match;
1130 return DiagnosticPredicateTy::NearMatch;
Sam Parker5f934642017-08-31 09:27:04 +00001131 }
1132
Sander de Smalen149916d2018-04-20 07:24:20 +00001133 template <unsigned RegClassID> bool isGPR64() const {
1134 return Kind == k_Register && Reg.Kind == RegKind::Scalar &&
1135 AArch64MCRegisterClasses[RegClassID].contains(getReg());
1136 }
1137
1138 template <unsigned RegClassID, int ExtWidth>
Sander de Smalenfe17a782018-04-26 12:54:42 +00001139 DiagnosticPredicate isGPR64WithShiftExtend() const {
1140 if (Kind != k_Register || Reg.Kind != RegKind::Scalar)
1141 return DiagnosticPredicateTy::NoMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001142
Sander de Smalenfe17a782018-04-26 12:54:42 +00001143 if (isGPR64<RegClassID>() && getShiftExtendType() == AArch64_AM::LSL &&
1144 getShiftExtendAmount() == Log2_32(ExtWidth / 8))
1145 return DiagnosticPredicateTy::Match;
1146 return DiagnosticPredicateTy::NearMatch;
Sander de Smalen149916d2018-04-20 07:24:20 +00001147 }
1148
Tim Northover3b0846e2014-05-24 12:50:23 +00001149 /// Is this a vector list with the type implicit (presumably attached to the
1150 /// instruction itself)?
Sander de Smalen650234b2018-04-12 11:40:52 +00001151 template <RegKind VectorKind, unsigned NumRegs>
1152 bool isImplicitlyTypedVectorList() const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001153 return Kind == k_VectorList && VectorList.Count == NumRegs &&
Sander de Smalen650234b2018-04-12 11:40:52 +00001154 VectorList.NumElements == 0 &&
1155 VectorList.RegisterKind == VectorKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001156 }
1157
Sander de Smalen650234b2018-04-12 11:40:52 +00001158 template <RegKind VectorKind, unsigned NumRegs, unsigned NumElements,
1159 unsigned ElementWidth>
Tim Northover3b0846e2014-05-24 12:50:23 +00001160 bool isTypedVectorList() const {
1161 if (Kind != k_VectorList)
1162 return false;
1163 if (VectorList.Count != NumRegs)
1164 return false;
Sander de Smalen650234b2018-04-12 11:40:52 +00001165 if (VectorList.RegisterKind != VectorKind)
1166 return false;
1167 if (VectorList.ElementWidth != ElementWidth)
Tim Northover3b0846e2014-05-24 12:50:23 +00001168 return false;
1169 return VectorList.NumElements == NumElements;
1170 }
1171
Sander de Smalenc33d6682018-06-04 06:40:55 +00001172 template <int Min, int Max>
1173 DiagnosticPredicate isVectorIndex() const {
1174 if (Kind != k_VectorIndex)
1175 return DiagnosticPredicateTy::NoMatch;
1176 if (VectorIndex.Val >= Min && VectorIndex.Val <= Max)
1177 return DiagnosticPredicateTy::Match;
1178 return DiagnosticPredicateTy::NearMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00001179 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001180
Tim Northover3b0846e2014-05-24 12:50:23 +00001181 bool isToken() const override { return Kind == k_Token; }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001182
Tim Northover3b0846e2014-05-24 12:50:23 +00001183 bool isTokenEqual(StringRef Str) const {
1184 return Kind == k_Token && getToken() == Str;
1185 }
1186 bool isSysCR() const { return Kind == k_SysCR; }
1187 bool isPrefetch() const { return Kind == k_Prefetch; }
Oliver Stannarda34e4702015-12-01 10:48:51 +00001188 bool isPSBHint() const { return Kind == k_PSBHint; }
Tim Northover3b0846e2014-05-24 12:50:23 +00001189 bool isShiftExtend() const { return Kind == k_ShiftExtend; }
1190 bool isShifter() const {
1191 if (!isShiftExtend())
1192 return false;
1193
1194 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1195 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1196 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR ||
1197 ST == AArch64_AM::MSL);
1198 }
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001199
1200 template <unsigned ImmEnum> DiagnosticPredicate isExactFPImm() const {
1201 if (Kind != k_FPImm)
1202 return DiagnosticPredicateTy::NoMatch;
1203
1204 if (getFPImmIsExact()) {
1205 // Lookup the immediate from table of supported immediates.
1206 auto *Desc = AArch64ExactFPImm::lookupExactFPImmByEnum(ImmEnum);
1207 assert(Desc && "Unknown enum value");
1208
1209 // Calculate its FP value.
1210 APFloat RealVal(APFloat::IEEEdouble());
1211 if (RealVal.convertFromString(Desc->Repr, APFloat::rmTowardZero) !=
1212 APFloat::opOK)
1213 llvm_unreachable("FP immediate is not exact");
1214
1215 if (getFPImm().bitwiseIsEqual(RealVal))
1216 return DiagnosticPredicateTy::Match;
1217 }
1218
1219 return DiagnosticPredicateTy::NearMatch;
1220 }
1221
1222 template <unsigned ImmA, unsigned ImmB>
1223 DiagnosticPredicate isExactFPImm() const {
1224 DiagnosticPredicate Res = DiagnosticPredicateTy::NoMatch;
1225 if ((Res = isExactFPImm<ImmA>()))
1226 return DiagnosticPredicateTy::Match;
1227 if ((Res = isExactFPImm<ImmB>()))
1228 return DiagnosticPredicateTy::Match;
1229 return Res;
1230 }
1231
Tim Northover3b0846e2014-05-24 12:50:23 +00001232 bool isExtend() const {
1233 if (!isShiftExtend())
1234 return false;
1235
1236 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1237 return (ET == AArch64_AM::UXTB || ET == AArch64_AM::SXTB ||
1238 ET == AArch64_AM::UXTH || ET == AArch64_AM::SXTH ||
1239 ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW ||
1240 ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1241 ET == AArch64_AM::LSL) &&
1242 getShiftExtendAmount() <= 4;
1243 }
1244
1245 bool isExtend64() const {
1246 if (!isExtend())
1247 return false;
1248 // UXTX and SXTX require a 64-bit source register (the ExtendLSL64 class).
1249 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1250 return ET != AArch64_AM::UXTX && ET != AArch64_AM::SXTX;
1251 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00001252
Tim Northover3b0846e2014-05-24 12:50:23 +00001253 bool isExtendLSL64() const {
1254 if (!isExtend())
1255 return false;
1256 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1257 return (ET == AArch64_AM::UXTX || ET == AArch64_AM::SXTX ||
1258 ET == AArch64_AM::LSL) &&
1259 getShiftExtendAmount() <= 4;
1260 }
1261
1262 template<int Width> bool isMemXExtend() const {
1263 if (!isExtend())
1264 return false;
1265 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1266 return (ET == AArch64_AM::LSL || ET == AArch64_AM::SXTX) &&
1267 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1268 getShiftExtendAmount() == 0);
1269 }
1270
1271 template<int Width> bool isMemWExtend() const {
1272 if (!isExtend())
1273 return false;
1274 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1275 return (ET == AArch64_AM::UXTW || ET == AArch64_AM::SXTW) &&
1276 (getShiftExtendAmount() == Log2_32(Width / 8) ||
1277 getShiftExtendAmount() == 0);
1278 }
1279
1280 template <unsigned width>
1281 bool isArithmeticShifter() const {
1282 if (!isShifter())
1283 return false;
1284
1285 // An arithmetic shifter is LSL, LSR, or ASR.
1286 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1287 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1288 ST == AArch64_AM::ASR) && getShiftExtendAmount() < width;
1289 }
1290
1291 template <unsigned width>
1292 bool isLogicalShifter() const {
1293 if (!isShifter())
1294 return false;
1295
1296 // A logical shifter is LSL, LSR, ASR or ROR.
1297 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1298 return (ST == AArch64_AM::LSL || ST == AArch64_AM::LSR ||
1299 ST == AArch64_AM::ASR || ST == AArch64_AM::ROR) &&
1300 getShiftExtendAmount() < width;
1301 }
1302
1303 bool isMovImm32Shifter() const {
1304 if (!isShifter())
1305 return false;
1306
1307 // A MOVi shifter is LSL of 0, 16, 32, or 48.
1308 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1309 if (ST != AArch64_AM::LSL)
1310 return false;
1311 uint64_t Val = getShiftExtendAmount();
1312 return (Val == 0 || Val == 16);
1313 }
1314
1315 bool isMovImm64Shifter() const {
1316 if (!isShifter())
1317 return false;
1318
1319 // A MOVi shifter is LSL of 0 or 16.
1320 AArch64_AM::ShiftExtendType ST = getShiftExtendType();
1321 if (ST != AArch64_AM::LSL)
1322 return false;
1323 uint64_t Val = getShiftExtendAmount();
1324 return (Val == 0 || Val == 16 || Val == 32 || Val == 48);
1325 }
1326
1327 bool isLogicalVecShifter() const {
1328 if (!isShifter())
1329 return false;
1330
1331 // A logical vector shifter is a left shift by 0, 8, 16, or 24.
1332 unsigned Shift = getShiftExtendAmount();
1333 return getShiftExtendType() == AArch64_AM::LSL &&
1334 (Shift == 0 || Shift == 8 || Shift == 16 || Shift == 24);
1335 }
1336
1337 bool isLogicalVecHalfWordShifter() const {
1338 if (!isLogicalVecShifter())
1339 return false;
1340
1341 // A logical vector shifter is a left shift by 0 or 8.
1342 unsigned Shift = getShiftExtendAmount();
1343 return getShiftExtendType() == AArch64_AM::LSL &&
1344 (Shift == 0 || Shift == 8);
1345 }
1346
1347 bool isMoveVecShifter() const {
1348 if (!isShiftExtend())
1349 return false;
1350
1351 // A logical vector shifter is a left shift by 8 or 16.
1352 unsigned Shift = getShiftExtendAmount();
1353 return getShiftExtendType() == AArch64_AM::MSL &&
1354 (Shift == 8 || Shift == 16);
1355 }
1356
1357 // Fallback unscaled operands are for aliases of LDR/STR that fall back
1358 // to LDUR/STUR when the offset is not legal for the former but is for
1359 // the latter. As such, in addition to checking for being a legal unscaled
1360 // address, also check that it is not a legal scaled address. This avoids
1361 // ambiguity in the matcher.
1362 template<int Width>
1363 bool isSImm9OffsetFB() const {
Sander de Smalen5aa809d2018-01-15 12:47:17 +00001364 return isSImm<9>() && !isUImm12Offset<Width / 8>();
Tim Northover3b0846e2014-05-24 12:50:23 +00001365 }
1366
1367 bool isAdrpLabel() const {
1368 // Validation was handled during parsing, so we just sanity check that
1369 // something didn't go haywire.
1370 if (!isImm())
1371 return false;
1372
1373 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1374 int64_t Val = CE->getValue();
1375 int64_t Min = - (4096 * (1LL << (21 - 1)));
1376 int64_t Max = 4096 * ((1LL << (21 - 1)) - 1);
1377 return (Val % 4096) == 0 && Val >= Min && Val <= Max;
1378 }
1379
1380 return true;
1381 }
1382
1383 bool isAdrLabel() const {
1384 // Validation was handled during parsing, so we just sanity check that
1385 // something didn't go haywire.
1386 if (!isImm())
1387 return false;
1388
1389 if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Imm.Val)) {
1390 int64_t Val = CE->getValue();
1391 int64_t Min = - (1LL << (21 - 1));
1392 int64_t Max = ((1LL << (21 - 1)) - 1);
1393 return Val >= Min && Val <= Max;
1394 }
1395
1396 return true;
1397 }
1398
1399 void addExpr(MCInst &Inst, const MCExpr *Expr) const {
1400 // Add as immediates when possible. Null MCExpr = 0.
1401 if (!Expr)
Jim Grosbache9119e42015-05-13 18:37:00 +00001402 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001403 else if (const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Expr))
Jim Grosbache9119e42015-05-13 18:37:00 +00001404 Inst.addOperand(MCOperand::createImm(CE->getValue()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001405 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001406 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00001407 }
1408
1409 void addRegOperands(MCInst &Inst, unsigned N) const {
1410 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001411 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001412 }
1413
1414 void addGPR32as64Operands(MCInst &Inst, unsigned N) const {
1415 assert(N == 1 && "Invalid number of operands!");
1416 assert(
1417 AArch64MCRegisterClasses[AArch64::GPR64RegClassID].contains(getReg()));
1418
1419 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1420 uint32_t Reg = RI->getRegClass(AArch64::GPR32RegClassID).getRegister(
1421 RI->getEncodingValue(getReg()));
1422
Jim Grosbache9119e42015-05-13 18:37:00 +00001423 Inst.addOperand(MCOperand::createReg(Reg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001424 }
1425
Sander de Smalen0325e302018-07-02 07:34:52 +00001426 void addGPR64as32Operands(MCInst &Inst, unsigned N) const {
1427 assert(N == 1 && "Invalid number of operands!");
1428 assert(
1429 AArch64MCRegisterClasses[AArch64::GPR32RegClassID].contains(getReg()));
1430
1431 const MCRegisterInfo *RI = Ctx.getRegisterInfo();
1432 uint32_t Reg = RI->getRegClass(AArch64::GPR64RegClassID).getRegister(
1433 RI->getEncodingValue(getReg()));
1434
1435 Inst.addOperand(MCOperand::createReg(Reg));
1436 }
1437
Sander de Smalenfd54a782018-06-04 07:07:35 +00001438 template <int Width>
1439 void addFPRasZPRRegOperands(MCInst &Inst, unsigned N) const {
1440 unsigned Base;
1441 switch (Width) {
1442 case 8: Base = AArch64::B0; break;
1443 case 16: Base = AArch64::H0; break;
1444 case 32: Base = AArch64::S0; break;
1445 case 64: Base = AArch64::D0; break;
1446 case 128: Base = AArch64::Q0; break;
1447 default:
1448 llvm_unreachable("Unsupported width");
1449 }
1450 Inst.addOperand(MCOperand::createReg(AArch64::Z0 + getReg() - Base));
1451 }
1452
Tim Northover3b0846e2014-05-24 12:50:23 +00001453 void addVectorReg64Operands(MCInst &Inst, unsigned N) const {
1454 assert(N == 1 && "Invalid number of operands!");
1455 assert(
1456 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001457 Inst.addOperand(MCOperand::createReg(AArch64::D0 + getReg() - AArch64::Q0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001458 }
1459
1460 void addVectorReg128Operands(MCInst &Inst, unsigned N) const {
1461 assert(N == 1 && "Invalid number of operands!");
1462 assert(
1463 AArch64MCRegisterClasses[AArch64::FPR128RegClassID].contains(getReg()));
Jim Grosbache9119e42015-05-13 18:37:00 +00001464 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001465 }
1466
1467 void addVectorRegLoOperands(MCInst &Inst, unsigned N) const {
1468 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001469 Inst.addOperand(MCOperand::createReg(getReg()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001470 }
1471
Sander de Smalen525e3222018-04-12 13:19:32 +00001472 enum VecListIndexType {
1473 VecListIdx_DReg = 0,
1474 VecListIdx_QReg = 1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001475 VecListIdx_ZReg = 2,
Sander de Smalen525e3222018-04-12 13:19:32 +00001476 };
1477
1478 template <VecListIndexType RegTy, unsigned NumRegs>
1479 void addVectorListOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001480 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen525e3222018-04-12 13:19:32 +00001481 static const unsigned FirstRegs[][5] = {
1482 /* DReg */ { AArch64::Q0,
1483 AArch64::D0, AArch64::D0_D1,
1484 AArch64::D0_D1_D2, AArch64::D0_D1_D2_D3 },
1485 /* QReg */ { AArch64::Q0,
1486 AArch64::Q0, AArch64::Q0_Q1,
Sander de Smalenea626e32018-04-13 09:11:53 +00001487 AArch64::Q0_Q1_Q2, AArch64::Q0_Q1_Q2_Q3 },
1488 /* ZReg */ { AArch64::Z0,
Sander de Smalend239eb32018-04-16 10:10:48 +00001489 AArch64::Z0, AArch64::Z0_Z1,
Sander de Smalen7a210db2018-04-16 10:46:18 +00001490 AArch64::Z0_Z1_Z2, AArch64::Z0_Z1_Z2_Z3 }
Sander de Smalen525e3222018-04-12 13:19:32 +00001491 };
Tim Northover3b0846e2014-05-24 12:50:23 +00001492
Sander de Smalen7a210db2018-04-16 10:46:18 +00001493 assert((RegTy != VecListIdx_ZReg || NumRegs <= 4) &&
1494 " NumRegs must be <= 4 for ZRegs");
Sander de Smalenea626e32018-04-13 09:11:53 +00001495
Sander de Smalen525e3222018-04-12 13:19:32 +00001496 unsigned FirstReg = FirstRegs[(unsigned)RegTy][NumRegs];
1497 Inst.addOperand(MCOperand::createReg(FirstReg + getVectorListStart() -
1498 FirstRegs[(unsigned)RegTy][0]));
Tim Northover3b0846e2014-05-24 12:50:23 +00001499 }
1500
Sander de Smalenafe1ee22018-04-29 18:18:21 +00001501 void addVectorIndexOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001502 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001503 Inst.addOperand(MCOperand::createImm(getVectorIndex()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001504 }
1505
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001506 template <unsigned ImmIs0, unsigned ImmIs1>
1507 void addExactFPImmOperands(MCInst &Inst, unsigned N) const {
1508 assert(N == 1 && "Invalid number of operands!");
1509 assert(bool(isExactFPImm<ImmIs0, ImmIs1>()) && "Invalid operand");
1510 Inst.addOperand(MCOperand::createImm(bool(isExactFPImm<ImmIs1>())));
1511 }
1512
Tim Northover3b0846e2014-05-24 12:50:23 +00001513 void addImmOperands(MCInst &Inst, unsigned N) const {
1514 assert(N == 1 && "Invalid number of operands!");
1515 // If this is a pageoff symrefexpr with an addend, adjust the addend
1516 // to be only the page-offset portion. Otherwise, just add the expr
1517 // as-is.
1518 addExpr(Inst, getImm());
1519 }
1520
Sander de Smalen62770792018-05-25 09:47:52 +00001521 template <int Shift>
1522 void addImmWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001523 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001524 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1525 Inst.addOperand(MCOperand::createImm(ShiftedVal->first));
1526 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1527 } else if (isShiftedImm()) {
Tim Northover3b0846e2014-05-24 12:50:23 +00001528 addExpr(Inst, getShiftedImmVal());
Jim Grosbache9119e42015-05-13 18:37:00 +00001529 Inst.addOperand(MCOperand::createImm(getShiftedImmShift()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001530 } else {
1531 addExpr(Inst, getImm());
Jim Grosbache9119e42015-05-13 18:37:00 +00001532 Inst.addOperand(MCOperand::createImm(0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001533 }
1534 }
1535
Sander de Smalen62770792018-05-25 09:47:52 +00001536 template <int Shift>
1537 void addImmNegWithOptionalShiftOperands(MCInst &Inst, unsigned N) const {
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001538 assert(N == 2 && "Invalid number of operands!");
Sander de Smalen62770792018-05-25 09:47:52 +00001539 if (auto ShiftedVal = getShiftedVal<Shift>()) {
1540 Inst.addOperand(MCOperand::createImm(-ShiftedVal->first));
1541 Inst.addOperand(MCOperand::createImm(ShiftedVal->second));
1542 } else
1543 llvm_unreachable("Not a shifted negative immediate");
Arnaud A. de Grandmaison650c5202015-07-01 15:05:58 +00001544 }
1545
Tim Northover3b0846e2014-05-24 12:50:23 +00001546 void addCondCodeOperands(MCInst &Inst, unsigned N) const {
1547 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001548 Inst.addOperand(MCOperand::createImm(getCondCode()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001549 }
1550
1551 void addAdrpLabelOperands(MCInst &Inst, unsigned N) const {
1552 assert(N == 1 && "Invalid number of operands!");
1553 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1554 if (!MCE)
1555 addExpr(Inst, getImm());
1556 else
Jim Grosbache9119e42015-05-13 18:37:00 +00001557 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 12));
Tim Northover3b0846e2014-05-24 12:50:23 +00001558 }
1559
1560 void addAdrLabelOperands(MCInst &Inst, unsigned N) const {
1561 addImmOperands(Inst, N);
1562 }
1563
1564 template<int Scale>
1565 void addUImm12OffsetOperands(MCInst &Inst, unsigned N) const {
1566 assert(N == 1 && "Invalid number of operands!");
1567 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1568
1569 if (!MCE) {
Jim Grosbache9119e42015-05-13 18:37:00 +00001570 Inst.addOperand(MCOperand::createExpr(getImm()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001571 return;
1572 }
Jim Grosbache9119e42015-05-13 18:37:00 +00001573 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
Tim Northover3b0846e2014-05-24 12:50:23 +00001574 }
1575
Sjoerd Meijera3dad802018-07-06 12:32:33 +00001576 void addUImm6Operands(MCInst &Inst, unsigned N) const {
1577 assert(N == 1 && "Invalid number of operands!");
1578 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1579 Inst.addOperand(MCOperand::createImm(MCE->getValue()));
1580 }
1581
Sander de Smalen5c625982018-04-13 12:56:14 +00001582 template <int Scale>
1583 void addImmScaledOperands(MCInst &Inst, unsigned N) const {
1584 assert(N == 1 && "Invalid number of operands!");
1585 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1586 Inst.addOperand(MCOperand::createImm(MCE->getValue() / Scale));
1587 }
1588
Sander de Smalena1c259c2018-01-29 13:05:38 +00001589 template <typename T>
1590 void addLogicalImmOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001591 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001592 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001593 typename std::make_unsigned<T>::type Val = MCE->getValue();
1594 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001595 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001596 }
1597
Sander de Smalena1c259c2018-01-29 13:05:38 +00001598 template <typename T>
1599 void addLogicalImmNotOperands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001600 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001601 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Sander de Smalena1c259c2018-01-29 13:05:38 +00001602 typename std::make_unsigned<T>::type Val = ~MCE->getValue();
1603 uint64_t encoding = AArch64_AM::encodeLogicalImmediate(Val, sizeof(T) * 8);
Jim Grosbache9119e42015-05-13 18:37:00 +00001604 Inst.addOperand(MCOperand::createImm(encoding));
Arnaud A. de Grandmaisonf6432312014-07-10 15:12:26 +00001605 }
1606
Tim Northover3b0846e2014-05-24 12:50:23 +00001607 void addSIMDImmType10Operands(MCInst &Inst, unsigned N) const {
1608 assert(N == 1 && "Invalid number of operands!");
Arnaud A. de Grandmaisond3d67162014-07-17 19:08:14 +00001609 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00001610 uint64_t encoding = AArch64_AM::encodeAdvSIMDModImmType10(MCE->getValue());
Jim Grosbache9119e42015-05-13 18:37:00 +00001611 Inst.addOperand(MCOperand::createImm(encoding));
Tim Northover3b0846e2014-05-24 12:50:23 +00001612 }
1613
1614 void addBranchTarget26Operands(MCInst &Inst, unsigned N) const {
1615 // Branch operands don't encode the low bits, so shift them off
1616 // here. If it's a label, however, just put it on directly as there's
1617 // not enough information now to do anything.
1618 assert(N == 1 && "Invalid number of operands!");
1619 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1620 if (!MCE) {
1621 addExpr(Inst, getImm());
1622 return;
1623 }
1624 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001625 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001626 }
1627
1628 void addPCRelLabel19Operands(MCInst &Inst, unsigned N) const {
1629 // Branch operands don't encode the low bits, so shift them off
1630 // here. If it's a label, however, just put it on directly as there's
1631 // not enough information now to do anything.
1632 assert(N == 1 && "Invalid number of operands!");
1633 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1634 if (!MCE) {
1635 addExpr(Inst, getImm());
1636 return;
1637 }
1638 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001639 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001640 }
1641
1642 void addBranchTarget14Operands(MCInst &Inst, unsigned N) const {
1643 // Branch operands don't encode the low bits, so shift them off
1644 // here. If it's a label, however, just put it on directly as there's
1645 // not enough information now to do anything.
1646 assert(N == 1 && "Invalid number of operands!");
1647 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(getImm());
1648 if (!MCE) {
1649 addExpr(Inst, getImm());
1650 return;
1651 }
1652 assert(MCE && "Invalid constant immediate operand!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001653 Inst.addOperand(MCOperand::createImm(MCE->getValue() >> 2));
Tim Northover3b0846e2014-05-24 12:50:23 +00001654 }
1655
1656 void addFPImmOperands(MCInst &Inst, unsigned N) const {
1657 assert(N == 1 && "Invalid number of operands!");
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001658 Inst.addOperand(MCOperand::createImm(
1659 AArch64_AM::getFP64Imm(getFPImm().bitcastToAPInt())));
Tim Northover3b0846e2014-05-24 12:50:23 +00001660 }
1661
1662 void addBarrierOperands(MCInst &Inst, unsigned N) const {
1663 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001664 Inst.addOperand(MCOperand::createImm(getBarrier()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001665 }
1666
1667 void addMRSSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1668 assert(N == 1 && "Invalid number of operands!");
1669
Jim Grosbache9119e42015-05-13 18:37:00 +00001670 Inst.addOperand(MCOperand::createImm(SysReg.MRSReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001671 }
1672
1673 void addMSRSystemRegisterOperands(MCInst &Inst, unsigned N) const {
1674 assert(N == 1 && "Invalid number of operands!");
1675
Jim Grosbache9119e42015-05-13 18:37:00 +00001676 Inst.addOperand(MCOperand::createImm(SysReg.MSRReg));
Tim Northover3b0846e2014-05-24 12:50:23 +00001677 }
1678
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00001679 void addSystemPStateFieldWithImm0_1Operands(MCInst &Inst, unsigned N) const {
1680 assert(N == 1 && "Invalid number of operands!");
1681
1682 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
1683 }
1684
1685 void addSystemPStateFieldWithImm0_15Operands(MCInst &Inst, unsigned N) const {
Tim Northover3b0846e2014-05-24 12:50:23 +00001686 assert(N == 1 && "Invalid number of operands!");
1687
Jim Grosbache9119e42015-05-13 18:37:00 +00001688 Inst.addOperand(MCOperand::createImm(SysReg.PStateField));
Tim Northover3b0846e2014-05-24 12:50:23 +00001689 }
1690
1691 void addSysCROperands(MCInst &Inst, unsigned N) const {
1692 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001693 Inst.addOperand(MCOperand::createImm(getSysCR()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001694 }
1695
1696 void addPrefetchOperands(MCInst &Inst, unsigned N) const {
1697 assert(N == 1 && "Invalid number of operands!");
Jim Grosbache9119e42015-05-13 18:37:00 +00001698 Inst.addOperand(MCOperand::createImm(getPrefetch()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001699 }
1700
Oliver Stannarda34e4702015-12-01 10:48:51 +00001701 void addPSBHintOperands(MCInst &Inst, unsigned N) const {
1702 assert(N == 1 && "Invalid number of operands!");
1703 Inst.addOperand(MCOperand::createImm(getPSBHint()));
1704 }
1705
Tim Northover3b0846e2014-05-24 12:50:23 +00001706 void addShifterOperands(MCInst &Inst, unsigned N) const {
1707 assert(N == 1 && "Invalid number of operands!");
1708 unsigned Imm =
1709 AArch64_AM::getShifterImm(getShiftExtendType(), getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001710 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001711 }
1712
1713 void addExtendOperands(MCInst &Inst, unsigned N) const {
1714 assert(N == 1 && "Invalid number of operands!");
1715 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1716 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTW;
1717 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001718 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001719 }
1720
1721 void addExtend64Operands(MCInst &Inst, unsigned N) const {
1722 assert(N == 1 && "Invalid number of operands!");
1723 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1724 if (ET == AArch64_AM::LSL) ET = AArch64_AM::UXTX;
1725 unsigned Imm = AArch64_AM::getArithExtendImm(ET, getShiftExtendAmount());
Jim Grosbache9119e42015-05-13 18:37:00 +00001726 Inst.addOperand(MCOperand::createImm(Imm));
Tim Northover3b0846e2014-05-24 12:50:23 +00001727 }
1728
1729 void addMemExtendOperands(MCInst &Inst, unsigned N) const {
1730 assert(N == 2 && "Invalid number of operands!");
1731 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1732 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001733 Inst.addOperand(MCOperand::createImm(IsSigned));
1734 Inst.addOperand(MCOperand::createImm(getShiftExtendAmount() != 0));
Tim Northover3b0846e2014-05-24 12:50:23 +00001735 }
1736
1737 // For 8-bit load/store instructions with a register offset, both the
1738 // "DoShift" and "NoShift" variants have a shift of 0. Because of this,
1739 // they're disambiguated by whether the shift was explicit or implicit rather
1740 // than its size.
1741 void addMemExtend8Operands(MCInst &Inst, unsigned N) const {
1742 assert(N == 2 && "Invalid number of operands!");
1743 AArch64_AM::ShiftExtendType ET = getShiftExtendType();
1744 bool IsSigned = ET == AArch64_AM::SXTW || ET == AArch64_AM::SXTX;
Jim Grosbache9119e42015-05-13 18:37:00 +00001745 Inst.addOperand(MCOperand::createImm(IsSigned));
1746 Inst.addOperand(MCOperand::createImm(hasShiftExtendAmount()));
Tim Northover3b0846e2014-05-24 12:50:23 +00001747 }
1748
1749 template<int Shift>
1750 void addMOVZMovAliasOperands(MCInst &Inst, unsigned N) const {
1751 assert(N == 1 && "Invalid number of operands!");
1752
1753 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1754 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001755 Inst.addOperand(MCOperand::createImm((Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001756 }
1757
1758 template<int Shift>
1759 void addMOVNMovAliasOperands(MCInst &Inst, unsigned N) const {
1760 assert(N == 1 && "Invalid number of operands!");
1761
1762 const MCConstantExpr *CE = cast<MCConstantExpr>(getImm());
1763 uint64_t Value = CE->getValue();
Jim Grosbache9119e42015-05-13 18:37:00 +00001764 Inst.addOperand(MCOperand::createImm((~Value >> Shift) & 0xffff));
Tim Northover3b0846e2014-05-24 12:50:23 +00001765 }
1766
Sam Parker5f934642017-08-31 09:27:04 +00001767 void addComplexRotationEvenOperands(MCInst &Inst, unsigned N) const {
1768 assert(N == 1 && "Invalid number of operands!");
1769 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1770 Inst.addOperand(MCOperand::createImm(MCE->getValue() / 90));
1771 }
1772
1773 void addComplexRotationOddOperands(MCInst &Inst, unsigned N) const {
1774 assert(N == 1 && "Invalid number of operands!");
1775 const MCConstantExpr *MCE = cast<MCConstantExpr>(getImm());
1776 Inst.addOperand(MCOperand::createImm((MCE->getValue() - 90) / 180));
1777 }
1778
Tim Northover3b0846e2014-05-24 12:50:23 +00001779 void print(raw_ostream &OS) const override;
1780
David Blaikie960ea3f2014-06-08 16:18:35 +00001781 static std::unique_ptr<AArch64Operand>
1782 CreateToken(StringRef Str, bool IsSuffix, SMLoc S, MCContext &Ctx) {
1783 auto Op = make_unique<AArch64Operand>(k_Token, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001784 Op->Tok.Data = Str.data();
1785 Op->Tok.Length = Str.size();
1786 Op->Tok.IsSuffix = IsSuffix;
1787 Op->StartLoc = S;
1788 Op->EndLoc = S;
1789 return Op;
1790 }
1791
David Blaikie960ea3f2014-06-08 16:18:35 +00001792 static std::unique_ptr<AArch64Operand>
Sander de Smalen149916d2018-04-20 07:24:20 +00001793 CreateReg(unsigned RegNum, RegKind Kind, SMLoc S, SMLoc E, MCContext &Ctx,
Sander de Smalen0325e302018-07-02 07:34:52 +00001794 RegConstraintEqualityTy EqTy = RegConstraintEqualityTy::EqualsReg,
Sander de Smalen149916d2018-04-20 07:24:20 +00001795 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1796 unsigned ShiftAmount = 0,
1797 unsigned HasExplicitAmount = false) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001798 auto Op = make_unique<AArch64Operand>(k_Register, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001799 Op->Reg.RegNum = RegNum;
Florian Hahnc4422242017-11-07 13:07:50 +00001800 Op->Reg.Kind = Kind;
Sander de Smalen149916d2018-04-20 07:24:20 +00001801 Op->Reg.ElementWidth = 0;
Sander de Smalen0325e302018-07-02 07:34:52 +00001802 Op->Reg.EqualityTy = EqTy;
Sander de Smalen149916d2018-04-20 07:24:20 +00001803 Op->Reg.ShiftExtend.Type = ExtTy;
1804 Op->Reg.ShiftExtend.Amount = ShiftAmount;
1805 Op->Reg.ShiftExtend.HasExplicitAmount = HasExplicitAmount;
Tim Northover3b0846e2014-05-24 12:50:23 +00001806 Op->StartLoc = S;
1807 Op->EndLoc = E;
1808 return Op;
1809 }
1810
David Blaikie960ea3f2014-06-08 16:18:35 +00001811 static std::unique_ptr<AArch64Operand>
Sander de Smalen73937b72018-04-11 07:36:10 +00001812 CreateVectorReg(unsigned RegNum, RegKind Kind, unsigned ElementWidth,
Sander de Smalen149916d2018-04-20 07:24:20 +00001813 SMLoc S, SMLoc E, MCContext &Ctx,
1814 AArch64_AM::ShiftExtendType ExtTy = AArch64_AM::LSL,
1815 unsigned ShiftAmount = 0,
1816 unsigned HasExplicitAmount = false) {
Sander de Smalen73937b72018-04-11 07:36:10 +00001817 assert((Kind == RegKind::NeonVector || Kind == RegKind::SVEDataVector ||
1818 Kind == RegKind::SVEPredicateVector) &&
1819 "Invalid vector kind");
Sander de Smalen0325e302018-07-02 07:34:52 +00001820 auto Op = CreateReg(RegNum, Kind, S, E, Ctx, EqualsReg, ExtTy, ShiftAmount,
Sander de Smalen149916d2018-04-20 07:24:20 +00001821 HasExplicitAmount);
Florian Hahn91f11e52017-11-07 16:45:48 +00001822 Op->Reg.ElementWidth = ElementWidth;
Florian Hahn91f11e52017-11-07 16:45:48 +00001823 return Op;
1824 }
1825
1826 static std::unique_ptr<AArch64Operand>
David Blaikie960ea3f2014-06-08 16:18:35 +00001827 CreateVectorList(unsigned RegNum, unsigned Count, unsigned NumElements,
Sander de Smalen650234b2018-04-12 11:40:52 +00001828 unsigned ElementWidth, RegKind RegisterKind, SMLoc S, SMLoc E,
1829 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001830 auto Op = make_unique<AArch64Operand>(k_VectorList, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001831 Op->VectorList.RegNum = RegNum;
1832 Op->VectorList.Count = Count;
1833 Op->VectorList.NumElements = NumElements;
Sander de Smalen650234b2018-04-12 11:40:52 +00001834 Op->VectorList.ElementWidth = ElementWidth;
1835 Op->VectorList.RegisterKind = RegisterKind;
Tim Northover3b0846e2014-05-24 12:50:23 +00001836 Op->StartLoc = S;
1837 Op->EndLoc = E;
1838 return Op;
1839 }
1840
David Blaikie960ea3f2014-06-08 16:18:35 +00001841 static std::unique_ptr<AArch64Operand>
1842 CreateVectorIndex(unsigned Idx, SMLoc S, SMLoc E, MCContext &Ctx) {
1843 auto Op = make_unique<AArch64Operand>(k_VectorIndex, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001844 Op->VectorIndex.Val = Idx;
1845 Op->StartLoc = S;
1846 Op->EndLoc = E;
1847 return Op;
1848 }
1849
David Blaikie960ea3f2014-06-08 16:18:35 +00001850 static std::unique_ptr<AArch64Operand> CreateImm(const MCExpr *Val, SMLoc S,
1851 SMLoc E, MCContext &Ctx) {
1852 auto Op = make_unique<AArch64Operand>(k_Immediate, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001853 Op->Imm.Val = Val;
1854 Op->StartLoc = S;
1855 Op->EndLoc = E;
1856 return Op;
1857 }
1858
David Blaikie960ea3f2014-06-08 16:18:35 +00001859 static std::unique_ptr<AArch64Operand> CreateShiftedImm(const MCExpr *Val,
1860 unsigned ShiftAmount,
1861 SMLoc S, SMLoc E,
1862 MCContext &Ctx) {
1863 auto Op = make_unique<AArch64Operand>(k_ShiftedImm, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001864 Op->ShiftedImm .Val = Val;
1865 Op->ShiftedImm.ShiftAmount = ShiftAmount;
1866 Op->StartLoc = S;
1867 Op->EndLoc = E;
1868 return Op;
1869 }
1870
David Blaikie960ea3f2014-06-08 16:18:35 +00001871 static std::unique_ptr<AArch64Operand>
1872 CreateCondCode(AArch64CC::CondCode Code, SMLoc S, SMLoc E, MCContext &Ctx) {
1873 auto Op = make_unique<AArch64Operand>(k_CondCode, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001874 Op->CondCode.Code = Code;
1875 Op->StartLoc = S;
1876 Op->EndLoc = E;
1877 return Op;
1878 }
1879
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001880 static std::unique_ptr<AArch64Operand>
1881 CreateFPImm(APFloat Val, bool IsExact, SMLoc S, MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001882 auto Op = make_unique<AArch64Operand>(k_FPImm, Ctx);
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001883 Op->FPImm.Val = Val.bitcastToAPInt().getSExtValue();
1884 Op->FPImm.IsExact = IsExact;
Tim Northover3b0846e2014-05-24 12:50:23 +00001885 Op->StartLoc = S;
1886 Op->EndLoc = S;
1887 return Op;
1888 }
1889
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001890 static std::unique_ptr<AArch64Operand> CreateBarrier(unsigned Val,
1891 StringRef Str,
1892 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001893 MCContext &Ctx) {
1894 auto Op = make_unique<AArch64Operand>(k_Barrier, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001895 Op->Barrier.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001896 Op->Barrier.Data = Str.data();
1897 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001898 Op->StartLoc = S;
1899 Op->EndLoc = S;
1900 return Op;
1901 }
1902
Tim Northover7cd58932015-01-22 17:23:04 +00001903 static std::unique_ptr<AArch64Operand> CreateSysReg(StringRef Str, SMLoc S,
1904 uint32_t MRSReg,
1905 uint32_t MSRReg,
1906 uint32_t PStateField,
1907 MCContext &Ctx) {
David Blaikie960ea3f2014-06-08 16:18:35 +00001908 auto Op = make_unique<AArch64Operand>(k_SysReg, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001909 Op->SysReg.Data = Str.data();
1910 Op->SysReg.Length = Str.size();
Tim Northover7cd58932015-01-22 17:23:04 +00001911 Op->SysReg.MRSReg = MRSReg;
1912 Op->SysReg.MSRReg = MSRReg;
1913 Op->SysReg.PStateField = PStateField;
Tim Northover3b0846e2014-05-24 12:50:23 +00001914 Op->StartLoc = S;
1915 Op->EndLoc = S;
1916 return Op;
1917 }
1918
David Blaikie960ea3f2014-06-08 16:18:35 +00001919 static std::unique_ptr<AArch64Operand> CreateSysCR(unsigned Val, SMLoc S,
1920 SMLoc E, MCContext &Ctx) {
1921 auto Op = make_unique<AArch64Operand>(k_SysCR, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001922 Op->SysCRImm.Val = Val;
1923 Op->StartLoc = S;
1924 Op->EndLoc = E;
1925 return Op;
1926 }
1927
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001928 static std::unique_ptr<AArch64Operand> CreatePrefetch(unsigned Val,
1929 StringRef Str,
1930 SMLoc S,
David Blaikie960ea3f2014-06-08 16:18:35 +00001931 MCContext &Ctx) {
1932 auto Op = make_unique<AArch64Operand>(k_Prefetch, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001933 Op->Prefetch.Val = Val;
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001934 Op->Barrier.Data = Str.data();
1935 Op->Barrier.Length = Str.size();
Tim Northover3b0846e2014-05-24 12:50:23 +00001936 Op->StartLoc = S;
1937 Op->EndLoc = S;
1938 return Op;
1939 }
1940
Oliver Stannarda34e4702015-12-01 10:48:51 +00001941 static std::unique_ptr<AArch64Operand> CreatePSBHint(unsigned Val,
1942 StringRef Str,
1943 SMLoc S,
1944 MCContext &Ctx) {
1945 auto Op = make_unique<AArch64Operand>(k_PSBHint, Ctx);
1946 Op->PSBHint.Val = Val;
1947 Op->PSBHint.Data = Str.data();
1948 Op->PSBHint.Length = Str.size();
1949 Op->StartLoc = S;
1950 Op->EndLoc = S;
1951 return Op;
1952 }
1953
David Blaikie960ea3f2014-06-08 16:18:35 +00001954 static std::unique_ptr<AArch64Operand>
1955 CreateShiftExtend(AArch64_AM::ShiftExtendType ShOp, unsigned Val,
1956 bool HasExplicitAmount, SMLoc S, SMLoc E, MCContext &Ctx) {
1957 auto Op = make_unique<AArch64Operand>(k_ShiftExtend, Ctx);
Tim Northover3b0846e2014-05-24 12:50:23 +00001958 Op->ShiftExtend.Type = ShOp;
1959 Op->ShiftExtend.Amount = Val;
1960 Op->ShiftExtend.HasExplicitAmount = HasExplicitAmount;
1961 Op->StartLoc = S;
1962 Op->EndLoc = E;
1963 return Op;
1964 }
1965};
1966
1967} // end anonymous namespace.
1968
1969void AArch64Operand::print(raw_ostream &OS) const {
1970 switch (Kind) {
1971 case k_FPImm:
Sander de Smalen3cbf1712018-06-15 13:11:49 +00001972 OS << "<fpimm " << getFPImm().bitcastToAPInt().getZExtValue();
1973 if (!getFPImmIsExact())
1974 OS << " (inexact)";
1975 OS << ">";
Tim Northover3b0846e2014-05-24 12:50:23 +00001976 break;
1977 case k_Barrier: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00001978 StringRef Name = getBarrierName();
1979 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00001980 OS << "<barrier " << Name << ">";
1981 else
1982 OS << "<barrier invalid #" << getBarrier() << ">";
1983 break;
1984 }
1985 case k_Immediate:
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001986 OS << *getImm();
Tim Northover3b0846e2014-05-24 12:50:23 +00001987 break;
1988 case k_ShiftedImm: {
1989 unsigned Shift = getShiftedImmShift();
1990 OS << "<shiftedimm ";
Rafael Espindolaf4a13652015-05-27 13:05:42 +00001991 OS << *getShiftedImmVal();
Tim Northover3b0846e2014-05-24 12:50:23 +00001992 OS << ", lsl #" << AArch64_AM::getShiftValue(Shift) << ">";
1993 break;
1994 }
1995 case k_CondCode:
1996 OS << "<condcode " << getCondCode() << ">";
1997 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00001998 case k_VectorList: {
1999 OS << "<vectorlist ";
2000 unsigned Reg = getVectorListStart();
2001 for (unsigned i = 0, e = getVectorListCount(); i != e; ++i)
2002 OS << Reg + i << " ";
2003 OS << ">";
2004 break;
2005 }
2006 case k_VectorIndex:
2007 OS << "<vectorindex " << getVectorIndex() << ">";
2008 break;
2009 case k_SysReg:
2010 OS << "<sysreg: " << getSysReg() << '>';
2011 break;
2012 case k_Token:
2013 OS << "'" << getToken() << "'";
2014 break;
2015 case k_SysCR:
2016 OS << "c" << getSysCR();
2017 break;
2018 case k_Prefetch: {
Vladimir Sukharev017d10b2015-03-26 17:29:53 +00002019 StringRef Name = getPrefetchName();
2020 if (!Name.empty())
Tim Northover3b0846e2014-05-24 12:50:23 +00002021 OS << "<prfop " << Name << ">";
2022 else
2023 OS << "<prfop invalid #" << getPrefetch() << ">";
2024 break;
2025 }
Eugene Zelenko049b0172017-01-06 00:30:53 +00002026 case k_PSBHint:
Oliver Stannarda34e4702015-12-01 10:48:51 +00002027 OS << getPSBHintName();
2028 break;
Sander de Smalen149916d2018-04-20 07:24:20 +00002029 case k_Register:
2030 OS << "<register " << getReg() << ">";
2031 if (!getShiftExtendAmount() && !hasShiftExtendAmount())
2032 break;
2033 LLVM_FALLTHROUGH;
Eugene Zelenko049b0172017-01-06 00:30:53 +00002034 case k_ShiftExtend:
Tim Northover3b0846e2014-05-24 12:50:23 +00002035 OS << "<" << AArch64_AM::getShiftExtendName(getShiftExtendType()) << " #"
2036 << getShiftExtendAmount();
2037 if (!hasShiftExtendAmount())
2038 OS << "<imp>";
2039 OS << '>';
2040 break;
2041 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002042}
2043
2044/// @name Auto-generated Match Functions
2045/// {
2046
2047static unsigned MatchRegisterName(StringRef Name);
2048
2049/// }
2050
Florian Hahnc4422242017-11-07 13:07:50 +00002051static unsigned MatchNeonVectorRegName(StringRef Name) {
Ranjeet Singh10511a42015-06-08 21:32:16 +00002052 return StringSwitch<unsigned>(Name.lower())
Tim Northover3b0846e2014-05-24 12:50:23 +00002053 .Case("v0", AArch64::Q0)
2054 .Case("v1", AArch64::Q1)
2055 .Case("v2", AArch64::Q2)
2056 .Case("v3", AArch64::Q3)
2057 .Case("v4", AArch64::Q4)
2058 .Case("v5", AArch64::Q5)
2059 .Case("v6", AArch64::Q6)
2060 .Case("v7", AArch64::Q7)
2061 .Case("v8", AArch64::Q8)
2062 .Case("v9", AArch64::Q9)
2063 .Case("v10", AArch64::Q10)
2064 .Case("v11", AArch64::Q11)
2065 .Case("v12", AArch64::Q12)
2066 .Case("v13", AArch64::Q13)
2067 .Case("v14", AArch64::Q14)
2068 .Case("v15", AArch64::Q15)
2069 .Case("v16", AArch64::Q16)
2070 .Case("v17", AArch64::Q17)
2071 .Case("v18", AArch64::Q18)
2072 .Case("v19", AArch64::Q19)
2073 .Case("v20", AArch64::Q20)
2074 .Case("v21", AArch64::Q21)
2075 .Case("v22", AArch64::Q22)
2076 .Case("v23", AArch64::Q23)
2077 .Case("v24", AArch64::Q24)
2078 .Case("v25", AArch64::Q25)
2079 .Case("v26", AArch64::Q26)
2080 .Case("v27", AArch64::Q27)
2081 .Case("v28", AArch64::Q28)
2082 .Case("v29", AArch64::Q29)
2083 .Case("v30", AArch64::Q30)
2084 .Case("v31", AArch64::Q31)
2085 .Default(0);
2086}
2087
Sander de Smalen73937b72018-04-11 07:36:10 +00002088/// Returns an optional pair of (#elements, element-width) if Suffix
2089/// is a valid vector kind. Where the number of elements in a vector
2090/// or the vector width is implicit or explicitly unknown (but still a
2091/// valid suffix kind), 0 is used.
2092static Optional<std::pair<int, int>> parseVectorKind(StringRef Suffix,
2093 RegKind VectorKind) {
2094 std::pair<int, int> Res = {-1, -1};
2095
2096 switch (VectorKind) {
2097 case RegKind::NeonVector:
2098 Res =
2099 StringSwitch<std::pair<int, int>>(Suffix.lower())
2100 .Case("", {0, 0})
2101 .Case(".1d", {1, 64})
2102 .Case(".1q", {1, 128})
2103 // '.2h' needed for fp16 scalar pairwise reductions
2104 .Case(".2h", {2, 16})
2105 .Case(".2s", {2, 32})
2106 .Case(".2d", {2, 64})
2107 // '.4b' is another special case for the ARMv8.2a dot product
2108 // operand
2109 .Case(".4b", {4, 8})
2110 .Case(".4h", {4, 16})
2111 .Case(".4s", {4, 32})
2112 .Case(".8b", {8, 8})
2113 .Case(".8h", {8, 16})
2114 .Case(".16b", {16, 8})
2115 // Accept the width neutral ones, too, for verbose syntax. If those
2116 // aren't used in the right places, the token operand won't match so
2117 // all will work out.
2118 .Case(".b", {0, 8})
2119 .Case(".h", {0, 16})
2120 .Case(".s", {0, 32})
2121 .Case(".d", {0, 64})
2122 .Default({-1, -1});
2123 break;
2124 case RegKind::SVEPredicateVector:
2125 case RegKind::SVEDataVector:
2126 Res = StringSwitch<std::pair<int, int>>(Suffix.lower())
2127 .Case("", {0, 0})
2128 .Case(".b", {0, 8})
2129 .Case(".h", {0, 16})
2130 .Case(".s", {0, 32})
2131 .Case(".d", {0, 64})
2132 .Case(".q", {0, 128})
2133 .Default({-1, -1});
2134 break;
2135 default:
2136 llvm_unreachable("Unsupported RegKind");
2137 }
2138
2139 if (Res == std::make_pair(-1, -1))
2140 return Optional<std::pair<int, int>>();
2141
2142 return Optional<std::pair<int, int>>(Res);
2143}
2144
2145static bool isValidVectorKind(StringRef Suffix, RegKind VectorKind) {
2146 return parseVectorKind(Suffix, VectorKind).hasValue();
Tim Northover3b0846e2014-05-24 12:50:23 +00002147}
2148
Florian Hahn91f11e52017-11-07 16:45:48 +00002149static unsigned matchSVEDataVectorRegName(StringRef Name) {
2150 return StringSwitch<unsigned>(Name.lower())
2151 .Case("z0", AArch64::Z0)
2152 .Case("z1", AArch64::Z1)
2153 .Case("z2", AArch64::Z2)
2154 .Case("z3", AArch64::Z3)
2155 .Case("z4", AArch64::Z4)
2156 .Case("z5", AArch64::Z5)
2157 .Case("z6", AArch64::Z6)
2158 .Case("z7", AArch64::Z7)
2159 .Case("z8", AArch64::Z8)
2160 .Case("z9", AArch64::Z9)
2161 .Case("z10", AArch64::Z10)
2162 .Case("z11", AArch64::Z11)
2163 .Case("z12", AArch64::Z12)
2164 .Case("z13", AArch64::Z13)
2165 .Case("z14", AArch64::Z14)
2166 .Case("z15", AArch64::Z15)
2167 .Case("z16", AArch64::Z16)
2168 .Case("z17", AArch64::Z17)
2169 .Case("z18", AArch64::Z18)
2170 .Case("z19", AArch64::Z19)
2171 .Case("z20", AArch64::Z20)
2172 .Case("z21", AArch64::Z21)
2173 .Case("z22", AArch64::Z22)
2174 .Case("z23", AArch64::Z23)
2175 .Case("z24", AArch64::Z24)
2176 .Case("z25", AArch64::Z25)
2177 .Case("z26", AArch64::Z26)
2178 .Case("z27", AArch64::Z27)
2179 .Case("z28", AArch64::Z28)
2180 .Case("z29", AArch64::Z29)
2181 .Case("z30", AArch64::Z30)
2182 .Case("z31", AArch64::Z31)
2183 .Default(0);
2184}
2185
Sander de Smalencd6be962017-12-20 11:02:42 +00002186static unsigned matchSVEPredicateVectorRegName(StringRef Name) {
2187 return StringSwitch<unsigned>(Name.lower())
2188 .Case("p0", AArch64::P0)
2189 .Case("p1", AArch64::P1)
2190 .Case("p2", AArch64::P2)
2191 .Case("p3", AArch64::P3)
2192 .Case("p4", AArch64::P4)
2193 .Case("p5", AArch64::P5)
2194 .Case("p6", AArch64::P6)
2195 .Case("p7", AArch64::P7)
2196 .Case("p8", AArch64::P8)
2197 .Case("p9", AArch64::P9)
2198 .Case("p10", AArch64::P10)
2199 .Case("p11", AArch64::P11)
2200 .Case("p12", AArch64::P12)
2201 .Case("p13", AArch64::P13)
2202 .Case("p14", AArch64::P14)
2203 .Case("p15", AArch64::P15)
2204 .Default(0);
2205}
2206
Tim Northover3b0846e2014-05-24 12:50:23 +00002207bool AArch64AsmParser::ParseRegister(unsigned &RegNo, SMLoc &StartLoc,
2208 SMLoc &EndLoc) {
2209 StartLoc = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00002210 auto Res = tryParseScalarRegister(RegNo);
Tim Northover3b0846e2014-05-24 12:50:23 +00002211 EndLoc = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Sander de Smalen50d87022018-04-19 07:35:08 +00002212 return Res != MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002213}
2214
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002215// Matches a register name or register alias previously defined by '.req'
2216unsigned AArch64AsmParser::matchRegisterNameAlias(StringRef Name,
Florian Hahnc4422242017-11-07 13:07:50 +00002217 RegKind Kind) {
Sander de Smalenc067c302017-12-20 09:45:45 +00002218 unsigned RegNum = 0;
2219 if ((RegNum = matchSVEDataVectorRegName(Name)))
2220 return Kind == RegKind::SVEDataVector ? RegNum : 0;
2221
Sander de Smalencd6be962017-12-20 11:02:42 +00002222 if ((RegNum = matchSVEPredicateVectorRegName(Name)))
2223 return Kind == RegKind::SVEPredicateVector ? RegNum : 0;
2224
Sander de Smalenc067c302017-12-20 09:45:45 +00002225 if ((RegNum = MatchNeonVectorRegName(Name)))
2226 return Kind == RegKind::NeonVector ? RegNum : 0;
2227
2228 // The parsed register must be of RegKind Scalar
2229 if ((RegNum = MatchRegisterName(Name)))
2230 return Kind == RegKind::Scalar ? RegNum : 0;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002231
Florian Hahnc4422242017-11-07 13:07:50 +00002232 if (!RegNum) {
Sander de Smalen50d87022018-04-19 07:35:08 +00002233 // Handle a few common aliases of registers.
2234 if (auto RegNum = StringSwitch<unsigned>(Name.lower())
2235 .Case("fp", AArch64::FP)
2236 .Case("lr", AArch64::LR)
2237 .Case("x31", AArch64::XZR)
2238 .Case("w31", AArch64::WZR)
2239 .Default(0))
2240 return Kind == RegKind::Scalar ? RegNum : 0;
2241
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002242 // Check for aliases registered via .req. Canonicalize to lower case.
2243 // That's more consistent since register names are case insensitive, and
2244 // it's how the original entry was passed in from MC/MCParser/AsmParser.
2245 auto Entry = RegisterReqs.find(Name.lower());
2246 if (Entry == RegisterReqs.end())
2247 return 0;
Florian Hahnc4422242017-11-07 13:07:50 +00002248
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002249 // set RegNum if the match is the right kind of register
Florian Hahnc4422242017-11-07 13:07:50 +00002250 if (Kind == Entry->getValue().first)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00002251 RegNum = Entry->getValue().second;
2252 }
2253 return RegNum;
2254}
2255
Sander de Smalen50d87022018-04-19 07:35:08 +00002256/// tryParseScalarRegister - Try to parse a register name. The token must be an
Tim Northover3b0846e2014-05-24 12:50:23 +00002257/// Identifier when called, and if it is a register name the token is eaten and
2258/// the register is added to the operand list.
Sander de Smalen50d87022018-04-19 07:35:08 +00002259OperandMatchResultTy
2260AArch64AsmParser::tryParseScalarRegister(unsigned &RegNum) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002261 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002262 const AsmToken &Tok = Parser.getTok();
Nirav Davee833c6c2016-11-08 18:31:04 +00002263 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen50d87022018-04-19 07:35:08 +00002264 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00002265
2266 std::string lowerCase = Tok.getString().lower();
Sander de Smalen50d87022018-04-19 07:35:08 +00002267 unsigned Reg = matchRegisterNameAlias(lowerCase, RegKind::Scalar);
2268 if (Reg == 0)
2269 return MatchOperand_NoMatch;
Sander de Smalenc067c302017-12-20 09:45:45 +00002270
Sander de Smalen50d87022018-04-19 07:35:08 +00002271 RegNum = Reg;
Tim Northover3b0846e2014-05-24 12:50:23 +00002272 Parser.Lex(); // Eat identifier token.
Sander de Smalen50d87022018-04-19 07:35:08 +00002273 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002274}
2275
Tim Northover3b0846e2014-05-24 12:50:23 +00002276/// tryParseSysCROperand - Try to parse a system instruction CR operand name.
Alex Bradbury58eba092016-11-01 16:32:05 +00002277OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002278AArch64AsmParser::tryParseSysCROperand(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002279 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002280 SMLoc S = getLoc();
2281
2282 if (Parser.getTok().isNot(AsmToken::Identifier)) {
2283 Error(S, "Expected cN operand where 0 <= N <= 15");
2284 return MatchOperand_ParseFail;
2285 }
2286
2287 StringRef Tok = Parser.getTok().getIdentifier();
2288 if (Tok[0] != 'c' && Tok[0] != 'C') {
2289 Error(S, "Expected cN operand where 0 <= N <= 15");
2290 return MatchOperand_ParseFail;
2291 }
2292
2293 uint32_t CRNum;
2294 bool BadNum = Tok.drop_front().getAsInteger(10, CRNum);
2295 if (BadNum || CRNum > 15) {
2296 Error(S, "Expected cN operand where 0 <= N <= 15");
2297 return MatchOperand_ParseFail;
2298 }
2299
2300 Parser.Lex(); // Eat identifier token.
2301 Operands.push_back(
2302 AArch64Operand::CreateSysCR(CRNum, S, getLoc(), getContext()));
2303 return MatchOperand_Success;
2304}
2305
2306/// tryParsePrefetch - Try to parse a prefetch operand.
Sander de Smalen93380372018-05-14 11:54:41 +00002307template <bool IsSVEPrefetch>
Alex Bradbury58eba092016-11-01 16:32:05 +00002308OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002309AArch64AsmParser::tryParsePrefetch(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002310 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002311 SMLoc S = getLoc();
2312 const AsmToken &Tok = Parser.getTok();
Sander de Smalen93380372018-05-14 11:54:41 +00002313
2314 auto LookupByName = [](StringRef N) {
2315 if (IsSVEPrefetch) {
2316 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByName(N))
2317 return Optional<unsigned>(Res->Encoding);
2318 } else if (auto Res = AArch64PRFM::lookupPRFMByName(N))
2319 return Optional<unsigned>(Res->Encoding);
2320 return Optional<unsigned>();
2321 };
2322
2323 auto LookupByEncoding = [](unsigned E) {
2324 if (IsSVEPrefetch) {
2325 if (auto Res = AArch64SVEPRFM::lookupSVEPRFMByEncoding(E))
2326 return Optional<StringRef>(Res->Name);
2327 } else if (auto Res = AArch64PRFM::lookupPRFMByEncoding(E))
2328 return Optional<StringRef>(Res->Name);
2329 return Optional<StringRef>();
2330 };
2331 unsigned MaxVal = IsSVEPrefetch ? 15 : 31;
2332
Tim Northover3b0846e2014-05-24 12:50:23 +00002333 // Either an identifier for named values or a 5-bit immediate.
Nirav Davee833c6c2016-11-08 18:31:04 +00002334 // Eat optional hash.
2335 if (parseOptionalToken(AsmToken::Hash) ||
2336 Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002337 const MCExpr *ImmVal;
2338 if (getParser().parseExpression(ImmVal))
2339 return MatchOperand_ParseFail;
2340
2341 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2342 if (!MCE) {
2343 TokError("immediate value expected for prefetch operand");
2344 return MatchOperand_ParseFail;
2345 }
2346 unsigned prfop = MCE->getValue();
Sander de Smalen93380372018-05-14 11:54:41 +00002347 if (prfop > MaxVal) {
2348 TokError("prefetch operand out of range, [0," + utostr(MaxVal) +
2349 "] expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002350 return MatchOperand_ParseFail;
2351 }
2352
Sander de Smalen93380372018-05-14 11:54:41 +00002353 auto PRFM = LookupByEncoding(MCE->getValue());
Tim Northovere6ae6762016-07-05 21:23:04 +00002354 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002355 prfop, PRFM.getValueOr(""), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002356 return MatchOperand_Success;
2357 }
2358
2359 if (Tok.isNot(AsmToken::Identifier)) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002360 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002361 return MatchOperand_ParseFail;
2362 }
2363
Sander de Smalen93380372018-05-14 11:54:41 +00002364 auto PRFM = LookupByName(Tok.getString());
Tim Northovere6ae6762016-07-05 21:23:04 +00002365 if (!PRFM) {
Sander de Smalen67f91542018-05-16 07:50:09 +00002366 TokError("prefetch hint expected");
Tim Northover3b0846e2014-05-24 12:50:23 +00002367 return MatchOperand_ParseFail;
2368 }
2369
2370 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002371 Operands.push_back(AArch64Operand::CreatePrefetch(
Sander de Smalen93380372018-05-14 11:54:41 +00002372 *PRFM, Tok.getString(), S, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002373 return MatchOperand_Success;
2374}
2375
Oliver Stannarda34e4702015-12-01 10:48:51 +00002376/// tryParsePSBHint - Try to parse a PSB operand, mapped to Hint command
Alex Bradbury58eba092016-11-01 16:32:05 +00002377OperandMatchResultTy
Oliver Stannarda34e4702015-12-01 10:48:51 +00002378AArch64AsmParser::tryParsePSBHint(OperandVector &Operands) {
2379 MCAsmParser &Parser = getParser();
2380 SMLoc S = getLoc();
2381 const AsmToken &Tok = Parser.getTok();
2382 if (Tok.isNot(AsmToken::Identifier)) {
2383 TokError("invalid operand for instruction");
2384 return MatchOperand_ParseFail;
2385 }
2386
Tim Northovere6ae6762016-07-05 21:23:04 +00002387 auto PSB = AArch64PSBHint::lookupPSBByName(Tok.getString());
2388 if (!PSB) {
Oliver Stannarda34e4702015-12-01 10:48:51 +00002389 TokError("invalid operand for instruction");
2390 return MatchOperand_ParseFail;
2391 }
2392
2393 Parser.Lex(); // Eat identifier token.
Tim Northovere6ae6762016-07-05 21:23:04 +00002394 Operands.push_back(AArch64Operand::CreatePSBHint(
2395 PSB->Encoding, Tok.getString(), S, getContext()));
Oliver Stannarda34e4702015-12-01 10:48:51 +00002396 return MatchOperand_Success;
2397}
2398
Tim Northover3b0846e2014-05-24 12:50:23 +00002399/// tryParseAdrpLabel - Parse and validate a source label for the ADRP
2400/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002401OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002402AArch64AsmParser::tryParseAdrpLabel(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002403 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002404 SMLoc S = getLoc();
2405 const MCExpr *Expr;
2406
2407 if (Parser.getTok().is(AsmToken::Hash)) {
2408 Parser.Lex(); // Eat hash token.
2409 }
2410
2411 if (parseSymbolicImmVal(Expr))
2412 return MatchOperand_ParseFail;
2413
2414 AArch64MCExpr::VariantKind ELFRefKind;
2415 MCSymbolRefExpr::VariantKind DarwinRefKind;
2416 int64_t Addend;
2417 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2418 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2419 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2420 // No modifier was specified at all; this is the syntax for an ELF basic
2421 // ADRP relocation (unfortunately).
2422 Expr =
Jim Grosbach13760bd2015-05-30 01:25:56 +00002423 AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS_PAGE, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00002424 } else if ((DarwinRefKind == MCSymbolRefExpr::VK_GOTPAGE ||
2425 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGE) &&
2426 Addend != 0) {
2427 Error(S, "gotpage label reference not allowed an addend");
2428 return MatchOperand_ParseFail;
2429 } else if (DarwinRefKind != MCSymbolRefExpr::VK_PAGE &&
2430 DarwinRefKind != MCSymbolRefExpr::VK_GOTPAGE &&
2431 DarwinRefKind != MCSymbolRefExpr::VK_TLVPPAGE &&
2432 ELFRefKind != AArch64MCExpr::VK_GOT_PAGE &&
2433 ELFRefKind != AArch64MCExpr::VK_GOTTPREL_PAGE &&
2434 ELFRefKind != AArch64MCExpr::VK_TLSDESC_PAGE) {
2435 // The operand must be an @page or @gotpage qualified symbolref.
2436 Error(S, "page or gotpage label reference expected");
2437 return MatchOperand_ParseFail;
2438 }
2439 }
2440
2441 // We have either a label reference possibly with addend or an immediate. The
2442 // addend is a raw value here. The linker will adjust it to only reference the
2443 // page.
2444 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2445 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2446
2447 return MatchOperand_Success;
2448}
2449
2450/// tryParseAdrLabel - Parse and validate a source label for the ADR
2451/// instruction.
Alex Bradbury58eba092016-11-01 16:32:05 +00002452OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002453AArch64AsmParser::tryParseAdrLabel(OperandVector &Operands) {
2454 SMLoc S = getLoc();
2455 const MCExpr *Expr;
2456
David Green9dd1d452018-08-22 11:31:39 +00002457 // Leave anything with a bracket to the default for SVE
2458 if (getParser().getTok().is(AsmToken::LBrac))
2459 return MatchOperand_NoMatch;
2460
2461 if (getParser().getTok().is(AsmToken::Hash))
2462 getParser().Lex(); // Eat hash token.
2463
2464 if (parseSymbolicImmVal(Expr))
2465 return MatchOperand_ParseFail;
2466
2467 AArch64MCExpr::VariantKind ELFRefKind;
2468 MCSymbolRefExpr::VariantKind DarwinRefKind;
2469 int64_t Addend;
2470 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
2471 if (DarwinRefKind == MCSymbolRefExpr::VK_None &&
2472 ELFRefKind == AArch64MCExpr::VK_INVALID) {
2473 // No modifier was specified at all; this is the syntax for an ELF basic
2474 // ADR relocation (unfortunately).
2475 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_ABS, getContext());
2476 } else {
2477 Error(S, "unexpected adr label");
Sander de Smalenc69944c2018-07-09 09:58:24 +00002478 return MatchOperand_ParseFail;
David Green9dd1d452018-08-22 11:31:39 +00002479 }
Sander de Smalenc69944c2018-07-09 09:58:24 +00002480 }
David Green9dd1d452018-08-22 11:31:39 +00002481
2482 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2483 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
2484 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002485}
2486
2487/// tryParseFPImm - A floating point immediate expression operand.
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002488template<bool AddFPZeroAsLiteral>
Alex Bradbury58eba092016-11-01 16:32:05 +00002489OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002490AArch64AsmParser::tryParseFPImm(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002491 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002492 SMLoc S = getLoc();
2493
Nirav Davee833c6c2016-11-08 18:31:04 +00002494 bool Hash = parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002495
2496 // Handle negation, as that still comes through as a separate token.
Nirav Davee833c6c2016-11-08 18:31:04 +00002497 bool isNegative = parseOptionalToken(AsmToken::Minus);
2498
Tim Northover3b0846e2014-05-24 12:50:23 +00002499 const AsmToken &Tok = Parser.getTok();
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002500 if (!Tok.is(AsmToken::Real) && !Tok.is(AsmToken::Integer)) {
2501 if (!Hash)
2502 return MatchOperand_NoMatch;
2503 TokError("invalid floating point immediate");
2504 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002505 }
2506
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002507 // Parse hexadecimal representation.
2508 if (Tok.is(AsmToken::Integer) && Tok.getString().startswith("0x")) {
2509 if (Tok.getIntVal() > 255 || isNegative) {
2510 TokError("encoded floating point value out of range");
2511 return MatchOperand_ParseFail;
2512 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002513
Sander de Smalen3cbf1712018-06-15 13:11:49 +00002514 APFloat F((double)AArch64_AM::getFPImmFloat(Tok.getIntVal()));
2515 Operands.push_back(
2516 AArch64Operand::CreateFPImm(F, true, S, getContext()));
2517 } else {
2518 // Parse FP representation.
2519 APFloat RealVal(APFloat::IEEEdouble());
2520 auto Status =
2521 RealVal.convertFromString(Tok.getString(), APFloat::rmTowardZero);
2522 if (isNegative)
2523 RealVal.changeSign();
2524
2525 if (AddFPZeroAsLiteral && RealVal.isPosZero()) {
2526 Operands.push_back(
2527 AArch64Operand::CreateToken("#0", false, S, getContext()));
2528 Operands.push_back(
2529 AArch64Operand::CreateToken(".0", false, S, getContext()));
2530 } else
2531 Operands.push_back(AArch64Operand::CreateFPImm(
2532 RealVal, Status == APFloat::opOK, S, getContext()));
2533 }
2534
2535 Parser.Lex(); // Eat the token.
2536
2537 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00002538}
2539
Sander de Smalen62770792018-05-25 09:47:52 +00002540/// tryParseImmWithOptionalShift - Parse immediate operand, optionally with
2541/// a shift suffix, for example '#1, lsl #12'.
Alex Bradbury58eba092016-11-01 16:32:05 +00002542OperandMatchResultTy
Sander de Smalen62770792018-05-25 09:47:52 +00002543AArch64AsmParser::tryParseImmWithOptionalShift(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002544 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002545 SMLoc S = getLoc();
2546
2547 if (Parser.getTok().is(AsmToken::Hash))
2548 Parser.Lex(); // Eat '#'
2549 else if (Parser.getTok().isNot(AsmToken::Integer))
2550 // Operand should start from # or should be integer, emit error otherwise.
2551 return MatchOperand_NoMatch;
2552
2553 const MCExpr *Imm;
2554 if (parseSymbolicImmVal(Imm))
2555 return MatchOperand_ParseFail;
2556 else if (Parser.getTok().isNot(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002557 SMLoc E = Parser.getTok().getLoc();
Sander de Smalen62770792018-05-25 09:47:52 +00002558 Operands.push_back(
2559 AArch64Operand::CreateImm(Imm, S, E, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002560 return MatchOperand_Success;
2561 }
2562
2563 // Eat ','
2564 Parser.Lex();
2565
2566 // The optional operand must be "lsl #N" where N is non-negative.
2567 if (!Parser.getTok().is(AsmToken::Identifier) ||
2568 !Parser.getTok().getIdentifier().equals_lower("lsl")) {
2569 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2570 return MatchOperand_ParseFail;
2571 }
2572
2573 // Eat 'lsl'
2574 Parser.Lex();
2575
Nirav Davee833c6c2016-11-08 18:31:04 +00002576 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00002577
2578 if (Parser.getTok().isNot(AsmToken::Integer)) {
2579 Error(Parser.getTok().getLoc(), "only 'lsl #+N' valid after immediate");
2580 return MatchOperand_ParseFail;
2581 }
2582
2583 int64_t ShiftAmount = Parser.getTok().getIntVal();
2584
2585 if (ShiftAmount < 0) {
2586 Error(Parser.getTok().getLoc(), "positive shift amount required");
2587 return MatchOperand_ParseFail;
2588 }
2589 Parser.Lex(); // Eat the number
2590
Sander de Smalen62770792018-05-25 09:47:52 +00002591 // Just in case the optional lsl #0 is used for immediates other than zero.
2592 if (ShiftAmount == 0 && Imm != 0) {
2593 SMLoc E = Parser.getTok().getLoc();
2594 Operands.push_back(AArch64Operand::CreateImm(Imm, S, E, getContext()));
2595 return MatchOperand_Success;
2596 }
2597
Tim Northover3b0846e2014-05-24 12:50:23 +00002598 SMLoc E = Parser.getTok().getLoc();
2599 Operands.push_back(AArch64Operand::CreateShiftedImm(Imm, ShiftAmount,
2600 S, E, getContext()));
2601 return MatchOperand_Success;
2602}
2603
2604/// parseCondCodeString - Parse a Condition Code string.
2605AArch64CC::CondCode AArch64AsmParser::parseCondCodeString(StringRef Cond) {
2606 AArch64CC::CondCode CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2607 .Case("eq", AArch64CC::EQ)
2608 .Case("ne", AArch64CC::NE)
2609 .Case("cs", AArch64CC::HS)
2610 .Case("hs", AArch64CC::HS)
2611 .Case("cc", AArch64CC::LO)
2612 .Case("lo", AArch64CC::LO)
2613 .Case("mi", AArch64CC::MI)
2614 .Case("pl", AArch64CC::PL)
2615 .Case("vs", AArch64CC::VS)
2616 .Case("vc", AArch64CC::VC)
2617 .Case("hi", AArch64CC::HI)
2618 .Case("ls", AArch64CC::LS)
2619 .Case("ge", AArch64CC::GE)
2620 .Case("lt", AArch64CC::LT)
2621 .Case("gt", AArch64CC::GT)
2622 .Case("le", AArch64CC::LE)
2623 .Case("al", AArch64CC::AL)
2624 .Case("nv", AArch64CC::NV)
2625 .Default(AArch64CC::Invalid);
Sander de Smalene31e6d42018-07-04 08:50:49 +00002626
2627 if (CC == AArch64CC::Invalid &&
2628 getSTI().getFeatureBits()[AArch64::FeatureSVE])
2629 CC = StringSwitch<AArch64CC::CondCode>(Cond.lower())
2630 .Case("none", AArch64CC::EQ)
2631 .Case("any", AArch64CC::NE)
2632 .Case("nlast", AArch64CC::HS)
2633 .Case("last", AArch64CC::LO)
2634 .Case("first", AArch64CC::MI)
2635 .Case("nfrst", AArch64CC::PL)
2636 .Case("pmore", AArch64CC::HI)
2637 .Case("plast", AArch64CC::LS)
2638 .Case("tcont", AArch64CC::GE)
2639 .Case("tstop", AArch64CC::LT)
2640 .Default(AArch64CC::Invalid);
2641
Tim Northover3b0846e2014-05-24 12:50:23 +00002642 return CC;
2643}
2644
2645/// parseCondCode - Parse a Condition Code operand.
2646bool AArch64AsmParser::parseCondCode(OperandVector &Operands,
2647 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002648 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002649 SMLoc S = getLoc();
2650 const AsmToken &Tok = Parser.getTok();
2651 assert(Tok.is(AsmToken::Identifier) && "Token is not an Identifier");
2652
2653 StringRef Cond = Tok.getString();
2654 AArch64CC::CondCode CC = parseCondCodeString(Cond);
2655 if (CC == AArch64CC::Invalid)
2656 return TokError("invalid condition code");
2657 Parser.Lex(); // Eat identifier token.
2658
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002659 if (invertCondCode) {
2660 if (CC == AArch64CC::AL || CC == AArch64CC::NV)
2661 return TokError("condition codes AL and NV are invalid for this instruction");
Tim Northover3b0846e2014-05-24 12:50:23 +00002662 CC = AArch64CC::getInvertedCondCode(AArch64CC::CondCode(CC));
Artyom Skrobov6c8682e2014-06-10 13:11:35 +00002663 }
Tim Northover3b0846e2014-05-24 12:50:23 +00002664
2665 Operands.push_back(
2666 AArch64Operand::CreateCondCode(CC, S, getLoc(), getContext()));
2667 return false;
2668}
2669
2670/// tryParseOptionalShift - Some operands take an optional shift argument. Parse
2671/// them if present.
Alex Bradbury58eba092016-11-01 16:32:05 +00002672OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002673AArch64AsmParser::tryParseOptionalShiftExtend(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002674 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002675 const AsmToken &Tok = Parser.getTok();
2676 std::string LowerID = Tok.getString().lower();
2677 AArch64_AM::ShiftExtendType ShOp =
2678 StringSwitch<AArch64_AM::ShiftExtendType>(LowerID)
2679 .Case("lsl", AArch64_AM::LSL)
2680 .Case("lsr", AArch64_AM::LSR)
2681 .Case("asr", AArch64_AM::ASR)
2682 .Case("ror", AArch64_AM::ROR)
2683 .Case("msl", AArch64_AM::MSL)
2684 .Case("uxtb", AArch64_AM::UXTB)
2685 .Case("uxth", AArch64_AM::UXTH)
2686 .Case("uxtw", AArch64_AM::UXTW)
2687 .Case("uxtx", AArch64_AM::UXTX)
2688 .Case("sxtb", AArch64_AM::SXTB)
2689 .Case("sxth", AArch64_AM::SXTH)
2690 .Case("sxtw", AArch64_AM::SXTW)
2691 .Case("sxtx", AArch64_AM::SXTX)
2692 .Default(AArch64_AM::InvalidShiftExtend);
2693
2694 if (ShOp == AArch64_AM::InvalidShiftExtend)
2695 return MatchOperand_NoMatch;
2696
2697 SMLoc S = Tok.getLoc();
2698 Parser.Lex();
2699
Nirav Davee833c6c2016-11-08 18:31:04 +00002700 bool Hash = parseOptionalToken(AsmToken::Hash);
2701
Tim Northover3b0846e2014-05-24 12:50:23 +00002702 if (!Hash && getLexer().isNot(AsmToken::Integer)) {
2703 if (ShOp == AArch64_AM::LSL || ShOp == AArch64_AM::LSR ||
2704 ShOp == AArch64_AM::ASR || ShOp == AArch64_AM::ROR ||
2705 ShOp == AArch64_AM::MSL) {
2706 // We expect a number here.
2707 TokError("expected #imm after shift specifier");
2708 return MatchOperand_ParseFail;
2709 }
2710
Chad Rosier2ff37b82016-12-27 16:58:09 +00002711 // "extend" type operations don't need an immediate, #0 is implicit.
Tim Northover3b0846e2014-05-24 12:50:23 +00002712 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
2713 Operands.push_back(
2714 AArch64Operand::CreateShiftExtend(ShOp, 0, false, S, E, getContext()));
2715 return MatchOperand_Success;
2716 }
2717
Chad Rosier2ff37b82016-12-27 16:58:09 +00002718 // Make sure we do actually have a number, identifier or a parenthesized
2719 // expression.
Jim Grosbach57fd2622014-09-23 22:16:02 +00002720 SMLoc E = Parser.getTok().getLoc();
2721 if (!Parser.getTok().is(AsmToken::Integer) &&
Chad Rosier2ff37b82016-12-27 16:58:09 +00002722 !Parser.getTok().is(AsmToken::LParen) &&
2723 !Parser.getTok().is(AsmToken::Identifier)) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002724 Error(E, "expected integer shift amount");
Tim Northover3b0846e2014-05-24 12:50:23 +00002725 return MatchOperand_ParseFail;
2726 }
2727
2728 const MCExpr *ImmVal;
2729 if (getParser().parseExpression(ImmVal))
2730 return MatchOperand_ParseFail;
2731
2732 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2733 if (!MCE) {
Jim Grosbach57fd2622014-09-23 22:16:02 +00002734 Error(E, "expected constant '#imm' after shift specifier");
Tim Northover3b0846e2014-05-24 12:50:23 +00002735 return MatchOperand_ParseFail;
2736 }
2737
Jim Grosbach57fd2622014-09-23 22:16:02 +00002738 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00002739 Operands.push_back(AArch64Operand::CreateShiftExtend(
2740 ShOp, MCE->getValue(), true, S, E, getContext()));
2741 return MatchOperand_Success;
2742}
2743
Oliver Stannard89b16042018-09-26 13:52:27 +00002744static const struct Extension {
2745 const char *Name;
2746 const FeatureBitset Features;
2747} ExtensionMap[] = {
2748 { "crc", {AArch64::FeatureCRC} },
2749 { "sm4", {AArch64::FeatureSM4} },
2750 { "sha3", {AArch64::FeatureSHA3} },
2751 { "sha2", {AArch64::FeatureSHA2} },
2752 { "aes", {AArch64::FeatureAES} },
2753 { "crypto", {AArch64::FeatureCrypto} },
2754 { "fp", {AArch64::FeatureFPARMv8} },
2755 { "simd", {AArch64::FeatureNEON} },
2756 { "ras", {AArch64::FeatureRAS} },
2757 { "lse", {AArch64::FeatureLSE} },
2758
2759 // FIXME: Unsupported extensions
2760 { "pan", {} },
2761 { "lor", {} },
2762 { "rdma", {} },
2763 { "profile", {} },
2764};
2765
2766
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002767static void setRequiredFeatureString(FeatureBitset FBS, std::string &Str) {
2768 if (FBS[AArch64::HasV8_1aOps])
2769 Str += "ARMv8.1a";
2770 else if (FBS[AArch64::HasV8_2aOps])
2771 Str += "ARMv8.2a";
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002772 else if (FBS[AArch64::HasV8_3aOps])
2773 Str += "ARMv8.3a";
2774 else if (FBS[AArch64::HasV8_4aOps])
2775 Str += "ARMv8.4a";
Oliver Stannard89b16042018-09-26 13:52:27 +00002776 else if (FBS[AArch64::HasV8_5aOps])
2777 Str += "ARMv8.5a";
2778 else {
2779 auto ext = std::find_if(std::begin(ExtensionMap),
2780 std::end(ExtensionMap),
2781 [&](const Extension& e)
2782 // Use & in case multiple features are enabled
2783 { return (FBS & e.Features) != FeatureBitset(); }
2784 );
2785
2786 Str += ext != std::end(ExtensionMap) ? ext->Name : "(unknown)";
2787 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002788}
2789
2790void AArch64AsmParser::createSysAlias(uint16_t Encoding, OperandVector &Operands,
2791 SMLoc S) {
2792 const uint16_t Op2 = Encoding & 7;
2793 const uint16_t Cm = (Encoding & 0x78) >> 3;
2794 const uint16_t Cn = (Encoding & 0x780) >> 7;
2795 const uint16_t Op1 = (Encoding & 0x3800) >> 11;
2796
2797 const MCExpr *Expr = MCConstantExpr::create(Op1, getContext());
2798
2799 Operands.push_back(
2800 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2801 Operands.push_back(
2802 AArch64Operand::CreateSysCR(Cn, S, getLoc(), getContext()));
2803 Operands.push_back(
2804 AArch64Operand::CreateSysCR(Cm, S, getLoc(), getContext()));
2805 Expr = MCConstantExpr::create(Op2, getContext());
2806 Operands.push_back(
2807 AArch64Operand::CreateImm(Expr, S, getLoc(), getContext()));
2808}
2809
Tim Northover3b0846e2014-05-24 12:50:23 +00002810/// parseSysAlias - The IC, DC, AT, and TLBI instructions are simple aliases for
2811/// the SYS instruction. Parse them specially so that we create a SYS MCInst.
2812bool AArch64AsmParser::parseSysAlias(StringRef Name, SMLoc NameLoc,
2813 OperandVector &Operands) {
2814 if (Name.find('.') != StringRef::npos)
2815 return TokError("invalid operand");
2816
2817 Mnemonic = Name;
2818 Operands.push_back(
2819 AArch64Operand::CreateToken("sys", false, NameLoc, getContext()));
2820
Rafael Espindola961d4692014-11-11 05:18:41 +00002821 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002822 const AsmToken &Tok = Parser.getTok();
2823 StringRef Op = Tok.getString();
2824 SMLoc S = Tok.getLoc();
2825
Tim Northover3b0846e2014-05-24 12:50:23 +00002826 if (Mnemonic == "ic") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002827 const AArch64IC::IC *IC = AArch64IC::lookupICByName(Op);
2828 if (!IC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002829 return TokError("invalid operand for IC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002830 else if (!IC->haveFeatures(getSTI().getFeatureBits())) {
2831 std::string Str("IC " + std::string(IC->Name) + " requires ");
2832 setRequiredFeatureString(IC->getRequiredFeatures(), Str);
2833 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002834 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002835 createSysAlias(IC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002836 } else if (Mnemonic == "dc") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002837 const AArch64DC::DC *DC = AArch64DC::lookupDCByName(Op);
2838 if (!DC)
Tim Northover3b0846e2014-05-24 12:50:23 +00002839 return TokError("invalid operand for DC instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002840 else if (!DC->haveFeatures(getSTI().getFeatureBits())) {
2841 std::string Str("DC " + std::string(DC->Name) + " requires ");
2842 setRequiredFeatureString(DC->getRequiredFeatures(), Str);
2843 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002844 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002845 createSysAlias(DC->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002846 } else if (Mnemonic == "at") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002847 const AArch64AT::AT *AT = AArch64AT::lookupATByName(Op);
2848 if (!AT)
Tim Northover3b0846e2014-05-24 12:50:23 +00002849 return TokError("invalid operand for AT instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002850 else if (!AT->haveFeatures(getSTI().getFeatureBits())) {
2851 std::string Str("AT " + std::string(AT->Name) + " requires ");
2852 setRequiredFeatureString(AT->getRequiredFeatures(), Str);
2853 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002854 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002855 createSysAlias(AT->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002856 } else if (Mnemonic == "tlbi") {
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002857 const AArch64TLBI::TLBI *TLBI = AArch64TLBI::lookupTLBIByName(Op);
2858 if (!TLBI)
Tim Northover3b0846e2014-05-24 12:50:23 +00002859 return TokError("invalid operand for TLBI instruction");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002860 else if (!TLBI->haveFeatures(getSTI().getFeatureBits())) {
2861 std::string Str("TLBI " + std::string(TLBI->Name) + " requires ");
2862 setRequiredFeatureString(TLBI->getRequiredFeatures(), Str);
2863 return TokError(Str.c_str());
Tim Northover3b0846e2014-05-24 12:50:23 +00002864 }
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002865 createSysAlias(TLBI->Encoding, Operands, S);
Tim Northover3b0846e2014-05-24 12:50:23 +00002866 }
2867
Tim Northover3b0846e2014-05-24 12:50:23 +00002868 Parser.Lex(); // Eat operand.
2869
2870 bool ExpectRegister = (Op.lower().find("all") == StringRef::npos);
2871 bool HasRegister = false;
2872
2873 // Check for the optional register operand.
Nirav Davee833c6c2016-11-08 18:31:04 +00002874 if (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002875 if (Tok.isNot(AsmToken::Identifier) || parseRegister(Operands))
2876 return TokError("expected register operand");
Tim Northover3b0846e2014-05-24 12:50:23 +00002877 HasRegister = true;
2878 }
2879
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002880 if (ExpectRegister && !HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002881 return TokError("specified " + Mnemonic + " op requires a register");
Sjoerd Meijer69bccf92017-03-03 08:12:47 +00002882 else if (!ExpectRegister && HasRegister)
Tim Northover3b0846e2014-05-24 12:50:23 +00002883 return TokError("specified " + Mnemonic + " op does not use a register");
Tim Northover3b0846e2014-05-24 12:50:23 +00002884
Nirav Davee833c6c2016-11-08 18:31:04 +00002885 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
2886 return true;
2887
Tim Northover3b0846e2014-05-24 12:50:23 +00002888 return false;
2889}
2890
Alex Bradbury58eba092016-11-01 16:32:05 +00002891OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002892AArch64AsmParser::tryParseBarrierOperand(OperandVector &Operands) {
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
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002896 if (Mnemonic == "tsb" && Tok.isNot(AsmToken::Identifier)) {
2897 TokError("'csync' operand expected");
2898 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002899 // Can be either a #imm style literal or an option name
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002900 } else if (parseOptionalToken(AsmToken::Hash) || Tok.is(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002901 // Immediate operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00002902 const MCExpr *ImmVal;
2903 SMLoc ExprLoc = getLoc();
2904 if (getParser().parseExpression(ImmVal))
2905 return MatchOperand_ParseFail;
2906 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
2907 if (!MCE) {
2908 Error(ExprLoc, "immediate value expected for barrier operand");
2909 return MatchOperand_ParseFail;
2910 }
2911 if (MCE->getValue() < 0 || MCE->getValue() > 15) {
2912 Error(ExprLoc, "barrier operand out of range");
2913 return MatchOperand_ParseFail;
2914 }
Tim Northovere6ae6762016-07-05 21:23:04 +00002915 auto DB = AArch64DB::lookupDBByEncoding(MCE->getValue());
2916 Operands.push_back(AArch64Operand::CreateBarrier(
2917 MCE->getValue(), DB ? DB->Name : "", ExprLoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002918 return MatchOperand_Success;
2919 }
2920
2921 if (Tok.isNot(AsmToken::Identifier)) {
2922 TokError("invalid operand for instruction");
2923 return MatchOperand_ParseFail;
2924 }
2925
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002926 auto TSB = AArch64TSB::lookupTSBByName(Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00002927 // The only valid named option for ISB is 'sy'
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002928 auto DB = AArch64DB::lookupDBByName(Tok.getString());
2929 if (Mnemonic == "isb" && (!DB || DB->Encoding != AArch64DB::sy)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00002930 TokError("'sy' or #imm operand expected");
2931 return MatchOperand_ParseFail;
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002932 // The only valid named option for TSB is 'csync'
2933 } else if (Mnemonic == "tsb" && (!TSB || TSB->Encoding != AArch64TSB::csync)) {
2934 TokError("'csync' operand expected");
2935 return MatchOperand_ParseFail;
2936 } else if (!DB && !TSB) {
Sjoerd Meijere5b85572017-04-24 08:22:20 +00002937 TokError("invalid barrier option name");
2938 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00002939 }
2940
Tim Northovere6ae6762016-07-05 21:23:04 +00002941 Operands.push_back(AArch64Operand::CreateBarrier(
Sjoerd Meijer2a57b352018-07-06 08:03:12 +00002942 DB ? DB->Encoding : TSB->Encoding, Tok.getString(), getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002943 Parser.Lex(); // Consume the option
2944
2945 return MatchOperand_Success;
2946}
2947
Alex Bradbury58eba092016-11-01 16:32:05 +00002948OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00002949AArch64AsmParser::tryParseSysReg(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002950 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002951 const AsmToken &Tok = Parser.getTok();
2952
2953 if (Tok.isNot(AsmToken::Identifier))
2954 return MatchOperand_NoMatch;
2955
Tim Northovere6ae6762016-07-05 21:23:04 +00002956 int MRSReg, MSRReg;
2957 auto SysReg = AArch64SysReg::lookupSysRegByName(Tok.getString());
2958 if (SysReg && SysReg->haveFeatures(getSTI().getFeatureBits())) {
2959 MRSReg = SysReg->Readable ? SysReg->Encoding : -1;
2960 MSRReg = SysReg->Writeable ? SysReg->Encoding : -1;
2961 } else
2962 MRSReg = MSRReg = AArch64SysReg::parseGenericRegister(Tok.getString());
Tim Northover7cd58932015-01-22 17:23:04 +00002963
Tim Northovere6ae6762016-07-05 21:23:04 +00002964 auto PState = AArch64PState::lookupPStateByName(Tok.getString());
2965 unsigned PStateImm = -1;
2966 if (PState && PState->haveFeatures(getSTI().getFeatureBits()))
2967 PStateImm = PState->Encoding;
Tim Northover7cd58932015-01-22 17:23:04 +00002968
Tim Northovere6ae6762016-07-05 21:23:04 +00002969 Operands.push_back(
2970 AArch64Operand::CreateSysReg(Tok.getString(), getLoc(), MRSReg, MSRReg,
2971 PStateImm, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00002972 Parser.Lex(); // Eat identifier
2973
2974 return MatchOperand_Success;
2975}
2976
Florian Hahnc4422242017-11-07 13:07:50 +00002977/// tryParseNeonVectorRegister - Parse a vector register operand.
2978bool AArch64AsmParser::tryParseNeonVectorRegister(OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00002979 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00002980 if (Parser.getTok().isNot(AsmToken::Identifier))
2981 return true;
2982
2983 SMLoc S = getLoc();
2984 // Check for a vector register specifier first.
2985 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00002986 unsigned Reg;
Sander de Smalen73937b72018-04-11 07:36:10 +00002987 OperandMatchResultTy Res =
2988 tryParseVectorRegister(Reg, Kind, RegKind::NeonVector);
2989 if (Res != MatchOperand_Success)
Tim Northover3b0846e2014-05-24 12:50:23 +00002990 return true;
Sander de Smalen73937b72018-04-11 07:36:10 +00002991
2992 const auto &KindRes = parseVectorKind(Kind, RegKind::NeonVector);
2993 if (!KindRes)
2994 return true;
2995
2996 unsigned ElementWidth = KindRes->second;
Tim Northover3b0846e2014-05-24 12:50:23 +00002997 Operands.push_back(
Sander de Smalen73937b72018-04-11 07:36:10 +00002998 AArch64Operand::CreateVectorReg(Reg, RegKind::NeonVector, ElementWidth,
2999 S, getLoc(), getContext()));
Florian Hahnc4422242017-11-07 13:07:50 +00003000
Tim Northover3b0846e2014-05-24 12:50:23 +00003001 // If there was an explicit qualifier, that goes on as a literal text
3002 // operand.
3003 if (!Kind.empty())
3004 Operands.push_back(
3005 AArch64Operand::CreateToken(Kind, false, S, getContext()));
3006
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003007 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3008}
3009
3010OperandMatchResultTy
3011AArch64AsmParser::tryParseVectorIndex(OperandVector &Operands) {
Nirav Davee833c6c2016-11-08 18:31:04 +00003012 SMLoc SIdx = getLoc();
3013 if (parseOptionalToken(AsmToken::LBrac)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003014 const MCExpr *ImmVal;
3015 if (getParser().parseExpression(ImmVal))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003016 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003017 const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal);
3018 if (!MCE) {
3019 TokError("immediate value expected for vector index");
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003020 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003021 }
3022
3023 SMLoc E = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003024
Nirav Davee833c6c2016-11-08 18:31:04 +00003025 if (parseToken(AsmToken::RBrac, "']' expected"))
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003026 return MatchOperand_ParseFail;;
Tim Northover3b0846e2014-05-24 12:50:23 +00003027
3028 Operands.push_back(AArch64Operand::CreateVectorIndex(MCE->getValue(), SIdx,
3029 E, getContext()));
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003030 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003031 }
3032
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003033 return MatchOperand_NoMatch;
Tim Northover3b0846e2014-05-24 12:50:23 +00003034}
3035
Sander de Smalen73937b72018-04-11 07:36:10 +00003036// tryParseVectorRegister - Try to parse a vector register name with
Florian Hahn91f11e52017-11-07 16:45:48 +00003037// optional kind specifier. If it is a register specifier, eat the token
3038// and return it.
Sander de Smalen8e607342017-11-15 15:44:43 +00003039OperandMatchResultTy
Sander de Smalen50d87022018-04-19 07:35:08 +00003040AArch64AsmParser::tryParseVectorRegister(unsigned &Reg, StringRef &Kind,
Sander de Smalen73937b72018-04-11 07:36:10 +00003041 RegKind MatchKind) {
Sander de Smalen8e607342017-11-15 15:44:43 +00003042 MCAsmParser &Parser = getParser();
3043 const AsmToken &Tok = Parser.getTok();
3044
Florian Hahn91f11e52017-11-07 16:45:48 +00003045 if (Tok.isNot(AsmToken::Identifier))
Sander de Smalen8e607342017-11-15 15:44:43 +00003046 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003047
3048 StringRef Name = Tok.getString();
3049 // If there is a kind specifier, it's separated from the register name by
3050 // a '.'.
3051 size_t Start = 0, Next = Name.find('.');
3052 StringRef Head = Name.slice(Start, Next);
Sander de Smalen8e607342017-11-15 15:44:43 +00003053 unsigned RegNum = matchRegisterNameAlias(Head, MatchKind);
Florian Hahn91f11e52017-11-07 16:45:48 +00003054
3055 if (RegNum) {
3056 if (Next != StringRef::npos) {
3057 Kind = Name.slice(Next, StringRef::npos);
Sander de Smalen73937b72018-04-11 07:36:10 +00003058 if (!isValidVectorKind(Kind, MatchKind)) {
3059 TokError("invalid vector kind qualifier");
Sander de Smalen8e607342017-11-15 15:44:43 +00003060 return MatchOperand_ParseFail;
Florian Hahn91f11e52017-11-07 16:45:48 +00003061 }
3062 }
Sander de Smalen8e607342017-11-15 15:44:43 +00003063 Parser.Lex(); // Eat the register token.
3064
3065 Reg = RegNum;
3066 return MatchOperand_Success;
Florian Hahn91f11e52017-11-07 16:45:48 +00003067 }
3068
Sander de Smalen8e607342017-11-15 15:44:43 +00003069 return MatchOperand_NoMatch;
Florian Hahn91f11e52017-11-07 16:45:48 +00003070}
3071
Sander de Smalencd6be962017-12-20 11:02:42 +00003072/// tryParseSVEPredicateVector - Parse a SVE predicate register operand.
3073OperandMatchResultTy
3074AArch64AsmParser::tryParseSVEPredicateVector(OperandVector &Operands) {
3075 // Check for a SVE predicate register specifier first.
3076 const SMLoc S = getLoc();
3077 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003078 unsigned RegNum;
Sander de Smalen73937b72018-04-11 07:36:10 +00003079 auto Res = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00003080 if (Res != MatchOperand_Success)
3081 return Res;
3082
Sander de Smalen73937b72018-04-11 07:36:10 +00003083 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEPredicateVector);
3084 if (!KindRes)
Sander de Smalencd6be962017-12-20 11:02:42 +00003085 return MatchOperand_NoMatch;
3086
Sander de Smalen73937b72018-04-11 07:36:10 +00003087 unsigned ElementWidth = KindRes->second;
3088 Operands.push_back(AArch64Operand::CreateVectorReg(
3089 RegNum, RegKind::SVEPredicateVector, ElementWidth, S,
3090 getLoc(), getContext()));
Sander de Smalencd6be962017-12-20 11:02:42 +00003091
Sander de Smalen7868e742018-01-09 11:17:06 +00003092 // Not all predicates are followed by a '/m' or '/z'.
3093 MCAsmParser &Parser = getParser();
3094 if (Parser.getTok().isNot(AsmToken::Slash))
3095 return MatchOperand_Success;
3096
3097 // But when they do they shouldn't have an element type suffix.
3098 if (!Kind.empty()) {
3099 Error(S, "not expecting size suffix");
3100 return MatchOperand_ParseFail;
3101 }
3102
3103 // Add a literal slash as operand
3104 Operands.push_back(
3105 AArch64Operand::CreateToken("/" , false, getLoc(), getContext()));
3106
3107 Parser.Lex(); // Eat the slash.
3108
3109 // Zeroing or merging?
Sander de Smalen906a5de2018-01-09 17:01:27 +00003110 auto Pred = Parser.getTok().getString().lower();
Sander de Smalen7868e742018-01-09 11:17:06 +00003111 if (Pred != "z" && Pred != "m") {
3112 Error(getLoc(), "expecting 'm' or 'z' predication");
3113 return MatchOperand_ParseFail;
3114 }
3115
3116 // Add zero/merge token.
3117 const char *ZM = Pred == "z" ? "z" : "m";
3118 Operands.push_back(
3119 AArch64Operand::CreateToken(ZM, false, getLoc(), getContext()));
3120
3121 Parser.Lex(); // Eat zero/merge token.
Sander de Smalencd6be962017-12-20 11:02:42 +00003122 return MatchOperand_Success;
3123}
3124
Sander de Smalen50d87022018-04-19 07:35:08 +00003125/// parseRegister - Parse a register operand.
Tim Northover3b0846e2014-05-24 12:50:23 +00003126bool AArch64AsmParser::parseRegister(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003127 // Try for a Neon vector register.
Florian Hahnc4422242017-11-07 13:07:50 +00003128 if (!tryParseNeonVectorRegister(Operands))
Tim Northover3b0846e2014-05-24 12:50:23 +00003129 return false;
3130
Sander de Smalen149916d2018-04-20 07:24:20 +00003131 // Otherwise try for a scalar register.
3132 if (tryParseGPROperand<false>(Operands) == MatchOperand_Success)
3133 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00003134
Sander de Smalen149916d2018-04-20 07:24:20 +00003135 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003136}
3137
3138bool AArch64AsmParser::parseSymbolicImmVal(const MCExpr *&ImmVal) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003139 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003140 bool HasELFModifier = false;
3141 AArch64MCExpr::VariantKind RefKind;
3142
Nirav Davee833c6c2016-11-08 18:31:04 +00003143 if (parseOptionalToken(AsmToken::Colon)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003144 HasELFModifier = true;
3145
Nirav Davee833c6c2016-11-08 18:31:04 +00003146 if (Parser.getTok().isNot(AsmToken::Identifier))
3147 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003148
3149 std::string LowerCase = Parser.getTok().getIdentifier().lower();
3150 RefKind = StringSwitch<AArch64MCExpr::VariantKind>(LowerCase)
3151 .Case("lo12", AArch64MCExpr::VK_LO12)
3152 .Case("abs_g3", AArch64MCExpr::VK_ABS_G3)
3153 .Case("abs_g2", AArch64MCExpr::VK_ABS_G2)
3154 .Case("abs_g2_s", AArch64MCExpr::VK_ABS_G2_S)
3155 .Case("abs_g2_nc", AArch64MCExpr::VK_ABS_G2_NC)
3156 .Case("abs_g1", AArch64MCExpr::VK_ABS_G1)
3157 .Case("abs_g1_s", AArch64MCExpr::VK_ABS_G1_S)
3158 .Case("abs_g1_nc", AArch64MCExpr::VK_ABS_G1_NC)
3159 .Case("abs_g0", AArch64MCExpr::VK_ABS_G0)
3160 .Case("abs_g0_s", AArch64MCExpr::VK_ABS_G0_S)
3161 .Case("abs_g0_nc", AArch64MCExpr::VK_ABS_G0_NC)
3162 .Case("dtprel_g2", AArch64MCExpr::VK_DTPREL_G2)
3163 .Case("dtprel_g1", AArch64MCExpr::VK_DTPREL_G1)
3164 .Case("dtprel_g1_nc", AArch64MCExpr::VK_DTPREL_G1_NC)
3165 .Case("dtprel_g0", AArch64MCExpr::VK_DTPREL_G0)
3166 .Case("dtprel_g0_nc", AArch64MCExpr::VK_DTPREL_G0_NC)
3167 .Case("dtprel_hi12", AArch64MCExpr::VK_DTPREL_HI12)
3168 .Case("dtprel_lo12", AArch64MCExpr::VK_DTPREL_LO12)
3169 .Case("dtprel_lo12_nc", AArch64MCExpr::VK_DTPREL_LO12_NC)
3170 .Case("tprel_g2", AArch64MCExpr::VK_TPREL_G2)
3171 .Case("tprel_g1", AArch64MCExpr::VK_TPREL_G1)
3172 .Case("tprel_g1_nc", AArch64MCExpr::VK_TPREL_G1_NC)
3173 .Case("tprel_g0", AArch64MCExpr::VK_TPREL_G0)
3174 .Case("tprel_g0_nc", AArch64MCExpr::VK_TPREL_G0_NC)
3175 .Case("tprel_hi12", AArch64MCExpr::VK_TPREL_HI12)
3176 .Case("tprel_lo12", AArch64MCExpr::VK_TPREL_LO12)
3177 .Case("tprel_lo12_nc", AArch64MCExpr::VK_TPREL_LO12_NC)
3178 .Case("tlsdesc_lo12", AArch64MCExpr::VK_TLSDESC_LO12)
3179 .Case("got", AArch64MCExpr::VK_GOT_PAGE)
3180 .Case("got_lo12", AArch64MCExpr::VK_GOT_LO12)
3181 .Case("gottprel", AArch64MCExpr::VK_GOTTPREL_PAGE)
3182 .Case("gottprel_lo12", AArch64MCExpr::VK_GOTTPREL_LO12_NC)
3183 .Case("gottprel_g1", AArch64MCExpr::VK_GOTTPREL_G1)
3184 .Case("gottprel_g0_nc", AArch64MCExpr::VK_GOTTPREL_G0_NC)
3185 .Case("tlsdesc", AArch64MCExpr::VK_TLSDESC_PAGE)
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00003186 .Case("secrel_lo12", AArch64MCExpr::VK_SECREL_LO12)
3187 .Case("secrel_hi12", AArch64MCExpr::VK_SECREL_HI12)
Tim Northover3b0846e2014-05-24 12:50:23 +00003188 .Default(AArch64MCExpr::VK_INVALID);
3189
Nirav Davee833c6c2016-11-08 18:31:04 +00003190 if (RefKind == AArch64MCExpr::VK_INVALID)
3191 return TokError("expect relocation specifier in operand after ':'");
Tim Northover3b0846e2014-05-24 12:50:23 +00003192
3193 Parser.Lex(); // Eat identifier
3194
Nirav Davee833c6c2016-11-08 18:31:04 +00003195 if (parseToken(AsmToken::Colon, "expect ':' after relocation specifier"))
Tim Northover3b0846e2014-05-24 12:50:23 +00003196 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003197 }
3198
3199 if (getParser().parseExpression(ImmVal))
3200 return true;
3201
3202 if (HasELFModifier)
Jim Grosbach13760bd2015-05-30 01:25:56 +00003203 ImmVal = AArch64MCExpr::create(ImmVal, RefKind, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00003204
3205 return false;
3206}
3207
Sander de Smalen650234b2018-04-12 11:40:52 +00003208template <RegKind VectorKind>
3209OperandMatchResultTy
3210AArch64AsmParser::tryParseVectorList(OperandVector &Operands,
3211 bool ExpectMatch) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003212 MCAsmParser &Parser = getParser();
Sander de Smalen650234b2018-04-12 11:40:52 +00003213 if (!Parser.getTok().is(AsmToken::LCurly))
3214 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003215
3216 // Wrapper around parse function
Sander de Smalen50d87022018-04-19 07:35:08 +00003217 auto ParseVector = [this, &Parser](unsigned &Reg, StringRef &Kind, SMLoc Loc,
Sander de Smalen650234b2018-04-12 11:40:52 +00003218 bool NoMatchIsError) {
3219 auto RegTok = Parser.getTok();
3220 auto ParseRes = tryParseVectorRegister(Reg, Kind, VectorKind);
3221 if (ParseRes == MatchOperand_Success) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003222 if (parseVectorKind(Kind, VectorKind))
Sander de Smalen650234b2018-04-12 11:40:52 +00003223 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003224 llvm_unreachable("Expected a valid vector kind");
3225 }
3226
Sander de Smalen650234b2018-04-12 11:40:52 +00003227 if (RegTok.isNot(AsmToken::Identifier) ||
3228 ParseRes == MatchOperand_ParseFail ||
3229 (ParseRes == MatchOperand_NoMatch && NoMatchIsError)) {
3230 Error(Loc, "vector register expected");
3231 return MatchOperand_ParseFail;
3232 }
3233
3234 return MatchOperand_NoMatch;
Sander de Smalen73937b72018-04-11 07:36:10 +00003235 };
3236
Tim Northover3b0846e2014-05-24 12:50:23 +00003237 SMLoc S = getLoc();
Sander de Smalen650234b2018-04-12 11:40:52 +00003238 auto LCurly = Parser.getTok();
Tim Northover3b0846e2014-05-24 12:50:23 +00003239 Parser.Lex(); // Eat left bracket token.
Sander de Smalen650234b2018-04-12 11:40:52 +00003240
Tim Northover3b0846e2014-05-24 12:50:23 +00003241 StringRef Kind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003242 unsigned FirstReg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003243 auto ParseRes = ParseVector(FirstReg, Kind, getLoc(), ExpectMatch);
3244
3245 // Put back the original left bracket if there was no match, so that
3246 // different types of list-operands can be matched (e.g. SVE, Neon).
3247 if (ParseRes == MatchOperand_NoMatch)
3248 Parser.getLexer().UnLex(LCurly);
3249
3250 if (ParseRes != MatchOperand_Success)
3251 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003252
Tim Northover3b0846e2014-05-24 12:50:23 +00003253 int64_t PrevReg = FirstReg;
3254 unsigned Count = 1;
3255
Nirav Davee833c6c2016-11-08 18:31:04 +00003256 if (parseOptionalToken(AsmToken::Minus)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003257 SMLoc Loc = getLoc();
3258 StringRef NextKind;
Sander de Smalen73937b72018-04-11 07:36:10 +00003259
Sander de Smalen50d87022018-04-19 07:35:08 +00003260 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003261 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3262 if (ParseRes != MatchOperand_Success)
3263 return ParseRes;
Sander de Smalen73937b72018-04-11 07:36:10 +00003264
Tim Northover3b0846e2014-05-24 12:50:23 +00003265 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003266 if (Kind != NextKind) {
3267 Error(Loc, "mismatched register size suffix");
3268 return MatchOperand_ParseFail;
3269 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003270
3271 unsigned Space = (PrevReg < Reg) ? (Reg - PrevReg) : (Reg + 32 - PrevReg);
3272
3273 if (Space == 0 || Space > 3) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003274 Error(Loc, "invalid number of vectors");
3275 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003276 }
3277
3278 Count += Space;
3279 }
3280 else {
Nirav Davee833c6c2016-11-08 18:31:04 +00003281 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003282 SMLoc Loc = getLoc();
3283 StringRef NextKind;
Sander de Smalen50d87022018-04-19 07:35:08 +00003284 unsigned Reg;
Sander de Smalen650234b2018-04-12 11:40:52 +00003285 ParseRes = ParseVector(Reg, NextKind, getLoc(), true);
3286 if (ParseRes != MatchOperand_Success)
3287 return ParseRes;
3288
Tim Northover3b0846e2014-05-24 12:50:23 +00003289 // Any Kind suffices must match on all regs in the list.
Sander de Smalen650234b2018-04-12 11:40:52 +00003290 if (Kind != NextKind) {
3291 Error(Loc, "mismatched register size suffix");
3292 return MatchOperand_ParseFail;
3293 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003294
3295 // Registers must be incremental (with wraparound at 31)
3296 if (getContext().getRegisterInfo()->getEncodingValue(Reg) !=
Sander de Smalen650234b2018-04-12 11:40:52 +00003297 (getContext().getRegisterInfo()->getEncodingValue(PrevReg) + 1) % 32) {
3298 Error(Loc, "registers must be sequential");
3299 return MatchOperand_ParseFail;
3300 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003301
3302 PrevReg = Reg;
3303 ++Count;
3304 }
3305 }
3306
Nirav Davee833c6c2016-11-08 18:31:04 +00003307 if (parseToken(AsmToken::RCurly, "'}' expected"))
Sander de Smalen650234b2018-04-12 11:40:52 +00003308 return MatchOperand_ParseFail;
Tim Northover3b0846e2014-05-24 12:50:23 +00003309
Sander de Smalen650234b2018-04-12 11:40:52 +00003310 if (Count > 4) {
3311 Error(S, "invalid number of vectors");
3312 return MatchOperand_ParseFail;
3313 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003314
3315 unsigned NumElements = 0;
Sander de Smalen73937b72018-04-11 07:36:10 +00003316 unsigned ElementWidth = 0;
3317 if (!Kind.empty()) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003318 if (const auto &VK = parseVectorKind(Kind, VectorKind))
Sander de Smalen73937b72018-04-11 07:36:10 +00003319 std::tie(NumElements, ElementWidth) = *VK;
3320 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003321
3322 Operands.push_back(AArch64Operand::CreateVectorList(
Sander de Smalen650234b2018-04-12 11:40:52 +00003323 FirstReg, Count, NumElements, ElementWidth, VectorKind, S, getLoc(),
3324 getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003325
Sander de Smalen650234b2018-04-12 11:40:52 +00003326 return MatchOperand_Success;
Tim Northover3b0846e2014-05-24 12:50:23 +00003327}
3328
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003329/// parseNeonVectorList - Parse a vector list operand for AdvSIMD instructions.
3330bool AArch64AsmParser::parseNeonVectorList(OperandVector &Operands) {
Sander de Smalen650234b2018-04-12 11:40:52 +00003331 auto ParseRes = tryParseVectorList<RegKind::NeonVector>(Operands, true);
3332 if (ParseRes != MatchOperand_Success)
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003333 return true;
3334
3335 return tryParseVectorIndex(Operands) == MatchOperand_ParseFail;
3336}
3337
Alex Bradbury58eba092016-11-01 16:32:05 +00003338OperandMatchResultTy
Tim Northover3b0846e2014-05-24 12:50:23 +00003339AArch64AsmParser::tryParseGPR64sp0Operand(OperandVector &Operands) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003340 SMLoc StartLoc = getLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00003341
Sander de Smalen50d87022018-04-19 07:35:08 +00003342 unsigned RegNum;
3343 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3344 if (Res != MatchOperand_Success)
3345 return Res;
Tim Northover3b0846e2014-05-24 12:50:23 +00003346
Nirav Davee833c6c2016-11-08 18:31:04 +00003347 if (!parseOptionalToken(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00003348 Operands.push_back(AArch64Operand::CreateReg(
3349 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003350 return MatchOperand_Success;
3351 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003352
Nirav Davee833c6c2016-11-08 18:31:04 +00003353 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003354
Sander de Smalen50d87022018-04-19 07:35:08 +00003355 if (getParser().getTok().isNot(AsmToken::Integer)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003356 Error(getLoc(), "index must be absent or #0");
3357 return MatchOperand_ParseFail;
3358 }
3359
3360 const MCExpr *ImmVal;
Sander de Smalen50d87022018-04-19 07:35:08 +00003361 if (getParser().parseExpression(ImmVal) || !isa<MCConstantExpr>(ImmVal) ||
Tim Northover3b0846e2014-05-24 12:50:23 +00003362 cast<MCConstantExpr>(ImmVal)->getValue() != 0) {
3363 Error(getLoc(), "index must be absent or #0");
3364 return MatchOperand_ParseFail;
3365 }
3366
Sander de Smalen50d87022018-04-19 07:35:08 +00003367 Operands.push_back(AArch64Operand::CreateReg(
3368 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003369 return MatchOperand_Success;
3370}
3371
Sander de Smalen0325e302018-07-02 07:34:52 +00003372template <bool ParseShiftExtend, RegConstraintEqualityTy EqTy>
Sander de Smalen149916d2018-04-20 07:24:20 +00003373OperandMatchResultTy
3374AArch64AsmParser::tryParseGPROperand(OperandVector &Operands) {
3375 SMLoc StartLoc = getLoc();
3376
3377 unsigned RegNum;
3378 OperandMatchResultTy Res = tryParseScalarRegister(RegNum);
3379 if (Res != MatchOperand_Success)
3380 return Res;
3381
3382 // No shift/extend is the default.
3383 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
3384 Operands.push_back(AArch64Operand::CreateReg(
Sander de Smalen0325e302018-07-02 07:34:52 +00003385 RegNum, RegKind::Scalar, StartLoc, getLoc(), getContext(), EqTy));
Sander de Smalen149916d2018-04-20 07:24:20 +00003386 return MatchOperand_Success;
3387 }
3388
3389 // Eat the comma
3390 getParser().Lex();
3391
3392 // Match the shift
3393 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
3394 Res = tryParseOptionalShiftExtend(ExtOpnd);
3395 if (Res != MatchOperand_Success)
3396 return Res;
3397
3398 auto Ext = static_cast<AArch64Operand*>(ExtOpnd.back().get());
Sander de Smalen0325e302018-07-02 07:34:52 +00003399 Operands.push_back(AArch64Operand::CreateReg(
3400 RegNum, RegKind::Scalar, StartLoc, Ext->getEndLoc(), getContext(), EqTy,
3401 Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
3402 Ext->hasShiftExtendAmount()));
Sander de Smalen149916d2018-04-20 07:24:20 +00003403
3404 return MatchOperand_Success;
3405}
3406
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003407bool AArch64AsmParser::parseOptionalMulOperand(OperandVector &Operands) {
Sander de Smalen5c625982018-04-13 12:56:14 +00003408 MCAsmParser &Parser = getParser();
3409
3410 // Some SVE instructions have a decoration after the immediate, i.e.
3411 // "mul vl". We parse them here and add tokens, which must be present in the
3412 // asm string in the tablegen instruction.
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003413 bool NextIsVL = Parser.getLexer().peekTok().getString().equals_lower("vl");
3414 bool NextIsHash = Parser.getLexer().peekTok().is(AsmToken::Hash);
Sander de Smalen5c625982018-04-13 12:56:14 +00003415 if (!Parser.getTok().getString().equals_lower("mul") ||
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003416 !(NextIsVL || NextIsHash))
Sander de Smalen5c625982018-04-13 12:56:14 +00003417 return true;
3418
Sander de Smalen5c625982018-04-13 12:56:14 +00003419 Operands.push_back(
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003420 AArch64Operand::CreateToken("mul", false, getLoc(), getContext()));
Sander de Smalen5c625982018-04-13 12:56:14 +00003421 Parser.Lex(); // Eat the "mul"
3422
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003423 if (NextIsVL) {
3424 Operands.push_back(
3425 AArch64Operand::CreateToken("vl", false, getLoc(), getContext()));
3426 Parser.Lex(); // Eat the "vl"
3427 return false;
3428 }
Sander de Smalen5c625982018-04-13 12:56:14 +00003429
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003430 if (NextIsHash) {
3431 Parser.Lex(); // Eat the #
3432 SMLoc S = getLoc();
3433
3434 // Parse immediate operand.
3435 const MCExpr *ImmVal;
3436 if (!Parser.parseExpression(ImmVal))
3437 if (const MCConstantExpr *MCE = dyn_cast<MCConstantExpr>(ImmVal)) {
3438 Operands.push_back(AArch64Operand::CreateImm(
3439 MCConstantExpr::create(MCE->getValue(), getContext()), S, getLoc(),
3440 getContext()));
3441 return MatchOperand_Success;
3442 }
3443 }
3444
3445 return Error(getLoc(), "expected 'vl' or '#<imm>'");
Sander de Smalen5c625982018-04-13 12:56:14 +00003446}
3447
Tim Northover3b0846e2014-05-24 12:50:23 +00003448/// parseOperand - Parse a arm instruction operand. For now this parses the
3449/// operand regardless of the mnemonic.
3450bool AArch64AsmParser::parseOperand(OperandVector &Operands, bool isCondCode,
3451 bool invertCondCode) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003452 MCAsmParser &Parser = getParser();
Sander de Smalencd6be962017-12-20 11:02:42 +00003453
3454 OperandMatchResultTy ResTy =
3455 MatchOperandParserImpl(Operands, Mnemonic, /*ParseForAllFeatures=*/ true);
3456
Tim Northover3b0846e2014-05-24 12:50:23 +00003457 // Check if the current operand has a custom associated parser, if so, try to
3458 // custom parse the operand, or fallback to the general approach.
Tim Northover3b0846e2014-05-24 12:50:23 +00003459 if (ResTy == MatchOperand_Success)
3460 return false;
3461 // If there wasn't a custom match, try the generic matcher below. Otherwise,
3462 // there was a match, but an error occurred, in which case, just return that
3463 // the operand parsing failed.
3464 if (ResTy == MatchOperand_ParseFail)
3465 return true;
3466
3467 // Nothing custom, so do general case parsing.
3468 SMLoc S, E;
3469 switch (getLexer().getKind()) {
3470 default: {
3471 SMLoc S = getLoc();
3472 const MCExpr *Expr;
3473 if (parseSymbolicImmVal(Expr))
3474 return Error(S, "invalid operand");
3475
3476 SMLoc E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3477 Operands.push_back(AArch64Operand::CreateImm(Expr, S, E, getContext()));
3478 return false;
3479 }
3480 case AsmToken::LBrac: {
3481 SMLoc Loc = Parser.getTok().getLoc();
3482 Operands.push_back(AArch64Operand::CreateToken("[", false, Loc,
3483 getContext()));
3484 Parser.Lex(); // Eat '['
3485
3486 // There's no comma after a '[', so we can parse the next operand
3487 // immediately.
3488 return parseOperand(Operands, false, false);
3489 }
3490 case AsmToken::LCurly:
Sander de Smalenc88f9a12018-04-11 14:10:37 +00003491 return parseNeonVectorList(Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003492 case AsmToken::Identifier: {
3493 // If we're expecting a Condition Code operand, then just parse that.
3494 if (isCondCode)
3495 return parseCondCode(Operands, invertCondCode);
3496
3497 // If it's a register name, parse it.
3498 if (!parseRegister(Operands))
3499 return false;
3500
Sander de Smalen18ac8f92018-06-15 15:47:44 +00003501 // See if this is a "mul vl" decoration or "mul #<int>" operand used
3502 // by SVE instructions.
3503 if (!parseOptionalMulOperand(Operands))
Sander de Smalen5c625982018-04-13 12:56:14 +00003504 return false;
3505
Tim Northover3b0846e2014-05-24 12:50:23 +00003506 // This could be an optional "shift" or "extend" operand.
3507 OperandMatchResultTy GotShift = tryParseOptionalShiftExtend(Operands);
3508 // We can only continue if no tokens were eaten.
3509 if (GotShift != MatchOperand_NoMatch)
3510 return GotShift;
3511
3512 // This was not a register so parse other operands that start with an
3513 // identifier (like labels) as expressions and create them as immediates.
3514 const MCExpr *IdVal;
3515 S = getLoc();
3516 if (getParser().parseExpression(IdVal))
3517 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003518 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3519 Operands.push_back(AArch64Operand::CreateImm(IdVal, S, E, getContext()));
3520 return false;
3521 }
3522 case AsmToken::Integer:
3523 case AsmToken::Real:
3524 case AsmToken::Hash: {
3525 // #42 -> immediate.
3526 S = getLoc();
Nirav Davee833c6c2016-11-08 18:31:04 +00003527
3528 parseOptionalToken(AsmToken::Hash);
Tim Northover3b0846e2014-05-24 12:50:23 +00003529
3530 // Parse a negative sign
3531 bool isNegative = false;
3532 if (Parser.getTok().is(AsmToken::Minus)) {
3533 isNegative = true;
3534 // We need to consume this token only when we have a Real, otherwise
3535 // we let parseSymbolicImmVal take care of it
3536 if (Parser.getLexer().peekTok().is(AsmToken::Real))
3537 Parser.Lex();
3538 }
3539
3540 // The only Real that should come through here is a literal #0.0 for
3541 // the fcmp[e] r, #0.0 instructions. They expect raw token operands,
3542 // so convert the value.
3543 const AsmToken &Tok = Parser.getTok();
3544 if (Tok.is(AsmToken::Real)) {
Stephan Bergmann17c7f702016-12-14 11:57:17 +00003545 APFloat RealVal(APFloat::IEEEdouble(), Tok.getString());
Tim Northover3b0846e2014-05-24 12:50:23 +00003546 uint64_t IntVal = RealVal.bitcastToAPInt().getZExtValue();
3547 if (Mnemonic != "fcmp" && Mnemonic != "fcmpe" && Mnemonic != "fcmeq" &&
3548 Mnemonic != "fcmge" && Mnemonic != "fcmgt" && Mnemonic != "fcmle" &&
Sander de Smalen8fcc3f52018-07-03 09:07:23 +00003549 Mnemonic != "fcmlt" && Mnemonic != "fcmne")
Tim Northover3b0846e2014-05-24 12:50:23 +00003550 return TokError("unexpected floating point literal");
3551 else if (IntVal != 0 || isNegative)
3552 return TokError("expected floating-point constant #0.0");
3553 Parser.Lex(); // Eat the token.
3554
3555 Operands.push_back(
3556 AArch64Operand::CreateToken("#0", false, S, getContext()));
3557 Operands.push_back(
3558 AArch64Operand::CreateToken(".0", false, S, getContext()));
3559 return false;
3560 }
3561
3562 const MCExpr *ImmVal;
3563 if (parseSymbolicImmVal(ImmVal))
3564 return true;
3565
3566 E = SMLoc::getFromPointer(getLoc().getPointer() - 1);
3567 Operands.push_back(AArch64Operand::CreateImm(ImmVal, S, E, getContext()));
3568 return false;
3569 }
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003570 case AsmToken::Equal: {
Nirav Davee833c6c2016-11-08 18:31:04 +00003571 SMLoc Loc = getLoc();
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003572 if (Mnemonic != "ldr") // only parse for ldr pseudo (e.g. ldr r0, =val)
Nirav Davee833c6c2016-11-08 18:31:04 +00003573 return TokError("unexpected token in operand");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003574 Parser.Lex(); // Eat '='
3575 const MCExpr *SubExprVal;
3576 if (getParser().parseExpression(SubExprVal))
3577 return true;
3578
David Peixottoae5ba762014-07-18 16:05:14 +00003579 if (Operands.size() < 2 ||
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00003580 !static_cast<AArch64Operand &>(*Operands[1]).isScalarReg())
Oliver Stannarddb9081b2015-11-16 10:25:19 +00003581 return Error(Loc, "Only valid when first operand is register");
David Peixottoae5ba762014-07-18 16:05:14 +00003582
3583 bool IsXReg =
3584 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
3585 Operands[1]->getReg());
3586
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003587 MCContext& Ctx = getContext();
3588 E = SMLoc::getFromPointer(Loc.getPointer() - 1);
3589 // 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 +00003590 if (isa<MCConstantExpr>(SubExprVal)) {
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003591 uint64_t Imm = (cast<MCConstantExpr>(SubExprVal))->getValue();
3592 uint32_t ShiftAmt = 0, MaxShiftAmt = IsXReg ? 48 : 16;
3593 while(Imm > 0xFFFF && countTrailingZeros(Imm) >= 16) {
3594 ShiftAmt += 16;
3595 Imm >>= 16;
3596 }
3597 if (ShiftAmt <= MaxShiftAmt && Imm <= 0xFFFF) {
3598 Operands[0] = AArch64Operand::CreateToken("movz", false, Loc, Ctx);
3599 Operands.push_back(AArch64Operand::CreateImm(
Jim Grosbach13760bd2015-05-30 01:25:56 +00003600 MCConstantExpr::create(Imm, Ctx), S, E, Ctx));
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003601 if (ShiftAmt)
3602 Operands.push_back(AArch64Operand::CreateShiftExtend(AArch64_AM::LSL,
3603 ShiftAmt, true, S, E, Ctx));
3604 return false;
3605 }
David Peixottoae5ba762014-07-18 16:05:14 +00003606 APInt Simm = APInt(64, Imm << ShiftAmt);
3607 // check if the immediate is an unsigned or signed 32-bit int for W regs
3608 if (!IsXReg && !(Simm.isIntN(32) || Simm.isSignedIntN(32)))
3609 return Error(Loc, "Immediate too large for register");
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003610 }
3611 // 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 +00003612 const MCExpr *CPLoc =
Oliver Stannard9327a752015-11-16 16:25:47 +00003613 getTargetStreamer().addConstantPoolEntry(SubExprVal, IsXReg ? 8 : 4, Loc);
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00003614 Operands.push_back(AArch64Operand::CreateImm(CPLoc, S, E, Ctx));
3615 return false;
3616 }
Tim Northover3b0846e2014-05-24 12:50:23 +00003617 }
3618}
3619
Sander de Smalen0325e302018-07-02 07:34:52 +00003620bool AArch64AsmParser::regsEqual(const MCParsedAsmOperand &Op1,
3621 const MCParsedAsmOperand &Op2) const {
3622 auto &AOp1 = static_cast<const AArch64Operand&>(Op1);
3623 auto &AOp2 = static_cast<const AArch64Operand&>(Op2);
3624 if (AOp1.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg &&
3625 AOp2.getRegEqualityTy() == RegConstraintEqualityTy::EqualsReg)
3626 return MCTargetAsmParser::regsEqual(Op1, Op2);
3627
3628 assert(AOp1.isScalarReg() && AOp2.isScalarReg() &&
3629 "Testing equality of non-scalar registers not supported");
3630
3631 // Check if a registers match their sub/super register classes.
3632 if (AOp1.getRegEqualityTy() == EqualsSuperReg)
3633 return getXRegFromWReg(Op1.getReg()) == Op2.getReg();
3634 if (AOp1.getRegEqualityTy() == EqualsSubReg)
3635 return getWRegFromXReg(Op1.getReg()) == Op2.getReg();
3636 if (AOp2.getRegEqualityTy() == EqualsSuperReg)
3637 return getXRegFromWReg(Op2.getReg()) == Op1.getReg();
3638 if (AOp2.getRegEqualityTy() == EqualsSubReg)
3639 return getWRegFromXReg(Op2.getReg()) == Op1.getReg();
3640
3641 return false;
3642}
3643
Tim Northover3b0846e2014-05-24 12:50:23 +00003644/// ParseInstruction - Parse an AArch64 instruction mnemonic followed by its
3645/// operands.
3646bool AArch64AsmParser::ParseInstruction(ParseInstructionInfo &Info,
3647 StringRef Name, SMLoc NameLoc,
3648 OperandVector &Operands) {
Rafael Espindola961d4692014-11-11 05:18:41 +00003649 MCAsmParser &Parser = getParser();
Tim Northover3b0846e2014-05-24 12:50:23 +00003650 Name = StringSwitch<StringRef>(Name.lower())
3651 .Case("beq", "b.eq")
3652 .Case("bne", "b.ne")
3653 .Case("bhs", "b.hs")
3654 .Case("bcs", "b.cs")
3655 .Case("blo", "b.lo")
3656 .Case("bcc", "b.cc")
3657 .Case("bmi", "b.mi")
3658 .Case("bpl", "b.pl")
3659 .Case("bvs", "b.vs")
3660 .Case("bvc", "b.vc")
3661 .Case("bhi", "b.hi")
3662 .Case("bls", "b.ls")
3663 .Case("bge", "b.ge")
3664 .Case("blt", "b.lt")
3665 .Case("bgt", "b.gt")
3666 .Case("ble", "b.le")
3667 .Case("bal", "b.al")
3668 .Case("bnv", "b.nv")
3669 .Default(Name);
3670
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00003671 // First check for the AArch64-specific .req directive.
3672 if (Parser.getTok().is(AsmToken::Identifier) &&
3673 Parser.getTok().getIdentifier() == ".req") {
3674 parseDirectiveReq(Name, NameLoc);
3675 // We always return 'error' for this, as we're done with this
3676 // statement and don't need to match the 'instruction."
3677 return true;
3678 }
3679
Tim Northover3b0846e2014-05-24 12:50:23 +00003680 // Create the leading tokens for the mnemonic, split by '.' characters.
3681 size_t Start = 0, Next = Name.find('.');
3682 StringRef Head = Name.slice(Start, Next);
3683
3684 // IC, DC, AT, and TLBI instructions are aliases for the SYS instruction.
Nirav Davee833c6c2016-11-08 18:31:04 +00003685 if (Head == "ic" || Head == "dc" || Head == "at" || Head == "tlbi")
3686 return parseSysAlias(Head, NameLoc, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00003687
3688 Operands.push_back(
3689 AArch64Operand::CreateToken(Head, false, NameLoc, getContext()));
3690 Mnemonic = Head;
3691
3692 // Handle condition codes for a branch mnemonic
3693 if (Head == "b" && Next != StringRef::npos) {
3694 Start = Next;
3695 Next = Name.find('.', Start + 1);
3696 Head = Name.slice(Start + 1, Next);
3697
3698 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3699 (Head.data() - Name.data()));
3700 AArch64CC::CondCode CC = parseCondCodeString(Head);
3701 if (CC == AArch64CC::Invalid)
3702 return Error(SuffixLoc, "invalid condition code");
3703 Operands.push_back(
3704 AArch64Operand::CreateToken(".", true, SuffixLoc, getContext()));
3705 Operands.push_back(
3706 AArch64Operand::CreateCondCode(CC, NameLoc, NameLoc, getContext()));
3707 }
3708
3709 // Add the remaining tokens in the mnemonic.
3710 while (Next != StringRef::npos) {
3711 Start = Next;
3712 Next = Name.find('.', Start + 1);
3713 Head = Name.slice(Start, Next);
3714 SMLoc SuffixLoc = SMLoc::getFromPointer(NameLoc.getPointer() +
3715 (Head.data() - Name.data()) + 1);
3716 Operands.push_back(
3717 AArch64Operand::CreateToken(Head, true, SuffixLoc, getContext()));
3718 }
3719
3720 // Conditional compare instructions have a Condition Code operand, which needs
3721 // to be parsed and an immediate operand created.
3722 bool condCodeFourthOperand =
3723 (Head == "ccmp" || Head == "ccmn" || Head == "fccmp" ||
3724 Head == "fccmpe" || Head == "fcsel" || Head == "csel" ||
3725 Head == "csinc" || Head == "csinv" || Head == "csneg");
3726
3727 // These instructions are aliases to some of the conditional select
3728 // instructions. However, the condition code is inverted in the aliased
3729 // instruction.
3730 //
3731 // FIXME: Is this the correct way to handle these? Or should the parser
3732 // generate the aliased instructions directly?
3733 bool condCodeSecondOperand = (Head == "cset" || Head == "csetm");
3734 bool condCodeThirdOperand =
3735 (Head == "cinc" || Head == "cinv" || Head == "cneg");
3736
3737 // Read the remaining operands.
3738 if (getLexer().isNot(AsmToken::EndOfStatement)) {
3739 // Read the first operand.
3740 if (parseOperand(Operands, false, false)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003741 return true;
3742 }
3743
3744 unsigned N = 2;
Nirav Davee833c6c2016-11-08 18:31:04 +00003745 while (parseOptionalToken(AsmToken::Comma)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003746 // Parse and remember the operand.
3747 if (parseOperand(Operands, (N == 4 && condCodeFourthOperand) ||
3748 (N == 3 && condCodeThirdOperand) ||
3749 (N == 2 && condCodeSecondOperand),
3750 condCodeSecondOperand || condCodeThirdOperand)) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003751 return true;
3752 }
3753
3754 // After successfully parsing some operands there are two special cases to
3755 // consider (i.e. notional operands not separated by commas). Both are due
3756 // to memory specifiers:
3757 // + An RBrac will end an address for load/store/prefetch
3758 // + An '!' will indicate a pre-indexed operation.
3759 //
3760 // It's someone else's responsibility to make sure these tokens are sane
3761 // in the given context!
Tim Northover3b0846e2014-05-24 12:50:23 +00003762
Nirav Davee833c6c2016-11-08 18:31:04 +00003763 SMLoc RLoc = Parser.getTok().getLoc();
3764 if (parseOptionalToken(AsmToken::RBrac))
3765 Operands.push_back(
3766 AArch64Operand::CreateToken("]", false, RLoc, getContext()));
3767 SMLoc ELoc = Parser.getTok().getLoc();
3768 if (parseOptionalToken(AsmToken::Exclaim))
3769 Operands.push_back(
3770 AArch64Operand::CreateToken("!", false, ELoc, getContext()));
Tim Northover3b0846e2014-05-24 12:50:23 +00003771
3772 ++N;
3773 }
3774 }
3775
Nirav Davee833c6c2016-11-08 18:31:04 +00003776 if (parseToken(AsmToken::EndOfStatement, "unexpected token in argument list"))
3777 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00003778
Tim Northover3b0846e2014-05-24 12:50:23 +00003779 return false;
3780}
3781
Sander de Smalen9b333092018-07-30 15:42:46 +00003782static inline bool isMatchingOrAlias(unsigned ZReg, unsigned Reg) {
3783 assert((ZReg >= AArch64::Z0) && (ZReg <= AArch64::Z31));
3784 return (ZReg == ((Reg - AArch64::B0) + AArch64::Z0)) ||
3785 (ZReg == ((Reg - AArch64::H0) + AArch64::Z0)) ||
3786 (ZReg == ((Reg - AArch64::S0) + AArch64::Z0)) ||
3787 (ZReg == ((Reg - AArch64::D0) + AArch64::Z0)) ||
3788 (ZReg == ((Reg - AArch64::Q0) + AArch64::Z0)) ||
3789 (ZReg == ((Reg - AArch64::Z0) + AArch64::Z0));
3790}
3791
Tim Northover3b0846e2014-05-24 12:50:23 +00003792// FIXME: This entire function is a giant hack to provide us with decent
3793// operand range validation/diagnostics until TableGen/MC can be extended
3794// to support autogeneration of this kind of validation.
Sander de Smalen9b333092018-07-30 15:42:46 +00003795bool AArch64AsmParser::validateInstruction(MCInst &Inst, SMLoc &IDLoc,
3796 SmallVectorImpl<SMLoc> &Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00003797 const MCRegisterInfo *RI = getContext().getRegisterInfo();
Sander de Smalen9b333092018-07-30 15:42:46 +00003798 const MCInstrDesc &MCID = MII.get(Inst.getOpcode());
3799
3800 // A prefix only applies to the instruction following it. Here we extract
3801 // prefix information for the next instruction before validating the current
3802 // one so that in the case of failure we don't erronously continue using the
3803 // current prefix.
3804 PrefixInfo Prefix = NextPrefix;
3805 NextPrefix = PrefixInfo::CreateFromInst(Inst, MCID.TSFlags);
3806
3807 // Before validating the instruction in isolation we run through the rules
3808 // applicable when it follows a prefix instruction.
3809 // NOTE: brk & hlt can be prefixed but require no additional validation.
3810 if (Prefix.isActive() &&
3811 (Inst.getOpcode() != AArch64::BRK) &&
3812 (Inst.getOpcode() != AArch64::HLT)) {
3813
3814 // Prefixed intructions must have a destructive operand.
3815 if ((MCID.TSFlags & AArch64::DestructiveInstTypeMask) ==
3816 AArch64::NotDestructive)
3817 return Error(IDLoc, "instruction is unpredictable when following a"
3818 " movprfx, suggest replacing movprfx with mov");
3819
3820 // Destination operands must match.
3821 if (Inst.getOperand(0).getReg() != Prefix.getDstReg())
3822 return Error(Loc[0], "instruction is unpredictable when following a"
3823 " movprfx writing to a different destination");
3824
3825 // Destination operand must not be used in any other location.
3826 for (unsigned i = 1; i < Inst.getNumOperands(); ++i) {
3827 if (Inst.getOperand(i).isReg() &&
3828 (MCID.getOperandConstraint(i, MCOI::TIED_TO) == -1) &&
3829 isMatchingOrAlias(Prefix.getDstReg(), Inst.getOperand(i).getReg()))
3830 return Error(Loc[0], "instruction is unpredictable when following a"
3831 " movprfx and destination also used as non-destructive"
3832 " source");
3833 }
3834
3835 auto PPRRegClass = AArch64MCRegisterClasses[AArch64::PPRRegClassID];
3836 if (Prefix.isPredicated()) {
3837 int PgIdx = -1;
3838
3839 // Find the instructions general predicate.
3840 for (unsigned i = 1; i < Inst.getNumOperands(); ++i)
3841 if (Inst.getOperand(i).isReg() &&
3842 PPRRegClass.contains(Inst.getOperand(i).getReg())) {
3843 PgIdx = i;
3844 break;
3845 }
3846
3847 // Instruction must be predicated if the movprfx is predicated.
3848 if (PgIdx == -1 ||
3849 (MCID.TSFlags & AArch64::ElementSizeMask) == AArch64::ElementSizeNone)
3850 return Error(IDLoc, "instruction is unpredictable when following a"
3851 " predicated movprfx, suggest using unpredicated movprfx");
3852
3853 // Instruction must use same general predicate as the movprfx.
3854 if (Inst.getOperand(PgIdx).getReg() != Prefix.getPgReg())
3855 return Error(IDLoc, "instruction is unpredictable when following a"
3856 " predicated movprfx using a different general predicate");
3857
3858 // Instruction element type must match the movprfx.
3859 if ((MCID.TSFlags & AArch64::ElementSizeMask) != Prefix.getElementSize())
3860 return Error(IDLoc, "instruction is unpredictable when following a"
3861 " predicated movprfx with a different element size");
3862 }
3863 }
3864
Tim Northover3b0846e2014-05-24 12:50:23 +00003865 // Check for indexed addressing modes w/ the base register being the
3866 // same as a destination/source register or pair load where
3867 // the Rt == Rt2. All of those are undefined behaviour.
3868 switch (Inst.getOpcode()) {
3869 case AArch64::LDPSWpre:
3870 case AArch64::LDPWpost:
3871 case AArch64::LDPWpre:
3872 case AArch64::LDPXpost:
3873 case AArch64::LDPXpre: {
3874 unsigned Rt = Inst.getOperand(1).getReg();
3875 unsigned Rt2 = Inst.getOperand(2).getReg();
3876 unsigned Rn = Inst.getOperand(3).getReg();
3877 if (RI->isSubRegisterEq(Rn, Rt))
3878 return Error(Loc[0], "unpredictable LDP instruction, writeback base "
3879 "is also a destination");
3880 if (RI->isSubRegisterEq(Rn, Rt2))
3881 return Error(Loc[1], "unpredictable LDP instruction, writeback base "
3882 "is also a destination");
Justin Bognerb03fd122016-08-17 05:10:15 +00003883 LLVM_FALLTHROUGH;
Tim Northover3b0846e2014-05-24 12:50:23 +00003884 }
3885 case AArch64::LDPDi:
3886 case AArch64::LDPQi:
3887 case AArch64::LDPSi:
3888 case AArch64::LDPSWi:
3889 case AArch64::LDPWi:
3890 case AArch64::LDPXi: {
3891 unsigned Rt = Inst.getOperand(0).getReg();
3892 unsigned Rt2 = Inst.getOperand(1).getReg();
3893 if (Rt == Rt2)
3894 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3895 break;
3896 }
3897 case AArch64::LDPDpost:
3898 case AArch64::LDPDpre:
3899 case AArch64::LDPQpost:
3900 case AArch64::LDPQpre:
3901 case AArch64::LDPSpost:
3902 case AArch64::LDPSpre:
3903 case AArch64::LDPSWpost: {
3904 unsigned Rt = Inst.getOperand(1).getReg();
3905 unsigned Rt2 = Inst.getOperand(2).getReg();
3906 if (Rt == Rt2)
3907 return Error(Loc[1], "unpredictable LDP instruction, Rt2==Rt");
3908 break;
3909 }
3910 case AArch64::STPDpost:
3911 case AArch64::STPDpre:
3912 case AArch64::STPQpost:
3913 case AArch64::STPQpre:
3914 case AArch64::STPSpost:
3915 case AArch64::STPSpre:
3916 case AArch64::STPWpost:
3917 case AArch64::STPWpre:
3918 case AArch64::STPXpost:
3919 case AArch64::STPXpre: {
3920 unsigned Rt = Inst.getOperand(1).getReg();
3921 unsigned Rt2 = Inst.getOperand(2).getReg();
3922 unsigned Rn = Inst.getOperand(3).getReg();
3923 if (RI->isSubRegisterEq(Rn, Rt))
3924 return Error(Loc[0], "unpredictable STP instruction, writeback base "
3925 "is also a source");
3926 if (RI->isSubRegisterEq(Rn, Rt2))
3927 return Error(Loc[1], "unpredictable STP instruction, writeback base "
3928 "is also a source");
3929 break;
3930 }
3931 case AArch64::LDRBBpre:
3932 case AArch64::LDRBpre:
3933 case AArch64::LDRHHpre:
3934 case AArch64::LDRHpre:
3935 case AArch64::LDRSBWpre:
3936 case AArch64::LDRSBXpre:
3937 case AArch64::LDRSHWpre:
3938 case AArch64::LDRSHXpre:
3939 case AArch64::LDRSWpre:
3940 case AArch64::LDRWpre:
3941 case AArch64::LDRXpre:
3942 case AArch64::LDRBBpost:
3943 case AArch64::LDRBpost:
3944 case AArch64::LDRHHpost:
3945 case AArch64::LDRHpost:
3946 case AArch64::LDRSBWpost:
3947 case AArch64::LDRSBXpost:
3948 case AArch64::LDRSHWpost:
3949 case AArch64::LDRSHXpost:
3950 case AArch64::LDRSWpost:
3951 case AArch64::LDRWpost:
3952 case AArch64::LDRXpost: {
3953 unsigned Rt = Inst.getOperand(1).getReg();
3954 unsigned Rn = Inst.getOperand(2).getReg();
3955 if (RI->isSubRegisterEq(Rn, Rt))
3956 return Error(Loc[0], "unpredictable LDR instruction, writeback base "
3957 "is also a source");
3958 break;
3959 }
3960 case AArch64::STRBBpost:
3961 case AArch64::STRBpost:
3962 case AArch64::STRHHpost:
3963 case AArch64::STRHpost:
3964 case AArch64::STRWpost:
3965 case AArch64::STRXpost:
3966 case AArch64::STRBBpre:
3967 case AArch64::STRBpre:
3968 case AArch64::STRHHpre:
3969 case AArch64::STRHpre:
3970 case AArch64::STRWpre:
3971 case AArch64::STRXpre: {
3972 unsigned Rt = Inst.getOperand(1).getReg();
3973 unsigned Rn = Inst.getOperand(2).getReg();
3974 if (RI->isSubRegisterEq(Rn, Rt))
3975 return Error(Loc[0], "unpredictable STR instruction, writeback base "
3976 "is also a source");
3977 break;
3978 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003979 case AArch64::STXRB:
3980 case AArch64::STXRH:
3981 case AArch64::STXRW:
3982 case AArch64::STXRX:
3983 case AArch64::STLXRB:
3984 case AArch64::STLXRH:
3985 case AArch64::STLXRW:
3986 case AArch64::STLXRX: {
3987 unsigned Rs = Inst.getOperand(0).getReg();
3988 unsigned Rt = Inst.getOperand(1).getReg();
3989 unsigned Rn = Inst.getOperand(2).getReg();
3990 if (RI->isSubRegisterEq(Rt, Rs) ||
3991 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
3992 return Error(Loc[0],
3993 "unpredictable STXR instruction, status is also a source");
3994 break;
Tim Northover3b0846e2014-05-24 12:50:23 +00003995 }
Tim Northover6a1c51b2018-04-10 11:04:29 +00003996 case AArch64::STXPW:
3997 case AArch64::STXPX:
3998 case AArch64::STLXPW:
3999 case AArch64::STLXPX: {
4000 unsigned Rs = Inst.getOperand(0).getReg();
4001 unsigned Rt1 = Inst.getOperand(1).getReg();
4002 unsigned Rt2 = Inst.getOperand(2).getReg();
4003 unsigned Rn = Inst.getOperand(3).getReg();
4004 if (RI->isSubRegisterEq(Rt1, Rs) || RI->isSubRegisterEq(Rt2, Rs) ||
4005 (RI->isSubRegisterEq(Rn, Rs) && Rn != AArch64::SP))
4006 return Error(Loc[0],
4007 "unpredictable STXP instruction, status is also a source");
4008 break;
4009 }
4010 }
4011
Tim Northover3b0846e2014-05-24 12:50:23 +00004012
4013 // Now check immediate ranges. Separate from the above as there is overlap
4014 // in the instructions being checked and this keeps the nested conditionals
4015 // to a minimum.
4016 switch (Inst.getOpcode()) {
4017 case AArch64::ADDSWri:
4018 case AArch64::ADDSXri:
4019 case AArch64::ADDWri:
4020 case AArch64::ADDXri:
4021 case AArch64::SUBSWri:
4022 case AArch64::SUBSXri:
4023 case AArch64::SUBWri:
4024 case AArch64::SUBXri: {
4025 // Annoyingly we can't do this in the isAddSubImm predicate, so there is
4026 // some slight duplication here.
4027 if (Inst.getOperand(2).isExpr()) {
4028 const MCExpr *Expr = Inst.getOperand(2).getExpr();
4029 AArch64MCExpr::VariantKind ELFRefKind;
4030 MCSymbolRefExpr::VariantKind DarwinRefKind;
4031 int64_t Addend;
Diana Picusc93518d2016-10-11 09:17:47 +00004032 if (classifySymbolRef(Expr, ELFRefKind, DarwinRefKind, Addend)) {
4033
4034 // Only allow these with ADDXri.
4035 if ((DarwinRefKind == MCSymbolRefExpr::VK_PAGEOFF ||
4036 DarwinRefKind == MCSymbolRefExpr::VK_TLVPPAGEOFF) &&
4037 Inst.getOpcode() == AArch64::ADDXri)
4038 return false;
4039
4040 // Only allow these with ADDXri/ADDWri
4041 if ((ELFRefKind == AArch64MCExpr::VK_LO12 ||
4042 ELFRefKind == AArch64MCExpr::VK_DTPREL_HI12 ||
4043 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12 ||
4044 ELFRefKind == AArch64MCExpr::VK_DTPREL_LO12_NC ||
4045 ELFRefKind == AArch64MCExpr::VK_TPREL_HI12 ||
4046 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12 ||
4047 ELFRefKind == AArch64MCExpr::VK_TPREL_LO12_NC ||
Martin Storsjoc61ff3b2018-03-01 20:42:28 +00004048 ELFRefKind == AArch64MCExpr::VK_TLSDESC_LO12 ||
4049 ELFRefKind == AArch64MCExpr::VK_SECREL_LO12 ||
4050 ELFRefKind == AArch64MCExpr::VK_SECREL_HI12) &&
Diana Picusc93518d2016-10-11 09:17:47 +00004051 (Inst.getOpcode() == AArch64::ADDXri ||
4052 Inst.getOpcode() == AArch64::ADDWri))
4053 return false;
4054
4055 // Don't allow symbol refs in the immediate field otherwise
4056 // Note: Loc.back() may be Loc[1] or Loc[2] depending on the number of
4057 // operands of the original instruction (i.e. 'add w0, w1, borked' vs
4058 // 'cmp w0, 'borked')
4059 return Error(Loc.back(), "invalid immediate expression");
Tim Northover3b0846e2014-05-24 12:50:23 +00004060 }
Diana Picusc93518d2016-10-11 09:17:47 +00004061 // We don't validate more complex expressions here
Tim Northover3b0846e2014-05-24 12:50:23 +00004062 }
4063 return false;
4064 }
4065 default:
4066 return false;
4067 }
4068}
4069
Craig Topper05515562017-10-26 06:46:41 +00004070static std::string AArch64MnemonicSpellCheck(StringRef S, uint64_t FBS,
4071 unsigned VariantID = 0);
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004072
4073bool AArch64AsmParser::showMatchError(SMLoc Loc, unsigned ErrCode,
Sander de Smalen0325e302018-07-02 07:34:52 +00004074 uint64_t ErrorInfo,
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004075 OperandVector &Operands) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004076 switch (ErrCode) {
Sander de Smalen0325e302018-07-02 07:34:52 +00004077 case Match_InvalidTiedOperand: {
4078 RegConstraintEqualityTy EqTy =
4079 static_cast<const AArch64Operand &>(*Operands[ErrorInfo])
4080 .getRegEqualityTy();
4081 switch (EqTy) {
4082 case RegConstraintEqualityTy::EqualsSubReg:
4083 return Error(Loc, "operand must be 64-bit form of destination register");
4084 case RegConstraintEqualityTy::EqualsSuperReg:
4085 return Error(Loc, "operand must be 32-bit form of destination register");
4086 case RegConstraintEqualityTy::EqualsReg:
4087 return Error(Loc, "operand must match destination register");
4088 }
Simon Pilgrim6dc45e62018-07-05 09:48:01 +00004089 llvm_unreachable("Unknown RegConstraintEqualityTy");
Sander de Smalen0325e302018-07-02 07:34:52 +00004090 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004091 case Match_MissingFeature:
4092 return Error(Loc,
4093 "instruction requires a CPU feature not currently enabled");
4094 case Match_InvalidOperand:
4095 return Error(Loc, "invalid operand for instruction");
4096 case Match_InvalidSuffix:
4097 return Error(Loc, "invalid type suffix for instruction");
4098 case Match_InvalidCondCode:
4099 return Error(Loc, "expected AArch64 condition code");
4100 case Match_AddSubRegExtendSmall:
4101 return Error(Loc,
4102 "expected '[su]xt[bhw]' or 'lsl' with optional integer in range [0, 4]");
4103 case Match_AddSubRegExtendLarge:
4104 return Error(Loc,
4105 "expected 'sxtx' 'uxtx' or 'lsl' with optional integer in range [0, 4]");
4106 case Match_AddSubSecondSource:
4107 return Error(Loc,
4108 "expected compatible register, symbol or integer in range [0, 4095]");
4109 case Match_LogicalSecondSource:
4110 return Error(Loc, "expected compatible register or logical immediate");
4111 case Match_InvalidMovImm32Shift:
4112 return Error(Loc, "expected 'lsl' with optional integer 0 or 16");
4113 case Match_InvalidMovImm64Shift:
4114 return Error(Loc, "expected 'lsl' with optional integer 0, 16, 32 or 48");
4115 case Match_AddSubRegShift32:
4116 return Error(Loc,
4117 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 31]");
4118 case Match_AddSubRegShift64:
4119 return Error(Loc,
4120 "expected 'lsl', 'lsr' or 'asr' with optional integer in range [0, 63]");
4121 case Match_InvalidFPImm:
4122 return Error(Loc,
4123 "expected compatible register or floating-point constant");
Sander de Smalen909cf952018-01-19 15:22:00 +00004124 case Match_InvalidMemoryIndexedSImm6:
4125 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen30fda452018-04-10 07:01:53 +00004126 case Match_InvalidMemoryIndexedSImm5:
4127 return Error(Loc, "index must be an integer in range [-16, 15].");
Sander de Smalen5c625982018-04-13 12:56:14 +00004128 case Match_InvalidMemoryIndexed1SImm4:
4129 return Error(Loc, "index must be an integer in range [-8, 7].");
Sander de Smalenf836af82018-04-16 07:09:29 +00004130 case Match_InvalidMemoryIndexed2SImm4:
4131 return Error(Loc, "index must be a multiple of 2 in range [-16, 14].");
Sander de Smalend239eb32018-04-16 10:10:48 +00004132 case Match_InvalidMemoryIndexed3SImm4:
4133 return Error(Loc, "index must be a multiple of 3 in range [-24, 21].");
Sander de Smalen7a210db2018-04-16 10:46:18 +00004134 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen137efb22018-04-20 09:45:50 +00004135 return Error(Loc, "index must be a multiple of 4 in range [-32, 28].");
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004136 case Match_InvalidMemoryIndexed16SImm4:
4137 return Error(Loc, "index must be a multiple of 16 in range [-128, 112].");
Sander de Smalen67f91542018-05-16 07:50:09 +00004138 case Match_InvalidMemoryIndexed1SImm6:
4139 return Error(Loc, "index must be an integer in range [-32, 31].");
Sander de Smalen592718f2018-07-05 07:54:10 +00004140 case Match_InvalidMemoryIndexedSImm8:
4141 return Error(Loc, "index must be an integer in range [-128, 127].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004142 case Match_InvalidMemoryIndexedSImm9:
4143 return Error(Loc, "index must be an integer in range [-256, 255].");
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004144 case Match_InvalidMemoryIndexed8SImm10:
Sam Parker6d42de72017-08-11 13:14:00 +00004145 return Error(Loc, "index must be a multiple of 8 in range [-4096, 4088].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004146 case Match_InvalidMemoryIndexed4SImm7:
4147 return Error(Loc, "index must be a multiple of 4 in range [-256, 252].");
4148 case Match_InvalidMemoryIndexed8SImm7:
4149 return Error(Loc, "index must be a multiple of 8 in range [-512, 504].");
4150 case Match_InvalidMemoryIndexed16SImm7:
4151 return Error(Loc, "index must be a multiple of 16 in range [-1024, 1008].");
Sander de Smalen50ded902018-04-29 17:33:38 +00004152 case Match_InvalidMemoryIndexed8UImm5:
4153 return Error(Loc, "index must be a multiple of 8 in range [0, 248].");
4154 case Match_InvalidMemoryIndexed4UImm5:
4155 return Error(Loc, "index must be a multiple of 4 in range [0, 124].");
4156 case Match_InvalidMemoryIndexed2UImm5:
4157 return Error(Loc, "index must be a multiple of 2 in range [0, 62].");
Sander de Smalend8e76492018-05-08 10:46:55 +00004158 case Match_InvalidMemoryIndexed8UImm6:
4159 return Error(Loc, "index must be a multiple of 8 in range [0, 504].");
4160 case Match_InvalidMemoryIndexed4UImm6:
4161 return Error(Loc, "index must be a multiple of 4 in range [0, 252].");
4162 case Match_InvalidMemoryIndexed2UImm6:
4163 return Error(Loc, "index must be a multiple of 2 in range [0, 126].");
4164 case Match_InvalidMemoryIndexed1UImm6:
4165 return Error(Loc, "index must be in range [0, 63].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004166 case Match_InvalidMemoryWExtend8:
4167 return Error(Loc,
4168 "expected 'uxtw' or 'sxtw' with optional shift of #0");
4169 case Match_InvalidMemoryWExtend16:
4170 return Error(Loc,
4171 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #1");
4172 case Match_InvalidMemoryWExtend32:
4173 return Error(Loc,
4174 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #2");
4175 case Match_InvalidMemoryWExtend64:
4176 return Error(Loc,
4177 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #3");
4178 case Match_InvalidMemoryWExtend128:
4179 return Error(Loc,
4180 "expected 'uxtw' or 'sxtw' with optional shift of #0 or #4");
4181 case Match_InvalidMemoryXExtend8:
4182 return Error(Loc,
4183 "expected 'lsl' or 'sxtx' with optional shift of #0");
4184 case Match_InvalidMemoryXExtend16:
4185 return Error(Loc,
4186 "expected 'lsl' or 'sxtx' with optional shift of #0 or #1");
4187 case Match_InvalidMemoryXExtend32:
4188 return Error(Loc,
4189 "expected 'lsl' or 'sxtx' with optional shift of #0 or #2");
4190 case Match_InvalidMemoryXExtend64:
4191 return Error(Loc,
4192 "expected 'lsl' or 'sxtx' with optional shift of #0 or #3");
4193 case Match_InvalidMemoryXExtend128:
4194 return Error(Loc,
4195 "expected 'lsl' or 'sxtx' with optional shift of #0 or #4");
4196 case Match_InvalidMemoryIndexed1:
4197 return Error(Loc, "index must be an integer in range [0, 4095].");
4198 case Match_InvalidMemoryIndexed2:
4199 return Error(Loc, "index must be a multiple of 2 in range [0, 8190].");
4200 case Match_InvalidMemoryIndexed4:
4201 return Error(Loc, "index must be a multiple of 4 in range [0, 16380].");
4202 case Match_InvalidMemoryIndexed8:
4203 return Error(Loc, "index must be a multiple of 8 in range [0, 32760].");
4204 case Match_InvalidMemoryIndexed16:
4205 return Error(Loc, "index must be a multiple of 16 in range [0, 65520].");
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004206 case Match_InvalidImm0_1:
4207 return Error(Loc, "immediate must be an integer in range [0, 1].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004208 case Match_InvalidImm0_7:
4209 return Error(Loc, "immediate must be an integer in range [0, 7].");
4210 case Match_InvalidImm0_15:
4211 return Error(Loc, "immediate must be an integer in range [0, 15].");
4212 case Match_InvalidImm0_31:
4213 return Error(Loc, "immediate must be an integer in range [0, 31].");
4214 case Match_InvalidImm0_63:
4215 return Error(Loc, "immediate must be an integer in range [0, 63].");
4216 case Match_InvalidImm0_127:
4217 return Error(Loc, "immediate must be an integer in range [0, 127].");
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004218 case Match_InvalidImm0_255:
4219 return Error(Loc, "immediate must be an integer in range [0, 255].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004220 case Match_InvalidImm0_65535:
4221 return Error(Loc, "immediate must be an integer in range [0, 65535].");
4222 case Match_InvalidImm1_8:
4223 return Error(Loc, "immediate must be an integer in range [1, 8].");
4224 case Match_InvalidImm1_16:
4225 return Error(Loc, "immediate must be an integer in range [1, 16].");
4226 case Match_InvalidImm1_32:
4227 return Error(Loc, "immediate must be an integer in range [1, 32].");
4228 case Match_InvalidImm1_64:
4229 return Error(Loc, "immediate must be an integer in range [1, 64].");
Sander de Smalen98686c62018-05-29 10:39:49 +00004230 case Match_InvalidSVEAddSubImm8:
4231 return Error(Loc, "immediate must be an integer in range [0, 255]"
4232 " with a shift amount of 0");
4233 case Match_InvalidSVEAddSubImm16:
4234 case Match_InvalidSVEAddSubImm32:
4235 case Match_InvalidSVEAddSubImm64:
4236 return Error(Loc, "immediate must be an integer in range [0, 255] or a "
4237 "multiple of 256 in range [256, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004238 case Match_InvalidSVECpyImm8:
4239 return Error(Loc, "immediate must be an integer in range [-128, 255]"
4240 " with a shift amount of 0");
4241 case Match_InvalidSVECpyImm16:
Sander de Smalend0a6f6a2018-06-04 07:24:23 +00004242 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4243 "multiple of 256 in range [-32768, 65280]");
Sander de Smalen62770792018-05-25 09:47:52 +00004244 case Match_InvalidSVECpyImm32:
4245 case Match_InvalidSVECpyImm64:
4246 return Error(Loc, "immediate must be an integer in range [-128, 127] or a "
4247 "multiple of 256 in range [-32768, 32512]");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004248 case Match_InvalidIndexRange1_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004249 return Error(Loc, "expected lane specifier '[1]'");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004250 case Match_InvalidIndexRange0_15:
Tim Northover3b0846e2014-05-24 12:50:23 +00004251 return Error(Loc, "vector lane must be an integer in range [0, 15].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004252 case Match_InvalidIndexRange0_7:
Tim Northover3b0846e2014-05-24 12:50:23 +00004253 return Error(Loc, "vector lane must be an integer in range [0, 7].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004254 case Match_InvalidIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004255 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004256 case Match_InvalidIndexRange0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004257 return Error(Loc, "vector lane must be an integer in range [0, 1].");
Sander de Smalenc33d6682018-06-04 06:40:55 +00004258 case Match_InvalidSVEIndexRange0_63:
4259 return Error(Loc, "vector lane must be an integer in range [0, 63].");
4260 case Match_InvalidSVEIndexRange0_31:
4261 return Error(Loc, "vector lane must be an integer in range [0, 31].");
4262 case Match_InvalidSVEIndexRange0_15:
4263 return Error(Loc, "vector lane must be an integer in range [0, 15].");
4264 case Match_InvalidSVEIndexRange0_7:
4265 return Error(Loc, "vector lane must be an integer in range [0, 7].");
4266 case Match_InvalidSVEIndexRange0_3:
4267 return Error(Loc, "vector lane must be an integer in range [0, 3].");
Tim Northover3b0846e2014-05-24 12:50:23 +00004268 case Match_InvalidLabel:
4269 return Error(Loc, "expected label or encodable integer pc offset");
4270 case Match_MRS:
4271 return Error(Loc, "expected readable system register");
4272 case Match_MSR:
4273 return Error(Loc, "expected writable system register or pstate");
Sam Parker5f934642017-08-31 09:27:04 +00004274 case Match_InvalidComplexRotationEven:
4275 return Error(Loc, "complex rotation must be 0, 90, 180 or 270.");
4276 case Match_InvalidComplexRotationOdd:
4277 return Error(Loc, "complex rotation must be 90 or 270.");
Sjoerd Meijerfe3ff692017-07-13 15:29:13 +00004278 case Match_MnemonicFail: {
4279 std::string Suggestion = AArch64MnemonicSpellCheck(
4280 ((AArch64Operand &)*Operands[0]).getToken(),
4281 ComputeAvailableFeatures(STI->getFeatureBits()));
4282 return Error(Loc, "unrecognized instruction mnemonic" + Suggestion);
4283 }
Sander de Smalen367694b2018-04-20 08:54:49 +00004284 case Match_InvalidGPR64shifted8:
4285 return Error(Loc, "register must be x0..x30 or xzr, without shift");
4286 case Match_InvalidGPR64shifted16:
4287 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #1'");
4288 case Match_InvalidGPR64shifted32:
4289 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #2'");
4290 case Match_InvalidGPR64shifted64:
4291 return Error(Loc, "register must be x0..x30 or xzr, with required shift 'lsl #3'");
4292 case Match_InvalidGPR64NoXZRshifted8:
4293 return Error(Loc, "register must be x0..x30 without shift");
4294 case Match_InvalidGPR64NoXZRshifted16:
4295 return Error(Loc, "register must be x0..x30 with required shift 'lsl #1'");
4296 case Match_InvalidGPR64NoXZRshifted32:
4297 return Error(Loc, "register must be x0..x30 with required shift 'lsl #2'");
4298 case Match_InvalidGPR64NoXZRshifted64:
4299 return Error(Loc, "register must be x0..x30 with required shift 'lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004300 case Match_InvalidZPR32UXTW8:
4301 case Match_InvalidZPR32SXTW8:
4302 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw)'");
4303 case Match_InvalidZPR32UXTW16:
4304 case Match_InvalidZPR32SXTW16:
4305 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #1'");
4306 case Match_InvalidZPR32UXTW32:
4307 case Match_InvalidZPR32SXTW32:
4308 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #2'");
4309 case Match_InvalidZPR32UXTW64:
4310 case Match_InvalidZPR32SXTW64:
4311 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, (uxtw|sxtw) #3'");
4312 case Match_InvalidZPR64UXTW8:
4313 case Match_InvalidZPR64SXTW8:
4314 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (uxtw|sxtw)'");
4315 case Match_InvalidZPR64UXTW16:
4316 case Match_InvalidZPR64SXTW16:
4317 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #1'");
4318 case Match_InvalidZPR64UXTW32:
4319 case Match_InvalidZPR64SXTW32:
4320 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #2'");
4321 case Match_InvalidZPR64UXTW64:
4322 case Match_InvalidZPR64SXTW64:
4323 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, (lsl|uxtw|sxtw) #3'");
Sander de Smalenc69944c2018-07-09 09:58:24 +00004324 case Match_InvalidZPR32LSL8:
4325 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s'");
4326 case Match_InvalidZPR32LSL16:
4327 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #1'");
4328 case Match_InvalidZPR32LSL32:
4329 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #2'");
4330 case Match_InvalidZPR32LSL64:
4331 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].s, lsl #3'");
Sander de Smaleneb896b12018-04-25 09:26:47 +00004332 case Match_InvalidZPR64LSL8:
4333 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d'");
4334 case Match_InvalidZPR64LSL16:
4335 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #1'");
4336 case Match_InvalidZPR64LSL32:
4337 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #2'");
4338 case Match_InvalidZPR64LSL64:
4339 return Error(Loc, "invalid shift/extend specified, expected 'z[0..31].d, lsl #3'");
Sander de Smalen22176a22018-05-16 15:45:17 +00004340 case Match_InvalidZPR0:
4341 return Error(Loc, "expected register without element width sufix");
4342 case Match_InvalidZPR8:
4343 case Match_InvalidZPR16:
4344 case Match_InvalidZPR32:
4345 case Match_InvalidZPR64:
4346 case Match_InvalidZPR128:
4347 return Error(Loc, "invalid element width");
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004348 case Match_InvalidZPR_3b8:
4349 return Error(Loc, "Invalid restricted vector register, expected z0.b..z7.b");
4350 case Match_InvalidZPR_3b16:
4351 return Error(Loc, "Invalid restricted vector register, expected z0.h..z7.h");
4352 case Match_InvalidZPR_3b32:
4353 return Error(Loc, "Invalid restricted vector register, expected z0.s..z7.s");
4354 case Match_InvalidZPR_4b16:
4355 return Error(Loc, "Invalid restricted vector register, expected z0.h..z15.h");
4356 case Match_InvalidZPR_4b32:
4357 return Error(Loc, "Invalid restricted vector register, expected z0.s..z15.s");
4358 case Match_InvalidZPR_4b64:
4359 return Error(Loc, "Invalid restricted vector register, expected z0.d..z15.d");
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004360 case Match_InvalidSVEPattern:
4361 return Error(Loc, "invalid predicate pattern");
Sander de Smalencd6be962017-12-20 11:02:42 +00004362 case Match_InvalidSVEPredicateAnyReg:
4363 case Match_InvalidSVEPredicateBReg:
4364 case Match_InvalidSVEPredicateHReg:
4365 case Match_InvalidSVEPredicateSReg:
4366 case Match_InvalidSVEPredicateDReg:
4367 return Error(Loc, "invalid predicate register.");
Sander de Smalendc5e0812018-01-03 10:15:46 +00004368 case Match_InvalidSVEPredicate3bAnyReg:
4369 case Match_InvalidSVEPredicate3bBReg:
4370 case Match_InvalidSVEPredicate3bHReg:
4371 case Match_InvalidSVEPredicate3bSReg:
4372 case Match_InvalidSVEPredicate3bDReg:
4373 return Error(Loc, "restricted predicate has range [0, 7].");
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004374 case Match_InvalidSVEExactFPImmOperandHalfOne:
4375 return Error(Loc, "Invalid floating point constant, expected 0.5 or 1.0.");
4376 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4377 return Error(Loc, "Invalid floating point constant, expected 0.5 or 2.0.");
4378 case Match_InvalidSVEExactFPImmOperandZeroOne:
4379 return Error(Loc, "Invalid floating point constant, expected 0.0 or 1.0.");
Tim Northover3b0846e2014-05-24 12:50:23 +00004380 default:
Craig Topper35b2f752014-06-19 06:10:58 +00004381 llvm_unreachable("unexpected error code!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004382 }
4383}
4384
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004385static const char *getSubtargetFeatureName(uint64_t Val);
Tim Northover3b0846e2014-05-24 12:50:23 +00004386
4387bool AArch64AsmParser::MatchAndEmitInstruction(SMLoc IDLoc, unsigned &Opcode,
4388 OperandVector &Operands,
4389 MCStreamer &Out,
Tim Northover26bb14e2014-08-18 11:49:42 +00004390 uint64_t &ErrorInfo,
Tim Northover3b0846e2014-05-24 12:50:23 +00004391 bool MatchingInlineAsm) {
4392 assert(!Operands.empty() && "Unexpect empty operand list!");
David Blaikie960ea3f2014-06-08 16:18:35 +00004393 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[0]);
4394 assert(Op.isToken() && "Leading operand should always be a mnemonic!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004395
David Blaikie960ea3f2014-06-08 16:18:35 +00004396 StringRef Tok = Op.getToken();
Tim Northover3b0846e2014-05-24 12:50:23 +00004397 unsigned NumOperands = Operands.size();
4398
4399 if (NumOperands == 4 && Tok == "lsl") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004400 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4401 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004402 if (Op2.isScalarReg() && Op3.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004403 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004404 if (Op3CE) {
4405 uint64_t Op3Val = Op3CE->getValue();
4406 uint64_t NewOp3Val = 0;
4407 uint64_t NewOp4Val = 0;
4408 if (AArch64MCRegisterClasses[AArch64::GPR32allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004409 Op2.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004410 NewOp3Val = (32 - Op3Val) & 0x1f;
4411 NewOp4Val = 31 - Op3Val;
4412 } else {
4413 NewOp3Val = (64 - Op3Val) & 0x3f;
4414 NewOp4Val = 63 - Op3Val;
4415 }
4416
Jim Grosbach13760bd2015-05-30 01:25:56 +00004417 const MCExpr *NewOp3 = MCConstantExpr::create(NewOp3Val, getContext());
4418 const MCExpr *NewOp4 = MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004419
4420 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004421 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004422 Operands.push_back(AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004423 NewOp4, Op3.getStartLoc(), Op3.getEndLoc(), getContext()));
4424 Operands[3] = AArch64Operand::CreateImm(NewOp3, Op3.getStartLoc(),
4425 Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004426 }
4427 }
Tim Northover03b99f62015-04-30 18:28:58 +00004428 } else if (NumOperands == 4 && Tok == "bfc") {
4429 // FIXME: Horrible hack to handle BFC->BFM alias.
4430 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4431 AArch64Operand LSBOp = static_cast<AArch64Operand &>(*Operands[2]);
4432 AArch64Operand WidthOp = static_cast<AArch64Operand &>(*Operands[3]);
4433
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004434 if (Op1.isScalarReg() && LSBOp.isImm() && WidthOp.isImm()) {
Tim Northover03b99f62015-04-30 18:28:58 +00004435 const MCConstantExpr *LSBCE = dyn_cast<MCConstantExpr>(LSBOp.getImm());
4436 const MCConstantExpr *WidthCE = dyn_cast<MCConstantExpr>(WidthOp.getImm());
4437
4438 if (LSBCE && WidthCE) {
4439 uint64_t LSB = LSBCE->getValue();
4440 uint64_t Width = WidthCE->getValue();
4441
4442 uint64_t RegWidth = 0;
4443 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
4444 Op1.getReg()))
4445 RegWidth = 64;
4446 else
4447 RegWidth = 32;
4448
4449 if (LSB >= RegWidth)
4450 return Error(LSBOp.getStartLoc(),
4451 "expected integer in range [0, 31]");
4452 if (Width < 1 || Width > RegWidth)
4453 return Error(WidthOp.getStartLoc(),
4454 "expected integer in range [1, 32]");
4455
4456 uint64_t ImmR = 0;
4457 if (RegWidth == 32)
4458 ImmR = (32 - LSB) & 0x1f;
4459 else
4460 ImmR = (64 - LSB) & 0x3f;
4461
4462 uint64_t ImmS = Width - 1;
4463
4464 if (ImmR != 0 && ImmS >= ImmR)
4465 return Error(WidthOp.getStartLoc(),
4466 "requested insert overflows register");
4467
Jim Grosbach13760bd2015-05-30 01:25:56 +00004468 const MCExpr *ImmRExpr = MCConstantExpr::create(ImmR, getContext());
4469 const MCExpr *ImmSExpr = MCConstantExpr::create(ImmS, getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004470 Operands[0] = AArch64Operand::CreateToken(
4471 "bfm", false, Op.getStartLoc(), getContext());
4472 Operands[2] = AArch64Operand::CreateReg(
Florian Hahnc4422242017-11-07 13:07:50 +00004473 RegWidth == 32 ? AArch64::WZR : AArch64::XZR, RegKind::Scalar,
4474 SMLoc(), SMLoc(), getContext());
Tim Northover03b99f62015-04-30 18:28:58 +00004475 Operands[3] = AArch64Operand::CreateImm(
4476 ImmRExpr, LSBOp.getStartLoc(), LSBOp.getEndLoc(), getContext());
4477 Operands.emplace_back(
4478 AArch64Operand::CreateImm(ImmSExpr, WidthOp.getStartLoc(),
4479 WidthOp.getEndLoc(), getContext()));
4480 }
4481 }
Tim Northover3b0846e2014-05-24 12:50:23 +00004482 } else if (NumOperands == 5) {
4483 // FIXME: Horrible hack to handle the BFI -> BFM, SBFIZ->SBFM, and
4484 // UBFIZ -> UBFM aliases.
4485 if (Tok == "bfi" || Tok == "sbfiz" || Tok == "ubfiz") {
David Blaikie960ea3f2014-06-08 16:18:35 +00004486 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4487 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4488 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004489
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004490 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004491 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4492 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004493
4494 if (Op3CE && Op4CE) {
4495 uint64_t Op3Val = Op3CE->getValue();
4496 uint64_t Op4Val = Op4CE->getValue();
4497
4498 uint64_t RegWidth = 0;
4499 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004500 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004501 RegWidth = 64;
4502 else
4503 RegWidth = 32;
4504
4505 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004506 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004507 "expected integer in range [0, 31]");
4508 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004509 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004510 "expected integer in range [1, 32]");
4511
4512 uint64_t NewOp3Val = 0;
Tim Northover03b99f62015-04-30 18:28:58 +00004513 if (RegWidth == 32)
Tim Northover3b0846e2014-05-24 12:50:23 +00004514 NewOp3Val = (32 - Op3Val) & 0x1f;
4515 else
4516 NewOp3Val = (64 - Op3Val) & 0x3f;
4517
4518 uint64_t NewOp4Val = Op4Val - 1;
4519
4520 if (NewOp3Val != 0 && NewOp4Val >= NewOp3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004521 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004522 "requested insert overflows register");
4523
4524 const MCExpr *NewOp3 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004525 MCConstantExpr::create(NewOp3Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004526 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004527 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004528 Operands[3] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004529 NewOp3, Op3.getStartLoc(), Op3.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004530 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004531 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004532 if (Tok == "bfi")
4533 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004534 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004535 else if (Tok == "sbfiz")
4536 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004537 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004538 else if (Tok == "ubfiz")
4539 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004540 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004541 else
4542 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004543 }
4544 }
4545
4546 // FIXME: Horrible hack to handle the BFXIL->BFM, SBFX->SBFM, and
4547 // UBFX -> UBFM aliases.
4548 } else if (NumOperands == 5 &&
4549 (Tok == "bfxil" || Tok == "sbfx" || Tok == "ubfx")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004550 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4551 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4552 AArch64Operand &Op4 = static_cast<AArch64Operand &>(*Operands[4]);
Tim Northover3b0846e2014-05-24 12:50:23 +00004553
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004554 if (Op1.isScalarReg() && Op3.isImm() && Op4.isImm()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004555 const MCConstantExpr *Op3CE = dyn_cast<MCConstantExpr>(Op3.getImm());
4556 const MCConstantExpr *Op4CE = dyn_cast<MCConstantExpr>(Op4.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00004557
4558 if (Op3CE && Op4CE) {
4559 uint64_t Op3Val = Op3CE->getValue();
4560 uint64_t Op4Val = Op4CE->getValue();
4561
4562 uint64_t RegWidth = 0;
4563 if (AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004564 Op1.getReg()))
Tim Northover3b0846e2014-05-24 12:50:23 +00004565 RegWidth = 64;
4566 else
4567 RegWidth = 32;
4568
4569 if (Op3Val >= RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004570 return Error(Op3.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004571 "expected integer in range [0, 31]");
4572 if (Op4Val < 1 || Op4Val > RegWidth)
David Blaikie960ea3f2014-06-08 16:18:35 +00004573 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004574 "expected integer in range [1, 32]");
4575
4576 uint64_t NewOp4Val = Op3Val + Op4Val - 1;
4577
4578 if (NewOp4Val >= RegWidth || NewOp4Val < Op3Val)
David Blaikie960ea3f2014-06-08 16:18:35 +00004579 return Error(Op4.getStartLoc(),
Tim Northover3b0846e2014-05-24 12:50:23 +00004580 "requested extract overflows register");
4581
4582 const MCExpr *NewOp4 =
Jim Grosbach13760bd2015-05-30 01:25:56 +00004583 MCConstantExpr::create(NewOp4Val, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004584 Operands[4] = AArch64Operand::CreateImm(
David Blaikie960ea3f2014-06-08 16:18:35 +00004585 NewOp4, Op4.getStartLoc(), Op4.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004586 if (Tok == "bfxil")
4587 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004588 "bfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004589 else if (Tok == "sbfx")
4590 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004591 "sbfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004592 else if (Tok == "ubfx")
4593 Operands[0] = AArch64Operand::CreateToken(
David Blaikie960ea3f2014-06-08 16:18:35 +00004594 "ubfm", false, Op.getStartLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004595 else
4596 llvm_unreachable("No valid mnemonic for alias?");
Tim Northover3b0846e2014-05-24 12:50:23 +00004597 }
4598 }
4599 }
4600 }
Tim Northover9097a072017-12-18 10:36:00 +00004601
4602 // The Cyclone CPU and early successors didn't execute the zero-cycle zeroing
4603 // instruction for FP registers correctly in some rare circumstances. Convert
4604 // it to a safe instruction and warn (because silently changing someone's
4605 // assembly is rude).
4606 if (getSTI().getFeatureBits()[AArch64::FeatureZCZeroingFPWorkaround] &&
4607 NumOperands == 4 && Tok == "movi") {
4608 AArch64Operand &Op1 = static_cast<AArch64Operand &>(*Operands[1]);
4609 AArch64Operand &Op2 = static_cast<AArch64Operand &>(*Operands[2]);
4610 AArch64Operand &Op3 = static_cast<AArch64Operand &>(*Operands[3]);
4611 if ((Op1.isToken() && Op2.isNeonVectorReg() && Op3.isImm()) ||
4612 (Op1.isNeonVectorReg() && Op2.isToken() && Op3.isImm())) {
4613 StringRef Suffix = Op1.isToken() ? Op1.getToken() : Op2.getToken();
4614 if (Suffix.lower() == ".2d" &&
4615 cast<MCConstantExpr>(Op3.getImm())->getValue() == 0) {
4616 Warning(IDLoc, "instruction movi.2d with immediate #0 may not function"
4617 " correctly on this CPU, converting to equivalent movi.16b");
4618 // Switch the suffix to .16b.
4619 unsigned Idx = Op1.isToken() ? 1 : 2;
4620 Operands[Idx] = AArch64Operand::CreateToken(".16b", false, IDLoc,
4621 getContext());
4622 }
4623 }
4624 }
4625
Tim Northover3b0846e2014-05-24 12:50:23 +00004626 // FIXME: Horrible hack for sxtw and uxtw with Wn src and Xd dst operands.
4627 // InstAlias can't quite handle this since the reg classes aren't
4628 // subclasses.
4629 if (NumOperands == 3 && (Tok == "sxtw" || Tok == "uxtw")) {
4630 // The source register can be Wn here, but the matcher expects a
4631 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004632 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004633 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004634 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004635 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4636 Op.getStartLoc(), Op.getEndLoc(),
4637 getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004638 }
4639 }
4640 // FIXME: Likewise for sxt[bh] with a Xd dst operand
4641 else if (NumOperands == 3 && (Tok == "sxtb" || Tok == "sxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004642 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004643 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004644 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004645 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004646 // The source register can be Wn here, but the matcher expects a
4647 // GPR64. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004648 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[2]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004649 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004650 unsigned Reg = getXRegFromWReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004651 Operands[2] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4652 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004653 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004654 }
4655 }
4656 }
4657 // FIXME: Likewise for uxt[bh] with a Xd dst operand
4658 else if (NumOperands == 3 && (Tok == "uxtb" || Tok == "uxth")) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004659 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004660 if (Op.isScalarReg() &&
Tim Northover3b0846e2014-05-24 12:50:23 +00004661 AArch64MCRegisterClasses[AArch64::GPR64allRegClassID].contains(
David Blaikie960ea3f2014-06-08 16:18:35 +00004662 Op.getReg())) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004663 // The source register can be Wn here, but the matcher expects a
4664 // GPR32. Twiddle it here if necessary.
David Blaikie960ea3f2014-06-08 16:18:35 +00004665 AArch64Operand &Op = static_cast<AArch64Operand &>(*Operands[1]);
Sander de Smalenc9b3e1c2018-01-02 13:39:44 +00004666 if (Op.isScalarReg()) {
David Blaikie960ea3f2014-06-08 16:18:35 +00004667 unsigned Reg = getWRegFromXReg(Op.getReg());
Florian Hahnc4422242017-11-07 13:07:50 +00004668 Operands[1] = AArch64Operand::CreateReg(Reg, RegKind::Scalar,
4669 Op.getStartLoc(),
David Blaikie960ea3f2014-06-08 16:18:35 +00004670 Op.getEndLoc(), getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00004671 }
4672 }
4673 }
4674
Tim Northover3b0846e2014-05-24 12:50:23 +00004675 MCInst Inst;
4676 // First try to match against the secondary set of tables containing the
4677 // short-form NEON instructions (e.g. "fadd.2s v0, v1, v2").
4678 unsigned MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004679 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 1);
Tim Northover3b0846e2014-05-24 12:50:23 +00004680
4681 // If that fails, try against the alternate table containing long-form NEON:
4682 // "fadd v0.2s, v1.2s, v2.2s"
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004683 if (MatchResult != Match_Success) {
4684 // But first, save the short-form match result: we can use it in case the
4685 // long-form match also fails.
4686 auto ShortFormNEONErrorInfo = ErrorInfo;
4687 auto ShortFormNEONMatchResult = MatchResult;
4688
Tim Northover3b0846e2014-05-24 12:50:23 +00004689 MatchResult =
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004690 MatchInstructionImpl(Operands, Inst, ErrorInfo, MatchingInlineAsm, 0);
Tim Northover3b0846e2014-05-24 12:50:23 +00004691
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004692 // Now, both matches failed, and the long-form match failed on the mnemonic
4693 // suffix token operand. The short-form match failure is probably more
4694 // relevant: use it instead.
4695 if (MatchResult == Match_InvalidOperand && ErrorInfo == 1 &&
Akira Hatanaka5a4e4f82015-10-13 18:55:34 +00004696 Operands.size() > 1 && ((AArch64Operand &)*Operands[1]).isToken() &&
Ahmed Bougacha9e00ec62015-08-19 17:40:19 +00004697 ((AArch64Operand &)*Operands[1]).isTokenSuffix()) {
4698 MatchResult = ShortFormNEONMatchResult;
4699 ErrorInfo = ShortFormNEONErrorInfo;
4700 }
4701 }
4702
Tim Northover3b0846e2014-05-24 12:50:23 +00004703 switch (MatchResult) {
4704 case Match_Success: {
4705 // Perform range checking and other semantic validations
4706 SmallVector<SMLoc, 8> OperandLocs;
4707 NumOperands = Operands.size();
4708 for (unsigned i = 1; i < NumOperands; ++i)
4709 OperandLocs.push_back(Operands[i]->getStartLoc());
Sander de Smalen9b333092018-07-30 15:42:46 +00004710 if (validateInstruction(Inst, IDLoc, OperandLocs))
Tim Northover3b0846e2014-05-24 12:50:23 +00004711 return true;
4712
4713 Inst.setLoc(IDLoc);
Akira Hatanakabd9fc282015-11-14 05:20:05 +00004714 Out.EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00004715 return false;
4716 }
4717 case Match_MissingFeature: {
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004718 assert(ErrorInfo && "Unknown missing feature!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004719 // Special case the error message for the very common case where only
4720 // a single subtarget feature is missing (neon, e.g.).
4721 std::string Msg = "instruction requires:";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004722 uint64_t Mask = 1;
4723 for (unsigned i = 0; i < (sizeof(ErrorInfo)*8-1); ++i) {
4724 if (ErrorInfo & Mask) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004725 Msg += " ";
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004726 Msg += getSubtargetFeatureName(ErrorInfo & Mask);
Tim Northover3b0846e2014-05-24 12:50:23 +00004727 }
Ranjeet Singh86ecbb72015-06-30 12:32:53 +00004728 Mask <<= 1;
Tim Northover3b0846e2014-05-24 12:50:23 +00004729 }
4730 return Error(IDLoc, Msg);
4731 }
4732 case Match_MnemonicFail:
Sander de Smalen0325e302018-07-02 07:34:52 +00004733 return showMatchError(IDLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004734 case Match_InvalidOperand: {
4735 SMLoc ErrorLoc = IDLoc;
Ahmed Bougacha80e4ac82015-08-13 21:09:13 +00004736
Tim Northover26bb14e2014-08-18 11:49:42 +00004737 if (ErrorInfo != ~0ULL) {
Tim Northover3b0846e2014-05-24 12:50:23 +00004738 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004739 return Error(IDLoc, "too few operands for instruction",
4740 SMRange(IDLoc, getTok().getLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004741
David Blaikie960ea3f2014-06-08 16:18:35 +00004742 ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004743 if (ErrorLoc == SMLoc())
4744 ErrorLoc = IDLoc;
4745 }
4746 // If the match failed on a suffix token operand, tweak the diagnostic
4747 // accordingly.
David Blaikie960ea3f2014-06-08 16:18:35 +00004748 if (((AArch64Operand &)*Operands[ErrorInfo]).isToken() &&
4749 ((AArch64Operand &)*Operands[ErrorInfo]).isTokenSuffix())
Tim Northover3b0846e2014-05-24 12:50:23 +00004750 MatchResult = Match_InvalidSuffix;
4751
Sander de Smalen0325e302018-07-02 07:34:52 +00004752 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004753 }
Sander de Smalen886510f2018-01-10 10:10:56 +00004754 case Match_InvalidTiedOperand:
Tim Northover3b0846e2014-05-24 12:50:23 +00004755 case Match_InvalidMemoryIndexed1:
4756 case Match_InvalidMemoryIndexed2:
4757 case Match_InvalidMemoryIndexed4:
4758 case Match_InvalidMemoryIndexed8:
4759 case Match_InvalidMemoryIndexed16:
4760 case Match_InvalidCondCode:
4761 case Match_AddSubRegExtendSmall:
4762 case Match_AddSubRegExtendLarge:
4763 case Match_AddSubSecondSource:
4764 case Match_LogicalSecondSource:
4765 case Match_AddSubRegShift32:
4766 case Match_AddSubRegShift64:
4767 case Match_InvalidMovImm32Shift:
4768 case Match_InvalidMovImm64Shift:
4769 case Match_InvalidFPImm:
4770 case Match_InvalidMemoryWExtend8:
4771 case Match_InvalidMemoryWExtend16:
4772 case Match_InvalidMemoryWExtend32:
4773 case Match_InvalidMemoryWExtend64:
4774 case Match_InvalidMemoryWExtend128:
4775 case Match_InvalidMemoryXExtend8:
4776 case Match_InvalidMemoryXExtend16:
4777 case Match_InvalidMemoryXExtend32:
4778 case Match_InvalidMemoryXExtend64:
4779 case Match_InvalidMemoryXExtend128:
Sander de Smalen5c625982018-04-13 12:56:14 +00004780 case Match_InvalidMemoryIndexed1SImm4:
Sander de Smalenf836af82018-04-16 07:09:29 +00004781 case Match_InvalidMemoryIndexed2SImm4:
Sander de Smalend239eb32018-04-16 10:10:48 +00004782 case Match_InvalidMemoryIndexed3SImm4:
Sander de Smalen7a210db2018-04-16 10:46:18 +00004783 case Match_InvalidMemoryIndexed4SImm4:
Sander de Smalen67f91542018-05-16 07:50:09 +00004784 case Match_InvalidMemoryIndexed1SImm6:
Sander de Smalenc1e44bd2018-05-02 08:49:08 +00004785 case Match_InvalidMemoryIndexed16SImm4:
Tim Northover3b0846e2014-05-24 12:50:23 +00004786 case Match_InvalidMemoryIndexed4SImm7:
4787 case Match_InvalidMemoryIndexed8SImm7:
4788 case Match_InvalidMemoryIndexed16SImm7:
Sander de Smalen50ded902018-04-29 17:33:38 +00004789 case Match_InvalidMemoryIndexed8UImm5:
4790 case Match_InvalidMemoryIndexed4UImm5:
4791 case Match_InvalidMemoryIndexed2UImm5:
Sander de Smalend8e76492018-05-08 10:46:55 +00004792 case Match_InvalidMemoryIndexed1UImm6:
4793 case Match_InvalidMemoryIndexed2UImm6:
4794 case Match_InvalidMemoryIndexed4UImm6:
4795 case Match_InvalidMemoryIndexed8UImm6:
Sander de Smalen5c625982018-04-13 12:56:14 +00004796 case Match_InvalidMemoryIndexedSImm6:
Sander de Smalen30fda452018-04-10 07:01:53 +00004797 case Match_InvalidMemoryIndexedSImm5:
Sander de Smalen592718f2018-07-05 07:54:10 +00004798 case Match_InvalidMemoryIndexedSImm8:
Tim Northover3b0846e2014-05-24 12:50:23 +00004799 case Match_InvalidMemoryIndexedSImm9:
Sander de Smalenafe1ee22018-04-29 18:18:21 +00004800 case Match_InvalidMemoryIndexed8SImm10:
Alexandros Lamprineas1bab1912015-10-05 13:42:31 +00004801 case Match_InvalidImm0_1:
Tim Northover3b0846e2014-05-24 12:50:23 +00004802 case Match_InvalidImm0_7:
4803 case Match_InvalidImm0_15:
4804 case Match_InvalidImm0_31:
4805 case Match_InvalidImm0_63:
4806 case Match_InvalidImm0_127:
Sjoerd Meijercb2d9502017-02-16 15:52:22 +00004807 case Match_InvalidImm0_255:
Tim Northover3b0846e2014-05-24 12:50:23 +00004808 case Match_InvalidImm0_65535:
4809 case Match_InvalidImm1_8:
4810 case Match_InvalidImm1_16:
4811 case Match_InvalidImm1_32:
4812 case Match_InvalidImm1_64:
Sander de Smalen98686c62018-05-29 10:39:49 +00004813 case Match_InvalidSVEAddSubImm8:
4814 case Match_InvalidSVEAddSubImm16:
4815 case Match_InvalidSVEAddSubImm32:
4816 case Match_InvalidSVEAddSubImm64:
Sander de Smalen62770792018-05-25 09:47:52 +00004817 case Match_InvalidSVECpyImm8:
4818 case Match_InvalidSVECpyImm16:
4819 case Match_InvalidSVECpyImm32:
4820 case Match_InvalidSVECpyImm64:
Sander de Smalenc33d6682018-06-04 06:40:55 +00004821 case Match_InvalidIndexRange1_1:
4822 case Match_InvalidIndexRange0_15:
4823 case Match_InvalidIndexRange0_7:
4824 case Match_InvalidIndexRange0_3:
4825 case Match_InvalidIndexRange0_1:
4826 case Match_InvalidSVEIndexRange0_63:
4827 case Match_InvalidSVEIndexRange0_31:
4828 case Match_InvalidSVEIndexRange0_15:
4829 case Match_InvalidSVEIndexRange0_7:
4830 case Match_InvalidSVEIndexRange0_3:
Tim Northover3b0846e2014-05-24 12:50:23 +00004831 case Match_InvalidLabel:
Sam Parker5f934642017-08-31 09:27:04 +00004832 case Match_InvalidComplexRotationEven:
4833 case Match_InvalidComplexRotationOdd:
Sander de Smalen367694b2018-04-20 08:54:49 +00004834 case Match_InvalidGPR64shifted8:
4835 case Match_InvalidGPR64shifted16:
4836 case Match_InvalidGPR64shifted32:
4837 case Match_InvalidGPR64shifted64:
4838 case Match_InvalidGPR64NoXZRshifted8:
4839 case Match_InvalidGPR64NoXZRshifted16:
4840 case Match_InvalidGPR64NoXZRshifted32:
4841 case Match_InvalidGPR64NoXZRshifted64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004842 case Match_InvalidZPR32UXTW8:
4843 case Match_InvalidZPR32UXTW16:
4844 case Match_InvalidZPR32UXTW32:
4845 case Match_InvalidZPR32UXTW64:
4846 case Match_InvalidZPR32SXTW8:
4847 case Match_InvalidZPR32SXTW16:
4848 case Match_InvalidZPR32SXTW32:
4849 case Match_InvalidZPR32SXTW64:
4850 case Match_InvalidZPR64UXTW8:
4851 case Match_InvalidZPR64SXTW8:
4852 case Match_InvalidZPR64UXTW16:
4853 case Match_InvalidZPR64SXTW16:
4854 case Match_InvalidZPR64UXTW32:
4855 case Match_InvalidZPR64SXTW32:
4856 case Match_InvalidZPR64UXTW64:
4857 case Match_InvalidZPR64SXTW64:
Sander de Smalenc69944c2018-07-09 09:58:24 +00004858 case Match_InvalidZPR32LSL8:
4859 case Match_InvalidZPR32LSL16:
4860 case Match_InvalidZPR32LSL32:
4861 case Match_InvalidZPR32LSL64:
Sander de Smaleneb896b12018-04-25 09:26:47 +00004862 case Match_InvalidZPR64LSL8:
4863 case Match_InvalidZPR64LSL16:
4864 case Match_InvalidZPR64LSL32:
4865 case Match_InvalidZPR64LSL64:
Sander de Smalen22176a22018-05-16 15:45:17 +00004866 case Match_InvalidZPR0:
4867 case Match_InvalidZPR8:
4868 case Match_InvalidZPR16:
4869 case Match_InvalidZPR32:
4870 case Match_InvalidZPR64:
4871 case Match_InvalidZPR128:
Sander de Smalen8cd1f532018-07-03 15:31:04 +00004872 case Match_InvalidZPR_3b8:
4873 case Match_InvalidZPR_3b16:
4874 case Match_InvalidZPR_3b32:
4875 case Match_InvalidZPR_4b16:
4876 case Match_InvalidZPR_4b32:
4877 case Match_InvalidZPR_4b64:
Sander de Smalencd6be962017-12-20 11:02:42 +00004878 case Match_InvalidSVEPredicateAnyReg:
Sander de Smalen7ab96f52018-01-22 15:29:19 +00004879 case Match_InvalidSVEPattern:
Sander de Smalencd6be962017-12-20 11:02:42 +00004880 case Match_InvalidSVEPredicateBReg:
4881 case Match_InvalidSVEPredicateHReg:
4882 case Match_InvalidSVEPredicateSReg:
4883 case Match_InvalidSVEPredicateDReg:
Sander de Smalendc5e0812018-01-03 10:15:46 +00004884 case Match_InvalidSVEPredicate3bAnyReg:
4885 case Match_InvalidSVEPredicate3bBReg:
4886 case Match_InvalidSVEPredicate3bHReg:
4887 case Match_InvalidSVEPredicate3bSReg:
4888 case Match_InvalidSVEPredicate3bDReg:
Sander de Smalen5eb51d72018-06-15 13:57:51 +00004889 case Match_InvalidSVEExactFPImmOperandHalfOne:
4890 case Match_InvalidSVEExactFPImmOperandHalfTwo:
4891 case Match_InvalidSVEExactFPImmOperandZeroOne:
Tim Northover3b0846e2014-05-24 12:50:23 +00004892 case Match_MSR:
4893 case Match_MRS: {
Artyom Skrobov7e9e31e2014-05-29 11:26:15 +00004894 if (ErrorInfo >= Operands.size())
Nirav Davee833c6c2016-11-08 18:31:04 +00004895 return Error(IDLoc, "too few operands for instruction", SMRange(IDLoc, (*Operands.back()).getEndLoc()));
Tim Northover3b0846e2014-05-24 12:50:23 +00004896 // Any time we get here, there's nothing fancy to do. Just get the
4897 // operand SMLoc and display the diagnostic.
David Blaikie960ea3f2014-06-08 16:18:35 +00004898 SMLoc ErrorLoc = ((AArch64Operand &)*Operands[ErrorInfo]).getStartLoc();
Tim Northover3b0846e2014-05-24 12:50:23 +00004899 if (ErrorLoc == SMLoc())
4900 ErrorLoc = IDLoc;
Sander de Smalen0325e302018-07-02 07:34:52 +00004901 return showMatchError(ErrorLoc, MatchResult, ErrorInfo, Operands);
Tim Northover3b0846e2014-05-24 12:50:23 +00004902 }
4903 }
4904
4905 llvm_unreachable("Implement any new match types added!");
Tim Northover3b0846e2014-05-24 12:50:23 +00004906}
4907
4908/// ParseDirective parses the arm specific directives
4909bool AArch64AsmParser::ParseDirective(AsmToken DirectiveID) {
Rafael Espindoladbaf0492015-08-14 15:48:41 +00004910 const MCObjectFileInfo::Environment Format =
4911 getContext().getObjectFileInfo()->getObjectFileType();
4912 bool IsMachO = Format == MCObjectFileInfo::IsMachO;
Chad Rosierdcd2a302014-10-22 20:35:57 +00004913
Tim Northover3b0846e2014-05-24 12:50:23 +00004914 StringRef IDVal = DirectiveID.getIdentifier();
4915 SMLoc Loc = DirectiveID.getLoc();
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004916 if (IDVal == ".arch")
Nirav Davee833c6c2016-11-08 18:31:04 +00004917 parseDirectiveArch(Loc);
4918 else if (IDVal == ".cpu")
4919 parseDirectiveCPU(Loc);
Nirav Davee833c6c2016-11-08 18:31:04 +00004920 else if (IDVal == ".tlsdesccall")
4921 parseDirectiveTLSDescCall(Loc);
4922 else if (IDVal == ".ltorg" || IDVal == ".pool")
4923 parseDirectiveLtorg(Loc);
4924 else if (IDVal == ".unreq")
4925 parseDirectiveUnreq(Loc);
Martin Storsjo3e3d39d2018-07-31 09:26:52 +00004926 else if (IDVal == ".inst")
4927 parseDirectiveInst(Loc);
Martin Storsjod4590c32018-08-01 06:50:18 +00004928 else if (IsMachO) {
4929 if (IDVal == MCLOHDirectiveName())
4930 parseDirectiveLOH(IDVal, Loc);
4931 else
4932 return true;
4933 } else
Nirav Davee833c6c2016-11-08 18:31:04 +00004934 return true;
4935 return false;
Tim Northover3b0846e2014-05-24 12:50:23 +00004936}
4937
Sjoerd Meijerdc198342018-07-26 07:13:59 +00004938static void ExpandCryptoAEK(AArch64::ArchKind ArchKind,
4939 SmallVector<StringRef, 4> &RequestedExtensions) {
4940 const bool NoCrypto =
4941 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
4942 "nocrypto") != std::end(RequestedExtensions));
4943 const bool Crypto =
4944 (std::find(RequestedExtensions.begin(), RequestedExtensions.end(),
4945 "crypto") != std::end(RequestedExtensions));
4946
4947 if (!NoCrypto && Crypto) {
4948 switch (ArchKind) {
4949 default:
4950 // Map 'generic' (and others) to sha2 and aes, because
4951 // that was the traditional meaning of crypto.
4952 case AArch64::ArchKind::ARMV8_1A:
4953 case AArch64::ArchKind::ARMV8_2A:
4954 case AArch64::ArchKind::ARMV8_3A:
4955 RequestedExtensions.push_back("sha2");
4956 RequestedExtensions.push_back("aes");
4957 break;
4958 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00004959 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00004960 RequestedExtensions.push_back("sm4");
4961 RequestedExtensions.push_back("sha3");
4962 RequestedExtensions.push_back("sha2");
4963 RequestedExtensions.push_back("aes");
4964 break;
4965 }
4966 } else if (NoCrypto) {
4967 switch (ArchKind) {
4968 default:
4969 // Map 'generic' (and others) to sha2 and aes, because
4970 // that was the traditional meaning of crypto.
4971 case AArch64::ArchKind::ARMV8_1A:
4972 case AArch64::ArchKind::ARMV8_2A:
4973 case AArch64::ArchKind::ARMV8_3A:
4974 RequestedExtensions.push_back("nosha2");
4975 RequestedExtensions.push_back("noaes");
4976 break;
4977 case AArch64::ArchKind::ARMV8_4A:
Oliver Stannard7c3c4ba2018-09-26 12:48:21 +00004978 case AArch64::ArchKind::ARMV8_5A:
Sjoerd Meijerdc198342018-07-26 07:13:59 +00004979 RequestedExtensions.push_back("nosm4");
4980 RequestedExtensions.push_back("nosha3");
4981 RequestedExtensions.push_back("nosha2");
4982 RequestedExtensions.push_back("noaes");
4983 break;
4984 }
4985 }
4986}
4987
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00004988/// parseDirectiveArch
4989/// ::= .arch token
4990bool AArch64AsmParser::parseDirectiveArch(SMLoc L) {
4991 SMLoc ArchLoc = getLoc();
4992
4993 StringRef Arch, ExtensionString;
4994 std::tie(Arch, ExtensionString) =
4995 getParser().parseStringToEndOfStatement().trim().split('+');
4996
Florian Hahn67ddd1d2017-07-27 16:27:56 +00004997 AArch64::ArchKind ID = AArch64::parseArch(Arch);
4998 if (ID == AArch64::ArchKind::INVALID)
Nirav Davee833c6c2016-11-08 18:31:04 +00004999 return Error(ArchLoc, "unknown arch name");
5000
5001 if (parseToken(AsmToken::EndOfStatement))
5002 return true;
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005003
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005004 // Get the architecture and extension features.
Mehdi Aminia0016ec2016-10-07 08:37:29 +00005005 std::vector<StringRef> AArch64Features;
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005006 AArch64::getArchFeatures(ID, AArch64Features);
5007 AArch64::getExtensionFeatures(AArch64::getDefaultExtensions("generic", ID),
5008 AArch64Features);
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005009
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005010 MCSubtargetInfo &STI = copySTI();
5011 std::vector<std::string> ArchFeatures(AArch64Features.begin(), AArch64Features.end());
5012 STI.setDefaultFeatures("generic", join(ArchFeatures.begin(), ArchFeatures.end(), ","));
5013
5014 SmallVector<StringRef, 4> RequestedExtensions;
5015 if (!ExtensionString.empty())
5016 ExtensionString.split(RequestedExtensions, '+');
5017
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005018 ExpandCryptoAEK(ID, RequestedExtensions);
5019
Eric Christopher98ddbdb2016-09-08 17:27:03 +00005020 FeatureBitset Features = STI.getFeatureBits();
5021 for (auto Name : RequestedExtensions) {
5022 bool EnableFeature = true;
5023
5024 if (Name.startswith_lower("no")) {
5025 EnableFeature = false;
5026 Name = Name.substr(2);
5027 }
5028
5029 for (const auto &Extension : ExtensionMap) {
5030 if (Extension.Name != Name)
5031 continue;
5032
5033 if (Extension.Features.none())
5034 report_fatal_error("unsupported architectural extension: " + Name);
5035
5036 FeatureBitset ToggleFeatures = EnableFeature
5037 ? (~Features & Extension.Features)
5038 : ( Features & Extension.Features);
5039 uint64_t Features =
5040 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5041 setAvailableFeatures(Features);
5042 break;
5043 }
5044 }
Saleem Abdulrasool6c19ffc2016-06-09 02:56:40 +00005045 return false;
5046}
5047
Tim Northover8b96c7e2017-05-15 19:42:15 +00005048static SMLoc incrementLoc(SMLoc L, int Offset) {
5049 return SMLoc::getFromPointer(L.getPointer() + Offset);
5050}
5051
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005052/// parseDirectiveCPU
5053/// ::= .cpu id
5054bool AArch64AsmParser::parseDirectiveCPU(SMLoc L) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005055 SMLoc CurLoc = getLoc();
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005056
5057 StringRef CPU, ExtensionString;
5058 std::tie(CPU, ExtensionString) =
5059 getParser().parseStringToEndOfStatement().trim().split('+');
5060
Nirav Davee833c6c2016-11-08 18:31:04 +00005061 if (parseToken(AsmToken::EndOfStatement))
5062 return true;
5063
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005064 SmallVector<StringRef, 4> RequestedExtensions;
5065 if (!ExtensionString.empty())
5066 ExtensionString.split(RequestedExtensions, '+');
5067
5068 // FIXME This is using tablegen data, but should be moved to ARMTargetParser
5069 // once that is tablegen'ed
5070 if (!getSTI().isCPUStringValid(CPU)) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005071 Error(CurLoc, "unknown CPU name");
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005072 return false;
5073 }
5074
5075 MCSubtargetInfo &STI = copySTI();
5076 STI.setDefaultFeatures(CPU, "");
Tim Northover8b96c7e2017-05-15 19:42:15 +00005077 CurLoc = incrementLoc(CurLoc, CPU.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005078
Sjoerd Meijerdc198342018-07-26 07:13:59 +00005079 ExpandCryptoAEK(llvm::AArch64::getCPUArchKind(CPU), RequestedExtensions);
5080
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005081 FeatureBitset Features = STI.getFeatureBits();
5082 for (auto Name : RequestedExtensions) {
Tim Northover8b96c7e2017-05-15 19:42:15 +00005083 // Advance source location past '+'.
5084 CurLoc = incrementLoc(CurLoc, 1);
5085
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005086 bool EnableFeature = true;
5087
5088 if (Name.startswith_lower("no")) {
5089 EnableFeature = false;
5090 Name = Name.substr(2);
5091 }
5092
Tim Northover8b96c7e2017-05-15 19:42:15 +00005093 bool FoundExtension = false;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005094 for (const auto &Extension : ExtensionMap) {
5095 if (Extension.Name != Name)
5096 continue;
5097
5098 if (Extension.Features.none())
5099 report_fatal_error("unsupported architectural extension: " + Name);
5100
5101 FeatureBitset ToggleFeatures = EnableFeature
5102 ? (~Features & Extension.Features)
5103 : ( Features & Extension.Features);
5104 uint64_t Features =
5105 ComputeAvailableFeatures(STI.ToggleFeature(ToggleFeatures));
5106 setAvailableFeatures(Features);
Tim Northover8b96c7e2017-05-15 19:42:15 +00005107 FoundExtension = true;
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005108
5109 break;
5110 }
Tim Northover8b96c7e2017-05-15 19:42:15 +00005111
5112 if (!FoundExtension)
5113 Error(CurLoc, "unsupported architectural extension");
5114
5115 CurLoc = incrementLoc(CurLoc, Name.size());
Saleem Abdulrasool85b436392016-04-02 19:29:52 +00005116 }
5117 return false;
5118}
5119
Chad Rosierdcd2a302014-10-22 20:35:57 +00005120/// parseDirectiveInst
5121/// ::= .inst opcode [, ...]
5122bool AArch64AsmParser::parseDirectiveInst(SMLoc Loc) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005123 if (getLexer().is(AsmToken::EndOfStatement))
5124 return Error(Loc, "expected expression following '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005125
Nirav Davee833c6c2016-11-08 18:31:04 +00005126 auto parseOp = [&]() -> bool {
5127 SMLoc L = getLoc();
Chad Rosierdcd2a302014-10-22 20:35:57 +00005128 const MCExpr *Expr;
Nirav Davee833c6c2016-11-08 18:31:04 +00005129 if (check(getParser().parseExpression(Expr), L, "expected expression"))
5130 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005131 const MCConstantExpr *Value = dyn_cast_or_null<MCConstantExpr>(Expr);
Nirav Davee833c6c2016-11-08 18:31:04 +00005132 if (check(!Value, L, "expected constant expression"))
5133 return true;
Chad Rosierdcd2a302014-10-22 20:35:57 +00005134 getTargetStreamer().emitInst(Value->getValue());
Nirav Davee833c6c2016-11-08 18:31:04 +00005135 return false;
5136 };
Chad Rosierdcd2a302014-10-22 20:35:57 +00005137
Nirav Davee833c6c2016-11-08 18:31:04 +00005138 if (parseMany(parseOp))
5139 return addErrorSuffix(" in '.inst' directive");
Chad Rosierdcd2a302014-10-22 20:35:57 +00005140 return false;
5141}
5142
Tim Northover3b0846e2014-05-24 12:50:23 +00005143// parseDirectiveTLSDescCall:
5144// ::= .tlsdesccall symbol
5145bool AArch64AsmParser::parseDirectiveTLSDescCall(SMLoc L) {
5146 StringRef Name;
Nirav Davee833c6c2016-11-08 18:31:04 +00005147 if (check(getParser().parseIdentifier(Name), L,
5148 "expected symbol after directive") ||
5149 parseToken(AsmToken::EndOfStatement))
5150 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005151
Jim Grosbach6f482002015-05-18 18:43:14 +00005152 MCSymbol *Sym = getContext().getOrCreateSymbol(Name);
Jim Grosbach13760bd2015-05-30 01:25:56 +00005153 const MCExpr *Expr = MCSymbolRefExpr::create(Sym, getContext());
5154 Expr = AArch64MCExpr::create(Expr, AArch64MCExpr::VK_TLSDESC, getContext());
Tim Northover3b0846e2014-05-24 12:50:23 +00005155
5156 MCInst Inst;
5157 Inst.setOpcode(AArch64::TLSDESCCALL);
Jim Grosbache9119e42015-05-13 18:37:00 +00005158 Inst.addOperand(MCOperand::createExpr(Expr));
Tim Northover3b0846e2014-05-24 12:50:23 +00005159
Akira Hatanakabd9fc282015-11-14 05:20:05 +00005160 getParser().getStreamer().EmitInstruction(Inst, getSTI());
Tim Northover3b0846e2014-05-24 12:50:23 +00005161 return false;
5162}
5163
5164/// ::= .loh <lohName | lohId> label1, ..., labelN
5165/// The number of arguments depends on the loh identifier.
5166bool AArch64AsmParser::parseDirectiveLOH(StringRef IDVal, SMLoc Loc) {
Tim Northover3b0846e2014-05-24 12:50:23 +00005167 MCLOHType Kind;
5168 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5169 if (getParser().getTok().isNot(AsmToken::Integer))
5170 return TokError("expected an identifier or a number in directive");
5171 // We successfully get a numeric value for the identifier.
5172 // Check if it is valid.
5173 int64_t Id = getParser().getTok().getIntVal();
Nirav Davee833c6c2016-11-08 18:31:04 +00005174 if (Id <= -1U && !isValidMCLOHType(Id))
5175 return TokError("invalid numeric identifier in directive");
Alexey Samsonov700964e2014-08-29 22:34:28 +00005176 Kind = (MCLOHType)Id;
Tim Northover3b0846e2014-05-24 12:50:23 +00005177 } else {
5178 StringRef Name = getTok().getIdentifier();
5179 // We successfully parse an identifier.
5180 // Check if it is a recognized one.
5181 int Id = MCLOHNameToId(Name);
5182
5183 if (Id == -1)
5184 return TokError("invalid identifier in directive");
5185 Kind = (MCLOHType)Id;
5186 }
5187 // Consume the identifier.
5188 Lex();
5189 // Get the number of arguments of this LOH.
5190 int NbArgs = MCLOHIdToNbArgs(Kind);
5191
5192 assert(NbArgs != -1 && "Invalid number of arguments");
5193
5194 SmallVector<MCSymbol *, 3> Args;
5195 for (int Idx = 0; Idx < NbArgs; ++Idx) {
5196 StringRef Name;
5197 if (getParser().parseIdentifier(Name))
5198 return TokError("expected identifier in directive");
Jim Grosbach6f482002015-05-18 18:43:14 +00005199 Args.push_back(getContext().getOrCreateSymbol(Name));
Tim Northover3b0846e2014-05-24 12:50:23 +00005200
5201 if (Idx + 1 == NbArgs)
5202 break;
Nirav Davee833c6c2016-11-08 18:31:04 +00005203 if (parseToken(AsmToken::Comma,
5204 "unexpected token in '" + Twine(IDVal) + "' directive"))
5205 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005206 }
Nirav Davee833c6c2016-11-08 18:31:04 +00005207 if (parseToken(AsmToken::EndOfStatement,
5208 "unexpected token in '" + Twine(IDVal) + "' directive"))
5209 return true;
Tim Northover3b0846e2014-05-24 12:50:23 +00005210
5211 getStreamer().EmitLOHDirective((MCLOHType)Kind, Args);
5212 return false;
5213}
5214
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005215/// parseDirectiveLtorg
5216/// ::= .ltorg | .pool
5217bool AArch64AsmParser::parseDirectiveLtorg(SMLoc L) {
Nirav Davee833c6c2016-11-08 18:31:04 +00005218 if (parseToken(AsmToken::EndOfStatement, "unexpected token in directive"))
5219 return true;
Weiming Zhaob1d4dbd2014-06-24 16:21:38 +00005220 getTargetStreamer().emitCurrentConstantPool();
5221 return false;
5222}
5223
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005224/// parseDirectiveReq
5225/// ::= name .req registername
5226bool AArch64AsmParser::parseDirectiveReq(StringRef Name, SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005227 MCAsmParser &Parser = getParser();
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005228 Parser.Lex(); // Eat the '.req' token.
5229 SMLoc SRegLoc = getLoc();
Florian Hahnc4422242017-11-07 13:07:50 +00005230 RegKind RegisterKind = RegKind::Scalar;
Sander de Smalen50d87022018-04-19 07:35:08 +00005231 unsigned RegNum;
5232 OperandMatchResultTy ParseRes = tryParseScalarRegister(RegNum);
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005233
Sander de Smalen50d87022018-04-19 07:35:08 +00005234 if (ParseRes != MatchOperand_Success) {
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005235 StringRef Kind;
Florian Hahnc4422242017-11-07 13:07:50 +00005236 RegisterKind = RegKind::NeonVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005237 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::NeonVector);
Sander de Smalen73937b72018-04-11 07:36:10 +00005238
Sander de Smalen50d87022018-04-19 07:35:08 +00005239 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen73937b72018-04-11 07:36:10 +00005240 return true;
5241
Sander de Smalen50d87022018-04-19 07:35:08 +00005242 if (ParseRes == MatchOperand_Success && !Kind.empty())
Nirav Dave2364748a2016-09-16 18:30:20 +00005243 return Error(SRegLoc, "vector register without type specifier expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005244 }
5245
Sander de Smalen50d87022018-04-19 07:35:08 +00005246 if (ParseRes != MatchOperand_Success) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005247 StringRef Kind;
5248 RegisterKind = RegKind::SVEDataVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005249 ParseRes =
Sander de Smalen73937b72018-04-11 07:36:10 +00005250 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005251
Sander de Smalen50d87022018-04-19 07:35:08 +00005252 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalen8e607342017-11-15 15:44:43 +00005253 return true;
5254
Sander de Smalen50d87022018-04-19 07:35:08 +00005255 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalen8e607342017-11-15 15:44:43 +00005256 return Error(SRegLoc,
5257 "sve vector register without type specifier expected");
Florian Hahn91f11e52017-11-07 16:45:48 +00005258 }
5259
Sander de Smalen50d87022018-04-19 07:35:08 +00005260 if (ParseRes != MatchOperand_Success) {
Sander de Smalencd6be962017-12-20 11:02:42 +00005261 StringRef Kind;
5262 RegisterKind = RegKind::SVEPredicateVector;
Sander de Smalen50d87022018-04-19 07:35:08 +00005263 ParseRes = tryParseVectorRegister(RegNum, Kind, RegKind::SVEPredicateVector);
Sander de Smalencd6be962017-12-20 11:02:42 +00005264
Sander de Smalen50d87022018-04-19 07:35:08 +00005265 if (ParseRes == MatchOperand_ParseFail)
Sander de Smalencd6be962017-12-20 11:02:42 +00005266 return true;
5267
Sander de Smalen50d87022018-04-19 07:35:08 +00005268 if (ParseRes == MatchOperand_Success && !Kind.empty())
Sander de Smalencd6be962017-12-20 11:02:42 +00005269 return Error(SRegLoc,
5270 "sve predicate register without type specifier expected");
5271 }
5272
Sander de Smalen50d87022018-04-19 07:35:08 +00005273 if (ParseRes != MatchOperand_Success)
Nirav Dave2364748a2016-09-16 18:30:20 +00005274 return Error(SRegLoc, "register name or alias expected");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005275
5276 // Shouldn't be anything else.
Nirav Davee833c6c2016-11-08 18:31:04 +00005277 if (parseToken(AsmToken::EndOfStatement,
5278 "unexpected input in .req directive"))
5279 return true;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005280
Sander de Smalen8e607342017-11-15 15:44:43 +00005281 auto pair = std::make_pair(RegisterKind, (unsigned) RegNum);
Frederic Rissb61f01f2015-02-04 03:10:03 +00005282 if (RegisterReqs.insert(std::make_pair(Name, pair)).first->second != pair)
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005283 Warning(L, "ignoring redefinition of register alias '" + Name + "'");
5284
Nirav Dave2364748a2016-09-16 18:30:20 +00005285 return false;
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005286}
5287
5288/// parseDirectiveUneq
5289/// ::= .unreq registername
5290bool AArch64AsmParser::parseDirectiveUnreq(SMLoc L) {
Rafael Espindola961d4692014-11-11 05:18:41 +00005291 MCAsmParser &Parser = getParser();
Nirav Davee833c6c2016-11-08 18:31:04 +00005292 if (getTok().isNot(AsmToken::Identifier))
5293 return TokError("unexpected input in .unreq directive.");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005294 RegisterReqs.erase(Parser.getTok().getIdentifier().lower());
5295 Parser.Lex(); // Eat the identifier.
Nirav Davee833c6c2016-11-08 18:31:04 +00005296 if (parseToken(AsmToken::EndOfStatement))
5297 return addErrorSuffix("in '.unreq' directive");
Saleem Abdulrasool2e09c512014-07-02 04:50:23 +00005298 return false;
5299}
5300
Tim Northover3b0846e2014-05-24 12:50:23 +00005301bool
5302AArch64AsmParser::classifySymbolRef(const MCExpr *Expr,
5303 AArch64MCExpr::VariantKind &ELFRefKind,
5304 MCSymbolRefExpr::VariantKind &DarwinRefKind,
5305 int64_t &Addend) {
5306 ELFRefKind = AArch64MCExpr::VK_INVALID;
5307 DarwinRefKind = MCSymbolRefExpr::VK_None;
5308 Addend = 0;
5309
5310 if (const AArch64MCExpr *AE = dyn_cast<AArch64MCExpr>(Expr)) {
5311 ELFRefKind = AE->getKind();
5312 Expr = AE->getSubExpr();
5313 }
5314
5315 const MCSymbolRefExpr *SE = dyn_cast<MCSymbolRefExpr>(Expr);
5316 if (SE) {
5317 // It's a simple symbol reference with no addend.
5318 DarwinRefKind = SE->getKind();
5319 return true;
5320 }
5321
David Green85d6a552018-09-18 09:44:53 +00005322 // Check that it looks like a symbol + an addend
5323 MCValue Res;
5324 bool Relocatable = Expr->evaluateAsRelocatable(Res, nullptr, nullptr);
5325 if (!Relocatable || !Res.getSymA() || Res.getSymB())
Tim Northover3b0846e2014-05-24 12:50:23 +00005326 return false;
5327
David Green85d6a552018-09-18 09:44:53 +00005328 DarwinRefKind = Res.getSymA()->getKind();
5329 Addend = Res.getConstant();
Tim Northover3b0846e2014-05-24 12:50:23 +00005330
5331 // It's some symbol reference + a constant addend, but really
5332 // shouldn't use both Darwin and ELF syntax.
5333 return ELFRefKind == AArch64MCExpr::VK_INVALID ||
5334 DarwinRefKind == MCSymbolRefExpr::VK_None;
5335}
5336
5337/// Force static initialization.
5338extern "C" void LLVMInitializeAArch64AsmParser() {
Mehdi Aminif42454b2016-10-09 23:00:34 +00005339 RegisterMCAsmParser<AArch64AsmParser> X(getTheAArch64leTarget());
5340 RegisterMCAsmParser<AArch64AsmParser> Y(getTheAArch64beTarget());
5341 RegisterMCAsmParser<AArch64AsmParser> Z(getTheARM64Target());
Tim Northover3b0846e2014-05-24 12:50:23 +00005342}
5343
5344#define GET_REGISTER_MATCHER
5345#define GET_SUBTARGET_FEATURE_NAME
5346#define GET_MATCHER_IMPLEMENTATION
Craig Topper2a060282017-10-26 06:46:40 +00005347#define GET_MNEMONIC_SPELL_CHECKER
Tim Northover3b0846e2014-05-24 12:50:23 +00005348#include "AArch64GenAsmMatcher.inc"
5349
5350// Define this matcher function after the auto-generated include so we
5351// have the match class enum definitions.
David Blaikie960ea3f2014-06-08 16:18:35 +00005352unsigned AArch64AsmParser::validateTargetOperandClass(MCParsedAsmOperand &AsmOp,
Tim Northover3b0846e2014-05-24 12:50:23 +00005353 unsigned Kind) {
David Blaikie960ea3f2014-06-08 16:18:35 +00005354 AArch64Operand &Op = static_cast<AArch64Operand &>(AsmOp);
Tim Northover3b0846e2014-05-24 12:50:23 +00005355 // If the kind is a token for a literal immediate, check if our asm
5356 // operand matches. This is for InstAliases which have a fixed-value
5357 // immediate in the syntax.
5358 int64_t ExpectedVal;
5359 switch (Kind) {
5360 default:
5361 return Match_InvalidOperand;
5362 case MCK__35_0:
5363 ExpectedVal = 0;
5364 break;
5365 case MCK__35_1:
5366 ExpectedVal = 1;
5367 break;
5368 case MCK__35_12:
5369 ExpectedVal = 12;
5370 break;
5371 case MCK__35_16:
5372 ExpectedVal = 16;
5373 break;
5374 case MCK__35_2:
5375 ExpectedVal = 2;
5376 break;
5377 case MCK__35_24:
5378 ExpectedVal = 24;
5379 break;
5380 case MCK__35_3:
5381 ExpectedVal = 3;
5382 break;
5383 case MCK__35_32:
5384 ExpectedVal = 32;
5385 break;
5386 case MCK__35_4:
5387 ExpectedVal = 4;
5388 break;
5389 case MCK__35_48:
5390 ExpectedVal = 48;
5391 break;
5392 case MCK__35_6:
5393 ExpectedVal = 6;
5394 break;
5395 case MCK__35_64:
5396 ExpectedVal = 64;
5397 break;
5398 case MCK__35_8:
5399 ExpectedVal = 8;
5400 break;
5401 }
David Blaikie960ea3f2014-06-08 16:18:35 +00005402 if (!Op.isImm())
Tim Northover3b0846e2014-05-24 12:50:23 +00005403 return Match_InvalidOperand;
David Blaikie960ea3f2014-06-08 16:18:35 +00005404 const MCConstantExpr *CE = dyn_cast<MCConstantExpr>(Op.getImm());
Tim Northover3b0846e2014-05-24 12:50:23 +00005405 if (!CE)
5406 return Match_InvalidOperand;
5407 if (CE->getValue() == ExpectedVal)
5408 return Match_Success;
5409 return Match_InvalidOperand;
5410}
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005411
Alex Bradbury58eba092016-11-01 16:32:05 +00005412OperandMatchResultTy
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005413AArch64AsmParser::tryParseGPRSeqPair(OperandVector &Operands) {
5414
5415 SMLoc S = getLoc();
5416
5417 if (getParser().getTok().isNot(AsmToken::Identifier)) {
5418 Error(S, "expected register");
5419 return MatchOperand_ParseFail;
5420 }
5421
Sander de Smalen50d87022018-04-19 07:35:08 +00005422 unsigned FirstReg;
5423 OperandMatchResultTy Res = tryParseScalarRegister(FirstReg);
5424 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005425 return MatchOperand_ParseFail;
Sander de Smalen50d87022018-04-19 07:35:08 +00005426
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005427 const MCRegisterClass &WRegClass =
5428 AArch64MCRegisterClasses[AArch64::GPR32RegClassID];
5429 const MCRegisterClass &XRegClass =
5430 AArch64MCRegisterClasses[AArch64::GPR64RegClassID];
5431
5432 bool isXReg = XRegClass.contains(FirstReg),
5433 isWReg = WRegClass.contains(FirstReg);
5434 if (!isXReg && !isWReg) {
5435 Error(S, "expected first even register of a "
5436 "consecutive same-size even/odd register pair");
5437 return MatchOperand_ParseFail;
5438 }
5439
5440 const MCRegisterInfo *RI = getContext().getRegisterInfo();
5441 unsigned FirstEncoding = RI->getEncodingValue(FirstReg);
5442
5443 if (FirstEncoding & 0x1) {
5444 Error(S, "expected first even register of a "
5445 "consecutive same-size even/odd register pair");
5446 return MatchOperand_ParseFail;
5447 }
5448
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005449 if (getParser().getTok().isNot(AsmToken::Comma)) {
Sander de Smalen50d87022018-04-19 07:35:08 +00005450 Error(getLoc(), "expected comma");
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005451 return MatchOperand_ParseFail;
5452 }
5453 // Eat the comma
5454 getParser().Lex();
5455
5456 SMLoc E = getLoc();
Sander de Smalen50d87022018-04-19 07:35:08 +00005457 unsigned SecondReg;
5458 Res = tryParseScalarRegister(SecondReg);
5459 if (Res != MatchOperand_Success)
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005460 return MatchOperand_ParseFail;
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005461
Eugene Zelenko049b0172017-01-06 00:30:53 +00005462 if (RI->getEncodingValue(SecondReg) != FirstEncoding + 1 ||
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005463 (isXReg && !XRegClass.contains(SecondReg)) ||
5464 (isWReg && !WRegClass.contains(SecondReg))) {
5465 Error(E,"expected second odd register of a "
5466 "consecutive same-size even/odd register pair");
5467 return MatchOperand_ParseFail;
5468 }
Joel Jones504bf332016-10-24 13:37:13 +00005469
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005470 unsigned Pair = 0;
Eugene Zelenko049b0172017-01-06 00:30:53 +00005471 if (isXReg) {
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005472 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube64,
5473 &AArch64MCRegisterClasses[AArch64::XSeqPairsClassRegClassID]);
5474 } else {
5475 Pair = RI->getMatchingSuperReg(FirstReg, AArch64::sube32,
5476 &AArch64MCRegisterClasses[AArch64::WSeqPairsClassRegClassID]);
5477 }
5478
Florian Hahnc4422242017-11-07 13:07:50 +00005479 Operands.push_back(AArch64Operand::CreateReg(Pair, RegKind::Scalar, S,
5480 getLoc(), getContext()));
Vladimir Sukharev5f6f60d2015-06-02 10:58:41 +00005481
5482 return MatchOperand_Success;
5483}
Florian Hahn91f11e52017-11-07 16:45:48 +00005484
Sander de Smaleneb896b12018-04-25 09:26:47 +00005485template <bool ParseShiftExtend, bool ParseSuffix>
Florian Hahn91f11e52017-11-07 16:45:48 +00005486OperandMatchResultTy
5487AArch64AsmParser::tryParseSVEDataVector(OperandVector &Operands) {
Florian Hahn91f11e52017-11-07 16:45:48 +00005488 const SMLoc S = getLoc();
5489 // Check for a SVE vector register specifier first.
Sander de Smalen50d87022018-04-19 07:35:08 +00005490 unsigned RegNum;
Florian Hahn91f11e52017-11-07 16:45:48 +00005491 StringRef Kind;
Florian Hahn91f11e52017-11-07 16:45:48 +00005492
Sander de Smalen8e607342017-11-15 15:44:43 +00005493 OperandMatchResultTy Res =
Sander de Smalen73937b72018-04-11 07:36:10 +00005494 tryParseVectorRegister(RegNum, Kind, RegKind::SVEDataVector);
Sander de Smalen8e607342017-11-15 15:44:43 +00005495
5496 if (Res != MatchOperand_Success)
5497 return Res;
Florian Hahn91f11e52017-11-07 16:45:48 +00005498
5499 if (ParseSuffix && Kind.empty())
5500 return MatchOperand_NoMatch;
5501
Sander de Smalen73937b72018-04-11 07:36:10 +00005502 const auto &KindRes = parseVectorKind(Kind, RegKind::SVEDataVector);
5503 if (!KindRes)
Florian Hahn91f11e52017-11-07 16:45:48 +00005504 return MatchOperand_NoMatch;
5505
Sander de Smalen73937b72018-04-11 07:36:10 +00005506 unsigned ElementWidth = KindRes->second;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005507
5508 // No shift/extend is the default.
5509 if (!ParseShiftExtend || getParser().getTok().isNot(AsmToken::Comma)) {
5510 Operands.push_back(AArch64Operand::CreateVectorReg(
5511 RegNum, RegKind::SVEDataVector, ElementWidth, S, S, getContext()));
5512
Sander de Smalenc33d6682018-06-04 06:40:55 +00005513 OperandMatchResultTy Res = tryParseVectorIndex(Operands);
5514 if (Res == MatchOperand_ParseFail)
5515 return MatchOperand_ParseFail;
Sander de Smaleneb896b12018-04-25 09:26:47 +00005516 return MatchOperand_Success;
5517 }
5518
5519 // Eat the comma
5520 getParser().Lex();
5521
5522 // Match the shift
5523 SmallVector<std::unique_ptr<MCParsedAsmOperand>, 1> ExtOpnd;
5524 Res = tryParseOptionalShiftExtend(ExtOpnd);
5525 if (Res != MatchOperand_Success)
5526 return Res;
5527
5528 auto Ext = static_cast<AArch64Operand *>(ExtOpnd.back().get());
Sander de Smalen73937b72018-04-11 07:36:10 +00005529 Operands.push_back(AArch64Operand::CreateVectorReg(
Sander de Smaleneb896b12018-04-25 09:26:47 +00005530 RegNum, RegKind::SVEDataVector, ElementWidth, S, Ext->getEndLoc(),
5531 getContext(), Ext->getShiftExtendType(), Ext->getShiftExtendAmount(),
5532 Ext->hasShiftExtendAmount()));
Florian Hahn91f11e52017-11-07 16:45:48 +00005533
5534 return MatchOperand_Success;
5535}
Sander de Smalen245e0e62018-01-22 10:46:00 +00005536
5537OperandMatchResultTy
5538AArch64AsmParser::tryParseSVEPattern(OperandVector &Operands) {
5539 MCAsmParser &Parser = getParser();
5540
5541 SMLoc SS = getLoc();
5542 const AsmToken &TokE = Parser.getTok();
5543 bool IsHash = TokE.is(AsmToken::Hash);
5544
5545 if (!IsHash && TokE.isNot(AsmToken::Identifier))
5546 return MatchOperand_NoMatch;
5547
5548 int64_t Pattern;
5549 if (IsHash) {
5550 Parser.Lex(); // Eat hash
5551
5552 // Parse the immediate operand.
5553 const MCExpr *ImmVal;
5554 SS = getLoc();
5555 if (Parser.parseExpression(ImmVal))
5556 return MatchOperand_ParseFail;
5557
5558 auto *MCE = dyn_cast<MCConstantExpr>(ImmVal);
5559 if (!MCE)
5560 return MatchOperand_ParseFail;
5561
5562 Pattern = MCE->getValue();
5563 } else {
5564 // Parse the pattern
5565 auto Pat = AArch64SVEPredPattern::lookupSVEPREDPATByName(TokE.getString());
5566 if (!Pat)
5567 return MatchOperand_NoMatch;
5568
5569 Parser.Lex();
5570 Pattern = Pat->Encoding;
5571 assert(Pattern >= 0 && Pattern < 32);
5572 }
5573
5574 Operands.push_back(
5575 AArch64Operand::CreateImm(MCConstantExpr::create(Pattern, getContext()),
5576 SS, getLoc(), getContext()));
5577
5578 return MatchOperand_Success;
5579}